diff --git a/INSTALL.md b/INSTALL.md index 893f5551e4..b92739a0db 100644 --- a/INSTALL.md +++ b/INSTALL.md @@ -10,7 +10,7 @@ Refer to the [wiki](http://cwiki.apache.org/confluence/display/CLOUDSTACK/Index) for the latest information, especially: - [Setting up development environment](https://cwiki.apache.org/confluence/display/CLOUDSTACK/Setting+up+CloudStack+Development+Environment) for Apache CloudStack. - - [Building](https://cwiki.apache.org/confluence/display/CLOUDSTACK/How+to+build+on+master+branch) Apache CloudStack. + - [Building](https://cwiki.apache.org/confluence/display/CLOUDSTACK/How+to+build+CloudStack) Apache CloudStack. ## Setting up Development Environment @@ -18,7 +18,7 @@ for the latest information, especially: Install tools and dependencies used for development: - $ yum install git ant ant-devel java-1.6.0-openjdk java-1.6.0-openjdk-devel + $ yum install git ant ant-devel java-1.7.0-openjdk java-1.7.0-openjdk-devel mysql mysql-server tomcat6 mkisofs gcc python MySQL-python openssh-clients wget Set up Maven (3.0.5): diff --git a/README.md b/README.md index c9f5733d5f..23f5004cd9 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,4 @@ -Apache CloudStack Version 4.2.0 +Apache CloudStack Version 4.4.0 # About Apache CloudStack diff --git a/agent-simulator/tomcatconf/commands-simulator.properties.in b/agent-simulator/tomcatconf/commands-simulator.properties.in index ba19e33dc5..4350bb788b 100644 --- a/agent-simulator/tomcatconf/commands-simulator.properties.in +++ b/agent-simulator/tomcatconf/commands-simulator.properties.in @@ -17,3 +17,5 @@ configureSimulator=com.cloud.api.commands.ConfigureSimulatorCmd;1 +querySimulatorMock=com.cloud.api.commands.QuerySimulatorMockCmd;1 +cleanupSimulatorMock=com.cloud.api.commands.CleanupSimulatorMockCmd;1 diff --git a/api/src/com/cloud/agent/api/VgpuTypesInfo.java b/api/src/com/cloud/agent/api/VgpuTypesInfo.java new file mode 100644 index 0000000000..85ffc18982 --- /dev/null +++ b/api/src/com/cloud/agent/api/VgpuTypesInfo.java @@ -0,0 +1,86 @@ +// 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.agent.api; +public class VgpuTypesInfo { + + private String modelName; + private String groupName; + private Long maxHeads; + private Long videoRam; + private Long maxResolutionX; + private Long maxResolutionY; + private Long maxVgpuPerGpu; + private Long remainingCapacity; + private Long maxCapacity; + + public String getModelName() { + return modelName; + } + + public String getGroupName() { + return groupName; + } + + public Long getVideoRam() { + return videoRam; + } + + public Long getMaxHeads() { + return maxHeads; + } + + public Long getMaxResolutionX() { + return maxResolutionX; + } + + public Long getMaxResolutionY() { + return maxResolutionY; + } + + public Long getMaxVpuPerGpu() { + return maxVgpuPerGpu; + } + + public Long getRemainingCapacity() { + return remainingCapacity; + } + + public void setRemainingCapacity(Long remainingCapacity) { + this.remainingCapacity = remainingCapacity; + } + + public Long getMaxCapacity() { + return maxCapacity; + } + + public void setMaxVmCapacity(Long maxCapacity) { + this.maxCapacity = maxCapacity; + } + + public VgpuTypesInfo(String groupName, String modelName, Long videoRam, Long maxHeads, Long maxResolutionX, Long maxResolutionY, Long maxVgpuPerGpu, + Long remainingCapacity, Long maxCapacity) { + this.groupName = groupName; + this.modelName = modelName; + this.videoRam = videoRam; + this.maxHeads = maxHeads; + this.maxResolutionX = maxResolutionX; + this.maxResolutionY = maxResolutionY; + this.maxVgpuPerGpu = maxVgpuPerGpu; + this.remainingCapacity = remainingCapacity; + this.maxCapacity = maxCapacity; + } +} diff --git a/api/src/com/cloud/agent/api/to/GPUDeviceTO.java b/api/src/com/cloud/agent/api/to/GPUDeviceTO.java index 8bc9e5229d..4afe080477 100644 --- a/api/src/com/cloud/agent/api/to/GPUDeviceTO.java +++ b/api/src/com/cloud/agent/api/to/GPUDeviceTO.java @@ -18,13 +18,15 @@ import java.util.HashMap; +import com.cloud.agent.api.VgpuTypesInfo; + public class GPUDeviceTO { private String gpuGroup; private String vgpuType; - private HashMap> groupDetails = new HashMap>(); + private HashMap> groupDetails = new HashMap>(); - public GPUDeviceTO( String gpuGroup, String vgpuType, HashMap> groupDetails) { + public GPUDeviceTO( String gpuGroup, String vgpuType, HashMap> groupDetails) { this.gpuGroup = gpuGroup; this.vgpuType = vgpuType; this.groupDetails = groupDetails; @@ -46,11 +48,12 @@ public void setVgpuType(String vgpuType) { this.vgpuType = vgpuType; } - public HashMap> getGroupDetails() { + public HashMap> getGroupDetails() { return groupDetails; } - public void setGroupDetails(HashMap> groupDetails) { + public void setGroupDetails(HashMap> groupDetails) { this.groupDetails = groupDetails; } + } diff --git a/api/src/com/cloud/agent/api/to/VirtualMachineTO.java b/api/src/com/cloud/agent/api/to/VirtualMachineTO.java index bbd83852ab..45bad79f98 100644 --- a/api/src/com/cloud/agent/api/to/VirtualMachineTO.java +++ b/api/src/com/cloud/agent/api/to/VirtualMachineTO.java @@ -47,6 +47,7 @@ public class VirtualMachineTO { String hostName; String arch; String os; + String platformEmulator; String bootArgs; String[] bootupScripts; boolean rebootOnCrash; @@ -236,7 +237,7 @@ public void setNics(NicTO[] nics) { } public String getVncPassword() { - return this.vncPassword; + return vncPassword; } public void setVncPassword(String vncPassword) { @@ -244,7 +245,7 @@ public void setVncPassword(String vncPassword) { } public String getVncAddr() { - return this.vncAddr; + return vncAddr; } public void setVncAddr(String vncAddr) { @@ -275,4 +276,12 @@ public void setGpuDevice(GPUDeviceTO gpuDevice) { this.gpuDevice = gpuDevice; } + public String getPlatformEmulator() { + return platformEmulator; + } + + public void setPlatformEmulator(String platformEmulator) { + this.platformEmulator = platformEmulator; + } + } diff --git a/api/src/com/cloud/capacity/Capacity.java b/api/src/com/cloud/capacity/Capacity.java index c1c5d8fa9b..2fbc1d6eef 100755 --- a/api/src/com/cloud/capacity/Capacity.java +++ b/api/src/com/cloud/capacity/Capacity.java @@ -30,6 +30,7 @@ public interface Capacity extends InternalIdentity, Identity { public static final short CAPACITY_TYPE_VLAN = 7; public static final short CAPACITY_TYPE_DIRECT_ATTACHED_PUBLIC_IP = 8; public static final short CAPACITY_TYPE_LOCAL_STORAGE = 9; + public static final short CAPACITY_TYPE_GPU = 19; public Long getHostOrPoolId(); diff --git a/api/src/com/cloud/event/EventTypes.java b/api/src/com/cloud/event/EventTypes.java index 39ef710f8a..d9aa3f45f6 100755 --- a/api/src/com/cloud/event/EventTypes.java +++ b/api/src/com/cloud/event/EventTypes.java @@ -19,6 +19,9 @@ import java.util.HashMap; import java.util.Map; +import com.cloud.server.ResourceTag; +import com.cloud.vm.ConsoleProxy; +import com.cloud.vm.SecondaryStorageVm; import org.apache.cloudstack.config.Configuration; import com.cloud.dc.DataCenter; @@ -62,7 +65,7 @@ public class EventTypes { //map of Event and corresponding entity for which Event is applicable - private static Map entityEventDetails = null; + private static Map entityEventDetails = null; // VM Events public static final String EVENT_VM_CREATE = "VM.CREATE"; @@ -131,9 +134,11 @@ public class EventTypes { public static final String EVENT_LOAD_BALANCER_CREATE = "LB.CREATE"; public static final String EVENT_LOAD_BALANCER_DELETE = "LB.DELETE"; public static final String EVENT_LB_STICKINESSPOLICY_CREATE = "LB.STICKINESSPOLICY.CREATE"; + public static final String EVENT_LB_STICKINESSPOLICY_UPDATE = "LB.STICKINESSPOLICY.UPDATE"; public static final String EVENT_LB_STICKINESSPOLICY_DELETE = "LB.STICKINESSPOLICY.DELETE"; public static final String EVENT_LB_HEALTHCHECKPOLICY_CREATE = "LB.HEALTHCHECKPOLICY.CREATE"; public static final String EVENT_LB_HEALTHCHECKPOLICY_DELETE = "LB.HEALTHCHECKPOLICY.DELETE"; + public static final String EVENT_LB_HEALTHCHECKPOLICY_UPDATE = "LB.HEALTHCHECKPOLICY.UPDATE"; public static final String EVENT_LOAD_BALANCER_UPDATE = "LB.UPDATE"; public static final String EVENT_LB_CERT_UPLOAD = "LB.CERT.UPLOAD"; public static final String EVENT_LB_CERT_DELETE = "LB.CERT.DELETE"; @@ -492,122 +497,120 @@ public class EventTypes { static { // TODO: need a way to force author adding event types to declare the entity details as well, with out braking - // current ActionEvent annotation semantics - // TODO #2 - The map should be from event type to class. - - entityEventDetails = new HashMap(); - - entityEventDetails.put(EVENT_VM_CREATE, VirtualMachine.class.getName()); - entityEventDetails.put(EVENT_VM_DESTROY, VirtualMachine.class.getName()); - entityEventDetails.put(EVENT_VM_START, VirtualMachine.class.getName()); - entityEventDetails.put(EVENT_VM_STOP, VirtualMachine.class.getName()); - entityEventDetails.put(EVENT_VM_REBOOT, VirtualMachine.class.getName()); - entityEventDetails.put(EVENT_VM_UPDATE, VirtualMachine.class.getName()); - entityEventDetails.put(EVENT_VM_UPGRADE, VirtualMachine.class.getName()); - entityEventDetails.put(EVENT_VM_DYNAMIC_SCALE, VirtualMachine.class.getName()); - entityEventDetails.put(EVENT_VM_RESETPASSWORD, VirtualMachine.class.getName()); - entityEventDetails.put(EVENT_VM_RESETSSHKEY, VirtualMachine.class.getName()); - entityEventDetails.put(EVENT_VM_MIGRATE, VirtualMachine.class.getName()); - entityEventDetails.put(EVENT_VM_MOVE, VirtualMachine.class.getName()); - entityEventDetails.put(EVENT_VM_RESTORE, VirtualMachine.class.getName()); - entityEventDetails.put(EVENT_VM_EXPUNGE, VirtualMachine.class.getName()); - - entityEventDetails.put(EVENT_ROUTER_CREATE, VirtualRouter.class.getName()); - entityEventDetails.put(EVENT_ROUTER_DESTROY, VirtualRouter.class.getName()); - entityEventDetails.put(EVENT_ROUTER_START, VirtualRouter.class.getName()); - entityEventDetails.put(EVENT_ROUTER_STOP, VirtualRouter.class.getName()); - entityEventDetails.put(EVENT_ROUTER_REBOOT, VirtualRouter.class.getName()); - entityEventDetails.put(EVENT_ROUTER_HA, VirtualRouter.class.getName()); - entityEventDetails.put(EVENT_ROUTER_UPGRADE, VirtualRouter.class.getName()); - - entityEventDetails.put(EVENT_PROXY_CREATE, "ConsoleProxy"); - entityEventDetails.put(EVENT_PROXY_DESTROY, "ConsoleProxy"); - entityEventDetails.put(EVENT_PROXY_START, "ConsoleProxy"); - entityEventDetails.put(EVENT_PROXY_STOP, "ConsoleProxy"); - entityEventDetails.put(EVENT_PROXY_REBOOT, "ConsoleProxy"); - entityEventDetails.put(EVENT_ROUTER_HA, "ConsoleProxy"); - entityEventDetails.put(EVENT_PROXY_HA, "ConsoleProxy"); + + entityEventDetails = new HashMap(); + + entityEventDetails.put(EVENT_VM_CREATE, VirtualMachine.class); + entityEventDetails.put(EVENT_VM_DESTROY, VirtualMachine.class); + entityEventDetails.put(EVENT_VM_START, VirtualMachine.class); + entityEventDetails.put(EVENT_VM_STOP, VirtualMachine.class); + entityEventDetails.put(EVENT_VM_REBOOT, VirtualMachine.class); + entityEventDetails.put(EVENT_VM_UPDATE, VirtualMachine.class); + entityEventDetails.put(EVENT_VM_UPGRADE, VirtualMachine.class); + entityEventDetails.put(EVENT_VM_DYNAMIC_SCALE, VirtualMachine.class); + entityEventDetails.put(EVENT_VM_RESETPASSWORD, VirtualMachine.class); + entityEventDetails.put(EVENT_VM_RESETSSHKEY, VirtualMachine.class); + entityEventDetails.put(EVENT_VM_MIGRATE, VirtualMachine.class); + entityEventDetails.put(EVENT_VM_MOVE, VirtualMachine.class); + entityEventDetails.put(EVENT_VM_RESTORE, VirtualMachine.class); + entityEventDetails.put(EVENT_VM_EXPUNGE, VirtualMachine.class); + + entityEventDetails.put(EVENT_ROUTER_CREATE, VirtualRouter.class); + entityEventDetails.put(EVENT_ROUTER_DESTROY, VirtualRouter.class); + entityEventDetails.put(EVENT_ROUTER_START, VirtualRouter.class); + entityEventDetails.put(EVENT_ROUTER_STOP, VirtualRouter.class); + entityEventDetails.put(EVENT_ROUTER_REBOOT, VirtualRouter.class); + entityEventDetails.put(EVENT_ROUTER_HA, VirtualRouter.class); + entityEventDetails.put(EVENT_ROUTER_UPGRADE, VirtualRouter.class); + + entityEventDetails.put(EVENT_PROXY_CREATE, ConsoleProxy.class); + entityEventDetails.put(EVENT_PROXY_DESTROY, ConsoleProxy.class); + entityEventDetails.put(EVENT_PROXY_START, ConsoleProxy.class); + entityEventDetails.put(EVENT_PROXY_STOP, ConsoleProxy.class); + entityEventDetails.put(EVENT_PROXY_REBOOT, ConsoleProxy.class); + entityEventDetails.put(EVENT_ROUTER_HA, ConsoleProxy.class); + entityEventDetails.put(EVENT_PROXY_HA, ConsoleProxy.class); entityEventDetails.put(EVENT_VNC_CONNECT, "VNC"); entityEventDetails.put(EVENT_VNC_DISCONNECT, "VNC"); // Network Events - entityEventDetails.put(EVENT_NETWORK_CREATE, Network.class.getName()); - entityEventDetails.put(EVENT_NETWORK_DELETE, Network.class.getName()); - entityEventDetails.put(EVENT_NETWORK_UPDATE, Network.class.getName()); - entityEventDetails.put(EVENT_NETWORK_RESTART, Network.class.getName()); - entityEventDetails.put(EVENT_NET_IP_ASSIGN, PublicIpAddress.class.getName()); - entityEventDetails.put(EVENT_NET_IP_RELEASE, PublicIpAddress.class.getName()); - entityEventDetails.put(EVENT_NET_RULE_ADD, Network.class.getName()); - entityEventDetails.put(EVENT_NET_RULE_DELETE, Network.class.getName()); - entityEventDetails.put(EVENT_NET_RULE_MODIFY, Network.class.getName()); - entityEventDetails.put(EVENT_FIREWALL_OPEN, Network.class.getName()); - entityEventDetails.put(EVENT_FIREWALL_CLOSE, Network.class.getName()); + entityEventDetails.put(EVENT_NETWORK_CREATE, Network.class); + entityEventDetails.put(EVENT_NETWORK_DELETE, Network.class); + entityEventDetails.put(EVENT_NETWORK_UPDATE, Network.class); + entityEventDetails.put(EVENT_NETWORK_RESTART, Network.class); + entityEventDetails.put(EVENT_NET_IP_ASSIGN, PublicIpAddress.class); + entityEventDetails.put(EVENT_NET_IP_RELEASE, PublicIpAddress.class); + entityEventDetails.put(EVENT_NET_RULE_ADD, Network.class); + entityEventDetails.put(EVENT_NET_RULE_DELETE, Network.class); + entityEventDetails.put(EVENT_NET_RULE_MODIFY, Network.class); + entityEventDetails.put(EVENT_FIREWALL_OPEN, Network.class); + entityEventDetails.put(EVENT_FIREWALL_CLOSE, Network.class); // Load Balancers - entityEventDetails.put(EVENT_ASSIGN_TO_LOAD_BALANCER_RULE, LoadBalancer.class.getName()); - entityEventDetails.put(EVENT_REMOVE_FROM_LOAD_BALANCER_RULE, LoadBalancer.class.getName()); - entityEventDetails.put(EVENT_LOAD_BALANCER_CREATE, LoadBalancer.class.getName()); - entityEventDetails.put(EVENT_LOAD_BALANCER_DELETE, LoadBalancer.class.getName()); - entityEventDetails.put(EVENT_LB_STICKINESSPOLICY_CREATE, LoadBalancer.class.getName()); - entityEventDetails.put(EVENT_LB_STICKINESSPOLICY_DELETE, LoadBalancer.class.getName()); - entityEventDetails.put(EVENT_LOAD_BALANCER_UPDATE, LoadBalancer.class.getName()); - entityEventDetails.put(EVENT_LB_CERT_UPLOAD, LoadBalancer.class.getName()); - entityEventDetails.put(EVENT_LB_CERT_DELETE, LoadBalancer.class.getName()); - entityEventDetails.put(EVENT_LB_CERT_ASSIGN, LoadBalancer.class.getName()); - entityEventDetails.put(EVENT_LB_CERT_REMOVE, LoadBalancer.class.getName()); + entityEventDetails.put(EVENT_ASSIGN_TO_LOAD_BALANCER_RULE, LoadBalancer.class); + entityEventDetails.put(EVENT_REMOVE_FROM_LOAD_BALANCER_RULE, LoadBalancer.class); + entityEventDetails.put(EVENT_LOAD_BALANCER_CREATE, LoadBalancer.class); + entityEventDetails.put(EVENT_LOAD_BALANCER_DELETE, LoadBalancer.class); + entityEventDetails.put(EVENT_LB_STICKINESSPOLICY_CREATE, LoadBalancer.class); + entityEventDetails.put(EVENT_LB_STICKINESSPOLICY_DELETE, LoadBalancer.class); + entityEventDetails.put(EVENT_LOAD_BALANCER_UPDATE, LoadBalancer.class); + entityEventDetails.put(EVENT_LB_CERT_UPLOAD, LoadBalancer.class); + entityEventDetails.put(EVENT_LB_CERT_DELETE, LoadBalancer.class); + entityEventDetails.put(EVENT_LB_CERT_ASSIGN, LoadBalancer.class); + entityEventDetails.put(EVENT_LB_CERT_REMOVE, LoadBalancer.class); // Account events - entityEventDetails.put(EVENT_ACCOUNT_ENABLE, Account.class.getName()); - entityEventDetails.put(EVENT_ACCOUNT_DISABLE, Account.class.getName()); - entityEventDetails.put(EVENT_ACCOUNT_CREATE, Account.class.getName()); - entityEventDetails.put(EVENT_ACCOUNT_DELETE, Account.class.getName()); - entityEventDetails.put(EVENT_ACCOUNT_UPDATE, Account.class.getName()); - entityEventDetails.put(EVENT_ACCOUNT_MARK_DEFAULT_ZONE, Account.class.getName()); + entityEventDetails.put(EVENT_ACCOUNT_ENABLE, Account.class); + entityEventDetails.put(EVENT_ACCOUNT_DISABLE, Account.class); + entityEventDetails.put(EVENT_ACCOUNT_CREATE, Account.class); + entityEventDetails.put(EVENT_ACCOUNT_DELETE, Account.class); + entityEventDetails.put(EVENT_ACCOUNT_UPDATE, Account.class); + entityEventDetails.put(EVENT_ACCOUNT_MARK_DEFAULT_ZONE, Account.class); // UserVO Events - entityEventDetails.put(EVENT_USER_LOGIN, User.class.getName()); - entityEventDetails.put(EVENT_USER_LOGOUT, User.class.getName()); - entityEventDetails.put(EVENT_USER_CREATE, User.class.getName()); - entityEventDetails.put(EVENT_USER_DELETE, User.class.getName()); - entityEventDetails.put(EVENT_USER_DISABLE, User.class.getName()); - entityEventDetails.put(EVENT_USER_UPDATE, User.class.getName()); - entityEventDetails.put(EVENT_USER_ENABLE, User.class.getName()); - entityEventDetails.put(EVENT_USER_LOCK, User.class.getName()); + entityEventDetails.put(EVENT_USER_LOGIN, User.class); + entityEventDetails.put(EVENT_USER_LOGOUT, User.class); + entityEventDetails.put(EVENT_USER_CREATE, User.class); + entityEventDetails.put(EVENT_USER_DELETE, User.class); + entityEventDetails.put(EVENT_USER_DISABLE, User.class); + entityEventDetails.put(EVENT_USER_UPDATE, User.class); + entityEventDetails.put(EVENT_USER_ENABLE, User.class); + entityEventDetails.put(EVENT_USER_LOCK, User.class); // Template Events - entityEventDetails.put(EVENT_TEMPLATE_CREATE, VirtualMachineTemplate.class.getName()); - entityEventDetails.put(EVENT_TEMPLATE_DELETE, VirtualMachineTemplate.class.getName()); - entityEventDetails.put(EVENT_TEMPLATE_UPDATE, VirtualMachineTemplate.class.getName()); - entityEventDetails.put(EVENT_TEMPLATE_DOWNLOAD_START, VirtualMachineTemplate.class.getName()); - entityEventDetails.put(EVENT_TEMPLATE_DOWNLOAD_SUCCESS, VirtualMachineTemplate.class.getName()); - entityEventDetails.put(EVENT_TEMPLATE_DOWNLOAD_FAILED, VirtualMachineTemplate.class.getName()); - entityEventDetails.put(EVENT_TEMPLATE_COPY, VirtualMachineTemplate.class.getName()); - entityEventDetails.put(EVENT_TEMPLATE_EXTRACT, VirtualMachineTemplate.class.getName()); - entityEventDetails.put(EVENT_TEMPLATE_UPLOAD, VirtualMachineTemplate.class.getName()); - entityEventDetails.put(EVENT_TEMPLATE_CLEANUP, VirtualMachineTemplate.class.getName()); + entityEventDetails.put(EVENT_TEMPLATE_CREATE, VirtualMachineTemplate.class); + entityEventDetails.put(EVENT_TEMPLATE_DELETE, VirtualMachineTemplate.class); + entityEventDetails.put(EVENT_TEMPLATE_UPDATE, VirtualMachineTemplate.class); + entityEventDetails.put(EVENT_TEMPLATE_DOWNLOAD_START, VirtualMachineTemplate.class); + entityEventDetails.put(EVENT_TEMPLATE_DOWNLOAD_SUCCESS, VirtualMachineTemplate.class); + entityEventDetails.put(EVENT_TEMPLATE_DOWNLOAD_FAILED, VirtualMachineTemplate.class); + entityEventDetails.put(EVENT_TEMPLATE_COPY, VirtualMachineTemplate.class); + entityEventDetails.put(EVENT_TEMPLATE_EXTRACT, VirtualMachineTemplate.class); + entityEventDetails.put(EVENT_TEMPLATE_UPLOAD, VirtualMachineTemplate.class); + entityEventDetails.put(EVENT_TEMPLATE_CLEANUP, VirtualMachineTemplate.class); // Volume Events - entityEventDetails.put(EVENT_VOLUME_CREATE, Volume.class.getName()); - entityEventDetails.put(EVENT_VOLUME_DELETE, Volume.class.getName()); - entityEventDetails.put(EVENT_VOLUME_ATTACH, Volume.class.getName()); - entityEventDetails.put(EVENT_VOLUME_DETACH, Volume.class.getName()); - entityEventDetails.put(EVENT_VOLUME_EXTRACT, Volume.class.getName()); - entityEventDetails.put(EVENT_VOLUME_UPLOAD, Volume.class.getName()); - entityEventDetails.put(EVENT_VOLUME_MIGRATE, Volume.class.getName()); - entityEventDetails.put(EVENT_VOLUME_RESIZE, Volume.class.getName()); + entityEventDetails.put(EVENT_VOLUME_CREATE, Volume.class); + entityEventDetails.put(EVENT_VOLUME_DELETE, Volume.class); + entityEventDetails.put(EVENT_VOLUME_ATTACH, Volume.class); + entityEventDetails.put(EVENT_VOLUME_DETACH, Volume.class); + entityEventDetails.put(EVENT_VOLUME_EXTRACT, Volume.class); + entityEventDetails.put(EVENT_VOLUME_UPLOAD, Volume.class); + entityEventDetails.put(EVENT_VOLUME_MIGRATE, Volume.class); + entityEventDetails.put(EVENT_VOLUME_RESIZE, Volume.class); // Domains - entityEventDetails.put(EVENT_DOMAIN_CREATE, Domain.class.getName()); - entityEventDetails.put(EVENT_DOMAIN_DELETE, Domain.class.getName()); - entityEventDetails.put(EVENT_DOMAIN_UPDATE, Domain.class.getName()); + entityEventDetails.put(EVENT_DOMAIN_CREATE, Domain.class); + entityEventDetails.put(EVENT_DOMAIN_DELETE, Domain.class); + entityEventDetails.put(EVENT_DOMAIN_UPDATE, Domain.class); // Snapshots - entityEventDetails.put(EVENT_SNAPSHOT_CREATE, Snapshot.class.getName()); - entityEventDetails.put(EVENT_SNAPSHOT_DELETE, Snapshot.class.getName()); - entityEventDetails.put(EVENT_SNAPSHOT_POLICY_CREATE, Snapshot.class.getName()); - entityEventDetails.put(EVENT_SNAPSHOT_POLICY_UPDATE, Snapshot.class.getName()); - entityEventDetails.put(EVENT_SNAPSHOT_POLICY_DELETE, Snapshot.class.getName()); + entityEventDetails.put(EVENT_SNAPSHOT_CREATE, Snapshot.class); + entityEventDetails.put(EVENT_SNAPSHOT_DELETE, Snapshot.class); + entityEventDetails.put(EVENT_SNAPSHOT_POLICY_CREATE, Snapshot.class); + entityEventDetails.put(EVENT_SNAPSHOT_POLICY_UPDATE, Snapshot.class); + entityEventDetails.put(EVENT_SNAPSHOT_POLICY_DELETE, Snapshot.class); // ISO entityEventDetails.put(EVENT_ISO_CREATE, "Iso"); @@ -619,129 +622,129 @@ public class EventTypes { entityEventDetails.put(EVENT_ISO_UPLOAD, "Iso"); // SSVM - entityEventDetails.put(EVENT_SSVM_CREATE, "SecondaryStorageVm"); - entityEventDetails.put(EVENT_SSVM_DESTROY, "SecondaryStorageVm"); - entityEventDetails.put(EVENT_SSVM_START, "SecondaryStorageVm"); - entityEventDetails.put(EVENT_SSVM_STOP, "SecondaryStorageVm"); - entityEventDetails.put(EVENT_SSVM_REBOOT, "SecondaryStorageVm"); - entityEventDetails.put(EVENT_SSVM_HA, "SecondaryStorageVm"); + entityEventDetails.put(EVENT_SSVM_CREATE, SecondaryStorageVm.class); + entityEventDetails.put(EVENT_SSVM_DESTROY, SecondaryStorageVm.class); + entityEventDetails.put(EVENT_SSVM_START, SecondaryStorageVm.class); + entityEventDetails.put(EVENT_SSVM_STOP, SecondaryStorageVm.class); + entityEventDetails.put(EVENT_SSVM_REBOOT, SecondaryStorageVm.class); + entityEventDetails.put(EVENT_SSVM_HA, SecondaryStorageVm.class); // Service Offerings - entityEventDetails.put(EVENT_SERVICE_OFFERING_CREATE, ServiceOffering.class.getName()); - entityEventDetails.put(EVENT_SERVICE_OFFERING_EDIT, ServiceOffering.class.getName()); - entityEventDetails.put(EVENT_SERVICE_OFFERING_DELETE, ServiceOffering.class.getName()); + entityEventDetails.put(EVENT_SERVICE_OFFERING_CREATE, ServiceOffering.class); + entityEventDetails.put(EVENT_SERVICE_OFFERING_EDIT, ServiceOffering.class); + entityEventDetails.put(EVENT_SERVICE_OFFERING_DELETE, ServiceOffering.class); // Disk Offerings - entityEventDetails.put(EVENT_DISK_OFFERING_CREATE, DiskOffering.class.getName()); - entityEventDetails.put(EVENT_DISK_OFFERING_EDIT, DiskOffering.class.getName()); - entityEventDetails.put(EVENT_DISK_OFFERING_DELETE, DiskOffering.class.getName()); + entityEventDetails.put(EVENT_DISK_OFFERING_CREATE, DiskOffering.class); + entityEventDetails.put(EVENT_DISK_OFFERING_EDIT, DiskOffering.class); + entityEventDetails.put(EVENT_DISK_OFFERING_DELETE, DiskOffering.class); // Network offerings - entityEventDetails.put(EVENT_NETWORK_OFFERING_CREATE, NetworkOffering.class.getName()); - entityEventDetails.put(EVENT_NETWORK_OFFERING_ASSIGN, NetworkOffering.class.getName()); - entityEventDetails.put(EVENT_NETWORK_OFFERING_EDIT, NetworkOffering.class.getName()); - entityEventDetails.put(EVENT_NETWORK_OFFERING_REMOVE, NetworkOffering.class.getName()); - entityEventDetails.put(EVENT_NETWORK_OFFERING_DELETE, NetworkOffering.class.getName()); + entityEventDetails.put(EVENT_NETWORK_OFFERING_CREATE, NetworkOffering.class); + entityEventDetails.put(EVENT_NETWORK_OFFERING_ASSIGN, NetworkOffering.class); + entityEventDetails.put(EVENT_NETWORK_OFFERING_EDIT, NetworkOffering.class); + entityEventDetails.put(EVENT_NETWORK_OFFERING_REMOVE, NetworkOffering.class); + entityEventDetails.put(EVENT_NETWORK_OFFERING_DELETE, NetworkOffering.class); // Pods - entityEventDetails.put(EVENT_POD_CREATE, Pod.class.getName()); - entityEventDetails.put(EVENT_POD_EDIT, Pod.class.getName()); - entityEventDetails.put(EVENT_POD_DELETE, Pod.class.getName()); + entityEventDetails.put(EVENT_POD_CREATE, Pod.class); + entityEventDetails.put(EVENT_POD_EDIT, Pod.class); + entityEventDetails.put(EVENT_POD_DELETE, Pod.class); // Zones - entityEventDetails.put(EVENT_ZONE_CREATE, DataCenter.class.getName()); - entityEventDetails.put(EVENT_ZONE_EDIT, DataCenter.class.getName()); - entityEventDetails.put(EVENT_ZONE_DELETE, DataCenter.class.getName()); + entityEventDetails.put(EVENT_ZONE_CREATE, DataCenter.class); + entityEventDetails.put(EVENT_ZONE_EDIT, DataCenter.class); + entityEventDetails.put(EVENT_ZONE_DELETE, DataCenter.class); // VLANs/IP ranges - entityEventDetails.put(EVENT_VLAN_IP_RANGE_CREATE, Vlan.class.getName()); - entityEventDetails.put(EVENT_VLAN_IP_RANGE_DELETE, Vlan.class.getName()); - entityEventDetails.put(EVENT_VLAN_IP_RANGE_DEDICATE, Vlan.class.getName()); - entityEventDetails.put(EVENT_VLAN_IP_RANGE_RELEASE, Vlan.class.getName()); + entityEventDetails.put(EVENT_VLAN_IP_RANGE_CREATE, Vlan.class); + entityEventDetails.put(EVENT_VLAN_IP_RANGE_DELETE, Vlan.class); + entityEventDetails.put(EVENT_VLAN_IP_RANGE_DEDICATE, Vlan.class); + entityEventDetails.put(EVENT_VLAN_IP_RANGE_RELEASE, Vlan.class); - entityEventDetails.put(EVENT_STORAGE_IP_RANGE_CREATE, StorageNetworkIpRange.class.getName()); - entityEventDetails.put(EVENT_STORAGE_IP_RANGE_DELETE, StorageNetworkIpRange.class.getName()); - entityEventDetails.put(EVENT_STORAGE_IP_RANGE_UPDATE, StorageNetworkIpRange.class.getName()); + entityEventDetails.put(EVENT_STORAGE_IP_RANGE_CREATE, StorageNetworkIpRange.class); + entityEventDetails.put(EVENT_STORAGE_IP_RANGE_DELETE, StorageNetworkIpRange.class); + entityEventDetails.put(EVENT_STORAGE_IP_RANGE_UPDATE, StorageNetworkIpRange.class); // Configuration Table - entityEventDetails.put(EVENT_CONFIGURATION_VALUE_EDIT, Configuration.class.getName()); + entityEventDetails.put(EVENT_CONFIGURATION_VALUE_EDIT, Configuration.class); // Security Groups - entityEventDetails.put(EVENT_SECURITY_GROUP_AUTHORIZE_INGRESS, SecurityGroup.class.getName()); - entityEventDetails.put(EVENT_SECURITY_GROUP_REVOKE_INGRESS, SecurityGroup.class.getName()); - entityEventDetails.put(EVENT_SECURITY_GROUP_AUTHORIZE_EGRESS, SecurityGroup.class.getName()); - entityEventDetails.put(EVENT_SECURITY_GROUP_REVOKE_EGRESS, SecurityGroup.class.getName()); - entityEventDetails.put(EVENT_SECURITY_GROUP_CREATE, SecurityGroup.class.getName()); - entityEventDetails.put(EVENT_SECURITY_GROUP_DELETE, SecurityGroup.class.getName()); - entityEventDetails.put(EVENT_SECURITY_GROUP_ASSIGN, SecurityGroup.class.getName()); - entityEventDetails.put(EVENT_SECURITY_GROUP_REMOVE, SecurityGroup.class.getName()); + entityEventDetails.put(EVENT_SECURITY_GROUP_AUTHORIZE_INGRESS, SecurityGroup.class); + entityEventDetails.put(EVENT_SECURITY_GROUP_REVOKE_INGRESS, SecurityGroup.class); + entityEventDetails.put(EVENT_SECURITY_GROUP_AUTHORIZE_EGRESS, SecurityGroup.class); + entityEventDetails.put(EVENT_SECURITY_GROUP_REVOKE_EGRESS, SecurityGroup.class); + entityEventDetails.put(EVENT_SECURITY_GROUP_CREATE, SecurityGroup.class); + entityEventDetails.put(EVENT_SECURITY_GROUP_DELETE, SecurityGroup.class); + entityEventDetails.put(EVENT_SECURITY_GROUP_ASSIGN, SecurityGroup.class); + entityEventDetails.put(EVENT_SECURITY_GROUP_REMOVE, SecurityGroup.class); // Host - entityEventDetails.put(EVENT_HOST_RECONNECT, Host.class.getName()); + entityEventDetails.put(EVENT_HOST_RECONNECT, Host.class); // Maintenance - entityEventDetails.put(EVENT_MAINTENANCE_CANCEL, Host.class.getName()); - entityEventDetails.put(EVENT_MAINTENANCE_CANCEL_PRIMARY_STORAGE, Host.class.getName()); - entityEventDetails.put(EVENT_MAINTENANCE_PREPARE, Host.class.getName()); - entityEventDetails.put(EVENT_MAINTENANCE_PREPARE_PRIMARY_STORAGE, Host.class.getName()); + entityEventDetails.put(EVENT_MAINTENANCE_CANCEL, Host.class); + entityEventDetails.put(EVENT_MAINTENANCE_CANCEL_PRIMARY_STORAGE, Host.class); + entityEventDetails.put(EVENT_MAINTENANCE_PREPARE, Host.class); + entityEventDetails.put(EVENT_MAINTENANCE_PREPARE_PRIMARY_STORAGE, Host.class); // VPN - entityEventDetails.put(EVENT_REMOTE_ACCESS_VPN_CREATE, RemoteAccessVpn.class.getName()); - entityEventDetails.put(EVENT_REMOTE_ACCESS_VPN_DESTROY, RemoteAccessVpn.class.getName()); - entityEventDetails.put(EVENT_VPN_USER_ADD, RemoteAccessVpn.class.getName()); - entityEventDetails.put(EVENT_VPN_USER_REMOVE, RemoteAccessVpn.class.getName()); - entityEventDetails.put(EVENT_S2S_VPN_GATEWAY_CREATE, RemoteAccessVpn.class.getName()); - entityEventDetails.put(EVENT_S2S_VPN_GATEWAY_DELETE, RemoteAccessVpn.class.getName()); - entityEventDetails.put(EVENT_S2S_VPN_CUSTOMER_GATEWAY_CREATE, RemoteAccessVpn.class.getName()); - entityEventDetails.put(EVENT_S2S_VPN_CUSTOMER_GATEWAY_DELETE, RemoteAccessVpn.class.getName()); - entityEventDetails.put(EVENT_S2S_VPN_CUSTOMER_GATEWAY_UPDATE, RemoteAccessVpn.class.getName()); - entityEventDetails.put(EVENT_S2S_VPN_CONNECTION_CREATE, RemoteAccessVpn.class.getName()); - entityEventDetails.put(EVENT_S2S_VPN_CONNECTION_DELETE, RemoteAccessVpn.class.getName()); - entityEventDetails.put(EVENT_S2S_VPN_CONNECTION_RESET, RemoteAccessVpn.class.getName()); + entityEventDetails.put(EVENT_REMOTE_ACCESS_VPN_CREATE, RemoteAccessVpn.class); + entityEventDetails.put(EVENT_REMOTE_ACCESS_VPN_DESTROY, RemoteAccessVpn.class); + entityEventDetails.put(EVENT_VPN_USER_ADD, RemoteAccessVpn.class); + entityEventDetails.put(EVENT_VPN_USER_REMOVE, RemoteAccessVpn.class); + entityEventDetails.put(EVENT_S2S_VPN_GATEWAY_CREATE, RemoteAccessVpn.class); + entityEventDetails.put(EVENT_S2S_VPN_GATEWAY_DELETE, RemoteAccessVpn.class); + entityEventDetails.put(EVENT_S2S_VPN_CUSTOMER_GATEWAY_CREATE, RemoteAccessVpn.class); + entityEventDetails.put(EVENT_S2S_VPN_CUSTOMER_GATEWAY_DELETE, RemoteAccessVpn.class); + entityEventDetails.put(EVENT_S2S_VPN_CUSTOMER_GATEWAY_UPDATE, RemoteAccessVpn.class); + entityEventDetails.put(EVENT_S2S_VPN_CONNECTION_CREATE, RemoteAccessVpn.class); + entityEventDetails.put(EVENT_S2S_VPN_CONNECTION_DELETE, RemoteAccessVpn.class); + entityEventDetails.put(EVENT_S2S_VPN_CONNECTION_RESET, RemoteAccessVpn.class); // Custom certificates entityEventDetails.put(EVENT_UPLOAD_CUSTOM_CERTIFICATE, "Certificate"); // OneToOnenat - entityEventDetails.put(EVENT_ENABLE_STATIC_NAT, StaticNat.class.getName()); - entityEventDetails.put(EVENT_DISABLE_STATIC_NAT, StaticNat.class.getName()); + entityEventDetails.put(EVENT_ENABLE_STATIC_NAT, StaticNat.class); + entityEventDetails.put(EVENT_DISABLE_STATIC_NAT, StaticNat.class); - entityEventDetails.put(EVENT_ZONE_VLAN_ASSIGN, Vlan.class.getName()); - entityEventDetails.put(EVENT_ZONE_VLAN_RELEASE, Vlan.class.getName()); + entityEventDetails.put(EVENT_ZONE_VLAN_ASSIGN, Vlan.class); + entityEventDetails.put(EVENT_ZONE_VLAN_RELEASE, Vlan.class); // Projects - entityEventDetails.put(EVENT_PROJECT_CREATE, Project.class.getName()); - entityEventDetails.put(EVENT_PROJECT_UPDATE, Project.class.getName()); - entityEventDetails.put(EVENT_PROJECT_DELETE, Project.class.getName()); - entityEventDetails.put(EVENT_PROJECT_ACTIVATE, Project.class.getName()); - entityEventDetails.put(EVENT_PROJECT_SUSPEND, Project.class.getName()); - entityEventDetails.put(EVENT_PROJECT_ACCOUNT_ADD, Project.class.getName()); - entityEventDetails.put(EVENT_PROJECT_INVITATION_UPDATE, Project.class.getName()); - entityEventDetails.put(EVENT_PROJECT_INVITATION_REMOVE, Project.class.getName()); - entityEventDetails.put(EVENT_PROJECT_ACCOUNT_REMOVE, Project.class.getName()); + entityEventDetails.put(EVENT_PROJECT_CREATE, Project.class); + entityEventDetails.put(EVENT_PROJECT_UPDATE, Project.class); + entityEventDetails.put(EVENT_PROJECT_DELETE, Project.class); + entityEventDetails.put(EVENT_PROJECT_ACTIVATE, Project.class); + entityEventDetails.put(EVENT_PROJECT_SUSPEND, Project.class); + entityEventDetails.put(EVENT_PROJECT_ACCOUNT_ADD, Project.class); + entityEventDetails.put(EVENT_PROJECT_INVITATION_UPDATE, Project.class); + entityEventDetails.put(EVENT_PROJECT_INVITATION_REMOVE, Project.class); + entityEventDetails.put(EVENT_PROJECT_ACCOUNT_REMOVE, Project.class); // Network as a Service - entityEventDetails.put(EVENT_NETWORK_ELEMENT_CONFIGURE, Network.class.getName()); + entityEventDetails.put(EVENT_NETWORK_ELEMENT_CONFIGURE, Network.class); // Physical Network Events - entityEventDetails.put(EVENT_PHYSICAL_NETWORK_CREATE, PhysicalNetwork.class.getName()); - entityEventDetails.put(EVENT_PHYSICAL_NETWORK_DELETE, PhysicalNetwork.class.getName()); - entityEventDetails.put(EVENT_PHYSICAL_NETWORK_UPDATE, PhysicalNetwork.class.getName()); + entityEventDetails.put(EVENT_PHYSICAL_NETWORK_CREATE, PhysicalNetwork.class); + entityEventDetails.put(EVENT_PHYSICAL_NETWORK_DELETE, PhysicalNetwork.class); + entityEventDetails.put(EVENT_PHYSICAL_NETWORK_UPDATE, PhysicalNetwork.class); // Physical Network Service Provider Events - entityEventDetails.put(EVENT_SERVICE_PROVIDER_CREATE, PhysicalNetworkServiceProvider.class.getName()); - entityEventDetails.put(EVENT_SERVICE_PROVIDER_DELETE, PhysicalNetworkServiceProvider.class.getName()); - entityEventDetails.put(EVENT_SERVICE_PROVIDER_UPDATE, PhysicalNetworkServiceProvider.class.getName()); + entityEventDetails.put(EVENT_SERVICE_PROVIDER_CREATE, PhysicalNetworkServiceProvider.class); + entityEventDetails.put(EVENT_SERVICE_PROVIDER_DELETE, PhysicalNetworkServiceProvider.class); + entityEventDetails.put(EVENT_SERVICE_PROVIDER_UPDATE, PhysicalNetworkServiceProvider.class); // Physical Network TrafficType Events - entityEventDetails.put(EVENT_TRAFFIC_TYPE_CREATE, PhysicalNetworkTrafficType.class.getName()); - entityEventDetails.put(EVENT_TRAFFIC_TYPE_DELETE, PhysicalNetworkTrafficType.class.getName()); - entityEventDetails.put(EVENT_TRAFFIC_TYPE_UPDATE, PhysicalNetworkTrafficType.class.getName()); + entityEventDetails.put(EVENT_TRAFFIC_TYPE_CREATE, PhysicalNetworkTrafficType.class); + entityEventDetails.put(EVENT_TRAFFIC_TYPE_DELETE, PhysicalNetworkTrafficType.class); + entityEventDetails.put(EVENT_TRAFFIC_TYPE_UPDATE, PhysicalNetworkTrafficType.class); // external network device events - entityEventDetails.put(EVENT_EXTERNAL_LB_DEVICE_ADD, PhysicalNetwork.class.getName()); - entityEventDetails.put(EVENT_EXTERNAL_LB_DEVICE_DELETE, PhysicalNetwork.class.getName()); - entityEventDetails.put(EVENT_EXTERNAL_LB_DEVICE_CONFIGURE, PhysicalNetwork.class.getName()); + entityEventDetails.put(EVENT_EXTERNAL_LB_DEVICE_ADD, PhysicalNetwork.class); + entityEventDetails.put(EVENT_EXTERNAL_LB_DEVICE_DELETE, PhysicalNetwork.class); + entityEventDetails.put(EVENT_EXTERNAL_LB_DEVICE_CONFIGURE, PhysicalNetwork.class); // external switch management device events (E.g.: Cisco Nexus 1000v Virtual Supervisor Module. entityEventDetails.put(EVENT_EXTERNAL_SWITCH_MGMT_DEVICE_ADD, "Nexus1000v"); @@ -750,32 +753,32 @@ public class EventTypes { entityEventDetails.put(EVENT_EXTERNAL_SWITCH_MGMT_DEVICE_ENABLE, "Nexus1000v"); entityEventDetails.put(EVENT_EXTERNAL_SWITCH_MGMT_DEVICE_DISABLE, "Nexus1000v"); - entityEventDetails.put(EVENT_EXTERNAL_FIREWALL_DEVICE_ADD, PhysicalNetwork.class.getName()); - entityEventDetails.put(EVENT_EXTERNAL_FIREWALL_DEVICE_DELETE, PhysicalNetwork.class.getName()); - entityEventDetails.put(EVENT_EXTERNAL_FIREWALL_DEVICE_CONFIGURE, PhysicalNetwork.class.getName()); + entityEventDetails.put(EVENT_EXTERNAL_FIREWALL_DEVICE_ADD, PhysicalNetwork.class); + entityEventDetails.put(EVENT_EXTERNAL_FIREWALL_DEVICE_DELETE, PhysicalNetwork.class); + entityEventDetails.put(EVENT_EXTERNAL_FIREWALL_DEVICE_CONFIGURE, PhysicalNetwork.class); // VPC - entityEventDetails.put(EVENT_VPC_CREATE, Vpc.class.getName()); - entityEventDetails.put(EVENT_VPC_UPDATE, Vpc.class.getName()); - entityEventDetails.put(EVENT_VPC_DELETE, Vpc.class.getName()); - entityEventDetails.put(EVENT_VPC_RESTART, Vpc.class.getName()); + entityEventDetails.put(EVENT_VPC_CREATE, Vpc.class); + entityEventDetails.put(EVENT_VPC_UPDATE, Vpc.class); + entityEventDetails.put(EVENT_VPC_DELETE, Vpc.class); + entityEventDetails.put(EVENT_VPC_RESTART, Vpc.class); // VPC offerings - entityEventDetails.put(EVENT_VPC_OFFERING_CREATE, Vpc.class.getName()); - entityEventDetails.put(EVENT_VPC_OFFERING_UPDATE, Vpc.class.getName()); - entityEventDetails.put(EVENT_VPC_OFFERING_DELETE, Vpc.class.getName()); + entityEventDetails.put(EVENT_VPC_OFFERING_CREATE, Vpc.class); + entityEventDetails.put(EVENT_VPC_OFFERING_UPDATE, Vpc.class); + entityEventDetails.put(EVENT_VPC_OFFERING_DELETE, Vpc.class); // Private gateway - entityEventDetails.put(EVENT_PRIVATE_GATEWAY_CREATE, PrivateGateway.class.getName()); - entityEventDetails.put(EVENT_PRIVATE_GATEWAY_DELETE, PrivateGateway.class.getName()); + entityEventDetails.put(EVENT_PRIVATE_GATEWAY_CREATE, PrivateGateway.class); + entityEventDetails.put(EVENT_PRIVATE_GATEWAY_DELETE, PrivateGateway.class); // Static routes - entityEventDetails.put(EVENT_STATIC_ROUTE_CREATE, StaticRoute.class.getName()); - entityEventDetails.put(EVENT_STATIC_ROUTE_DELETE, StaticRoute.class.getName()); + entityEventDetails.put(EVENT_STATIC_ROUTE_CREATE, StaticRoute.class); + entityEventDetails.put(EVENT_STATIC_ROUTE_DELETE, StaticRoute.class); // tag related events - entityEventDetails.put(EVENT_TAGS_CREATE, "Tag"); - entityEventDetails.put(EVENT_TAGS_DELETE, "tag"); + entityEventDetails.put(EVENT_TAGS_CREATE, ResourceTag.class); + entityEventDetails.put(EVENT_TAGS_DELETE, ResourceTag.class); // external network device events entityEventDetails.put(EVENT_EXTERNAL_NVP_CONTROLLER_ADD, "NvpController"); @@ -783,23 +786,23 @@ public class EventTypes { entityEventDetails.put(EVENT_EXTERNAL_NVP_CONTROLLER_CONFIGURE, "NvpController"); // AutoScale - entityEventDetails.put(EVENT_COUNTER_CREATE, AutoScaleCounter.class.getName()); - entityEventDetails.put(EVENT_COUNTER_DELETE, AutoScaleCounter.class.getName()); - entityEventDetails.put(EVENT_CONDITION_CREATE, Condition.class.getName()); - entityEventDetails.put(EVENT_CONDITION_DELETE, Condition.class.getName()); - entityEventDetails.put(EVENT_AUTOSCALEPOLICY_CREATE, AutoScalePolicy.class.getName()); - entityEventDetails.put(EVENT_AUTOSCALEPOLICY_UPDATE, AutoScalePolicy.class.getName()); - entityEventDetails.put(EVENT_AUTOSCALEPOLICY_DELETE, AutoScalePolicy.class.getName()); - entityEventDetails.put(EVENT_AUTOSCALEVMPROFILE_CREATE, AutoScaleVmProfile.class.getName()); - entityEventDetails.put(EVENT_AUTOSCALEVMPROFILE_DELETE, AutoScaleVmProfile.class.getName()); - entityEventDetails.put(EVENT_AUTOSCALEVMPROFILE_UPDATE, AutoScaleVmProfile.class.getName()); - entityEventDetails.put(EVENT_AUTOSCALEVMGROUP_CREATE, AutoScaleVmGroup.class.getName()); - entityEventDetails.put(EVENT_AUTOSCALEVMGROUP_DELETE, AutoScaleVmGroup.class.getName()); - entityEventDetails.put(EVENT_AUTOSCALEVMGROUP_UPDATE, AutoScaleVmGroup.class.getName()); - entityEventDetails.put(EVENT_AUTOSCALEVMGROUP_ENABLE, AutoScaleVmGroup.class.getName()); - entityEventDetails.put(EVENT_AUTOSCALEVMGROUP_DISABLE, AutoScaleVmGroup.class.getName()); - entityEventDetails.put(EVENT_GUEST_VLAN_RANGE_DEDICATE, GuestVlan.class.getName()); - entityEventDetails.put(EVENT_DEDICATED_GUEST_VLAN_RANGE_RELEASE, GuestVlan.class.getName()); + entityEventDetails.put(EVENT_COUNTER_CREATE, AutoScaleCounter.class); + entityEventDetails.put(EVENT_COUNTER_DELETE, AutoScaleCounter.class); + entityEventDetails.put(EVENT_CONDITION_CREATE, Condition.class); + entityEventDetails.put(EVENT_CONDITION_DELETE, Condition.class); + entityEventDetails.put(EVENT_AUTOSCALEPOLICY_CREATE, AutoScalePolicy.class); + entityEventDetails.put(EVENT_AUTOSCALEPOLICY_UPDATE, AutoScalePolicy.class); + entityEventDetails.put(EVENT_AUTOSCALEPOLICY_DELETE, AutoScalePolicy.class); + entityEventDetails.put(EVENT_AUTOSCALEVMPROFILE_CREATE, AutoScaleVmProfile.class); + entityEventDetails.put(EVENT_AUTOSCALEVMPROFILE_DELETE, AutoScaleVmProfile.class); + entityEventDetails.put(EVENT_AUTOSCALEVMPROFILE_UPDATE, AutoScaleVmProfile.class); + entityEventDetails.put(EVENT_AUTOSCALEVMGROUP_CREATE, AutoScaleVmGroup.class); + entityEventDetails.put(EVENT_AUTOSCALEVMGROUP_DELETE, AutoScaleVmGroup.class); + entityEventDetails.put(EVENT_AUTOSCALEVMGROUP_UPDATE, AutoScaleVmGroup.class); + entityEventDetails.put(EVENT_AUTOSCALEVMGROUP_ENABLE, AutoScaleVmGroup.class); + entityEventDetails.put(EVENT_AUTOSCALEVMGROUP_DISABLE, AutoScaleVmGroup.class); + entityEventDetails.put(EVENT_GUEST_VLAN_RANGE_DEDICATE, GuestVlan.class); + entityEventDetails.put(EVENT_DEDICATED_GUEST_VLAN_RANGE_RELEASE, GuestVlan.class); // OpenDaylight entityEventDetails.put(EVENT_EXTERNAL_OPENDAYLIGHT_ADD_CONTROLLER, "OpenDaylightController"); @@ -807,24 +810,40 @@ public class EventTypes { entityEventDetails.put(EVENT_EXTERNAL_OPENDAYLIGHT_CONFIGURE_CONTROLLER, "OpenDaylightController"); //Guest OS - entityEventDetails.put(EVENT_GUEST_OS_ADD, GuestOS.class.getName()); - entityEventDetails.put(EVENT_GUEST_OS_REMOVE, GuestOS.class.getName()); - entityEventDetails.put(EVENT_GUEST_OS_UPDATE, GuestOS.class.getName()); - entityEventDetails.put(EVENT_GUEST_OS_MAPPING_ADD, GuestOSHypervisor.class.getName()); - entityEventDetails.put(EVENT_GUEST_OS_MAPPING_REMOVE, GuestOSHypervisor.class.getName()); - entityEventDetails.put(EVENT_GUEST_OS_MAPPING_UPDATE, GuestOSHypervisor.class.getName()); + entityEventDetails.put(EVENT_GUEST_OS_ADD, GuestOS.class); + entityEventDetails.put(EVENT_GUEST_OS_REMOVE, GuestOS.class); + entityEventDetails.put(EVENT_GUEST_OS_UPDATE, GuestOS.class); + entityEventDetails.put(EVENT_GUEST_OS_MAPPING_ADD, GuestOSHypervisor.class); + entityEventDetails.put(EVENT_GUEST_OS_MAPPING_REMOVE, GuestOSHypervisor.class); + entityEventDetails.put(EVENT_GUEST_OS_MAPPING_UPDATE, GuestOSHypervisor.class); } public static String getEntityForEvent(String eventName) { - String entityClassName = entityEventDetails.get(eventName); - if (entityClassName == null || entityClassName.isEmpty()) { + Object entityClass = entityEventDetails.get(eventName); + if (entityClass == null) { return null; + } else if (entityClass instanceof String){ + return (String)entityClass; + } else if (entityClass instanceof Class){ + String entityClassName = ((Class)entityClass).getName(); + int index = entityClassName.lastIndexOf("."); + String entityName = entityClassName; + if (index != -1) { + entityName = entityClassName.substring(index + 1); + } + return entityName; } - int index = entityClassName.lastIndexOf("."); - String entityName = entityClassName; - if (index != -1) { - entityName = entityClassName.substring(index + 1); + + return null; + } + + public static Class getEntityClassForEvent(String eventName) { + Object clz = entityEventDetails.get(eventName); + + if(clz instanceof Class){ + return (Class)entityEventDetails.get(eventName); } - return entityName; + + return null; } } diff --git a/api/src/com/cloud/gpu/GPU.java b/api/src/com/cloud/gpu/GPU.java index 0eb466758f..9177edbf9c 100644 --- a/api/src/com/cloud/gpu/GPU.java +++ b/api/src/com/cloud/gpu/GPU.java @@ -23,15 +23,13 @@ public enum Keys { pciDevice, vgpuType } - public enum Type { - GPU_Passthrough, - VGPU - } public enum vGPUType { GRID_K100("GRID K100"), + GRID_K120Q("GRID K120Q"), GRID_K140Q("GRID K140Q"), GRID_K200("GRID K200"), + GRID_K220Q("GRID K220Q"), GRID_K240Q("GRID K240Q"), GRID_K260("GRID K260Q"), passthrough("passthrough"); diff --git a/api/src/com/cloud/network/IpAddress.java b/api/src/com/cloud/network/IpAddress.java index 5aae784279..f831e275c7 100644 --- a/api/src/com/cloud/network/IpAddress.java +++ b/api/src/com/cloud/network/IpAddress.java @@ -19,6 +19,7 @@ import java.util.Date; import org.apache.cloudstack.acl.ControlledEntity; +import org.apache.cloudstack.api.Displayable; import org.apache.cloudstack.api.Identity; import org.apache.cloudstack.api.InternalIdentity; @@ -35,7 +36,7 @@ * - DomainId = domain of the account owner. * - Allocated = time it was allocated. */ -public interface IpAddress extends ControlledEntity, Identity, InternalIdentity { +public interface IpAddress extends ControlledEntity, Identity, InternalIdentity, Displayable { 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. @@ -85,6 +86,7 @@ enum Purpose { Long getNetworkId(); + @Override boolean isDisplay(); } diff --git a/api/src/com/cloud/network/Network.java b/api/src/com/cloud/network/Network.java index 3283a55bfe..885bffef98 100644 --- a/api/src/com/cloud/network/Network.java +++ b/api/src/com/cloud/network/Network.java @@ -22,6 +22,7 @@ import java.util.List; import org.apache.cloudstack.acl.ControlledEntity; +import org.apache.cloudstack.api.Displayable; import org.apache.cloudstack.api.Identity; import org.apache.cloudstack.api.InternalIdentity; @@ -34,7 +35,7 @@ /** * owned by an account. */ -public interface Network extends ControlledEntity, StateObject, InternalIdentity, Identity, Serializable { +public interface Network extends ControlledEntity, StateObject, InternalIdentity, Identity, Serializable, Displayable { public enum GuestType { Shared, Isolated @@ -57,7 +58,7 @@ public static class Service { public static final Service PortForwarding = new Service("PortForwarding"); public static final Service SecurityGroup = new Service("SecurityGroup"); public static final Service NetworkACL = new Service("NetworkACL", Capability.SupportedProtocols); - public static final Service Connectivity = new Service("Connectivity", Capability.DistributedRouter); + public static final Service Connectivity = new Service("Connectivity", Capability.DistributedRouter, Capability.RegionLevelVpc, Capability.StretchedL2Subnet); private final String name; private final Capability[] caps; @@ -187,6 +188,8 @@ public static class Capability { public static final Capability LbSchemes = new Capability("LbSchemes"); public static final Capability DhcpAccrossMultipleSubnets = new Capability("DhcpAccrossMultipleSubnets"); public static final Capability DistributedRouter = new Capability("DistributedRouter"); + public static final Capability StretchedL2Subnet = new Capability("StretchedL2Subnet"); + public static final Capability RegionLevelVpc = new Capability("RegionLevelVpc"); private final String name; @@ -325,8 +328,11 @@ public void setIp6Address(String ip6Address) { boolean getSpecifyIpRanges(); + @Deprecated boolean getDisplayNetwork(); + boolean isDisplay(); + String getGuruName(); /** @@ -337,4 +343,6 @@ public void setIp6Address(String ip6Address) { Long getNetworkACLId(); void setNetworkACLId(Long networkACLId); + + boolean isStrechedL2Network(); } diff --git a/api/src/com/cloud/network/NetworkModel.java b/api/src/com/cloud/network/NetworkModel.java index f6555db565..1e0a8e88e4 100644 --- a/api/src/com/cloud/network/NetworkModel.java +++ b/api/src/com/cloud/network/NetworkModel.java @@ -22,6 +22,8 @@ import java.util.Map; import java.util.Set; +import org.apache.cloudstack.acl.SecurityChecker.AccessType; + import com.cloud.dc.Vlan; import com.cloud.exception.InsufficientAddressCapacityException; import com.cloud.exception.InvalidParameterValueException; @@ -273,4 +275,6 @@ public interface NetworkModel { boolean isNetworkReadyForGc(long networkId); boolean getNetworkEgressDefaultPolicy(Long networkId); + + void checkNetworkPermissions(Account owner, Network network, AccessType accessType); } \ No newline at end of file diff --git a/api/src/com/cloud/network/NetworkProfile.java b/api/src/com/cloud/network/NetworkProfile.java index 3f576945a5..1b806d56de 100644 --- a/api/src/com/cloud/network/NetworkProfile.java +++ b/api/src/com/cloud/network/NetworkProfile.java @@ -18,8 +18,6 @@ import java.net.URI; -import org.apache.cloudstack.acl.IAMEntityType; - import com.cloud.network.Networks.BroadcastDomainType; import com.cloud.network.Networks.Mode; import com.cloud.network.Networks.TrafficType; @@ -57,6 +55,7 @@ public class NetworkProfile implements Network { private final boolean displayNetwork; private Long networkAclId; private final String guruName; + private boolean strechedL2Subnet; public NetworkProfile(Network network) { id = network.getId(); @@ -89,6 +88,7 @@ public NetworkProfile(Network network) { displayNetwork = network.getDisplayNetwork(); networkAclId = network.getNetworkACLId(); guruName = network.getGuruName(); + strechedL2Subnet = network.isStrechedL2Network(); } public String getDns1() { @@ -248,6 +248,11 @@ public boolean getDisplayNetwork() { return displayNetwork; } + @Override + public boolean isDisplay(){ + return displayNetwork; + } + @Override public Long getVpcId() { return vpcId; @@ -279,7 +284,13 @@ public String getIp6Cidr() { } @Override - public IAMEntityType getEntityType() { - return IAMEntityType.Network; + public Class getEntityType() { + return Network.class; } + + @Override + public boolean isStrechedL2Network() { + return false; + } + } diff --git a/api/src/com/cloud/network/RemoteAccessVpn.java b/api/src/com/cloud/network/RemoteAccessVpn.java index 4d7e4d49b1..25b4fbbcde 100644 --- a/api/src/com/cloud/network/RemoteAccessVpn.java +++ b/api/src/com/cloud/network/RemoteAccessVpn.java @@ -17,10 +17,11 @@ package com.cloud.network; import org.apache.cloudstack.acl.ControlledEntity; +import org.apache.cloudstack.api.Displayable; import org.apache.cloudstack.api.Identity; import org.apache.cloudstack.api.InternalIdentity; -public interface RemoteAccessVpn extends ControlledEntity, InternalIdentity, Identity { +public interface RemoteAccessVpn extends ControlledEntity, InternalIdentity, Identity, Displayable { enum State { Added, Running, Removed } @@ -39,5 +40,6 @@ enum State { State getState(); + @Override boolean isDisplay(); } diff --git a/api/src/com/cloud/network/Site2SiteVpnConnection.java b/api/src/com/cloud/network/Site2SiteVpnConnection.java index 81e8180119..cfc439abcd 100644 --- a/api/src/com/cloud/network/Site2SiteVpnConnection.java +++ b/api/src/com/cloud/network/Site2SiteVpnConnection.java @@ -19,9 +19,10 @@ import java.util.Date; import org.apache.cloudstack.acl.ControlledEntity; +import org.apache.cloudstack.api.Displayable; import org.apache.cloudstack.api.InternalIdentity; -public interface Site2SiteVpnConnection extends ControlledEntity, InternalIdentity { +public interface Site2SiteVpnConnection extends ControlledEntity, InternalIdentity, Displayable { enum State { Pending, Connected, Disconnected, Error, } @@ -43,5 +44,6 @@ enum State { public boolean isPassive(); + @Override boolean isDisplay(); } diff --git a/api/src/com/cloud/network/Site2SiteVpnGateway.java b/api/src/com/cloud/network/Site2SiteVpnGateway.java index bae12597f2..57037d6b64 100644 --- a/api/src/com/cloud/network/Site2SiteVpnGateway.java +++ b/api/src/com/cloud/network/Site2SiteVpnGateway.java @@ -19,16 +19,18 @@ import java.util.Date; import org.apache.cloudstack.acl.ControlledEntity; +import org.apache.cloudstack.api.Displayable; import org.apache.cloudstack.api.Identity; import org.apache.cloudstack.api.InternalIdentity; -public interface Site2SiteVpnGateway extends ControlledEntity, Identity, InternalIdentity { +public interface Site2SiteVpnGateway extends ControlledEntity, Identity, InternalIdentity, Displayable { public long getAddrId(); public long getVpcId(); public Date getRemoved(); + @Override boolean isDisplay(); } diff --git a/api/src/com/cloud/network/as/AutoScaleVmGroup.java b/api/src/com/cloud/network/as/AutoScaleVmGroup.java index 14c761593b..cf2c15c421 100644 --- a/api/src/com/cloud/network/as/AutoScaleVmGroup.java +++ b/api/src/com/cloud/network/as/AutoScaleVmGroup.java @@ -20,9 +20,10 @@ import java.util.Date; import org.apache.cloudstack.acl.ControlledEntity; +import org.apache.cloudstack.api.Displayable; import org.apache.cloudstack.api.InternalIdentity; -public interface AutoScaleVmGroup extends ControlledEntity, InternalIdentity { +public interface AutoScaleVmGroup extends ControlledEntity, InternalIdentity, Displayable { String State_New = "new"; String State_Revoke = "revoke"; @@ -53,6 +54,7 @@ public interface AutoScaleVmGroup extends ControlledEntity, InternalIdentity { String getUuid(); + @Override boolean isDisplay(); } diff --git a/api/src/com/cloud/network/as/AutoScaleVmProfile.java b/api/src/com/cloud/network/as/AutoScaleVmProfile.java index 6e0b5ffb91..495446a6e8 100644 --- a/api/src/com/cloud/network/as/AutoScaleVmProfile.java +++ b/api/src/com/cloud/network/as/AutoScaleVmProfile.java @@ -20,6 +20,7 @@ import java.util.List; import org.apache.cloudstack.acl.ControlledEntity; +import org.apache.cloudstack.api.Displayable; import org.apache.cloudstack.api.InternalIdentity; import com.cloud.utils.Pair; @@ -27,7 +28,7 @@ /** * AutoScaleVmProfile */ -public interface AutoScaleVmProfile extends ControlledEntity, InternalIdentity { +public interface AutoScaleVmProfile extends ControlledEntity, InternalIdentity, Displayable { @Override public long getId(); @@ -48,6 +49,7 @@ public interface AutoScaleVmProfile extends ControlledEntity, InternalIdentity { public long getAutoScaleUserId(); + @Override boolean isDisplay(); } diff --git a/api/src/com/cloud/network/lb/LoadBalancingRulesService.java b/api/src/com/cloud/network/lb/LoadBalancingRulesService.java index 4c87d342db..c4976338f0 100644 --- a/api/src/com/cloud/network/lb/LoadBalancingRulesService.java +++ b/api/src/com/cloud/network/lb/LoadBalancingRulesService.java @@ -92,13 +92,13 @@ LoadBalancer createPublicLoadBalancerRule(String xId, String name, String descri boolean deleteLBHealthCheckPolicy(long healthCheckPolicyId, boolean apply); /** - * Assign a virtual machine, or list of virtual machines, to a load balancer. + * Assign a virtual machine or list of virtual machines, or Map of to a load balancer. */ - boolean assignToLoadBalancer(long lbRuleId, List vmIds); + boolean assignToLoadBalancer(long lbRuleId, List vmIds, Map> vmIdIpMap); boolean assignSSLCertToLoadBalancerRule(Long lbRuleId, String certName, String publicCert, String privateKey); - boolean removeFromLoadBalancer(long lbRuleId, List vmIds); + boolean removeFromLoadBalancer(long lbRuleId, List vmIds, Map> vmIdIpMap); boolean applyLoadBalancerConfig(long lbRuleId) throws ResourceUnavailableException; @@ -151,4 +151,12 @@ LoadBalancer createPublicLoadBalancerRule(String xId, String name, String descri public void updateLBHealthChecks(Scheme scheme) throws ResourceUnavailableException; Map getLbInstances(long lbId); + + boolean isLbRuleMappedToVmGuestIp(String vmSecondaryIp); + + List listLbVmIpAddress(long id, long vmId); + + StickinessPolicy updateLBStickinessPolicy(long id, String customId, Boolean forDisplay); + + HealthCheckPolicy updateLBHealthCheckPolicy(long id, String customId, Boolean forDisplay); } diff --git a/api/src/com/cloud/network/rules/FirewallRule.java b/api/src/com/cloud/network/rules/FirewallRule.java index b02257b7c8..4346e2f665 100644 --- a/api/src/com/cloud/network/rules/FirewallRule.java +++ b/api/src/com/cloud/network/rules/FirewallRule.java @@ -19,10 +19,11 @@ import java.util.List; import org.apache.cloudstack.acl.ControlledEntity; +import org.apache.cloudstack.api.Displayable; import org.apache.cloudstack.api.Identity; import org.apache.cloudstack.api.InternalIdentity; -public interface FirewallRule extends ControlledEntity, Identity, InternalIdentity { +public interface FirewallRule extends ControlledEntity, Identity, InternalIdentity, Displayable { enum Purpose { Firewall, PortForwarding, LoadBalancing, Vpn, StaticNat, NetworkACL, } @@ -87,6 +88,7 @@ enum TrafficType { */ TrafficType getTrafficType(); + @Override boolean isDisplay(); } diff --git a/api/src/com/cloud/network/rules/HealthCheckPolicy.java b/api/src/com/cloud/network/rules/HealthCheckPolicy.java index 6157bd4020..f7562e8e89 100644 --- a/api/src/com/cloud/network/rules/HealthCheckPolicy.java +++ b/api/src/com/cloud/network/rules/HealthCheckPolicy.java @@ -16,12 +16,13 @@ // under the License. package com.cloud.network.rules; +import org.apache.cloudstack.api.Displayable; import org.apache.cloudstack.api.Identity; import org.apache.cloudstack.api.InternalIdentity; /** */ -public interface HealthCheckPolicy extends InternalIdentity, Identity { +public interface HealthCheckPolicy extends InternalIdentity, Identity, Displayable { public long getLoadBalancerId(); @@ -39,4 +40,7 @@ public interface HealthCheckPolicy extends InternalIdentity, Identity { public boolean isRevoke(); + @Override + boolean isDisplay(); + } diff --git a/api/src/com/cloud/network/rules/StickinessPolicy.java b/api/src/com/cloud/network/rules/StickinessPolicy.java index da48754666..7f956f98d4 100644 --- a/api/src/com/cloud/network/rules/StickinessPolicy.java +++ b/api/src/com/cloud/network/rules/StickinessPolicy.java @@ -18,6 +18,7 @@ import java.util.List; +import org.apache.cloudstack.api.Displayable; import org.apache.cloudstack.api.Identity; import org.apache.cloudstack.api.InternalIdentity; @@ -25,7 +26,7 @@ /** */ -public interface StickinessPolicy extends InternalIdentity, Identity { +public interface StickinessPolicy extends InternalIdentity, Identity, Displayable { public long getLoadBalancerId(); @@ -39,4 +40,7 @@ public interface StickinessPolicy extends InternalIdentity, Identity { public List> getParams(); /* get params in Map format */ + @Override + boolean isDisplay(); + } diff --git a/api/src/com/cloud/network/vpc/NetworkACL.java b/api/src/com/cloud/network/vpc/NetworkACL.java index 3ebee146ed..193a48c60f 100644 --- a/api/src/com/cloud/network/vpc/NetworkACL.java +++ b/api/src/com/cloud/network/vpc/NetworkACL.java @@ -17,9 +17,10 @@ package com.cloud.network.vpc; +import org.apache.cloudstack.api.Displayable; import org.apache.cloudstack.api.InternalIdentity; -public interface NetworkACL extends InternalIdentity { +public interface NetworkACL extends InternalIdentity, Displayable { public static final long DEFAULT_DENY = 1; public static final long DEFAULT_ALLOW = 2; @@ -34,5 +35,6 @@ public interface NetworkACL extends InternalIdentity { String getName(); + @Override boolean isDisplay(); } diff --git a/api/src/com/cloud/network/vpc/NetworkACLItem.java b/api/src/com/cloud/network/vpc/NetworkACLItem.java index faa4d273c9..8e288a2b96 100644 --- a/api/src/com/cloud/network/vpc/NetworkACLItem.java +++ b/api/src/com/cloud/network/vpc/NetworkACLItem.java @@ -18,9 +18,10 @@ import java.util.List; +import org.apache.cloudstack.api.Displayable; import org.apache.cloudstack.api.InternalIdentity; -public interface NetworkACLItem extends InternalIdentity { +public interface NetworkACLItem extends InternalIdentity, Displayable { String getUuid(); @@ -73,6 +74,7 @@ enum Action { */ TrafficType getTrafficType(); + @Override boolean isDisplay(); } diff --git a/api/src/com/cloud/network/vpc/StaticRouteProfile.java b/api/src/com/cloud/network/vpc/StaticRouteProfile.java index b5bd5f7af5..737541f0a4 100644 --- a/api/src/com/cloud/network/vpc/StaticRouteProfile.java +++ b/api/src/com/cloud/network/vpc/StaticRouteProfile.java @@ -16,7 +16,6 @@ // under the License. package com.cloud.network.vpc; -import org.apache.cloudstack.acl.IAMEntityType; public class StaticRouteProfile implements StaticRoute { private long id; @@ -104,7 +103,7 @@ public String getNetmask() { } @Override - public IAMEntityType getEntityType() { - return IAMEntityType.StaticRoute; + public Class getEntityType() { + return StaticRoute.class; } } diff --git a/api/src/com/cloud/network/vpc/Vpc.java b/api/src/com/cloud/network/vpc/Vpc.java index 4bc8c98872..23388787d2 100644 --- a/api/src/com/cloud/network/vpc/Vpc.java +++ b/api/src/com/cloud/network/vpc/Vpc.java @@ -79,4 +79,10 @@ public enum State { * @return true if VPC is configured to use distributed router to provides one-hop forwarding and hypervisor based ACL */ boolean usesDistributedRouter(); + + /** + * + * @return true if VPC spans multiple zones in the region + */ + boolean isRegionLevelVpc(); } diff --git a/api/src/com/cloud/network/vpc/VpcOffering.java b/api/src/com/cloud/network/vpc/VpcOffering.java index a0a1b1528c..660c79dc1e 100644 --- a/api/src/com/cloud/network/vpc/VpcOffering.java +++ b/api/src/com/cloud/network/vpc/VpcOffering.java @@ -56,8 +56,12 @@ public enum State { Long getServiceOfferingId(); /** - * * @return true if the offering provides a distributed router capable of one-hop forwarding */ boolean supportsDistributedRouter(); + + /** + * @return true if VPC created with the offering can span multiple zones in the region + */ + boolean offersRegionLevelVPC(); } diff --git a/api/src/com/cloud/network/vpc/VpcProvisioningService.java b/api/src/com/cloud/network/vpc/VpcProvisioningService.java index e545275217..82a7baae95 100644 --- a/api/src/com/cloud/network/vpc/VpcProvisioningService.java +++ b/api/src/com/cloud/network/vpc/VpcProvisioningService.java @@ -16,6 +16,7 @@ // under the License. package com.cloud.network.vpc; + import java.util.List; import java.util.Map; diff --git a/api/src/com/cloud/network/vpn/RemoteAccessVpnService.java b/api/src/com/cloud/network/vpn/RemoteAccessVpnService.java index acf007bbb3..decf8c4373 100644 --- a/api/src/com/cloud/network/vpn/RemoteAccessVpnService.java +++ b/api/src/com/cloud/network/vpn/RemoteAccessVpnService.java @@ -33,7 +33,7 @@ public interface RemoteAccessVpnService { RemoteAccessVpn createRemoteAccessVpn(long vpnServerAddressId, String ipRange, boolean openFirewall, Boolean forDisplay) throws NetworkRuleConflictException; - void destroyRemoteAccessVpnForIp(long vpnServerAddressId, Account caller) throws ResourceUnavailableException; + boolean destroyRemoteAccessVpnForIp(long ipId, Account caller) throws ResourceUnavailableException; RemoteAccessVpn startRemoteAccessVpn(long vpnServerAddressId, boolean openFirewall) throws ResourceUnavailableException; diff --git a/api/src/com/cloud/offering/NetworkOffering.java b/api/src/com/cloud/offering/NetworkOffering.java index b4f3863293..f1ef69c2f6 100644 --- a/api/src/com/cloud/offering/NetworkOffering.java +++ b/api/src/com/cloud/offering/NetworkOffering.java @@ -129,4 +129,6 @@ public enum Detail { Integer getConcurrentConnections(); boolean isKeepAliveEnabled(); + + boolean getSupportsStrechedL2(); } diff --git a/api/src/com/cloud/server/ResourceTag.java b/api/src/com/cloud/server/ResourceTag.java index 275510e1a1..d91bb7d519 100644 --- a/api/src/com/cloud/server/ResourceTag.java +++ b/api/src/com/cloud/server/ResourceTag.java @@ -53,7 +53,10 @@ public enum ResourceObjectType { User(true, true), DiskOffering(false, true), AutoScaleVmProfile(false, true), - AutoScaleVmGroup(false, true); + AutoScaleVmGroup(false, true), + LBStickinessPolicy(false, true), + LBHealthCheckPolicy(false, true); + ResourceObjectType(boolean resourceTagsSupport, boolean resourceMetadataSupport) { this.resourceTagsSupport = resourceTagsSupport; diff --git a/api/src/com/cloud/storage/GuestOS.java b/api/src/com/cloud/storage/GuestOS.java index 767a60ecf9..371260bec6 100644 --- a/api/src/com/cloud/storage/GuestOS.java +++ b/api/src/com/cloud/storage/GuestOS.java @@ -32,4 +32,6 @@ public interface GuestOS extends InternalIdentity, Identity { Date getCreated(); Date getRemoved(); + + boolean getIsUserDefined(); } diff --git a/api/src/com/cloud/storage/GuestOSHypervisor.java b/api/src/com/cloud/storage/GuestOSHypervisor.java index 1cfc3a1728..f579ce343a 100644 --- a/api/src/com/cloud/storage/GuestOSHypervisor.java +++ b/api/src/com/cloud/storage/GuestOSHypervisor.java @@ -35,4 +35,6 @@ public interface GuestOSHypervisor extends InternalIdentity { Date getRemoved(); Date getCreated(); + + boolean getIsUserDefined(); } diff --git a/api/src/com/cloud/storage/StoragePool.java b/api/src/com/cloud/storage/StoragePool.java index 6ede960c1f..8e03c3348f 100644 --- a/api/src/com/cloud/storage/StoragePool.java +++ b/api/src/com/cloud/storage/StoragePool.java @@ -21,6 +21,7 @@ import org.apache.cloudstack.api.Identity; import org.apache.cloudstack.api.InternalIdentity; +import com.cloud.hypervisor.Hypervisor; import com.cloud.storage.Storage.StoragePoolType; public interface StoragePool extends Identity, InternalIdentity { @@ -98,10 +99,9 @@ public interface StoragePool extends Identity, InternalIdentity { Long getPodId(); - /** - * @return - */ String getStorageProviderName(); boolean isInMaintenance(); + + Hypervisor.HypervisorType getHypervisor(); } diff --git a/api/src/com/cloud/storage/Volume.java b/api/src/com/cloud/storage/Volume.java index 304dbcfe34..a78049b5c9 100755 --- a/api/src/com/cloud/storage/Volume.java +++ b/api/src/com/cloud/storage/Volume.java @@ -19,6 +19,7 @@ import java.util.Date; import org.apache.cloudstack.acl.ControlledEntity; +import org.apache.cloudstack.api.Displayable; import org.apache.cloudstack.api.Identity; import org.apache.cloudstack.api.InternalIdentity; @@ -26,7 +27,7 @@ import com.cloud.utils.fsm.StateMachine2; import com.cloud.utils.fsm.StateObject; -public interface Volume extends ControlledEntity, Identity, InternalIdentity, BasedOn, StateObject { +public interface Volume extends ControlledEntity, Identity, InternalIdentity, BasedOn, StateObject, Displayable { enum Type { UNKNOWN, ROOT, SWAP, DATADISK, ISO }; @@ -191,5 +192,8 @@ enum Event { Integer getHypervisorSnapshotReserve(); + @Deprecated boolean isDisplayVolume(); + + boolean isDisplay(); } diff --git a/api/src/com/cloud/storage/VolumeApiService.java b/api/src/com/cloud/storage/VolumeApiService.java index beaa29096e..5487a4bf9b 100644 --- a/api/src/com/cloud/storage/VolumeApiService.java +++ b/api/src/com/cloud/storage/VolumeApiService.java @@ -96,4 +96,6 @@ public interface VolumeApiService { String extractVolume(ExtractVolumeCmd cmd); boolean isDisplayResourceEnabled(Long id); + + void updateDisplay(Volume volume, Boolean displayVolume); } diff --git a/api/src/com/cloud/user/AccountService.java b/api/src/com/cloud/user/AccountService.java index 7e37b386b9..6cc86cda3f 100755 --- a/api/src/com/cloud/user/AccountService.java +++ b/api/src/com/cloud/user/AccountService.java @@ -24,7 +24,6 @@ import org.apache.cloudstack.api.command.admin.user.RegisterCmd; import com.cloud.domain.Domain; -import com.cloud.domain.PartOf; import com.cloud.exception.PermissionDeniedException; public interface AccountService { @@ -74,7 +73,7 @@ UserAccount createUserAccount(String userName, String password, String firstName User createUser(String userName, String password, String firstName, String lastName, String email, String timeZone, String accountName, Long domainId, String userUUID); - boolean isAdmin(short accountType); + boolean isAdmin(Long accountId); Account finalizeOwner(Account caller, String accountName, Long domainId, Long projectId); @@ -104,15 +103,19 @@ UserAccount createUserAccount(String userName, String password, String firstName RoleType getRoleType(Account account); - void checkAccess(Account account, Domain domain) throws PermissionDeniedException; + void checkAccess(Account caller, Domain domain) throws PermissionDeniedException; - void checkAccess(Account account, AccessType accessType, boolean sameOwner, ControlledEntity... entities) throws PermissionDeniedException; + void checkAccess(Account caller, AccessType accessType, ControlledEntity... entities) throws PermissionDeniedException; - void checkAccess(Account account, AccessType accessType, boolean sameOwner, String apiName, - ControlledEntity... entities) throws PermissionDeniedException; - - //TO be implemented, to check accessibility for an entity owned by domain - void checkAccess(Account account, AccessType accessType, boolean sameOwner, PartOf... entities) throws PermissionDeniedException; + void checkAccess(Account caller, AccessType accessType, String apiName, ControlledEntity... entities) throws PermissionDeniedException; Long finalyzeAccountId(String accountName, Long domainId, Long projectId, boolean enabledOnly); + + /** + * returns the user account object for a given user id + * @param userId user id + * @return useraccount object if it exists else null + */ + UserAccount getUserAccountById(Long userId); + } diff --git a/api/src/com/cloud/vm/UserVmService.java b/api/src/com/cloud/vm/UserVmService.java index af4e1d3699..c0c0335675 100755 --- a/api/src/com/cloud/vm/UserVmService.java +++ b/api/src/com/cloud/vm/UserVmService.java @@ -21,7 +21,6 @@ import org.apache.cloudstack.api.BaseCmd.HTTPMethod; import org.apache.cloudstack.api.command.admin.vm.AssignVMCmd; -import org.apache.cloudstack.api.command.admin.vm.ExpungeVMCmd; import org.apache.cloudstack.api.command.admin.vm.RecoverVMCmd; import org.apache.cloudstack.api.command.user.vm.AddNicToVMCmd; import org.apache.cloudstack.api.command.user.vm.DeployVMCmd; @@ -457,8 +456,6 @@ UserVm moveVMToUser(AssignVMCmd moveUserVMCmd) throws ResourceAllocationExceptio UserVm upgradeVirtualMachine(ScaleVMCmd cmd) throws ResourceUnavailableException, ConcurrentOperationException, ManagementServerException, VirtualMachineMigrationException; - UserVm expungeVm(ExpungeVMCmd cmd) throws ResourceUnavailableException, ConcurrentOperationException; - UserVm expungeVm(long vmId) throws ResourceUnavailableException, ConcurrentOperationException; /** diff --git a/api/src/com/cloud/vm/VirtualMachine.java b/api/src/com/cloud/vm/VirtualMachine.java index b085d4a7c4..34387ebea8 100755 --- a/api/src/com/cloud/vm/VirtualMachine.java +++ b/api/src/com/cloud/vm/VirtualMachine.java @@ -20,6 +20,7 @@ import java.util.Map; import org.apache.cloudstack.acl.ControlledEntity; +import org.apache.cloudstack.api.Displayable; import org.apache.cloudstack.api.Identity; import org.apache.cloudstack.api.InternalIdentity; @@ -31,7 +32,7 @@ * VirtualMachine describes the properties held by a virtual machine * */ -public interface VirtualMachine extends RunningOn, ControlledEntity, Identity, InternalIdentity, StateObject { +public interface VirtualMachine extends RunningOn, ControlledEntity, Identity, InternalIdentity, Displayable, StateObject { public enum PowerState { PowerUnknown, @@ -102,6 +103,7 @@ public static StateMachine2 getStat s_fsm.addTransition(State.Running, VirtualMachine.Event.StopRequested, State.Stopping); s_fsm.addTransition(State.Running, VirtualMachine.Event.AgentReportShutdowned, State.Stopped); s_fsm.addTransition(State.Running, VirtualMachine.Event.AgentReportMigrated, State.Running); + s_fsm.addTransition(State.Running, VirtualMachine.Event.OperationSucceeded, State.Running); s_fsm.addTransition(State.Migrating, VirtualMachine.Event.MigrationRequested, State.Migrating); s_fsm.addTransition(State.Migrating, VirtualMachine.Event.OperationSucceeded, State.Running); s_fsm.addTransition(State.Migrating, VirtualMachine.Event.OperationFailed, State.Running); @@ -320,4 +322,7 @@ public boolean isUsedBySystem() { long getUpdated(); + @Override + boolean isDisplay(); + } diff --git a/api/src/com/cloud/vm/VirtualMachineName.java b/api/src/com/cloud/vm/VirtualMachineName.java index 4bbcb64ebc..e6c2fbaab1 100755 --- a/api/src/com/cloud/vm/VirtualMachineName.java +++ b/api/src/com/cloud/vm/VirtualMachineName.java @@ -18,8 +18,6 @@ import java.util.Formatter; -import com.cloud.dc.Vlan; - /** * VM Name. */ @@ -52,26 +50,16 @@ public static boolean isValidVmName(String vmName) { public static boolean isValidVmName(String vmName, String instance) { String[] tokens = vmName.split(SEPARATOR); - /*Some vms doesn't have vlan/vnet id*/ - if (tokens.length != 5 && tokens.length != 4) { - return false; - } - if (!tokens[0].equals("i")) { + if (tokens.length <= 1) { return false; } - try { - Long.parseLong(tokens[1]); - Long.parseLong(tokens[2]); - if (tokens.length == 5 && !Vlan.UNTAGGED.equalsIgnoreCase(tokens[4])) { - Long.parseLong(tokens[4], 16); - } - } catch (NumberFormatException e) { + if (!tokens[0].equals("i")) { return false; } - return instance == null || instance.equals(tokens[3]); + return true; } public static String getVmName(long vmId, long userId, String instance) { diff --git a/api/src/com/cloud/vm/VirtualMachineProfile.java b/api/src/com/cloud/vm/VirtualMachineProfile.java index c098e85db5..29f3164632 100644 --- a/api/src/com/cloud/vm/VirtualMachineProfile.java +++ b/api/src/com/cloud/vm/VirtualMachineProfile.java @@ -53,6 +53,23 @@ public Param(String name) { public String getName() { return name; } + + @Override + public int hashCode() { + return this.getName() != null ? this.getName().hashCode() : 0; + } + + @Override + public boolean equals(Object obj) { + if (this == obj) + return true; + if (obj == null) + return false; + if (getClass() != obj.getClass()) + return false; + Param other = (Param) obj; + return (other.getName().equals(this.getName())); + } } String getHostName(); diff --git a/api/src/org/apache/cloudstack/acl/ControlledEntity.java b/api/src/org/apache/cloudstack/acl/ControlledEntity.java index 2572705daa..b8a244f3bd 100644 --- a/api/src/org/apache/cloudstack/acl/ControlledEntity.java +++ b/api/src/org/apache/cloudstack/acl/ControlledEntity.java @@ -29,5 +29,5 @@ public enum ACLType { Account, Domain } - IAMEntityType getEntityType(); + Class getEntityType(); } diff --git a/api/src/org/apache/cloudstack/acl/IAMEntityType.java b/api/src/org/apache/cloudstack/acl/IAMEntityType.java deleted file mode 100644 index c1703ea5c3..0000000000 --- a/api/src/org/apache/cloudstack/acl/IAMEntityType.java +++ /dev/null @@ -1,61 +0,0 @@ -// Licensed to the Apache Software Foundation (ASF) under one -// or more contributor license agreements. See the NOTICE file -// distributed with this work for additional information -// regarding copyright ownership. The ASF licenses this file -// to you under the Apache License, Version 2.0 (the -// "License"); you may not use this file except in compliance -// with the License. You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, -// software distributed under the License is distributed on an -// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY -// KIND, either express or implied. See the License for the -// specific language governing permissions and limitations -// under the License. -package org.apache.cloudstack.acl; - -public enum IAMEntityType { - // currently supported entity, to be added one by one after we support acl on the entity - VirtualMachine, - Volume, - ResourceTag, - Account, - AffinityGroup, - AutoScalePolicy, - AutoScaleVmGroup, - AutoScaleVmProfile, - Condition, - Vpc, - VpcGateway, - PrivateGateway, - VpnUser, - VMSnapshot, - VirtualMachineTemplate, - UserIpv6Address, - StaticRoute, - SSHKeyPair, - Snapshot, - Site2SiteVpnGateway, - Site2SiteVpnConnection, - Site2SiteCustomerGateway, - SecurityGroup, - RemoteAccessVpn, - PublicIpAddress, - ProjectInvitation, - NicSecondaryIp, - NicIpAlias, - Network, - IpAddress, - InstanceGroup, - GlobalLoadBalancerRule, - FirewallRule, - PortForwardingRule, - Event, - AsyncJob, - IAMPolicy, - IAMGroup, - MonitorService, - SSLCert -} diff --git a/api/src/org/apache/cloudstack/acl/QuerySelector.java b/api/src/org/apache/cloudstack/acl/QuerySelector.java index b89aa4e9ef..229ce9866f 100644 --- a/api/src/org/apache/cloudstack/acl/QuerySelector.java +++ b/api/src/org/apache/cloudstack/acl/QuerySelector.java @@ -18,6 +18,8 @@ import java.util.List; +import org.apache.cloudstack.acl.SecurityChecker.AccessType; + import com.cloud.user.Account; import com.cloud.utils.component.Adapter; @@ -33,7 +35,7 @@ public interface QuerySelector extends Adapter { * @param action action * @return list of domain Ids granted to the caller account. */ - List getAuthorizedDomains(Account caller, String action); + List getAuthorizedDomains(Account caller, String action, AccessType accessType); /** * List granted accounts for the caller, given a specific action. @@ -42,7 +44,7 @@ public interface QuerySelector extends Adapter { * @param action action. * @return list of domain Ids granted to the caller account. */ - List getAuthorizedAccounts(Account caller, String action); + List getAuthorizedAccounts(Account caller, String action, AccessType accessType); /** @@ -52,7 +54,7 @@ public interface QuerySelector extends Adapter { * @param action action. * @return list of domain Ids granted to the caller account. */ - List getAuthorizedResources(Account caller, String action); + List getAuthorizedResources(Account caller, String action, AccessType accessType); /** * Check if this account is associated with a policy with scope of ALL @@ -60,7 +62,7 @@ public interface QuerySelector extends Adapter { * @param action action. * @return true if this account is attached with a policy for the given action of ALL scope. */ - boolean isGrantedAll(Account caller, String action); + boolean isGrantedAll(Account caller, String action, AccessType accessType); /** * List of ACL group the given account belongs to diff --git a/api/src/org/apache/cloudstack/acl/SecurityChecker.java b/api/src/org/apache/cloudstack/acl/SecurityChecker.java index 614f604aec..79366bdc97 100644 --- a/api/src/org/apache/cloudstack/acl/SecurityChecker.java +++ b/api/src/org/apache/cloudstack/acl/SecurityChecker.java @@ -31,9 +31,10 @@ public interface SecurityChecker extends Adapter { public enum AccessType { - ModifyProject, + ListEntry, + UseEntry, OperateEntry, - UseEntry + ModifyProject, } /** @@ -99,6 +100,26 @@ boolean checkAccess(Account caller, ControlledEntity entity, AccessType accessTy */ boolean checkAccess(Account caller, ControlledEntity entity, AccessType accessType, String action) throws PermissionDeniedException; + /** + * Checks if the account can access multiple objects. + * + * @param caller + * account to check against. + * @param entities + * objects that the account is trying to access. + * @param accessType + * TODO + * @param action + * name of the API + * @return true if access allowed. false if this adapter cannot provide + * permission. + * @throws PermissionDeniedException + * if this adapter is suppose to authenticate ownership and the + * check failed. + */ + boolean checkAccess(Account caller, AccessType accessType, String action, ControlledEntity... entities) + throws PermissionDeniedException; + /** * Checks if the user belongs to an account that can access the object. diff --git a/api/src/org/apache/cloudstack/api/APICommand.java b/api/src/org/apache/cloudstack/api/APICommand.java index 9b4dfafdb6..d451e4b10a 100644 --- a/api/src/org/apache/cloudstack/api/APICommand.java +++ b/api/src/org/apache/cloudstack/api/APICommand.java @@ -22,7 +22,6 @@ import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; -import org.apache.cloudstack.acl.IAMEntityType; import org.apache.cloudstack.acl.RoleType; import org.apache.cloudstack.api.ResponseObject.ResponseView; @@ -49,5 +48,5 @@ RoleType[] authorized() default {}; - IAMEntityType[] entityType() default {}; + Class[] entityType() default {}; } diff --git a/api/src/org/apache/cloudstack/api/ApiConstants.java b/api/src/org/apache/cloudstack/api/ApiConstants.java index 32107edf84..850e67e64b 100755 --- a/api/src/org/apache/cloudstack/api/ApiConstants.java +++ b/api/src/org/apache/cloudstack/api/ApiConstants.java @@ -26,6 +26,7 @@ public class ApiConstants { public static final String API_KEY = "apikey"; public static final String USER_API_KEY = "userapikey"; public static final String APPLIED = "applied"; + public static final String LIST_LB_VMIPS = "lbvmips"; public static final String AVAILABLE = "available"; public static final String BITS = "bits"; public static final String BOOTABLE = "bootable"; @@ -262,6 +263,8 @@ public class ApiConstants { public static final String VALUE = "value"; public static final String VIRTUAL_MACHINE_ID = "virtualmachineid"; public static final String VIRTUAL_MACHINE_IDS = "virtualmachineids"; + public static final String VIRTUAL_MACHINE_ID_IP = "vmidipmap"; + public static final String VLAN = "vlan"; public static final String VLAN_RANGE = "vlanrange"; public static final String REMOVE_VLAN = "removevlan"; @@ -287,6 +290,7 @@ public class ApiConstants { public static final String SPECIFY_VLAN = "specifyvlan"; public static final String IS_DEFAULT = "isdefault"; public static final String IS_SYSTEM = "issystem"; + public static final String IS_USER_DEFINED = "isuserdefined"; public static final String AVAILABILITY = "availability"; public static final String NETWORKRATE = "networkrate"; public static final String HOST_TAGS = "hosttags"; @@ -417,6 +421,7 @@ public class ApiConstants { public static final String INSTANCE_NAME = "instancename"; public static final String START_VM = "startvm"; public static final String HA_HOST = "hahost"; + public static final String CUSTOM_DISK_OFF_MIN_SIZE = "customdiskofferingminsize"; public static final String CUSTOM_DISK_OFF_MAX_SIZE = "customdiskofferingmaxsize"; public static final String DEFAULT_ZONE_ID = "defaultzoneid"; public static final String LIVE_MIGRATE = "livemigrate"; @@ -587,9 +592,20 @@ public class ApiConstants { public static final String GPUGROUPNAME = "gpugroupname"; public static final String VGPU = "vgpu"; public static final String VGPUTYPE = "vgputype"; + public static final String VIDEORAM = "videoram"; + public static final String MAXHEADS = "maxheads"; + public static final String MAXRESOLUTIONX = "maxresolutionx"; + public static final String MAXRESOLUTIONY = "maxresolutiony"; + public static final String MAXVGPUPERPGPU = "maxvgpuperpgpu"; public static final String REMAININGCAPACITY = "remainingcapacity"; + public static final String MAXCAPACITY = "maxcapacity"; public static final String DISTRIBUTED_VPC_ROUTER = "distributedvpcrouter"; - + public static final String SUPPORTS_REGION_LEVEL_VPC = "supportsregionLevelvpc"; + public static final String SUPPORTS_STRECHED_L2_SUBNET = "supportsstrechedl2subnet"; + public static final String REGION_LEVEL_VPC = "regionlevelvpc"; + public static final String READ_ONLY = "readonly"; + public static final String STRECHED_L2_SUBNET = "strechedl2subnet"; + public static final String NETWORK_SPANNED_ZONES = "zonesnetworkspans"; public enum HostDetails { all, capacity, events, stats, min; diff --git a/api/src/org/apache/cloudstack/api/BaseAsyncCmd.java b/api/src/org/apache/cloudstack/api/BaseAsyncCmd.java index 0b1396fbf8..6b83d39dc9 100644 --- a/api/src/org/apache/cloudstack/api/BaseAsyncCmd.java +++ b/api/src/org/apache/cloudstack/api/BaseAsyncCmd.java @@ -17,6 +17,8 @@ package org.apache.cloudstack.api; +import org.apache.log4j.Logger; + /** * queryAsyncJobResult API command. */ @@ -27,6 +29,7 @@ public abstract class BaseAsyncCmd extends BaseCmd { public static final String vpcSyncObject = "vpc"; public static final String snapshotHostSyncObject = "snapshothost"; public static final String gslbSyncObject = "globalserverloadbalacner"; + private static final Logger s_logger = Logger.getLogger(BaseAsyncCmd.class.getName()); private Object job; @@ -89,4 +92,5 @@ public Long getSyncObjId() { public Object getJob() { return job; } + } diff --git a/api/src/org/apache/cloudstack/api/BaseCmd.java b/api/src/org/apache/cloudstack/api/BaseCmd.java index f6f21ae716..ed7e983981 100644 --- a/api/src/org/apache/cloudstack/api/BaseCmd.java +++ b/api/src/org/apache/cloudstack/api/BaseCmd.java @@ -360,7 +360,45 @@ public void validateSpecificParameters(final Map params){ * display flag is used to control the display of the resource only to the end user. It doesnt affect Root Admin. * @return display flag */ - public boolean isDisplayResourceEnabled(){ - return true; + public boolean isDisplay(){ + CallContext context = CallContext.current(); + Map contextMap = context.getContextParameters(); + boolean isDisplay = true; + + // Iterate over all the first class entities in context and check their display property. + for(Map.Entry entry : contextMap.entrySet()){ + try{ + Object key = entry.getKey(); + Class clz = Class.forName((String)key); + if(Displayable.class.isAssignableFrom(clz)){ + final Object objVO = _entityMgr.findById(clz, getInternalId(entry.getValue())); + isDisplay = ((Displayable) objVO).isDisplay(); + } + + // If the flag is false break immediately + if(!isDisplay) + break; + } catch (Exception e){ + s_logger.trace("Caught exception while checking first class entities for display property, continuing on", e); + } + } + + context.setEventDisplayEnabled(isDisplay); + return isDisplay; + } + + private static Long getInternalId(Object internalIdObj){ + Long internalId = null; + + // In case its an async job the value would be a string because of json deserialization + if(internalIdObj instanceof String){ + internalId = Long.valueOf((String) internalIdObj); + }else if (internalIdObj instanceof Long){ + internalId = (Long) internalIdObj; + } + + return internalId; + } + } diff --git a/api/src/org/apache/cloudstack/api/BaseListAccountResourcesCmd.java b/api/src/org/apache/cloudstack/api/BaseListAccountResourcesCmd.java index 63d2b7f761..d494f6403f 100644 --- a/api/src/org/apache/cloudstack/api/BaseListAccountResourcesCmd.java +++ b/api/src/org/apache/cloudstack/api/BaseListAccountResourcesCmd.java @@ -16,9 +16,6 @@ // under the License. package org.apache.cloudstack.api; -import org.apache.cloudstack.context.CallContext; - -import com.cloud.user.Account; public abstract class BaseListAccountResourcesCmd extends BaseListDomainResourcesCmd { @@ -30,10 +27,6 @@ public String getAccountName() { } public Boolean getDisplay() { - Account caller = CallContext.current().getCallingAccount(); - if (caller.getType() == Account.ACCOUNT_TYPE_NORMAL) { - return true; - } - return null; + return true; } } diff --git a/api/src/org/apache/cloudstack/api/BaseAsyncVMCmd.java b/api/src/org/apache/cloudstack/api/Displayable.java similarity index 72% rename from api/src/org/apache/cloudstack/api/BaseAsyncVMCmd.java rename to api/src/org/apache/cloudstack/api/Displayable.java index abfc953027..2a83c8dc73 100644 --- a/api/src/org/apache/cloudstack/api/BaseAsyncVMCmd.java +++ b/api/src/org/apache/cloudstack/api/Displayable.java @@ -16,15 +16,6 @@ // under the License. package org.apache.cloudstack.api; -/** - * A generic class for implementing methods common to all async vm commands - */ -public abstract class BaseAsyncVMCmd extends BaseAsyncCmd { - - @Override - public boolean isDisplayResourceEnabled(){ - return _userVmService.isDisplayResourceEnabled(getId()); - } - - public abstract Long getId(); +public interface Displayable { + boolean isDisplay(); } diff --git a/api/src/org/apache/cloudstack/api/command/admin/account/CreateAccountCmd.java b/api/src/org/apache/cloudstack/api/command/admin/account/CreateAccountCmd.java index 0c46d501bd..50d67d993d 100644 --- a/api/src/org/apache/cloudstack/api/command/admin/account/CreateAccountCmd.java +++ b/api/src/org/apache/cloudstack/api/command/admin/account/CreateAccountCmd.java @@ -21,7 +21,6 @@ import org.apache.log4j.Logger; -import org.apache.cloudstack.acl.IAMEntityType; import org.apache.cloudstack.api.APICommand; import org.apache.cloudstack.api.ApiConstants; import org.apache.cloudstack.api.ApiErrorCode; @@ -37,7 +36,7 @@ import com.cloud.user.UserAccount; -@APICommand(name = "createAccount", description = "Creates an account", responseObject = AccountResponse.class, entityType = {IAMEntityType.Account}, +@APICommand(name = "createAccount", description = "Creates an account", responseObject = AccountResponse.class, entityType = {Account.class}, requestHasSensitiveInfo = true, responseHasSensitiveInfo = true) public class CreateAccountCmd extends BaseCmd { public static final Logger s_logger = Logger.getLogger(CreateAccountCmd.class.getName()); diff --git a/api/src/org/apache/cloudstack/api/command/admin/account/DeleteAccountCmd.java b/api/src/org/apache/cloudstack/api/command/admin/account/DeleteAccountCmd.java index 8cc87c2884..5754ec5010 100644 --- a/api/src/org/apache/cloudstack/api/command/admin/account/DeleteAccountCmd.java +++ b/api/src/org/apache/cloudstack/api/command/admin/account/DeleteAccountCmd.java @@ -20,7 +20,6 @@ import org.apache.log4j.Logger; -import org.apache.cloudstack.acl.IAMEntityType; import org.apache.cloudstack.acl.SecurityChecker.AccessType; import org.apache.cloudstack.api.ACL; import org.apache.cloudstack.api.APICommand; @@ -39,7 +38,7 @@ import com.cloud.user.Account; import com.cloud.user.User; -@APICommand(name = "deleteAccount", description = "Deletes a account, and all users associated with this account", responseObject = SuccessResponse.class, entityType = {IAMEntityType.Account}, +@APICommand(name = "deleteAccount", description = "Deletes a account, and all users associated with this account", responseObject = SuccessResponse.class, entityType = {Account.class}, requestHasSensitiveInfo = false, responseHasSensitiveInfo = false) public class DeleteAccountCmd extends BaseAsyncCmd { public static final Logger s_logger = Logger.getLogger(DeleteAccountCmd.class.getName()); diff --git a/api/src/org/apache/cloudstack/api/command/admin/account/DisableAccountCmd.java b/api/src/org/apache/cloudstack/api/command/admin/account/DisableAccountCmd.java index 1e810091ee..3e5e1d3d01 100644 --- a/api/src/org/apache/cloudstack/api/command/admin/account/DisableAccountCmd.java +++ b/api/src/org/apache/cloudstack/api/command/admin/account/DisableAccountCmd.java @@ -20,7 +20,6 @@ import org.apache.log4j.Logger; -import org.apache.cloudstack.acl.IAMEntityType; import org.apache.cloudstack.acl.SecurityChecker.AccessType; import org.apache.cloudstack.api.ACL; import org.apache.cloudstack.api.APICommand; @@ -41,7 +40,7 @@ import com.cloud.exception.ResourceUnavailableException; import com.cloud.user.Account; -@APICommand(name = "disableAccount", description = "Disables an account", responseObject = AccountResponse.class, entityType = {IAMEntityType.Account}, +@APICommand(name = "disableAccount", description = "Disables an account", responseObject = AccountResponse.class, entityType = {Account.class}, requestHasSensitiveInfo = false, responseHasSensitiveInfo = true) public class DisableAccountCmd extends BaseAsyncCmd { public static final Logger s_logger = Logger.getLogger(DisableAccountCmd.class.getName()); diff --git a/api/src/org/apache/cloudstack/api/command/admin/account/EnableAccountCmd.java b/api/src/org/apache/cloudstack/api/command/admin/account/EnableAccountCmd.java index 1bfd71c804..f30c985c96 100644 --- a/api/src/org/apache/cloudstack/api/command/admin/account/EnableAccountCmd.java +++ b/api/src/org/apache/cloudstack/api/command/admin/account/EnableAccountCmd.java @@ -20,7 +20,6 @@ import org.apache.log4j.Logger; -import org.apache.cloudstack.acl.IAMEntityType; import org.apache.cloudstack.acl.SecurityChecker.AccessType; import org.apache.cloudstack.api.ACL; import org.apache.cloudstack.api.APICommand; @@ -36,7 +35,7 @@ import com.cloud.user.Account; -@APICommand(name = "enableAccount", description = "Enables an account", responseObject = AccountResponse.class, entityType = {IAMEntityType.Account}, +@APICommand(name = "enableAccount", description = "Enables an account", responseObject = AccountResponse.class, entityType = {Account.class}, requestHasSensitiveInfo = false, responseHasSensitiveInfo = true) public class EnableAccountCmd extends BaseCmd { public static final Logger s_logger = Logger.getLogger(EnableAccountCmd.class.getName()); diff --git a/api/src/org/apache/cloudstack/api/command/admin/account/LockAccountCmd.java b/api/src/org/apache/cloudstack/api/command/admin/account/LockAccountCmd.java index 780dac1d7a..3c185e41bd 100644 --- a/api/src/org/apache/cloudstack/api/command/admin/account/LockAccountCmd.java +++ b/api/src/org/apache/cloudstack/api/command/admin/account/LockAccountCmd.java @@ -18,7 +18,6 @@ import org.apache.log4j.Logger; -import org.apache.cloudstack.acl.IAMEntityType; import org.apache.cloudstack.api.APICommand; import org.apache.cloudstack.api.ApiConstants; import org.apache.cloudstack.api.BaseCmd; @@ -28,7 +27,7 @@ import com.cloud.user.Account; -@APICommand(name = "lockAccount", description = "Locks an account", responseObject = AccountResponse.class, entityType = {IAMEntityType.Account}, +@APICommand(name = "lockAccount", description = "Locks an account", responseObject = AccountResponse.class, entityType = {Account.class}, requestHasSensitiveInfo = false, responseHasSensitiveInfo = true) public class LockAccountCmd extends BaseCmd { public static final Logger s_logger = Logger.getLogger(LockAccountCmd.class.getName()); diff --git a/api/src/org/apache/cloudstack/api/command/admin/account/UpdateAccountCmd.java b/api/src/org/apache/cloudstack/api/command/admin/account/UpdateAccountCmd.java index 8d9fe261f9..a7ce74a129 100644 --- a/api/src/org/apache/cloudstack/api/command/admin/account/UpdateAccountCmd.java +++ b/api/src/org/apache/cloudstack/api/command/admin/account/UpdateAccountCmd.java @@ -23,7 +23,6 @@ import org.apache.log4j.Logger; -import org.apache.cloudstack.acl.IAMEntityType; import org.apache.cloudstack.acl.SecurityChecker.AccessType; import org.apache.cloudstack.api.ACL; import org.apache.cloudstack.api.APICommand; @@ -39,7 +38,7 @@ import com.cloud.user.Account; -@APICommand(name = "updateAccount", description = "Updates account information for the authenticated user", responseObject = AccountResponse.class, entityType = {IAMEntityType.Account}, +@APICommand(name = "updateAccount", description = "Updates account information for the authenticated user", responseObject = AccountResponse.class, entityType = {Account.class}, requestHasSensitiveInfo = false, responseHasSensitiveInfo = true) public class UpdateAccountCmd extends BaseCmd { public static final Logger s_logger = Logger.getLogger(UpdateAccountCmd.class.getName()); diff --git a/api/src/org/apache/cloudstack/api/command/admin/address/AssociateIPAddrCmdByAdmin.java b/api/src/org/apache/cloudstack/api/command/admin/address/AssociateIPAddrCmdByAdmin.java index dbff93f222..494a6d66e4 100644 --- a/api/src/org/apache/cloudstack/api/command/admin/address/AssociateIPAddrCmdByAdmin.java +++ b/api/src/org/apache/cloudstack/api/command/admin/address/AssociateIPAddrCmdByAdmin.java @@ -31,8 +31,11 @@ import com.cloud.exception.ResourceAllocationException; import com.cloud.exception.ResourceUnavailableException; import com.cloud.network.IpAddress; +import com.cloud.network.vpc.Vpc; -@APICommand(name = "associateIpAddress", description = "Acquires and associates a public IP to an account.", responseObject = IPAddressResponse.class, responseView = ResponseView.Full) +@APICommand(name = "associateIpAddress", description = "Acquires and associates a public IP to an account.", responseObject = IPAddressResponse.class, responseView = ResponseView.Full, + entityType = {IpAddress.class, Vpc.class}, + requestHasSensitiveInfo = false, responseHasSensitiveInfo = false) public class AssociateIPAddrCmdByAdmin extends AssociateIPAddrCmd { public static final Logger s_logger = Logger.getLogger(AssociateIPAddrCmdByAdmin.class.getName()); diff --git a/api/src/org/apache/cloudstack/api/command/admin/internallb/ListInternalLBVMsCmd.java b/api/src/org/apache/cloudstack/api/command/admin/internallb/ListInternalLBVMsCmd.java index e6ea519778..0b59b73f9d 100644 --- a/api/src/org/apache/cloudstack/api/command/admin/internallb/ListInternalLBVMsCmd.java +++ b/api/src/org/apache/cloudstack/api/command/admin/internallb/ListInternalLBVMsCmd.java @@ -18,7 +18,6 @@ import org.apache.log4j.Logger; -import org.apache.cloudstack.acl.IAMEntityType; import org.apache.cloudstack.api.APICommand; import org.apache.cloudstack.api.ApiCommandJobType; import org.apache.cloudstack.api.ApiConstants; @@ -34,8 +33,9 @@ import org.apache.cloudstack.api.response.ZoneResponse; import com.cloud.network.router.VirtualRouter.Role; +import com.cloud.vm.VirtualMachine; -@APICommand(name = "listInternalLoadBalancerVMs", description = "List internal LB VMs.", responseObject = DomainRouterResponse.class, entityType = {IAMEntityType.VirtualMachine}, +@APICommand(name = "listInternalLoadBalancerVMs", description = "List internal LB VMs.", responseObject = DomainRouterResponse.class, entityType = {VirtualMachine.class}, requestHasSensitiveInfo = false, responseHasSensitiveInfo = false) public class ListInternalLBVMsCmd extends BaseListProjectAndAccountResourcesCmd { public static final Logger s_logger = Logger.getLogger(ListInternalLBVMsCmd.class.getName()); diff --git a/api/src/org/apache/cloudstack/api/command/admin/internallb/ListInternalLoadBalancerElementsCmd.java b/api/src/org/apache/cloudstack/api/command/admin/internallb/ListInternalLoadBalancerElementsCmd.java index 489b64325f..8f62b41969 100644 --- a/api/src/org/apache/cloudstack/api/command/admin/internallb/ListInternalLoadBalancerElementsCmd.java +++ b/api/src/org/apache/cloudstack/api/command/admin/internallb/ListInternalLoadBalancerElementsCmd.java @@ -47,7 +47,7 @@ responseHasSensitiveInfo = false) public class ListInternalLoadBalancerElementsCmd extends BaseListCmd { public static final Logger s_logger = Logger.getLogger(ListInternalLoadBalancerElementsCmd.class.getName()); - private static final String Name = "listinternalloadbalancerelementsresponse"; + private static final String s_name = "listinternalloadbalancerelementsresponse"; @Inject private InternalLoadBalancerElementService _service; @@ -88,7 +88,7 @@ public Boolean getEnabled() { @Override public String getCommandName() { - return Name; + return s_name; } @Override diff --git a/api/src/org/apache/cloudstack/api/command/admin/internallb/StartInternalLBVMCmd.java b/api/src/org/apache/cloudstack/api/command/admin/internallb/StartInternalLBVMCmd.java index 54d7621600..7040e7cf29 100644 --- a/api/src/org/apache/cloudstack/api/command/admin/internallb/StartInternalLBVMCmd.java +++ b/api/src/org/apache/cloudstack/api/command/admin/internallb/StartInternalLBVMCmd.java @@ -18,7 +18,6 @@ import org.apache.log4j.Logger; -import org.apache.cloudstack.acl.IAMEntityType; import org.apache.cloudstack.acl.SecurityChecker.AccessType; import org.apache.cloudstack.api.ACL; import org.apache.cloudstack.api.APICommand; @@ -38,8 +37,9 @@ import com.cloud.exception.ResourceUnavailableException; import com.cloud.network.router.VirtualRouter; import com.cloud.network.router.VirtualRouter.Role; +import com.cloud.vm.VirtualMachine; -@APICommand(name = "startInternalLoadBalancerVM", responseObject = DomainRouterResponse.class, description = "Starts an existing internal lb vm.", entityType = {IAMEntityType.VirtualMachine}, +@APICommand(name = "startInternalLoadBalancerVM", responseObject = DomainRouterResponse.class, description = "Starts an existing internal lb vm.", entityType = {VirtualMachine.class}, requestHasSensitiveInfo = false, responseHasSensitiveInfo = false) public class StartInternalLBVMCmd extends BaseAsyncCmd { public static final Logger s_logger = Logger.getLogger(StartInternalLBVMCmd.class.getName()); diff --git a/api/src/org/apache/cloudstack/api/command/admin/internallb/StopInternalLBVMCmd.java b/api/src/org/apache/cloudstack/api/command/admin/internallb/StopInternalLBVMCmd.java index aa946bee31..51a3d9f8fa 100644 --- a/api/src/org/apache/cloudstack/api/command/admin/internallb/StopInternalLBVMCmd.java +++ b/api/src/org/apache/cloudstack/api/command/admin/internallb/StopInternalLBVMCmd.java @@ -18,7 +18,6 @@ import org.apache.log4j.Logger; -import org.apache.cloudstack.acl.IAMEntityType; import org.apache.cloudstack.acl.SecurityChecker.AccessType; import org.apache.cloudstack.api.ACL; import org.apache.cloudstack.api.APICommand; @@ -37,8 +36,9 @@ import com.cloud.exception.ResourceUnavailableException; import com.cloud.network.router.VirtualRouter; import com.cloud.network.router.VirtualRouter.Role; +import com.cloud.vm.VirtualMachine; -@APICommand(name = "stopInternalLoadBalancerVM", description = "Stops an Internal LB vm.", responseObject = DomainRouterResponse.class, entityType = {IAMEntityType.VirtualMachine}, +@APICommand(name = "stopInternalLoadBalancerVM", description = "Stops an Internal LB vm.", responseObject = DomainRouterResponse.class, entityType = {VirtualMachine.class}, requestHasSensitiveInfo = false, responseHasSensitiveInfo = false) public class StopInternalLBVMCmd extends BaseAsyncCmd { public static final Logger s_logger = Logger.getLogger(StopInternalLBVMCmd.class.getName()); diff --git a/api/src/org/apache/cloudstack/api/command/admin/iso/CopyIsoCmdByAdmin.java b/api/src/org/apache/cloudstack/api/command/admin/iso/CopyIsoCmdByAdmin.java new file mode 100644 index 0000000000..0475b37155 --- /dev/null +++ b/api/src/org/apache/cloudstack/api/command/admin/iso/CopyIsoCmdByAdmin.java @@ -0,0 +1,12 @@ +package org.apache.cloudstack.api.command.admin.iso; + +import org.apache.cloudstack.api.APICommand; +import org.apache.cloudstack.api.ResponseObject.ResponseView; +import org.apache.cloudstack.api.command.user.iso.CopyIsoCmd; +import org.apache.cloudstack.api.response.TemplateResponse; + +@APICommand(name = "copyIso", description = "Copies an iso from one zone to another.", responseObject = TemplateResponse.class, responseView = ResponseView.Full, + requestHasSensitiveInfo = false, responseHasSensitiveInfo = false) +public class CopyIsoCmdByAdmin extends CopyIsoCmd { + +} diff --git a/api/src/org/apache/cloudstack/api/command/admin/loadbalancer/ListLoadBalancerRuleInstancesCmdByAdmin.java b/api/src/org/apache/cloudstack/api/command/admin/loadbalancer/ListLoadBalancerRuleInstancesCmdByAdmin.java index 26202b9bae..6c0d8a4888 100644 --- a/api/src/org/apache/cloudstack/api/command/admin/loadbalancer/ListLoadBalancerRuleInstancesCmdByAdmin.java +++ b/api/src/org/apache/cloudstack/api/command/admin/loadbalancer/ListLoadBalancerRuleInstancesCmdByAdmin.java @@ -19,6 +19,8 @@ import java.util.ArrayList; import java.util.List; +import com.cloud.vm.VirtualMachine; +import org.apache.cloudstack.api.response.LoadBalancerRuleVmMapResponse; import org.apache.log4j.Logger; import org.apache.cloudstack.api.APICommand; @@ -30,7 +32,7 @@ import com.cloud.uservm.UserVm; import com.cloud.utils.Pair; -@APICommand(name = "listLoadBalancerRuleInstances", description = "List all virtual machine instances that are assigned to a load balancer rule.", responseObject = UserVmResponse.class, responseView = ResponseView.Full) +@APICommand(name = "listLoadBalancerRuleInstances", description = "List all virtual machine instances that are assigned to a load balancer rule.", responseObject = LoadBalancerRuleVmMapResponse.class, responseView = ResponseView.Full) public class ListLoadBalancerRuleInstancesCmdByAdmin extends ListLoadBalancerRuleInstancesCmd { public static final Logger s_logger = Logger.getLogger (ListLoadBalancerRuleInstancesCmdByAdmin.class.getName()); @@ -41,17 +43,50 @@ public void execute(){ Pair, List> vmServiceMap = _lbService.listLoadBalancerInstances(this); List result = vmServiceMap.first(); List serviceStates = vmServiceMap.second(); - ListResponse response = new ListResponse(); - List vmResponses = new ArrayList(); - if (result != null) { - vmResponses = _responseGenerator.createUserVmResponse(ResponseView.Full, "loadbalancerruleinstance", result.toArray(new UserVm[result.size()])); - } - for (int i=0;i response = new ListResponse(); + List vmResponses = new ArrayList(); + if (result != null) { + vmResponses = _responseGenerator.createUserVmResponse(ResponseView.Restricted, "loadbalancerruleinstance", result.toArray(new UserVm[result.size()])); + + + for (int i = 0; i < result.size(); i++) { + vmResponses.get(i).setServiceState(serviceStates.get(i)); + } + } + response.setResponses(vmResponses); + response.setResponseName(getCommandName()); + setResponseObject(response); + + } else { + ListResponse lbRes = new ListResponse(); + + List vmResponses = new ArrayList(); + List listlbVmRes = new ArrayList(); + + if (result != null) { + vmResponses = _responseGenerator.createUserVmResponse(ResponseView.Full, "loadbalancerruleinstance", result.toArray(new UserVm[result.size()])); + + List ipaddr = null; + + for (int i=0;i getDetails() { ///////////////////////////////////////////////////// @Override public String getCommandName() { - return Name; + return s_name; } @Override diff --git a/api/src/org/apache/cloudstack/api/command/admin/network/ListSupportedNetworkServicesCmd.java b/api/src/org/apache/cloudstack/api/command/admin/network/ListSupportedNetworkServicesCmd.java index 612c733a34..39e99a43a6 100644 --- a/api/src/org/apache/cloudstack/api/command/admin/network/ListSupportedNetworkServicesCmd.java +++ b/api/src/org/apache/cloudstack/api/command/admin/network/ListSupportedNetworkServicesCmd.java @@ -41,7 +41,7 @@ responseHasSensitiveInfo = false) public class ListSupportedNetworkServicesCmd extends BaseListCmd { public static final Logger s_logger = Logger.getLogger(ListSupportedNetworkServicesCmd.class.getName()); - private static final String Name = "listsupportednetworkservicesresponse"; + private static final String s_name = "listsupportednetworkservicesresponse"; @Parameter(name = ApiConstants.PROVIDER, type = CommandType.STRING, description = "network service provider name") private String providerName; @@ -74,7 +74,7 @@ public String getServiceName() { ///////////////////////////////////////////////////// @Override public String getCommandName() { - return Name; + return s_name; } @Override diff --git a/api/src/org/apache/cloudstack/api/command/admin/network/UpdateNetworkOfferingCmd.java b/api/src/org/apache/cloudstack/api/command/admin/network/UpdateNetworkOfferingCmd.java index f650b4ffb0..411da4fd36 100644 --- a/api/src/org/apache/cloudstack/api/command/admin/network/UpdateNetworkOfferingCmd.java +++ b/api/src/org/apache/cloudstack/api/command/admin/network/UpdateNetworkOfferingCmd.java @@ -33,7 +33,7 @@ requestHasSensitiveInfo = false, responseHasSensitiveInfo = false) public class UpdateNetworkOfferingCmd extends BaseCmd { public static final Logger s_logger = Logger.getLogger(UpdateNetworkOfferingCmd.class.getName()); - private static final String Name = "updatenetworkofferingresponse"; + private static final String s_name = "updatenetworkofferingresponse"; ///////////////////////////////////////////////////// //////////////// API parameters ///////////////////// @@ -110,7 +110,7 @@ public Boolean getKeepAliveEnabled() { ///////////////////////////////////////////////////// @Override public String getCommandName() { - return Name; + return s_name; } @Override 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 78101fb11a..6cd5d84a07 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 @@ -38,7 +38,7 @@ requestHasSensitiveInfo = false, responseHasSensitiveInfo = false) public class CreateServiceOfferingCmd extends BaseCmd { public static final Logger s_logger = Logger.getLogger(CreateServiceOfferingCmd.class.getName()); - private static final String Name = "createserviceofferingresponse"; + private static final String s_name = "createserviceofferingresponse"; ///////////////////////////////////////////////////// //////////////// API parameters ///////////////////// @@ -118,19 +118,20 @@ public class CreateServiceOfferingCmd extends BaseCmd { @Parameter(name = ApiConstants.IOPS_WRITE_RATE, type = CommandType.LONG, required = false, description = "io requests write rate of the disk offering") private Long iopsWriteRate; - @Parameter(name = ApiConstants.CUSTOMIZED_IOPS, type = CommandType.BOOLEAN, required = false, description = "whether compute offering iops is custom or not") + @Parameter(name = ApiConstants.CUSTOMIZED_IOPS, type = CommandType.BOOLEAN, required = false, description = "whether compute offering iops is custom or not", since = "4.4") private Boolean customizedIops; - @Parameter(name = ApiConstants.MIN_IOPS, type = CommandType.LONG, required = false, description = "min iops of the compute offering") + @Parameter(name = ApiConstants.MIN_IOPS, type = CommandType.LONG, required = false, description = "min iops of the compute offering", since = "4.4") private Long minIops; - @Parameter(name = ApiConstants.MAX_IOPS, type = CommandType.LONG, required = false, description = "max iops of the compute offering") + @Parameter(name = ApiConstants.MAX_IOPS, type = CommandType.LONG, required = false, description = "max iops of the compute offering", since = "4.4") private Long maxIops; @Parameter(name = ApiConstants.HYPERVISOR_SNAPSHOT_RESERVE, type = CommandType.INTEGER, required = false, - description = "Hypervisor snapshot reserve space as a percent of a volume (for managed storage using Xen or VMware)") + description = "Hypervisor snapshot reserve space as a percent of a volume (for managed storage using Xen or VMware)", + since = "4.4") private Integer hypervisorSnapshotReserve; ///////////////////////////////////////////////////// @@ -257,7 +258,7 @@ public Integer getHypervisorSnapshotReserve() { @Override public String getCommandName() { - return Name; + return s_name; } @Override diff --git a/api/src/org/apache/cloudstack/api/command/admin/router/DestroyRouterCmd.java b/api/src/org/apache/cloudstack/api/command/admin/router/DestroyRouterCmd.java index 26440d4be9..4513e2e85e 100644 --- a/api/src/org/apache/cloudstack/api/command/admin/router/DestroyRouterCmd.java +++ b/api/src/org/apache/cloudstack/api/command/admin/router/DestroyRouterCmd.java @@ -18,7 +18,6 @@ import org.apache.log4j.Logger; -import org.apache.cloudstack.acl.IAMEntityType; import org.apache.cloudstack.api.APICommand; import org.apache.cloudstack.api.ApiCommandJobType; import org.apache.cloudstack.api.ApiConstants; @@ -34,8 +33,9 @@ import com.cloud.exception.ResourceUnavailableException; import com.cloud.network.router.VirtualRouter; import com.cloud.user.Account; +import com.cloud.vm.VirtualMachine; -@APICommand(name = "destroyRouter", description = "Destroys a router.", responseObject = DomainRouterResponse.class, entityType = {IAMEntityType.VirtualMachine}, +@APICommand(name = "destroyRouter", description = "Destroys a router.", responseObject = DomainRouterResponse.class, entityType = {VirtualMachine.class}, requestHasSensitiveInfo = false, responseHasSensitiveInfo = false) public class DestroyRouterCmd extends BaseAsyncCmd { public static final Logger s_logger = Logger.getLogger(DestroyRouterCmd.class.getName()); diff --git a/api/src/org/apache/cloudstack/api/command/admin/router/ListRoutersCmd.java b/api/src/org/apache/cloudstack/api/command/admin/router/ListRoutersCmd.java index d55a5f3ed9..121fc5bc14 100644 --- a/api/src/org/apache/cloudstack/api/command/admin/router/ListRoutersCmd.java +++ b/api/src/org/apache/cloudstack/api/command/admin/router/ListRoutersCmd.java @@ -18,7 +18,6 @@ import org.apache.log4j.Logger; -import org.apache.cloudstack.acl.IAMEntityType; import org.apache.cloudstack.api.APICommand; import org.apache.cloudstack.api.ApiCommandJobType; import org.apache.cloudstack.api.ApiConstants; @@ -35,8 +34,9 @@ import org.apache.cloudstack.api.response.ZoneResponse; import com.cloud.network.router.VirtualRouter.Role; +import com.cloud.vm.VirtualMachine; -@APICommand(name = "listRouters", description = "List routers.", responseObject = DomainRouterResponse.class, entityType = {IAMEntityType.VirtualMachine}, +@APICommand(name = "listRouters", description = "List routers.", responseObject = DomainRouterResponse.class, entityType = {VirtualMachine.class}, requestHasSensitiveInfo = false, responseHasSensitiveInfo = false) public class ListRoutersCmd extends BaseListProjectAndAccountResourcesCmd { public static final Logger s_logger = Logger.getLogger(ListRoutersCmd.class.getName()); diff --git a/api/src/org/apache/cloudstack/api/command/admin/router/ListVirtualRouterElementsCmd.java b/api/src/org/apache/cloudstack/api/command/admin/router/ListVirtualRouterElementsCmd.java index 62c6da5ee2..24bbf5ae2e 100644 --- a/api/src/org/apache/cloudstack/api/command/admin/router/ListVirtualRouterElementsCmd.java +++ b/api/src/org/apache/cloudstack/api/command/admin/router/ListVirtualRouterElementsCmd.java @@ -44,7 +44,7 @@ requestHasSensitiveInfo = false, responseHasSensitiveInfo = false) public class ListVirtualRouterElementsCmd extends BaseListCmd { public static final Logger s_logger = Logger.getLogger(ListNetworkOfferingsCmd.class.getName()); - private static final String Name = "listvirtualrouterelementsresponse"; + private static final String s_name = "listvirtualrouterelementsresponse"; // TODO, VirtualRouterElementServer is not singleton in system! @Inject @@ -95,7 +95,7 @@ public Boolean getEnabled() { @Override public String getCommandName() { - return Name; + return s_name; } @Override diff --git a/api/src/org/apache/cloudstack/api/command/admin/router/RebootRouterCmd.java b/api/src/org/apache/cloudstack/api/command/admin/router/RebootRouterCmd.java index 3a8938812b..4b138f3cfc 100644 --- a/api/src/org/apache/cloudstack/api/command/admin/router/RebootRouterCmd.java +++ b/api/src/org/apache/cloudstack/api/command/admin/router/RebootRouterCmd.java @@ -18,7 +18,6 @@ import org.apache.log4j.Logger; -import org.apache.cloudstack.acl.IAMEntityType; import org.apache.cloudstack.api.APICommand; import org.apache.cloudstack.api.ApiCommandJobType; import org.apache.cloudstack.api.ApiConstants; @@ -35,8 +34,9 @@ import com.cloud.exception.ResourceUnavailableException; import com.cloud.network.router.VirtualRouter; import com.cloud.user.Account; +import com.cloud.vm.VirtualMachine; -@APICommand(name = "rebootRouter", description = "Starts a router.", responseObject = DomainRouterResponse.class, entityType = {IAMEntityType.VirtualMachine}, +@APICommand(name = "rebootRouter", description = "Starts a router.", responseObject = DomainRouterResponse.class, entityType = {VirtualMachine.class}, requestHasSensitiveInfo = false, responseHasSensitiveInfo = false) public class RebootRouterCmd extends BaseAsyncCmd { public static final Logger s_logger = Logger.getLogger(RebootRouterCmd.class.getName()); diff --git a/api/src/org/apache/cloudstack/api/command/admin/router/StartRouterCmd.java b/api/src/org/apache/cloudstack/api/command/admin/router/StartRouterCmd.java index f83466b1dc..173833cb42 100644 --- a/api/src/org/apache/cloudstack/api/command/admin/router/StartRouterCmd.java +++ b/api/src/org/apache/cloudstack/api/command/admin/router/StartRouterCmd.java @@ -18,7 +18,6 @@ import org.apache.log4j.Logger; -import org.apache.cloudstack.acl.IAMEntityType; import org.apache.cloudstack.api.APICommand; import org.apache.cloudstack.api.ApiCommandJobType; import org.apache.cloudstack.api.ApiConstants; @@ -37,8 +36,9 @@ import com.cloud.network.router.VirtualRouter; import com.cloud.network.router.VirtualRouter.Role; import com.cloud.user.Account; +import com.cloud.vm.VirtualMachine; -@APICommand(name = "startRouter", responseObject = DomainRouterResponse.class, description = "Starts a router.", entityType = {IAMEntityType.VirtualMachine}, +@APICommand(name = "startRouter", responseObject = DomainRouterResponse.class, description = "Starts a router.", entityType = {VirtualMachine.class}, requestHasSensitiveInfo = false, responseHasSensitiveInfo = false) public class StartRouterCmd extends BaseAsyncCmd { public static final Logger s_logger = Logger.getLogger(StartRouterCmd.class.getName()); diff --git a/api/src/org/apache/cloudstack/api/command/admin/router/StopRouterCmd.java b/api/src/org/apache/cloudstack/api/command/admin/router/StopRouterCmd.java index e2d420073d..2592cae545 100644 --- a/api/src/org/apache/cloudstack/api/command/admin/router/StopRouterCmd.java +++ b/api/src/org/apache/cloudstack/api/command/admin/router/StopRouterCmd.java @@ -18,7 +18,6 @@ import org.apache.log4j.Logger; -import org.apache.cloudstack.acl.IAMEntityType; import org.apache.cloudstack.api.APICommand; import org.apache.cloudstack.api.ApiCommandJobType; import org.apache.cloudstack.api.ApiConstants; @@ -36,8 +35,9 @@ import com.cloud.network.router.VirtualRouter; import com.cloud.network.router.VirtualRouter.Role; import com.cloud.user.Account; +import com.cloud.vm.VirtualMachine; -@APICommand(name = "stopRouter", description = "Stops a router.", responseObject = DomainRouterResponse.class, entityType = {IAMEntityType.VirtualMachine}, +@APICommand(name = "stopRouter", description = "Stops a router.", responseObject = DomainRouterResponse.class, entityType = {VirtualMachine.class}, requestHasSensitiveInfo = false, responseHasSensitiveInfo = false) public class StopRouterCmd extends BaseAsyncCmd { public static final Logger s_logger = Logger.getLogger(StopRouterCmd.class.getName()); diff --git a/api/src/org/apache/cloudstack/api/command/admin/router/UpgradeRouterCmd.java b/api/src/org/apache/cloudstack/api/command/admin/router/UpgradeRouterCmd.java index 0b67db9cef..067d344337 100644 --- a/api/src/org/apache/cloudstack/api/command/admin/router/UpgradeRouterCmd.java +++ b/api/src/org/apache/cloudstack/api/command/admin/router/UpgradeRouterCmd.java @@ -18,7 +18,6 @@ import org.apache.log4j.Logger; -import org.apache.cloudstack.acl.IAMEntityType; import org.apache.cloudstack.api.APICommand; import org.apache.cloudstack.api.ApiConstants; import org.apache.cloudstack.api.ApiErrorCode; @@ -30,8 +29,9 @@ import com.cloud.network.router.VirtualRouter; import com.cloud.user.Account; +import com.cloud.vm.VirtualMachine; -@APICommand(name = "changeServiceForRouter", description = "Upgrades domain router to a new service offering", responseObject = DomainRouterResponse.class, entityType = {IAMEntityType.VirtualMachine}, +@APICommand(name = "changeServiceForRouter", description = "Upgrades domain router to a new service offering", responseObject = DomainRouterResponse.class, entityType = {VirtualMachine.class}, requestHasSensitiveInfo = false, responseHasSensitiveInfo = false) public class UpgradeRouterCmd extends BaseCmd { public static final Logger s_logger = Logger.getLogger(UpgradeRouterCmd.class.getName()); diff --git a/api/src/org/apache/cloudstack/api/command/admin/storage/AddS3Cmd.java b/api/src/org/apache/cloudstack/api/command/admin/storage/AddS3Cmd.java index 8a82e89d7a..4164394f5e 100644 --- a/api/src/org/apache/cloudstack/api/command/admin/storage/AddS3Cmd.java +++ b/api/src/org/apache/cloudstack/api/command/admin/storage/AddS3Cmd.java @@ -57,7 +57,7 @@ public final class AddS3Cmd extends BaseCmd { public static final Logger s_logger = Logger.getLogger(AddS3Cmd.class.getName()); - private static final String COMMAND_NAME = "adds3response"; + private static final String s_name = "adds3response"; @Parameter(name = S3_ACCESS_KEY, type = STRING, required = true, description = "S3 access key") private String accessKey; @@ -190,7 +190,7 @@ public int hashCode() { @Override public String getCommandName() { - return COMMAND_NAME; + return s_name; } @Override diff --git a/api/src/org/apache/cloudstack/api/command/admin/systemvm/DestroySystemVmCmd.java b/api/src/org/apache/cloudstack/api/command/admin/systemvm/DestroySystemVmCmd.java index bc977a456e..47dfe8b724 100644 --- a/api/src/org/apache/cloudstack/api/command/admin/systemvm/DestroySystemVmCmd.java +++ b/api/src/org/apache/cloudstack/api/command/admin/systemvm/DestroySystemVmCmd.java @@ -18,7 +18,6 @@ import org.apache.log4j.Logger; -import org.apache.cloudstack.acl.IAMEntityType; import org.apache.cloudstack.acl.SecurityChecker.AccessType; import org.apache.cloudstack.api.ACL; import org.apache.cloudstack.api.APICommand; @@ -35,7 +34,7 @@ import com.cloud.user.Account; import com.cloud.vm.VirtualMachine; -@APICommand(name = "destroySystemVm", responseObject = SystemVmResponse.class, description = "Destroyes a system virtual machine.", entityType = {IAMEntityType.VirtualMachine}, +@APICommand(name = "destroySystemVm", responseObject = SystemVmResponse.class, description = "Destroyes a system virtual machine.", entityType = {VirtualMachine.class}, requestHasSensitiveInfo = false, responseHasSensitiveInfo = false) public class DestroySystemVmCmd extends BaseAsyncCmd { public static final Logger s_logger = Logger.getLogger(DestroySystemVmCmd.class.getName()); diff --git a/api/src/org/apache/cloudstack/api/command/admin/systemvm/ListSystemVMsCmd.java b/api/src/org/apache/cloudstack/api/command/admin/systemvm/ListSystemVMsCmd.java index bfecd1857f..2b2faf5011 100644 --- a/api/src/org/apache/cloudstack/api/command/admin/systemvm/ListSystemVMsCmd.java +++ b/api/src/org/apache/cloudstack/api/command/admin/systemvm/ListSystemVMsCmd.java @@ -21,7 +21,6 @@ import org.apache.log4j.Logger; -import org.apache.cloudstack.acl.IAMEntityType; import org.apache.cloudstack.api.APICommand; import org.apache.cloudstack.api.ApiCommandJobType; import org.apache.cloudstack.api.ApiConstants; @@ -37,7 +36,7 @@ import com.cloud.utils.Pair; import com.cloud.vm.VirtualMachine; -@APICommand(name = "listSystemVms", description = "List system virtual machines.", responseObject = SystemVmResponse.class, entityType = {IAMEntityType.VirtualMachine}, +@APICommand(name = "listSystemVms", description = "List system virtual machines.", responseObject = SystemVmResponse.class, entityType = {VirtualMachine.class}, requestHasSensitiveInfo = false, responseHasSensitiveInfo = false) public class ListSystemVMsCmd extends BaseListCmd { public static final Logger s_logger = Logger.getLogger(ListSystemVMsCmd.class.getName()); diff --git a/api/src/org/apache/cloudstack/api/command/admin/systemvm/MigrateSystemVMCmd.java b/api/src/org/apache/cloudstack/api/command/admin/systemvm/MigrateSystemVMCmd.java index 994635a1b7..97acfe0c46 100644 --- a/api/src/org/apache/cloudstack/api/command/admin/systemvm/MigrateSystemVMCmd.java +++ b/api/src/org/apache/cloudstack/api/command/admin/systemvm/MigrateSystemVMCmd.java @@ -18,7 +18,6 @@ import org.apache.log4j.Logger; -import org.apache.cloudstack.acl.IAMEntityType; import org.apache.cloudstack.acl.SecurityChecker.AccessType; import org.apache.cloudstack.api.ACL; import org.apache.cloudstack.api.APICommand; @@ -41,7 +40,7 @@ import com.cloud.user.Account; import com.cloud.vm.VirtualMachine; -@APICommand(name = "migrateSystemVm", description = "Attempts Migration of a system virtual machine to the host specified.", responseObject = SystemVmResponse.class, entityType = {IAMEntityType.VirtualMachine}, +@APICommand(name = "migrateSystemVm", description = "Attempts Migration of a system virtual machine to the host specified.", responseObject = SystemVmResponse.class, entityType = {VirtualMachine.class}, requestHasSensitiveInfo = false, responseHasSensitiveInfo = false) public class MigrateSystemVMCmd extends BaseAsyncCmd { public static final Logger s_logger = Logger.getLogger(MigrateSystemVMCmd.class.getName()); diff --git a/api/src/org/apache/cloudstack/api/command/admin/systemvm/RebootSystemVmCmd.java b/api/src/org/apache/cloudstack/api/command/admin/systemvm/RebootSystemVmCmd.java index 0031d60351..f439ddf4de 100644 --- a/api/src/org/apache/cloudstack/api/command/admin/systemvm/RebootSystemVmCmd.java +++ b/api/src/org/apache/cloudstack/api/command/admin/systemvm/RebootSystemVmCmd.java @@ -18,7 +18,6 @@ import org.apache.log4j.Logger; -import org.apache.cloudstack.acl.IAMEntityType; import org.apache.cloudstack.acl.SecurityChecker.AccessType; import org.apache.cloudstack.api.ACL; import org.apache.cloudstack.api.APICommand; @@ -35,7 +34,7 @@ import com.cloud.user.Account; import com.cloud.vm.VirtualMachine; -@APICommand(name = "rebootSystemVm", description = "Reboots a system VM.", responseObject = SystemVmResponse.class, entityType = {IAMEntityType.VirtualMachine}, +@APICommand(name = "rebootSystemVm", description = "Reboots a system VM.", responseObject = SystemVmResponse.class, entityType = {VirtualMachine.class}, requestHasSensitiveInfo = false, responseHasSensitiveInfo = false) public class RebootSystemVmCmd extends BaseAsyncCmd { public static final Logger s_logger = Logger.getLogger(RebootSystemVmCmd.class.getName()); 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 index f50b2c4b2c..68e9f94a8b 100644 --- a/api/src/org/apache/cloudstack/api/command/admin/systemvm/ScaleSystemVMCmd.java +++ b/api/src/org/apache/cloudstack/api/command/admin/systemvm/ScaleSystemVMCmd.java @@ -23,7 +23,6 @@ import org.apache.log4j.Logger; -import org.apache.cloudstack.acl.IAMEntityType; import org.apache.cloudstack.acl.SecurityChecker.AccessType; import org.apache.cloudstack.api.ACL; import org.apache.cloudstack.api.APICommand; @@ -48,7 +47,7 @@ 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.", entityType = {IAMEntityType.VirtualMachine}, + + "The system vm must be in a \"Stopped\" state for " + "this command to take effect.", entityType = {VirtualMachine.class}, requestHasSensitiveInfo = false, responseHasSensitiveInfo = false) public class ScaleSystemVMCmd extends BaseAsyncCmd { public static final Logger s_logger = Logger.getLogger(UpgradeVMCmd.class.getName()); diff --git a/api/src/org/apache/cloudstack/api/command/admin/systemvm/StartSystemVMCmd.java b/api/src/org/apache/cloudstack/api/command/admin/systemvm/StartSystemVMCmd.java index 6aecc9117c..c456592d10 100644 --- a/api/src/org/apache/cloudstack/api/command/admin/systemvm/StartSystemVMCmd.java +++ b/api/src/org/apache/cloudstack/api/command/admin/systemvm/StartSystemVMCmd.java @@ -18,7 +18,6 @@ import org.apache.log4j.Logger; -import org.apache.cloudstack.acl.IAMEntityType; import org.apache.cloudstack.acl.SecurityChecker.AccessType; import org.apache.cloudstack.api.ACL; import org.apache.cloudstack.api.APICommand; @@ -35,7 +34,7 @@ import com.cloud.user.Account; import com.cloud.vm.VirtualMachine; -@APICommand(name = "startSystemVm", responseObject = SystemVmResponse.class, description = "Starts a system virtual machine.", entityType = {IAMEntityType.VirtualMachine}, +@APICommand(name = "startSystemVm", responseObject = SystemVmResponse.class, description = "Starts a system virtual machine.", entityType = {VirtualMachine.class}, requestHasSensitiveInfo = false, responseHasSensitiveInfo = false) public class StartSystemVMCmd extends BaseAsyncCmd { public static final Logger s_logger = Logger.getLogger(StartSystemVMCmd.class.getName()); diff --git a/api/src/org/apache/cloudstack/api/command/admin/systemvm/StopSystemVmCmd.java b/api/src/org/apache/cloudstack/api/command/admin/systemvm/StopSystemVmCmd.java index 9a049c2afe..d60460ced1 100644 --- a/api/src/org/apache/cloudstack/api/command/admin/systemvm/StopSystemVmCmd.java +++ b/api/src/org/apache/cloudstack/api/command/admin/systemvm/StopSystemVmCmd.java @@ -18,7 +18,6 @@ import org.apache.log4j.Logger; -import org.apache.cloudstack.acl.IAMEntityType; import org.apache.cloudstack.acl.SecurityChecker.AccessType; import org.apache.cloudstack.api.ACL; import org.apache.cloudstack.api.APICommand; @@ -37,7 +36,7 @@ import com.cloud.user.Account; import com.cloud.vm.VirtualMachine; -@APICommand(name = "stopSystemVm", description = "Stops a system VM.", responseObject = SystemVmResponse.class, entityType = {IAMEntityType.VirtualMachine}, +@APICommand(name = "stopSystemVm", description = "Stops a system VM.", responseObject = SystemVmResponse.class, entityType = {VirtualMachine.class}, requestHasSensitiveInfo = false, responseHasSensitiveInfo = false) public class StopSystemVmCmd extends BaseAsyncCmd { public static final Logger s_logger = Logger.getLogger(StopSystemVmCmd.class.getName()); diff --git a/api/src/org/apache/cloudstack/api/command/admin/systemvm/UpgradeSystemVMCmd.java b/api/src/org/apache/cloudstack/api/command/admin/systemvm/UpgradeSystemVMCmd.java index 033709aca4..d71ef03244 100644 --- a/api/src/org/apache/cloudstack/api/command/admin/systemvm/UpgradeSystemVMCmd.java +++ b/api/src/org/apache/cloudstack/api/command/admin/systemvm/UpgradeSystemVMCmd.java @@ -23,7 +23,6 @@ import org.apache.log4j.Logger; -import org.apache.cloudstack.acl.IAMEntityType; import org.apache.cloudstack.acl.SecurityChecker.AccessType; import org.apache.cloudstack.api.ACL; import org.apache.cloudstack.api.APICommand; @@ -43,7 +42,7 @@ import com.cloud.vm.VirtualMachine; @APICommand(name = "changeServiceForSystemVm", responseObject = SystemVmResponse.class, description = "Changes 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.", entityType = {IAMEntityType.VirtualMachine}, + + "The system vm must be in a \"Stopped\" state for " + "this command to take effect.", entityType = {VirtualMachine.class}, requestHasSensitiveInfo = false, responseHasSensitiveInfo = false) public class UpgradeSystemVMCmd extends BaseCmd { public static final Logger s_logger = Logger.getLogger(UpgradeVMCmd.class.getName()); diff --git a/api/src/org/apache/cloudstack/api/command/admin/template/ListTemplatesCmdByAdmin.java b/api/src/org/apache/cloudstack/api/command/admin/template/ListTemplatesCmdByAdmin.java index b2e9ef54e2..4e2bb018d0 100644 --- a/api/src/org/apache/cloudstack/api/command/admin/template/ListTemplatesCmdByAdmin.java +++ b/api/src/org/apache/cloudstack/api/command/admin/template/ListTemplatesCmdByAdmin.java @@ -16,13 +16,14 @@ // under the License. package org.apache.cloudstack.api.command.admin.template; -import org.apache.cloudstack.acl.IAMEntityType; import org.apache.cloudstack.api.APICommand; import org.apache.cloudstack.api.ResponseObject.ResponseView; import org.apache.cloudstack.api.command.user.template.ListTemplatesCmd; import org.apache.cloudstack.api.response.TemplateResponse; -@APICommand(name = "listTemplates", description = "List all public, private, and privileged templates.", responseObject = TemplateResponse.class, entityType = {IAMEntityType.VirtualMachineTemplate}, responseView = ResponseView.Full) +import com.cloud.template.VirtualMachineTemplate; + +@APICommand(name = "listTemplates", description = "List all public, private, and privileged templates.", responseObject = TemplateResponse.class, entityType = {VirtualMachineTemplate.class}, responseView = ResponseView.Full) public class ListTemplatesCmdByAdmin extends ListTemplatesCmd { } diff --git a/api/src/org/apache/cloudstack/api/command/admin/template/PrepareTemplateCmd.java b/api/src/org/apache/cloudstack/api/command/admin/template/PrepareTemplateCmd.java index ce432430e1..d4c26966d9 100644 --- a/api/src/org/apache/cloudstack/api/command/admin/template/PrepareTemplateCmd.java +++ b/api/src/org/apache/cloudstack/api/command/admin/template/PrepareTemplateCmd.java @@ -20,7 +20,6 @@ import org.apache.log4j.Logger; -import org.apache.cloudstack.acl.IAMEntityType; import org.apache.cloudstack.acl.SecurityChecker.AccessType; import org.apache.cloudstack.api.ACL; import org.apache.cloudstack.api.APICommand; @@ -35,7 +34,7 @@ import com.cloud.template.VirtualMachineTemplate; import com.cloud.user.Account; -@APICommand(name = "prepareTemplate", responseObject = TemplateResponse.class, description = "load template into primary storage", entityType = {IAMEntityType.VirtualMachineTemplate}, +@APICommand(name = "prepareTemplate", responseObject = TemplateResponse.class, description = "load template into primary storage", entityType = {VirtualMachineTemplate.class}, requestHasSensitiveInfo = false, responseHasSensitiveInfo = false) public class PrepareTemplateCmd extends BaseCmd { public static final Logger s_logger = Logger.getLogger(PrepareTemplateCmd.class.getName()); diff --git a/api/src/org/apache/cloudstack/api/command/admin/usage/ListTrafficTypeImplementorsCmd.java b/api/src/org/apache/cloudstack/api/command/admin/usage/ListTrafficTypeImplementorsCmd.java index a1ff29fd00..bd634bbe5c 100644 --- a/api/src/org/apache/cloudstack/api/command/admin/usage/ListTrafficTypeImplementorsCmd.java +++ b/api/src/org/apache/cloudstack/api/command/admin/usage/ListTrafficTypeImplementorsCmd.java @@ -45,7 +45,7 @@ responseHasSensitiveInfo = false) public class ListTrafficTypeImplementorsCmd extends BaseListCmd { public static final Logger s_logger = Logger.getLogger(ListTrafficTypeImplementorsCmd.class); - private static final String Name = "listtraffictypeimplementorsresponse"; + private static final String s_name = "listtraffictypeimplementorsresponse"; ///////////////////////////////////////////////////// //////////////// API parameters ///////////////////// @@ -89,6 +89,6 @@ public long getEntityOwnerId() { @Override public String getCommandName() { - return Name; + return s_name; } } diff --git a/api/src/org/apache/cloudstack/api/command/admin/usage/ListTrafficTypesCmd.java b/api/src/org/apache/cloudstack/api/command/admin/usage/ListTrafficTypesCmd.java index 33ee29611d..fd0635959b 100644 --- a/api/src/org/apache/cloudstack/api/command/admin/usage/ListTrafficTypesCmd.java +++ b/api/src/org/apache/cloudstack/api/command/admin/usage/ListTrafficTypesCmd.java @@ -38,7 +38,7 @@ requestHasSensitiveInfo = false, responseHasSensitiveInfo = false) public class ListTrafficTypesCmd extends BaseListCmd { public static final Logger s_logger = Logger.getLogger(ListTrafficTypesCmd.class.getName()); - private static final String Name = "listtraffictypesresponse"; + private static final String s_name = "listtraffictypesresponse"; ///////////////////////////////////////////////////// //////////////// API parameters ///////////////////// @@ -67,7 +67,7 @@ public Long getPhysicalNetworkId() { ///////////////////////////////////////////////////// @Override public String getCommandName() { - return Name; + return s_name; } @Override diff --git a/api/src/org/apache/cloudstack/api/command/admin/user/CreateUserCmd.java b/api/src/org/apache/cloudstack/api/command/admin/user/CreateUserCmd.java index 51e218d7de..bd67436f6e 100644 --- a/api/src/org/apache/cloudstack/api/command/admin/user/CreateUserCmd.java +++ b/api/src/org/apache/cloudstack/api/command/admin/user/CreateUserCmd.java @@ -31,7 +31,7 @@ import com.cloud.user.User; @APICommand(name = "createUser", description = "Creates a user for an account that already exists", responseObject = UserResponse.class, - requestHasSensitiveInfo = true, responseHasSensitiveInfo = true) + requestHasSensitiveInfo = true, responseHasSensitiveInfo = true, entityType = { Account.class }) public class CreateUserCmd extends BaseCmd { public static final Logger s_logger = Logger.getLogger(CreateUserCmd.class.getName()); @@ -131,7 +131,7 @@ public String getCommandName() { @Override public long getEntityOwnerId() { Account account = CallContext.current().getCallingAccount(); - if ((account == null) || _accountService.isAdmin(account.getType())) { + if ((account == null) || _accountService.isAdmin(account.getId())) { if ((domainId != null) && (accountName != null)) { Account userAccount = _responseGenerator.findAccountByNameDomain(accountName, domainId); if (userAccount != null) { diff --git a/api/src/org/apache/cloudstack/api/command/admin/user/DeleteUserCmd.java b/api/src/org/apache/cloudstack/api/command/admin/user/DeleteUserCmd.java index 08ba521ed6..f90a48043d 100644 --- a/api/src/org/apache/cloudstack/api/command/admin/user/DeleteUserCmd.java +++ b/api/src/org/apache/cloudstack/api/command/admin/user/DeleteUserCmd.java @@ -35,7 +35,7 @@ import com.cloud.user.User; @APICommand(name = "deleteUser", description = "Deletes a user for an account", responseObject = SuccessResponse.class, - requestHasSensitiveInfo = false, responseHasSensitiveInfo = false) + requestHasSensitiveInfo = false, responseHasSensitiveInfo = false, entityType = { Account.class }) public class DeleteUserCmd extends BaseCmd { public static final Logger s_logger = Logger.getLogger(DeleteUserCmd.class.getName()); diff --git a/api/src/org/apache/cloudstack/api/command/admin/user/DisableUserCmd.java b/api/src/org/apache/cloudstack/api/command/admin/user/DisableUserCmd.java index c6e09ef0f9..3a9676e246 100644 --- a/api/src/org/apache/cloudstack/api/command/admin/user/DisableUserCmd.java +++ b/api/src/org/apache/cloudstack/api/command/admin/user/DisableUserCmd.java @@ -37,7 +37,7 @@ import com.cloud.user.UserAccount; @APICommand(name = "disableUser", description = "Disables a user account", responseObject = UserResponse.class, - requestHasSensitiveInfo = false, responseHasSensitiveInfo = true) + requestHasSensitiveInfo = false, responseHasSensitiveInfo = true, entityType = { Account.class }) public class DisableUserCmd extends BaseAsyncCmd { public static final Logger s_logger = Logger.getLogger(DisableUserCmd.class.getName()); private static final String s_name = "disableuserresponse"; diff --git a/api/src/org/apache/cloudstack/api/command/admin/user/EnableUserCmd.java b/api/src/org/apache/cloudstack/api/command/admin/user/EnableUserCmd.java index d69eccf934..e4f4477103 100644 --- a/api/src/org/apache/cloudstack/api/command/admin/user/EnableUserCmd.java +++ b/api/src/org/apache/cloudstack/api/command/admin/user/EnableUserCmd.java @@ -35,7 +35,7 @@ import com.cloud.user.UserAccount; @APICommand(name = "enableUser", description = "Enables a user account", responseObject = UserResponse.class, - requestHasSensitiveInfo = false, responseHasSensitiveInfo = true) + requestHasSensitiveInfo = false, responseHasSensitiveInfo = true, entityType = { Account.class }) public class EnableUserCmd extends BaseCmd { public static final Logger s_logger = Logger.getLogger(EnableUserCmd.class.getName()); private static final String s_name = "enableuserresponse"; diff --git a/api/src/org/apache/cloudstack/api/command/admin/user/GetUserCmd.java b/api/src/org/apache/cloudstack/api/command/admin/user/GetUserCmd.java index b2c6734c9e..f8c7589e78 100644 --- a/api/src/org/apache/cloudstack/api/command/admin/user/GetUserCmd.java +++ b/api/src/org/apache/cloudstack/api/command/admin/user/GetUserCmd.java @@ -25,10 +25,11 @@ import org.apache.cloudstack.api.response.UserResponse; import com.cloud.exception.InvalidParameterValueException; +import com.cloud.user.Account; import com.cloud.user.UserAccount; @APICommand(name = "getUser", description = "Find user account by API key", responseObject = UserResponse.class, - requestHasSensitiveInfo = false, responseHasSensitiveInfo = true) + requestHasSensitiveInfo = false, responseHasSensitiveInfo = true, entityType = { Account.class }) public class GetUserCmd extends BaseCmd { public static final Logger s_logger = Logger.getLogger(GetUserCmd.class.getName()); diff --git a/api/src/org/apache/cloudstack/api/command/admin/user/ListUsersCmd.java b/api/src/org/apache/cloudstack/api/command/admin/user/ListUsersCmd.java index c0c2b24814..14cbb26602 100644 --- a/api/src/org/apache/cloudstack/api/command/admin/user/ListUsersCmd.java +++ b/api/src/org/apache/cloudstack/api/command/admin/user/ListUsersCmd.java @@ -25,8 +25,10 @@ import org.apache.cloudstack.api.response.ListResponse; import org.apache.cloudstack.api.response.UserResponse; +import com.cloud.user.Account; + @APICommand(name = "listUsers", description = "Lists user accounts", responseObject = UserResponse.class, - requestHasSensitiveInfo = false, responseHasSensitiveInfo = true) + requestHasSensitiveInfo = false, responseHasSensitiveInfo = true, entityType = { Account.class }) public class ListUsersCmd extends BaseListAccountResourcesCmd { public static final Logger s_logger = Logger.getLogger(ListUsersCmd.class.getName()); diff --git a/api/src/org/apache/cloudstack/api/command/admin/user/UpdateUserCmd.java b/api/src/org/apache/cloudstack/api/command/admin/user/UpdateUserCmd.java index cf5d355e26..e7236e8659 100644 --- a/api/src/org/apache/cloudstack/api/command/admin/user/UpdateUserCmd.java +++ b/api/src/org/apache/cloudstack/api/command/admin/user/UpdateUserCmd.java @@ -35,7 +35,7 @@ import com.cloud.user.UserAccount; @APICommand(name = "updateUser", description = "Updates a user account", responseObject = UserResponse.class, - requestHasSensitiveInfo = true, responseHasSensitiveInfo = true) + requestHasSensitiveInfo = true, responseHasSensitiveInfo = true, entityType = { Account.class }) public class UpdateUserCmd extends BaseCmd { public static final Logger s_logger = Logger.getLogger(UpdateUserCmd.class.getName()); @@ -45,7 +45,7 @@ public class UpdateUserCmd extends BaseCmd { //////////////// API parameters ///////////////////// ///////////////////////////////////////////////////// - @Parameter(name = ApiConstants.API_KEY, type = CommandType.STRING, description = "The API key for the user. Must be specified with userSecretKey") + @Parameter(name = ApiConstants.USER_API_KEY, type = CommandType.STRING, description = "The API key for the user. Must be specified with userSecretKey") private String apiKey; @Parameter(name = ApiConstants.EMAIL, type = CommandType.STRING, description = "email") @@ -65,7 +65,7 @@ public class UpdateUserCmd extends BaseCmd { description = "Clear text password (default hashed to SHA256SALT). If you wish to use any other hasing algorithm, you would need to write a custom authentication adapter") private String password; - @Parameter(name = ApiConstants.SECRET_KEY, type = CommandType.STRING, description = "The secret key for the user. Must be specified with userApiKey") + @Parameter(name = ApiConstants.SECRET_KEY, type = CommandType.STRING, description = "The secret key for the user. Must be specified with userSecretKey") private String secretKey; @Parameter(name = ApiConstants.TIMEZONE, diff --git a/api/src/org/apache/cloudstack/api/command/admin/vm/AddNicToVMCmdByAdmin.java b/api/src/org/apache/cloudstack/api/command/admin/vm/AddNicToVMCmdByAdmin.java index 996d1bd49e..3dd22c15ad 100644 --- a/api/src/org/apache/cloudstack/api/command/admin/vm/AddNicToVMCmdByAdmin.java +++ b/api/src/org/apache/cloudstack/api/command/admin/vm/AddNicToVMCmdByAdmin.java @@ -31,9 +31,10 @@ import org.apache.cloudstack.context.CallContext; import com.cloud.uservm.UserVm; +import com.cloud.vm.VirtualMachine; -@APICommand(name = "addNicToVirtualMachine", description = "Adds VM to specified network by creating a NIC", responseObject = UserVmResponse.class, responseView = ResponseView.Full) - +@APICommand(name = "addNicToVirtualMachine", description = "Adds VM to specified network by creating a NIC", responseObject = UserVmResponse.class, responseView = ResponseView.Full, entityType = {VirtualMachine.class}, + requestHasSensitiveInfo = false, responseHasSensitiveInfo = true) public class AddNicToVMCmdByAdmin extends AddNicToVMCmd { public static final Logger s_logger = Logger.getLogger(AddNicToVMCmdByAdmin.class); diff --git a/api/src/org/apache/cloudstack/api/command/admin/vm/AssignVMCmd.java b/api/src/org/apache/cloudstack/api/command/admin/vm/AssignVMCmd.java index dd84ec2a60..435b7f1848 100644 --- a/api/src/org/apache/cloudstack/api/command/admin/vm/AssignVMCmd.java +++ b/api/src/org/apache/cloudstack/api/command/admin/vm/AssignVMCmd.java @@ -20,7 +20,6 @@ import org.apache.log4j.Logger; -import org.apache.cloudstack.acl.IAMEntityType; import org.apache.cloudstack.api.APICommand; import org.apache.cloudstack.api.ApiConstants; import org.apache.cloudstack.api.ApiErrorCode; @@ -35,11 +34,12 @@ import com.cloud.user.Account; import com.cloud.uservm.UserVm; +import com.cloud.vm.VirtualMachine; @APICommand(name = "assignVirtualMachine", description = "Change ownership of a VM from one account to another. This API is available for Basic zones with security groups and Advanced zones with guest networks. A root administrator can reassign a VM from any account to any other account in any domain. A domain administrator can reassign a VM to any account in the same domain.", responseObject = UserVmResponse.class, - since = "3.0.0", entityType = {IAMEntityType.VirtualMachine}, + since = "3.0.0", entityType = {VirtualMachine.class}, requestHasSensitiveInfo = false, responseHasSensitiveInfo = true) public class AssignVMCmd extends BaseCmd { diff --git a/api/src/org/apache/cloudstack/api/command/admin/vm/DeployVMCmdByAdmin.java b/api/src/org/apache/cloudstack/api/command/admin/vm/DeployVMCmdByAdmin.java index 99fec6b5a7..77aa20f3ca 100755 --- a/api/src/org/apache/cloudstack/api/command/admin/vm/DeployVMCmdByAdmin.java +++ b/api/src/org/apache/cloudstack/api/command/admin/vm/DeployVMCmdByAdmin.java @@ -68,7 +68,7 @@ public void execute(){ } if (result != null) { - UserVmResponse response = _responseGenerator.createUserVmResponse(ResponseView.Restricted, "virtualmachine", result).get(0); + UserVmResponse response = _responseGenerator.createUserVmResponse(ResponseView.Full, "virtualmachine", result).get(0); response.setResponseName(getCommandName()); setResponseObject(response); } else { diff --git a/api/src/org/apache/cloudstack/api/command/admin/vm/ExpungeVMCmd.java b/api/src/org/apache/cloudstack/api/command/admin/vm/ExpungeVMCmd.java index 623ddb6779..155fcfff4d 100644 --- a/api/src/org/apache/cloudstack/api/command/admin/vm/ExpungeVMCmd.java +++ b/api/src/org/apache/cloudstack/api/command/admin/vm/ExpungeVMCmd.java @@ -18,7 +18,6 @@ import org.apache.log4j.Logger; -import org.apache.cloudstack.acl.IAMEntityType; import org.apache.cloudstack.acl.SecurityChecker.AccessType; import org.apache.cloudstack.api.ACL; import org.apache.cloudstack.api.APICommand; @@ -39,8 +38,9 @@ import com.cloud.user.Account; import com.cloud.uservm.UserVm; import com.cloud.utils.exception.CloudRuntimeException; +import com.cloud.vm.VirtualMachine; -@APICommand(name = "expungeVirtualMachine", description = "Expunge a virtual machine. Once expunged, it cannot be recoverd.", responseObject = SuccessResponse.class, entityType = {IAMEntityType.VirtualMachine}, +@APICommand(name = "expungeVirtualMachine", description = "Expunge a virtual machine. Once expunged, it cannot be recoverd.", responseObject = SuccessResponse.class, entityType = {VirtualMachine.class}, requestHasSensitiveInfo = false, responseHasSensitiveInfo = false) public class ExpungeVMCmd extends BaseAsyncCmd { public static final Logger s_logger = Logger.getLogger(ExpungeVMCmd.class.getName()); @@ -106,7 +106,7 @@ public Long getInstanceId() { public void execute() throws ResourceUnavailableException, ConcurrentOperationException { CallContext.current().setEventDetails("Vm Id: " + getId()); try { - UserVm result = _userVmService.expungeVm(this); + UserVm result = _userVmService.expungeVm(this.getId()); if (result != null) { SuccessResponse response = new SuccessResponse(getCommandName()); diff --git a/api/src/org/apache/cloudstack/api/command/admin/vm/MigrateVMCmd.java b/api/src/org/apache/cloudstack/api/command/admin/vm/MigrateVMCmd.java index fe8446859c..ef9619effa 100644 --- a/api/src/org/apache/cloudstack/api/command/admin/vm/MigrateVMCmd.java +++ b/api/src/org/apache/cloudstack/api/command/admin/vm/MigrateVMCmd.java @@ -18,7 +18,6 @@ import org.apache.log4j.Logger; -import org.apache.cloudstack.acl.IAMEntityType; import org.apache.cloudstack.api.APICommand; import org.apache.cloudstack.api.ApiConstants; import org.apache.cloudstack.api.ApiErrorCode; @@ -45,7 +44,7 @@ @APICommand(name = "migrateVirtualMachine", description = "Attempts Migration of a VM to a different host or Root volume of the vm to a different storage pool", - responseObject = UserVmResponse.class, entityType = {IAMEntityType.VirtualMachine}, + responseObject = UserVmResponse.class, entityType = {VirtualMachine.class}, requestHasSensitiveInfo = false, responseHasSensitiveInfo = true) public class MigrateVMCmd extends BaseAsyncCmd { diff --git a/api/src/org/apache/cloudstack/api/command/admin/vm/MigrateVirtualMachineWithVolumeCmd.java b/api/src/org/apache/cloudstack/api/command/admin/vm/MigrateVirtualMachineWithVolumeCmd.java index b5d1ae9315..f1d3fe975f 100644 --- a/api/src/org/apache/cloudstack/api/command/admin/vm/MigrateVirtualMachineWithVolumeCmd.java +++ b/api/src/org/apache/cloudstack/api/command/admin/vm/MigrateVirtualMachineWithVolumeCmd.java @@ -23,7 +23,6 @@ import org.apache.log4j.Logger; -import org.apache.cloudstack.acl.IAMEntityType; import org.apache.cloudstack.api.APICommand; import org.apache.cloudstack.api.ApiConstants; import org.apache.cloudstack.api.ApiErrorCode; @@ -47,7 +46,7 @@ @APICommand(name = "migrateVirtualMachineWithVolume", description = "Attempts Migration of a VM with its volumes to a different host", - responseObject = UserVmResponse.class, entityType = {IAMEntityType.VirtualMachine}, + responseObject = UserVmResponse.class, entityType = {VirtualMachine.class}, requestHasSensitiveInfo = false, responseHasSensitiveInfo = true) public class MigrateVirtualMachineWithVolumeCmd extends BaseAsyncCmd { diff --git a/api/src/org/apache/cloudstack/api/command/admin/vm/RecoverVMCmd.java b/api/src/org/apache/cloudstack/api/command/admin/vm/RecoverVMCmd.java index e7fbbdb784..4ad0917154 100644 --- a/api/src/org/apache/cloudstack/api/command/admin/vm/RecoverVMCmd.java +++ b/api/src/org/apache/cloudstack/api/command/admin/vm/RecoverVMCmd.java @@ -18,7 +18,6 @@ import org.apache.log4j.Logger; -import org.apache.cloudstack.acl.IAMEntityType; import org.apache.cloudstack.api.APICommand; import org.apache.cloudstack.api.ApiConstants; import org.apache.cloudstack.api.ApiErrorCode; @@ -31,8 +30,9 @@ import com.cloud.exception.ResourceAllocationException; import com.cloud.user.Account; import com.cloud.uservm.UserVm; +import com.cloud.vm.VirtualMachine; -@APICommand(name = "recoverVirtualMachine", description = "Recovers a virtual machine.", responseObject = UserVmResponse.class, entityType = {IAMEntityType.VirtualMachine}, +@APICommand(name = "recoverVirtualMachine", description = "Recovers a virtual machine.", responseObject = UserVmResponse.class, entityType = {VirtualMachine.class}, requestHasSensitiveInfo = false, responseHasSensitiveInfo = true) public class RecoverVMCmd extends BaseCmd { public static final Logger s_logger = Logger.getLogger(RecoverVMCmd.class.getName()); diff --git a/api/src/org/apache/cloudstack/api/command/admin/volume/CreateVolumeCmdByAdmin.java b/api/src/org/apache/cloudstack/api/command/admin/volume/CreateVolumeCmdByAdmin.java index 5df7481497..8ff3993cd5 100644 --- a/api/src/org/apache/cloudstack/api/command/admin/volume/CreateVolumeCmdByAdmin.java +++ b/api/src/org/apache/cloudstack/api/command/admin/volume/CreateVolumeCmdByAdmin.java @@ -28,8 +28,11 @@ import com.cloud.storage.Snapshot; import com.cloud.storage.Volume; +import com.cloud.vm.VirtualMachine; -@APICommand(name = "createVolume", responseObject = VolumeResponse.class, description = "Creates a disk volume from a disk offering. This disk volume must still be attached to a virtual machine to make use of it.", responseView = ResponseView.Full) +@APICommand(name = "createVolume", responseObject = VolumeResponse.class, description = "Creates a disk volume from a disk offering. This disk volume must still be attached to a virtual machine to make use of it.", responseView = ResponseView.Full, entityType = { + Volume.class, VirtualMachine.class}, + requestHasSensitiveInfo = false, responseHasSensitiveInfo = false) public class CreateVolumeCmdByAdmin extends CreateVolumeCmd { public static final Logger s_logger = Logger.getLogger(CreateVolumeCmdByAdmin.class.getName()); diff --git a/api/src/org/apache/cloudstack/api/command/admin/vpc/CreatePrivateGatewayCmd.java b/api/src/org/apache/cloudstack/api/command/admin/vpc/CreatePrivateGatewayCmd.java index ff88ada781..01db44e25d 100644 --- a/api/src/org/apache/cloudstack/api/command/admin/vpc/CreatePrivateGatewayCmd.java +++ b/api/src/org/apache/cloudstack/api/command/admin/vpc/CreatePrivateGatewayCmd.java @@ -18,7 +18,6 @@ import org.apache.log4j.Logger; -import org.apache.cloudstack.acl.IAMEntityType; import org.apache.cloudstack.api.APICommand; import org.apache.cloudstack.api.ApiCommandJobType; import org.apache.cloudstack.api.ApiConstants; @@ -41,9 +40,10 @@ import com.cloud.exception.ResourceUnavailableException; import com.cloud.network.vpc.PrivateGateway; import com.cloud.network.vpc.Vpc; +import com.cloud.network.vpc.VpcGateway; import com.cloud.user.Account; -@APICommand(name = "createPrivateGateway", description = "Creates a private gateway", responseObject = PrivateGatewayResponse.class, entityType = {IAMEntityType.PrivateGateway}, +@APICommand(name = "createPrivateGateway", description = "Creates a private gateway", responseObject = PrivateGatewayResponse.class, entityType = {VpcGateway.class}, requestHasSensitiveInfo = false, responseHasSensitiveInfo = false) public class CreatePrivateGatewayCmd extends BaseAsyncCreateCmd { public static final Logger s_logger = Logger.getLogger(CreatePrivateGatewayCmd.class.getName()); diff --git a/api/src/org/apache/cloudstack/api/command/admin/vpc/CreateVPCOfferingCmd.java b/api/src/org/apache/cloudstack/api/command/admin/vpc/CreateVPCOfferingCmd.java index 5b3090bd75..13e4c0e04b 100644 --- a/api/src/org/apache/cloudstack/api/command/admin/vpc/CreateVPCOfferingCmd.java +++ b/api/src/org/apache/cloudstack/api/command/admin/vpc/CreateVPCOfferingCmd.java @@ -43,7 +43,7 @@ requestHasSensitiveInfo = false, responseHasSensitiveInfo = false) public class CreateVPCOfferingCmd extends BaseAsyncCreateCmd { public static final Logger s_logger = Logger.getLogger(CreateVPCOfferingCmd.class.getName()); - private static final String Name = "createvpcofferingresponse"; + private static final String s_name = "createvpcofferingresponse"; ///////////////////////////////////////////////////// //////////////// API parameters ///////////////////// @@ -66,7 +66,7 @@ public class CreateVPCOfferingCmd extends BaseAsyncCreateCmd { + "If not specified, the provider for the service will be mapped to the default provider on the physical network") private Map serviceProviderList; - @Parameter(name = ApiConstants.SERVICE_CAPABILITY_LIST, type = CommandType.MAP, description = "desired service capabilities as part of vpc offering") + @Parameter(name = ApiConstants.SERVICE_CAPABILITY_LIST, type = CommandType.MAP, description = "desired service capabilities as part of vpc offering", since = "4.4") private Map serviceCapabilitystList; @Parameter(name = ApiConstants.SERVICE_OFFERING_ID, @@ -159,7 +159,7 @@ public String getEventDescription() { @Override public String getCommandName() { - return Name; + return s_name; } @Override diff --git a/api/src/org/apache/cloudstack/api/command/admin/vpc/DeletePrivateGatewayCmd.java b/api/src/org/apache/cloudstack/api/command/admin/vpc/DeletePrivateGatewayCmd.java index dcce58e227..8d67a4ed8c 100644 --- a/api/src/org/apache/cloudstack/api/command/admin/vpc/DeletePrivateGatewayCmd.java +++ b/api/src/org/apache/cloudstack/api/command/admin/vpc/DeletePrivateGatewayCmd.java @@ -18,7 +18,6 @@ import org.apache.log4j.Logger; -import org.apache.cloudstack.acl.IAMEntityType; import org.apache.cloudstack.api.APICommand; import org.apache.cloudstack.api.ApiCommandJobType; import org.apache.cloudstack.api.ApiConstants; @@ -37,7 +36,7 @@ import com.cloud.network.vpc.VpcGateway; import com.cloud.user.Account; -@APICommand(name = "deletePrivateGateway", description = "Deletes a Private gateway", responseObject = SuccessResponse.class, entityType = {IAMEntityType.PrivateGateway}, +@APICommand(name = "deletePrivateGateway", description = "Deletes a Private gateway", responseObject = SuccessResponse.class, entityType = {VpcGateway.class}, requestHasSensitiveInfo = false, responseHasSensitiveInfo = false) public class DeletePrivateGatewayCmd extends BaseAsyncCmd { public static final Logger s_logger = Logger.getLogger(DeletePrivateGatewayCmd.class.getName()); diff --git a/api/src/org/apache/cloudstack/api/command/admin/vpc/UpdateVPCOfferingCmd.java b/api/src/org/apache/cloudstack/api/command/admin/vpc/UpdateVPCOfferingCmd.java index 8b05a7a5a2..5af47d3a4c 100644 --- a/api/src/org/apache/cloudstack/api/command/admin/vpc/UpdateVPCOfferingCmd.java +++ b/api/src/org/apache/cloudstack/api/command/admin/vpc/UpdateVPCOfferingCmd.java @@ -34,7 +34,7 @@ requestHasSensitiveInfo = false, responseHasSensitiveInfo = false) public class UpdateVPCOfferingCmd extends BaseAsyncCmd { public static final Logger s_logger = Logger.getLogger(UpdateVPCOfferingCmd.class.getName()); - private static final String Name = "updatevpcofferingresponse"; + private static final String s_name = "updatevpcofferingresponse"; ///////////////////////////////////////////////////// //////////////// API parameters ///////////////////// @@ -77,7 +77,7 @@ public String getState() { ///////////////////////////////////////////////////// @Override public String getCommandName() { - return Name; + return s_name; } @Override diff --git a/api/src/org/apache/cloudstack/api/command/user/account/ListAccountsCmd.java b/api/src/org/apache/cloudstack/api/command/user/account/ListAccountsCmd.java index 65331e4c4a..0b5ae7c0ba 100644 --- a/api/src/org/apache/cloudstack/api/command/user/account/ListAccountsCmd.java +++ b/api/src/org/apache/cloudstack/api/command/user/account/ListAccountsCmd.java @@ -18,7 +18,6 @@ import org.apache.log4j.Logger; -import org.apache.cloudstack.acl.IAMEntityType; import org.apache.cloudstack.api.APICommand; import org.apache.cloudstack.api.ApiConstants; import org.apache.cloudstack.api.BaseListDomainResourcesCmd; @@ -27,7 +26,9 @@ import org.apache.cloudstack.api.response.AccountResponse; import org.apache.cloudstack.api.response.ListResponse; -@APICommand(name = "listAccounts", description = "Lists accounts and provides detailed account information for listed accounts", responseObject = AccountResponse.class, responseView = ResponseView.Restricted, entityType = {IAMEntityType.Account}, +import com.cloud.user.Account; + +@APICommand(name = "listAccounts", description = "Lists accounts and provides detailed account information for listed accounts", responseObject = AccountResponse.class, responseView = ResponseView.Restricted, entityType = {Account.class}, requestHasSensitiveInfo = false, responseHasSensitiveInfo = true) public class ListAccountsCmd extends BaseListDomainResourcesCmd { public static final Logger s_logger = Logger.getLogger(ListAccountsCmd.class.getName()); 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 3f0d2467bf..48fe43ee84 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 @@ -58,6 +58,7 @@ import com.cloud.user.Account; @APICommand(name = "associateIpAddress", description = "Acquires and associates a public IP to an account.", responseObject = IPAddressResponse.class, responseView = ResponseView.Restricted, + entityType = {IpAddress.class, Vpc.class}, requestHasSensitiveInfo = false, responseHasSensitiveInfo = false) public class AssociateIPAddrCmd extends BaseAsyncCreateCmd { public static final Logger s_logger = Logger.getLogger(AssociateIPAddrCmd.class.getName()); @@ -201,10 +202,19 @@ public Long getNetworkId() { } } + @Deprecated public Boolean getDisplayIp() { return display; } + @Override + public boolean isDisplay() { + if(display == null) + return true; + else + return display; + } + @Override public long getEntityOwnerId() { Account caller = CallContext.current().getCallingAccount(); 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 269fcb552b..ba4184434e 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 @@ -37,7 +37,7 @@ import com.cloud.user.Account; @APICommand(name = "disassociateIpAddress", description = "Disassociates an ip address from the account.", responseObject = SuccessResponse.class, - requestHasSensitiveInfo = false, responseHasSensitiveInfo = false) + requestHasSensitiveInfo = false, responseHasSensitiveInfo = false, entityType = { IpAddress.class }) public class DisassociateIPAddrCmd extends BaseAsyncCmd { public static final Logger s_logger = Logger.getLogger(DisassociateIPAddrCmd.class.getName()); diff --git a/api/src/org/apache/cloudstack/api/command/user/address/ListPublicIpAddressesCmd.java b/api/src/org/apache/cloudstack/api/command/user/address/ListPublicIpAddressesCmd.java index 321871380d..07ccfe9918 100644 --- a/api/src/org/apache/cloudstack/api/command/user/address/ListPublicIpAddressesCmd.java +++ b/api/src/org/apache/cloudstack/api/command/user/address/ListPublicIpAddressesCmd.java @@ -40,7 +40,7 @@ import com.cloud.utils.Pair; @APICommand(name = "listPublicIpAddresses", description = "Lists all public ip addresses", responseObject = IPAddressResponse.class, responseView = ResponseView.Restricted, - requestHasSensitiveInfo = false, responseHasSensitiveInfo = false) + requestHasSensitiveInfo = false, responseHasSensitiveInfo = false, entityType = { IpAddress.class }) public class ListPublicIpAddressesCmd extends BaseListTaggedResourcesCmd { public static final Logger s_logger = Logger.getLogger(ListPublicIpAddressesCmd.class.getName()); diff --git a/api/src/org/apache/cloudstack/api/command/user/address/UpdateIPAddrCmd.java b/api/src/org/apache/cloudstack/api/command/user/address/UpdateIPAddrCmd.java index cc736d0d64..c64b6411c5 100644 --- a/api/src/org/apache/cloudstack/api/command/user/address/UpdateIPAddrCmd.java +++ b/api/src/org/apache/cloudstack/api/command/user/address/UpdateIPAddrCmd.java @@ -38,8 +38,8 @@ import com.cloud.network.IpAddress; import com.cloud.user.Account; -@APICommand(name = "updatePublicIpAddress", description = "Updates an ip address", responseObject = IPAddressResponse.class, - requestHasSensitiveInfo = false, responseHasSensitiveInfo = false) +@APICommand(name = "updateIpAddress", description = "Updates an ip address", responseObject = IPAddressResponse.class, + requestHasSensitiveInfo = false, responseHasSensitiveInfo = false, entityType = { IpAddress.class }) public class UpdateIPAddrCmd extends BaseAsyncCustomIdCmd { public static final Logger s_logger = Logger.getLogger(UpdateIPAddrCmd.class.getName()); private static final String s_name = "updateipaddressresponse"; diff --git a/api/src/org/apache/cloudstack/api/command/user/affinitygroup/CreateAffinityGroupCmd.java b/api/src/org/apache/cloudstack/api/command/user/affinitygroup/CreateAffinityGroupCmd.java index 50573e9683..96d8bec96d 100644 --- a/api/src/org/apache/cloudstack/api/command/user/affinitygroup/CreateAffinityGroupCmd.java +++ b/api/src/org/apache/cloudstack/api/command/user/affinitygroup/CreateAffinityGroupCmd.java @@ -18,7 +18,6 @@ import org.apache.log4j.Logger; -import org.apache.cloudstack.acl.IAMEntityType; import org.apache.cloudstack.affinity.AffinityGroup; import org.apache.cloudstack.affinity.AffinityGroupResponse; import org.apache.cloudstack.api.APICommand; @@ -35,7 +34,7 @@ import com.cloud.exception.ResourceAllocationException; import com.cloud.user.Account; -@APICommand(name = "createAffinityGroup", responseObject = AffinityGroupResponse.class, description = "Creates an affinity/anti-affinity group", entityType = {IAMEntityType.AffinityGroup}, +@APICommand(name = "createAffinityGroup", responseObject = AffinityGroupResponse.class, description = "Creates an affinity/anti-affinity group", entityType = {AffinityGroup.class}, requestHasSensitiveInfo = false, responseHasSensitiveInfo = false) public class CreateAffinityGroupCmd extends BaseAsyncCreateCmd { public static final Logger s_logger = Logger.getLogger(CreateAffinityGroupCmd.class.getName()); @@ -103,7 +102,7 @@ public String getCommandName() { @Override public long getEntityOwnerId() { Account account = CallContext.current().getCallingAccount(); - if ((account == null) || _accountService.isAdmin(account.getType())) { + if ((account == null) || _accountService.isAdmin(account.getId())) { if ((domainId != null) && (accountName != null)) { Account userAccount = _responseGenerator.findAccountByNameDomain(accountName, domainId); if (userAccount != null) { diff --git a/api/src/org/apache/cloudstack/api/command/user/affinitygroup/DeleteAffinityGroupCmd.java b/api/src/org/apache/cloudstack/api/command/user/affinitygroup/DeleteAffinityGroupCmd.java index 378a826ef8..21c2fa86d0 100644 --- a/api/src/org/apache/cloudstack/api/command/user/affinitygroup/DeleteAffinityGroupCmd.java +++ b/api/src/org/apache/cloudstack/api/command/user/affinitygroup/DeleteAffinityGroupCmd.java @@ -19,8 +19,8 @@ import org.apache.log4j.Logger; -import org.apache.cloudstack.acl.IAMEntityType; import org.apache.cloudstack.acl.SecurityChecker.AccessType; +import org.apache.cloudstack.affinity.AffinityGroup; import org.apache.cloudstack.affinity.AffinityGroupResponse; import org.apache.cloudstack.api.ACL; import org.apache.cloudstack.api.APICommand; @@ -38,7 +38,7 @@ import com.cloud.exception.InvalidParameterValueException; import com.cloud.user.Account; -@APICommand(name = "deleteAffinityGroup", description = "Deletes affinity group", responseObject = SuccessResponse.class, entityType = {IAMEntityType.AffinityGroup}, +@APICommand(name = "deleteAffinityGroup", description = "Deletes affinity group", responseObject = SuccessResponse.class, entityType = {AffinityGroup.class}, requestHasSensitiveInfo = false, responseHasSensitiveInfo = false) public class DeleteAffinityGroupCmd extends BaseAsyncCmd { public static final Logger s_logger = Logger.getLogger(DeleteAffinityGroupCmd.class.getName()); @@ -110,7 +110,7 @@ public String getCommandName() { @Override public long getEntityOwnerId() { Account account = CallContext.current().getCallingAccount(); - if ((account == null) || _accountService.isAdmin(account.getType())) { + if ((account == null) || _accountService.isAdmin(account.getId())) { if ((domainId != null) && (accountName != null)) { Account userAccount = _responseGenerator.findAccountByNameDomain(accountName, domainId); if (userAccount != null) { diff --git a/api/src/org/apache/cloudstack/api/command/user/affinitygroup/ListAffinityGroupsCmd.java b/api/src/org/apache/cloudstack/api/command/user/affinitygroup/ListAffinityGroupsCmd.java index e469eab2c1..6313c4812e 100644 --- a/api/src/org/apache/cloudstack/api/command/user/affinitygroup/ListAffinityGroupsCmd.java +++ b/api/src/org/apache/cloudstack/api/command/user/affinitygroup/ListAffinityGroupsCmd.java @@ -18,7 +18,7 @@ import org.apache.log4j.Logger; -import org.apache.cloudstack.acl.IAMEntityType; +import org.apache.cloudstack.affinity.AffinityGroup; import org.apache.cloudstack.affinity.AffinityGroupResponse; import org.apache.cloudstack.api.APICommand; import org.apache.cloudstack.api.ApiCommandJobType; @@ -28,7 +28,7 @@ import org.apache.cloudstack.api.response.ListResponse; import org.apache.cloudstack.api.response.UserVmResponse; -@APICommand(name = "listAffinityGroups", description = "Lists affinity groups", responseObject = AffinityGroupResponse.class, entityType = {IAMEntityType.AffinityGroup}, +@APICommand(name = "listAffinityGroups", description = "Lists affinity groups", responseObject = AffinityGroupResponse.class, entityType = {AffinityGroup.class}, requestHasSensitiveInfo = false, responseHasSensitiveInfo = false) public class ListAffinityGroupsCmd extends BaseListAccountResourcesCmd { public static final Logger s_logger = Logger.getLogger(ListAffinityGroupsCmd.class.getName()); diff --git a/api/src/org/apache/cloudstack/api/command/user/affinitygroup/UpdateVMAffinityGroupCmd.java b/api/src/org/apache/cloudstack/api/command/user/affinitygroup/UpdateVMAffinityGroupCmd.java index 4bfcddb3a6..66201477b9 100644 --- a/api/src/org/apache/cloudstack/api/command/user/affinitygroup/UpdateVMAffinityGroupCmd.java +++ b/api/src/org/apache/cloudstack/api/command/user/affinitygroup/UpdateVMAffinityGroupCmd.java @@ -22,7 +22,6 @@ import org.apache.log4j.Logger; -import org.apache.cloudstack.acl.IAMEntityType; import org.apache.cloudstack.acl.SecurityChecker.AccessType; import org.apache.cloudstack.affinity.AffinityGroupResponse; import org.apache.cloudstack.api.ACL; @@ -44,13 +43,14 @@ import com.cloud.exception.ResourceUnavailableException; import com.cloud.user.Account; import com.cloud.uservm.UserVm; +import com.cloud.vm.VirtualMachine; @APICommand(name = "updateVMAffinityGroup", description = "Updates the affinity/anti-affinity group associations of a virtual machine. The VM has to be stopped and restarted for the " + "new properties to take effect.", responseObject = UserVmResponse.class, responseView = ResponseView.Restricted, - entityType = {IAMEntityType.VirtualMachine}, + entityType = {VirtualMachine.class}, requestHasSensitiveInfo = false, responseHasSensitiveInfo = true) public class UpdateVMAffinityGroupCmd extends BaseAsyncCmd { diff --git a/api/src/org/apache/cloudstack/api/command/user/autoscale/CreateAutoScalePolicyCmd.java b/api/src/org/apache/cloudstack/api/command/user/autoscale/CreateAutoScalePolicyCmd.java index 8b5708d072..4541efa798 100644 --- a/api/src/org/apache/cloudstack/api/command/user/autoscale/CreateAutoScalePolicyCmd.java +++ b/api/src/org/apache/cloudstack/api/command/user/autoscale/CreateAutoScalePolicyCmd.java @@ -20,7 +20,6 @@ import org.apache.log4j.Logger; -import org.apache.cloudstack.acl.IAMEntityType; import org.apache.cloudstack.api.APICommand; import org.apache.cloudstack.api.ApiCommandJobType; import org.apache.cloudstack.api.ApiConstants; @@ -40,7 +39,7 @@ @APICommand(name = "createAutoScalePolicy", description = "Creates an autoscale policy for a provision or deprovision action, the action is taken when the all the conditions evaluates to true for the specified duration. The policy is in effect once it is attached to a autscale vm group.", - responseObject = AutoScalePolicyResponse.class, entityType = {IAMEntityType.AutoScalePolicy}, + responseObject = AutoScalePolicyResponse.class, entityType = {AutoScalePolicy.class}, requestHasSensitiveInfo = false, responseHasSensitiveInfo = false) public class CreateAutoScalePolicyCmd extends BaseAsyncCreateCmd { diff --git a/api/src/org/apache/cloudstack/api/command/user/autoscale/CreateAutoScaleVmGroupCmd.java b/api/src/org/apache/cloudstack/api/command/user/autoscale/CreateAutoScaleVmGroupCmd.java index 43a7f18189..0308c1710c 100644 --- a/api/src/org/apache/cloudstack/api/command/user/autoscale/CreateAutoScaleVmGroupCmd.java +++ b/api/src/org/apache/cloudstack/api/command/user/autoscale/CreateAutoScaleVmGroupCmd.java @@ -20,7 +20,6 @@ import org.apache.log4j.Logger; -import org.apache.cloudstack.acl.IAMEntityType; import org.apache.cloudstack.acl.RoleType; import org.apache.cloudstack.api.APICommand; import org.apache.cloudstack.api.ApiCommandJobType; @@ -42,7 +41,7 @@ @APICommand(name = "createAutoScaleVmGroup", description = "Creates and automatically starts a virtual machine based on a service offering, disk offering, and template.", - responseObject = AutoScaleVmGroupResponse.class, entityType = { IAMEntityType.AutoScaleVmGroup }, + responseObject = AutoScaleVmGroupResponse.class, entityType = {AutoScaleVmGroup.class}, requestHasSensitiveInfo = false, responseHasSensitiveInfo = false) public class CreateAutoScaleVmGroupCmd extends BaseAsyncCreateCmd { @@ -185,10 +184,19 @@ public ApiCommandJobType getInstanceType() { return ApiCommandJobType.AutoScaleVmGroup; } + @Deprecated public Boolean getDisplay() { return display; } + @Override + public boolean isDisplay() { + if(display == null) + return true; + else + return display; + } + @Override public void create() throws ResourceAllocationException { AutoScaleVmGroup result = _autoScaleService.createAutoScaleVmGroup(this); diff --git a/api/src/org/apache/cloudstack/api/command/user/autoscale/CreateAutoScaleVmProfileCmd.java b/api/src/org/apache/cloudstack/api/command/user/autoscale/CreateAutoScaleVmProfileCmd.java index 5d78593832..447085e79b 100644 --- a/api/src/org/apache/cloudstack/api/command/user/autoscale/CreateAutoScaleVmProfileCmd.java +++ b/api/src/org/apache/cloudstack/api/command/user/autoscale/CreateAutoScaleVmProfileCmd.java @@ -21,7 +21,6 @@ import org.apache.log4j.Logger; -import org.apache.cloudstack.acl.IAMEntityType; import org.apache.cloudstack.acl.RoleType; import org.apache.cloudstack.api.APICommand; import org.apache.cloudstack.api.ApiCommandJobType; @@ -46,7 +45,7 @@ @APICommand(name = "createAutoScaleVmProfile", description = "Creates a profile that contains information about the virtual machine which will be provisioned automatically by autoscale feature.", - responseObject = AutoScaleVmProfileResponse.class, entityType = { IAMEntityType.AutoScaleVmProfile }, + responseObject = AutoScaleVmProfileResponse.class, entityType = {AutoScaleVmProfile.class}, requestHasSensitiveInfo = false, responseHasSensitiveInfo = false) @SuppressWarnings("rawtypes") @@ -132,10 +131,19 @@ public Long getTemplateId() { return templateId; } + @Deprecated public Boolean getDisplay() { return display; } + @Override + public boolean isDisplay() { + if(display == null) + return true; + else + return display; + } + public Map getCounterParamList() { return counterParamList; } diff --git a/api/src/org/apache/cloudstack/api/command/user/autoscale/CreateConditionCmd.java b/api/src/org/apache/cloudstack/api/command/user/autoscale/CreateConditionCmd.java index b603a152d5..847866ef3a 100644 --- a/api/src/org/apache/cloudstack/api/command/user/autoscale/CreateConditionCmd.java +++ b/api/src/org/apache/cloudstack/api/command/user/autoscale/CreateConditionCmd.java @@ -19,7 +19,6 @@ import org.apache.log4j.Logger; -import org.apache.cloudstack.acl.IAMEntityType; import org.apache.cloudstack.api.APICommand; import org.apache.cloudstack.api.ApiCommandJobType; import org.apache.cloudstack.api.ApiConstants; @@ -36,7 +35,7 @@ import com.cloud.exception.ResourceAllocationException; import com.cloud.network.as.Condition; -@APICommand(name = "createCondition", description = "Creates a condition", responseObject = ConditionResponse.class, entityType = {IAMEntityType.Condition}, +@APICommand(name = "createCondition", description = "Creates a condition", responseObject = ConditionResponse.class, entityType = {Condition.class}, requestHasSensitiveInfo = false, responseHasSensitiveInfo = false) public class CreateConditionCmd extends BaseAsyncCreateCmd { public static final Logger s_logger = Logger.getLogger(CreateConditionCmd.class.getName()); diff --git a/api/src/org/apache/cloudstack/api/command/user/autoscale/DeleteAutoScalePolicyCmd.java b/api/src/org/apache/cloudstack/api/command/user/autoscale/DeleteAutoScalePolicyCmd.java index 779ee0a392..c0a3a00f7d 100644 --- a/api/src/org/apache/cloudstack/api/command/user/autoscale/DeleteAutoScalePolicyCmd.java +++ b/api/src/org/apache/cloudstack/api/command/user/autoscale/DeleteAutoScalePolicyCmd.java @@ -18,7 +18,6 @@ import org.apache.log4j.Logger; -import org.apache.cloudstack.acl.IAMEntityType; import org.apache.cloudstack.acl.SecurityChecker.AccessType; import org.apache.cloudstack.api.ACL; import org.apache.cloudstack.api.APICommand; @@ -36,7 +35,7 @@ import com.cloud.network.as.AutoScalePolicy; import com.cloud.user.Account; -@APICommand(name = "deleteAutoScalePolicy", description = "Deletes a autoscale policy.", responseObject = SuccessResponse.class, entityType = {IAMEntityType.AutoScalePolicy}, +@APICommand(name = "deleteAutoScalePolicy", description = "Deletes a autoscale policy.", responseObject = SuccessResponse.class, entityType = {AutoScalePolicy.class}, requestHasSensitiveInfo = false, responseHasSensitiveInfo = false) public class DeleteAutoScalePolicyCmd extends BaseAsyncCmd { public static final Logger s_logger = Logger.getLogger(DeleteAutoScalePolicyCmd.class.getName()); diff --git a/api/src/org/apache/cloudstack/api/command/user/autoscale/DeleteAutoScaleVmGroupCmd.java b/api/src/org/apache/cloudstack/api/command/user/autoscale/DeleteAutoScaleVmGroupCmd.java index 5a43abe866..a9d2f4e232 100644 --- a/api/src/org/apache/cloudstack/api/command/user/autoscale/DeleteAutoScaleVmGroupCmd.java +++ b/api/src/org/apache/cloudstack/api/command/user/autoscale/DeleteAutoScaleVmGroupCmd.java @@ -18,7 +18,6 @@ import org.apache.log4j.Logger; -import org.apache.cloudstack.acl.IAMEntityType; import org.apache.cloudstack.acl.SecurityChecker.AccessType; import org.apache.cloudstack.api.ACL; import org.apache.cloudstack.api.APICommand; @@ -36,7 +35,7 @@ import com.cloud.network.as.AutoScaleVmGroup; import com.cloud.user.Account; -@APICommand(name = "deleteAutoScaleVmGroup", description = "Deletes a autoscale vm group.", responseObject = SuccessResponse.class, entityType = {IAMEntityType.AutoScaleVmGroup}, +@APICommand(name = "deleteAutoScaleVmGroup", description = "Deletes a autoscale vm group.", responseObject = SuccessResponse.class, entityType = {AutoScaleVmGroup.class}, requestHasSensitiveInfo = false, responseHasSensitiveInfo = false) public class DeleteAutoScaleVmGroupCmd extends BaseAsyncCmd { public static final Logger s_logger = Logger.getLogger(DeleteAutoScaleVmGroupCmd.class.getName()); diff --git a/api/src/org/apache/cloudstack/api/command/user/autoscale/DeleteAutoScaleVmProfileCmd.java b/api/src/org/apache/cloudstack/api/command/user/autoscale/DeleteAutoScaleVmProfileCmd.java index 2391a938d8..779315a96d 100644 --- a/api/src/org/apache/cloudstack/api/command/user/autoscale/DeleteAutoScaleVmProfileCmd.java +++ b/api/src/org/apache/cloudstack/api/command/user/autoscale/DeleteAutoScaleVmProfileCmd.java @@ -18,7 +18,6 @@ import org.apache.log4j.Logger; -import org.apache.cloudstack.acl.IAMEntityType; import org.apache.cloudstack.acl.SecurityChecker.AccessType; import org.apache.cloudstack.api.ACL; import org.apache.cloudstack.api.APICommand; @@ -36,7 +35,7 @@ import com.cloud.network.as.AutoScaleVmProfile; import com.cloud.user.Account; -@APICommand(name = "deleteAutoScaleVmProfile", description = "Deletes a autoscale vm profile.", responseObject = SuccessResponse.class, entityType = {IAMEntityType.AutoScaleVmProfile}, +@APICommand(name = "deleteAutoScaleVmProfile", description = "Deletes a autoscale vm profile.", responseObject = SuccessResponse.class, entityType = {AutoScaleVmProfile.class}, requestHasSensitiveInfo = false, responseHasSensitiveInfo = false) public class DeleteAutoScaleVmProfileCmd extends BaseAsyncCmd { public static final Logger s_logger = Logger.getLogger(DeleteAutoScaleVmProfileCmd.class.getName()); diff --git a/api/src/org/apache/cloudstack/api/command/user/autoscale/DeleteConditionCmd.java b/api/src/org/apache/cloudstack/api/command/user/autoscale/DeleteConditionCmd.java index 9a7d2d7df8..24f4cc6878 100644 --- a/api/src/org/apache/cloudstack/api/command/user/autoscale/DeleteConditionCmd.java +++ b/api/src/org/apache/cloudstack/api/command/user/autoscale/DeleteConditionCmd.java @@ -19,7 +19,6 @@ import org.apache.log4j.Logger; -import org.apache.cloudstack.acl.IAMEntityType; import org.apache.cloudstack.acl.SecurityChecker.AccessType; import org.apache.cloudstack.api.ACL; import org.apache.cloudstack.api.APICommand; @@ -37,7 +36,7 @@ import com.cloud.network.as.Condition; import com.cloud.user.Account; -@APICommand(name = "deleteCondition", description = "Removes a condition", responseObject = SuccessResponse.class, entityType = {IAMEntityType.Condition}, +@APICommand(name = "deleteCondition", description = "Removes a condition", responseObject = SuccessResponse.class, entityType = {Condition.class}, requestHasSensitiveInfo = false, responseHasSensitiveInfo = false) public class DeleteConditionCmd extends BaseAsyncCmd { public static final Logger s_logger = Logger.getLogger(DeleteConditionCmd.class.getName()); diff --git a/api/src/org/apache/cloudstack/api/command/user/autoscale/DisableAutoScaleVmGroupCmd.java b/api/src/org/apache/cloudstack/api/command/user/autoscale/DisableAutoScaleVmGroupCmd.java index 6575d27ba7..8eb1809f88 100644 --- a/api/src/org/apache/cloudstack/api/command/user/autoscale/DisableAutoScaleVmGroupCmd.java +++ b/api/src/org/apache/cloudstack/api/command/user/autoscale/DisableAutoScaleVmGroupCmd.java @@ -19,7 +19,6 @@ import org.apache.log4j.Logger; -import org.apache.cloudstack.acl.IAMEntityType; import org.apache.cloudstack.acl.SecurityChecker.AccessType; import org.apache.cloudstack.api.ACL; import org.apache.cloudstack.api.APICommand; @@ -35,7 +34,7 @@ import com.cloud.network.as.AutoScaleVmGroup; import com.cloud.user.Account; -@APICommand(name = "disableAutoScaleVmGroup", description = "Disables an AutoScale Vm Group", responseObject = AutoScaleVmGroupResponse.class, entityType = {IAMEntityType.AutoScaleVmGroup}, +@APICommand(name = "disableAutoScaleVmGroup", description = "Disables an AutoScale Vm Group", responseObject = AutoScaleVmGroupResponse.class, entityType = {AutoScaleVmGroup.class}, requestHasSensitiveInfo = false, responseHasSensitiveInfo = false) public class DisableAutoScaleVmGroupCmd extends BaseAsyncCmd { public static final Logger s_logger = Logger.getLogger(DisableAutoScaleVmGroupCmd.class.getName()); diff --git a/api/src/org/apache/cloudstack/api/command/user/autoscale/EnableAutoScaleVmGroupCmd.java b/api/src/org/apache/cloudstack/api/command/user/autoscale/EnableAutoScaleVmGroupCmd.java index 6b9f2c3ac0..59c9f7a9aa 100644 --- a/api/src/org/apache/cloudstack/api/command/user/autoscale/EnableAutoScaleVmGroupCmd.java +++ b/api/src/org/apache/cloudstack/api/command/user/autoscale/EnableAutoScaleVmGroupCmd.java @@ -19,7 +19,6 @@ import org.apache.log4j.Logger; -import org.apache.cloudstack.acl.IAMEntityType; import org.apache.cloudstack.acl.SecurityChecker.AccessType; import org.apache.cloudstack.api.ACL; import org.apache.cloudstack.api.APICommand; @@ -35,7 +34,7 @@ import com.cloud.network.as.AutoScaleVmGroup; import com.cloud.user.Account; -@APICommand(name = "enableAutoScaleVmGroup", description = "Enables an AutoScale Vm Group", responseObject = AutoScaleVmGroupResponse.class, entityType = {IAMEntityType.AutoScaleVmGroup}, +@APICommand(name = "enableAutoScaleVmGroup", description = "Enables an AutoScale Vm Group", responseObject = AutoScaleVmGroupResponse.class, entityType = {AutoScaleVmGroup.class}, requestHasSensitiveInfo = false, responseHasSensitiveInfo = false) public class EnableAutoScaleVmGroupCmd extends BaseAsyncCmd { public static final Logger s_logger = Logger.getLogger(EnableAutoScaleVmGroupCmd.class.getName()); diff --git a/api/src/org/apache/cloudstack/api/command/user/autoscale/ListAutoScalePoliciesCmd.java b/api/src/org/apache/cloudstack/api/command/user/autoscale/ListAutoScalePoliciesCmd.java index 43c4c72a80..c2b244f2a7 100644 --- a/api/src/org/apache/cloudstack/api/command/user/autoscale/ListAutoScalePoliciesCmd.java +++ b/api/src/org/apache/cloudstack/api/command/user/autoscale/ListAutoScalePoliciesCmd.java @@ -21,7 +21,6 @@ import org.apache.log4j.Logger; -import org.apache.cloudstack.acl.IAMEntityType; import org.apache.cloudstack.api.APICommand; import org.apache.cloudstack.api.ApiConstants; import org.apache.cloudstack.api.BaseListAccountResourcesCmd; @@ -33,7 +32,7 @@ import com.cloud.network.as.AutoScalePolicy; -@APICommand(name = "listAutoScalePolicies", description = "Lists autoscale policies.", responseObject = AutoScalePolicyResponse.class, entityType = {IAMEntityType.AutoScalePolicy}, +@APICommand(name = "listAutoScalePolicies", description = "Lists autoscale policies.", responseObject = AutoScalePolicyResponse.class, entityType = {AutoScalePolicy.class}, requestHasSensitiveInfo = false, responseHasSensitiveInfo = false) public class ListAutoScalePoliciesCmd extends BaseListAccountResourcesCmd { public static final Logger s_logger = Logger.getLogger(ListAutoScalePoliciesCmd.class.getName()); diff --git a/api/src/org/apache/cloudstack/api/command/user/autoscale/ListAutoScaleVmGroupsCmd.java b/api/src/org/apache/cloudstack/api/command/user/autoscale/ListAutoScaleVmGroupsCmd.java index 2e88c27b7d..37c90b9bfd 100644 --- a/api/src/org/apache/cloudstack/api/command/user/autoscale/ListAutoScaleVmGroupsCmd.java +++ b/api/src/org/apache/cloudstack/api/command/user/autoscale/ListAutoScaleVmGroupsCmd.java @@ -21,7 +21,6 @@ import org.apache.log4j.Logger; -import org.apache.cloudstack.acl.IAMEntityType; import org.apache.cloudstack.acl.RoleType; import org.apache.cloudstack.api.APICommand; import org.apache.cloudstack.api.ApiConstants; @@ -37,7 +36,7 @@ import com.cloud.exception.InvalidParameterValueException; import com.cloud.network.as.AutoScaleVmGroup; -@APICommand(name = "listAutoScaleVmGroups", description = "Lists autoscale vm groups.", responseObject = AutoScaleVmGroupResponse.class, entityType = { IAMEntityType.AutoScaleVmGroup }, +@APICommand(name = "listAutoScaleVmGroups", description = "Lists autoscale vm groups.", responseObject = AutoScaleVmGroupResponse.class, entityType = {AutoScaleVmGroup.class}, requestHasSensitiveInfo = false, responseHasSensitiveInfo = false) public class ListAutoScaleVmGroupsCmd extends BaseListProjectAndAccountResourcesCmd { public static final Logger s_logger = Logger.getLogger(ListAutoScaleVmGroupsCmd.class.getName()); diff --git a/api/src/org/apache/cloudstack/api/command/user/autoscale/ListAutoScaleVmProfilesCmd.java b/api/src/org/apache/cloudstack/api/command/user/autoscale/ListAutoScaleVmProfilesCmd.java index 94f0eee7f5..554b48854a 100644 --- a/api/src/org/apache/cloudstack/api/command/user/autoscale/ListAutoScaleVmProfilesCmd.java +++ b/api/src/org/apache/cloudstack/api/command/user/autoscale/ListAutoScaleVmProfilesCmd.java @@ -21,7 +21,6 @@ import org.apache.log4j.Logger; -import org.apache.cloudstack.acl.IAMEntityType; import org.apache.cloudstack.acl.RoleType; import org.apache.cloudstack.api.APICommand; import org.apache.cloudstack.api.ApiConstants; @@ -35,7 +34,7 @@ import com.cloud.network.as.AutoScaleVmProfile; -@APICommand(name = "listAutoScaleVmProfiles", description = "Lists autoscale vm profiles.", responseObject = AutoScaleVmProfileResponse.class, entityType = { IAMEntityType.AutoScaleVmProfile }, +@APICommand(name = "listAutoScaleVmProfiles", description = "Lists autoscale vm profiles.", responseObject = AutoScaleVmProfileResponse.class, entityType = {AutoScaleVmProfile.class}, requestHasSensitiveInfo = false, responseHasSensitiveInfo = false) public class ListAutoScaleVmProfilesCmd extends BaseListProjectAndAccountResourcesCmd { public static final Logger s_logger = Logger.getLogger(ListAutoScaleVmProfilesCmd.class.getName()); @@ -52,7 +51,7 @@ public class ListAutoScaleVmProfilesCmd extends BaseListProjectAndAccountResourc @Parameter(name = ApiConstants.TEMPLATE_ID, type = CommandType.UUID, entityType = TemplateResponse.class, description = "the templateid of the autoscale vm profile") private Long templateId; - @Parameter(name = ApiConstants.SERVICE_OFFERING_ID, type = CommandType.UUID, entityType = ServiceOfferingResponse.class, description = "list profiles by service offering id") + @Parameter(name = ApiConstants.SERVICE_OFFERING_ID, type = CommandType.UUID, entityType = ServiceOfferingResponse.class, description = "list profiles by service offering id", since = "4.4") private Long serviceOffId; @Parameter(name = ApiConstants.OTHER_DEPLOY_PARAMS, type = CommandType.STRING, description = "the otherdeployparameters of the autoscale vm profile") diff --git a/api/src/org/apache/cloudstack/api/command/user/autoscale/UpdateAutoScalePolicyCmd.java b/api/src/org/apache/cloudstack/api/command/user/autoscale/UpdateAutoScalePolicyCmd.java index 8cd7211a2f..24858f4656 100644 --- a/api/src/org/apache/cloudstack/api/command/user/autoscale/UpdateAutoScalePolicyCmd.java +++ b/api/src/org/apache/cloudstack/api/command/user/autoscale/UpdateAutoScalePolicyCmd.java @@ -21,7 +21,6 @@ import org.apache.log4j.Logger; -import org.apache.cloudstack.acl.IAMEntityType; import org.apache.cloudstack.acl.SecurityChecker.AccessType; import org.apache.cloudstack.api.ACL; import org.apache.cloudstack.api.APICommand; @@ -39,7 +38,7 @@ import com.cloud.network.as.AutoScalePolicy; import com.cloud.user.Account; -@APICommand(name = "updateAutoScalePolicy", description = "Updates an existing autoscale policy.", responseObject = AutoScalePolicyResponse.class, entityType = {IAMEntityType.AutoScalePolicy}, +@APICommand(name = "updateAutoScalePolicy", description = "Updates an existing autoscale policy.", responseObject = AutoScalePolicyResponse.class, entityType = {AutoScalePolicy.class}, requestHasSensitiveInfo = false, responseHasSensitiveInfo = false) public class UpdateAutoScalePolicyCmd extends BaseAsyncCmd { public static final Logger s_logger = Logger.getLogger(UpdateAutoScalePolicyCmd.class.getName()); diff --git a/api/src/org/apache/cloudstack/api/command/user/autoscale/UpdateAutoScaleVmGroupCmd.java b/api/src/org/apache/cloudstack/api/command/user/autoscale/UpdateAutoScaleVmGroupCmd.java index 60ea51efc9..76fa3d75d1 100644 --- a/api/src/org/apache/cloudstack/api/command/user/autoscale/UpdateAutoScaleVmGroupCmd.java +++ b/api/src/org/apache/cloudstack/api/command/user/autoscale/UpdateAutoScaleVmGroupCmd.java @@ -21,7 +21,6 @@ import org.apache.log4j.Logger; -import org.apache.cloudstack.acl.IAMEntityType; import org.apache.cloudstack.acl.RoleType; import org.apache.cloudstack.acl.SecurityChecker.AccessType; import org.apache.cloudstack.api.ACL; @@ -40,7 +39,7 @@ import com.cloud.network.as.AutoScaleVmGroup; import com.cloud.user.Account; -@APICommand(name = "updateAutoScaleVmGroup", description = "Updates an existing autoscale vm group.", responseObject = AutoScaleVmGroupResponse.class, entityType = { IAMEntityType.AutoScaleVmGroup }, +@APICommand(name = "updateAutoScaleVmGroup", description = "Updates an existing autoscale vm group.", responseObject = AutoScaleVmGroupResponse.class, entityType = {AutoScaleVmGroup.class}, requestHasSensitiveInfo = false, responseHasSensitiveInfo = false) public class UpdateAutoScaleVmGroupCmd extends BaseAsyncCustomIdCmd { public static final Logger s_logger = Logger.getLogger(UpdateAutoScaleVmGroupCmd.class.getName()); diff --git a/api/src/org/apache/cloudstack/api/command/user/autoscale/UpdateAutoScaleVmProfileCmd.java b/api/src/org/apache/cloudstack/api/command/user/autoscale/UpdateAutoScaleVmProfileCmd.java index 54e34da196..deebe2ecc9 100644 --- a/api/src/org/apache/cloudstack/api/command/user/autoscale/UpdateAutoScaleVmProfileCmd.java +++ b/api/src/org/apache/cloudstack/api/command/user/autoscale/UpdateAutoScaleVmProfileCmd.java @@ -21,7 +21,6 @@ import org.apache.log4j.Logger; -import org.apache.cloudstack.acl.IAMEntityType; import org.apache.cloudstack.acl.RoleType; import org.apache.cloudstack.acl.SecurityChecker.AccessType; import org.apache.cloudstack.api.ACL; @@ -41,7 +40,7 @@ import com.cloud.network.as.AutoScaleVmProfile; import com.cloud.user.Account; -@APICommand(name = "updateAutoScaleVmProfile", description = "Updates an existing autoscale vm profile.", responseObject = AutoScaleVmProfileResponse.class, entityType = { IAMEntityType.AutoScaleVmProfile }, +@APICommand(name = "updateAutoScaleVmProfile", description = "Updates an existing autoscale vm profile.", responseObject = AutoScaleVmProfileResponse.class, entityType = {AutoScaleVmProfile.class}, requestHasSensitiveInfo = false, responseHasSensitiveInfo = false) public class UpdateAutoScaleVmProfileCmd extends BaseAsyncCustomIdCmd { public static final Logger s_logger = Logger.getLogger(UpdateAutoScaleVmProfileCmd.class.getName()); diff --git a/api/src/org/apache/cloudstack/api/command/user/config/ListCapabilitiesCmd.java b/api/src/org/apache/cloudstack/api/command/user/config/ListCapabilitiesCmd.java index d47645b956..e6696e17ff 100644 --- a/api/src/org/apache/cloudstack/api/command/user/config/ListCapabilitiesCmd.java +++ b/api/src/org/apache/cloudstack/api/command/user/config/ListCapabilitiesCmd.java @@ -53,6 +53,7 @@ public void execute() { response.setSupportELB((String)capabilities.get("supportELB")); response.setProjectInviteRequired((Boolean)capabilities.get("projectInviteRequired")); response.setAllowUsersCreateProjects((Boolean)capabilities.get("allowusercreateprojects")); + response.setDiskOffMinSize((Long)capabilities.get("customDiskOffMinSize")); response.setDiskOffMaxSize((Long)capabilities.get("customDiskOffMaxSize")); response.setRegionSecondaryEnabled((Boolean)capabilities.get("regionSecondaryEnabled")); response.setKVMSnapshotEnabled((Boolean)capabilities.get("KVMSnapshotEnabled")); diff --git a/api/src/org/apache/cloudstack/api/command/user/event/ArchiveEventsCmd.java b/api/src/org/apache/cloudstack/api/command/user/event/ArchiveEventsCmd.java index 8ff2c3e445..e4970d6530 100644 --- a/api/src/org/apache/cloudstack/api/command/user/event/ArchiveEventsCmd.java +++ b/api/src/org/apache/cloudstack/api/command/user/event/ArchiveEventsCmd.java @@ -21,7 +21,6 @@ import org.apache.log4j.Logger; -import org.apache.cloudstack.acl.IAMEntityType; import org.apache.cloudstack.api.APICommand; import org.apache.cloudstack.api.ApiConstants; import org.apache.cloudstack.api.ApiErrorCode; @@ -32,10 +31,11 @@ import org.apache.cloudstack.api.response.SuccessResponse; import org.apache.cloudstack.context.CallContext; +import com.cloud.event.Event; import com.cloud.exception.InvalidParameterValueException; import com.cloud.user.Account; -@APICommand(name = "archiveEvents", description = "Archive one or more events.", responseObject = SuccessResponse.class, entityType = {IAMEntityType.Event}, +@APICommand(name = "archiveEvents", description = "Archive one or more events.", responseObject = SuccessResponse.class, entityType = {Event.class}, requestHasSensitiveInfo = false, responseHasSensitiveInfo = false) public class ArchiveEventsCmd extends BaseCmd { diff --git a/api/src/org/apache/cloudstack/api/command/user/event/DeleteEventsCmd.java b/api/src/org/apache/cloudstack/api/command/user/event/DeleteEventsCmd.java index 10c1c0c860..defb009696 100644 --- a/api/src/org/apache/cloudstack/api/command/user/event/DeleteEventsCmd.java +++ b/api/src/org/apache/cloudstack/api/command/user/event/DeleteEventsCmd.java @@ -21,7 +21,6 @@ import org.apache.log4j.Logger; -import org.apache.cloudstack.acl.IAMEntityType; import org.apache.cloudstack.api.APICommand; import org.apache.cloudstack.api.ApiConstants; import org.apache.cloudstack.api.ApiErrorCode; @@ -32,10 +31,11 @@ import org.apache.cloudstack.api.response.SuccessResponse; import org.apache.cloudstack.context.CallContext; +import com.cloud.event.Event; import com.cloud.exception.InvalidParameterValueException; import com.cloud.user.Account; -@APICommand(name = "deleteEvents", description = "Delete one or more events.", responseObject = SuccessResponse.class, entityType = {IAMEntityType.Event}, +@APICommand(name = "deleteEvents", description = "Delete one or more events.", responseObject = SuccessResponse.class, entityType = {Event.class}, requestHasSensitiveInfo = false, responseHasSensitiveInfo = false) public class DeleteEventsCmd extends BaseCmd { diff --git a/api/src/org/apache/cloudstack/api/command/user/event/ListEventsCmd.java b/api/src/org/apache/cloudstack/api/command/user/event/ListEventsCmd.java index b420cf1ed2..a4934fa1dd 100644 --- a/api/src/org/apache/cloudstack/api/command/user/event/ListEventsCmd.java +++ b/api/src/org/apache/cloudstack/api/command/user/event/ListEventsCmd.java @@ -20,7 +20,6 @@ import org.apache.log4j.Logger; -import org.apache.cloudstack.acl.IAMEntityType; import org.apache.cloudstack.api.APICommand; import org.apache.cloudstack.api.ApiConstants; import org.apache.cloudstack.api.BaseListProjectAndAccountResourcesCmd; @@ -28,7 +27,9 @@ import org.apache.cloudstack.api.response.EventResponse; import org.apache.cloudstack.api.response.ListResponse; -@APICommand(name = "listEvents", description = "A command to list events.", responseObject = EventResponse.class, entityType = {IAMEntityType.Event}, +import com.cloud.event.Event; + +@APICommand(name = "listEvents", description = "A command to list events.", responseObject = EventResponse.class, entityType = {Event.class}, requestHasSensitiveInfo = false, responseHasSensitiveInfo = false) public class ListEventsCmd extends BaseListProjectAndAccountResourcesCmd { public static final Logger s_logger = Logger.getLogger(ListEventsCmd.class.getName()); diff --git a/api/src/org/apache/cloudstack/api/command/user/firewall/CreateEgressFirewallRuleCmd.java b/api/src/org/apache/cloudstack/api/command/user/firewall/CreateEgressFirewallRuleCmd.java index 8ef1b89518..579cccbfb2 100644 --- a/api/src/org/apache/cloudstack/api/command/user/firewall/CreateEgressFirewallRuleCmd.java +++ b/api/src/org/apache/cloudstack/api/command/user/firewall/CreateEgressFirewallRuleCmd.java @@ -22,7 +22,6 @@ import org.apache.log4j.Logger; -import org.apache.cloudstack.acl.IAMEntityType; import org.apache.cloudstack.acl.RoleType; import org.apache.cloudstack.api.APICommand; import org.apache.cloudstack.api.ApiCommandJobType; @@ -45,7 +44,7 @@ import com.cloud.user.Account; import com.cloud.utils.net.NetUtils; -@APICommand(name = "createEgressFirewallRule", description = "Creates a egress firewall rule for a given network ", responseObject = FirewallResponse.class, entityType = { IAMEntityType.FirewallRule }, +@APICommand(name = "createEgressFirewallRule", description = "Creates a egress firewall rule for a given network ", responseObject = FirewallResponse.class, entityType = {FirewallRule.class}, requestHasSensitiveInfo = false, responseHasSensitiveInfo = false) public class CreateEgressFirewallRuleCmd extends BaseAsyncCreateCmd implements FirewallRule { public static final Logger s_logger = Logger.getLogger(CreateEgressFirewallRuleCmd.class.getName()); @@ -357,8 +356,8 @@ public boolean isDisplay() { } @Override - public IAMEntityType getEntityType() { - return IAMEntityType.FirewallRule; + public Class getEntityType() { + return FirewallRule.class; } } diff --git a/api/src/org/apache/cloudstack/api/command/user/firewall/CreateFirewallRuleCmd.java b/api/src/org/apache/cloudstack/api/command/user/firewall/CreateFirewallRuleCmd.java index 21e680ae62..b09d3a73a7 100644 --- a/api/src/org/apache/cloudstack/api/command/user/firewall/CreateFirewallRuleCmd.java +++ b/api/src/org/apache/cloudstack/api/command/user/firewall/CreateFirewallRuleCmd.java @@ -21,7 +21,6 @@ import org.apache.log4j.Logger; -import org.apache.cloudstack.acl.IAMEntityType; import org.apache.cloudstack.acl.RoleType; import org.apache.cloudstack.api.APICommand; import org.apache.cloudstack.api.ApiCommandJobType; @@ -44,7 +43,7 @@ import com.cloud.user.Account; import com.cloud.utils.net.NetUtils; -@APICommand(name = "createFirewallRule", description = "Creates a firewall rule for a given ip address", responseObject = FirewallResponse.class, entityType = { IAMEntityType.FirewallRule }, +@APICommand(name = "createFirewallRule", description = "Creates a firewall rule for a given ip address", responseObject = FirewallResponse.class, entityType = {FirewallRule.class}, requestHasSensitiveInfo = false, responseHasSensitiveInfo = false) public class CreateFirewallRuleCmd extends BaseAsyncCreateCmd implements FirewallRule { public static final Logger s_logger = Logger.getLogger(CreateFirewallRuleCmd.class.getName()); @@ -350,8 +349,8 @@ public boolean isDisplay() { } @Override - public IAMEntityType getEntityType() { - return IAMEntityType.FirewallRule; + public Class getEntityType() { + return FirewallRule.class; } } diff --git a/api/src/org/apache/cloudstack/api/command/user/firewall/CreatePortForwardingRuleCmd.java b/api/src/org/apache/cloudstack/api/command/user/firewall/CreatePortForwardingRuleCmd.java index 7328374f5c..6fb120fa8b 100644 --- a/api/src/org/apache/cloudstack/api/command/user/firewall/CreatePortForwardingRuleCmd.java +++ b/api/src/org/apache/cloudstack/api/command/user/firewall/CreatePortForwardingRuleCmd.java @@ -20,8 +20,9 @@ import org.apache.log4j.Logger; -import org.apache.cloudstack.acl.IAMEntityType; import org.apache.cloudstack.acl.RoleType; +import org.apache.cloudstack.acl.SecurityChecker.AccessType; +import org.apache.cloudstack.api.ACL; import org.apache.cloudstack.api.APICommand; import org.apache.cloudstack.api.ApiCommandJobType; import org.apache.cloudstack.api.ApiConstants; @@ -41,12 +42,15 @@ import com.cloud.exception.NetworkRuleConflictException; import com.cloud.exception.ResourceUnavailableException; import com.cloud.network.IpAddress; +import com.cloud.network.rules.FirewallRule; import com.cloud.network.rules.PortForwardingRule; import com.cloud.user.Account; import com.cloud.utils.net.Ip; import com.cloud.utils.net.NetUtils; +import com.cloud.vm.VirtualMachine; -@APICommand(name = "createPortForwardingRule", description = "Creates a port forwarding rule", responseObject = FirewallRuleResponse.class, entityType = { IAMEntityType.PortForwardingRule }, +@APICommand(name = "createPortForwardingRule", description = "Creates a port forwarding rule", responseObject = FirewallRuleResponse.class, entityType = {FirewallRule.class, + VirtualMachine.class, IpAddress.class}, requestHasSensitiveInfo = false, responseHasSensitiveInfo = false) public class CreatePortForwardingRuleCmd extends BaseAsyncCreateCmd implements PortForwardingRule { public static final Logger s_logger = Logger.getLogger(CreatePortForwardingRuleCmd.class.getName()); @@ -57,6 +61,7 @@ public class CreatePortForwardingRuleCmd extends BaseAsyncCreateCmd implements P // ////////////// API parameters ///////////////////// // /////////////////////////////////////////////////// + @ACL(accessType = AccessType.OperateEntry) @Parameter(name = ApiConstants.IP_ADDRESS_ID, type = CommandType.UUID, entityType = IPAddressResponse.class, @@ -94,6 +99,7 @@ public class CreatePortForwardingRuleCmd extends BaseAsyncCreateCmd implements P description = "the ending port of port forwarding rule's private port range") private Integer publicEndPort; + @ACL(accessType = AccessType.OperateEntry) @Parameter(name = ApiConstants.VIRTUAL_MACHINE_ID, type = CommandType.UUID, entityType = UserVmResponse.class, @@ -432,8 +438,8 @@ public boolean isDisplay() { } @Override - public IAMEntityType getEntityType() { - return IAMEntityType.FirewallRule; + public Class getEntityType() { + return FirewallRule.class; } } diff --git a/api/src/org/apache/cloudstack/api/command/user/firewall/DeleteEgressFirewallRuleCmd.java b/api/src/org/apache/cloudstack/api/command/user/firewall/DeleteEgressFirewallRuleCmd.java index ebed335ba3..4d227722f8 100644 --- a/api/src/org/apache/cloudstack/api/command/user/firewall/DeleteEgressFirewallRuleCmd.java +++ b/api/src/org/apache/cloudstack/api/command/user/firewall/DeleteEgressFirewallRuleCmd.java @@ -19,7 +19,6 @@ import org.apache.log4j.Logger; -import org.apache.cloudstack.acl.IAMEntityType; import org.apache.cloudstack.acl.SecurityChecker.AccessType; import org.apache.cloudstack.api.ACL; import org.apache.cloudstack.api.APICommand; @@ -39,7 +38,7 @@ import com.cloud.exception.ResourceUnavailableException; import com.cloud.network.rules.FirewallRule; -@APICommand(name = "deleteEgressFirewallRule", description = "Deletes an ggress firewall rule", responseObject = SuccessResponse.class, entityType = {IAMEntityType.FirewallRule}, +@APICommand(name = "deleteEgressFirewallRule", description = "Deletes an ggress firewall rule", responseObject = SuccessResponse.class, entityType = {FirewallRule.class}, requestHasSensitiveInfo = false, responseHasSensitiveInfo = false) public class DeleteEgressFirewallRuleCmd extends BaseAsyncCmd { public static final Logger s_logger = Logger.getLogger(DeleteEgressFirewallRuleCmd.class.getName()); diff --git a/api/src/org/apache/cloudstack/api/command/user/firewall/DeleteFirewallRuleCmd.java b/api/src/org/apache/cloudstack/api/command/user/firewall/DeleteFirewallRuleCmd.java index 3f61e640c8..66dcc039c3 100644 --- a/api/src/org/apache/cloudstack/api/command/user/firewall/DeleteFirewallRuleCmd.java +++ b/api/src/org/apache/cloudstack/api/command/user/firewall/DeleteFirewallRuleCmd.java @@ -18,7 +18,6 @@ import org.apache.log4j.Logger; -import org.apache.cloudstack.acl.IAMEntityType; import org.apache.cloudstack.acl.SecurityChecker.AccessType; import org.apache.cloudstack.api.ACL; import org.apache.cloudstack.api.APICommand; @@ -38,7 +37,7 @@ import com.cloud.exception.ResourceUnavailableException; import com.cloud.network.rules.FirewallRule; -@APICommand(name = "deleteFirewallRule", description = "Deletes a firewall rule", responseObject = SuccessResponse.class, entityType = {IAMEntityType.FirewallRule}, +@APICommand(name = "deleteFirewallRule", description = "Deletes a firewall rule", responseObject = SuccessResponse.class, entityType = {FirewallRule.class}, requestHasSensitiveInfo = false, responseHasSensitiveInfo = false) public class DeleteFirewallRuleCmd extends BaseAsyncCmd { public static final Logger s_logger = Logger.getLogger(DeleteFirewallRuleCmd.class.getName()); diff --git a/api/src/org/apache/cloudstack/api/command/user/firewall/DeletePortForwardingRuleCmd.java b/api/src/org/apache/cloudstack/api/command/user/firewall/DeletePortForwardingRuleCmd.java index 551885d017..4c7b07f14f 100644 --- a/api/src/org/apache/cloudstack/api/command/user/firewall/DeletePortForwardingRuleCmd.java +++ b/api/src/org/apache/cloudstack/api/command/user/firewall/DeletePortForwardingRuleCmd.java @@ -18,7 +18,6 @@ import org.apache.log4j.Logger; -import org.apache.cloudstack.acl.IAMEntityType; import org.apache.cloudstack.acl.SecurityChecker.AccessType; import org.apache.cloudstack.api.ACL; import org.apache.cloudstack.api.APICommand; @@ -37,7 +36,7 @@ import com.cloud.exception.InvalidParameterValueException; import com.cloud.network.rules.PortForwardingRule; -@APICommand(name = "deletePortForwardingRule", description = "Deletes a port forwarding rule", responseObject = SuccessResponse.class, entityType = {IAMEntityType.PortForwardingRule}, +@APICommand(name = "deletePortForwardingRule", description = "Deletes a port forwarding rule", responseObject = SuccessResponse.class, entityType = {PortForwardingRule.class}, requestHasSensitiveInfo = false, responseHasSensitiveInfo = false) public class DeletePortForwardingRuleCmd extends BaseAsyncCmd { public static final Logger s_logger = Logger.getLogger(DeletePortForwardingRuleCmd.class.getName()); diff --git a/api/src/org/apache/cloudstack/api/command/user/firewall/ListEgressFirewallRulesCmd.java b/api/src/org/apache/cloudstack/api/command/user/firewall/ListEgressFirewallRulesCmd.java index ece2201a89..e31496e474 100644 --- a/api/src/org/apache/cloudstack/api/command/user/firewall/ListEgressFirewallRulesCmd.java +++ b/api/src/org/apache/cloudstack/api/command/user/firewall/ListEgressFirewallRulesCmd.java @@ -22,7 +22,6 @@ import org.apache.log4j.Logger; -import org.apache.cloudstack.acl.IAMEntityType; import org.apache.cloudstack.api.APICommand; import org.apache.cloudstack.api.ApiConstants; import org.apache.cloudstack.api.Parameter; @@ -34,7 +33,7 @@ import com.cloud.network.rules.FirewallRule; import com.cloud.utils.Pair; -@APICommand(name = "listEgressFirewallRules", description = "Lists all egress firewall rules for network id.", responseObject = FirewallResponse.class, entityType = { IAMEntityType.FirewallRule }, +@APICommand(name = "listEgressFirewallRules", description = "Lists all egress firewall rules for network id.", responseObject = FirewallResponse.class, entityType = {FirewallRule.class}, requestHasSensitiveInfo = false, responseHasSensitiveInfo = false) public class ListEgressFirewallRulesCmd extends ListFirewallRulesCmd { public static final Logger s_logger = Logger.getLogger(ListEgressFirewallRulesCmd.class.getName()); diff --git a/api/src/org/apache/cloudstack/api/command/user/firewall/ListFirewallRulesCmd.java b/api/src/org/apache/cloudstack/api/command/user/firewall/ListFirewallRulesCmd.java index 870f81d914..9c9fbc8397 100644 --- a/api/src/org/apache/cloudstack/api/command/user/firewall/ListFirewallRulesCmd.java +++ b/api/src/org/apache/cloudstack/api/command/user/firewall/ListFirewallRulesCmd.java @@ -21,7 +21,6 @@ import org.apache.log4j.Logger; -import org.apache.cloudstack.acl.IAMEntityType; import org.apache.cloudstack.acl.RoleType; import org.apache.cloudstack.api.APICommand; import org.apache.cloudstack.api.ApiConstants; @@ -36,7 +35,7 @@ import com.cloud.network.rules.FirewallRule; import com.cloud.utils.Pair; -@APICommand(name = "listFirewallRules", description = "Lists all firewall rules for an IP address.", responseObject = FirewallResponse.class, entityType = {IAMEntityType.FirewallRule}, +@APICommand(name = "listFirewallRules", description = "Lists all firewall rules for an IP address.", responseObject = FirewallResponse.class, entityType = {FirewallRule.class}, requestHasSensitiveInfo = false, responseHasSensitiveInfo = false) public class ListFirewallRulesCmd extends BaseListTaggedResourcesCmd { public static final Logger s_logger = Logger.getLogger(ListFirewallRulesCmd.class.getName()); diff --git a/api/src/org/apache/cloudstack/api/command/user/firewall/ListPortForwardingRulesCmd.java b/api/src/org/apache/cloudstack/api/command/user/firewall/ListPortForwardingRulesCmd.java index 681da333f0..cde2563f9a 100644 --- a/api/src/org/apache/cloudstack/api/command/user/firewall/ListPortForwardingRulesCmd.java +++ b/api/src/org/apache/cloudstack/api/command/user/firewall/ListPortForwardingRulesCmd.java @@ -21,7 +21,6 @@ import org.apache.log4j.Logger; -import org.apache.cloudstack.acl.IAMEntityType; import org.apache.cloudstack.acl.RoleType; import org.apache.cloudstack.api.APICommand; import org.apache.cloudstack.api.ApiConstants; @@ -35,7 +34,7 @@ import com.cloud.network.rules.PortForwardingRule; import com.cloud.utils.Pair; -@APICommand(name = "listPortForwardingRules", description = "Lists all port forwarding rules for an IP address.", responseObject = FirewallRuleResponse.class, entityType = {IAMEntityType.PortForwardingRule}, +@APICommand(name = "listPortForwardingRules", description = "Lists all port forwarding rules for an IP address.", responseObject = FirewallRuleResponse.class, entityType = {PortForwardingRule.class}, requestHasSensitiveInfo = false, responseHasSensitiveInfo = false) public class ListPortForwardingRulesCmd extends BaseListTaggedResourcesCmd { public static final Logger s_logger = Logger.getLogger(ListPortForwardingRulesCmd.class.getName()); diff --git a/api/src/org/apache/cloudstack/api/command/user/firewall/UpdatePortForwardingRuleCmd.java b/api/src/org/apache/cloudstack/api/command/user/firewall/UpdatePortForwardingRuleCmd.java index 55b378a21a..eb4d468886 100644 --- a/api/src/org/apache/cloudstack/api/command/user/firewall/UpdatePortForwardingRuleCmd.java +++ b/api/src/org/apache/cloudstack/api/command/user/firewall/UpdatePortForwardingRuleCmd.java @@ -16,9 +16,6 @@ // under the License. package org.apache.cloudstack.api.command.user.firewall; -import org.apache.log4j.Logger; - -import org.apache.cloudstack.acl.IAMEntityType; import org.apache.cloudstack.acl.RoleType; import org.apache.cloudstack.api.APICommand; import org.apache.cloudstack.api.ApiConstants; @@ -28,17 +25,17 @@ import org.apache.cloudstack.api.response.FirewallRuleResponse; import org.apache.cloudstack.api.response.IPAddressResponse; import org.apache.cloudstack.api.response.UserVmResponse; +import org.apache.log4j.Logger; import com.cloud.event.EventTypes; import com.cloud.exception.InvalidParameterValueException; -import com.cloud.network.IpAddress; import com.cloud.network.rules.FirewallRule; import com.cloud.network.rules.PortForwardingRule; import com.cloud.user.Account; @APICommand(name = "updatePortForwardingRule", responseObject = FirewallRuleResponse.class, - description = "Updates a port forwarding rule. Only the private port and the virtual machine can be updated.", entityType = {IAMEntityType.PortForwardingRule}, + description = "Updates a port forwarding rule. Only the private port and the virtual machine can be updated.", entityType = {PortForwardingRule.class}, requestHasSensitiveInfo = false, responseHasSensitiveInfo = false) public class UpdatePortForwardingRuleCmd extends BaseAsyncCustomIdCmd { public static final Logger s_logger = Logger.getLogger(UpdatePortForwardingRuleCmd.class.getName()); @@ -47,7 +44,7 @@ public class UpdatePortForwardingRuleCmd extends BaseAsyncCustomIdCmd { ///////////////////////////////////////////////////// //////////////// API parameters ///////////////////// ///////////////////////////////////////////////////// - @Parameter(name = ApiConstants.ID, type = CommandType.UUID, entityType = FirewallRuleResponse.class, required = true, description = "the ID of the port forwarding rule") + @Parameter(name = ApiConstants.ID, type = CommandType.UUID, entityType = FirewallRuleResponse.class, required = true, description = "the ID of the port forwarding rule", since = "4.4") private Long id; @Parameter(name = ApiConstants.PRIVATE_IP, type = CommandType.STRING, description = "the private IP address of the port forwarding rule") @@ -95,10 +92,6 @@ public String getProtocol() { return protocol; } - public Long getPublicIpId() { - return publicIpId; - } - public String getPublicPort() { return publicPort; } @@ -110,11 +103,16 @@ public Long getVirtualMachineId() { public Boolean getDisplay() { return display; } + public Long getId() { + return id; + } ///////////////////////////////////////////////////// /////////////// API Implementation/////////////////// ///////////////////////////////////////////////////// + + @Override public String getCommandName() { return s_name; @@ -122,9 +120,9 @@ public String getCommandName() { @Override public long getEntityOwnerId() { - IpAddress addr = _entityMgr.findById(IpAddress.class, getPublicIpId()); - if (addr != null) { - return addr.getAccountId(); + PortForwardingRule rule = _entityMgr.findById(PortForwardingRule.class, getId()); + if (rule != null) { + return rule.getAccountId(); } // bad address given, parent this command to SYSTEM so ERROR events are tracked @@ -174,14 +172,11 @@ public String getSyncObjType() { @Override public Long getSyncObjId() { - return getIp().getAssociatedWithNetworkId(); - } - - private IpAddress getIp() { - IpAddress ip = _networkService.getIp(publicIpId); - if (ip == null) { - throw new InvalidParameterValueException("Unable to find ip address by id " + publicIpId); + PortForwardingRule rule = _entityMgr.findById(PortForwardingRule.class, getId()); + if (rule != null) { + return rule.getNetworkId(); + } else { + throw new InvalidParameterValueException("Unable to find the rule by id"); } - return ip; } } diff --git a/api/src/org/apache/cloudstack/api/command/user/iso/CopyIsoCmd.java b/api/src/org/apache/cloudstack/api/command/user/iso/CopyIsoCmd.java index 21196bcb65..9002624c48 100644 --- a/api/src/org/apache/cloudstack/api/command/user/iso/CopyIsoCmd.java +++ b/api/src/org/apache/cloudstack/api/command/user/iso/CopyIsoCmd.java @@ -19,10 +19,11 @@ import org.apache.log4j.Logger; import org.apache.cloudstack.api.APICommand; +import org.apache.cloudstack.api.ResponseObject.ResponseView; import org.apache.cloudstack.api.command.user.template.CopyTemplateCmd; import org.apache.cloudstack.api.response.TemplateResponse; -@APICommand(name = "copyIso", description = "Copies an iso from one zone to another.", responseObject = TemplateResponse.class, +@APICommand(name = "copyIso", description = "Copies an iso from one zone to another.", responseObject = TemplateResponse.class, responseView = ResponseView.Restricted, requestHasSensitiveInfo = false, responseHasSensitiveInfo = false) public class CopyIsoCmd extends CopyTemplateCmd { public static final Logger s_logger = Logger.getLogger(CopyIsoCmd.class.getName()); diff --git a/api/src/org/apache/cloudstack/api/command/user/iso/ListIsosCmd.java b/api/src/org/apache/cloudstack/api/command/user/iso/ListIsosCmd.java index 3aabf926fc..88e4326c7d 100644 --- a/api/src/org/apache/cloudstack/api/command/user/iso/ListIsosCmd.java +++ b/api/src/org/apache/cloudstack/api/command/user/iso/ListIsosCmd.java @@ -121,7 +121,7 @@ public Boolean getShowRemoved() { public boolean listInReadyState() { Account account = CallContext.current().getCallingAccount(); // It is account specific if account is admin type and domainId and accountName are not null - boolean isAccountSpecific = (account == null || _accountService.isAdmin(account.getType())) && (getAccountName() != null) && (getDomainId() != null); + boolean isAccountSpecific = (account == null || _accountService.isAdmin(account.getId())) && (getAccountName() != null) && (getDomainId() != null); // Show only those that are downloaded. TemplateFilter templateFilter = TemplateFilter.valueOf(getIsoFilter()); boolean onlyReady = diff --git a/api/src/org/apache/cloudstack/api/command/user/loadbalancer/AssignToLoadBalancerRuleCmd.java b/api/src/org/apache/cloudstack/api/command/user/loadbalancer/AssignToLoadBalancerRuleCmd.java index 6bd7537827..db4d70e685 100644 --- a/api/src/org/apache/cloudstack/api/command/user/loadbalancer/AssignToLoadBalancerRuleCmd.java +++ b/api/src/org/apache/cloudstack/api/command/user/loadbalancer/AssignToLoadBalancerRuleCmd.java @@ -16,10 +16,18 @@ // under the License. package org.apache.cloudstack.api.command.user.loadbalancer; +import java.util.ArrayList; +import java.util.Collection; +import java.util.HashMap; +import java.util.Iterator; import java.util.List; +import java.util.Map; +import com.cloud.utils.net.NetUtils; import org.apache.log4j.Logger; +import org.apache.cloudstack.acl.SecurityChecker.AccessType; +import org.apache.cloudstack.api.ACL; import org.apache.cloudstack.api.APICommand; import org.apache.cloudstack.api.ApiConstants; import org.apache.cloudstack.api.ApiErrorCode; @@ -33,13 +41,15 @@ import com.cloud.event.EventTypes; import com.cloud.exception.InvalidParameterValueException; +import com.cloud.network.rules.FirewallRule; import com.cloud.network.rules.LoadBalancer; import com.cloud.user.Account; import com.cloud.utils.StringUtils; +import com.cloud.vm.VirtualMachine; @APICommand(name = "assignToLoadBalancerRule", description = "Assigns virtual machine or a list of virtual machines to a load balancer rule.", - responseObject = SuccessResponse.class, + responseObject = SuccessResponse.class, entityType = {FirewallRule.class, VirtualMachine.class}, requestHasSensitiveInfo = false, responseHasSensitiveInfo = false) public class AssignToLoadBalancerRuleCmd extends BaseAsyncCmd { @@ -51,6 +61,7 @@ public class AssignToLoadBalancerRuleCmd extends BaseAsyncCmd { //////////////// API parameters ///////////////////// ///////////////////////////////////////////////////// + @ACL(accessType = AccessType.OperateEntry) @Parameter(name = ApiConstants.ID, type = CommandType.UUID, entityType = FirewallRuleResponse.class, @@ -58,14 +69,20 @@ public class AssignToLoadBalancerRuleCmd extends BaseAsyncCmd { description = "the ID of the load balancer rule") private Long id; + @ACL(accessType = AccessType.OperateEntry) @Parameter(name = ApiConstants.VIRTUAL_MACHINE_IDS, type = CommandType.LIST, collectionType = CommandType.UUID, entityType = UserVmResponse.class, - required = true, description = "the list of IDs of the virtual machine that are being assigned to the load balancer rule(i.e. virtualMachineIds=1,2,3)") private List virtualMachineIds; + @Parameter(name = ApiConstants.VIRTUAL_MACHINE_ID_IP, + type = CommandType.MAP, + description = "VM ID and IP map, vmidipmap[0].vmid=1 vmidipmap[0].ip=10.1.1.75", + since = "4.4") + private Map vmIdIpMap; + ///////////////////////////////////////////////////// /////////////////// Accessors /////////////////////// ///////////////////////////////////////////////////// @@ -78,6 +95,10 @@ public List getVirtualMachineIds() { return virtualMachineIds; } + public Map getVmIdIpMap() { + return vmIdIpMap; + } + ///////////////////////////////////////////////////// /////////////// API Implementation/////////////////// ///////////////////////////////////////////////////// @@ -106,13 +127,54 @@ public String getEventDescription() { return "applying instances for load balancer: " + getLoadBalancerId() + " (ids: " + StringUtils.join(getVirtualMachineIds(), ",") + ")"; } + + public Map> getVmIdIpListMap() { + Map> vmIdIpsMap = new HashMap>(); + if (vmIdIpMap != null && !vmIdIpMap.isEmpty()) { + Collection idIpsCollection = vmIdIpMap.values(); + Iterator iter = idIpsCollection.iterator(); + while (iter.hasNext()) { + HashMap idIpsMap = (HashMap)iter.next(); + String vmId = idIpsMap.get("vmid"); + String vmIp = idIpsMap.get("vmip"); + + VirtualMachine lbvm = _entityMgr.findByUuid(VirtualMachine.class, vmId); + if (lbvm == null) { + throw new InvalidParameterValueException("Unable to find virtual machine ID: " + vmId); + } + + //check wether the given ip is valid ip or not + if (vmIp == null || !NetUtils.isValidIp(vmIp)) { + throw new InvalidParameterValueException("Invalid ip address "+ vmIp +" passed in vmidipmap for " + + "vmid " + vmId); + } + Long longVmId = lbvm.getId(); + + List ipsList = null; + if (vmIdIpsMap.containsKey(longVmId)) { + ipsList = vmIdIpsMap.get(longVmId); + } else { + ipsList = new ArrayList(); + } + ipsList.add(vmIp); + vmIdIpsMap.put(longVmId, ipsList); + + } + } + + return vmIdIpsMap; + } + @Override public void execute() { CallContext.current().setEventDetails("Load balancer Id: " + getLoadBalancerId() + " VmIds: " + StringUtils.join(getVirtualMachineIds(), ",")); - boolean result = _lbService.assignToLoadBalancer(getLoadBalancerId(), virtualMachineIds); + + Map> vmIdIpsMap = getVmIdIpListMap(); + + boolean result = _lbService.assignToLoadBalancer(getLoadBalancerId(), virtualMachineIds, vmIdIpsMap); if (result) { SuccessResponse response = new SuccessResponse(getCommandName()); - this.setResponseObject(response); + setResponseObject(response); } else { throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, "Failed to assign load balancer rule"); } diff --git a/api/src/org/apache/cloudstack/api/command/user/loadbalancer/CreateLBHealthCheckPolicyCmd.java b/api/src/org/apache/cloudstack/api/command/user/loadbalancer/CreateLBHealthCheckPolicyCmd.java index 547274dc53..f6eb48e800 100644 --- a/api/src/org/apache/cloudstack/api/command/user/loadbalancer/CreateLBHealthCheckPolicyCmd.java +++ b/api/src/org/apache/cloudstack/api/command/user/loadbalancer/CreateLBHealthCheckPolicyCmd.java @@ -16,8 +16,7 @@ // under the License. package org.apache.cloudstack.api.command.user.loadbalancer; -import org.apache.log4j.Logger; - +import org.apache.cloudstack.acl.RoleType; import org.apache.cloudstack.api.APICommand; import org.apache.cloudstack.api.ApiConstants; import org.apache.cloudstack.api.ApiErrorCode; @@ -27,6 +26,7 @@ import org.apache.cloudstack.api.response.FirewallRuleResponse; import org.apache.cloudstack.api.response.LBHealthCheckResponse; import org.apache.cloudstack.context.CallContext; +import org.apache.log4j.Logger; import com.cloud.event.EventTypes; import com.cloud.exception.InvalidParameterValueException; @@ -89,10 +89,27 @@ public class CreateLBHealthCheckPolicyCmd extends BaseAsyncCreateCmd { description = "Number of consecutive health check failures before declaring an instance unhealthy") private int unhealthyThreshold; + @Parameter(name = ApiConstants.FOR_DISPLAY, type = CommandType.BOOLEAN, description = "an optional field, whether to the display the rule to the end user or not", since = "4.4", authorized = {RoleType.Admin}) + private Boolean display; + + // /////////////////////////////////////////////////// // ///////////////// Accessors /////////////////////// // /////////////////////////////////////////////////// + @Deprecated + public Boolean getDisplay() { + return display; + } + + @Override + public boolean isDisplay() { + if(display == null) + return true; + else + return display; + } + public Long getLbRuleId() { return lbRuleId; } diff --git a/api/src/org/apache/cloudstack/api/command/user/loadbalancer/CreateLBStickinessPolicyCmd.java b/api/src/org/apache/cloudstack/api/command/user/loadbalancer/CreateLBStickinessPolicyCmd.java index 738f837ccd..152f6612f0 100644 --- a/api/src/org/apache/cloudstack/api/command/user/loadbalancer/CreateLBStickinessPolicyCmd.java +++ b/api/src/org/apache/cloudstack/api/command/user/loadbalancer/CreateLBStickinessPolicyCmd.java @@ -18,8 +18,7 @@ import java.util.Map; -import org.apache.log4j.Logger; - +import org.apache.cloudstack.acl.RoleType; import org.apache.cloudstack.api.APICommand; import org.apache.cloudstack.api.ApiConstants; import org.apache.cloudstack.api.ApiErrorCode; @@ -30,6 +29,7 @@ import org.apache.cloudstack.api.response.FirewallRuleResponse; import org.apache.cloudstack.api.response.LBStickinessResponse; import org.apache.cloudstack.context.CallContext; +import org.apache.log4j.Logger; import com.cloud.event.EventTypes; import com.cloud.exception.InvalidParameterValueException; @@ -74,10 +74,27 @@ public class CreateLBStickinessPolicyCmd extends BaseAsyncCreateCmd { @Parameter(name = ApiConstants.PARAM_LIST, type = CommandType.MAP, description = "param list. Example: param[0].name=cookiename¶m[0].value=LBCookie ") private Map paramList; + @Parameter(name = ApiConstants.FOR_DISPLAY, type = CommandType.BOOLEAN, description = "an optional field, whether to the display the rule to the end user or not", since = "4.4", authorized = {RoleType.Admin}) + private Boolean display; + + // /////////////////////////////////////////////////// // ///////////////// Accessors /////////////////////// // /////////////////////////////////////////////////// + @Deprecated + public Boolean getDisplay() { + return display; + } + + @Override + public boolean isDisplay() { + if(display == null) + return true; + else + return display; + } + public Long getLbRuleId() { return lbRuleId; } diff --git a/api/src/org/apache/cloudstack/api/command/user/loadbalancer/CreateLoadBalancerRuleCmd.java b/api/src/org/apache/cloudstack/api/command/user/loadbalancer/CreateLoadBalancerRuleCmd.java index a405913f78..7c371928d9 100644 --- a/api/src/org/apache/cloudstack/api/command/user/loadbalancer/CreateLoadBalancerRuleCmd.java +++ b/api/src/org/apache/cloudstack/api/command/user/loadbalancer/CreateLoadBalancerRuleCmd.java @@ -124,8 +124,13 @@ public class CreateLoadBalancerRuleCmd extends BaseAsyncCreateCmd /*implements L /////////////////// Accessors /////////////////////// ///////////////////////////////////////////////////// - public Boolean getDisplay() { - return display; + @Override + public boolean isDisplay() { + if (display != null) { + return display; + } else { + return true; + } } public String getAlgorithm() { @@ -309,7 +314,7 @@ public void create() { try { LoadBalancer result = _lbService.createPublicLoadBalancerRule(getXid(), getName(), getDescription(), getSourcePortStart(), getSourcePortEnd(), getDefaultPortStart(), - getDefaultPortEnd(), getSourceIpAddressId(), getProtocol(), getAlgorithm(), getNetworkId(), getEntityOwnerId(), getOpenFirewall(), getLbProtocol(), getDisplay()); + getDefaultPortEnd(), getSourceIpAddressId(), getProtocol(), getAlgorithm(), getNetworkId(), getEntityOwnerId(), getOpenFirewall(), getLbProtocol(), isDisplay()); this.setEntityId(result.getId()); this.setEntityUuid(result.getUuid()); } catch (NetworkRuleConflictException e) { diff --git a/api/src/org/apache/cloudstack/api/command/user/loadbalancer/ListLBHealthCheckPoliciesCmd.java b/api/src/org/apache/cloudstack/api/command/user/loadbalancer/ListLBHealthCheckPoliciesCmd.java index 5f4ca09ec9..7f78da6409 100644 --- a/api/src/org/apache/cloudstack/api/command/user/loadbalancer/ListLBHealthCheckPoliciesCmd.java +++ b/api/src/org/apache/cloudstack/api/command/user/loadbalancer/ListLBHealthCheckPoliciesCmd.java @@ -19,8 +19,7 @@ import java.util.ArrayList; import java.util.List; -import org.apache.log4j.Logger; - +import org.apache.cloudstack.acl.RoleType; import org.apache.cloudstack.api.APICommand; import org.apache.cloudstack.api.ApiConstants; import org.apache.cloudstack.api.BaseListCmd; @@ -28,6 +27,7 @@ import org.apache.cloudstack.api.response.FirewallRuleResponse; import org.apache.cloudstack.api.response.LBHealthCheckResponse; import org.apache.cloudstack.api.response.ListResponse; +import org.apache.log4j.Logger; import com.cloud.network.rules.HealthCheckPolicy; import com.cloud.network.rules.LoadBalancer; @@ -49,6 +49,9 @@ public class ListLBHealthCheckPoliciesCmd extends BaseListCmd { description = "the ID of the load balancer rule") private Long lbRuleId; + @Parameter(name = ApiConstants.FOR_DISPLAY, type = CommandType.BOOLEAN, description = "list resources by display flag; only ROOT admin is eligible to pass this parameter", since = "4.4", authorized = {RoleType.Admin}) + private Boolean display; + // /////////////////////////////////////////////////// // ///////////////// Accessors /////////////////////// // /////////////////////////////////////////////////// @@ -56,6 +59,13 @@ public Long getLbRuleId() { return lbRuleId; } + public boolean getDisplay() { + if (display != null) { + return display; + } + return true; + } + // /////////////////////////////////////////////////// // ///////////// API Implementation/////////////////// // /////////////////////////////////////////////////// diff --git a/api/src/org/apache/cloudstack/api/command/user/loadbalancer/ListLBStickinessPoliciesCmd.java b/api/src/org/apache/cloudstack/api/command/user/loadbalancer/ListLBStickinessPoliciesCmd.java index 2e7ae3c5e1..dd031913c1 100644 --- a/api/src/org/apache/cloudstack/api/command/user/loadbalancer/ListLBStickinessPoliciesCmd.java +++ b/api/src/org/apache/cloudstack/api/command/user/loadbalancer/ListLBStickinessPoliciesCmd.java @@ -19,8 +19,7 @@ import java.util.ArrayList; import java.util.List; -import org.apache.log4j.Logger; - +import org.apache.cloudstack.acl.RoleType; import org.apache.cloudstack.api.APICommand; import org.apache.cloudstack.api.ApiConstants; import org.apache.cloudstack.api.BaseListCmd; @@ -29,6 +28,7 @@ import org.apache.cloudstack.api.response.LBStickinessResponse; import org.apache.cloudstack.api.response.ListResponse; import org.apache.cloudstack.context.CallContext; +import org.apache.log4j.Logger; import com.cloud.network.rules.LoadBalancer; import com.cloud.network.rules.StickinessPolicy; @@ -51,6 +51,9 @@ public class ListLBStickinessPoliciesCmd extends BaseListCmd { description = "the ID of the load balancer rule") private Long lbRuleId; + @Parameter(name = ApiConstants.FOR_DISPLAY, type = CommandType.BOOLEAN, description = "list resources by display flag; only ROOT admin is eligible to pass this parameter", since = "4.4", authorized = {RoleType.Admin}) + private Boolean display; + // /////////////////////////////////////////////////// // ///////////////// Accessors /////////////////////// // /////////////////////////////////////////////////// @@ -58,6 +61,13 @@ public Long getLbRuleId() { return lbRuleId; } + public boolean getDisplay() { + if (display != null) { + return display; + } + return true; + } + // /////////////////////////////////////////////////// // ///////////// API Implementation/////////////////// // /////////////////////////////////////////////////// @@ -76,7 +86,7 @@ public void execute() { if (lb != null) { //check permissions Account caller = CallContext.current().getCallingAccount(); - _accountService.checkAccess(caller, null, true, lb); + _accountService.checkAccess(caller, null, lb); List stickinessPolicies = _lbService.searchForLBStickinessPolicies(this); LBStickinessResponse spResponse = _responseGenerator.createLBStickinessPolicyResponse(stickinessPolicies, lb); spResponses.add(spResponse); @@ -84,7 +94,7 @@ public void execute() { } response.setResponseName(getCommandName()); - this.setResponseObject(response); + setResponseObject(response); } } diff --git a/api/src/org/apache/cloudstack/api/command/user/loadbalancer/ListLoadBalancerRuleInstancesCmd.java b/api/src/org/apache/cloudstack/api/command/user/loadbalancer/ListLoadBalancerRuleInstancesCmd.java index 2d458a7408..cc4203c359 100644 --- a/api/src/org/apache/cloudstack/api/command/user/loadbalancer/ListLoadBalancerRuleInstancesCmd.java +++ b/api/src/org/apache/cloudstack/api/command/user/loadbalancer/ListLoadBalancerRuleInstancesCmd.java @@ -19,6 +19,7 @@ import java.util.ArrayList; import java.util.List; +import org.apache.cloudstack.api.response.LoadBalancerRuleVmMapResponse; import org.apache.log4j.Logger; import org.apache.cloudstack.api.APICommand; @@ -33,7 +34,7 @@ import com.cloud.uservm.UserVm; import com.cloud.utils.Pair; -@APICommand(name = "listLoadBalancerRuleInstances", description = "List all virtual machine instances that are assigned to a load balancer rule.", responseObject = UserVmResponse.class, responseView = ResponseView.Restricted, +@APICommand(name = "listLoadBalancerRuleInstances", description = "List all virtual machine instances that are assigned to a load balancer rule.", responseObject = LoadBalancerRuleVmMapResponse.class, responseView = ResponseView.Restricted, requestHasSensitiveInfo = false, responseHasSensitiveInfo = true) public class ListLoadBalancerRuleInstancesCmd extends BaseListCmd { @@ -57,6 +58,13 @@ public class ListLoadBalancerRuleInstancesCmd extends BaseListCmd { description = "the ID of the load balancer rule") private Long id; + + @Parameter(name = ApiConstants.LIST_LB_VMIPS, + type = CommandType.BOOLEAN, + description = "true if lb rule vm ip information to be included; default is false") + private boolean isListLbVmip; + + ///////////////////////////////////////////////////// /////////////////// Accessors /////////////////////// ///////////////////////////////////////////////////// @@ -69,6 +77,10 @@ public Long getId() { return id; } + public boolean isListLbVmip() { + return isListLbVmip; + } + ///////////////////////////////////////////////////// /////////////// API Implementation/////////////////// ///////////////////////////////////////////////////// @@ -83,17 +95,49 @@ public void execute() { Pair, List> vmServiceMap = _lbService.listLoadBalancerInstances(this); List result = vmServiceMap.first(); List serviceStates = vmServiceMap.second(); - ListResponse response = new ListResponse(); - List vmResponses = new ArrayList(); - if (result != null) { - vmResponses = _responseGenerator.createUserVmResponse(ResponseView.Restricted, "loadbalancerruleinstance", result.toArray(new UserVm[result.size()])); - } - for (int i = 0; i < result.size(); i++) { - vmResponses.get(i).setServiceState(serviceStates.get(i)); + if (!isListLbVmip()) { + // list lb instances + ListResponse response = new ListResponse(); + List vmResponses = new ArrayList(); + if (result != null) { + vmResponses = _responseGenerator.createUserVmResponse(ResponseView.Restricted, "loadbalancerruleinstance", result.toArray(new UserVm[result.size()])); + + + for (int i = 0; i < result.size(); i++) { + vmResponses.get(i).setServiceState(serviceStates.get(i)); + } + } + response.setResponses(vmResponses); + response.setResponseName(getCommandName()); + setResponseObject(response); + + + } else { + ListResponse lbRes = new ListResponse(); + + List vmResponses = new ArrayList(); + List listlbVmRes = new ArrayList(); + + if (result != null) { + vmResponses = _responseGenerator.createUserVmResponse(ResponseView.Full, "loadbalancerruleinstance", result.toArray(new UserVm[result.size()])); + + + List ipaddr = null; + + for (int i=0;i virtualMachineIds; + @Parameter(name = ApiConstants.VIRTUAL_MACHINE_ID_IP, + type = CommandType.MAP, + description = "VM ID and IP map, vmidipmap[0].vmid=1 vmidipmap[0].ip=10.1.1.75", + since = "4.4") + private Map vmIdIpMap; + ///////////////////////////////////////////////////// /////////////////// Accessors /////////////////////// ///////////////////////////////////////////////////// @@ -78,6 +89,10 @@ public List getVirtualMachineIds() { return virtualMachineIds; } + public Map getVmIdIpMap() { + return vmIdIpMap; + } + ///////////////////////////////////////////////////// /////////////// API Implementation/////////////////// ///////////////////////////////////////////////////// @@ -101,20 +116,58 @@ public String getEventType() { return EventTypes.EVENT_REMOVE_FROM_LOAD_BALANCER_RULE; } + + public Map> getVmIdIpListMap() { + Map> vmIdIpsMap = new HashMap>(); + if (vmIdIpMap != null && !vmIdIpMap.isEmpty()) { + Collection idIpsCollection = vmIdIpMap.values(); + Iterator iter = idIpsCollection.iterator(); + while (iter.hasNext()) { + HashMap idIpsMap = (HashMap)iter.next(); + String vmId = idIpsMap.get("vmid"); + String vmIp = idIpsMap.get("vmip"); + + VirtualMachine lbvm = _entityMgr.findByUuid(VirtualMachine.class, vmId); + if (lbvm == null) { + throw new InvalidParameterValueException("Unable to find virtual machine ID: " + vmId); + } + + Long longVmId = lbvm.getId(); + + List ipsList = null; + if (vmIdIpsMap.containsKey(longVmId)) { + ipsList = vmIdIpsMap.get(longVmId); + } else { + ipsList = new ArrayList(); + } + ipsList.add(vmIp); + vmIdIpsMap.put(longVmId, ipsList); + + } + } + + return vmIdIpsMap; + } + @Override public String getEventDescription() { return "removing instances from load balancer: " + getId() + " (ids: " + StringUtils.join(getVirtualMachineIds(), ",") + ")"; } @Override - public void execute() { + public void execute() { CallContext.current().setEventDetails("Load balancer Id: " + getId() + " VmIds: " + StringUtils.join(getVirtualMachineIds(), ",")); - boolean result = _lbService.removeFromLoadBalancer(id, virtualMachineIds); - if (result) { - SuccessResponse response = new SuccessResponse(getCommandName()); - this.setResponseObject(response); - } else { - throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, "Failed to remove instance from load balancer rule"); + Map> vmIdIpsMap = getVmIdIpListMap(); + try { + boolean result = _lbService.removeFromLoadBalancer(id, virtualMachineIds, vmIdIpsMap); + if (result) { + SuccessResponse response = new SuccessResponse(getCommandName()); + this.setResponseObject(response); + } else { + throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, "Failed to remove instance from load balancer rule"); + } + }catch (InvalidParameterValueException ex) { + throw new ServerApiException(ApiErrorCode.PARAM_ERROR, "Failed to remove instance from load balancer rule"); } } diff --git a/api/src/org/apache/cloudstack/api/command/user/loadbalancer/UpdateLBHealthCheckPolicyCmd.java b/api/src/org/apache/cloudstack/api/command/user/loadbalancer/UpdateLBHealthCheckPolicyCmd.java new file mode 100644 index 0000000000..0b0c34fff9 --- /dev/null +++ b/api/src/org/apache/cloudstack/api/command/user/loadbalancer/UpdateLBHealthCheckPolicyCmd.java @@ -0,0 +1,100 @@ +// Copyright 2012 Citrix Systems, Inc. Licensed under the +// Apache License, Version 2.0 (the "License"); you may not use this +// file except in compliance with the License. Citrix Systems, Inc. +// reserves all rights not expressly granted by 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. +// +// Automatically generated by addcopyright.py at 04/03/2012 +package org.apache.cloudstack.api.command.user.loadbalancer; + +import org.apache.cloudstack.acl.RoleType; +import org.apache.cloudstack.api.APICommand; +import org.apache.cloudstack.api.ApiConstants; +import org.apache.cloudstack.api.BaseAsyncCustomIdCmd; +import org.apache.cloudstack.api.Parameter; +import org.apache.cloudstack.api.response.LBHealthCheckResponse; +import org.apache.cloudstack.context.CallContext; +import org.apache.log4j.Logger; + +import com.cloud.event.EventTypes; +import com.cloud.network.rules.HealthCheckPolicy; +import com.cloud.network.rules.LoadBalancer; +import com.cloud.network.rules.StickinessPolicy; +import com.cloud.user.Account; + +@APICommand(name = "updateLBHealthCheckPolicy", description = "Updates LB HealthCheck policy", responseObject = LBHealthCheckResponse.class, since = "4.4", +requestHasSensitiveInfo = false, responseHasSensitiveInfo = false) +public class UpdateLBHealthCheckPolicyCmd extends BaseAsyncCustomIdCmd{ + public static final Logger s_logger = Logger.getLogger(UpdateLBHealthCheckPolicyCmd.class.getName()); + + private static final String s_name = "updatelbhealthcheckpolicyresponse"; + + ///////////////////////////////////////////////////// + //////////////// API parameters ///////////////////// + ///////////////////////////////////////////////////// + @Parameter(name = ApiConstants.ID, type = CommandType.UUID, entityType = LBHealthCheckResponse.class, required = true, description = "id of lb healthcheck policy") + private Long id; + + @Parameter(name = ApiConstants.FOR_DISPLAY, type = CommandType.BOOLEAN, description = "an optional field, whether to the display the policy to the end user or not", since = "4.4", authorized = {RoleType.Admin}) + private Boolean display; + + ///////////////////////////////////////////////////// + /////////////////// Accessors /////////////////////// + ///////////////////////////////////////////////////// + public Long getId() { + return id; + } + + public Boolean getDisplay() { + return display; + } + + @Override + public String getCommandName() { + return s_name; + } + + @Override + public long getEntityOwnerId() { + Account account = CallContext.current().getCallingAccount(); + 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 String getEventDescription() { + return "Update LB healthcheck policy id= " + id; + } + + @Override + public String getEventType() { + return EventTypes.EVENT_LB_HEALTHCHECKPOLICY_UPDATE; + } + + ///////////////////////////////////////////////////// + /////////////// API Implementation/////////////////// + ///////////////////////////////////////////////////// + @Override + public void execute() { + HealthCheckPolicy policy = _lbService.updateLBHealthCheckPolicy(this.getId(), this.getCustomId(), this.getDisplay()); + LoadBalancer lb = _lbService.findById(policy.getLoadBalancerId()); + LBHealthCheckResponse hcResponse = _responseGenerator.createLBHealthCheckPolicyResponse(policy, lb); + setResponseObject(hcResponse); + hcResponse.setResponseName(getCommandName()); + } + + @Override + public void checkUuid() { + if (this.getCustomId() != null) { + _uuidMgr.checkUuid(this.getCustomId(), StickinessPolicy.class); + } + } +} diff --git a/api/src/org/apache/cloudstack/api/command/user/loadbalancer/UpdateLBStickinessPolicyCmd.java b/api/src/org/apache/cloudstack/api/command/user/loadbalancer/UpdateLBStickinessPolicyCmd.java new file mode 100644 index 0000000000..c652945477 --- /dev/null +++ b/api/src/org/apache/cloudstack/api/command/user/loadbalancer/UpdateLBStickinessPolicyCmd.java @@ -0,0 +1,99 @@ +// Copyright 2012 Citrix Systems, Inc. Licensed under the +// Apache License, Version 2.0 (the "License"); you may not use this +// file except in compliance with the License. Citrix Systems, Inc. +// reserves all rights not expressly granted by 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. +// +// Automatically generated by addcopyright.py at 04/03/2012 +package org.apache.cloudstack.api.command.user.loadbalancer; + +import org.apache.cloudstack.acl.RoleType; +import org.apache.cloudstack.api.APICommand; +import org.apache.cloudstack.api.ApiConstants; +import org.apache.cloudstack.api.BaseAsyncCustomIdCmd; +import org.apache.cloudstack.api.Parameter; +import org.apache.cloudstack.api.response.LBStickinessResponse; +import org.apache.cloudstack.context.CallContext; +import org.apache.log4j.Logger; + +import com.cloud.event.EventTypes; +import com.cloud.network.rules.LoadBalancer; +import com.cloud.network.rules.StickinessPolicy; +import com.cloud.user.Account; + +@APICommand(name = "updateLBStickinessPolicy", description = "Updates LB Stickiness policy", responseObject = LBStickinessResponse.class, since = "4.4", +requestHasSensitiveInfo = false, responseHasSensitiveInfo = false) +public class UpdateLBStickinessPolicyCmd extends BaseAsyncCustomIdCmd{ + public static final Logger s_logger = Logger.getLogger(UpdateLBStickinessPolicyCmd.class.getName()); + + private static final String s_name = "updatelbstickinesspolicyresponse"; + + ///////////////////////////////////////////////////// + //////////////// API parameters ///////////////////// + ///////////////////////////////////////////////////// + @Parameter(name = ApiConstants.ID, type = CommandType.UUID, entityType = LBStickinessResponse.class, required = true, description = "id of lb stickiness policy") + private Long id; + + @Parameter(name = ApiConstants.FOR_DISPLAY, type = CommandType.BOOLEAN, description = "an optional field, whether to the display the policy to the end user or not", since = "4.4", authorized = {RoleType.Admin}) + private Boolean display; + + ///////////////////////////////////////////////////// + /////////////////// Accessors /////////////////////// + ///////////////////////////////////////////////////// + public Long getId() { + return id; + } + + public Boolean getDisplay() { + return display; + } + + @Override + public String getCommandName() { + return s_name; + } + + @Override + public long getEntityOwnerId() { + Account account = CallContext.current().getCallingAccount(); + 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 String getEventDescription() { + return "Update LB stickiness policy id= " + id; + } + + @Override + public String getEventType() { + return EventTypes.EVENT_LB_STICKINESSPOLICY_UPDATE; + } + + ///////////////////////////////////////////////////// + /////////////// API Implementation/////////////////// + ///////////////////////////////////////////////////// + @Override + public void execute() { + StickinessPolicy policy = _lbService.updateLBStickinessPolicy(this.getId(), this.getCustomId(), this.getDisplay()); + LoadBalancer lb = _lbService.findById(policy.getLoadBalancerId()); + LBStickinessResponse spResponse = _responseGenerator.createLBStickinessPolicyResponse(policy, lb); + setResponseObject(spResponse); + spResponse.setResponseName(getCommandName()); + } + + @Override + public void checkUuid() { + if (this.getCustomId() != null) { + _uuidMgr.checkUuid(this.getCustomId(), StickinessPolicy.class); + } + } +} diff --git a/api/src/org/apache/cloudstack/api/command/user/nat/CreateIpForwardingRuleCmd.java b/api/src/org/apache/cloudstack/api/command/user/nat/CreateIpForwardingRuleCmd.java index 77edbfccca..8925d066fe 100644 --- a/api/src/org/apache/cloudstack/api/command/user/nat/CreateIpForwardingRuleCmd.java +++ b/api/src/org/apache/cloudstack/api/command/user/nat/CreateIpForwardingRuleCmd.java @@ -20,7 +20,6 @@ import org.apache.log4j.Logger; -import org.apache.cloudstack.acl.IAMEntityType; import org.apache.cloudstack.api.APICommand; import org.apache.cloudstack.api.ApiCommandJobType; import org.apache.cloudstack.api.ApiConstants; @@ -325,8 +324,8 @@ public boolean isDisplay() { } @Override - public IAMEntityType getEntityType() { - return IAMEntityType.FirewallRule; + public Class getEntityType() { + return FirewallRule.class; } } diff --git a/api/src/org/apache/cloudstack/api/command/user/nat/DisableStaticNatCmd.java b/api/src/org/apache/cloudstack/api/command/user/nat/DisableStaticNatCmd.java index 1df77ec0fd..2a9311e963 100644 --- a/api/src/org/apache/cloudstack/api/command/user/nat/DisableStaticNatCmd.java +++ b/api/src/org/apache/cloudstack/api/command/user/nat/DisableStaticNatCmd.java @@ -34,8 +34,11 @@ import com.cloud.exception.NetworkRuleConflictException; import com.cloud.exception.ResourceUnavailableException; import com.cloud.network.IpAddress; +import com.cloud.network.vpc.Vpc; +import com.cloud.vm.VirtualMachine; @APICommand(name = "disableStaticNat", description = "Disables static rule for given ip address", responseObject = SuccessResponse.class, + entityType = {IpAddress.class, VirtualMachine.class, Vpc.class}, requestHasSensitiveInfo = false, responseHasSensitiveInfo = false) public class DisableStaticNatCmd extends BaseAsyncCmd { public static final Logger s_logger = Logger.getLogger(DeletePortForwardingRuleCmd.class.getName()); @@ -89,7 +92,7 @@ public void execute() throws ResourceUnavailableException, NetworkRuleConflictEx if (result) { SuccessResponse response = new SuccessResponse(getCommandName()); - this.setResponseObject(response); + setResponseObject(response); } else { throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, "Failed to disable static nat"); } 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 aa4e28768a..9d888760fa 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 @@ -18,6 +18,8 @@ import org.apache.log4j.Logger; +import org.apache.cloudstack.acl.SecurityChecker.AccessType; +import org.apache.cloudstack.api.ACL; import org.apache.cloudstack.api.APICommand; import org.apache.cloudstack.api.ApiConstants; import org.apache.cloudstack.api.ApiErrorCode; @@ -33,10 +35,13 @@ import com.cloud.exception.NetworkRuleConflictException; import com.cloud.exception.ResourceUnavailableException; import com.cloud.network.IpAddress; +import com.cloud.network.vpc.Vpc; import com.cloud.user.Account; import com.cloud.uservm.UserVm; +import com.cloud.vm.VirtualMachine; @APICommand(name = "enableStaticNat", description = "Enables static nat for given ip address", responseObject = SuccessResponse.class, + entityType = {IpAddress.class, VirtualMachine.class, Vpc.class}, requestHasSensitiveInfo = false, responseHasSensitiveInfo = false) public class EnableStaticNatCmd extends BaseCmd { public static final Logger s_logger = Logger.getLogger(CreateIpForwardingRuleCmd.class.getName()); @@ -47,10 +52,12 @@ public class EnableStaticNatCmd extends BaseCmd { //////////////// API parameters ///////////////////// ///////////////////////////////////////////////////// + @ACL(accessType = AccessType.OperateEntry) @Parameter(name = ApiConstants.IP_ADDRESS_ID, type = CommandType.UUID, entityType = IPAddressResponse.class, required = true, description = "the public IP " + "address id for which static nat feature is being enabled") private Long ipAddressId; + @ACL(accessType = AccessType.OperateEntry) @Parameter(name = ApiConstants.VIRTUAL_MACHINE_ID, type = CommandType.UUID, entityType = UserVmResponse.class, required = true, description = "the ID of " + "the virtual machine for enabling static nat feature") private Long virtualMachineId; @@ -133,7 +140,7 @@ public void execute() throws ResourceUnavailableException { boolean result = _rulesService.enableStaticNat(ipAddressId, virtualMachineId, getNetworkId(), getVmSecondaryIp()); if (result) { SuccessResponse response = new SuccessResponse(getCommandName()); - this.setResponseObject(response); + setResponseObject(response); } else { throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, "Failed to enable static nat"); } diff --git a/api/src/org/apache/cloudstack/api/command/user/network/CreateNetworkACLCmd.java b/api/src/org/apache/cloudstack/api/command/user/network/CreateNetworkACLCmd.java index e47fa8b2cf..b4d54896d9 100644 --- a/api/src/org/apache/cloudstack/api/command/user/network/CreateNetworkACLCmd.java +++ b/api/src/org/apache/cloudstack/api/command/user/network/CreateNetworkACLCmd.java @@ -103,10 +103,20 @@ public class CreateNetworkACLCmd extends BaseAsyncCreateCmd { // /////////////////////////////////////////////////// // ///////////////// Accessors /////////////////////// // /////////////////////////////////////////////////// + @Deprecated public Boolean getDisplay() { return display; } + @Override + public boolean isDisplay() { + if (display != null) { + return display; + } else { + return true; + } + } + public String getProtocol() { String p = protocol.trim(); // Deal with ICMP(protocol number 1) specially because it need to be paired with icmp type and code diff --git a/api/src/org/apache/cloudstack/api/command/user/network/CreateNetworkACLListCmd.java b/api/src/org/apache/cloudstack/api/command/user/network/CreateNetworkACLListCmd.java index 07156cf944..9aa0bab5ae 100644 --- a/api/src/org/apache/cloudstack/api/command/user/network/CreateNetworkACLListCmd.java +++ b/api/src/org/apache/cloudstack/api/command/user/network/CreateNetworkACLListCmd.java @@ -77,8 +77,13 @@ public Long getVpcId() { return vpcId; } - public Boolean getDisplay() { - return display; + @Override + public boolean isDisplay() { + if (display != null) { + return display; + } else { + return true; + } } // /////////////////////////////////////////////////// @@ -92,7 +97,7 @@ public String getCommandName() { @Override public void create() { - NetworkACL result = _networkACLService.createNetworkACL(getName(), getDescription(), getVpcId(), getDisplay()); + NetworkACL result = _networkACLService.createNetworkACL(getName(), getDescription(), getVpcId(), isDisplay()); setEntityId(result.getId()); setEntityUuid(result.getUuid()); } diff --git a/api/src/org/apache/cloudstack/api/command/user/network/CreateNetworkCmd.java b/api/src/org/apache/cloudstack/api/command/user/network/CreateNetworkCmd.java index 3ecec7bde8..40bf5875f5 100644 --- a/api/src/org/apache/cloudstack/api/command/user/network/CreateNetworkCmd.java +++ b/api/src/org/apache/cloudstack/api/command/user/network/CreateNetworkCmd.java @@ -18,7 +18,6 @@ import org.apache.log4j.Logger; -import org.apache.cloudstack.acl.IAMEntityType; import org.apache.cloudstack.acl.RoleType; import org.apache.cloudstack.api.APICommand; import org.apache.cloudstack.api.ApiConstants; @@ -45,7 +44,7 @@ import com.cloud.network.Network.GuestType; import com.cloud.offering.NetworkOffering; -@APICommand(name = "createNetwork", description = "Creates a network", responseObject = NetworkResponse.class, responseView = ResponseView.Restricted, entityType = {IAMEntityType.Network}, +@APICommand(name = "createNetwork", description = "Creates a network", responseObject = NetworkResponse.class, responseView = ResponseView.Restricted, entityType = {Network.class}, requestHasSensitiveInfo = false, responseHasSensitiveInfo = false) public class CreateNetworkCmd extends BaseCmd { public static final Logger s_logger = Logger.getLogger(CreateNetworkCmd.class.getName()); @@ -213,6 +212,14 @@ public Boolean getDisplayNetwork() { return displayNetwork; } + @Override + public boolean isDisplay() { + if(displayNetwork == null) + return true; + else + return displayNetwork; + } + public Long getZoneId() { Long physicalNetworkId = getPhysicalNetworkId(); diff --git a/api/src/org/apache/cloudstack/api/command/user/network/DeleteNetworkCmd.java b/api/src/org/apache/cloudstack/api/command/user/network/DeleteNetworkCmd.java index 50bc94a126..4c3a292c4a 100644 --- a/api/src/org/apache/cloudstack/api/command/user/network/DeleteNetworkCmd.java +++ b/api/src/org/apache/cloudstack/api/command/user/network/DeleteNetworkCmd.java @@ -18,7 +18,6 @@ import org.apache.log4j.Logger; -import org.apache.cloudstack.acl.IAMEntityType; import org.apache.cloudstack.acl.SecurityChecker.AccessType; import org.apache.cloudstack.api.ACL; import org.apache.cloudstack.api.APICommand; @@ -36,7 +35,7 @@ import com.cloud.exception.InvalidParameterValueException; import com.cloud.network.Network; -@APICommand(name = "deleteNetwork", description = "Deletes a network", responseObject = SuccessResponse.class, entityType = {IAMEntityType.Network}, +@APICommand(name = "deleteNetwork", description = "Deletes a network", responseObject = SuccessResponse.class, entityType = {Network.class}, requestHasSensitiveInfo = false, responseHasSensitiveInfo = false) public class DeleteNetworkCmd extends BaseAsyncCmd { public static final Logger s_logger = Logger.getLogger(DeleteNetworkOfferingCmd.class.getName()); diff --git a/api/src/org/apache/cloudstack/api/command/user/network/ListNetworkOfferingsCmd.java b/api/src/org/apache/cloudstack/api/command/user/network/ListNetworkOfferingsCmd.java index a08e28fb6d..6ac0f395b7 100644 --- a/api/src/org/apache/cloudstack/api/command/user/network/ListNetworkOfferingsCmd.java +++ b/api/src/org/apache/cloudstack/api/command/user/network/ListNetworkOfferingsCmd.java @@ -36,7 +36,7 @@ requestHasSensitiveInfo = false, responseHasSensitiveInfo = false) public class ListNetworkOfferingsCmd extends BaseListCmd { public static final Logger s_logger = Logger.getLogger(ListNetworkOfferingsCmd.class.getName()); - private static final String Name = "listnetworkofferingsresponse"; + private static final String s_name = "listnetworkofferingsresponse"; ///////////////////////////////////////////////////// //////////////// API parameters ///////////////////// @@ -182,7 +182,7 @@ public Boolean getForVpc() { ///////////////////////////////////////////////////// @Override public String getCommandName() { - return Name; + return s_name; } @Override diff --git a/api/src/org/apache/cloudstack/api/command/user/network/ListNetworksCmd.java b/api/src/org/apache/cloudstack/api/command/user/network/ListNetworksCmd.java index 455d8dc6a0..86f3ba2ad6 100644 --- a/api/src/org/apache/cloudstack/api/command/user/network/ListNetworksCmd.java +++ b/api/src/org/apache/cloudstack/api/command/user/network/ListNetworksCmd.java @@ -21,7 +21,6 @@ import org.apache.log4j.Logger; -import org.apache.cloudstack.acl.IAMEntityType; import org.apache.cloudstack.acl.RoleType; import org.apache.cloudstack.api.APICommand; import org.apache.cloudstack.api.ApiConstants; @@ -37,11 +36,11 @@ import com.cloud.network.Network; import com.cloud.utils.Pair; -@APICommand(name = "listNetworks", description = "Lists all available networks.", responseObject = NetworkResponse.class, responseView = ResponseView.Restricted, entityType = { IAMEntityType.Network }, +@APICommand(name = "listNetworks", description = "Lists all available networks.", responseObject = NetworkResponse.class, responseView = ResponseView.Restricted, entityType = {Network.class}, requestHasSensitiveInfo = false, responseHasSensitiveInfo = false) public class ListNetworksCmd extends BaseListTaggedResourcesCmd { public static final Logger s_logger = Logger.getLogger(ListNetworksCmd.class.getName()); - private static final String Name = "listnetworksresponse"; + private static final String s_name = "listnetworksresponse"; ///////////////////////////////////////////////////// //////////////// API parameters ///////////////////// @@ -156,7 +155,7 @@ public Boolean getDisplay() { ///////////////////////////////////////////////////// @Override public String getCommandName() { - return Name; + return s_name; } @Override diff --git a/api/src/org/apache/cloudstack/api/command/user/network/RestartNetworkCmd.java b/api/src/org/apache/cloudstack/api/command/user/network/RestartNetworkCmd.java index 6baafda7c8..eba8310421 100644 --- a/api/src/org/apache/cloudstack/api/command/user/network/RestartNetworkCmd.java +++ b/api/src/org/apache/cloudstack/api/command/user/network/RestartNetworkCmd.java @@ -18,7 +18,6 @@ import org.apache.log4j.Logger; -import org.apache.cloudstack.acl.IAMEntityType; import org.apache.cloudstack.acl.SecurityChecker.AccessType; import org.apache.cloudstack.api.ACL; import org.apache.cloudstack.api.APICommand; @@ -41,7 +40,7 @@ @APICommand(name = "restartNetwork", description = "Restarts the network; includes 1) restarting network elements - virtual routers, dhcp servers 2) reapplying all public ips 3) reapplying loadBalancing/portForwarding rules", - responseObject = IPAddressResponse.class, entityType = {IAMEntityType.Network}, + responseObject = IPAddressResponse.class, entityType = {Network.class}, requestHasSensitiveInfo = false, responseHasSensitiveInfo = false) public class RestartNetworkCmd extends BaseAsyncCmd { diff --git a/api/src/org/apache/cloudstack/api/command/user/network/UpdateNetworkACLItemCmd.java b/api/src/org/apache/cloudstack/api/command/user/network/UpdateNetworkACLItemCmd.java index eb095df209..59ae05df40 100644 --- a/api/src/org/apache/cloudstack/api/command/user/network/UpdateNetworkACLItemCmd.java +++ b/api/src/org/apache/cloudstack/api/command/user/network/UpdateNetworkACLItemCmd.java @@ -88,8 +88,14 @@ public class UpdateNetworkACLItemCmd extends BaseAsyncCustomIdCmd { // /////////////////////////////////////////////////// // ///////////////// Accessors /////////////////////// // /////////////////////////////////////////////////// - public Boolean getDisplay() { - return display; + + @Override + public boolean isDisplay() { + if (display != null) { + return display; + } else { + return true; + } } public Long getId() { @@ -172,7 +178,7 @@ public void execute() throws ResourceUnavailableException { CallContext.current().setEventDetails("Rule Id: " + getId()); NetworkACLItem aclItem = _networkACLService.updateNetworkACLItem(getId(), getProtocol(), getSourceCidrList(), getTrafficType(), getAction(), getNumber(), getSourcePortStart(), - getSourcePortEnd(), getIcmpCode(), getIcmpType(), this.getCustomId(), this.getDisplay()); + getSourcePortEnd(), getIcmpCode(), getIcmpType(), this.getCustomId(), this.isDisplay()); if (aclItem == null) { throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, "Failed to update network ACL Item"); } diff --git a/api/src/org/apache/cloudstack/api/command/user/network/UpdateNetworkCmd.java b/api/src/org/apache/cloudstack/api/command/user/network/UpdateNetworkCmd.java index aea7448ab3..0f73ddef93 100644 --- a/api/src/org/apache/cloudstack/api/command/user/network/UpdateNetworkCmd.java +++ b/api/src/org/apache/cloudstack/api/command/user/network/UpdateNetworkCmd.java @@ -18,7 +18,6 @@ import org.apache.log4j.Logger; -import org.apache.cloudstack.acl.IAMEntityType; import org.apache.cloudstack.acl.RoleType; import org.apache.cloudstack.acl.SecurityChecker.AccessType; import org.apache.cloudstack.api.ACL; @@ -43,7 +42,7 @@ import com.cloud.user.Account; import com.cloud.user.User; -@APICommand(name = "updateNetwork", description = "Updates a network", responseObject = NetworkResponse.class, responseView = ResponseView.Restricted, entityType = {IAMEntityType.Network}, +@APICommand(name = "updateNetwork", description = "Updates a network", responseObject = NetworkResponse.class, responseView = ResponseView.Restricted, entityType = {Network.class}, requestHasSensitiveInfo = false, responseHasSensitiveInfo = false) public class UpdateNetworkCmd extends BaseAsyncCustomIdCmd { public static final Logger s_logger = Logger.getLogger(UpdateNetworkCmd.class.getName()); diff --git a/api/src/org/apache/cloudstack/api/command/user/resource/UpdateResourceCountCmd.java b/api/src/org/apache/cloudstack/api/command/user/resource/UpdateResourceCountCmd.java index 5a417496eb..81d725b919 100644 --- a/api/src/org/apache/cloudstack/api/command/user/resource/UpdateResourceCountCmd.java +++ b/api/src/org/apache/cloudstack/api/command/user/resource/UpdateResourceCountCmd.java @@ -106,7 +106,7 @@ public String getCommandName() { @Override public long getEntityOwnerId() { Account account = CallContext.current().getCallingAccount(); - if ((account == null) || _accountService.isAdmin(account.getType())) { + if ((account == null) || _accountService.isAdmin(account.getId())) { if ((domainId != null) && (accountName != null)) { Account userAccount = _responseGenerator.findAccountByNameDomain(accountName, domainId); if (userAccount != null) { diff --git a/api/src/org/apache/cloudstack/api/command/user/securitygroup/AuthorizeSecurityGroupEgressCmd.java b/api/src/org/apache/cloudstack/api/command/user/securitygroup/AuthorizeSecurityGroupEgressCmd.java index 96509f1081..9909bf3085 100644 --- a/api/src/org/apache/cloudstack/api/command/user/securitygroup/AuthorizeSecurityGroupEgressCmd.java +++ b/api/src/org/apache/cloudstack/api/command/user/securitygroup/AuthorizeSecurityGroupEgressCmd.java @@ -24,7 +24,6 @@ import org.apache.log4j.Logger; -import org.apache.cloudstack.acl.IAMEntityType; import org.apache.cloudstack.acl.SecurityChecker.AccessType; import org.apache.cloudstack.api.ACL; import org.apache.cloudstack.api.APICommand; @@ -42,10 +41,11 @@ import com.cloud.event.EventTypes; import com.cloud.exception.InvalidParameterValueException; +import com.cloud.network.security.SecurityGroup; import com.cloud.network.security.SecurityRule; import com.cloud.utils.StringUtils; -@APICommand(name = "authorizeSecurityGroupEgress", responseObject = SecurityGroupRuleResponse.class, description = "Authorizes a particular egress rule for this security group", since = "3.0.0", entityType = {IAMEntityType.SecurityGroup}, +@APICommand(name = "authorizeSecurityGroupEgress", responseObject = SecurityGroupRuleResponse.class, description = "Authorizes a particular egress rule for this security group", since = "3.0.0", entityType = {SecurityGroup.class}, requestHasSensitiveInfo = false, responseHasSensitiveInfo = false) @SuppressWarnings("rawtypes") @@ -95,7 +95,8 @@ public class AuthorizeSecurityGroupEgressCmd extends BaseAsyncCmd { @Parameter(name=ApiConstants.SECURITY_GROUP_ID, type=CommandType.UUID, description="The ID of the security group. Mutually exclusive with securityGroupName parameter", entityType=SecurityGroupResponse.class) private Long securityGroupId; - @ACL(accessType = AccessType.OperateEntry) + // This @ACL will not work, since we don't have a way to convert this parameter to the entity like securityGroupId. + //@ACL(accessType = AccessType.OperateEntry) @Parameter(name=ApiConstants.SECURITY_GROUP_NAME, type=CommandType.STRING, description="The name of the security group. Mutually exclusive with securityGroupName parameter") private String securityGroupName; diff --git a/api/src/org/apache/cloudstack/api/command/user/securitygroup/AuthorizeSecurityGroupIngressCmd.java b/api/src/org/apache/cloudstack/api/command/user/securitygroup/AuthorizeSecurityGroupIngressCmd.java index 1e324e2a1e..3549d5139d 100644 --- a/api/src/org/apache/cloudstack/api/command/user/securitygroup/AuthorizeSecurityGroupIngressCmd.java +++ b/api/src/org/apache/cloudstack/api/command/user/securitygroup/AuthorizeSecurityGroupIngressCmd.java @@ -24,7 +24,6 @@ import org.apache.log4j.Logger; -import org.apache.cloudstack.acl.IAMEntityType; import org.apache.cloudstack.acl.SecurityChecker.AccessType; import org.apache.cloudstack.api.ACL; import org.apache.cloudstack.api.APICommand; @@ -42,10 +41,11 @@ import com.cloud.event.EventTypes; import com.cloud.exception.InvalidParameterValueException; +import com.cloud.network.security.SecurityGroup; import com.cloud.network.security.SecurityRule; import com.cloud.utils.StringUtils; -@APICommand(name = "authorizeSecurityGroupIngress", responseObject = SecurityGroupRuleResponse.class, description = "Authorizes a particular ingress rule for this security group", entityType = {IAMEntityType.SecurityGroup}, +@APICommand(name = "authorizeSecurityGroupIngress", responseObject = SecurityGroupRuleResponse.class, description = "Authorizes a particular ingress rule for this security group", entityType = {SecurityGroup.class}, requestHasSensitiveInfo = false, responseHasSensitiveInfo = false) @SuppressWarnings("rawtypes") @@ -95,7 +95,8 @@ public class AuthorizeSecurityGroupIngressCmd extends BaseAsyncCmd { @Parameter(name=ApiConstants.SECURITY_GROUP_ID, type=CommandType.UUID, description="The ID of the security group. Mutually exclusive with securityGroupName parameter", entityType=SecurityGroupResponse.class) private Long securityGroupId; - @ACL(accessType = AccessType.OperateEntry) + // This @ACL will not work, since we don't have a way to convert this parameter to the entity like securityGroupId. + //@ACL(accessType = AccessType.OperateEntry) @Parameter(name=ApiConstants.SECURITY_GROUP_NAME, type=CommandType.STRING, description="The name of the security group. Mutually exclusive with securityGroupName parameter") private String securityGroupName; diff --git a/api/src/org/apache/cloudstack/api/command/user/securitygroup/CreateSecurityGroupCmd.java b/api/src/org/apache/cloudstack/api/command/user/securitygroup/CreateSecurityGroupCmd.java index 1f7f872f1e..d3d35bc0b3 100644 --- a/api/src/org/apache/cloudstack/api/command/user/securitygroup/CreateSecurityGroupCmd.java +++ b/api/src/org/apache/cloudstack/api/command/user/securitygroup/CreateSecurityGroupCmd.java @@ -18,7 +18,6 @@ import org.apache.log4j.Logger; -import org.apache.cloudstack.acl.IAMEntityType; import org.apache.cloudstack.api.APICommand; import org.apache.cloudstack.api.ApiConstants; import org.apache.cloudstack.api.ApiErrorCode; @@ -33,7 +32,7 @@ import com.cloud.network.security.SecurityGroup; import com.cloud.user.Account; -@APICommand(name = "createSecurityGroup", responseObject = SecurityGroupResponse.class, description = "Creates a security group", entityType = {IAMEntityType.SecurityGroup}, +@APICommand(name = "createSecurityGroup", responseObject = SecurityGroupResponse.class, description = "Creates a security group", entityType = {SecurityGroup.class}, requestHasSensitiveInfo = false, responseHasSensitiveInfo = false) public class CreateSecurityGroupCmd extends BaseCmd { public static final Logger s_logger = Logger.getLogger(CreateSecurityGroupCmd.class.getName()); @@ -98,7 +97,7 @@ public String getCommandName() { @Override public long getEntityOwnerId() { Account account = CallContext.current().getCallingAccount(); - if ((account == null) || _accountService.isAdmin(account.getType())) { + if ((account == null) || _accountService.isAdmin(account.getId())) { if ((domainId != null) && (accountName != null)) { Account userAccount = _responseGenerator.findAccountByNameDomain(accountName, domainId); if (userAccount != null) { diff --git a/api/src/org/apache/cloudstack/api/command/user/securitygroup/DeleteSecurityGroupCmd.java b/api/src/org/apache/cloudstack/api/command/user/securitygroup/DeleteSecurityGroupCmd.java index 827c7d7389..87e6df41b6 100644 --- a/api/src/org/apache/cloudstack/api/command/user/securitygroup/DeleteSecurityGroupCmd.java +++ b/api/src/org/apache/cloudstack/api/command/user/securitygroup/DeleteSecurityGroupCmd.java @@ -18,7 +18,6 @@ import org.apache.log4j.Logger; -import org.apache.cloudstack.acl.IAMEntityType; import org.apache.cloudstack.acl.SecurityChecker.AccessType; import org.apache.cloudstack.api.ACL; import org.apache.cloudstack.api.APICommand; @@ -35,8 +34,9 @@ import com.cloud.exception.InvalidParameterValueException; import com.cloud.exception.ResourceInUseException; +import com.cloud.network.security.SecurityGroup; -@APICommand(name = "deleteSecurityGroup", description = "Deletes security group", responseObject = SuccessResponse.class, entityType = {IAMEntityType.SecurityGroup}, +@APICommand(name = "deleteSecurityGroup", description = "Deletes security group", responseObject = SuccessResponse.class, entityType = {SecurityGroup.class}, requestHasSensitiveInfo = false, responseHasSensitiveInfo = false) public class DeleteSecurityGroupCmd extends BaseCmd { public static final Logger s_logger = Logger.getLogger(DeleteSecurityGroupCmd.class.getName()); diff --git a/api/src/org/apache/cloudstack/api/command/user/securitygroup/ListSecurityGroupsCmd.java b/api/src/org/apache/cloudstack/api/command/user/securitygroup/ListSecurityGroupsCmd.java index 02be63d0b4..4a8081a350 100644 --- a/api/src/org/apache/cloudstack/api/command/user/securitygroup/ListSecurityGroupsCmd.java +++ b/api/src/org/apache/cloudstack/api/command/user/securitygroup/ListSecurityGroupsCmd.java @@ -18,7 +18,6 @@ import org.apache.log4j.Logger; -import org.apache.cloudstack.acl.IAMEntityType; import org.apache.cloudstack.api.APICommand; import org.apache.cloudstack.api.ApiCommandJobType; import org.apache.cloudstack.api.ApiConstants; @@ -28,7 +27,9 @@ import org.apache.cloudstack.api.response.SecurityGroupResponse; import org.apache.cloudstack.api.response.UserVmResponse; -@APICommand(name = "listSecurityGroups", description = "Lists security groups", responseObject = SecurityGroupResponse.class, entityType = {IAMEntityType.SecurityGroup}, +import com.cloud.network.security.SecurityGroup; + +@APICommand(name = "listSecurityGroups", description = "Lists security groups", responseObject = SecurityGroupResponse.class, entityType = {SecurityGroup.class}, requestHasSensitiveInfo = false, responseHasSensitiveInfo = false) public class ListSecurityGroupsCmd extends BaseListTaggedResourcesCmd { public static final Logger s_logger = Logger.getLogger(ListSecurityGroupsCmd.class.getName()); diff --git a/api/src/org/apache/cloudstack/api/command/user/securitygroup/RevokeSecurityGroupEgressCmd.java b/api/src/org/apache/cloudstack/api/command/user/securitygroup/RevokeSecurityGroupEgressCmd.java index d1ffc1e5ea..a28a220b53 100644 --- a/api/src/org/apache/cloudstack/api/command/user/securitygroup/RevokeSecurityGroupEgressCmd.java +++ b/api/src/org/apache/cloudstack/api/command/user/securitygroup/RevokeSecurityGroupEgressCmd.java @@ -18,7 +18,6 @@ import org.apache.log4j.Logger; -import org.apache.cloudstack.acl.IAMEntityType; import org.apache.cloudstack.api.APICommand; import org.apache.cloudstack.api.ApiCommandJobType; import org.apache.cloudstack.api.ApiConstants; @@ -35,7 +34,7 @@ import com.cloud.user.Account; -@APICommand(name = "revokeSecurityGroupEgress", responseObject = SuccessResponse.class, description = "Deletes a particular egress rule from this security group", since = "3.0.0", entityType = {IAMEntityType.SecurityGroup}, +@APICommand(name = "revokeSecurityGroupEgress", responseObject = SuccessResponse.class, description = "Deletes a particular egress rule from this security group", since = "3.0.0", entityType = {SecurityGroup.class}, requestHasSensitiveInfo = false, responseHasSensitiveInfo = false) public class RevokeSecurityGroupEgressCmd extends BaseAsyncCmd { diff --git a/api/src/org/apache/cloudstack/api/command/user/securitygroup/RevokeSecurityGroupIngressCmd.java b/api/src/org/apache/cloudstack/api/command/user/securitygroup/RevokeSecurityGroupIngressCmd.java index 8543e0e1de..9e81d0bc4e 100644 --- a/api/src/org/apache/cloudstack/api/command/user/securitygroup/RevokeSecurityGroupIngressCmd.java +++ b/api/src/org/apache/cloudstack/api/command/user/securitygroup/RevokeSecurityGroupIngressCmd.java @@ -18,7 +18,6 @@ import org.apache.log4j.Logger; -import org.apache.cloudstack.acl.IAMEntityType; import org.apache.cloudstack.acl.SecurityChecker.AccessType; import org.apache.cloudstack.api.ACL; import org.apache.cloudstack.api.APICommand; @@ -36,7 +35,7 @@ import com.cloud.network.security.SecurityRule; import com.cloud.user.Account; -@APICommand(name = "revokeSecurityGroupIngress", responseObject = SuccessResponse.class, description = "Deletes a particular ingress rule from this security group", entityType = {IAMEntityType.SecurityGroup}, +@APICommand(name = "revokeSecurityGroupIngress", responseObject = SuccessResponse.class, description = "Deletes a particular ingress rule from this security group", entityType = {SecurityGroup.class}, requestHasSensitiveInfo = false, responseHasSensitiveInfo = false) public class RevokeSecurityGroupIngressCmd extends BaseAsyncCmd { public static final Logger s_logger = Logger.getLogger(RevokeSecurityGroupIngressCmd.class.getName()); diff --git a/api/src/org/apache/cloudstack/api/command/user/snapshot/CreateSnapshotCmd.java b/api/src/org/apache/cloudstack/api/command/user/snapshot/CreateSnapshotCmd.java index 2020518528..bd8662e146 100644 --- a/api/src/org/apache/cloudstack/api/command/user/snapshot/CreateSnapshotCmd.java +++ b/api/src/org/apache/cloudstack/api/command/user/snapshot/CreateSnapshotCmd.java @@ -18,7 +18,7 @@ import org.apache.log4j.Logger; -import org.apache.cloudstack.acl.IAMEntityType; +import org.apache.cloudstack.api.ACL; import org.apache.cloudstack.api.APICommand; import org.apache.cloudstack.api.ApiCommandJobType; import org.apache.cloudstack.api.ApiConstants; @@ -42,7 +42,7 @@ import com.cloud.storage.Volume; import com.cloud.user.Account; -@APICommand(name = "createSnapshot", description = "Creates an instant snapshot of a volume.", responseObject = SnapshotResponse.class, entityType = {IAMEntityType.Snapshot}, +@APICommand(name = "createSnapshot", description = "Creates an instant snapshot of a volume.", responseObject = SnapshotResponse.class, entityType = {Snapshot.class}, requestHasSensitiveInfo = false, responseHasSensitiveInfo = false) public class CreateSnapshotCmd extends BaseAsyncCreateCmd { public static final Logger s_logger = Logger.getLogger(CreateSnapshotCmd.class.getName()); @@ -63,6 +63,7 @@ public class CreateSnapshotCmd extends BaseAsyncCreateCmd { description = "The domain ID of the snapshot. If used with the account parameter, specifies a domain for the account associated with the disk volume.") private Long domainId; + @ACL @Parameter(name = ApiConstants.VOLUME_ID, type = CommandType.UUID, entityType = VolumeResponse.class, required = true, description = "The ID of the disk volume") private Long volumeId; diff --git a/api/src/org/apache/cloudstack/api/command/user/snapshot/DeleteSnapshotCmd.java b/api/src/org/apache/cloudstack/api/command/user/snapshot/DeleteSnapshotCmd.java index 7d57c21459..64a432d0bc 100644 --- a/api/src/org/apache/cloudstack/api/command/user/snapshot/DeleteSnapshotCmd.java +++ b/api/src/org/apache/cloudstack/api/command/user/snapshot/DeleteSnapshotCmd.java @@ -18,7 +18,6 @@ import org.apache.log4j.Logger; -import org.apache.cloudstack.acl.IAMEntityType; import org.apache.cloudstack.acl.SecurityChecker.AccessType; import org.apache.cloudstack.api.ACL; import org.apache.cloudstack.api.APICommand; @@ -36,7 +35,7 @@ import com.cloud.storage.Snapshot; import com.cloud.user.Account; -@APICommand(name = "deleteSnapshot", description = "Deletes a snapshot of a disk volume.", responseObject = SuccessResponse.class, entityType = {IAMEntityType.Snapshot}, +@APICommand(name = "deleteSnapshot", description = "Deletes a snapshot of a disk volume.", responseObject = SuccessResponse.class, entityType = {Snapshot.class}, requestHasSensitiveInfo = false, responseHasSensitiveInfo = false) public class DeleteSnapshotCmd extends BaseAsyncCmd { public static final Logger s_logger = Logger.getLogger(DeleteSnapshotCmd.class.getName()); diff --git a/api/src/org/apache/cloudstack/api/command/user/snapshot/ListSnapshotsCmd.java b/api/src/org/apache/cloudstack/api/command/user/snapshot/ListSnapshotsCmd.java index ed26e7ff6f..47a6876d09 100644 --- a/api/src/org/apache/cloudstack/api/command/user/snapshot/ListSnapshotsCmd.java +++ b/api/src/org/apache/cloudstack/api/command/user/snapshot/ListSnapshotsCmd.java @@ -21,7 +21,6 @@ import org.apache.log4j.Logger; -import org.apache.cloudstack.acl.IAMEntityType; import org.apache.cloudstack.api.APICommand; import org.apache.cloudstack.api.ApiCommandJobType; import org.apache.cloudstack.api.ApiConstants; @@ -35,7 +34,7 @@ import com.cloud.storage.Snapshot; import com.cloud.utils.Pair; -@APICommand(name = "listSnapshots", description = "Lists all available snapshots for the account.", responseObject = SnapshotResponse.class, entityType = {IAMEntityType.Snapshot}, +@APICommand(name = "listSnapshots", description = "Lists all available snapshots for the account.", responseObject = SnapshotResponse.class, entityType = {Snapshot.class}, requestHasSensitiveInfo = false, responseHasSensitiveInfo = false) public class ListSnapshotsCmd extends BaseListTaggedResourcesCmd { public static final Logger s_logger = Logger.getLogger(ListSnapshotsCmd.class.getName()); diff --git a/api/src/org/apache/cloudstack/api/command/user/snapshot/RevertSnapshotCmd.java b/api/src/org/apache/cloudstack/api/command/user/snapshot/RevertSnapshotCmd.java index ab83812262..0c79f81564 100644 --- a/api/src/org/apache/cloudstack/api/command/user/snapshot/RevertSnapshotCmd.java +++ b/api/src/org/apache/cloudstack/api/command/user/snapshot/RevertSnapshotCmd.java @@ -18,7 +18,6 @@ */ package org.apache.cloudstack.api.command.user.snapshot; -import org.apache.cloudstack.acl.IAMEntityType; import org.apache.cloudstack.acl.SecurityChecker.AccessType; import org.apache.cloudstack.api.ACL; import org.apache.cloudstack.api.APICommand; @@ -37,7 +36,7 @@ import com.cloud.storage.Snapshot; import com.cloud.user.Account; -@APICommand(name = "revertSnapshot", description = "revert a volume snapshot.", responseObject = SnapshotResponse.class, entityType = {IAMEntityType.Snapshot}, +@APICommand(name = "revertSnapshot", description = "revert a volume snapshot.", responseObject = SnapshotResponse.class, entityType = {Snapshot.class}, requestHasSensitiveInfo = false, responseHasSensitiveInfo = false) public class RevertSnapshotCmd extends BaseAsyncCmd { private static final String s_name = "revertsnapshotresponse"; diff --git a/api/src/org/apache/cloudstack/api/command/user/ssh/CreateSSHKeyPairCmd.java b/api/src/org/apache/cloudstack/api/command/user/ssh/CreateSSHKeyPairCmd.java index a0f05d18d3..bd7f613f89 100644 --- a/api/src/org/apache/cloudstack/api/command/user/ssh/CreateSSHKeyPairCmd.java +++ b/api/src/org/apache/cloudstack/api/command/user/ssh/CreateSSHKeyPairCmd.java @@ -18,7 +18,6 @@ import org.apache.log4j.Logger; -import org.apache.cloudstack.acl.IAMEntityType; import org.apache.cloudstack.api.APICommand; import org.apache.cloudstack.api.ApiConstants; import org.apache.cloudstack.api.BaseCmd; @@ -30,7 +29,7 @@ import com.cloud.user.SSHKeyPair; -@APICommand(name = "createSSHKeyPair", description = "Create a new keypair and returns the private key", responseObject = CreateSSHKeyPairResponse.class, entityType = {IAMEntityType.SSHKeyPair}, +@APICommand(name = "createSSHKeyPair", description = "Create a new keypair and returns the private key", responseObject = CreateSSHKeyPairResponse.class, entityType = {SSHKeyPair.class}, requestHasSensitiveInfo = false, responseHasSensitiveInfo = true) public class CreateSSHKeyPairCmd extends BaseCmd { public static final Logger s_logger = Logger.getLogger(CreateSSHKeyPairCmd.class.getName()); diff --git a/api/src/org/apache/cloudstack/api/command/user/ssh/DeleteSSHKeyPairCmd.java b/api/src/org/apache/cloudstack/api/command/user/ssh/DeleteSSHKeyPairCmd.java index d0a5234e05..9258587735 100644 --- a/api/src/org/apache/cloudstack/api/command/user/ssh/DeleteSSHKeyPairCmd.java +++ b/api/src/org/apache/cloudstack/api/command/user/ssh/DeleteSSHKeyPairCmd.java @@ -19,7 +19,6 @@ import org.apache.log4j.Logger; -import org.apache.cloudstack.acl.IAMEntityType; import org.apache.cloudstack.api.APICommand; import org.apache.cloudstack.api.ApiConstants; import org.apache.cloudstack.api.BaseCmd; @@ -30,8 +29,9 @@ import org.apache.cloudstack.context.CallContext; import com.cloud.user.Account; +import com.cloud.user.SSHKeyPair; -@APICommand(name = "deleteSSHKeyPair", description = "Deletes a keypair by name", responseObject = SuccessResponse.class, entityType = {IAMEntityType.SSHKeyPair}, +@APICommand(name = "deleteSSHKeyPair", description = "Deletes a keypair by name", responseObject = SuccessResponse.class, entityType = {SSHKeyPair.class}, requestHasSensitiveInfo = false, responseHasSensitiveInfo = false) public class DeleteSSHKeyPairCmd extends BaseCmd { public static final Logger s_logger = Logger.getLogger(CreateSSHKeyPairCmd.class.getName()); @@ -93,7 +93,7 @@ public String getCommandName() { @Override public long getEntityOwnerId() { Account account = CallContext.current().getCallingAccount(); - if ((account == null) || _accountService.isAdmin(account.getType())) { + if ((account == null) || _accountService.isAdmin(account.getId())) { if ((domainId != null) && (accountName != null)) { Account userAccount = _responseGenerator.findAccountByNameDomain(accountName, domainId); if (userAccount != null) { diff --git a/api/src/org/apache/cloudstack/api/command/user/ssh/ListSSHKeyPairsCmd.java b/api/src/org/apache/cloudstack/api/command/user/ssh/ListSSHKeyPairsCmd.java index f02bf9f4f5..022cbc5068 100644 --- a/api/src/org/apache/cloudstack/api/command/user/ssh/ListSSHKeyPairsCmd.java +++ b/api/src/org/apache/cloudstack/api/command/user/ssh/ListSSHKeyPairsCmd.java @@ -21,7 +21,6 @@ import org.apache.log4j.Logger; -import org.apache.cloudstack.acl.IAMEntityType; import org.apache.cloudstack.api.APICommand; import org.apache.cloudstack.api.ApiConstants; import org.apache.cloudstack.api.BaseListProjectAndAccountResourcesCmd; @@ -32,7 +31,7 @@ import com.cloud.user.SSHKeyPair; import com.cloud.utils.Pair; -@APICommand(name = "listSSHKeyPairs", description = "List registered keypairs", responseObject = SSHKeyPairResponse.class, entityType = {IAMEntityType.SSHKeyPair}, +@APICommand(name = "listSSHKeyPairs", description = "List registered keypairs", responseObject = SSHKeyPairResponse.class, entityType = {SSHKeyPair.class}, requestHasSensitiveInfo = false, responseHasSensitiveInfo = false) public class ListSSHKeyPairsCmd extends BaseListProjectAndAccountResourcesCmd { public static final Logger s_logger = Logger.getLogger(ListSSHKeyPairsCmd.class.getName()); diff --git a/api/src/org/apache/cloudstack/api/command/user/ssh/RegisterSSHKeyPairCmd.java b/api/src/org/apache/cloudstack/api/command/user/ssh/RegisterSSHKeyPairCmd.java index e095227d98..c7cbc56ae6 100644 --- a/api/src/org/apache/cloudstack/api/command/user/ssh/RegisterSSHKeyPairCmd.java +++ b/api/src/org/apache/cloudstack/api/command/user/ssh/RegisterSSHKeyPairCmd.java @@ -18,7 +18,6 @@ import org.apache.log4j.Logger; -import org.apache.cloudstack.acl.IAMEntityType; import org.apache.cloudstack.api.APICommand; import org.apache.cloudstack.api.ApiConstants; import org.apache.cloudstack.api.BaseCmd; @@ -30,7 +29,7 @@ import com.cloud.user.SSHKeyPair; -@APICommand(name = "registerSSHKeyPair", description = "Register a public key in a keypair under a certain name", responseObject = SSHKeyPairResponse.class, entityType = {IAMEntityType.SSHKeyPair}, +@APICommand(name = "registerSSHKeyPair", description = "Register a public key in a keypair under a certain name", responseObject = SSHKeyPairResponse.class, entityType = {SSHKeyPair.class}, requestHasSensitiveInfo = false, responseHasSensitiveInfo = false) public class RegisterSSHKeyPairCmd extends BaseCmd { public static final Logger s_logger = Logger.getLogger(RegisterSSHKeyPairCmd.class.getName()); diff --git a/api/src/org/apache/cloudstack/api/command/user/tag/CreateTagsCmd.java b/api/src/org/apache/cloudstack/api/command/user/tag/CreateTagsCmd.java index eab114fea8..6aecc05548 100644 --- a/api/src/org/apache/cloudstack/api/command/user/tag/CreateTagsCmd.java +++ b/api/src/org/apache/cloudstack/api/command/user/tag/CreateTagsCmd.java @@ -25,7 +25,6 @@ import org.apache.log4j.Logger; -import org.apache.cloudstack.acl.IAMEntityType; import org.apache.cloudstack.api.APICommand; import org.apache.cloudstack.api.ApiConstants; import org.apache.cloudstack.api.ApiErrorCode; @@ -38,7 +37,7 @@ import com.cloud.server.ResourceTag; import com.cloud.server.ResourceTag.ResourceObjectType; -@APICommand(name = "createTags", description = "Creates resource tag(s)", responseObject = SuccessResponse.class, since = "4.0.0", entityType = {IAMEntityType.ResourceTag}, +@APICommand(name = "createTags", description = "Creates resource tag(s)", responseObject = SuccessResponse.class, since = "4.0.0", entityType = {ResourceTag.class}, requestHasSensitiveInfo = false, responseHasSensitiveInfo = false) public class CreateTagsCmd extends BaseAsyncCmd { public static final Logger s_logger = Logger.getLogger(CreateTagsCmd.class.getName()); diff --git a/api/src/org/apache/cloudstack/api/command/user/tag/DeleteTagsCmd.java b/api/src/org/apache/cloudstack/api/command/user/tag/DeleteTagsCmd.java index 39b6630b61..e42cfce4d9 100644 --- a/api/src/org/apache/cloudstack/api/command/user/tag/DeleteTagsCmd.java +++ b/api/src/org/apache/cloudstack/api/command/user/tag/DeleteTagsCmd.java @@ -25,7 +25,6 @@ import org.apache.log4j.Logger; -import org.apache.cloudstack.acl.IAMEntityType; import org.apache.cloudstack.api.APICommand; import org.apache.cloudstack.api.ApiConstants; import org.apache.cloudstack.api.ApiErrorCode; @@ -35,9 +34,10 @@ import org.apache.cloudstack.api.response.SuccessResponse; import com.cloud.event.EventTypes; +import com.cloud.server.ResourceTag; import com.cloud.server.ResourceTag.ResourceObjectType; -@APICommand(name = "deleteTags", description = "Deleting resource tag(s)", responseObject = SuccessResponse.class, since = "4.0.0", entityType = {IAMEntityType.ResourceTag}, +@APICommand(name = "deleteTags", description = "Deleting resource tag(s)", responseObject = SuccessResponse.class, since = "4.0.0", entityType = {ResourceTag.class}, requestHasSensitiveInfo = false, responseHasSensitiveInfo = false) public class DeleteTagsCmd extends BaseAsyncCmd { public static final Logger s_logger = Logger.getLogger(DeleteTagsCmd.class.getName()); diff --git a/api/src/org/apache/cloudstack/api/command/user/tag/ListTagsCmd.java b/api/src/org/apache/cloudstack/api/command/user/tag/ListTagsCmd.java index b2249104ac..e02b25c446 100644 --- a/api/src/org/apache/cloudstack/api/command/user/tag/ListTagsCmd.java +++ b/api/src/org/apache/cloudstack/api/command/user/tag/ListTagsCmd.java @@ -17,7 +17,6 @@ package org.apache.cloudstack.api.command.user.tag; -import org.apache.cloudstack.acl.IAMEntityType; import org.apache.cloudstack.api.APICommand; import org.apache.cloudstack.api.ApiConstants; import org.apache.cloudstack.api.BaseListProjectAndAccountResourcesCmd; @@ -25,7 +24,9 @@ import org.apache.cloudstack.api.response.ListResponse; import org.apache.cloudstack.api.response.ResourceTagResponse; -@APICommand(name = "listTags", description = "List resource tag(s)", responseObject = ResourceTagResponse.class, since = "4.0.0", entityType = {IAMEntityType.ResourceTag}, +import com.cloud.server.ResourceTag; + +@APICommand(name = "listTags", description = "List resource tag(s)", responseObject = ResourceTagResponse.class, since = "4.0.0", entityType = {ResourceTag.class}, requestHasSensitiveInfo = false, responseHasSensitiveInfo = false) public class ListTagsCmd extends BaseListProjectAndAccountResourcesCmd { private static final String s_name = "listtagsresponse"; diff --git a/api/src/org/apache/cloudstack/api/command/user/template/ListTemplatesCmd.java b/api/src/org/apache/cloudstack/api/command/user/template/ListTemplatesCmd.java index 0be9ab8007..7a2a15834a 100644 --- a/api/src/org/apache/cloudstack/api/command/user/template/ListTemplatesCmd.java +++ b/api/src/org/apache/cloudstack/api/command/user/template/ListTemplatesCmd.java @@ -18,7 +18,6 @@ import org.apache.log4j.Logger; -import org.apache.cloudstack.acl.IAMEntityType; import org.apache.cloudstack.api.APICommand; import org.apache.cloudstack.api.ApiCommandJobType; import org.apache.cloudstack.api.ApiConstants; @@ -30,10 +29,11 @@ import org.apache.cloudstack.api.response.ZoneResponse; import org.apache.cloudstack.context.CallContext; +import com.cloud.template.VirtualMachineTemplate; import com.cloud.template.VirtualMachineTemplate.TemplateFilter; import com.cloud.user.Account; -@APICommand(name = "listTemplates", description = "List all public, private, and privileged templates.", responseObject = TemplateResponse.class, entityType = {IAMEntityType.VirtualMachineTemplate}, responseView = ResponseView.Restricted, +@APICommand(name = "listTemplates", description = "List all public, private, and privileged templates.", responseObject = TemplateResponse.class, entityType = {VirtualMachineTemplate.class}, responseView = ResponseView.Restricted, requestHasSensitiveInfo = false, responseHasSensitiveInfo = false) public class ListTemplatesCmd extends BaseListTaggedResourcesCmd { public static final Logger s_logger = Logger.getLogger(ListTemplatesCmd.class.getName()); @@ -103,7 +103,7 @@ public boolean listInReadyState() { Account account = CallContext.current().getCallingAccount(); // It is account specific if account is admin type and domainId and accountName are not null - boolean isAccountSpecific = (account == null || _accountService.isAdmin(account.getType())) && (getAccountName() != null) && (getDomainId() != null); + boolean isAccountSpecific = (account == null || _accountService.isAdmin(account.getId())) && (getAccountName() != null) && (getDomainId() != null); // Show only those that are downloaded. TemplateFilter templateFilter = TemplateFilter.valueOf(getTemplateFilter()); boolean onlyReady = diff --git a/api/src/org/apache/cloudstack/api/command/user/template/UpdateTemplatePermissionsCmd.java b/api/src/org/apache/cloudstack/api/command/user/template/UpdateTemplatePermissionsCmd.java index d5d0c58742..2029156837 100644 --- a/api/src/org/apache/cloudstack/api/command/user/template/UpdateTemplatePermissionsCmd.java +++ b/api/src/org/apache/cloudstack/api/command/user/template/UpdateTemplatePermissionsCmd.java @@ -18,7 +18,6 @@ import org.apache.log4j.Logger; -import org.apache.cloudstack.acl.IAMEntityType; import org.apache.cloudstack.api.APICommand; import org.apache.cloudstack.api.BaseUpdateTemplateOrIsoPermissionsCmd; import org.apache.cloudstack.api.response.SuccessResponse; @@ -28,7 +27,7 @@ @APICommand(name = "updateTemplatePermissions", responseObject = SuccessResponse.class, description = "Updates a template visibility permissions. " + "A public template is visible to all accounts within the same domain. " + "A private template is visible only to the owner of the template. " - + "A priviledged template is a private template with account permissions added. " + "Only accounts specified under the template permissions are visible to them.", entityType = {IAMEntityType.VirtualMachineTemplate}, + + "A priviledged template is a private template with account permissions added. " + "Only accounts specified under the template permissions are visible to them.", entityType = {VirtualMachineTemplate.class}, requestHasSensitiveInfo = false, responseHasSensitiveInfo = false) public class UpdateTemplatePermissionsCmd extends BaseUpdateTemplateOrIsoPermissionsCmd { @Override diff --git a/api/src/org/apache/cloudstack/api/command/user/vm/AddIpToVmNicCmd.java b/api/src/org/apache/cloudstack/api/command/user/vm/AddIpToVmNicCmd.java index a7f94368dc..870bbbf01e 100644 --- a/api/src/org/apache/cloudstack/api/command/user/vm/AddIpToVmNicCmd.java +++ b/api/src/org/apache/cloudstack/api/command/user/vm/AddIpToVmNicCmd.java @@ -92,6 +92,12 @@ private NetworkType getNetworkType() { return dc.getNetworkType(); } + private boolean isZoneSGEnabled() { + Network ntwk = _entityMgr.findById(Network.class, getNetworkId()); + DataCenter dc = _entityMgr.findById(DataCenter.class, ntwk.getDataCenterId()); + return dc.isSecurityGroupEnabled(); + } + @Override public String getEventType() { return EventTypes.EVENT_NET_IP_ASSIGN; @@ -136,7 +142,7 @@ public void execute() throws ResourceUnavailableException, ResourceAllocationExc if (result != null) { secondaryIp = result.getIp4Address(); - if (getNetworkType() == NetworkType.Basic) { + if (isZoneSGEnabled()) { // add security group rules for the secondary ip addresses boolean success = false; success = _securityGroupService.securityGroupRulesForVmSecIp(getNicId(), secondaryIp, true); diff --git a/api/src/org/apache/cloudstack/api/command/user/vm/AddNicToVMCmd.java b/api/src/org/apache/cloudstack/api/command/user/vm/AddNicToVMCmd.java index a1bbe2a45b..fd30152ae0 100644 --- a/api/src/org/apache/cloudstack/api/command/user/vm/AddNicToVMCmd.java +++ b/api/src/org/apache/cloudstack/api/command/user/vm/AddNicToVMCmd.java @@ -21,7 +21,6 @@ import org.apache.log4j.Logger; -import org.apache.cloudstack.acl.IAMEntityType; import org.apache.cloudstack.acl.SecurityChecker.AccessType; import org.apache.cloudstack.api.ACL; import org.apache.cloudstack.api.APICommand; @@ -39,8 +38,9 @@ import com.cloud.event.EventTypes; import com.cloud.user.Account; import com.cloud.uservm.UserVm; +import com.cloud.vm.VirtualMachine; -@APICommand(name = "addNicToVirtualMachine", description = "Adds VM to specified network by creating a NIC", responseObject = UserVmResponse.class, responseView = ResponseView.Restricted, entityType = {IAMEntityType.VirtualMachine}, +@APICommand(name = "addNicToVirtualMachine", description = "Adds VM to specified network by creating a NIC", responseObject = UserVmResponse.class, responseView = ResponseView.Restricted, entityType = {VirtualMachine.class}, requestHasSensitiveInfo = false, responseHasSensitiveInfo = true) public class AddNicToVMCmd extends BaseAsyncCmd { public static final Logger s_logger = Logger.getLogger(AddNicToVMCmd.class); @@ -54,6 +54,7 @@ public class AddNicToVMCmd extends BaseAsyncCmd { required=true, description="Virtual Machine ID") private Long vmId; + @ACL @Parameter(name = ApiConstants.NETWORK_ID, type = CommandType.UUID, entityType = NetworkResponse.class, required = true, description = "Network ID") private Long netId; 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 0235fcc305..0adc57be64 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 @@ -26,7 +26,6 @@ import org.apache.log4j.Logger; -import org.apache.cloudstack.acl.IAMEntityType; import org.apache.cloudstack.acl.RoleType; import org.apache.cloudstack.acl.SecurityChecker.AccessType; import org.apache.cloudstack.affinity.AffinityGroupResponse; @@ -68,8 +67,9 @@ import com.cloud.template.VirtualMachineTemplate; import com.cloud.user.Account; import com.cloud.uservm.UserVm; +import com.cloud.vm.VirtualMachine; -@APICommand(name = "deployVirtualMachine", description = "Creates and automatically starts a virtual machine based on a service offering, disk offering, and template.", responseObject = UserVmResponse.class, responseView = ResponseView.Restricted, entityType = { IAMEntityType.VirtualMachine }, +@APICommand(name = "deployVirtualMachine", description = "Creates and automatically starts a virtual machine based on a service offering, disk offering, and template.", responseObject = UserVmResponse.class, responseView = ResponseView.Restricted, entityType = {VirtualMachine.class}, requestHasSensitiveInfo = false, responseHasSensitiveInfo = true) public class DeployVMCmd extends BaseAsyncCreateCustomIdCmd { public static final Logger s_logger = Logger.getLogger(DeployVMCmd.class.getName()); @@ -121,6 +121,12 @@ public class DeployVMCmd extends BaseAsyncCreateCustomIdCmd { @Parameter(name = ApiConstants.SIZE, type = CommandType.LONG, description = "the arbitrary size for the DATADISK volume. Mutually exclusive with diskOfferingId") private Long size; + @Parameter(name = ApiConstants.ROOT_DISK_SIZE, + type = CommandType.LONG, + description = "Optional field to resize root disk on deploy. Only applies to template-based deployments. Analogous to details[0].rootdisksize, which takes precedence over this parameter if both are provided", + since = "4.4") + private Long rootdisksize; + @Parameter(name = ApiConstants.GROUP, type = CommandType.STRING, description = "an optional group for the virtual machine") private String group; @@ -226,6 +232,9 @@ public Map getDetails() { } } } + if (rootdisksize != null && !customparameterMap.containsKey("rootdisksize")) { + customparameterMap.put("rootdisksize", rootdisksize.toString()); + } return customparameterMap; } @@ -241,6 +250,14 @@ public Boolean getDisplayVm() { return displayVm; } + @Override + public boolean isDisplay() { + if(displayVm == null) + return true; + else + return displayVm; + } + public List getSecurityGroupIdList() { if (securityGroupNameList != null && securityGroupIdList != null) { throw new InvalidParameterValueException("securitygroupids parameter is mutually exclusive with securitygroupnames parameter"); @@ -399,16 +416,6 @@ public long getEntityOwnerId() { return accountId; } - @Override - public boolean isDisplayResourceEnabled(){ - Boolean display = getDisplayVm(); - if(display == null){ - return true; - } else { - return display; - } - } - @Override public String getEventType() { return EventTypes.EVENT_VM_CREATE; @@ -482,41 +489,50 @@ private void verifyDetails() { String minIops = (String)map.get("minIops"); String maxIops = (String)map.get("maxIops"); - if ((minIops != null && maxIops == null) || (minIops == null && maxIops != null)) { - throw new InvalidParameterValueException("Either 'Min IOPS' and 'Max IOPS' must both be specified or neither be specified."); - } + verifyMinAndMaxIops(minIops, maxIops); - long lMinIops; + minIops = (String)map.get("minIopsDo"); + maxIops = (String)map.get("maxIopsDo"); - try { - if (minIops != null) { - lMinIops = Long.valueOf(minIops); - } - else { - lMinIops = 0; - } + verifyMinAndMaxIops(minIops, maxIops); + } + } + + private void verifyMinAndMaxIops(String minIops, String maxIops) { + if ((minIops != null && maxIops == null) || (minIops == null && maxIops != null)) { + throw new InvalidParameterValueException("Either 'Min IOPS' and 'Max IOPS' must both be specified or neither be specified."); + } + + long lMinIops; + + try { + if (minIops != null) { + lMinIops = Long.valueOf(minIops); } - catch (NumberFormatException ex) { - throw new InvalidParameterValueException("'Min IOPS' must be a whole number."); + else { + lMinIops = 0; } + } + catch (NumberFormatException ex) { + throw new InvalidParameterValueException("'Min IOPS' must be a whole number."); + } - long lMaxIops; + long lMaxIops; - try { - if (maxIops != null) { - lMaxIops = Long.valueOf(maxIops); - } - else { - lMaxIops = 0; - } + try { + if (maxIops != null) { + lMaxIops = Long.valueOf(maxIops); } - catch (NumberFormatException ex) { - throw new InvalidParameterValueException("'Max IOPS' must be a whole number."); + else { + lMaxIops = 0; } + } + catch (NumberFormatException ex) { + throw new InvalidParameterValueException("'Max IOPS' must be a whole number."); + } - if (lMinIops > lMaxIops) { - throw new InvalidParameterValueException("'Min IOPS' must be less than or equal to 'Max IOPS'."); - } + if (lMinIops > lMaxIops) { + throw new InvalidParameterValueException("'Min IOPS' must be less than or equal to 'Max IOPS'."); } } diff --git a/api/src/org/apache/cloudstack/api/command/user/vm/DestroyVMCmd.java b/api/src/org/apache/cloudstack/api/command/user/vm/DestroyVMCmd.java index 4c3a41589c..3de0e4f72d 100644 --- a/api/src/org/apache/cloudstack/api/command/user/vm/DestroyVMCmd.java +++ b/api/src/org/apache/cloudstack/api/command/user/vm/DestroyVMCmd.java @@ -18,16 +18,15 @@ import java.util.List; -import org.apache.cloudstack.api.BaseAsyncVMCmd; import org.apache.log4j.Logger; -import org.apache.cloudstack.acl.IAMEntityType; import org.apache.cloudstack.acl.SecurityChecker.AccessType; import org.apache.cloudstack.api.ACL; import org.apache.cloudstack.api.APICommand; import org.apache.cloudstack.api.ApiCommandJobType; import org.apache.cloudstack.api.ApiConstants; import org.apache.cloudstack.api.ApiErrorCode; +import org.apache.cloudstack.api.BaseAsyncCmd; import org.apache.cloudstack.api.Parameter; import org.apache.cloudstack.api.ResponseObject.ResponseView; import org.apache.cloudstack.api.ServerApiException; @@ -39,11 +38,12 @@ import com.cloud.exception.ResourceUnavailableException; import com.cloud.user.Account; import com.cloud.uservm.UserVm; +import com.cloud.vm.VirtualMachine; -@APICommand(name = "destroyVirtualMachine", description = "Destroys a virtual machine. Once destroyed, only the administrator can recover it.", responseObject = UserVmResponse.class, responseView = ResponseView.Restricted, entityType = {IAMEntityType.VirtualMachine}, +@APICommand(name = "destroyVirtualMachine", description = "Destroys a virtual machine. Once destroyed, only the administrator can recover it.", responseObject = UserVmResponse.class, responseView = ResponseView.Restricted, entityType = {VirtualMachine.class}, requestHasSensitiveInfo = false, responseHasSensitiveInfo = true) -public class DestroyVMCmd extends BaseAsyncVMCmd { +public class DestroyVMCmd extends BaseAsyncCmd { public static final Logger s_logger = Logger.getLogger(DestroyVMCmd.class.getName()); private static final String s_name = "destroyvirtualmachineresponse"; diff --git a/api/src/org/apache/cloudstack/api/command/user/vm/GetVMPasswordCmd.java b/api/src/org/apache/cloudstack/api/command/user/vm/GetVMPasswordCmd.java index ebee189d35..0ba9db538a 100644 --- a/api/src/org/apache/cloudstack/api/command/user/vm/GetVMPasswordCmd.java +++ b/api/src/org/apache/cloudstack/api/command/user/vm/GetVMPasswordCmd.java @@ -20,7 +20,6 @@ import org.apache.log4j.Logger; -import org.apache.cloudstack.acl.IAMEntityType; import org.apache.cloudstack.acl.SecurityChecker.AccessType; import org.apache.cloudstack.api.ACL; import org.apache.cloudstack.api.APICommand; @@ -32,8 +31,9 @@ import com.cloud.user.Account; import com.cloud.uservm.UserVm; +import com.cloud.vm.VirtualMachine; -@APICommand(name = "getVMPassword", responseObject = GetVMPasswordResponse.class, description = "Returns an encrypted password for the VM", entityType = {IAMEntityType.VirtualMachine}, +@APICommand(name = "getVMPassword", responseObject = GetVMPasswordResponse.class, description = "Returns an encrypted password for the VM", entityType = {VirtualMachine.class}, requestHasSensitiveInfo = false, responseHasSensitiveInfo = false) public class GetVMPasswordCmd extends BaseCmd { public static final Logger s_logger = Logger.getLogger(GetVMPasswordCmd.class.getName()); diff --git a/api/src/org/apache/cloudstack/api/command/user/vm/ListNicsCmd.java b/api/src/org/apache/cloudstack/api/command/user/vm/ListNicsCmd.java index 408497cbc6..49402dc70d 100644 --- a/api/src/org/apache/cloudstack/api/command/user/vm/ListNicsCmd.java +++ b/api/src/org/apache/cloudstack/api/command/user/vm/ListNicsCmd.java @@ -99,11 +99,10 @@ public long getEntityOwnerId() { public Boolean getDisplay() { - Account caller = CallContext.current().getCallingAccount(); - if (caller.getType() == Account.ACCOUNT_TYPE_NORMAL) { - return true; + if (display != null) { + return display; } - return display; + return true; } ///////////////////////////////////////////////////// diff --git a/api/src/org/apache/cloudstack/api/command/user/vm/ListVMsCmd.java b/api/src/org/apache/cloudstack/api/command/user/vm/ListVMsCmd.java index 6c95a1215e..76e3db07b7 100644 --- a/api/src/org/apache/cloudstack/api/command/user/vm/ListVMsCmd.java +++ b/api/src/org/apache/cloudstack/api/command/user/vm/ListVMsCmd.java @@ -22,7 +22,6 @@ import org.apache.log4j.Logger; -import org.apache.cloudstack.acl.IAMEntityType; import org.apache.cloudstack.acl.RoleType; import org.apache.cloudstack.affinity.AffinityGroupResponse; import org.apache.cloudstack.api.APICommand; @@ -46,9 +45,10 @@ import org.apache.cloudstack.api.response.ZoneResponse; import com.cloud.exception.InvalidParameterValueException; +import com.cloud.vm.VirtualMachine; -@APICommand(name = "listVirtualMachines", description = "List the virtual machines owned by the account.", responseObject = UserVmResponse.class, responseView = ResponseView.Restricted, entityType = { IAMEntityType.VirtualMachine }, +@APICommand(name = "listVirtualMachines", description = "List the virtual machines owned by the account.", responseObject = UserVmResponse.class, responseView = ResponseView.Restricted, entityType = {VirtualMachine.class}, requestHasSensitiveInfo = false, responseHasSensitiveInfo = true) public class ListVMsCmd extends BaseListTaggedResourcesCmd { public static final Logger s_logger = Logger.getLogger(ListVMsCmd.class.getName()); diff --git a/api/src/org/apache/cloudstack/api/command/user/vm/RebootVMCmd.java b/api/src/org/apache/cloudstack/api/command/user/vm/RebootVMCmd.java index 0f041148cd..e7a0c16b10 100644 --- a/api/src/org/apache/cloudstack/api/command/user/vm/RebootVMCmd.java +++ b/api/src/org/apache/cloudstack/api/command/user/vm/RebootVMCmd.java @@ -16,16 +16,15 @@ // under the License. package org.apache.cloudstack.api.command.user.vm; -import org.apache.cloudstack.api.BaseAsyncVMCmd; import org.apache.log4j.Logger; -import org.apache.cloudstack.acl.IAMEntityType; import org.apache.cloudstack.acl.SecurityChecker.AccessType; import org.apache.cloudstack.api.ACL; import org.apache.cloudstack.api.APICommand; import org.apache.cloudstack.api.ApiCommandJobType; import org.apache.cloudstack.api.ApiConstants; import org.apache.cloudstack.api.ApiErrorCode; +import org.apache.cloudstack.api.BaseAsyncCmd; import org.apache.cloudstack.api.Parameter; import org.apache.cloudstack.api.ResponseObject.ResponseView; import org.apache.cloudstack.api.ServerApiException; @@ -37,10 +36,11 @@ import com.cloud.exception.ResourceUnavailableException; import com.cloud.user.Account; import com.cloud.uservm.UserVm; +import com.cloud.vm.VirtualMachine; -@APICommand(name = "rebootVirtualMachine", description = "Reboots a virtual machine.", responseObject = UserVmResponse.class, responseView = ResponseView.Restricted, entityType = {IAMEntityType.VirtualMachine}, +@APICommand(name = "rebootVirtualMachine", description = "Reboots a virtual machine.", responseObject = UserVmResponse.class, responseView = ResponseView.Restricted, entityType = {VirtualMachine.class}, requestHasSensitiveInfo = false, responseHasSensitiveInfo = true) -public class RebootVMCmd extends BaseAsyncVMCmd { +public class RebootVMCmd extends BaseAsyncCmd { public static final Logger s_logger = Logger.getLogger(RebootVMCmd.class.getName()); private static final String s_name = "rebootvirtualmachineresponse"; diff --git a/api/src/org/apache/cloudstack/api/command/user/vm/RemoveIpFromVmNicCmd.java b/api/src/org/apache/cloudstack/api/command/user/vm/RemoveIpFromVmNicCmd.java index 75eafa9503..70d5b48a16 100644 --- a/api/src/org/apache/cloudstack/api/command/user/vm/RemoveIpFromVmNicCmd.java +++ b/api/src/org/apache/cloudstack/api/command/user/vm/RemoveIpFromVmNicCmd.java @@ -131,6 +131,13 @@ public NetworkType getNetworkType() { return null; } + + private boolean isZoneSGEnabled() { + Network ntwk = _entityMgr.findById(Network.class, getNetworkId()); + DataCenter dc = _entityMgr.findById(DataCenter.class, ntwk.getDataCenterId()); + return dc.isSecurityGroupEnabled(); + } + @Override public void execute() throws InvalidParameterValueException { CallContext.current().setEventDetails("Ip Id: " + id); @@ -140,7 +147,7 @@ public void execute() throws InvalidParameterValueException { throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, "Invalid IP id is passed"); } - if (getNetworkType() == NetworkType.Basic) { + if (isZoneSGEnabled()) { //remove the security group rules for this secondary ip boolean success = false; success = _securityGroupService.securityGroupRulesForVmSecIp(nicSecIp.getNicId(), nicSecIp.getIp4Address(), false); diff --git a/api/src/org/apache/cloudstack/api/command/user/vm/RemoveNicFromVMCmd.java b/api/src/org/apache/cloudstack/api/command/user/vm/RemoveNicFromVMCmd.java index 44dfcf61af..d740260fc6 100644 --- a/api/src/org/apache/cloudstack/api/command/user/vm/RemoveNicFromVMCmd.java +++ b/api/src/org/apache/cloudstack/api/command/user/vm/RemoveNicFromVMCmd.java @@ -21,7 +21,6 @@ import org.apache.log4j.Logger; -import org.apache.cloudstack.acl.IAMEntityType; import org.apache.cloudstack.acl.SecurityChecker.AccessType; import org.apache.cloudstack.api.ACL; import org.apache.cloudstack.api.APICommand; @@ -39,8 +38,9 @@ import com.cloud.event.EventTypes; import com.cloud.user.Account; import com.cloud.uservm.UserVm; +import com.cloud.vm.VirtualMachine; -@APICommand(name = "removeNicFromVirtualMachine", description = "Removes VM from specified network by deleting a NIC", responseObject = UserVmResponse.class, responseView = ResponseView.Restricted, entityType = {IAMEntityType.VirtualMachine}, +@APICommand(name = "removeNicFromVirtualMachine", description = "Removes VM from specified network by deleting a NIC", responseObject = UserVmResponse.class, responseView = ResponseView.Restricted, entityType = {VirtualMachine.class}, requestHasSensitiveInfo = false, responseHasSensitiveInfo = true) public class RemoveNicFromVMCmd extends BaseAsyncCmd { public static final Logger s_logger = Logger.getLogger(RemoveNicFromVMCmd.class); diff --git a/api/src/org/apache/cloudstack/api/command/user/vm/ResetVMPasswordCmd.java b/api/src/org/apache/cloudstack/api/command/user/vm/ResetVMPasswordCmd.java index 615ef69369..365f3ed16a 100644 --- a/api/src/org/apache/cloudstack/api/command/user/vm/ResetVMPasswordCmd.java +++ b/api/src/org/apache/cloudstack/api/command/user/vm/ResetVMPasswordCmd.java @@ -16,16 +16,15 @@ // under the License. package org.apache.cloudstack.api.command.user.vm; -import org.apache.cloudstack.api.BaseAsyncVMCmd; import org.apache.log4j.Logger; -import org.apache.cloudstack.acl.IAMEntityType; import org.apache.cloudstack.acl.SecurityChecker.AccessType; import org.apache.cloudstack.api.ACL; import org.apache.cloudstack.api.APICommand; import org.apache.cloudstack.api.ApiCommandJobType; import org.apache.cloudstack.api.ApiConstants; import org.apache.cloudstack.api.ApiErrorCode; +import org.apache.cloudstack.api.BaseAsyncCmd; import org.apache.cloudstack.api.Parameter; import org.apache.cloudstack.api.ResponseObject.ResponseView; import org.apache.cloudstack.api.ServerApiException; @@ -37,12 +36,13 @@ import com.cloud.exception.ResourceUnavailableException; import com.cloud.user.Account; import com.cloud.uservm.UserVm; +import com.cloud.vm.VirtualMachine; @APICommand(name = "resetPasswordForVirtualMachine", responseObject=UserVmResponse.class, description="Resets the password for virtual machine. " + "The virtual machine must be in a \"Stopped\" state and the template must already " + - "support this feature for this command to take effect. [async]", responseView = ResponseView.Restricted, entityType = {IAMEntityType.VirtualMachine}, + "support this feature for this command to take effect. [async]", responseView = ResponseView.Restricted, entityType = {VirtualMachine.class}, requestHasSensitiveInfo = false, responseHasSensitiveInfo = true) -public class ResetVMPasswordCmd extends BaseAsyncVMCmd { +public class ResetVMPasswordCmd extends BaseAsyncCmd { public static final Logger s_logger = Logger.getLogger(ResetVMPasswordCmd.class.getName()); private static final String s_name = "resetpasswordforvirtualmachineresponse"; diff --git a/api/src/org/apache/cloudstack/api/command/user/vm/ResetVMSSHKeyCmd.java b/api/src/org/apache/cloudstack/api/command/user/vm/ResetVMSSHKeyCmd.java index 7d43853149..db2c7ff87d 100644 --- a/api/src/org/apache/cloudstack/api/command/user/vm/ResetVMSSHKeyCmd.java +++ b/api/src/org/apache/cloudstack/api/command/user/vm/ResetVMSSHKeyCmd.java @@ -17,16 +17,15 @@ package org.apache.cloudstack.api.command.user.vm; -import org.apache.cloudstack.api.BaseAsyncVMCmd; import org.apache.log4j.Logger; -import org.apache.cloudstack.acl.IAMEntityType; import org.apache.cloudstack.acl.SecurityChecker.AccessType; import org.apache.cloudstack.api.ACL; import org.apache.cloudstack.api.APICommand; import org.apache.cloudstack.api.ApiCommandJobType; import org.apache.cloudstack.api.ApiConstants; import org.apache.cloudstack.api.ApiErrorCode; +import org.apache.cloudstack.api.BaseAsyncCmd; import org.apache.cloudstack.api.Parameter; import org.apache.cloudstack.api.ResponseObject.ResponseView; import org.apache.cloudstack.api.ServerApiException; @@ -40,11 +39,12 @@ import com.cloud.exception.ResourceUnavailableException; import com.cloud.user.Account; import com.cloud.uservm.UserVm; +import com.cloud.vm.VirtualMachine; @APICommand(name = "resetSSHKeyForVirtualMachine", responseObject = UserVmResponse.class, description = "Resets the SSH Key for virtual machine. " + - "The virtual machine must be in a \"Stopped\" state. [async]", responseView = ResponseView.Restricted, entityType = {IAMEntityType.VirtualMachine}, + "The virtual machine must be in a \"Stopped\" state. [async]", responseView = ResponseView.Restricted, entityType = {VirtualMachine.class}, requestHasSensitiveInfo = false, responseHasSensitiveInfo = true) -public class ResetVMSSHKeyCmd extends BaseAsyncVMCmd { +public class ResetVMSSHKeyCmd extends BaseAsyncCmd { public static final Logger s_logger = Logger.getLogger(ResetVMSSHKeyCmd.class.getName()); diff --git a/api/src/org/apache/cloudstack/api/command/user/vm/RestoreVMCmd.java b/api/src/org/apache/cloudstack/api/command/user/vm/RestoreVMCmd.java index 0d5ef70bee..44265a32f5 100644 --- a/api/src/org/apache/cloudstack/api/command/user/vm/RestoreVMCmd.java +++ b/api/src/org/apache/cloudstack/api/command/user/vm/RestoreVMCmd.java @@ -16,15 +16,14 @@ // under the License. package org.apache.cloudstack.api.command.user.vm; -import org.apache.cloudstack.api.BaseAsyncVMCmd; import org.apache.log4j.Logger; -import org.apache.cloudstack.acl.IAMEntityType; import org.apache.cloudstack.acl.SecurityChecker.AccessType; import org.apache.cloudstack.api.ACL; import org.apache.cloudstack.api.APICommand; import org.apache.cloudstack.api.ApiConstants; import org.apache.cloudstack.api.ApiErrorCode; +import org.apache.cloudstack.api.BaseAsyncCmd; import org.apache.cloudstack.api.Parameter; import org.apache.cloudstack.api.ResponseObject.ResponseView; import org.apache.cloudstack.api.ServerApiException; @@ -39,11 +38,12 @@ import com.cloud.exception.ResourceUnavailableException; import com.cloud.user.Account; import com.cloud.uservm.UserVm; +import com.cloud.vm.VirtualMachine; -@APICommand(name = "restoreVirtualMachine", description = "Restore a VM to original template/ISO or new template/ISO", responseObject = UserVmResponse.class, since = "3.0.0", responseView = ResponseView.Restricted, entityType = {IAMEntityType.VirtualMachine}, +@APICommand(name = "restoreVirtualMachine", description = "Restore a VM to original template/ISO or new template/ISO", responseObject = UserVmResponse.class, since = "3.0.0", responseView = ResponseView.Restricted, entityType = {VirtualMachine.class}, requestHasSensitiveInfo = false, responseHasSensitiveInfo = true) -public class RestoreVMCmd extends BaseAsyncVMCmd { +public class RestoreVMCmd extends BaseAsyncCmd { public static final Logger s_logger = Logger.getLogger(RestoreVMCmd.class); private static final String s_name = "restorevmresponse"; @@ -106,7 +106,6 @@ public Long getTemplateId() { } // TODO - Remove vmid param and make it "id" in 5.0 so that we dont have two getters - @Override public Long getId() { return getVmId(); } 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 d668ad4fed..661100b533 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 @@ -24,13 +24,12 @@ import org.apache.log4j.Logger; -import org.apache.cloudstack.acl.IAMEntityType; import org.apache.cloudstack.acl.SecurityChecker.AccessType; import org.apache.cloudstack.api.ACL; import org.apache.cloudstack.api.APICommand; import org.apache.cloudstack.api.ApiConstants; import org.apache.cloudstack.api.ApiErrorCode; -import org.apache.cloudstack.api.BaseAsyncVMCmd; +import org.apache.cloudstack.api.BaseAsyncCmd; import org.apache.cloudstack.api.BaseCmd; import org.apache.cloudstack.api.Parameter; import org.apache.cloudstack.api.ResponseObject.ResponseView; @@ -46,11 +45,12 @@ import com.cloud.exception.VirtualMachineMigrationException; import com.cloud.user.Account; import com.cloud.uservm.UserVm; +import com.cloud.vm.VirtualMachine; -@APICommand(name = "scaleVirtualMachine", description = "Scales the virtual machine to a new service offering.", responseObject = SuccessResponse.class, responseView = ResponseView.Restricted, entityType = {IAMEntityType.VirtualMachine}, +@APICommand(name = "scaleVirtualMachine", description = "Scales the virtual machine to a new service offering.", responseObject = SuccessResponse.class, responseView = ResponseView.Restricted, entityType = {VirtualMachine.class}, requestHasSensitiveInfo = false, responseHasSensitiveInfo = false) -public class ScaleVMCmd extends BaseAsyncVMCmd { +public class ScaleVMCmd extends BaseAsyncCmd { public static final Logger s_logger = Logger.getLogger(ScaleVMCmd.class.getName()); private static final String s_name = "scalevirtualmachineresponse"; 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 13b7442eaf..8289412404 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 @@ -18,7 +18,6 @@ import org.apache.log4j.Logger; -import org.apache.cloudstack.acl.IAMEntityType; import org.apache.cloudstack.acl.RoleType; import org.apache.cloudstack.acl.SecurityChecker.AccessType; import org.apache.cloudstack.api.ACL; @@ -26,7 +25,7 @@ import org.apache.cloudstack.api.ApiCommandJobType; import org.apache.cloudstack.api.ApiConstants; import org.apache.cloudstack.api.ApiErrorCode; -import org.apache.cloudstack.api.BaseAsyncVMCmd; +import org.apache.cloudstack.api.BaseAsyncCmd; import org.apache.cloudstack.api.Parameter; import org.apache.cloudstack.api.ResponseObject.ResponseView; import org.apache.cloudstack.api.ServerApiException; @@ -44,10 +43,11 @@ import com.cloud.user.Account; import com.cloud.uservm.UserVm; import com.cloud.utils.exception.ExecutionException; +import com.cloud.vm.VirtualMachine; -@APICommand(name = "startVirtualMachine", responseObject = UserVmResponse.class, description = "Starts a virtual machine.", responseView = ResponseView.Restricted, entityType = {IAMEntityType.VirtualMachine}, +@APICommand(name = "startVirtualMachine", responseObject = UserVmResponse.class, description = "Starts a virtual machine.", responseView = ResponseView.Restricted, entityType = {VirtualMachine.class}, requestHasSensitiveInfo = false, responseHasSensitiveInfo = true) -public class StartVMCmd extends BaseAsyncVMCmd { +public class StartVMCmd extends BaseAsyncCmd { public static final Logger s_logger = Logger.getLogger(StartVMCmd.class.getName()); private static final String s_name = "startvirtualmachineresponse"; @@ -74,7 +74,6 @@ public class StartVMCmd extends BaseAsyncVMCmd { // ///////////////// Accessors /////////////////////// // /////////////////////////////////////////////////// - @Override public Long getId() { return id; } diff --git a/api/src/org/apache/cloudstack/api/command/user/vm/StopVMCmd.java b/api/src/org/apache/cloudstack/api/command/user/vm/StopVMCmd.java index 6db5d18d30..ece41b8dcc 100644 --- a/api/src/org/apache/cloudstack/api/command/user/vm/StopVMCmd.java +++ b/api/src/org/apache/cloudstack/api/command/user/vm/StopVMCmd.java @@ -16,16 +16,15 @@ // under the License. package org.apache.cloudstack.api.command.user.vm; -import org.apache.cloudstack.api.BaseAsyncVMCmd; import org.apache.log4j.Logger; -import org.apache.cloudstack.acl.IAMEntityType; import org.apache.cloudstack.acl.SecurityChecker.AccessType; import org.apache.cloudstack.api.ACL; import org.apache.cloudstack.api.APICommand; import org.apache.cloudstack.api.ApiCommandJobType; import org.apache.cloudstack.api.ApiConstants; import org.apache.cloudstack.api.ApiErrorCode; +import org.apache.cloudstack.api.BaseAsyncCmd; import org.apache.cloudstack.api.Parameter; import org.apache.cloudstack.api.ResponseObject.ResponseView; import org.apache.cloudstack.api.ServerApiException; @@ -36,10 +35,11 @@ import com.cloud.exception.ConcurrentOperationException; import com.cloud.user.Account; import com.cloud.uservm.UserVm; +import com.cloud.vm.VirtualMachine; -@APICommand(name = "stopVirtualMachine", responseObject = UserVmResponse.class, description = "Stops a virtual machine.", responseView = ResponseView.Restricted, entityType = {IAMEntityType.VirtualMachine}, +@APICommand(name = "stopVirtualMachine", responseObject = UserVmResponse.class, description = "Stops a virtual machine.", responseView = ResponseView.Restricted, entityType = {VirtualMachine.class}, requestHasSensitiveInfo = false, responseHasSensitiveInfo = true) -public class StopVMCmd extends BaseAsyncVMCmd { +public class StopVMCmd extends BaseAsyncCmd { public static final Logger s_logger = Logger.getLogger(StopVMCmd.class.getName()); private static final String s_name = "stopvirtualmachineresponse"; diff --git a/api/src/org/apache/cloudstack/api/command/user/vm/UpdateDefaultNicForVMCmd.java b/api/src/org/apache/cloudstack/api/command/user/vm/UpdateDefaultNicForVMCmd.java index c70f7e502d..cffd903792 100644 --- a/api/src/org/apache/cloudstack/api/command/user/vm/UpdateDefaultNicForVMCmd.java +++ b/api/src/org/apache/cloudstack/api/command/user/vm/UpdateDefaultNicForVMCmd.java @@ -21,7 +21,6 @@ import org.apache.log4j.Logger; -import org.apache.cloudstack.acl.IAMEntityType; import org.apache.cloudstack.acl.SecurityChecker.AccessType; import org.apache.cloudstack.api.ACL; import org.apache.cloudstack.api.APICommand; @@ -39,8 +38,9 @@ import com.cloud.event.EventTypes; import com.cloud.user.Account; import com.cloud.uservm.UserVm; +import com.cloud.vm.VirtualMachine; -@APICommand(name = "updateDefaultNicForVirtualMachine", description = "Changes the default NIC on a VM", responseObject = UserVmResponse.class, responseView = ResponseView.Restricted, entityType = {IAMEntityType.VirtualMachine}, +@APICommand(name = "updateDefaultNicForVirtualMachine", description = "Changes the default NIC on a VM", responseObject = UserVmResponse.class, responseView = ResponseView.Restricted, entityType = {VirtualMachine.class}, requestHasSensitiveInfo = false, responseHasSensitiveInfo = true) public class UpdateDefaultNicForVMCmd extends BaseAsyncCmd { public static final Logger s_logger = Logger.getLogger(UpdateDefaultNicForVMCmd.class); diff --git a/api/src/org/apache/cloudstack/api/command/user/vm/UpdateVMCmd.java b/api/src/org/apache/cloudstack/api/command/user/vm/UpdateVMCmd.java index fac82aac9b..7938c56671 100644 --- a/api/src/org/apache/cloudstack/api/command/user/vm/UpdateVMCmd.java +++ b/api/src/org/apache/cloudstack/api/command/user/vm/UpdateVMCmd.java @@ -18,7 +18,6 @@ import org.apache.log4j.Logger; -import org.apache.cloudstack.acl.IAMEntityType; import org.apache.cloudstack.acl.RoleType; import org.apache.cloudstack.acl.SecurityChecker.AccessType; import org.apache.cloudstack.api.ACL; @@ -37,10 +36,11 @@ import com.cloud.exception.ResourceUnavailableException; import com.cloud.user.Account; import com.cloud.uservm.UserVm; +import com.cloud.vm.VirtualMachine; @APICommand(name = "updateVirtualMachine", description="Updates properties of a virtual machine. The VM has to be stopped and restarted for the " + "new properties to take effect. UpdateVirtualMachine does not first check whether the VM is stopped. " + - "Therefore, stop the VM manually before issuing this call.", responseObject = UserVmResponse.class, responseView = ResponseView.Restricted, entityType = {IAMEntityType.VirtualMachine}, + "Therefore, stop the VM manually before issuing this call.", responseObject = UserVmResponse.class, responseView = ResponseView.Restricted, entityType = {VirtualMachine.class}, requestHasSensitiveInfo = false, responseHasSensitiveInfo = true) public class UpdateVMCmd extends BaseCustomIdCmd { public static final Logger s_logger = Logger.getLogger(UpdateVMCmd.class.getName()); @@ -150,16 +150,6 @@ public long getEntityOwnerId() { return Account.ACCOUNT_ID_SYSTEM; // no account info given, parent this command to SYSTEM so ERROR events are tracked } - @Override - public boolean isDisplayResourceEnabled(){ - UserVm userVm = _entityMgr.findById(UserVm.class, getId()); - if (userVm != null) { - return userVm.isDisplayVm(); - } - - return true; // no info means true - } - @Override public void execute() throws ResourceUnavailableException, InsufficientCapacityException, ServerApiException { CallContext.current().setEventDetails("Vm Id: " + getId()); diff --git a/api/src/org/apache/cloudstack/api/command/user/vm/UpgradeVMCmd.java b/api/src/org/apache/cloudstack/api/command/user/vm/UpgradeVMCmd.java index 3560b04098..b10555556b 100644 --- a/api/src/org/apache/cloudstack/api/command/user/vm/UpgradeVMCmd.java +++ b/api/src/org/apache/cloudstack/api/command/user/vm/UpgradeVMCmd.java @@ -23,7 +23,6 @@ import org.apache.log4j.Logger; -import org.apache.cloudstack.acl.IAMEntityType; import org.apache.cloudstack.acl.SecurityChecker.AccessType; import org.apache.cloudstack.api.ACL; import org.apache.cloudstack.api.APICommand; @@ -42,10 +41,11 @@ import com.cloud.offering.ServiceOffering; import com.cloud.user.Account; import com.cloud.uservm.UserVm; +import com.cloud.vm.VirtualMachine; @APICommand(name = "changeServiceForVirtualMachine", responseObject=UserVmResponse.class, description="Changes the service offering for a virtual machine. " + "The virtual machine must be in a \"Stopped\" state for " + - "this command to take effect.", responseView = ResponseView.Restricted, entityType = {IAMEntityType.VirtualMachine}, + "this command to take effect.", responseView = ResponseView.Restricted, entityType = {VirtualMachine.class}, requestHasSensitiveInfo = false, responseHasSensitiveInfo = true) public class UpgradeVMCmd extends BaseCmd { public static final Logger s_logger = Logger.getLogger(UpgradeVMCmd.class.getName()); @@ -117,11 +117,6 @@ public long getEntityOwnerId() { return Account.ACCOUNT_ID_SYSTEM; // no account info given, parent this command to SYSTEM so ERROR events are tracked } - @Override - public boolean isDisplayResourceEnabled(){ - return _userVmService.isDisplayResourceEnabled(getId()); - } - @Override public void execute() throws ResourceAllocationException { CallContext.current().setEventDetails("Vm Id: " + getId()); diff --git a/api/src/org/apache/cloudstack/api/command/user/vmgroup/CreateVMGroupCmd.java b/api/src/org/apache/cloudstack/api/command/user/vmgroup/CreateVMGroupCmd.java index 104cfa3672..6947f15059 100644 --- a/api/src/org/apache/cloudstack/api/command/user/vmgroup/CreateVMGroupCmd.java +++ b/api/src/org/apache/cloudstack/api/command/user/vmgroup/CreateVMGroupCmd.java @@ -18,7 +18,6 @@ import org.apache.log4j.Logger; -import org.apache.cloudstack.acl.IAMEntityType; import org.apache.cloudstack.api.APICommand; import org.apache.cloudstack.api.ApiConstants; import org.apache.cloudstack.api.ApiErrorCode; @@ -32,7 +31,7 @@ import com.cloud.vm.InstanceGroup; -@APICommand(name = "createInstanceGroup", description = "Creates a vm group", responseObject = InstanceGroupResponse.class, entityType = {IAMEntityType.InstanceGroup}, +@APICommand(name = "createInstanceGroup", description = "Creates a vm group", responseObject = InstanceGroupResponse.class, entityType = {InstanceGroup.class}, requestHasSensitiveInfo = false, responseHasSensitiveInfo = false) public class CreateVMGroupCmd extends BaseCmd { public static final Logger s_logger = Logger.getLogger(CreateVMGroupCmd.class.getName()); diff --git a/api/src/org/apache/cloudstack/api/command/user/vmgroup/DeleteVMGroupCmd.java b/api/src/org/apache/cloudstack/api/command/user/vmgroup/DeleteVMGroupCmd.java index 0bc52369d2..8311eccf99 100644 --- a/api/src/org/apache/cloudstack/api/command/user/vmgroup/DeleteVMGroupCmd.java +++ b/api/src/org/apache/cloudstack/api/command/user/vmgroup/DeleteVMGroupCmd.java @@ -18,7 +18,6 @@ import org.apache.log4j.Logger; -import org.apache.cloudstack.acl.IAMEntityType; import org.apache.cloudstack.acl.SecurityChecker.AccessType; import org.apache.cloudstack.api.ACL; import org.apache.cloudstack.api.APICommand; @@ -33,7 +32,7 @@ import com.cloud.user.Account; import com.cloud.vm.InstanceGroup; -@APICommand(name = "deleteInstanceGroup", description = "Deletes a vm group", responseObject = SuccessResponse.class, entityType = {IAMEntityType.InstanceGroup}, +@APICommand(name = "deleteInstanceGroup", description = "Deletes a vm group", responseObject = SuccessResponse.class, entityType = {InstanceGroup.class}, requestHasSensitiveInfo = false, responseHasSensitiveInfo = false) public class DeleteVMGroupCmd extends BaseCmd { public static final Logger s_logger = Logger.getLogger(DeleteVMGroupCmd.class.getName()); diff --git a/api/src/org/apache/cloudstack/api/command/user/vmgroup/ListVMGroupsCmd.java b/api/src/org/apache/cloudstack/api/command/user/vmgroup/ListVMGroupsCmd.java index e9844dd19a..73fdb8aa18 100644 --- a/api/src/org/apache/cloudstack/api/command/user/vmgroup/ListVMGroupsCmd.java +++ b/api/src/org/apache/cloudstack/api/command/user/vmgroup/ListVMGroupsCmd.java @@ -18,7 +18,6 @@ import org.apache.log4j.Logger; -import org.apache.cloudstack.acl.IAMEntityType; import org.apache.cloudstack.api.APICommand; import org.apache.cloudstack.api.ApiConstants; import org.apache.cloudstack.api.BaseListProjectAndAccountResourcesCmd; @@ -26,7 +25,9 @@ import org.apache.cloudstack.api.response.InstanceGroupResponse; import org.apache.cloudstack.api.response.ListResponse; -@APICommand(name = "listInstanceGroups", description = "Lists vm groups", responseObject = InstanceGroupResponse.class, entityType = {IAMEntityType.InstanceGroup}, +import com.cloud.vm.InstanceGroup; + +@APICommand(name = "listInstanceGroups", description = "Lists vm groups", responseObject = InstanceGroupResponse.class, entityType = {InstanceGroup.class}, requestHasSensitiveInfo = false, responseHasSensitiveInfo = false) public class ListVMGroupsCmd extends BaseListProjectAndAccountResourcesCmd { public static final Logger s_logger = Logger.getLogger(ListVMGroupsCmd.class.getName()); diff --git a/api/src/org/apache/cloudstack/api/command/user/vmgroup/UpdateVMGroupCmd.java b/api/src/org/apache/cloudstack/api/command/user/vmgroup/UpdateVMGroupCmd.java index e06ec52e1a..befa46c9ce 100644 --- a/api/src/org/apache/cloudstack/api/command/user/vmgroup/UpdateVMGroupCmd.java +++ b/api/src/org/apache/cloudstack/api/command/user/vmgroup/UpdateVMGroupCmd.java @@ -18,7 +18,6 @@ import org.apache.log4j.Logger; -import org.apache.cloudstack.acl.IAMEntityType; import org.apache.cloudstack.acl.SecurityChecker.AccessType; import org.apache.cloudstack.api.ACL; import org.apache.cloudstack.api.APICommand; @@ -32,7 +31,7 @@ import com.cloud.user.Account; import com.cloud.vm.InstanceGroup; -@APICommand(name = "updateInstanceGroup", description = "Updates a vm group", responseObject = InstanceGroupResponse.class, entityType = {IAMEntityType.InstanceGroup}, +@APICommand(name = "updateInstanceGroup", description = "Updates a vm group", responseObject = InstanceGroupResponse.class, entityType = {InstanceGroup.class}, requestHasSensitiveInfo = false, responseHasSensitiveInfo = false) public class UpdateVMGroupCmd extends BaseCmd { diff --git a/api/src/org/apache/cloudstack/api/command/user/vmsnapshot/CreateVMSnapshotCmd.java b/api/src/org/apache/cloudstack/api/command/user/vmsnapshot/CreateVMSnapshotCmd.java index fae0e61723..1310ba5b75 100644 --- a/api/src/org/apache/cloudstack/api/command/user/vmsnapshot/CreateVMSnapshotCmd.java +++ b/api/src/org/apache/cloudstack/api/command/user/vmsnapshot/CreateVMSnapshotCmd.java @@ -19,8 +19,6 @@ import java.util.logging.Logger; -import org.apache.cloudstack.acl.IAMEntityType; -import org.apache.cloudstack.acl.SecurityChecker.AccessType; import org.apache.cloudstack.api.ACL; import org.apache.cloudstack.api.APICommand; import org.apache.cloudstack.api.ApiConstants; @@ -37,14 +35,14 @@ import com.cloud.uservm.UserVm; import com.cloud.vm.snapshot.VMSnapshot; -@APICommand(name = "createVMSnapshot", description = "Creates snapshot for a vm.", responseObject = VMSnapshotResponse.class, since = "4.2.0", entityType = {IAMEntityType.VMSnapshot}, +@APICommand(name = "createVMSnapshot", description = "Creates snapshot for a vm.", responseObject = VMSnapshotResponse.class, since = "4.2.0", entityType = {VMSnapshot.class}, requestHasSensitiveInfo = false, responseHasSensitiveInfo = false) public class CreateVMSnapshotCmd extends BaseAsyncCreateCmd { public static final Logger s_logger = Logger.getLogger(CreateVMSnapshotCmd.class.getName()); private static final String s_name = "createvmsnapshotresponse"; - @ACL(accessType = AccessType.OperateEntry) + @ACL @Parameter(name = ApiConstants.VIRTUAL_MACHINE_ID, type = CommandType.UUID, required = true, entityType = UserVmResponse.class, description = "The ID of the vm") private Long vmId; diff --git a/api/src/org/apache/cloudstack/api/command/user/vmsnapshot/DeleteVMSnapshotCmd.java b/api/src/org/apache/cloudstack/api/command/user/vmsnapshot/DeleteVMSnapshotCmd.java index af076cff57..7baad7cd59 100644 --- a/api/src/org/apache/cloudstack/api/command/user/vmsnapshot/DeleteVMSnapshotCmd.java +++ b/api/src/org/apache/cloudstack/api/command/user/vmsnapshot/DeleteVMSnapshotCmd.java @@ -19,7 +19,6 @@ import org.apache.log4j.Logger; -import org.apache.cloudstack.acl.IAMEntityType; import org.apache.cloudstack.acl.SecurityChecker.AccessType; import org.apache.cloudstack.api.ACL; import org.apache.cloudstack.api.APICommand; @@ -36,7 +35,7 @@ import com.cloud.user.Account; import com.cloud.vm.snapshot.VMSnapshot; -@APICommand(name = "deleteVMSnapshot", description = "Deletes a vmsnapshot.", responseObject = SuccessResponse.class, since = "4.2.0", entityType = {IAMEntityType.VMSnapshot}, +@APICommand(name = "deleteVMSnapshot", description = "Deletes a vmsnapshot.", responseObject = SuccessResponse.class, since = "4.2.0", entityType = {VMSnapshot.class}, requestHasSensitiveInfo = false, responseHasSensitiveInfo = false) public class DeleteVMSnapshotCmd extends BaseAsyncCmd { public static final Logger s_logger = Logger.getLogger(DeleteVMSnapshotCmd.class.getName()); diff --git a/api/src/org/apache/cloudstack/api/command/user/vmsnapshot/ListVMSnapshotCmd.java b/api/src/org/apache/cloudstack/api/command/user/vmsnapshot/ListVMSnapshotCmd.java index 3167d09f01..c9bc2430d2 100644 --- a/api/src/org/apache/cloudstack/api/command/user/vmsnapshot/ListVMSnapshotCmd.java +++ b/api/src/org/apache/cloudstack/api/command/user/vmsnapshot/ListVMSnapshotCmd.java @@ -20,7 +20,6 @@ import java.util.ArrayList; import java.util.List; -import org.apache.cloudstack.acl.IAMEntityType; import org.apache.cloudstack.api.APICommand; import org.apache.cloudstack.api.ApiConstants; import org.apache.cloudstack.api.BaseListTaggedResourcesCmd; @@ -31,7 +30,7 @@ import com.cloud.vm.snapshot.VMSnapshot; -@APICommand(name = "listVMSnapshot", description = "List virtual machine snapshot by conditions", responseObject = VMSnapshotResponse.class, since = "4.2.0", entityType = {IAMEntityType.VMSnapshot}, +@APICommand(name = "listVMSnapshot", description = "List virtual machine snapshot by conditions", responseObject = VMSnapshotResponse.class, since = "4.2.0", entityType = {VMSnapshot.class}, requestHasSensitiveInfo = false, responseHasSensitiveInfo = false) public class ListVMSnapshotCmd extends BaseListTaggedResourcesCmd { diff --git a/api/src/org/apache/cloudstack/api/command/user/volume/AttachVolumeCmd.java b/api/src/org/apache/cloudstack/api/command/user/volume/AttachVolumeCmd.java index f9d9081f36..8034745951 100644 --- a/api/src/org/apache/cloudstack/api/command/user/volume/AttachVolumeCmd.java +++ b/api/src/org/apache/cloudstack/api/command/user/volume/AttachVolumeCmd.java @@ -16,16 +16,15 @@ // under the License. package org.apache.cloudstack.api.command.user.volume; +import org.apache.cloudstack.api.BaseAsyncCmd; import org.apache.log4j.Logger; -import org.apache.cloudstack.acl.IAMEntityType; import org.apache.cloudstack.acl.SecurityChecker.AccessType; import org.apache.cloudstack.api.ACL; import org.apache.cloudstack.api.APICommand; import org.apache.cloudstack.api.ApiCommandJobType; import org.apache.cloudstack.api.ApiConstants; import org.apache.cloudstack.api.ApiErrorCode; -import org.apache.cloudstack.api.BaseAsyncVolumeCmd; import org.apache.cloudstack.api.Parameter; import org.apache.cloudstack.api.ResponseObject.ResponseView; import org.apache.cloudstack.api.ServerApiException; @@ -36,10 +35,12 @@ import com.cloud.event.EventTypes; import com.cloud.storage.Volume; import com.cloud.user.Account; +import com.cloud.vm.VirtualMachine; -@APICommand(name = "attachVolume", description = "Attaches a disk volume to a virtual machine.", responseObject = VolumeResponse.class, responseView = ResponseView.Restricted, entityType = {IAMEntityType.VirtualMachine}, +@APICommand(name = "attachVolume", description = "Attaches a disk volume to a virtual machine.", responseObject = VolumeResponse.class, responseView = ResponseView.Restricted, entityType = { + VirtualMachine.class, Volume.class}, requestHasSensitiveInfo = false, responseHasSensitiveInfo = false) -public class AttachVolumeCmd extends BaseAsyncVolumeCmd { +public class AttachVolumeCmd extends BaseAsyncCmd { public static final Logger s_logger = Logger.getLogger(AttachVolumeCmd.class.getName()); private static final String s_name = "attachvolumeresponse"; @@ -52,6 +53,7 @@ public class AttachVolumeCmd extends BaseAsyncVolumeCmd { + "* 4 - /dev/xvde" + "* 5 - /dev/xvdf" + "* 6 - /dev/xvdg" + "* 7 - /dev/xvdh" + "* 8 - /dev/xvdi" + "* 9 - /dev/xvdj") private Long deviceId; + @ACL(accessType = AccessType.OperateEntry) @Parameter(name = ApiConstants.ID, type = CommandType.UUID, entityType = VolumeResponse.class, required = true, description = "the ID of the disk volume") private Long id; @@ -68,7 +70,6 @@ public Long getDeviceId() { return deviceId; } - @Override public Long getId() { return id; } diff --git a/api/src/org/apache/cloudstack/api/command/user/volume/CreateVolumeCmd.java b/api/src/org/apache/cloudstack/api/command/user/volume/CreateVolumeCmd.java index 9b83f61b0b..dc912610b4 100644 --- a/api/src/org/apache/cloudstack/api/command/user/volume/CreateVolumeCmd.java +++ b/api/src/org/apache/cloudstack/api/command/user/volume/CreateVolumeCmd.java @@ -18,8 +18,9 @@ import org.apache.log4j.Logger; -import org.apache.cloudstack.acl.IAMEntityType; import org.apache.cloudstack.acl.RoleType; +import org.apache.cloudstack.acl.SecurityChecker.AccessType; +import org.apache.cloudstack.api.ACL; import org.apache.cloudstack.api.APICommand; import org.apache.cloudstack.api.ApiCommandJobType; import org.apache.cloudstack.api.ApiConstants; @@ -42,8 +43,10 @@ import com.cloud.exception.ResourceAllocationException; import com.cloud.storage.Snapshot; import com.cloud.storage.Volume; +import com.cloud.vm.VirtualMachine; -@APICommand(name = "createVolume", responseObject = VolumeResponse.class, description = "Creates a disk volume from a disk offering. This disk volume must still be attached to a virtual machine to make use of it.", responseView = ResponseView.Restricted, entityType = {IAMEntityType.Volume}, +@APICommand(name = "createVolume", responseObject = VolumeResponse.class, description = "Creates a disk volume from a disk offering. This disk volume must still be attached to a virtual machine to make use of it.", responseView = ResponseView.Restricted, entityType = { + Volume.class, VirtualMachine.class}, requestHasSensitiveInfo = false, responseHasSensitiveInfo = false) public class CreateVolumeCmd extends BaseAsyncCreateCustomIdCmd { public static final Logger s_logger = Logger.getLogger(CreateVolumeCmd.class.getName()); @@ -90,6 +93,7 @@ public class CreateVolumeCmd extends BaseAsyncCreateCustomIdCmd { @Parameter(name = ApiConstants.MAX_IOPS, type = CommandType.LONG, description = "max iops") private Long maxIops; + @ACL @Parameter(name = ApiConstants.SNAPSHOT_ID, type = CommandType.UUID, entityType = SnapshotResponse.class, @@ -102,6 +106,7 @@ public class CreateVolumeCmd extends BaseAsyncCreateCustomIdCmd { @Parameter(name = ApiConstants.DISPLAY_VOLUME, type = CommandType.BOOLEAN, description = "an optional field, whether to display the volume to the end user or not.", authorized = {RoleType.Admin}) private Boolean displayVolume; + @ACL(accessType = AccessType.OperateEntry) @Parameter(name = ApiConstants.VIRTUAL_MACHINE_ID, type = CommandType.UUID, entityType = UserVmResponse.class, @@ -156,6 +161,14 @@ public Boolean getDisplayVolume() { return displayVolume; } + @Override + public boolean isDisplay() { + if(displayVolume == null) + return true; + else + return displayVolume; + } + public Long getVirtualMachineId() { return virtualMachineId; } @@ -192,16 +205,6 @@ public String getEventType() { return EventTypes.EVENT_VOLUME_CREATE; } - @Override - public boolean isDisplayResourceEnabled(){ - Boolean display = getDisplayVolume(); - if(display == null){ - return true; - } else { - return display; - } - } - @Override public String getEventDescription() { return "creating volume: " + getVolumeName() + ((getSnapshotId() == null) ? "" : " from snapshot: " + getSnapshotId()); diff --git a/api/src/org/apache/cloudstack/api/command/user/volume/DeleteVolumeCmd.java b/api/src/org/apache/cloudstack/api/command/user/volume/DeleteVolumeCmd.java index 6ca96b08b0..0b0c1b7303 100644 --- a/api/src/org/apache/cloudstack/api/command/user/volume/DeleteVolumeCmd.java +++ b/api/src/org/apache/cloudstack/api/command/user/volume/DeleteVolumeCmd.java @@ -17,7 +17,6 @@ package org.apache.cloudstack.api.command.user.volume; import org.apache.log4j.Logger; -import org.apache.cloudstack.acl.IAMEntityType; import org.apache.cloudstack.acl.SecurityChecker.AccessType; import org.apache.cloudstack.api.ACL; import org.apache.cloudstack.api.APICommand; @@ -34,7 +33,7 @@ import com.cloud.storage.Volume; import com.cloud.user.Account; -@APICommand(name = "deleteVolume", description = "Deletes a detached disk volume.", responseObject = SuccessResponse.class, entityType = {IAMEntityType.Volume}, +@APICommand(name = "deleteVolume", description = "Deletes a detached disk volume.", responseObject = SuccessResponse.class, entityType = {Volume.class}, requestHasSensitiveInfo = false, responseHasSensitiveInfo = false) public class DeleteVolumeCmd extends BaseCmd { public static final Logger s_logger = Logger.getLogger(DeleteVolumeCmd.class.getName()); @@ -80,11 +79,6 @@ public long getEntityOwnerId() { return Account.ACCOUNT_ID_SYSTEM; // no account info given, parent this command to SYSTEM so ERROR events are tracked } - @Override - public boolean isDisplayResourceEnabled(){ - return _volumeService.isDisplayResourceEnabled(getId()); - } - @Override public void execute() throws ConcurrentOperationException { CallContext.current().setEventDetails("Volume Id: " + getId()); diff --git a/api/src/org/apache/cloudstack/api/command/user/volume/DetachVolumeCmd.java b/api/src/org/apache/cloudstack/api/command/user/volume/DetachVolumeCmd.java index bfd032203c..cad0a7ffe0 100644 --- a/api/src/org/apache/cloudstack/api/command/user/volume/DetachVolumeCmd.java +++ b/api/src/org/apache/cloudstack/api/command/user/volume/DetachVolumeCmd.java @@ -16,16 +16,15 @@ // under the License. package org.apache.cloudstack.api.command.user.volume; +import org.apache.cloudstack.api.BaseAsyncCmd; import org.apache.log4j.Logger; -import org.apache.cloudstack.acl.IAMEntityType; import org.apache.cloudstack.acl.SecurityChecker.AccessType; import org.apache.cloudstack.api.ACL; import org.apache.cloudstack.api.APICommand; import org.apache.cloudstack.api.ApiCommandJobType; import org.apache.cloudstack.api.ApiConstants; import org.apache.cloudstack.api.ApiErrorCode; -import org.apache.cloudstack.api.BaseAsyncVolumeCmd; import org.apache.cloudstack.api.Parameter; import org.apache.cloudstack.api.ResponseObject.ResponseView; import org.apache.cloudstack.api.ServerApiException; @@ -37,10 +36,11 @@ import com.cloud.storage.Volume; import com.cloud.user.Account; import com.cloud.uservm.UserVm; +import com.cloud.vm.VirtualMachine; -@APICommand(name = "detachVolume", description = "Detaches a disk volume from a virtual machine.", responseObject = VolumeResponse.class, responseView = ResponseView.Restricted, entityType = {IAMEntityType.Volume}, +@APICommand(name = "detachVolume", description = "Detaches a disk volume from a virtual machine.", responseObject = VolumeResponse.class, responseView = ResponseView.Restricted, entityType = {VirtualMachine.class}, requestHasSensitiveInfo = false, responseHasSensitiveInfo = false) -public class DetachVolumeCmd extends BaseAsyncVolumeCmd { +public class DetachVolumeCmd extends BaseAsyncCmd { public static final Logger s_logger = Logger.getLogger(DetachVolumeCmd.class.getName()); private static final String s_name = "detachvolumeresponse"; @@ -48,7 +48,6 @@ public class DetachVolumeCmd extends BaseAsyncVolumeCmd { //////////////// API parameters ///////////////////// ///////////////////////////////////////////////////// - @ACL(accessType = AccessType.OperateEntry) @Parameter(name=ApiConstants.ID, type=CommandType.UUID, entityType=VolumeResponse.class, description="the ID of the disk volume") private Long id; @@ -56,6 +55,7 @@ public class DetachVolumeCmd extends BaseAsyncVolumeCmd { @Parameter(name = ApiConstants.DEVICE_ID, type = CommandType.LONG, description = "the device ID on the virtual machine where volume is detached from") private Long deviceId; + @ACL(accessType = AccessType.OperateEntry) @Parameter(name = ApiConstants.VIRTUAL_MACHINE_ID, type = CommandType.UUID, entityType = UserVmResponse.class, @@ -66,7 +66,6 @@ public class DetachVolumeCmd extends BaseAsyncVolumeCmd { /////////////////// Accessors /////////////////////// ///////////////////////////////////////////////////// - @Override public Long getId() { return id; } diff --git a/api/src/org/apache/cloudstack/api/command/user/volume/ExtractVolumeCmd.java b/api/src/org/apache/cloudstack/api/command/user/volume/ExtractVolumeCmd.java index cc7f56cc7b..049396c370 100644 --- a/api/src/org/apache/cloudstack/api/command/user/volume/ExtractVolumeCmd.java +++ b/api/src/org/apache/cloudstack/api/command/user/volume/ExtractVolumeCmd.java @@ -16,16 +16,15 @@ // under the License. package org.apache.cloudstack.api.command.user.volume; -import org.apache.cloudstack.api.BaseAsyncVolumeCmd; import org.apache.log4j.Logger; -import org.apache.cloudstack.acl.IAMEntityType; import org.apache.cloudstack.acl.SecurityChecker.AccessType; import org.apache.cloudstack.api.ACL; import org.apache.cloudstack.api.APICommand; import org.apache.cloudstack.api.ApiCommandJobType; import org.apache.cloudstack.api.ApiConstants; import org.apache.cloudstack.api.ApiErrorCode; +import org.apache.cloudstack.api.BaseAsyncCmd; import org.apache.cloudstack.api.Parameter; import org.apache.cloudstack.api.ServerApiException; import org.apache.cloudstack.api.response.ExtractResponse; @@ -39,9 +38,9 @@ import com.cloud.storage.Volume; import com.cloud.user.Account; -@APICommand(name = "extractVolume", description = "Extracts volume", responseObject = ExtractResponse.class, entityType = {IAMEntityType.Volume}, +@APICommand(name = "extractVolume", description = "Extracts volume", responseObject = ExtractResponse.class, entityType = {Volume.class}, requestHasSensitiveInfo = false, responseHasSensitiveInfo = false) -public class ExtractVolumeCmd extends BaseAsyncVolumeCmd { +public class ExtractVolumeCmd extends BaseAsyncCmd { public static final Logger s_logger = Logger.getLogger(ExtractVolumeCmd.class.getName()); private static final String s_name = "extractvolumeresponse"; diff --git a/api/src/org/apache/cloudstack/api/command/user/volume/ListResourceDetailsCmd.java b/api/src/org/apache/cloudstack/api/command/user/volume/ListResourceDetailsCmd.java index 0aeff0c63c..93dc29db79 100644 --- a/api/src/org/apache/cloudstack/api/command/user/volume/ListResourceDetailsCmd.java +++ b/api/src/org/apache/cloudstack/api/command/user/volume/ListResourceDetailsCmd.java @@ -19,6 +19,7 @@ import java.util.List; +import org.apache.cloudstack.acl.RoleType; import org.apache.cloudstack.api.APICommand; import org.apache.cloudstack.api.ApiConstants; import org.apache.cloudstack.api.BaseListProjectAndAccountResourcesCmd; @@ -26,7 +27,6 @@ import org.apache.cloudstack.api.response.ListResponse; import org.apache.cloudstack.api.response.ResourceDetailResponse; import org.apache.cloudstack.api.response.ResourceTagResponse; -import org.apache.cloudstack.context.CallContext; import com.cloud.server.ResourceTag; @@ -45,7 +45,7 @@ public class ListResourceDetailsCmd extends BaseListProjectAndAccountResourcesCm private String key; @Parameter(name = ApiConstants.FOR_DISPLAY, type = CommandType.BOOLEAN, description = "if set to true, only details marked with display=true, are returned." - + " Always false is the call is made by the regular user", since = "4.3") + + " False by default", since = "4.3", authorized = { RoleType.Admin }) private Boolean forDisplay; public String getResourceId() { @@ -61,12 +61,12 @@ public String getCommandName() { return s_name; } - public Boolean forDisplay() { - if (!_accountService.isAdmin(CallContext.current().getCallingAccount().getType())) { - return true; + @Override + public Boolean getDisplay() { + if (forDisplay != null) { + return forDisplay; } - - return forDisplay; + return super.getDisplay(); } ///////////////////////////////////////////////////// diff --git a/api/src/org/apache/cloudstack/api/command/user/volume/ListVolumesCmd.java b/api/src/org/apache/cloudstack/api/command/user/volume/ListVolumesCmd.java index b4ac4ae64c..cc218f7197 100644 --- a/api/src/org/apache/cloudstack/api/command/user/volume/ListVolumesCmd.java +++ b/api/src/org/apache/cloudstack/api/command/user/volume/ListVolumesCmd.java @@ -18,7 +18,6 @@ import org.apache.log4j.Logger; -import org.apache.cloudstack.acl.IAMEntityType; import org.apache.cloudstack.acl.RoleType; import org.apache.cloudstack.api.APICommand; import org.apache.cloudstack.api.ApiCommandJobType; @@ -35,7 +34,9 @@ import org.apache.cloudstack.api.response.VolumeResponse; import org.apache.cloudstack.api.response.ZoneResponse; -@APICommand(name = "listVolumes", description = "Lists all volumes.", responseObject = VolumeResponse.class, responseView = ResponseView.Restricted, entityType = { IAMEntityType.Volume }, +import com.cloud.storage.Volume; + +@APICommand(name = "listVolumes", description = "Lists all volumes.", responseObject = VolumeResponse.class, responseView = ResponseView.Restricted, entityType = {Volume.class}, requestHasSensitiveInfo = false, responseHasSensitiveInfo = false) public class ListVolumesCmd extends BaseListTaggedResourcesCmd { public static final Logger s_logger = Logger.getLogger(ListVolumesCmd.class.getName()); @@ -75,7 +76,11 @@ public class ListVolumesCmd extends BaseListTaggedResourcesCmd { authorized = {RoleType.Admin}) private Long storageId; - @Parameter(name = ApiConstants.DISK_OFFERING_ID, type = CommandType.UUID, entityType = DiskOfferingResponse.class, description = "list volumes by disk offering") + @Parameter(name = ApiConstants.DISK_OFFERING_ID, + type = CommandType.UUID, + entityType = DiskOfferingResponse.class, + description = "list volumes by disk offering", + since = "4.4") private Long diskOfferingId; @Parameter(name = ApiConstants.DISPLAY_VOLUME, type = CommandType.BOOLEAN, description = "list resources by display flag; only ROOT admin is eligible to pass this parameter", since = "4.4", authorized = {RoleType.Admin}) diff --git a/api/src/org/apache/cloudstack/api/command/user/volume/MigrateVolumeCmd.java b/api/src/org/apache/cloudstack/api/command/user/volume/MigrateVolumeCmd.java index d80595a78f..e751da342a 100644 --- a/api/src/org/apache/cloudstack/api/command/user/volume/MigrateVolumeCmd.java +++ b/api/src/org/apache/cloudstack/api/command/user/volume/MigrateVolumeCmd.java @@ -16,11 +16,10 @@ // under the License. package org.apache.cloudstack.api.command.user.volume; -import org.apache.cloudstack.acl.IAMEntityType; import org.apache.cloudstack.api.APICommand; import org.apache.cloudstack.api.ApiConstants; import org.apache.cloudstack.api.ApiErrorCode; -import org.apache.cloudstack.api.BaseAsyncVolumeCmd; +import org.apache.cloudstack.api.BaseAsyncCmd; import org.apache.cloudstack.api.Parameter; import org.apache.cloudstack.api.ResponseObject.ResponseView; import org.apache.cloudstack.api.ServerApiException; @@ -31,9 +30,9 @@ import com.cloud.storage.Volume; import com.cloud.user.Account; -@APICommand(name = "migrateVolume", description = "Migrate volume", responseObject = VolumeResponse.class, since = "3.0.0", responseView = ResponseView.Restricted, entityType = {IAMEntityType.Volume}, +@APICommand(name = "migrateVolume", description = "Migrate volume", responseObject = VolumeResponse.class, since = "3.0.0", responseView = ResponseView.Restricted, entityType = {Volume.class}, requestHasSensitiveInfo = false, responseHasSensitiveInfo = false) -public class MigrateVolumeCmd extends BaseAsyncVolumeCmd { +public class MigrateVolumeCmd extends BaseAsyncCmd { private static final String s_name = "migratevolumeresponse"; ///////////////////////////////////////////////////// @@ -65,7 +64,6 @@ public Long getVolumeId() { return volumeId; } - @Override public Long getId() { return getVolumeId(); } diff --git a/api/src/org/apache/cloudstack/api/command/user/volume/ResizeVolumeCmd.java b/api/src/org/apache/cloudstack/api/command/user/volume/ResizeVolumeCmd.java index d5cd62bbc3..1cf4f29dc2 100644 --- a/api/src/org/apache/cloudstack/api/command/user/volume/ResizeVolumeCmd.java +++ b/api/src/org/apache/cloudstack/api/command/user/volume/ResizeVolumeCmd.java @@ -15,16 +15,15 @@ // specific language governing permissions and limitations // under the License. package org.apache.cloudstack.api.command.user.volume; +import org.apache.cloudstack.api.BaseAsyncCmd; import org.apache.log4j.Logger; -import org.apache.cloudstack.acl.IAMEntityType; import org.apache.cloudstack.acl.SecurityChecker.AccessType; import org.apache.cloudstack.api.ACL; import org.apache.cloudstack.api.APICommand; import org.apache.cloudstack.api.ApiCommandJobType; import org.apache.cloudstack.api.ApiConstants; import org.apache.cloudstack.api.ApiErrorCode; -import org.apache.cloudstack.api.BaseAsyncVolumeCmd; import org.apache.cloudstack.api.Parameter; import org.apache.cloudstack.api.ResponseObject.ResponseView; import org.apache.cloudstack.api.ServerApiException; @@ -41,9 +40,9 @@ import com.cloud.user.Account; -@APICommand(name = "resizeVolume", description = "Resizes a volume", responseObject = VolumeResponse.class, responseView = ResponseView.Restricted, entityType = {IAMEntityType.Volume}, +@APICommand(name = "resizeVolume", description = "Resizes a volume", responseObject = VolumeResponse.class, responseView = ResponseView.Restricted, entityType = {Volume.class}, requestHasSensitiveInfo = false, responseHasSensitiveInfo = false) -public class ResizeVolumeCmd extends BaseAsyncVolumeCmd { +public class ResizeVolumeCmd extends BaseAsyncCmd { public static final Logger s_logger = Logger.getLogger(ResizeVolumeCmd.class.getName()); private static final String s_name = "resizevolumeresponse"; @@ -78,7 +77,6 @@ public Long getEntityId() { return id; } - @Override public Long getId() { return getEntityId(); } diff --git a/api/src/org/apache/cloudstack/api/command/user/volume/UpdateVolumeCmd.java b/api/src/org/apache/cloudstack/api/command/user/volume/UpdateVolumeCmd.java index 05e461e5ec..e7e3820da4 100644 --- a/api/src/org/apache/cloudstack/api/command/user/volume/UpdateVolumeCmd.java +++ b/api/src/org/apache/cloudstack/api/command/user/volume/UpdateVolumeCmd.java @@ -18,7 +18,6 @@ import org.apache.log4j.Logger; -import org.apache.cloudstack.acl.IAMEntityType; import org.apache.cloudstack.acl.RoleType; import org.apache.cloudstack.acl.SecurityChecker.AccessType; import org.apache.cloudstack.api.ACL; @@ -38,7 +37,7 @@ import com.cloud.exception.InvalidParameterValueException; import com.cloud.storage.Volume; -@APICommand(name = "updateVolume", description = "Updates the volume.", responseObject = VolumeResponse.class, responseView = ResponseView.Restricted, entityType = { IAMEntityType.Volume }, +@APICommand(name = "updateVolume", description = "Updates the volume.", responseObject = VolumeResponse.class, responseView = ResponseView.Restricted, entityType = {Volume.class}, requestHasSensitiveInfo = false, responseHasSensitiveInfo = false) public class UpdateVolumeCmd extends BaseAsyncCustomIdCmd { public static final Logger s_logger = Logger.getLogger(UpdateVolumeCmd.class.getName()); @@ -55,7 +54,10 @@ public class UpdateVolumeCmd extends BaseAsyncCustomIdCmd { @Parameter(name = ApiConstants.PATH, type = CommandType.STRING, description = "The path of the volume") private String path; - @Parameter(name = ApiConstants.CHAIN_INFO, type = CommandType.STRING, description = "The chain info of the volume") + @Parameter(name = ApiConstants.CHAIN_INFO, + type = CommandType.STRING, + description = "The chain info of the volume", + since = "4.4") private String chainInfo; @Parameter(name = ApiConstants.STORAGE_ID, @@ -128,11 +130,6 @@ public long getEntityOwnerId() { return volume.getAccountId(); } - @Override - public boolean isDisplayResourceEnabled(){ - return _volumeService.isDisplayResourceEnabled(getId()); - } - @Override public String getEventType() { return EventTypes.EVENT_VOLUME_UPDATE; diff --git a/api/src/org/apache/cloudstack/api/command/user/volume/UploadVolumeCmd.java b/api/src/org/apache/cloudstack/api/command/user/volume/UploadVolumeCmd.java index e992759224..7a08abf276 100644 --- a/api/src/org/apache/cloudstack/api/command/user/volume/UploadVolumeCmd.java +++ b/api/src/org/apache/cloudstack/api/command/user/volume/UploadVolumeCmd.java @@ -18,7 +18,6 @@ import org.apache.log4j.Logger; -import org.apache.cloudstack.acl.IAMEntityType; import org.apache.cloudstack.api.APICommand; import org.apache.cloudstack.api.ApiConstants; import org.apache.cloudstack.api.ApiErrorCode; @@ -40,7 +39,7 @@ import com.cloud.exception.ResourceUnavailableException; import com.cloud.storage.Volume; -@APICommand(name = "uploadVolume", description = "Uploads a data disk.", responseObject = VolumeResponse.class, responseView = ResponseView.Restricted, entityType = {IAMEntityType.Volume}, +@APICommand(name = "uploadVolume", description = "Uploads a data disk.", responseObject = VolumeResponse.class, responseView = ResponseView.Restricted, entityType = {Volume.class}, requestHasSensitiveInfo = false, responseHasSensitiveInfo = false) public class UploadVolumeCmd extends BaseAsyncCmd { public static final Logger s_logger = Logger.getLogger(UploadVolumeCmd.class.getName()); diff --git a/api/src/org/apache/cloudstack/api/command/user/vpc/CreateStaticRouteCmd.java b/api/src/org/apache/cloudstack/api/command/user/vpc/CreateStaticRouteCmd.java index f2c9e2c2e2..e2f2029ce0 100644 --- a/api/src/org/apache/cloudstack/api/command/user/vpc/CreateStaticRouteCmd.java +++ b/api/src/org/apache/cloudstack/api/command/user/vpc/CreateStaticRouteCmd.java @@ -18,7 +18,6 @@ import org.apache.log4j.Logger; -import org.apache.cloudstack.acl.IAMEntityType; import org.apache.cloudstack.api.APICommand; import org.apache.cloudstack.api.ApiCommandJobType; import org.apache.cloudstack.api.ApiConstants; @@ -40,7 +39,7 @@ import com.cloud.network.vpc.Vpc; import com.cloud.network.vpc.VpcGateway; -@APICommand(name = "createStaticRoute", description = "Creates a static route", responseObject = StaticRouteResponse.class, entityType = {IAMEntityType.StaticRoute}, +@APICommand(name = "createStaticRoute", description = "Creates a static route", responseObject = StaticRouteResponse.class, entityType = {StaticRoute.class}, requestHasSensitiveInfo = false, responseHasSensitiveInfo = false) public class CreateStaticRouteCmd extends BaseAsyncCreateCmd { private static final String s_name = "createstaticrouteresponse"; diff --git a/api/src/org/apache/cloudstack/api/command/user/vpc/CreateVPCCmd.java b/api/src/org/apache/cloudstack/api/command/user/vpc/CreateVPCCmd.java index c179ec857f..e2f261e1ba 100644 --- a/api/src/org/apache/cloudstack/api/command/user/vpc/CreateVPCCmd.java +++ b/api/src/org/apache/cloudstack/api/command/user/vpc/CreateVPCCmd.java @@ -18,7 +18,6 @@ import org.apache.log4j.Logger; -import org.apache.cloudstack.acl.IAMEntityType; import org.apache.cloudstack.acl.RoleType; import org.apache.cloudstack.api.APICommand; import org.apache.cloudstack.api.ApiConstants; @@ -41,7 +40,7 @@ import com.cloud.exception.ResourceUnavailableException; import com.cloud.network.vpc.Vpc; -@APICommand(name = "createVPC", description = "Creates a VPC", responseObject = VpcResponse.class, responseView = ResponseView.Restricted, entityType = {IAMEntityType.Vpc}, +@APICommand(name = "createVPC", description = "Creates a VPC", responseObject = VpcResponse.class, responseView = ResponseView.Restricted, entityType = {Vpc.class}, requestHasSensitiveInfo = false, responseHasSensitiveInfo = false) public class CreateVPCCmd extends BaseAsyncCreateCmd { public static final Logger s_logger = Logger.getLogger(CreateVPCCmd.class.getName()); @@ -65,7 +64,7 @@ public class CreateVPCCmd extends BaseAsyncCreateCmd { private Long projectId; @Parameter(name = ApiConstants.ZONE_ID, type = CommandType.UUID, entityType = ZoneResponse.class, - required = true, description = "the ID of the availability zone") + required = true, description = "the ID of the availability zone") private Long zoneId; @Parameter(name = ApiConstants.NAME, type = CommandType.STRING, required = true, description = "the name of the VPC") diff --git a/api/src/org/apache/cloudstack/api/command/user/vpc/DeleteStaticRouteCmd.java b/api/src/org/apache/cloudstack/api/command/user/vpc/DeleteStaticRouteCmd.java index 0017753e33..9449e6d534 100644 --- a/api/src/org/apache/cloudstack/api/command/user/vpc/DeleteStaticRouteCmd.java +++ b/api/src/org/apache/cloudstack/api/command/user/vpc/DeleteStaticRouteCmd.java @@ -18,7 +18,6 @@ import org.apache.log4j.Logger; -import org.apache.cloudstack.acl.IAMEntityType; import org.apache.cloudstack.acl.SecurityChecker.AccessType; import org.apache.cloudstack.api.ACL; import org.apache.cloudstack.api.APICommand; @@ -38,7 +37,7 @@ import com.cloud.exception.ResourceUnavailableException; import com.cloud.network.vpc.StaticRoute; -@APICommand(name = "deleteStaticRoute", description = "Deletes a static route", responseObject = SuccessResponse.class, entityType = {IAMEntityType.StaticRoute}, +@APICommand(name = "deleteStaticRoute", description = "Deletes a static route", responseObject = SuccessResponse.class, entityType = {StaticRoute.class}, requestHasSensitiveInfo = false, responseHasSensitiveInfo = false) public class DeleteStaticRouteCmd extends BaseAsyncCmd { public static final Logger s_logger = Logger.getLogger(DeleteStaticRouteCmd.class.getName()); diff --git a/api/src/org/apache/cloudstack/api/command/user/vpc/DeleteVPCCmd.java b/api/src/org/apache/cloudstack/api/command/user/vpc/DeleteVPCCmd.java index 5928aabff6..9d13b63e6a 100644 --- a/api/src/org/apache/cloudstack/api/command/user/vpc/DeleteVPCCmd.java +++ b/api/src/org/apache/cloudstack/api/command/user/vpc/DeleteVPCCmd.java @@ -18,7 +18,6 @@ import org.apache.log4j.Logger; -import org.apache.cloudstack.acl.IAMEntityType; import org.apache.cloudstack.acl.SecurityChecker.AccessType; import org.apache.cloudstack.api.ACL; import org.apache.cloudstack.api.APICommand; @@ -36,7 +35,7 @@ import com.cloud.network.vpc.Vpc; import com.cloud.user.Account; -@APICommand(name = "deleteVPC", description = "Deletes a VPC", responseObject = SuccessResponse.class, entityType = {IAMEntityType.Vpc}, +@APICommand(name = "deleteVPC", description = "Deletes a VPC", responseObject = SuccessResponse.class, entityType = {Vpc.class}, requestHasSensitiveInfo = false, responseHasSensitiveInfo = false) public class DeleteVPCCmd extends BaseAsyncCmd { public static final Logger s_logger = Logger.getLogger(DeleteVPCCmd.class.getName()); diff --git a/api/src/org/apache/cloudstack/api/command/user/vpc/ListPrivateGatewaysCmd.java b/api/src/org/apache/cloudstack/api/command/user/vpc/ListPrivateGatewaysCmd.java index 160355a481..a985e7633c 100644 --- a/api/src/org/apache/cloudstack/api/command/user/vpc/ListPrivateGatewaysCmd.java +++ b/api/src/org/apache/cloudstack/api/command/user/vpc/ListPrivateGatewaysCmd.java @@ -21,7 +21,6 @@ import org.apache.log4j.Logger; -import org.apache.cloudstack.acl.IAMEntityType; import org.apache.cloudstack.api.APICommand; import org.apache.cloudstack.api.ApiConstants; import org.apache.cloudstack.api.BaseListProjectAndAccountResourcesCmd; @@ -31,9 +30,10 @@ import org.apache.cloudstack.api.response.VpcResponse; import com.cloud.network.vpc.PrivateGateway; +import com.cloud.network.vpc.VpcGateway; import com.cloud.utils.Pair; -@APICommand(name = "listPrivateGateways", description = "List private gateways", responseObject = PrivateGatewayResponse.class, entityType = {IAMEntityType.VpcGateway}, +@APICommand(name = "listPrivateGateways", description = "List private gateways", responseObject = PrivateGatewayResponse.class, entityType = {VpcGateway.class}, requestHasSensitiveInfo = false, responseHasSensitiveInfo = false) public class ListPrivateGatewaysCmd extends BaseListProjectAndAccountResourcesCmd { public static final Logger s_logger = Logger.getLogger(ListPrivateGatewaysCmd.class.getName()); diff --git a/api/src/org/apache/cloudstack/api/command/user/vpc/ListStaticRoutesCmd.java b/api/src/org/apache/cloudstack/api/command/user/vpc/ListStaticRoutesCmd.java index b2cdf87911..3dba84c8a7 100644 --- a/api/src/org/apache/cloudstack/api/command/user/vpc/ListStaticRoutesCmd.java +++ b/api/src/org/apache/cloudstack/api/command/user/vpc/ListStaticRoutesCmd.java @@ -19,7 +19,6 @@ import java.util.ArrayList; import java.util.List; -import org.apache.cloudstack.acl.IAMEntityType; import org.apache.cloudstack.api.APICommand; import org.apache.cloudstack.api.ApiConstants; import org.apache.cloudstack.api.BaseListTaggedResourcesCmd; @@ -32,7 +31,7 @@ import com.cloud.network.vpc.StaticRoute; import com.cloud.utils.Pair; -@APICommand(name = "listStaticRoutes", description = "Lists all static routes", responseObject = StaticRouteResponse.class, entityType = {IAMEntityType.StaticRoute}, +@APICommand(name = "listStaticRoutes", description = "Lists all static routes", responseObject = StaticRouteResponse.class, entityType = {StaticRoute.class}, requestHasSensitiveInfo = false, responseHasSensitiveInfo = false) public class ListStaticRoutesCmd extends BaseListTaggedResourcesCmd { private static final String s_name = "liststaticroutesresponse"; diff --git a/api/src/org/apache/cloudstack/api/command/user/vpc/ListVPCOfferingsCmd.java b/api/src/org/apache/cloudstack/api/command/user/vpc/ListVPCOfferingsCmd.java index 66ea17654a..e76afc92cd 100644 --- a/api/src/org/apache/cloudstack/api/command/user/vpc/ListVPCOfferingsCmd.java +++ b/api/src/org/apache/cloudstack/api/command/user/vpc/ListVPCOfferingsCmd.java @@ -34,7 +34,7 @@ requestHasSensitiveInfo = false, responseHasSensitiveInfo = false) public class ListVPCOfferingsCmd extends BaseListCmd { public static final Logger s_logger = Logger.getLogger(ListVPCOfferingsCmd.class.getName()); - private static final String Name = "listvpcofferingsresponse"; + private static final String s_name = "listvpcofferingsresponse"; ///////////////////////////////////////////////////// //////////////// API parameters ///////////////////// @@ -110,7 +110,7 @@ public void execute() { @Override public String getCommandName() { - return Name; + return s_name; } } diff --git a/api/src/org/apache/cloudstack/api/command/user/vpc/ListVPCsCmd.java b/api/src/org/apache/cloudstack/api/command/user/vpc/ListVPCsCmd.java index fa60f6f773..9079dff11d 100644 --- a/api/src/org/apache/cloudstack/api/command/user/vpc/ListVPCsCmd.java +++ b/api/src/org/apache/cloudstack/api/command/user/vpc/ListVPCsCmd.java @@ -21,7 +21,6 @@ import org.apache.log4j.Logger; -import org.apache.cloudstack.acl.IAMEntityType; import org.apache.cloudstack.acl.RoleType; import org.apache.cloudstack.api.APICommand; import org.apache.cloudstack.api.ApiConstants; @@ -36,7 +35,7 @@ import com.cloud.network.vpc.Vpc; -@APICommand(name = "listVPCs", description = "Lists VPCs", responseObject = VpcResponse.class, responseView = ResponseView.Restricted, entityType = { IAMEntityType.Vpc }, +@APICommand(name = "listVPCs", description = "Lists VPCs", responseObject = VpcResponse.class, responseView = ResponseView.Restricted, entityType = {Vpc.class}, requestHasSensitiveInfo = false, responseHasSensitiveInfo = false) public class ListVPCsCmd extends BaseListTaggedResourcesCmd { public static final Logger s_logger = Logger.getLogger(ListVPCsCmd.class.getName()); diff --git a/api/src/org/apache/cloudstack/api/command/user/vpc/RestartVPCCmd.java b/api/src/org/apache/cloudstack/api/command/user/vpc/RestartVPCCmd.java index d1d805ae48..84e790c3b2 100644 --- a/api/src/org/apache/cloudstack/api/command/user/vpc/RestartVPCCmd.java +++ b/api/src/org/apache/cloudstack/api/command/user/vpc/RestartVPCCmd.java @@ -18,7 +18,6 @@ import org.apache.log4j.Logger; -import org.apache.cloudstack.acl.IAMEntityType; import org.apache.cloudstack.acl.SecurityChecker.AccessType; import org.apache.cloudstack.api.ACL; import org.apache.cloudstack.api.APICommand; @@ -37,11 +36,11 @@ import com.cloud.network.vpc.Vpc; import com.cloud.user.Account; -@APICommand(name = "restartVPC", description = "Restarts a VPC", responseObject = VpcResponse.class, entityType = {IAMEntityType.Vpc}, +@APICommand(name = "restartVPC", description = "Restarts a VPC", responseObject = VpcResponse.class, entityType = {Vpc.class}, requestHasSensitiveInfo = false, responseHasSensitiveInfo = false) public class RestartVPCCmd extends BaseAsyncCmd { public static final Logger s_logger = Logger.getLogger(RestartVPCCmd.class.getName()); - private static final String Name = "restartvpcresponse"; + private static final String s_name = "restartvpcresponse"; ///////////////////////////////////////////////////// //////////////// API parameters ///////////////////// @@ -63,7 +62,7 @@ public Long getId() { ///////////////////////////////////////////////////// @Override public String getCommandName() { - return Name; + return s_name; } @Override diff --git a/api/src/org/apache/cloudstack/api/command/user/vpc/UpdateVPCCmd.java b/api/src/org/apache/cloudstack/api/command/user/vpc/UpdateVPCCmd.java index 76244233b9..94d0e6efcd 100644 --- a/api/src/org/apache/cloudstack/api/command/user/vpc/UpdateVPCCmd.java +++ b/api/src/org/apache/cloudstack/api/command/user/vpc/UpdateVPCCmd.java @@ -18,7 +18,6 @@ import org.apache.log4j.Logger; -import org.apache.cloudstack.acl.IAMEntityType; import org.apache.cloudstack.acl.RoleType; import org.apache.cloudstack.acl.SecurityChecker.AccessType; import org.apache.cloudstack.api.ACL; @@ -36,11 +35,11 @@ import com.cloud.network.vpc.Vpc; import com.cloud.user.Account; -@APICommand(name = "updateVPC", description = "Updates a VPC", responseObject = VpcResponse.class, responseView = ResponseView.Restricted, entityType = { IAMEntityType.Vpc }, +@APICommand(name = "updateVPC", description = "Updates a VPC", responseObject = VpcResponse.class, responseView = ResponseView.Restricted, entityType = {Vpc.class}, requestHasSensitiveInfo = false, responseHasSensitiveInfo = false) public class UpdateVPCCmd extends BaseAsyncCustomIdCmd { public static final Logger s_logger = Logger.getLogger(UpdateVPCCmd.class.getName()); - private static final String Name = "updatevpcresponse"; + private static final String s_name = "updatevpcresponse"; ///////////////////////////////////////////////////// //////////////// API parameters ///////////////////// @@ -83,7 +82,7 @@ public Boolean getDisplayVpc() { ///////////////////////////////////////////////////// @Override public String getCommandName() { - return Name; + return s_name; } @Override diff --git a/api/src/org/apache/cloudstack/api/command/user/vpn/AddVpnUserCmd.java b/api/src/org/apache/cloudstack/api/command/user/vpn/AddVpnUserCmd.java index e839f9feff..9993102eca 100644 --- a/api/src/org/apache/cloudstack/api/command/user/vpn/AddVpnUserCmd.java +++ b/api/src/org/apache/cloudstack/api/command/user/vpn/AddVpnUserCmd.java @@ -18,7 +18,6 @@ import org.apache.log4j.Logger; -import org.apache.cloudstack.acl.IAMEntityType; import org.apache.cloudstack.api.APICommand; import org.apache.cloudstack.api.ApiConstants; import org.apache.cloudstack.api.ApiErrorCode; @@ -35,7 +34,7 @@ import com.cloud.network.VpnUser; import com.cloud.user.Account; -@APICommand(name = "addVpnUser", description = "Adds vpn users", responseObject = VpnUsersResponse.class, entityType = {IAMEntityType.VpnUser}, +@APICommand(name = "addVpnUser", description = "Adds vpn users", responseObject = VpnUsersResponse.class, entityType = {VpnUser.class}, requestHasSensitiveInfo = false, responseHasSensitiveInfo = false) public class AddVpnUserCmd extends BaseAsyncCreateCmd { public static final Logger s_logger = Logger.getLogger(AddVpnUserCmd.class.getName()); diff --git a/api/src/org/apache/cloudstack/api/command/user/vpn/CreateRemoteAccessVpnCmd.java b/api/src/org/apache/cloudstack/api/command/user/vpn/CreateRemoteAccessVpnCmd.java index 4df21345ec..14b781d236 100644 --- a/api/src/org/apache/cloudstack/api/command/user/vpn/CreateRemoteAccessVpnCmd.java +++ b/api/src/org/apache/cloudstack/api/command/user/vpn/CreateRemoteAccessVpnCmd.java @@ -18,7 +18,6 @@ import org.apache.log4j.Logger; -import org.apache.cloudstack.acl.IAMEntityType; import org.apache.cloudstack.acl.RoleType; import org.apache.cloudstack.api.APICommand; import org.apache.cloudstack.api.ApiConstants; @@ -38,7 +37,7 @@ import com.cloud.network.IpAddress; import com.cloud.network.RemoteAccessVpn; -@APICommand(name = "createRemoteAccessVpn", description = "Creates a l2tp/ipsec remote access vpn", responseObject = RemoteAccessVpnResponse.class, entityType = { IAMEntityType.RemoteAccessVpn }, +@APICommand(name = "createRemoteAccessVpn", description = "Creates a l2tp/ipsec remote access vpn", responseObject = RemoteAccessVpnResponse.class, entityType = {RemoteAccessVpn.class}, requestHasSensitiveInfo = false, responseHasSensitiveInfo = false) public class CreateRemoteAccessVpnCmd extends BaseAsyncCreateCmd { public static final Logger s_logger = Logger.getLogger(CreateRemoteAccessVpnCmd.class.getName()); @@ -146,7 +145,7 @@ public String getEventType() { @Override public void create() { try { - RemoteAccessVpn vpn = _ravService.createRemoteAccessVpn(publicIpId, ipRange, getOpenFirewall(), getDisplay()); + RemoteAccessVpn vpn = _ravService.createRemoteAccessVpn(publicIpId, ipRange, getOpenFirewall(), isDisplay()); if (vpn != null) { setEntityId(vpn.getServerAddressId()); // find uuid for server ip address @@ -199,7 +198,11 @@ private IpAddress getIp() { return ip; } - public Boolean getDisplay() { - return display; + @Override + public boolean isDisplay() { + if(display == null) + return true; + else + return display; } } diff --git a/api/src/org/apache/cloudstack/api/command/user/vpn/CreateVpnConnectionCmd.java b/api/src/org/apache/cloudstack/api/command/user/vpn/CreateVpnConnectionCmd.java index d405c17ac3..6c08a42325 100644 --- a/api/src/org/apache/cloudstack/api/command/user/vpn/CreateVpnConnectionCmd.java +++ b/api/src/org/apache/cloudstack/api/command/user/vpn/CreateVpnConnectionCmd.java @@ -18,7 +18,6 @@ import org.apache.log4j.Logger; -import org.apache.cloudstack.acl.IAMEntityType; import org.apache.cloudstack.acl.RoleType; import org.apache.cloudstack.api.APICommand; import org.apache.cloudstack.api.ApiConstants; @@ -39,7 +38,7 @@ import com.cloud.network.vpc.Vpc; -@APICommand(name = "createVpnConnection", description = "Create site to site vpn connection", responseObject = Site2SiteVpnConnectionResponse.class, entityType = { IAMEntityType.Site2SiteVpnConnection }, +@APICommand(name = "createVpnConnection", description = "Create site to site vpn connection", responseObject = Site2SiteVpnConnectionResponse.class, entityType = {Site2SiteVpnConnection.class}, requestHasSensitiveInfo = false, responseHasSensitiveInfo = false) public class CreateVpnConnectionCmd extends BaseAsyncCreateCmd { public static final Logger s_logger = Logger.getLogger(CreateVpnConnectionCmd.class.getName()); @@ -88,10 +87,20 @@ public boolean isPassive() { return passive; } + @Deprecated public Boolean getDisplay() { return display; } + @Override + public boolean isDisplay() { + if (display != null) { + return display; + } else { + return true; + } + } + ///////////////////////////////////////////////////// /////////////// API Implementation/////////////////// ///////////////////////////////////////////////////// diff --git a/api/src/org/apache/cloudstack/api/command/user/vpn/CreateVpnCustomerGatewayCmd.java b/api/src/org/apache/cloudstack/api/command/user/vpn/CreateVpnCustomerGatewayCmd.java index 5da46f0ada..6967ff4978 100644 --- a/api/src/org/apache/cloudstack/api/command/user/vpn/CreateVpnCustomerGatewayCmd.java +++ b/api/src/org/apache/cloudstack/api/command/user/vpn/CreateVpnCustomerGatewayCmd.java @@ -18,7 +18,6 @@ import org.apache.log4j.Logger; -import org.apache.cloudstack.acl.IAMEntityType; import org.apache.cloudstack.api.APICommand; import org.apache.cloudstack.api.ApiConstants; import org.apache.cloudstack.api.ApiErrorCode; @@ -32,7 +31,7 @@ import com.cloud.event.EventTypes; import com.cloud.network.Site2SiteCustomerGateway; -@APICommand(name = "createVpnCustomerGateway", description = "Creates site to site vpn customer gateway", responseObject = Site2SiteCustomerGatewayResponse.class, entityType = {IAMEntityType.Site2SiteCustomerGateway}, +@APICommand(name = "createVpnCustomerGateway", description = "Creates site to site vpn customer gateway", responseObject = Site2SiteCustomerGatewayResponse.class, entityType = {Site2SiteCustomerGateway.class}, requestHasSensitiveInfo = false, responseHasSensitiveInfo = false) public class CreateVpnCustomerGatewayCmd extends BaseAsyncCmd { public static final Logger s_logger = Logger.getLogger(CreateVpnCustomerGatewayCmd.class.getName()); diff --git a/api/src/org/apache/cloudstack/api/command/user/vpn/CreateVpnGatewayCmd.java b/api/src/org/apache/cloudstack/api/command/user/vpn/CreateVpnGatewayCmd.java index 12abfb6e35..fb933ba832 100644 --- a/api/src/org/apache/cloudstack/api/command/user/vpn/CreateVpnGatewayCmd.java +++ b/api/src/org/apache/cloudstack/api/command/user/vpn/CreateVpnGatewayCmd.java @@ -18,7 +18,6 @@ import org.apache.log4j.Logger; -import org.apache.cloudstack.acl.IAMEntityType; import org.apache.cloudstack.acl.RoleType; import org.apache.cloudstack.api.APICommand; import org.apache.cloudstack.api.ApiConstants; @@ -33,7 +32,7 @@ import com.cloud.network.Site2SiteVpnGateway; import com.cloud.network.vpc.Vpc; -@APICommand(name = "createVpnGateway", description = "Creates site to site vpn local gateway", responseObject = Site2SiteVpnGatewayResponse.class, entityType = { IAMEntityType.Site2SiteVpnGateway }, +@APICommand(name = "createVpnGateway", description = "Creates site to site vpn local gateway", responseObject = Site2SiteVpnGatewayResponse.class, entityType = {Site2SiteVpnGateway.class}, requestHasSensitiveInfo = false, responseHasSensitiveInfo = false) public class CreateVpnGatewayCmd extends BaseAsyncCmd { public static final Logger s_logger = Logger.getLogger(CreateVpnGatewayCmd.class.getName()); @@ -61,10 +60,20 @@ public Long getVpcId() { return vpcId; } + @Deprecated public Boolean getDisplay() { return display; } + @Override + public boolean isDisplay() { + if (display != null) { + return display; + } else { + return true; + } + } + ///////////////////////////////////////////////////// /////////////// API Implementation/////////////////// ///////////////////////////////////////////////////// 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 7d0c5aa5a4..37b7b5aaa3 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 @@ -18,9 +18,10 @@ import org.apache.log4j.Logger; -import org.apache.cloudstack.acl.IAMEntityType; import org.apache.cloudstack.api.APICommand; import org.apache.cloudstack.api.ApiConstants; +import org.apache.cloudstack.api.ApiErrorCode; +import org.apache.cloudstack.api.ServerApiException; import org.apache.cloudstack.api.BaseAsyncCmd; import org.apache.cloudstack.api.Parameter; import org.apache.cloudstack.api.response.AccountResponse; @@ -33,7 +34,7 @@ import com.cloud.exception.ResourceUnavailableException; import com.cloud.network.RemoteAccessVpn; -@APICommand(name = "deleteRemoteAccessVpn", description = "Destroys a l2tp/ipsec remote access vpn", responseObject = SuccessResponse.class, entityType = {IAMEntityType.RemoteAccessVpn}, +@APICommand(name = "deleteRemoteAccessVpn", description = "Destroys a l2tp/ipsec remote access vpn", responseObject = SuccessResponse.class, entityType = {RemoteAccessVpn.class}, requestHasSensitiveInfo = false, responseHasSensitiveInfo = false) public class DeleteRemoteAccessVpnCmd extends BaseAsyncCmd { public static final Logger s_logger = Logger.getLogger(DeleteRemoteAccessVpnCmd.class.getName()); @@ -92,7 +93,9 @@ public String getEventType() { @Override public void execute() throws ResourceUnavailableException { - _ravService.destroyRemoteAccessVpnForIp(publicIpId, CallContext.current().getCallingAccount()); + if (! _ravService.destroyRemoteAccessVpnForIp(publicIpId, CallContext.current().getCallingAccount())) { + throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, "Failed to delete remote access vpn"); + } } @Override diff --git a/api/src/org/apache/cloudstack/api/command/user/vpn/DeleteVpnConnectionCmd.java b/api/src/org/apache/cloudstack/api/command/user/vpn/DeleteVpnConnectionCmd.java index 6034bcb0de..a76b0c804e 100644 --- a/api/src/org/apache/cloudstack/api/command/user/vpn/DeleteVpnConnectionCmd.java +++ b/api/src/org/apache/cloudstack/api/command/user/vpn/DeleteVpnConnectionCmd.java @@ -18,7 +18,6 @@ import org.apache.log4j.Logger; -import org.apache.cloudstack.acl.IAMEntityType; import org.apache.cloudstack.api.APICommand; import org.apache.cloudstack.api.ApiConstants; import org.apache.cloudstack.api.ApiErrorCode; @@ -33,7 +32,7 @@ import com.cloud.network.Site2SiteVpnConnection; import com.cloud.user.Account; -@APICommand(name = "deleteVpnConnection", description = "Delete site to site vpn connection", responseObject = SuccessResponse.class, entityType = {IAMEntityType.Site2SiteVpnConnection}, +@APICommand(name = "deleteVpnConnection", description = "Delete site to site vpn connection", responseObject = SuccessResponse.class, entityType = {Site2SiteVpnConnection.class}, requestHasSensitiveInfo = false, responseHasSensitiveInfo = false) public class DeleteVpnConnectionCmd extends BaseAsyncCmd { public static final Logger s_logger = Logger.getLogger(DeleteVpnConnectionCmd.class.getName()); diff --git a/api/src/org/apache/cloudstack/api/command/user/vpn/DeleteVpnCustomerGatewayCmd.java b/api/src/org/apache/cloudstack/api/command/user/vpn/DeleteVpnCustomerGatewayCmd.java index 3faf5fd201..aad69ce0a9 100644 --- a/api/src/org/apache/cloudstack/api/command/user/vpn/DeleteVpnCustomerGatewayCmd.java +++ b/api/src/org/apache/cloudstack/api/command/user/vpn/DeleteVpnCustomerGatewayCmd.java @@ -18,7 +18,6 @@ import org.apache.log4j.Logger; -import org.apache.cloudstack.acl.IAMEntityType; import org.apache.cloudstack.acl.SecurityChecker.AccessType; import org.apache.cloudstack.api.ACL; import org.apache.cloudstack.api.APICommand; @@ -34,7 +33,7 @@ import com.cloud.network.Site2SiteCustomerGateway; import com.cloud.user.Account; -@APICommand(name = "deleteVpnCustomerGateway", description = "Delete site to site vpn customer gateway", responseObject = SuccessResponse.class, entityType = {IAMEntityType.Site2SiteCustomerGateway}, +@APICommand(name = "deleteVpnCustomerGateway", description = "Delete site to site vpn customer gateway", responseObject = SuccessResponse.class, entityType = {Site2SiteCustomerGateway.class}, requestHasSensitiveInfo = false, responseHasSensitiveInfo = false) public class DeleteVpnCustomerGatewayCmd extends BaseAsyncCmd { public static final Logger s_logger = Logger.getLogger(DeleteVpnCustomerGatewayCmd.class.getName()); diff --git a/api/src/org/apache/cloudstack/api/command/user/vpn/DeleteVpnGatewayCmd.java b/api/src/org/apache/cloudstack/api/command/user/vpn/DeleteVpnGatewayCmd.java index 66fd55bba2..ff927408a2 100644 --- a/api/src/org/apache/cloudstack/api/command/user/vpn/DeleteVpnGatewayCmd.java +++ b/api/src/org/apache/cloudstack/api/command/user/vpn/DeleteVpnGatewayCmd.java @@ -18,7 +18,6 @@ import org.apache.log4j.Logger; -import org.apache.cloudstack.acl.IAMEntityType; import org.apache.cloudstack.api.APICommand; import org.apache.cloudstack.api.ApiConstants; import org.apache.cloudstack.api.ApiErrorCode; @@ -32,7 +31,7 @@ import com.cloud.network.Site2SiteVpnGateway; import com.cloud.user.Account; -@APICommand(name = "deleteVpnGateway", description = "Delete site to site vpn gateway", responseObject = SuccessResponse.class, entityType = {IAMEntityType.Site2SiteVpnGateway}, +@APICommand(name = "deleteVpnGateway", description = "Delete site to site vpn gateway", responseObject = SuccessResponse.class, entityType = {Site2SiteVpnGateway.class}, requestHasSensitiveInfo = false, responseHasSensitiveInfo = false) public class DeleteVpnGatewayCmd extends BaseAsyncCmd { public static final Logger s_logger = Logger.getLogger(DeleteVpnGatewayCmd.class.getName()); diff --git a/api/src/org/apache/cloudstack/api/command/user/vpn/ListRemoteAccessVpnsCmd.java b/api/src/org/apache/cloudstack/api/command/user/vpn/ListRemoteAccessVpnsCmd.java index 61a3a2993b..492eaccefa 100644 --- a/api/src/org/apache/cloudstack/api/command/user/vpn/ListRemoteAccessVpnsCmd.java +++ b/api/src/org/apache/cloudstack/api/command/user/vpn/ListRemoteAccessVpnsCmd.java @@ -21,7 +21,6 @@ import org.apache.log4j.Logger; -import org.apache.cloudstack.acl.IAMEntityType; import org.apache.cloudstack.acl.RoleType; import org.apache.cloudstack.api.APICommand; import org.apache.cloudstack.api.ApiConstants; @@ -35,7 +34,7 @@ import com.cloud.network.RemoteAccessVpn; import com.cloud.utils.Pair; -@APICommand(name = "listRemoteAccessVpns", description = "Lists remote access vpns", responseObject = RemoteAccessVpnResponse.class, entityType = { IAMEntityType.RemoteAccessVpn }, +@APICommand(name = "listRemoteAccessVpns", description = "Lists remote access vpns", responseObject = RemoteAccessVpnResponse.class, entityType = {RemoteAccessVpn.class}, requestHasSensitiveInfo = false, responseHasSensitiveInfo = false) public class ListRemoteAccessVpnsCmd extends BaseListProjectAndAccountResourcesCmd { public static final Logger s_logger = Logger.getLogger(ListRemoteAccessVpnsCmd.class.getName()); diff --git a/api/src/org/apache/cloudstack/api/command/user/vpn/ListVpnConnectionsCmd.java b/api/src/org/apache/cloudstack/api/command/user/vpn/ListVpnConnectionsCmd.java index f8e81c2f01..74b9325eb2 100644 --- a/api/src/org/apache/cloudstack/api/command/user/vpn/ListVpnConnectionsCmd.java +++ b/api/src/org/apache/cloudstack/api/command/user/vpn/ListVpnConnectionsCmd.java @@ -21,7 +21,6 @@ import org.apache.log4j.Logger; -import org.apache.cloudstack.acl.IAMEntityType; import org.apache.cloudstack.acl.RoleType; import org.apache.cloudstack.api.APICommand; import org.apache.cloudstack.api.ApiConstants; @@ -34,7 +33,7 @@ import com.cloud.network.Site2SiteVpnConnection; import com.cloud.utils.Pair; -@APICommand(name = "listVpnConnections", description = "Lists site to site vpn connection gateways", responseObject = Site2SiteVpnConnectionResponse.class, entityType = { IAMEntityType.Site2SiteVpnConnection }, +@APICommand(name = "listVpnConnections", description = "Lists site to site vpn connection gateways", responseObject = Site2SiteVpnConnectionResponse.class, entityType = {Site2SiteVpnConnection.class}, requestHasSensitiveInfo = false, responseHasSensitiveInfo = false) public class ListVpnConnectionsCmd extends BaseListProjectAndAccountResourcesCmd { public static final Logger s_logger = Logger.getLogger(ListVpnConnectionsCmd.class.getName()); diff --git a/api/src/org/apache/cloudstack/api/command/user/vpn/ListVpnCustomerGatewaysCmd.java b/api/src/org/apache/cloudstack/api/command/user/vpn/ListVpnCustomerGatewaysCmd.java index fed96a72b3..6b870be138 100644 --- a/api/src/org/apache/cloudstack/api/command/user/vpn/ListVpnCustomerGatewaysCmd.java +++ b/api/src/org/apache/cloudstack/api/command/user/vpn/ListVpnCustomerGatewaysCmd.java @@ -21,7 +21,6 @@ import org.apache.log4j.Logger; -import org.apache.cloudstack.acl.IAMEntityType; import org.apache.cloudstack.api.APICommand; import org.apache.cloudstack.api.ApiConstants; import org.apache.cloudstack.api.BaseListProjectAndAccountResourcesCmd; @@ -32,7 +31,7 @@ import com.cloud.network.Site2SiteCustomerGateway; import com.cloud.utils.Pair; -@APICommand(name = "listVpnCustomerGateways", description = "Lists site to site vpn customer gateways", responseObject = Site2SiteCustomerGatewayResponse.class, entityType = {IAMEntityType.Site2SiteCustomerGateway}, +@APICommand(name = "listVpnCustomerGateways", description = "Lists site to site vpn customer gateways", responseObject = Site2SiteCustomerGatewayResponse.class, entityType = {Site2SiteCustomerGateway.class}, requestHasSensitiveInfo = false, responseHasSensitiveInfo = false) public class ListVpnCustomerGatewaysCmd extends BaseListProjectAndAccountResourcesCmd { public static final Logger s_logger = Logger.getLogger(ListVpnCustomerGatewaysCmd.class.getName()); diff --git a/api/src/org/apache/cloudstack/api/command/user/vpn/ListVpnGatewaysCmd.java b/api/src/org/apache/cloudstack/api/command/user/vpn/ListVpnGatewaysCmd.java index 17702252e8..3eade02880 100644 --- a/api/src/org/apache/cloudstack/api/command/user/vpn/ListVpnGatewaysCmd.java +++ b/api/src/org/apache/cloudstack/api/command/user/vpn/ListVpnGatewaysCmd.java @@ -21,7 +21,6 @@ import org.apache.log4j.Logger; -import org.apache.cloudstack.acl.IAMEntityType; import org.apache.cloudstack.acl.RoleType; import org.apache.cloudstack.api.APICommand; import org.apache.cloudstack.api.ApiConstants; @@ -34,7 +33,7 @@ import com.cloud.network.Site2SiteVpnGateway; import com.cloud.utils.Pair; -@APICommand(name = "listVpnGateways", description = "Lists site 2 site vpn gateways", responseObject = Site2SiteVpnGatewayResponse.class, entityType = { IAMEntityType.Site2SiteVpnGateway }, +@APICommand(name = "listVpnGateways", description = "Lists site 2 site vpn gateways", responseObject = Site2SiteVpnGatewayResponse.class, entityType = {Site2SiteVpnGateway.class}, requestHasSensitiveInfo = false, responseHasSensitiveInfo = false) public class ListVpnGatewaysCmd extends BaseListProjectAndAccountResourcesCmd { public static final Logger s_logger = Logger.getLogger(ListVpnGatewaysCmd.class.getName()); diff --git a/api/src/org/apache/cloudstack/api/command/user/vpn/ListVpnUsersCmd.java b/api/src/org/apache/cloudstack/api/command/user/vpn/ListVpnUsersCmd.java index 1d8ea85cbb..9af060ac00 100644 --- a/api/src/org/apache/cloudstack/api/command/user/vpn/ListVpnUsersCmd.java +++ b/api/src/org/apache/cloudstack/api/command/user/vpn/ListVpnUsersCmd.java @@ -21,7 +21,6 @@ import org.apache.log4j.Logger; -import org.apache.cloudstack.acl.IAMEntityType; import org.apache.cloudstack.api.APICommand; import org.apache.cloudstack.api.ApiConstants; import org.apache.cloudstack.api.BaseListProjectAndAccountResourcesCmd; @@ -32,7 +31,7 @@ import com.cloud.network.VpnUser; import com.cloud.utils.Pair; -@APICommand(name = "listVpnUsers", description = "Lists vpn users", responseObject = VpnUsersResponse.class, entityType = {IAMEntityType.VpnUser}, +@APICommand(name = "listVpnUsers", description = "Lists vpn users", responseObject = VpnUsersResponse.class, entityType = {VpnUser.class}, requestHasSensitiveInfo = false, responseHasSensitiveInfo = false) public class ListVpnUsersCmd extends BaseListProjectAndAccountResourcesCmd { public static final Logger s_logger = Logger.getLogger(ListVpnUsersCmd.class.getName()); diff --git a/api/src/org/apache/cloudstack/api/command/user/vpn/RemoveVpnUserCmd.java b/api/src/org/apache/cloudstack/api/command/user/vpn/RemoveVpnUserCmd.java index 068746945c..f552b14fbf 100644 --- a/api/src/org/apache/cloudstack/api/command/user/vpn/RemoveVpnUserCmd.java +++ b/api/src/org/apache/cloudstack/api/command/user/vpn/RemoveVpnUserCmd.java @@ -18,7 +18,6 @@ import org.apache.log4j.Logger; -import org.apache.cloudstack.acl.IAMEntityType; import org.apache.cloudstack.api.APICommand; import org.apache.cloudstack.api.ApiConstants; import org.apache.cloudstack.api.ApiErrorCode; @@ -31,9 +30,10 @@ import org.apache.cloudstack.context.CallContext; import com.cloud.event.EventTypes; +import com.cloud.network.VpnUser; import com.cloud.user.Account; -@APICommand(name = "removeVpnUser", description = "Removes vpn user", responseObject = SuccessResponse.class, entityType = {IAMEntityType.VpnUser}, +@APICommand(name = "removeVpnUser", description = "Removes vpn user", responseObject = SuccessResponse.class, entityType = {VpnUser.class}, requestHasSensitiveInfo = false, responseHasSensitiveInfo = false) public class RemoveVpnUserCmd extends BaseAsyncCmd { public static final Logger s_logger = Logger.getLogger(RemoveVpnUserCmd.class.getName()); diff --git a/api/src/org/apache/cloudstack/api/command/user/vpn/ResetVpnConnectionCmd.java b/api/src/org/apache/cloudstack/api/command/user/vpn/ResetVpnConnectionCmd.java index 21eb182d0b..75e74adcda 100644 --- a/api/src/org/apache/cloudstack/api/command/user/vpn/ResetVpnConnectionCmd.java +++ b/api/src/org/apache/cloudstack/api/command/user/vpn/ResetVpnConnectionCmd.java @@ -18,7 +18,6 @@ import org.apache.log4j.Logger; -import org.apache.cloudstack.acl.IAMEntityType; import org.apache.cloudstack.api.APICommand; import org.apache.cloudstack.api.ApiConstants; import org.apache.cloudstack.api.ApiErrorCode; @@ -34,7 +33,7 @@ import com.cloud.network.Site2SiteVpnConnection; import com.cloud.user.Account; -@APICommand(name = "resetVpnConnection", description = "Reset site to site vpn connection", responseObject = Site2SiteVpnConnectionResponse.class, entityType = {IAMEntityType.Site2SiteVpnConnection}, +@APICommand(name = "resetVpnConnection", description = "Reset site to site vpn connection", responseObject = Site2SiteVpnConnectionResponse.class, entityType = {Site2SiteVpnConnection.class}, requestHasSensitiveInfo = false, responseHasSensitiveInfo = false) public class ResetVpnConnectionCmd extends BaseAsyncCmd { public static final Logger s_logger = Logger.getLogger(ResetVpnConnectionCmd.class.getName()); diff --git a/api/src/org/apache/cloudstack/api/command/user/vpn/UpdateVpnCustomerGatewayCmd.java b/api/src/org/apache/cloudstack/api/command/user/vpn/UpdateVpnCustomerGatewayCmd.java index 9e178efc0e..ceb67d510a 100644 --- a/api/src/org/apache/cloudstack/api/command/user/vpn/UpdateVpnCustomerGatewayCmd.java +++ b/api/src/org/apache/cloudstack/api/command/user/vpn/UpdateVpnCustomerGatewayCmd.java @@ -18,7 +18,6 @@ import org.apache.log4j.Logger; -import org.apache.cloudstack.acl.IAMEntityType; import org.apache.cloudstack.api.APICommand; import org.apache.cloudstack.api.ApiConstants; import org.apache.cloudstack.api.ApiErrorCode; @@ -32,7 +31,7 @@ import com.cloud.event.EventTypes; import com.cloud.network.Site2SiteCustomerGateway; -@APICommand(name = "updateVpnCustomerGateway", description = "Update site to site vpn customer gateway", responseObject = Site2SiteCustomerGatewayResponse.class, entityType = {IAMEntityType.Site2SiteCustomerGateway}, +@APICommand(name = "updateVpnCustomerGateway", description = "Update site to site vpn customer gateway", responseObject = Site2SiteCustomerGatewayResponse.class, entityType = {Site2SiteCustomerGateway.class}, requestHasSensitiveInfo = false, responseHasSensitiveInfo = false) public class UpdateVpnCustomerGatewayCmd extends BaseAsyncCmd { public static final Logger s_logger = Logger.getLogger(UpdateVpnCustomerGatewayCmd.class.getName()); diff --git a/api/src/org/apache/cloudstack/api/response/AccountResponse.java b/api/src/org/apache/cloudstack/api/response/AccountResponse.java index 991b162ac1..2e50c51858 100644 --- a/api/src/org/apache/cloudstack/api/response/AccountResponse.java +++ b/api/src/org/apache/cloudstack/api/response/AccountResponse.java @@ -240,7 +240,7 @@ public class AccountResponse extends BaseResponse implements ResourceLimitAndCou private Boolean isDefault; @SerializedName(ApiConstants.IAM_GROUPS) - @Param(description = "the list of acl groups that account belongs to") + @Param(description = "the list of acl groups that account belongs to", since = "4.4") private List groups; @Override diff --git a/api/src/org/apache/cloudstack/api/response/CapabilitiesResponse.java b/api/src/org/apache/cloudstack/api/response/CapabilitiesResponse.java index c8de587336..f7fdb95fb6 100644 --- a/api/src/org/apache/cloudstack/api/response/CapabilitiesResponse.java +++ b/api/src/org/apache/cloudstack/api/response/CapabilitiesResponse.java @@ -49,6 +49,10 @@ public class CapabilitiesResponse extends BaseResponse { @Param(description = "true if regular user is allowed to create projects") private Boolean allowUsersCreateProjects; + @SerializedName(ApiConstants.CUSTOM_DISK_OFF_MIN_SIZE) + @Param(description = "minimum size that can be specified when " + "create disk from disk offering with custom size") + private Long diskOffMinSize; + @SerializedName(ApiConstants.CUSTOM_DISK_OFF_MAX_SIZE) @Param(description = "maximum size that can be specified when " + "create disk from disk offering with custom size") private Long diskOffMaxSize; @@ -93,6 +97,10 @@ public void setAllowUsersCreateProjects(Boolean allowUsersCreateProjects) { this.allowUsersCreateProjects = allowUsersCreateProjects; } + public void setDiskOffMinSize(Long diskOffMinSize) { + this.diskOffMinSize = diskOffMinSize; + } + public void setDiskOffMaxSize(Long diskOffMaxSize) { this.diskOffMaxSize = diskOffMaxSize; } diff --git a/api/src/org/apache/cloudstack/api/response/DiskOfferingResponse.java b/api/src/org/apache/cloudstack/api/response/DiskOfferingResponse.java index 0894eeced3..91bd441353 100644 --- a/api/src/org/apache/cloudstack/api/response/DiskOfferingResponse.java +++ b/api/src/org/apache/cloudstack/api/response/DiskOfferingResponse.java @@ -74,7 +74,7 @@ public class DiskOfferingResponse extends BaseResponse { private Long maxIops; @SerializedName(ApiConstants.HYPERVISOR_SNAPSHOT_RESERVE) - @Param(description = "Hypervisor snapshot reserve space as a percent of a volume (for managed storage using Xen or VMware)") + @Param(description = "Hypervisor snapshot reserve space as a percent of a volume (for managed storage using Xen or VMware)", since = "4.4") private Integer hypervisorSnapshotReserve; @SerializedName(ApiConstants.TAGS) @@ -102,7 +102,7 @@ public class DiskOfferingResponse extends BaseResponse { private Long iopsWriteRate; @SerializedName("cacheMode") - @Param(description = "the cache mode to use for this disk offering. none, writeback or writethrough") + @Param(description = "the cache mode to use for this disk offering. none, writeback or writethrough", since = "4.4") private String cacheMode; @SerializedName("displayoffering") diff --git a/api/src/org/apache/cloudstack/api/response/GetVMPasswordResponse.java b/api/src/org/apache/cloudstack/api/response/GetVMPasswordResponse.java index c72031b822..7a4543d437 100644 --- a/api/src/org/apache/cloudstack/api/response/GetVMPasswordResponse.java +++ b/api/src/org/apache/cloudstack/api/response/GetVMPasswordResponse.java @@ -25,7 +25,7 @@ public class GetVMPasswordResponse extends BaseResponse { @SerializedName("encryptedpassword") - @Param(description = "The encrypted password of the VM") + @Param(description = "The base64 encoded encrypted password of the VM") private String encryptedPassword; public GetVMPasswordResponse() { diff --git a/api/src/org/apache/cloudstack/api/response/GuestOSResponse.java b/api/src/org/apache/cloudstack/api/response/GuestOSResponse.java index 9737d6073a..6822288a86 100644 --- a/api/src/org/apache/cloudstack/api/response/GuestOSResponse.java +++ b/api/src/org/apache/cloudstack/api/response/GuestOSResponse.java @@ -39,6 +39,10 @@ public class GuestOSResponse extends BaseResponse { @Param(description = "the name/description of the OS type") private String description; + @SerializedName(ApiConstants.IS_USER_DEFINED) + @Param(description = "is the guest OS user defined") + private String isUserDefined; + public String getId() { return id; } @@ -62,4 +66,13 @@ public String getDescription() { public void setDescription(String description) { this.description = description; } + + public String getIsUserDefined() { + return isUserDefined; + } + + public void setIsUserDefined(String isUserDefined) { + this.isUserDefined = isUserDefined; + } + } diff --git a/api/src/org/apache/cloudstack/api/response/GuestOsMappingResponse.java b/api/src/org/apache/cloudstack/api/response/GuestOsMappingResponse.java index a0f7d1d0ed..583768d47b 100644 --- a/api/src/org/apache/cloudstack/api/response/GuestOsMappingResponse.java +++ b/api/src/org/apache/cloudstack/api/response/GuestOsMappingResponse.java @@ -52,6 +52,18 @@ public class GuestOsMappingResponse extends BaseResponse { @Param(description = "hypervisor specific name for the Guest OS") private String osNameForHypervisor; + @SerializedName(ApiConstants.IS_USER_DEFINED) + @Param(description = "is the mapping user defined") + private String isUserDefined; + + public String getIsUserDefined() { + return isUserDefined; + } + + public void setIsUserDefined(String isUserDefined) { + this.isUserDefined = isUserDefined; + } + public String getId() { return id; } diff --git a/api/src/org/apache/cloudstack/api/response/HostResponse.java b/api/src/org/apache/cloudstack/api/response/HostResponse.java index 1fbc6684e1..d7638dee0f 100644 --- a/api/src/org/apache/cloudstack/api/response/HostResponse.java +++ b/api/src/org/apache/cloudstack/api/response/HostResponse.java @@ -137,7 +137,7 @@ public class HostResponse extends BaseResponse { private Long memoryUsed; @SerializedName(ApiConstants.GPUGROUP) - @Param(description = "GPU cards present in the host", responseObject = GpuResponse.class) + @Param(description = "GPU cards present in the host", responseObject = GpuResponse.class, since = "4.4") private List gpuGroup; @SerializedName("disksizetotal") @@ -328,6 +328,7 @@ public void setMemoryUsed(Long memoryUsed) { public void setGpuGroups(List gpuGroup) { this.gpuGroup = gpuGroup; } + public void setDiskSizeTotal(Long diskSizeTotal) { this.diskSizeTotal = diskSizeTotal; } diff --git a/api/src/org/apache/cloudstack/api/response/LBHealthCheckPolicyResponse.java b/api/src/org/apache/cloudstack/api/response/LBHealthCheckPolicyResponse.java index 406a8dab0d..8ce7b3d219 100644 --- a/api/src/org/apache/cloudstack/api/response/LBHealthCheckPolicyResponse.java +++ b/api/src/org/apache/cloudstack/api/response/LBHealthCheckPolicyResponse.java @@ -16,12 +16,13 @@ // under the License. package org.apache.cloudstack.api.response; -import com.google.gson.annotations.SerializedName; - +import org.apache.cloudstack.acl.RoleType; +import org.apache.cloudstack.api.ApiConstants; import org.apache.cloudstack.api.BaseResponse; import com.cloud.network.rules.HealthCheckPolicy; import com.cloud.serializer.Param; +import com.google.gson.annotations.SerializedName; public class LBHealthCheckPolicyResponse extends BaseResponse { @SerializedName("id") @@ -56,6 +57,10 @@ public class LBHealthCheckPolicyResponse extends BaseResponse { @Param(description = "Number of consecutive health check failures before declaring an instance unhealthy.") private int unhealthcheckthresshold; + @SerializedName(ApiConstants.FOR_DISPLAY) + @Param(description = "is policy for display to the regular user", since = "4.4", authorized = {RoleType.Admin}) + private Boolean forDisplay; + public void setId(String id) { this.id = id; } @@ -95,6 +100,11 @@ public LBHealthCheckPolicyResponse(HealthCheckPolicy healthcheckpolicy) { this.responseTime = healthcheckpolicy.getResponseTime(); this.healthcheckthresshold = healthcheckpolicy.getHealthcheckThresshold(); this.unhealthcheckthresshold = healthcheckpolicy.getUnhealthThresshold(); + this.forDisplay = healthcheckpolicy.isDisplay(); setObjectName("healthcheckpolicy"); } + + public void setForDisplay(Boolean forDisplay) { + this.forDisplay = forDisplay; + } } diff --git a/api/src/org/apache/cloudstack/api/response/LBStickinessPolicyResponse.java b/api/src/org/apache/cloudstack/api/response/LBStickinessPolicyResponse.java index 76c54cd4cd..8fa884982b 100644 --- a/api/src/org/apache/cloudstack/api/response/LBStickinessPolicyResponse.java +++ b/api/src/org/apache/cloudstack/api/response/LBStickinessPolicyResponse.java @@ -22,6 +22,8 @@ import com.google.gson.annotations.SerializedName; +import org.apache.cloudstack.acl.RoleType; +import org.apache.cloudstack.api.ApiConstants; import org.apache.cloudstack.api.BaseResponse; import com.cloud.network.rules.StickinessPolicy; @@ -49,6 +51,10 @@ public class LBStickinessPolicyResponse extends BaseResponse { @Param(description = "the state of the policy") private String state; + @SerializedName(ApiConstants.FOR_DISPLAY) + @Param(description = "is policy for display to the regular user", since = "4.4", authorized = {RoleType.Admin}) + private Boolean forDisplay; + // FIXME : if prams with the same name exists more then once then value are concatinated with ":" as delimitor . // Reason: Map does not support duplicate keys, need to look for the alernate data structure // Example: {indirect=null, name=testcookie, nocache=null, domain=www.yahoo.com:www.google.com, postonly=null} @@ -98,6 +104,7 @@ public LBStickinessPolicyResponse(StickinessPolicy stickinesspolicy) { List> paramsList = stickinesspolicy.getParams(); this.methodName = stickinesspolicy.getMethodName(); this.description = stickinesspolicy.getDescription(); + this.forDisplay = stickinesspolicy.isDisplay(); if (stickinesspolicy.isRevoke()) { this.setState("Revoked"); } @@ -126,4 +133,8 @@ public LBStickinessPolicyResponse(StickinessPolicy stickinesspolicy) { this.params = tempParamList; setObjectName("stickinesspolicy"); } + + public void setForDisplay(Boolean forDisplay) { + this.forDisplay = forDisplay; + } } diff --git a/api/src/org/apache/cloudstack/api/response/LoadBalancerRuleVmMapResponse.java b/api/src/org/apache/cloudstack/api/response/LoadBalancerRuleVmMapResponse.java new file mode 100644 index 0000000000..57c45e6432 --- /dev/null +++ b/api/src/org/apache/cloudstack/api/response/LoadBalancerRuleVmMapResponse.java @@ -0,0 +1,54 @@ +// 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 com.cloud.network.router.VirtualRouter; +import com.cloud.uservm.UserVm; +import com.cloud.vm.VirtualMachine; +import com.google.gson.annotations.SerializedName; + +import org.apache.cloudstack.api.BaseResponse; +import org.apache.cloudstack.api.EntityReference; + +import com.cloud.serializer.Param; + +import java.util.List; + +@EntityReference(value = {VirtualMachine.class, UserVm.class, VirtualRouter.class}) +@SuppressWarnings("unused") +public class LoadBalancerRuleVmMapResponse extends BaseResponse { + + + @SerializedName("loadbalancerruleinstance") + @Param(description = "the user vm set for lb rule") + private UserVmResponse UserVmResponse; + + @SerializedName("lbvmipaddresses") + @Param(description = "IP addresses of the vm set of lb rule") + private List ipAddr; + + public void setIpAddr(List ipAddr) { + this.ipAddr = ipAddr; + } + + public void setUserVmResponse(UserVmResponse userVmResponse) { + this.UserVmResponse = userVmResponse; + } + + + +} diff --git a/api/src/org/apache/cloudstack/api/response/NetworkOfferingResponse.java b/api/src/org/apache/cloudstack/api/response/NetworkOfferingResponse.java index 8219147726..775c9a8fdd 100644 --- a/api/src/org/apache/cloudstack/api/response/NetworkOfferingResponse.java +++ b/api/src/org/apache/cloudstack/api/response/NetworkOfferingResponse.java @@ -109,13 +109,17 @@ public class NetworkOfferingResponse extends BaseResponse { private Map details; @SerializedName(ApiConstants.EGRESS_DEFAULT_POLICY) - @Param(description = "true if network offering supports persistent networks, false otherwise") + @Param(description = "true if guest network default egress policy is allow; false if default egress policy is deny") private Boolean egressDefaultPolicy; @SerializedName(ApiConstants.MAX_CONNECTIONS) @Param(description = "maximum number of concurrents connections to be handled by lb") private Integer concurrentConnections; + @SerializedName(ApiConstants.SUPPORTS_STRECHED_L2_SUBNET) + @Param(description = "true if network offering supports network that span multiple zones", since = "4.4") + private Boolean supportsStrechedL2Subnet; + public void setId(String id) { this.id = id; } @@ -200,4 +204,7 @@ public void setConcurrentConnections(Integer concurrentConnections) { this.concurrentConnections = concurrentConnections; } + public void setSupportsStrechedL2Subnet(Boolean supportsStrechedL2Subnet) { + this.supportsStrechedL2Subnet = supportsStrechedL2Subnet; + } } diff --git a/api/src/org/apache/cloudstack/api/response/NetworkResponse.java b/api/src/org/apache/cloudstack/api/response/NetworkResponse.java index bf92aa4f78..40c90729cd 100644 --- a/api/src/org/apache/cloudstack/api/response/NetworkResponse.java +++ b/api/src/org/apache/cloudstack/api/response/NetworkResponse.java @@ -18,6 +18,7 @@ import java.util.List; +import java.util.Set; import org.apache.cloudstack.acl.RoleType; import org.apache.cloudstack.api.ApiConstants; import org.apache.cloudstack.api.BaseResponse; @@ -216,6 +217,14 @@ public class NetworkResponse extends BaseResponse implements ControlledEntityRes @Param(description = "ACL Id associated with the VPC network") private String aclId; + @SerializedName(ApiConstants.STRECHED_L2_SUBNET) + @Param(description = "true if network can span multiple zones", since = "4.4") + private Boolean strechedL2Subnet; + + @SerializedName(ApiConstants.NETWORK_SPANNED_ZONES) + @Param(description = "If a network is enabled for 'streched l2 subnet' then represents zones on which network currently spans", since = "4.4") + private Set networkSpannedZones; + public Boolean getDisplayNetwork() { return displayNetwork; } @@ -412,4 +421,12 @@ public String getAclId() { public void setAclId(String aclId) { this.aclId = aclId; } + + public void setStrechedL2Subnet(Boolean strechedL2Subnet) { + this.strechedL2Subnet = strechedL2Subnet; + } + + public void setNetworkSpannedZones(Set networkSpannedZones) { + this.networkSpannedZones = networkSpannedZones; + } } diff --git a/api/src/org/apache/cloudstack/api/response/ServiceOfferingResponse.java b/api/src/org/apache/cloudstack/api/response/ServiceOfferingResponse.java index d371f9a925..764ade510a 100644 --- a/api/src/org/apache/cloudstack/api/response/ServiceOfferingResponse.java +++ b/api/src/org/apache/cloudstack/api/response/ServiceOfferingResponse.java @@ -107,19 +107,19 @@ public class ServiceOfferingResponse extends BaseResponse { private Integer networkRate; @SerializedName("iscustomizediops") - @Param(description = "true if disk offering uses custom iops, false otherwise") + @Param(description = "true if disk offering uses custom iops, false otherwise", since = "4.4") private Boolean customizedIops; @SerializedName(ApiConstants.MIN_IOPS) - @Param(description = "the min iops of the disk offering") + @Param(description = "the min iops of the disk offering", since = "4.4") private Long minIops; @SerializedName(ApiConstants.MAX_IOPS) - @Param(description = "the max iops of the disk offering") + @Param(description = "the max iops of the disk offering", since = "4.4") private Long maxIops; @SerializedName(ApiConstants.HYPERVISOR_SNAPSHOT_RESERVE) - @Param(description = "Hypervisor snapshot reserve space as a percent of a volume (for managed storage using Xen or VMware)") + @Param(description = "Hypervisor snapshot reserve space as a percent of a volume (for managed storage using Xen or VMware)", since = "4.4") private Integer hypervisorSnapshotReserve; @SerializedName("diskBytesReadRate") diff --git a/api/src/org/apache/cloudstack/api/response/StoragePoolResponse.java b/api/src/org/apache/cloudstack/api/response/StoragePoolResponse.java index 98c90e2fd3..3571866fe7 100644 --- a/api/src/org/apache/cloudstack/api/response/StoragePoolResponse.java +++ b/api/src/org/apache/cloudstack/api/response/StoragePoolResponse.java @@ -108,8 +108,8 @@ public class StoragePoolResponse extends BaseResponse { private String scope; @SerializedName("overprovisionfactor") - @Param(description = "the overprovisionfactor for the storage pool") - private String overprovisionfactor; + @Param(description = "the overprovisionfactor for the storage pool", since = "4.4") + private String overProvisionFactor; @SerializedName(ApiConstants.HYPERVISOR) @Param(description = "the hypervisor type of the storage pool") @@ -307,6 +307,6 @@ public void setSuitableForMigration(Boolean suitableForMigration) { } public void setOverProvisionFactor(String overProvisionFactor) { - this.overprovisionfactor = overProvisionFactor; + this.overProvisionFactor = overProvisionFactor; } } diff --git a/api/src/org/apache/cloudstack/api/response/UserVmResponse.java b/api/src/org/apache/cloudstack/api/response/UserVmResponse.java index d6ce84f495..9fe3475f57 100644 --- a/api/src/org/apache/cloudstack/api/response/UserVmResponse.java +++ b/api/src/org/apache/cloudstack/api/response/UserVmResponse.java @@ -141,11 +141,11 @@ public class UserVmResponse extends BaseResponse implements ControlledEntityResp private String serviceOfferingName; @SerializedName(ApiConstants.DISK_OFFERING_ID) - @Param(description = "the ID of the disk offering of the virtual machine") + @Param(description = "the ID of the disk offering of the virtual machine", since = "4.4") private String diskOfferingId; @SerializedName("diskofferingname") - @Param(description = "the name of the disk offering of the virtual machine") + @Param(description = "the name of the disk offering of the virtual machine", since = "4.4") private String diskOfferingName; @SerializedName("forvirtualnetwork") @@ -165,7 +165,7 @@ public class UserVmResponse extends BaseResponse implements ControlledEntityResp private Integer memory; @SerializedName(ApiConstants.VGPU) - @Param(description = "the vgpu type used by the virtual machine") + @Param(description = "the vgpu type used by the virtual machine", since = "4.4") private String vgpu; @SerializedName("cpuused") diff --git a/api/src/org/apache/cloudstack/api/response/VgpuResponse.java b/api/src/org/apache/cloudstack/api/response/VgpuResponse.java index 17e194be5b..c51dc8d0f6 100644 --- a/api/src/org/apache/cloudstack/api/response/VgpuResponse.java +++ b/api/src/org/apache/cloudstack/api/response/VgpuResponse.java @@ -29,24 +29,63 @@ public class VgpuResponse extends BaseResponse { @Param(description = "Model Name of vGPU") private String name; + @SerializedName(ApiConstants.VIDEORAM) + @Param(description = "Video RAM for this vGPU type") + private Long videoRam; + + @SerializedName(ApiConstants.MAXHEADS) + @Param(description = "Maximum displays per user") + private Long maxHeads; + + @SerializedName(ApiConstants.MAXRESOLUTIONX) + @Param(description = "Maximum X resolution per display") + private Long maxResolutionX; + + @SerializedName(ApiConstants.MAXRESOLUTIONY) + @Param(description = "Maximum Y resolution per display") + private Long maxResolutionY; + + @SerializedName(ApiConstants.MAXVGPUPERPGPU) + @Param(description = "Maximum no. of vgpu per gpu card (pgpu)") + private Long maxVgpuPerPgpu; + @SerializedName(ApiConstants.REMAININGCAPACITY) - @Param(description = "No. of more VMs can be deployped with this vGPU type") - private Long capacity; + @Param(description = "Remaining capacity in terms of no. of more VMs that can be deployped with this vGPU type") + private Long remainingCapacity; - public String getName() { - return name; - } + @SerializedName(ApiConstants.MAXCAPACITY) + @Param(description = "Maximum vgpu can be created with this vgpu type on the given gpu group") + private Long maxCapacity; public void setName(String name) { this.name = name; } - public Long getCapacity() { - return capacity; + public void setVideoRam(Long videoRam) { + this.videoRam = videoRam; + } + + public void setMaxHeads(Long maxHeads) { + this.maxHeads = maxHeads; } - public void setCapacity(Long capacity) { - this.capacity = capacity; + public void setMaxResolutionX(Long maxResolutionX) { + this.maxResolutionX = maxResolutionX; } + public void setMaxResolutionY(Long maxResolutionY) { + this.maxResolutionY = maxResolutionY; + } + + public void setMaxVgpuPerPgpu(Long maxVgpuPerPgpu) { + this.maxVgpuPerPgpu = maxVgpuPerPgpu; + } + + public void setRemainingCapacity(Long remainingCapacity) { + this.remainingCapacity = remainingCapacity; + } + + public void setmaxCapacity(Long maxCapacity) { + this.maxCapacity = maxCapacity; + } } diff --git a/api/src/org/apache/cloudstack/api/response/VolumeResponse.java b/api/src/org/apache/cloudstack/api/response/VolumeResponse.java index 27e95def02..c3e214fb10 100644 --- a/api/src/org/apache/cloudstack/api/response/VolumeResponse.java +++ b/api/src/org/apache/cloudstack/api/response/VolumeResponse.java @@ -60,6 +60,30 @@ public class VolumeResponse extends BaseResponse implements ControlledViewEntity @Param(description = "id of the virtual machine") private String virtualMachineId; + @SerializedName("isoid") + @Param(description = "the ID of the ISO attached to the virtual machine") + private String isoId; + + @SerializedName("isoname") + @Param(description = "the name of the ISO attached to the virtual machine") + private String isoName; + + @SerializedName("isodisplaytext") + @Param(description = "an alternate display text of the ISO attached to the virtual machine") + private String isoDisplayText; + + @SerializedName(ApiConstants.TEMPLATE_ID) + @Param(description = "the ID of the template for the virtual machine. A -1 is returned if the virtual machine was created from an ISO file.") + private String templateId; + + @SerializedName("templatename") + @Param(description = "the name of the template for the virtual machine") + private String templateName; + + @SerializedName("templatedisplaytext") + @Param(description = " an alternate display text of the template for the virtual machine") + private String templateDisplayText; + @SerializedName("vmname") @Param(description = "name of the virtual machine") private String virtualMachineName; @@ -204,6 +228,11 @@ public class VolumeResponse extends BaseResponse implements ControlledViewEntity @Param(description = "the chain info of the volume", since = "4.4") String chainInfo; + @SerializedName(ApiConstants.SNAPSHOT_QUIESCEVM) + @Param(description = "need quiesce vm or not when taking snapshot", since="4.3") + private boolean needQuiescevm; + + public String getPath() { return path; } @@ -425,4 +454,64 @@ public String getChainInfo() { public void setChainInfo(String chainInfo) { this.chainInfo = chainInfo; } + + public String getStoragePoolId() { + return storagePoolId; + } + + public void setNeedQuiescevm(boolean quiescevm) { + this.needQuiescevm = quiescevm; + } + + public boolean isNeedQuiescevm() { + return this.needQuiescevm; + } + + public String getIsoId() { + return isoId; + } + + public void setIsoId(String isoId) { + this.isoId = isoId; + } + + public String getIsoName() { + return isoName; + } + + public void setIsoName(String isoName) { + this.isoName = isoName; + } + + public String getIsoDisplayText() { + return isoDisplayText; + } + + public void setIsoDisplayText(String isoDisplayText) { + this.isoDisplayText = isoDisplayText; + } + + public String getTemplateId() { + return templateId; + } + + public void setTemplateId(String templateId) { + this.templateId = templateId; + } + + public String getTemplateName() { + return templateName; + } + + public void setTemplateName(String templateName) { + this.templateName = templateName; + } + + public String getTemplateDisplayText() { + return templateDisplayText; + } + + public void setTemplateDisplayText(String templateDisplayText) { + this.templateDisplayText = templateDisplayText; + } } diff --git a/api/src/org/apache/cloudstack/api/response/VpcOfferingResponse.java b/api/src/org/apache/cloudstack/api/response/VpcOfferingResponse.java index 89697f04ad..512746fb6a 100644 --- a/api/src/org/apache/cloudstack/api/response/VpcOfferingResponse.java +++ b/api/src/org/apache/cloudstack/api/response/VpcOfferingResponse.java @@ -60,9 +60,13 @@ public class VpcOfferingResponse extends BaseResponse { private List services; @SerializedName(ApiConstants.DISTRIBUTED_VPC_ROUTER) - @Param(description = " indicates if the vpc offering supports distributed router for one-hop forwarding") + @Param(description = " indicates if the vpc offering supports distributed router for one-hop forwarding", since = "4.4") private Boolean supportsDistributedRouter; + @SerializedName((ApiConstants.SUPPORTS_REGION_LEVEL_VPC)) + @Param(description = " indicated if the offering can support region level vpc", since = "4.4") + private Boolean supportsRegionLevelVpc; + public void setId(String id) { this.id = id; } @@ -94,4 +98,8 @@ public void setState(String state) { public void setSupportsDistributedRouter(Boolean supportsDistributedRouter) { this.supportsDistributedRouter = supportsDistributedRouter; } + + public void setSupportsRegionLevelVpc(Boolean supports) { + this.supportsRegionLevelVpc = supports; + } } diff --git a/api/src/org/apache/cloudstack/api/response/VpcResponse.java b/api/src/org/apache/cloudstack/api/response/VpcResponse.java index e3b44f2113..d1afdfb816 100644 --- a/api/src/org/apache/cloudstack/api/response/VpcResponse.java +++ b/api/src/org/apache/cloudstack/api/response/VpcResponse.java @@ -111,11 +111,14 @@ public class VpcResponse extends BaseResponse implements ControlledEntityRespons @Param(description = "is vpc for display to the regular user", since = "4.4", authorized = {RoleType.Admin}) private Boolean forDisplay; - @SerializedName(ApiConstants.DISTRIBUTED_VPC_ROUTER) - @Param(description = "is VPC uses distributed router for one hop forwarding and host based network ACL's") + @Param(description = "is VPC uses distributed router for one hop forwarding and host based network ACL's", since = "4.4") private boolean usesDistributedRouter; + @SerializedName((ApiConstants.REGION_LEVEL_VPC)) + @Param(description = "true if VPC is region level", since = "4.4") + private Boolean regionLevelVpc; + public void setId(String id) { this.id = id; } @@ -205,6 +208,10 @@ public void setForDisplay(Boolean forDisplay) { this.forDisplay = forDisplay; } + public void setRegionLevelVpc(Boolean regionLevelVpc) { + this.regionLevelVpc = regionLevelVpc; + } + public void setUsesDistributedRouter(Boolean usesDistributedRouter) { this.usesDistributedRouter = usesDistributedRouter; } diff --git a/api/src/org/apache/cloudstack/context/CallContext.java b/api/src/org/apache/cloudstack/context/CallContext.java index 661b01dd55..7305d14ba9 100644 --- a/api/src/org/apache/cloudstack/context/CallContext.java +++ b/api/src/org/apache/cloudstack/context/CallContext.java @@ -316,6 +316,17 @@ public void setEventDisplayEnabled(boolean eventDisplayEnabled) { isEventDisplayEnabled = eventDisplayEnabled; } + public Map getContextParameters() { + return context; + } + + public void putContextParameters(Map details){ + if (details == null) return; + for(Object key : details.keySet()){ + putContextParameter(key, details.get(key)); + } + } + public static void setActionEventInfo(String eventType, String description) { CallContext context = CallContext.current(); if (context != null) { diff --git a/awsapi/pom.xml b/awsapi/pom.xml index 601e6959a5..32ec2c4466 100644 --- a/awsapi/pom.xml +++ b/awsapi/pom.xml @@ -126,94 +126,6 @@ CAStorSDK 1.3.1-CS40 - - org.apache.rampart - rahas - ${cs.rampart.version} - mar - - - bouncycastle - bcprov-jdk14 - - - org.apache.xalan - xalan - - - org.opensaml - opensaml1 - - - - - org.apache.rampart - rampart - ${cs.rampart.version} - mar - - - bouncycastle - bcprov-jdk14 - - - org.apache.xalan - xalan - - - org.opensaml - opensaml1 - - - - - org.apache.rampart - rampart-core - ${cs.rampart.version} - runtime - - - org.apache.xalan - xalan - - - org.opensaml - opensaml1 - - - - - org.apache.rampart - rampart-policy - ${cs.rampart.version} - runtime - - - org.apache.xalan - xalan - - - org.opensaml - opensaml1 - - - - - org.apache.rampart - rampart-trust - ${cs.rampart.version} - runtime - - - org.apache.xalan - xalan - - - org.opensaml - opensaml1 - - - org.slf4j slf4j-jdk14 diff --git a/client/WEB-INF/classes/resources/messages.properties b/client/WEB-INF/classes/resources/messages.properties index c46361a12e..94b5d7ce55 100644 --- a/client/WEB-INF/classes/resources/messages.properties +++ b/client/WEB-INF/classes/resources/messages.properties @@ -14,6 +14,12 @@ # KIND, either express or implied. See the License for the # specific language governing permissions and limitations # under the License. +message.listView.subselect.multi=(Ctrl/Cmd-click) +label.use.vm.ips=Use VM IPs +label.reinstall.vm=Reinstall VM +message.reinstall.vm=NOTE: Proceed with caution. This will cause the VM to be reinstalled from the template; data on the root disk will be lost. Extra data volumes, if any, will not be touched. +label.recover.vm=Recover VM +message.recover.vm=Please confirm that you would like to recover this VM. label.port=Port label.remove.ldap=Remove LDAP label.configure.ldap=Configure LDAP @@ -1277,6 +1283,18 @@ label.assign.instance.another=Assign Instance to Another Account label.network.addVM=Add network to VM label.set.default.NIC=Set default NIC label.Xenserver.Tools.Version61plus=XenServer Tools Version 6.1\+ +label.supportsstrechedl2subnet=Supports Streched L2 Subnet +label.menu.vpc.offerings=VPC Offerings +label.vpc.offering=VPC Offering +label.regionlevelvpc=Region Level VPC +label.add.vpc.offering=Add VPC Offering +label.distributedrouter=DistributedRouter +label.vpc.offering.details=VPC offering details +label.disable.vpc.offering=Disable VPC offering +label.enable.vpc.offering=Enable VPC offering +label.remove.vpc.offering=Remove VPC offering +label.vpc.distributedvpcrouter=Distributed VPC Router +label.vpc.supportsregionlevelvpc=Supports Region Level VPC label.dynamically.scalable=Dynamically Scalable label.instance.scaled.up=Instance Scaled Up label.tag.key=Tag Key @@ -1481,6 +1499,12 @@ label.allow=Allow label.deny=Deny label.default.egress.policy=Default egress policy label.xenserver.tools.version.61.plus=XenServer Tools Version 6.1\+ +label.gpu=GPU +label.vgpu.type=vGPU type +label.vgpu.video.ram=Video RAM +label.vgpu.max.resolution=Max resolution +label.vgpu.max.vgpu.per.gpu=vGPUs per GPU +label.vgpu.remaining.capacity=Remaining capacity managed.state=Managed State message.acquire.new.ip.vpc=Please confirm that you would like to acquire a new IP for this VPC. message.acquire.new.ip=Please confirm that you would like to acquire a new IP for this network. @@ -1780,7 +1804,7 @@ message.tooltip.reserved.system.netmask=The network prefix that defines the pod message.tooltip.zone.name=A name for the zone. message.update.os.preference=Please choose a OS preference for this host. All virtual instances with similar preferences will be first allocated to this host before choosing another. message.update.resource.count=Please confirm that you want to update resource counts for this account. -message.update.ssl=Please submit a new X.509 compliant SSL certificate to be updated to each console proxy virtual instance\: +message.update.ssl=Please submit a new X.509 compliant SSL certificate to be updated to each console proxy and secondary storage virtual instance\: message.validate.instance.name=Instance name can not be longer than 63 characters. Only ASCII letters a~z, A~Z, digits 0~9, hyphen are allowed. Must start with a letter and end with a letter or a digit. message.virtual.network.desc=A dedicated virtualized network for your account. The broadcast domain is contained within a VLAN and all public network access is routed out by a virtual router. message.vm.create.template.confirm=Create Template will reboot the VM automatically. @@ -1793,7 +1817,7 @@ message.zone.no.network.selection=The zone you selected does not have any choice message.zone.step.1.desc=Please select a network model for your zone. message.zone.step.2.desc=Please enter the following info to add a new zone message.zone.step.3.desc=Please enter the following info to add a new pod -message.zoneWizard.enable.local.storage=WARNING\: If you enable local storage for this zone, you must do the following, depending on where you would like your system VMs to launch\:

1. If system VMs need to be launched in primary storage, primary storage needs to be added to the zone after creation. You must also start the zone in a disabled state.

2. If system VMs need to be launched in local storage, system.vm.use.local.storage needs to be set to true before you enable the zone.


Would you like to continue? +message.zoneWizard.enable.local.storage=WARNING\: If you enable local storage for this zone, you must do the following, depending on where you would like your system VMs to launch\:

1. If system VMs need to be launched in shared primary storage, shared primary storage needs to be added to the zone after creation. You must also start the zone in a disabled state.

2. If system VMs need to be launched in local primary storage, system.vm.use.local.storage needs to be set to true before you enable the zone.


Would you like to continue? message.validate.fieldrequired=This field is required. message.validate.fixfield=Please fix this field. message.validate.email.address=Please enter a valid email address. @@ -1878,6 +1902,11 @@ message.confirm.enable.network.offering=Are you sure you want to enable this net message.enabling.network.offering=Enabling network offering message.confirm.remove.network.offering=Are you sure you want to remove this network offering? message.confirm.disable.network.offering=Are you sure you want to disable this network offering? +message.disabling.vpc.offering=Disabling VPC offering +message.confirm.enable.vpc.offering=Are you sure you want to enable this VPC offering? +message.enabling.vpc.offering=Enabling VPC offering +message.confirm.remove.vpc.offering=Are you sure you want to remove this VPC offering? +message.confirm.disable.vpc.offering=Are you sure you want to disable this VPC offering? mode=Mode network.rate=Network Rate notification.reboot.instance=Reboot instance diff --git a/client/pom.xml b/client/pom.xml index 74c459e769..eda8a8560f 100644 --- a/client/pom.xml +++ b/client/pom.xml @@ -35,6 +35,11 @@ cloud-plugin-storage-volume-solidfire ${project.version}
+ + org.apache.cloudstack + cloud-plugin-storage-volume-cloudbyte + ${project.version} + org.apache.cloudstack cloud-server diff --git a/client/tomcatconf/commands.properties.in b/client/tomcatconf/commands.properties.in index 45debe41a9..da3fbfc00d 100644 --- a/client/tomcatconf/commands.properties.in +++ b/client/tomcatconf/commands.properties.in @@ -146,7 +146,7 @@ listDedicatedGuestVlanRanges=1 associateIpAddress=15 disassociateIpAddress=15 listPublicIpAddresses=15 -updatePublicIpAddress=15 +updateIpAddress=15 #### firewall commands listPortForwardingRules=15 @@ -167,11 +167,13 @@ deleteLoadBalancerRule=15 removeFromLoadBalancerRule=15 assignToLoadBalancerRule=15 createLBStickinessPolicy=15 +updateLBStickinessPolicy=15 deleteLBStickinessPolicy=15 listLoadBalancerRules=15 listLBStickinessPolicies=15 listLBHealthCheckPolicies=15 createLBHealthCheckPolicy=15 +updateLBHealthCheckPolicy=15 deleteLBHealthCheckPolicy=15 listLoadBalancerRuleInstances=15 updateLoadBalancerRule=15 @@ -618,6 +620,8 @@ deleteStratoshereSsp=1 #### host simulator commands configureSimulator=1 +querySimulatorMock=1 +cleanupSimulatorMock=1 #### api discovery commands diff --git a/core/src/com/cloud/agent/api/GetGPUStatsAnswer.java b/core/src/com/cloud/agent/api/GetGPUStatsAnswer.java index 566eed5ab6..583326b839 100644 --- a/core/src/com/cloud/agent/api/GetGPUStatsAnswer.java +++ b/core/src/com/cloud/agent/api/GetGPUStatsAnswer.java @@ -23,14 +23,14 @@ @LogLevel(Log4jLevel.Trace) public class GetGPUStatsAnswer extends Answer { - private HashMap> groupDetails; + private HashMap> groupDetails; - public GetGPUStatsAnswer(GetGPUStatsCommand cmd, HashMap> groupDetails) { + public GetGPUStatsAnswer(GetGPUStatsCommand cmd, HashMap> groupDetails) { super(cmd); this.groupDetails = groupDetails; } - public HashMap> getGroupDetails() { + public HashMap> getGroupDetails() { return this.groupDetails; } } diff --git a/core/src/com/cloud/agent/api/GetRouterAlertsAnswer.java b/core/src/com/cloud/agent/api/GetRouterAlertsAnswer.java index 06a7a7a84e..31485396f4 100644 --- a/core/src/com/cloud/agent/api/GetRouterAlertsAnswer.java +++ b/core/src/com/cloud/agent/api/GetRouterAlertsAnswer.java @@ -22,7 +22,6 @@ public class GetRouterAlertsAnswer extends Answer { - String routerName; String[] alerts; String timeStamp; @@ -36,8 +35,8 @@ public GetRouterAlertsAnswer(GetRouterAlertsCommand cmd, String alerts[], String } - public GetRouterAlertsAnswer(GetRouterAlertsCommand cmd, Exception ex) { - super(cmd, ex); + public GetRouterAlertsAnswer(GetRouterAlertsCommand cmd, String details) { + super(cmd, false, details); } public void setAlerts(String[] alerts) { @@ -56,7 +55,4 @@ public String getTimeStamp() { return timeStamp; } - public String getRouterName() { - return routerName; - } } diff --git a/core/src/com/cloud/agent/api/GetVmConfigAnswer.java b/core/src/com/cloud/agent/api/GetVmConfigAnswer.java index 46e003ecae..e0d1536341 100644 --- a/core/src/com/cloud/agent/api/GetVmConfigAnswer.java +++ b/core/src/com/cloud/agent/api/GetVmConfigAnswer.java @@ -42,13 +42,15 @@ public List getNics() { public class NicDetails { String macAddress; int vlanid; + boolean state; public NicDetails() { } - public NicDetails(String macAddress, int vlanid) { + public NicDetails(String macAddress, int vlanid, boolean state) { this.macAddress = macAddress; this.vlanid = vlanid; + this.state = state; } public String getMacAddress() { @@ -59,6 +61,9 @@ public int getVlanid() { return vlanid; } + public boolean getState() { + return state; + } } @Override diff --git a/core/src/com/cloud/agent/api/ModifyVmNicConfigCommand.java b/core/src/com/cloud/agent/api/ModifyVmNicConfigCommand.java index 5f4f0e1d9a..54c0eb098b 100644 --- a/core/src/com/cloud/agent/api/ModifyVmNicConfigCommand.java +++ b/core/src/com/cloud/agent/api/ModifyVmNicConfigCommand.java @@ -22,6 +22,9 @@ public class ModifyVmNicConfigCommand extends Command { int vlan; String macAddress; int index; + boolean enable; + String switchLableName; + protected ModifyVmNicConfigCommand() { } @@ -37,10 +40,24 @@ public ModifyVmNicConfigCommand(String vmName, int vlan, int position) { this.index = position; } + public ModifyVmNicConfigCommand(String vmName, int vlan, int position, boolean enable) { + this.vmName = vmName; + this.vlan = vlan; + this.index = position; + this.enable = enable; + } + public String getVmName() { return vmName; } + public String getSwitchLableName() { + return switchLableName; + } + + public void setSwitchLableName(String switchlableName) { + this.switchLableName = switchlableName; + } @Override public boolean executeInSequence() { diff --git a/core/src/com/cloud/agent/api/PoolEjectCommand.java b/core/src/com/cloud/agent/api/PoolEjectCommand.java deleted file mode 100644 index fa6b651797..0000000000 --- a/core/src/com/cloud/agent/api/PoolEjectCommand.java +++ /dev/null @@ -1,44 +0,0 @@ -// Licensed to the Apache Software Foundation (ASF) under one -// or more contributor license agreements. See the NOTICE file -// distributed with this work for additional information -// regarding copyright ownership. The ASF licenses this file -// to you under the Apache License, Version 2.0 (the -// "License"); you may not use this file except in compliance -// with the License. You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, -// software distributed under the License is distributed on an -// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY -// KIND, either express or implied. See the License for the -// specific language governing permissions and limitations -// under the License. -package com.cloud.agent.api; - -public class PoolEjectCommand extends Command { - private String hostuuid; - - public String getHostuuid() { - return hostuuid; - } - - public void setHostuuid(String hostuuid) { - this.hostuuid = hostuuid; - } - - public PoolEjectCommand() { - super(); - } - - public PoolEjectCommand(String hostuuid) { - super(); - setHostuuid(hostuuid); - } - - @Override - public boolean executeInSequence() { - return true; - } - -} diff --git a/core/src/com/cloud/agent/api/StartupRoutingCommand.java b/core/src/com/cloud/agent/api/StartupRoutingCommand.java index dc37113386..52814eac9a 100755 --- a/core/src/com/cloud/agent/api/StartupRoutingCommand.java +++ b/core/src/com/cloud/agent/api/StartupRoutingCommand.java @@ -70,7 +70,7 @@ public String getHost() { HypervisorType hypervisorType; Map hostDetails; //stuff like host os, cpu capabilities String hypervisorVersion; - HashMap> groupDetails = new HashMap>(); + HashMap> groupDetails = new HashMap>(); public StartupRoutingCommand() { super(Host.Type.Routing); @@ -246,11 +246,11 @@ public void setHostVmStateReport(Map hostVmState this._hostVmStateReport = hostVmStateReport; } - public HashMap> getGpuGroupDetails() { + public HashMap> getGpuGroupDetails() { return groupDetails; } - public void setGpuGroupDetails(HashMap> groupDetails) { + public void setGpuGroupDetails(HashMap> groupDetails) { this.groupDetails = groupDetails; } } diff --git a/core/src/com/cloud/agent/api/StopCommand.java b/core/src/com/cloud/agent/api/StopCommand.java index 00d7f5fff6..61d13e0f8e 100755 --- a/core/src/com/cloud/agent/api/StopCommand.java +++ b/core/src/com/cloud/agent/api/StopCommand.java @@ -25,26 +25,30 @@ public class StopCommand extends RebootCommand { private String publicConsoleProxyIpAddress = null; boolean executeInSequence = false; private GPUDeviceTO gpuDevice; + boolean checkBeforeCleanup = false; protected StopCommand() { } - public StopCommand(VirtualMachine vm, boolean isProxy, String urlPort, String publicConsoleProxyIpAddress, boolean executeInSequence) { + public StopCommand(VirtualMachine vm, boolean isProxy, String urlPort, String publicConsoleProxyIpAddress, boolean executeInSequence, boolean checkBeforeCleanup) { super(vm); this.isProxy = isProxy; this.urlPort = urlPort; this.publicConsoleProxyIpAddress = publicConsoleProxyIpAddress; this.executeInSequence = executeInSequence; + this.checkBeforeCleanup = checkBeforeCleanup; } - public StopCommand(VirtualMachine vm, boolean executeInSequence) { + public StopCommand(VirtualMachine vm, boolean executeInSequence, boolean checkBeforeCleanup) { super(vm); this.executeInSequence = executeInSequence; + this.checkBeforeCleanup = checkBeforeCleanup; } - public StopCommand(String vmName, boolean executeInSequence) { + public StopCommand(String vmName, boolean executeInSequence, boolean checkBeforeCleanup) { super(vmName); this.executeInSequence = executeInSequence; + this.checkBeforeCleanup = checkBeforeCleanup; } @Override @@ -71,4 +75,8 @@ public GPUDeviceTO getGpuDevice() { public void setGpuDevice(GPUDeviceTO gpuDevice) { this.gpuDevice = gpuDevice; } + + public boolean checkBeforeCleanup() { + return this.checkBeforeCleanup; + } } diff --git a/core/src/com/cloud/agent/api/VMSnapshotBaseCommand.java b/core/src/com/cloud/agent/api/VMSnapshotBaseCommand.java index d2abd54e04..2752965311 100644 --- a/core/src/com/cloud/agent/api/VMSnapshotBaseCommand.java +++ b/core/src/com/cloud/agent/api/VMSnapshotBaseCommand.java @@ -26,10 +26,11 @@ public class VMSnapshotBaseCommand extends Command { protected VMSnapshotTO target; protected String vmName; protected String guestOSType; + protected String platformEmulator; public VMSnapshotBaseCommand(String vmName, VMSnapshotTO snapshot, List volumeTOs, String guestOSType) { this.vmName = vmName; - this.target = snapshot; + target = snapshot; this.volumeTOs = volumeTOs; this.guestOSType = guestOSType; } @@ -70,4 +71,12 @@ public String getGuestOSType() { public void setGuestOSType(String guestOSType) { this.guestOSType = guestOSType; } + + public String getPlatformEmulator() { + return platformEmulator; + } + + public void setPlatformEmulator(String platformEmulator) { + this.platformEmulator = platformEmulator; + } } diff --git a/core/src/com/cloud/agent/resource/virtualnetwork/VirtualRouterDeployer.java b/core/src/com/cloud/agent/resource/virtualnetwork/VirtualRouterDeployer.java index 243098abea..1feaaead9f 100644 --- a/core/src/com/cloud/agent/resource/virtualnetwork/VirtualRouterDeployer.java +++ b/core/src/com/cloud/agent/resource/virtualnetwork/VirtualRouterDeployer.java @@ -21,6 +21,8 @@ public interface VirtualRouterDeployer { ExecutionResult executeInVR(String routerIp, String script, String args); + /* timeout in seconds */ + ExecutionResult executeInVR(String routerIp, String script, String args, int timeout); ExecutionResult createFileInVR(String routerIp, String path, String filename, String content); ExecutionResult prepareCommand(NetworkElementCommand cmd); ExecutionResult cleanupCommand(NetworkElementCommand cmd); diff --git a/core/src/com/cloud/agent/resource/virtualnetwork/VirtualRoutingResource.java b/core/src/com/cloud/agent/resource/virtualnetwork/VirtualRoutingResource.java index e13fbf651c..7bb6f5ea6c 100755 --- a/core/src/com/cloud/agent/resource/virtualnetwork/VirtualRoutingResource.java +++ b/core/src/com/cloud/agent/resource/virtualnetwork/VirtualRoutingResource.java @@ -134,6 +134,7 @@ protected class VRScripts { private int _sleep; private int _retry; private int _port; + private int _eachTimeout; private String _cfgVersion = "1.0"; @@ -649,25 +650,23 @@ private CheckS2SVpnConnectionsAnswer execute(CheckS2SVpnConnectionsCommand cmd) private GetRouterAlertsAnswer execute(GetRouterAlertsCommand cmd) { - String args = null; String routerIp = cmd.getAccessDetail(NetworkElementCommand.ROUTER_IP); - if (cmd.getPreviousAlertTimeStamp() != null) { - args = cmd.getPreviousAlertTimeStamp(); - } + String args = cmd.getPreviousAlertTimeStamp(); ExecutionResult result = _vrDeployer.executeInVR(routerIp, VRScripts.ROUTER_ALERTS, args); String alerts[] = null; String lastAlertTimestamp = null; - // CallHostPlugin results "success" when there are no alerts on virtual router + if (result.isSuccess()) { - if (!result.getDetails().isEmpty() && !result.getDetails().equals("No Alerts")) { - alerts = result.getDetails().split("\\\\n"); - String[] lastAlert = alerts[alerts.length - 1].split(" "); - lastAlertTimestamp = lastAlert[0] + " " + lastAlert[1]; + if (!result.getDetails().isEmpty() && !result.getDetails().trim().equals("No Alerts")) { + alerts = result.getDetails().trim().split("\\\\n"); + String[] lastAlert = alerts[alerts.length - 1].split(","); + lastAlertTimestamp = lastAlert[0]; } + return new GetRouterAlertsAnswer(cmd, alerts, lastAlertTimestamp); + } else { + return new GetRouterAlertsAnswer(cmd, result.getDetails()); } - - return new GetRouterAlertsAnswer(cmd, alerts, lastAlertTimestamp); } protected Answer execute(CheckRouterCommand cmd) { @@ -760,21 +759,6 @@ protected List generateConfig(SetMonitorServiceCommand cmd) { return cfg; } - protected List generateConfig(GetRouterAlertsCommand cmd) { - LinkedList cfg = new LinkedList<>(); - - String args = null; - String routerIp = cmd.getAccessDetail(NetworkElementCommand.ROUTER_IP); - if (cmd.getPreviousAlertTimeStamp() != null) { - args = "getRouterAlerts.sh " + routerIp + " " + cmd.getPreviousAlertTimeStamp(); - } else { - args = "getRouterAlerts.sh " + routerIp; - } - - cfg.add(new ConfigItem(VRScripts.ROUTER_ALERTS, args)); - return cfg; - } - protected List generateConfig(SetupGuestNetworkCommand cmd) { LinkedList cfg = new LinkedList<>(); @@ -796,8 +780,14 @@ protected List generateConfig(SetupGuestNetworkCommand cmd) { String dev = "eth" + nic.getDeviceId(); String netmask = NetUtils.getSubNet(routerGIP, nic.getNetmask()); - - String args = " -C"; + String args = ""; + if(cmd.isAdd() == false) { + //pass the argument to script to delete the network + args +=" -D"; + } else { + // pass create option argument if the ip needs to be added to eth device + args +=" -C"; + } args += " -M " + nic.getMac(); args += " -d " + dev; args += " -i " + routerGIP; @@ -989,6 +979,9 @@ public boolean configure(final String name, final Map params) th value = (String)params.get("ssh.port"); _port = NumbersUtil.parseInt(value, 3922); + value = (String)params.get("router.aggregation.command.each.timeout"); + _eachTimeout = NumbersUtil.parseInt(value, 3); + if (_vrDeployer == null) { throw new ConfigurationException("Unable to find the resource for VirtualRouterDeployer!"); } @@ -1137,11 +1130,13 @@ private Answer execute(AggregationControlCommand cmd) { return new Answer(cmd); } else if (action == Action.Finish) { Queue queue = _vrAggregateCommandsSet.get(routerName); + int answerCounts = 0; try { StringBuilder sb = new StringBuilder(); sb.append("#Apache CloudStack Virtual Router Config File\n"); sb.append("\n" + _cfgVersion + "\n\n"); for (NetworkElementCommand command : queue) { + answerCounts += command.getAnswersCount(); List cfg = generateCommandCfg(command); if (cfg == null) { s_logger.warn("Unknown commands for VirtualRoutingResource, but continue: " + cmd.toString()); @@ -1168,7 +1163,12 @@ private Answer execute(AggregationControlCommand cmd) { return new Answer(cmd, false, result.getDetails()); } - result = _vrDeployer.executeInVR(cmd.getRouterAccessIp(), VRScripts.VR_CFG, "-c " + cfgFilePath + cfgFileName); + // 120s is the minimal timeout + int timeout = answerCounts * _eachTimeout; + if (timeout < 120) { + timeout = 120; + } + result = _vrDeployer.executeInVR(cmd.getRouterAccessIp(), VRScripts.VR_CFG, "-c " + cfgFilePath + cfgFileName, timeout); if (!result.isSuccess()) { return new Answer(cmd, false, result.getDetails()); } diff --git a/core/src/com/cloud/storage/resource/StoragePoolResource.java b/core/src/com/cloud/storage/resource/StoragePoolResource.java index 5ec8f0ef2b..a87dfec0a0 100644 --- a/core/src/com/cloud/storage/resource/StoragePoolResource.java +++ b/core/src/com/cloud/storage/resource/StoragePoolResource.java @@ -19,8 +19,6 @@ import com.cloud.agent.api.Answer; import com.cloud.agent.api.storage.CopyVolumeAnswer; import com.cloud.agent.api.storage.CopyVolumeCommand; -import com.cloud.agent.api.storage.CreateAnswer; -import com.cloud.agent.api.storage.CreateCommand; import com.cloud.agent.api.storage.DestroyCommand; import com.cloud.agent.api.storage.PrimaryStorageDownloadAnswer; import com.cloud.agent.api.storage.PrimaryStorageDownloadCommand; @@ -33,6 +31,4 @@ public interface StoragePoolResource { Answer execute(DestroyCommand cmd); CopyVolumeAnswer execute(CopyVolumeCommand cmd); - - CreateAnswer execute(CreateCommand cmd); } diff --git a/core/src/org/apache/cloudstack/storage/command/AttachCommand.java b/core/src/org/apache/cloudstack/storage/command/AttachCommand.java index 7e47ba4e31..303457b4a4 100644 --- a/core/src/org/apache/cloudstack/storage/command/AttachCommand.java +++ b/core/src/org/apache/cloudstack/storage/command/AttachCommand.java @@ -24,6 +24,7 @@ public final class AttachCommand extends Command implements StorageSubSystemCommand { private DiskTO disk; private String vmName; + private boolean inSeq = false; public AttachCommand(DiskTO disk, String vmName) { super(); @@ -51,4 +52,9 @@ public String getVmName() { public void setVmName(String vmName) { this.vmName = vmName; } + + @Override + public void setExecuteInSequence(boolean inSeq) { + this.inSeq = inSeq; + } } diff --git a/core/src/org/apache/cloudstack/storage/command/AttachPrimaryDataStoreCmd.java b/core/src/org/apache/cloudstack/storage/command/AttachPrimaryDataStoreCmd.java index 2083876b56..25679ba28c 100644 --- a/core/src/org/apache/cloudstack/storage/command/AttachPrimaryDataStoreCmd.java +++ b/core/src/org/apache/cloudstack/storage/command/AttachPrimaryDataStoreCmd.java @@ -21,6 +21,11 @@ import com.cloud.agent.api.Command; public final class AttachPrimaryDataStoreCmd extends Command implements StorageSubSystemCommand { + @Override + public void setExecuteInSequence(boolean inSeq) { + + } + private final String dataStore; public AttachPrimaryDataStoreCmd(String uri) { diff --git a/core/src/org/apache/cloudstack/storage/command/CopyCommand.java b/core/src/org/apache/cloudstack/storage/command/CopyCommand.java index 446c61f9a7..96822a4ff2 100644 --- a/core/src/org/apache/cloudstack/storage/command/CopyCommand.java +++ b/core/src/org/apache/cloudstack/storage/command/CopyCommand.java @@ -78,4 +78,8 @@ public Map getOptions() { return options; } + @Override + public void setExecuteInSequence(boolean inSeq) { + this.executeInSequence = inSeq; + } } diff --git a/core/src/org/apache/cloudstack/storage/command/CreateObjectCommand.java b/core/src/org/apache/cloudstack/storage/command/CreateObjectCommand.java index 121a7ee449..8c239b5304 100644 --- a/core/src/org/apache/cloudstack/storage/command/CreateObjectCommand.java +++ b/core/src/org/apache/cloudstack/storage/command/CreateObjectCommand.java @@ -42,4 +42,8 @@ public DataTO getData() { return this.data; } + @Override + public void setExecuteInSequence(boolean inSeq) { + + } } diff --git a/core/src/org/apache/cloudstack/storage/command/CreatePrimaryDataStoreCmd.java b/core/src/org/apache/cloudstack/storage/command/CreatePrimaryDataStoreCmd.java index b536028927..21716cf111 100644 --- a/core/src/org/apache/cloudstack/storage/command/CreatePrimaryDataStoreCmd.java +++ b/core/src/org/apache/cloudstack/storage/command/CreatePrimaryDataStoreCmd.java @@ -35,4 +35,8 @@ public boolean executeInSequence() { return false; } + @Override + public void setExecuteInSequence(boolean inSeq) { + + } } diff --git a/core/src/org/apache/cloudstack/storage/command/DeleteCommand.java b/core/src/org/apache/cloudstack/storage/command/DeleteCommand.java index 76696da30a..7445050763 100644 --- a/core/src/org/apache/cloudstack/storage/command/DeleteCommand.java +++ b/core/src/org/apache/cloudstack/storage/command/DeleteCommand.java @@ -42,4 +42,8 @@ public DataTO getData() { return this.data; } + @Override + public void setExecuteInSequence(boolean inSeq) { + + } } diff --git a/core/src/org/apache/cloudstack/storage/command/DettachCommand.java b/core/src/org/apache/cloudstack/storage/command/DettachCommand.java index 61cb88b284..1e501d9600 100644 --- a/core/src/org/apache/cloudstack/storage/command/DettachCommand.java +++ b/core/src/org/apache/cloudstack/storage/command/DettachCommand.java @@ -87,4 +87,9 @@ public void setStoragePort(int storagePort) { public int getStoragePort() { return _storagePort; } + + @Override + public void setExecuteInSequence(boolean inSeq) { + + } } diff --git a/core/src/org/apache/cloudstack/storage/command/ForgetObjectCmd.java b/core/src/org/apache/cloudstack/storage/command/ForgetObjectCmd.java index ffee0ab921..981a098102 100644 --- a/core/src/org/apache/cloudstack/storage/command/ForgetObjectCmd.java +++ b/core/src/org/apache/cloudstack/storage/command/ForgetObjectCmd.java @@ -36,4 +36,9 @@ public DataTO getDataTO() { public boolean executeInSequence() { return false; } + + @Override + public void setExecuteInSequence(boolean inSeq) { + + } } diff --git a/core/src/org/apache/cloudstack/storage/command/IntroduceObjectCmd.java b/core/src/org/apache/cloudstack/storage/command/IntroduceObjectCmd.java index c6c6d23726..b463b2c5f0 100644 --- a/core/src/org/apache/cloudstack/storage/command/IntroduceObjectCmd.java +++ b/core/src/org/apache/cloudstack/storage/command/IntroduceObjectCmd.java @@ -36,4 +36,9 @@ public DataTO getDataTO() { public boolean executeInSequence() { return false; } + + @Override + public void setExecuteInSequence(boolean inSeq) { + + } } diff --git a/core/src/org/apache/cloudstack/storage/command/StorageSubSystemCommand.java b/core/src/org/apache/cloudstack/storage/command/StorageSubSystemCommand.java index d14161ae4c..fb7b373684 100644 --- a/core/src/org/apache/cloudstack/storage/command/StorageSubSystemCommand.java +++ b/core/src/org/apache/cloudstack/storage/command/StorageSubSystemCommand.java @@ -19,5 +19,5 @@ package org.apache.cloudstack.storage.command; public interface StorageSubSystemCommand { - + void setExecuteInSequence(boolean inSeq); } diff --git a/core/src/org/apache/cloudstack/storage/to/PrimaryDataStoreTO.java b/core/src/org/apache/cloudstack/storage/to/PrimaryDataStoreTO.java index 6a5d679331..29e53b0d95 100644 --- a/core/src/org/apache/cloudstack/storage/to/PrimaryDataStoreTO.java +++ b/core/src/org/apache/cloudstack/storage/to/PrimaryDataStoreTO.java @@ -27,6 +27,7 @@ public class PrimaryDataStoreTO implements DataStoreTO { public static final String MANAGED = PrimaryDataStore.MANAGED; public static final String STORAGE_HOST = PrimaryDataStore.STORAGE_HOST; + public static final String STORAGE_PORT = PrimaryDataStore.STORAGE_PORT; public static final String MANAGED_STORE_TARGET = PrimaryDataStore.MANAGED_STORE_TARGET; public static final String MANAGED_STORE_TARGET_ROOT_VOLUME = PrimaryDataStore.MANAGED_STORE_TARGET_ROOT_VOLUME; public static final String CHAP_INITIATOR_USERNAME = PrimaryDataStore.CHAP_INITIATOR_USERNAME; diff --git a/core/test/com/cloud/agent/resource/virtualnetwork/VirtualRoutingResourceTest.java b/core/test/com/cloud/agent/resource/virtualnetwork/VirtualRoutingResourceTest.java index 48da1bb58b..531c71854d 100644 --- a/core/test/com/cloud/agent/resource/virtualnetwork/VirtualRoutingResourceTest.java +++ b/core/test/com/cloud/agent/resource/virtualnetwork/VirtualRoutingResourceTest.java @@ -91,6 +91,11 @@ public class VirtualRoutingResourceTest implements VirtualRouterDeployer { @Override public ExecutionResult executeInVR(String routerIp, String script, String args) { + return executeInVR(routerIp, script, args, 60); + } + + @Override + public ExecutionResult executeInVR(String routerIp, String script, String args, int timeout) { assertEquals(routerIp, ROUTERIP); verifyCommand(_currentCmd, script, args); return new ExecutionResult(true, null); diff --git a/core/test/org/apache/cloudstack/api/agent/test/BackupSnapshotCommandTest.java b/core/test/org/apache/cloudstack/api/agent/test/BackupSnapshotCommandTest.java index eaa9b94fee..33361e8726 100644 --- a/core/test/org/apache/cloudstack/api/agent/test/BackupSnapshotCommandTest.java +++ b/core/test/org/apache/cloudstack/api/agent/test/BackupSnapshotCommandTest.java @@ -28,6 +28,7 @@ import com.cloud.agent.api.BackupSnapshotCommand; import com.cloud.agent.api.to.SwiftTO; +import com.cloud.hypervisor.Hypervisor; import com.cloud.storage.Storage.StoragePoolType; import com.cloud.storage.StoragePool; import com.cloud.storage.StoragePoolStatus; @@ -145,7 +146,14 @@ public String getStorageProviderName() { public boolean isInMaintenance() { // TODO Auto-generated method stub return false; - }; + } + + @Override + public Hypervisor.HypervisorType getHypervisor() { + return null; //To change body of implemented methods use File | Settings | File Templates. + } + + ; }; BackupSnapshotCommand bsc = new BackupSnapshotCommand("http://secondary.Storage.Url", 101L, 102L, 103L, 104L, 105L, "vPath", pool, diff --git a/core/test/org/apache/cloudstack/api/agent/test/CheckNetworkAnswerTest.java b/core/test/org/apache/cloudstack/api/agent/test/CheckNetworkAnswerTest.java index b0872bfc52..66feaecb5e 100644 --- a/core/test/org/apache/cloudstack/api/agent/test/CheckNetworkAnswerTest.java +++ b/core/test/org/apache/cloudstack/api/agent/test/CheckNetworkAnswerTest.java @@ -32,6 +32,7 @@ import com.cloud.agent.api.CheckNetworkCommand; import com.cloud.agent.api.storage.ResizeVolumeCommand; import com.cloud.agent.api.to.StorageFilerTO; +import com.cloud.hypervisor.Hypervisor; import com.cloud.storage.Storage; import com.cloud.storage.StoragePool; import com.cloud.storage.StoragePoolStatus; @@ -184,7 +185,14 @@ public String getStorageProviderName() { public boolean isInMaintenance() { // TODO Auto-generated method stub return false; - }; + } + + @Override + public Hypervisor.HypervisorType getHypervisor() { + return null; //To change body of implemented methods use File | Settings | File Templates. + } + + ; }; Long newSize = 4194304L; diff --git a/core/test/org/apache/cloudstack/api/agent/test/SnapshotCommandTest.java b/core/test/org/apache/cloudstack/api/agent/test/SnapshotCommandTest.java index 8339a98b9f..114c8854d1 100644 --- a/core/test/org/apache/cloudstack/api/agent/test/SnapshotCommandTest.java +++ b/core/test/org/apache/cloudstack/api/agent/test/SnapshotCommandTest.java @@ -28,6 +28,7 @@ import org.junit.Test; import com.cloud.agent.api.SnapshotCommand; +import com.cloud.hypervisor.Hypervisor; import com.cloud.storage.Storage.StoragePoolType; import com.cloud.storage.StoragePool; import com.cloud.storage.StoragePoolStatus; @@ -146,7 +147,14 @@ public String getStorageProviderName() { public boolean isInMaintenance() { // TODO Auto-generated method stub return false; - }; + } + + @Override + public Hypervisor.HypervisorType getHypervisor() { + return null; //To change body of implemented methods use File | Settings | File Templates. + } + + ; }; SnapshotCommand ssc = new SnapshotCommand(pool, "http://secondary.Storage.Url", "420fa39c-4ef1-a83c-fd93-46dc1ff515ae", "snapshotName", 101L, 102L, 103L); diff --git a/debian/control b/debian/control index ab4644badd..504ef99f31 100644 --- a/debian/control +++ b/debian/control @@ -15,7 +15,7 @@ Description: A common package which contains files which are shared by several C Package: cloudstack-management Architecture: all -Depends: cloudstack-common (= ${source:Version}), tomcat6, sysvinit-utils, sudo, jsvc, python-mysqldb, python-paramiko, augeas-tools +Depends: cloudstack-common (= ${source:Version}), tomcat6, sysvinit-utils, sudo, jsvc, python-mysqldb, libmysql-java, python-paramiko, augeas-tools Conflicts: cloud-server, cloud-client, cloud-client-ui Description: CloudStack server library The CloudStack management server diff --git a/debian/rules b/debian/rules index 4edf893060..197e243bcf 100755 --- a/debian/rules +++ b/debian/rules @@ -35,7 +35,7 @@ build: build-indep build-indep: build-indep-stamp build-indep-stamp: configure - mvn clean package -Pawsapi -DskipTests -Dsystemvm \ + mvn -T C1.5 clean package -Pawsapi -DskipTests -Dsystemvm \ -Dcs.replace.properties=replace.properties.tmp \ ${ACS_BUILD_OPTS} touch $@ diff --git a/engine/api/src/com/cloud/vm/VirtualMachineManager.java b/engine/api/src/com/cloud/vm/VirtualMachineManager.java index 99f5595579..b1e5258af7 100644 --- a/engine/api/src/com/cloud/vm/VirtualMachineManager.java +++ b/engine/api/src/com/cloud/vm/VirtualMachineManager.java @@ -36,11 +36,9 @@ import com.cloud.exception.ResourceUnavailableException; import com.cloud.hypervisor.Hypervisor.HypervisorType; import com.cloud.network.Network; -import com.cloud.offering.DiskOffering; import com.cloud.offering.DiskOfferingInfo; import com.cloud.offering.ServiceOffering; import com.cloud.storage.StoragePool; -import com.cloud.storage.Volume; import com.cloud.template.VirtualMachineTemplate; import com.cloud.utils.component.Manager; import com.cloud.utils.fsm.NoTransitionException; @@ -77,7 +75,7 @@ public interface Topics { * @throws InsufficientCapacityException If there are insufficient capacity to deploy this vm. */ void allocate(String vmInstanceName, VirtualMachineTemplate template, ServiceOffering serviceOffering, DiskOfferingInfo rootDiskOfferingInfo, - LinkedHashMap dataDiskOfferings, LinkedHashMap> auxiliaryNetworks, DeploymentPlan plan, + List dataDiskOfferings, LinkedHashMap> auxiliaryNetworks, DeploymentPlan plan, HypervisorType hyperType) throws InsufficientCapacityException; void allocate(String vmInstanceName, VirtualMachineTemplate template, ServiceOffering serviceOffering, @@ -114,7 +112,7 @@ void orchestrateStart(String vmUuid, Map pa void migrate(String vmUuid, long srcHostId, DeployDestination dest) throws ResourceUnavailableException, ConcurrentOperationException; - void migrateWithStorage(String vmUuid, long srcId, long destId, Map volumeToPool) throws ResourceUnavailableException, ConcurrentOperationException; + void migrateWithStorage(String vmUuid, long srcId, long destId, Map volumeToPool) throws ResourceUnavailableException, ConcurrentOperationException; void reboot(String vmUuid, Map params) throws InsufficientCapacityException, ResourceUnavailableException; diff --git a/engine/api/src/org/apache/cloudstack/engine/orchestration/service/VolumeOrchestrationService.java b/engine/api/src/org/apache/cloudstack/engine/orchestration/service/VolumeOrchestrationService.java index 2531074029..3b555e55be 100644 --- a/engine/api/src/org/apache/cloudstack/engine/orchestration/service/VolumeOrchestrationService.java +++ b/engine/api/src/org/apache/cloudstack/engine/orchestration/service/VolumeOrchestrationService.java @@ -21,6 +21,7 @@ import java.util.Map; import java.util.Set; +import org.apache.cloudstack.engine.subsystem.api.storage.DataStore; import org.apache.cloudstack.engine.subsystem.api.storage.VolumeInfo; import com.cloud.agent.api.to.VirtualMachineTO; @@ -86,7 +87,7 @@ VolumeInfo moveVolume(VolumeInfo volume, long destPoolDcId, Long destPoolPodId, void destroyVolume(Volume volume); - DiskProfile allocateRawVolume(Type type, String name, DiskOffering offering, Long size, VirtualMachine vm, VirtualMachineTemplate template, Account owner); + DiskProfile allocateRawVolume(Type type, String name, DiskOffering offering, Long size, Long minIops, Long maxIops, VirtualMachine vm, VirtualMachineTemplate template, Account owner); VolumeInfo createVolumeOnPrimaryStorage(VirtualMachine vm, Volume rootVolumeOfVm, VolumeInfo volume, HypervisorType rootDiskHyperType) throws NoTransitionException; @@ -94,6 +95,8 @@ VolumeInfo moveVolume(VolumeInfo volume, long destPoolDcId, Long destPoolPodId, void cleanupVolumes(long vmId) throws ConcurrentOperationException; + void disconnectVolumeFromHost(VolumeInfo volumeInfo, Host host, DataStore dataStore); + void disconnectVolumesFromHost(long vmId, long hostId); void migrateVolumes(VirtualMachine vm, VirtualMachineTO vmTo, Host srcHost, Host destHost, Map volumeToPool); @@ -118,4 +121,5 @@ DiskProfile allocateTemplatedVolume(Type type, String name, DiskOffering offerin StoragePool findStoragePool(DiskProfile dskCh, DataCenter dc, Pod pod, Long clusterId, Long hostId, VirtualMachine vm, Set avoid); void updateVolumeDiskChain(long volumeId, String path, String chainInfo); + } diff --git a/engine/api/src/org/apache/cloudstack/engine/subsystem/api/storage/PrimaryDataStoreInfo.java b/engine/api/src/org/apache/cloudstack/engine/subsystem/api/storage/PrimaryDataStoreInfo.java index bb9f2dad1f..f08d9a4550 100644 --- a/engine/api/src/org/apache/cloudstack/engine/subsystem/api/storage/PrimaryDataStoreInfo.java +++ b/engine/api/src/org/apache/cloudstack/engine/subsystem/api/storage/PrimaryDataStoreInfo.java @@ -29,6 +29,7 @@ public interface PrimaryDataStoreInfo extends StoragePool { static final String MANAGED = "managed"; static final String STORAGE_HOST= "storageHost"; + static final String STORAGE_PORT = "storagePort"; static final String MANAGED_STORE_TARGET = "managedStoreTarget"; static final String MANAGED_STORE_TARGET_ROOT_VOLUME = "managedStoreTargetRootVolume"; static final String CHAP_INITIATOR_USERNAME = "chapInitiatorUsername"; diff --git a/engine/api/src/org/apache/cloudstack/engine/subsystem/api/storage/TemplateDataFactory.java b/engine/api/src/org/apache/cloudstack/engine/subsystem/api/storage/TemplateDataFactory.java index 801c4427f5..fd22da12e4 100644 --- a/engine/api/src/org/apache/cloudstack/engine/subsystem/api/storage/TemplateDataFactory.java +++ b/engine/api/src/org/apache/cloudstack/engine/subsystem/api/storage/TemplateDataFactory.java @@ -25,6 +25,8 @@ public interface TemplateDataFactory { TemplateInfo getTemplate(long templateId, DataStore store); + TemplateInfo getReadyTemplateOnImageStore(long templateId, Long zoneId); + TemplateInfo getTemplate(DataObject obj, DataStore store); TemplateInfo getTemplate(long templateId, DataStoreRole storeRole); diff --git a/engine/components-api/src/com/cloud/event/UsageEventUtils.java b/engine/components-api/src/com/cloud/event/UsageEventUtils.java index 4f32cb3263..f1707bd45d 100644 --- a/engine/components-api/src/com/cloud/event/UsageEventUtils.java +++ b/engine/components-api/src/com/cloud/event/UsageEventUtils.java @@ -70,6 +70,15 @@ public static void publishUsageEvent(String usageType, long accountId, long zone publishUsageEvent(usageType, accountId, zoneId, entityType, entityUUID); } + public static void publishUsageEvent(String usageType, long accountId, long zoneId, long resourceId, String resourceName, Long offeringId, Long templateId, + Long size, String entityType, String entityUUID, boolean displayResource) { + if(displayResource){ + saveUsageEvent(usageType, accountId, zoneId, resourceId, resourceName, offeringId, templateId, size); + } + publishUsageEvent(usageType, accountId, zoneId, entityType, entityUUID); + + } + public static void publishUsageEvent(String usageType, long accountId, long zoneId, long resourceId, String resourceName, Long offeringId, Long templateId, Long size, Long virtualSize, String entityType, String entityUUID) { saveUsageEvent(usageType, accountId, zoneId, resourceId, resourceName, offeringId, templateId, size, virtualSize); @@ -81,6 +90,13 @@ public static void publishUsageEvent(String usageType, long accountId, long zone publishUsageEvent(usageType, accountId, zoneId, entityType, entityUUID); } + public static void publishUsageEvent(String usageType, long accountId, long zoneId, long resourceId, String resourceName, String entityType, String entityUUID, boolean diplayResource) { + if (diplayResource){ + saveUsageEvent(usageType, accountId, zoneId, resourceId, resourceName); + publishUsageEvent(usageType, accountId, zoneId, entityType, entityUUID); + } + } + public static void publishUsageEvent(String usageType, long accountId, long zoneId, long ipAddressId, String ipAddress, boolean isSourceNat, String guestType, boolean isSystem, String entityType, String entityUUID) { saveUsageEvent(usageType, accountId, zoneId, ipAddressId, ipAddress, isSourceNat, guestType, isSystem); @@ -88,9 +104,12 @@ public static void publishUsageEvent(String usageType, long accountId, long zone } public static void publishUsageEvent(String usageType, long accountId, long zoneId, long resourceId, String resourceName, Long offeringId, Long templateId, - String resourceType, String entityType, String entityUUID) { - saveUsageEvent(usageType, accountId, zoneId, resourceId, resourceName, offeringId, templateId, resourceType); + String resourceType, String entityType, String entityUUID, boolean displayResource) { + if(displayResource){ + saveUsageEvent(usageType, accountId, zoneId, resourceId, resourceName, offeringId, templateId, resourceType); + } publishUsageEvent(usageType, accountId, zoneId, entityType, entityUUID); + } public static void publishUsageEvent(String usageType, long accountId, long zoneId, long vmId, long securityGroupId, String entityType, String entityUUID) { @@ -99,9 +118,12 @@ public static void publishUsageEvent(String usageType, long accountId, long zone } public static void publishUsageEvent(String usageType, long accountId, long zoneId, long resourceId, String resourceName, Long offeringId, Long templateId, - String resourceType, String entityType, String entityUUID, Map details) { - saveUsageEvent(usageType, accountId, zoneId, resourceId, resourceName, offeringId, templateId, resourceType, details); + String resourceType, String entityType, String entityUUID, Map details, boolean displayResource) { + if(displayResource){ + saveUsageEvent(usageType, accountId, zoneId, resourceId, resourceName, offeringId, templateId, resourceType, details); + } publishUsageEvent(usageType, accountId, zoneId, entityType, entityUUID); + } private static void saveUsageEvent(String usageType, long accountId, long zoneId, long resourceId, String resourceName, Long offeringId, Long templateId, diff --git a/engine/components-api/src/com/cloud/network/addr/PublicIp.java b/engine/components-api/src/com/cloud/network/addr/PublicIp.java index ff11b3349a..a20e3459e7 100644 --- a/engine/components-api/src/com/cloud/network/addr/PublicIp.java +++ b/engine/components-api/src/com/cloud/network/addr/PublicIp.java @@ -18,9 +18,8 @@ import java.util.Date; -import org.apache.cloudstack.acl.IAMEntityType; - import com.cloud.dc.VlanVO; +import com.cloud.network.IpAddress; import com.cloud.network.PublicIpAddress; import com.cloud.network.dao.IPAddressVO; import com.cloud.utils.net.Ip; @@ -240,7 +239,7 @@ public boolean isDisplay() { } @Override - public IAMEntityType getEntityType() { - return IAMEntityType.PublicIpAddress; + public Class getEntityType() { + return IpAddress.class; } } diff --git a/engine/components-api/src/com/cloud/network/rules/StaticNatRuleImpl.java b/engine/components-api/src/com/cloud/network/rules/StaticNatRuleImpl.java index bdaf2bc1b2..9a49db0ca1 100644 --- a/engine/components-api/src/com/cloud/network/rules/StaticNatRuleImpl.java +++ b/engine/components-api/src/com/cloud/network/rules/StaticNatRuleImpl.java @@ -18,8 +18,6 @@ import java.util.List; -import org.apache.cloudstack.acl.IAMEntityType; - public class StaticNatRuleImpl implements StaticNatRule { long id; String xid; @@ -152,7 +150,7 @@ public boolean isDisplay() { } @Override - public IAMEntityType getEntityType() { - return IAMEntityType.FirewallRule; + public Class getEntityType() { + return FirewallRule.class; } } diff --git a/engine/components-api/src/com/cloud/resource/ResourceManager.java b/engine/components-api/src/com/cloud/resource/ResourceManager.java index 5a9bddb186..4f43adb3f5 100755 --- a/engine/components-api/src/com/cloud/resource/ResourceManager.java +++ b/engine/components-api/src/com/cloud/resource/ResourceManager.java @@ -23,6 +23,7 @@ import com.cloud.agent.api.StartupCommand; import com.cloud.agent.api.StartupRoutingCommand; +import com.cloud.agent.api.VgpuTypesInfo; import com.cloud.agent.api.to.GPUDeviceTO; import com.cloud.dc.DataCenterVO; import com.cloud.dc.HostPodVO; @@ -141,41 +142,51 @@ public interface ResourceManager extends ResourceService { */ List listAllUpAndEnabledNonHAHosts(Type type, Long clusterId, Long podId, long dcId); + /** + * Check if host is GPU enabled + * @param hostId the host to be checked + * @return true if host contains GPU card else false + */ + boolean isHostGpuEnabled(long hostId); + /** * Check if host has GPU devices available * @param hostId the host to be checked + * @param groupName: gpuCard name * @param vgpuType the VGPU type * @return true when the host has the capacity with given VGPU type */ - boolean isGPUDeviceAvailable(long hostId, String vgpuType); + boolean isGPUDeviceAvailable(long hostId, String groupName, String vgpuType); /** * Get available GPU device * @param hostId the host to be checked + * @param groupName: gpuCard name * @param vgpuType the VGPU type * @return GPUDeviceTO[] */ - GPUDeviceTO getGPUDevice(long hostId, String vgpuType); + GPUDeviceTO getGPUDevice(long hostId, String groupName, String vgpuType); /** * Return listof available GPU devices * @param hostId, the host to be checked + * @param groupName: gpuCard name * @param vgpuType the VGPU type * @return List of HostGpuGroupsVO. */ - List listAvailableGPUDevice(long hostId, String vgpuType); + List listAvailableGPUDevice(long hostId, String groupName, String vgpuType); /** * Update GPU device details (post VM deployment) * @param hostId, the dest host Id * @param groupDetails, capacity of GPU group. */ - void updateGPUDetails(long hostId, HashMap> groupDetails); + void updateGPUDetails(long hostId, HashMap> groupDetails); /** * Get GPU details for a host * @param host, the Host object * @return Details of groupNames and enabled VGPU type with remaining capacity. */ - HashMap> getGPUStatistics(HostVO host); + HashMap> getGPUStatistics(HostVO host); } diff --git a/engine/orchestration/src/com/cloud/agent/manager/AgentManagerImpl.java b/engine/orchestration/src/com/cloud/agent/manager/AgentManagerImpl.java index 0d41bc1b3b..f43086fab9 100755 --- a/engine/orchestration/src/com/cloud/agent/manager/AgentManagerImpl.java +++ b/engine/orchestration/src/com/cloud/agent/manager/AgentManagerImpl.java @@ -185,8 +185,15 @@ public class AgentManagerImpl extends ManagerBase implements AgentManager, Handl "The number of direct agents to load each time", false); protected final ConfigKey DirectAgentPoolSize = new ConfigKey(Integer.class, "direct.agent.pool.size", "Advanced", "500", "Default size for DirectAgentPool", false); - protected final ConfigKey DirectAgentThreadCap = new ConfigKey(Float.class, "direct.agent.thread.cap", "Advanced", "0.1", + protected final ConfigKey DirectAgentThreadCap = new ConfigKey(Float.class, "direct.agent.thread.cap", "Advanced", "1", "Percentage (as a value between 0 and 1) of direct.agent.pool.size to be used as upper thread cap for a single direct agent to process requests", false); + protected final ConfigKey CheckTxnBeforeSending = new ConfigKey( + "Developer", + Boolean.class, + "check.txn.before.sending.agent.commands", + "false", + "This parameter allows developers to enable a check to see if a transaction wraps commands that are sent to the resource. This is not to be enabled on production systems.", + true); @Override public boolean configure(final String name, final Map params) throws ConfigurationException { @@ -378,7 +385,16 @@ public Answer[] send(Long hostId, Commands commands, int timeout) throws AgentUn if (timeout <= 0) { timeout = Wait.value(); } - assert noDbTxn() : "I know, I know. Why are we so strict as to not allow txn across an agent call? ... Why are we so cruel ... Why are we such a dictator .... Too bad... Sorry...but NO AGENT COMMANDS WRAPPED WITHIN DB TRANSACTIONS!"; + + if (CheckTxnBeforeSending.value()) { + if (!noDbTxn()) { + throw new CloudRuntimeException("We do not allow transactions to be wrapped around commands sent to be executed on remote agents. " + + "We cannot predict how long it takes a command to complete. " + + "The transaction may be rolled back because the connection took too long."); + } + } else { + assert noDbTxn() : "I know, I know. Why are we so strict as to not allow txn across an agent call? ... Why are we so cruel ... Why are we such a dictator .... Too bad... Sorry...but NO AGENT COMMANDS WRAPPED WITHIN DB TRANSACTIONS!"; + } Command[] cmds = commands.toCommands(); @@ -1582,7 +1598,7 @@ public String getConfigComponentName() { @Override public ConfigKey[] getConfigKeys() { - return new ConfigKey[] {Workers, Port, PingInterval, PingTimeout, Wait, AlertWait, DirectAgentLoadSize, DirectAgentPoolSize, DirectAgentThreadCap}; + return new ConfigKey[] {CheckTxnBeforeSending, Workers, Port, PingInterval, PingTimeout, Wait, AlertWait, DirectAgentLoadSize, DirectAgentPoolSize, DirectAgentThreadCap}; } } diff --git a/engine/orchestration/src/com/cloud/vm/VirtualMachineManagerImpl.java b/engine/orchestration/src/com/cloud/vm/VirtualMachineManagerImpl.java index e9d2fd2073..d8abdfb4d7 100755 --- a/engine/orchestration/src/com/cloud/vm/VirtualMachineManagerImpl.java +++ b/engine/orchestration/src/com/cloud/vm/VirtualMachineManagerImpl.java @@ -1,4 +1,4 @@ -// Licensed to the Apache Software Foundation (ASF) under one +// Licensed to the Apacohe 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 @@ -26,6 +26,7 @@ import java.util.Date; import java.util.HashMap; import java.util.HashSet; +import java.util.Iterator; import java.util.LinkedHashMap; import java.util.List; import java.util.Map; @@ -154,7 +155,6 @@ import com.cloud.network.dao.NetworkDao; import com.cloud.network.dao.NetworkVO; import com.cloud.network.rules.RulesManager; -import com.cloud.offering.DiskOffering; import com.cloud.offering.DiskOfferingInfo; import com.cloud.offering.ServiceOffering; import com.cloud.org.Cluster; @@ -376,7 +376,7 @@ public void registerGuru(VirtualMachine.Type type, VirtualMachineGuru guru) { @Override @DB public void allocate(String vmInstanceName, final VirtualMachineTemplate template, ServiceOffering serviceOffering, - final DiskOfferingInfo rootDiskOfferingInfo, LinkedHashMap dataDiskOfferings, + final DiskOfferingInfo rootDiskOfferingInfo, final List dataDiskOfferings, final LinkedHashMap> auxiliaryNetworks, DeploymentPlan plan, HypervisorType hyperType) throws InsufficientCapacityException { @@ -393,8 +393,6 @@ public void allocate(String vmInstanceName, final VirtualMachineTemplate templat } assert (plan.getClusterId() == null && plan.getPoolId() == null) : "We currently don't support cluster and pool preset yet"; final VMInstanceVO vmFinal = _vmDao.persist(vm); - final LinkedHashMap dataDiskOfferingsFinal = - dataDiskOfferings == null ? new LinkedHashMap() : dataDiskOfferings; final VirtualMachineProfileImpl vmProfile = new VirtualMachineProfileImpl(vmFinal, template, serviceOffering, null, null); @@ -416,8 +414,8 @@ public void doInTransactionWithoutResult(TransactionStatus status) throws Insuff } if (template.getFormat() == ImageFormat.ISO) { - volumeMgr.allocateRawVolume(Type.ROOT, "ROOT-" + vmFinal.getId(), rootDiskOfferingInfo.getDiskOffering(), rootDiskOfferingInfo.getSize(), vmFinal, - template, owner); + volumeMgr.allocateRawVolume(Type.ROOT, "ROOT-" + vmFinal.getId(), rootDiskOfferingInfo.getDiskOffering(), rootDiskOfferingInfo.getSize(), + rootDiskOfferingInfo.getMinIops(), rootDiskOfferingInfo.getMaxIops(), vmFinal, template, owner); } else if (template.getFormat() == ImageFormat.BAREMETAL) { // Do nothing } else { @@ -425,8 +423,11 @@ public void doInTransactionWithoutResult(TransactionStatus status) throws Insuff rootDiskOfferingInfo.getMinIops(), rootDiskOfferingInfo.getMaxIops(), template, vmFinal, owner); } - for (Map.Entry offering : dataDiskOfferingsFinal.entrySet()) { - volumeMgr.allocateRawVolume(Type.DATADISK, "DATA-" + vmFinal.getId(), offering.getKey(), offering.getValue(), vmFinal, template, owner); + if (dataDiskOfferings != null) { + for (DiskOfferingInfo dataDiskOfferingInfo : dataDiskOfferings) { + volumeMgr.allocateRawVolume(Type.DATADISK, "DATA-" + vmFinal.getId(), dataDiskOfferingInfo.getDiskOffering(), dataDiskOfferingInfo.getSize(), + dataDiskOfferingInfo.getMinIops(), dataDiskOfferingInfo.getMaxIops(), vmFinal, template, owner); + } } } }); @@ -439,7 +440,7 @@ public void doInTransactionWithoutResult(TransactionStatus status) throws Insuff @Override public void allocate(String vmInstanceName, VirtualMachineTemplate template, ServiceOffering serviceOffering, LinkedHashMap> networks, DeploymentPlan plan, HypervisorType hyperType) throws InsufficientCapacityException { - allocate(vmInstanceName, template, serviceOffering, new DiskOfferingInfo(serviceOffering), null, networks, plan, hyperType); + allocate(vmInstanceName, template, serviceOffering, new DiskOfferingInfo(serviceOffering), new ArrayList(), networks, plan, hyperType); } private VirtualMachineGuru getVmGuru(VirtualMachine vm) { @@ -569,8 +570,8 @@ protected void advanceExpunge(VMInstanceVO vm) throws ResourceUnavailableExcepti @Override public boolean start() { // TODO, initial delay is hardcoded - _executor.scheduleAtFixedRate(new TransitionTask(), 5000, VmJobStateReportInterval.value(), TimeUnit.SECONDS); - _executor.scheduleAtFixedRate(new CleanupTask(), VmOpCleanupInterval.value(), VmOpCleanupInterval.value(), TimeUnit.SECONDS); + _executor.scheduleAtFixedRate(new CleanupTask(), 5, VmJobStateReportInterval.value(), TimeUnit.SECONDS); + _executor.scheduleAtFixedRate(new TransitionTask(), VmOpCleanupInterval.value(), VmOpCleanupInterval.value(), TimeUnit.SECONDS); cancelWorkItems(_nodeId); // cleanup left over place holder works @@ -996,7 +997,9 @@ public void orchestrateStart(String vmUuid, Map vmmetadata = new HashMap(); + vmmetadata.put(vm.getInstanceName(), platform); + syncVMMetaData(vmmetadata); } } } @@ -1214,9 +1217,18 @@ public void stop(String vmUuid) throws ResourceUnavailableException { } } - protected boolean sendStop(VirtualMachineGuru guru, VirtualMachineProfile profile, boolean force) { + + protected boolean getExecuteInSequence(HypervisorType hypervisorType) { + if (HypervisorType.KVM == hypervisorType) { + return false; + } else { + return ExecuteInSequence.value(); + } + } + + protected boolean sendStop(VirtualMachineGuru guru, VirtualMachineProfile profile, boolean force, boolean checkBeforeCleanup) { VirtualMachine vm = profile.getVirtualMachine(); - StopCommand stop = new StopCommand(vm, ExecuteInSequence.value()); + StopCommand stop = new StopCommand(vm, getExecuteInSequence(vm.getHypervisorType()), checkBeforeCleanup); try { StopAnswer answer = (StopAnswer)_agentMgr.send(vm.getHostId(), stop); if (answer != null) { @@ -1262,62 +1274,65 @@ protected boolean cleanup(VirtualMachineGuru guru, VirtualMachineProfile profile VirtualMachine vm = profile.getVirtualMachine(); State state = vm.getState(); s_logger.debug("Cleaning up resources for the vm " + vm + " in " + state + " state"); - if (state == State.Starting) { - Step step = work.getStep(); - if (step == Step.Starting && !cleanUpEvenIfUnableToStop) { - s_logger.warn("Unable to cleanup vm " + vm + "; work state is incorrect: " + step); - return false; - } + try { + if (state == State.Starting) { + Step step = work.getStep(); + if (step == Step.Starting && !cleanUpEvenIfUnableToStop) { + s_logger.warn("Unable to cleanup vm " + vm + "; work state is incorrect: " + step); + return false; + } + + if (step == Step.Started || step == Step.Starting || step == Step.Release) { + if (vm.getHostId() != null) { + if (!sendStop(guru, profile, cleanUpEvenIfUnableToStop, false)) { + s_logger.warn("Failed to stop vm " + vm + " in " + State.Starting + " state as a part of cleanup process"); + return false; + } + } + } - if (step == Step.Started || step == Step.Starting || step == Step.Release) { + if (step != Step.Release && step != Step.Prepare && step != Step.Started && step != Step.Starting) { + s_logger.debug("Cleanup is not needed for vm " + vm + "; work state is incorrect: " + step); + return true; + } + } else if (state == State.Stopping) { if (vm.getHostId() != null) { - if (!sendStop(guru, profile, cleanUpEvenIfUnableToStop)) { - s_logger.warn("Failed to stop vm " + vm + " in " + State.Starting + " state as a part of cleanup process"); + if (!sendStop(guru, profile, cleanUpEvenIfUnableToStop, false)) { + s_logger.warn("Failed to stop vm " + vm + " in " + State.Stopping + " state as a part of cleanup process"); return false; } } - } - - if (step != Step.Release && step != Step.Prepare && step != Step.Started && step != Step.Starting) { - s_logger.debug("Cleanup is not needed for vm " + vm + "; work state is incorrect: " + step); - return true; - } - } else if (state == State.Stopping) { - if (vm.getHostId() != null) { - if (!sendStop(guru, profile, cleanUpEvenIfUnableToStop)) { - s_logger.warn("Failed to stop vm " + vm + " in " + State.Stopping + " state as a part of cleanup process"); - return false; + } else if (state == State.Migrating) { + if (vm.getHostId() != null) { + if (!sendStop(guru, profile, cleanUpEvenIfUnableToStop, false)) { + s_logger.warn("Failed to stop vm " + vm + " in " + State.Migrating + " state as a part of cleanup process"); + return false; + } } - } - } else if (state == State.Migrating) { - if (vm.getHostId() != null) { - if (!sendStop(guru, profile, cleanUpEvenIfUnableToStop)) { - s_logger.warn("Failed to stop vm " + vm + " in " + State.Migrating + " state as a part of cleanup process"); - return false; + if (vm.getLastHostId() != null) { + if (!sendStop(guru, profile, cleanUpEvenIfUnableToStop, false)) { + s_logger.warn("Failed to stop vm " + vm + " in " + State.Migrating + " state as a part of cleanup process"); + return false; + } } - } - if (vm.getLastHostId() != null) { - if (!sendStop(guru, profile, cleanUpEvenIfUnableToStop)) { - s_logger.warn("Failed to stop vm " + vm + " in " + State.Migrating + " state as a part of cleanup process"); + } else if (state == State.Running) { + if (!sendStop(guru, profile, cleanUpEvenIfUnableToStop, false)) { + s_logger.warn("Failed to stop vm " + vm + " in " + State.Running + " state as a part of cleanup process"); return false; } } - } else if (state == State.Running) { - if (!sendStop(guru, profile, cleanUpEvenIfUnableToStop)) { - s_logger.warn("Failed to stop vm " + vm + " in " + State.Running + " state as a part of cleanup process"); - return false; + } finally { + try { + _networkMgr.release(profile, cleanUpEvenIfUnableToStop); + s_logger.debug("Successfully released network resources for the vm " + vm); + } catch (Exception e) { + s_logger.warn("Unable to release some network resources.", e); } - } - try { - _networkMgr.release(profile, cleanUpEvenIfUnableToStop); - s_logger.debug("Successfully released network resources for the vm " + vm); - } catch (Exception e) { - s_logger.warn("Unable to release some network resources.", e); + volumeMgr.release(profile); + s_logger.debug("Successfully cleanued up resources for the vm " + vm + " in " + state + " state"); } - volumeMgr.release(profile); - s_logger.debug("Successfully cleanued up resources for the vm " + vm + " in " + state + " state"); return true; } @@ -1476,7 +1491,9 @@ private void advanceStop(VMInstanceVO vm, boolean cleanUpEvenIfUnableToStop) thr } vmGuru.prepareStop(profile); - StopCommand stop = new StopCommand(vm, ExecuteInSequence.value()); + + StopCommand stop = new StopCommand(vm, getExecuteInSequence(vm.getHypervisorType()), false); + boolean stopped = false; StopAnswer answer = null; try { @@ -1948,24 +1965,26 @@ protected void migrate(VMInstanceVO vm, long srcHostId, DeployDestination dest) } } - private Map getPoolListForVolumesForMigration(VirtualMachineProfile profile, Host host, Map volumeToPool) { + private Map getPoolListForVolumesForMigration(VirtualMachineProfile profile, Host host, Map volumeToPool) { List allVolumes = _volsDao.findUsableVolumesForInstance(profile.getId()); + Map volumeToPoolObjectMap = new HashMap (); for (VolumeVO volume : allVolumes) { - StoragePool pool = volumeToPool.get(volume); - DiskOfferingVO diskOffering = _diskOfferingDao.findById(volume.getDiskOfferingId()); + Long poolId = volumeToPool.get(Long.valueOf(volume.getId())); + StoragePoolVO pool = _storagePoolDao.findById(poolId); StoragePoolVO currentPool = _storagePoolDao.findById(volume.getPoolId()); + DiskOfferingVO diskOffering = _diskOfferingDao.findById(volume.getDiskOfferingId()); if (pool != null) { // Check if pool is accessible from the destination host and disk offering with which the volume was // created is compliant with the pool type. if (_poolHostDao.findByPoolHost(pool.getId(), host.getId()) == null || pool.isLocal() != diskOffering.getUseLocalStorage()) { // Cannot find a pool for the volume. Throw an exception. throw new CloudRuntimeException("Cannot migrate volume " + volume + " to storage pool " + pool + " while migrating vm to host " + host + - ". Either the pool is not accessible from the " + "host or because of the offering with which the volume is created it cannot be placed on " + + ". Either the pool is not accessible from the host or because of the offering with which the volume is created it cannot be placed on " + "the given pool."); } else if (pool.getId() == currentPool.getId()) { - // If the pool to migrate too is the same as current pool, remove the volume from the list of - // volumes to be migrated. - volumeToPool.remove(volume); + // If the pool to migrate too is the same as current pool, the volume doesn't need to be migrated. + } else { + volumeToPoolObjectMap.put(volume, pool); } } else { // Find a suitable pool for the volume. Call the storage pool allocator to find the list of pools. @@ -1974,23 +1993,33 @@ private Map getPoolListForVolumesForMigration(VirtualMachin ExcludeList avoid = new ExcludeList(); boolean currentPoolAvailable = false; + List poolList = new ArrayList(); for (StoragePoolAllocator allocator : _storagePoolAllocators) { - List poolList = allocator.allocateToPool(diskProfile, profile, plan, avoid, StoragePoolAllocator.RETURN_UPTO_ALL); - if (poolList != null && !poolList.isEmpty()) { - // Volume needs to be migrated. Pick the first pool from the list. Add a mapping to migrate the - // volume to a pool only if it is required; that is the current pool on which the volume resides - // is not available on the destination host. - if (poolList.contains(currentPool)) { + List poolListFromAllocator = allocator.allocateToPool(diskProfile, profile, plan, avoid, StoragePoolAllocator.RETURN_UPTO_ALL); + if (poolListFromAllocator != null && !poolListFromAllocator.isEmpty()) { + poolList.addAll(poolListFromAllocator); + } + } + + if (poolList != null && !poolList.isEmpty()) { + // Volume needs to be migrated. Pick the first pool from the list. Add a mapping to migrate the + // volume to a pool only if it is required; that is the current pool on which the volume resides + // is not available on the destination host. + Iterator iter = poolList.iterator(); + while (iter.hasNext()) { + if (currentPool.getId() == iter.next().getId()) { currentPoolAvailable = true; - } else { - volumeToPool.put(volume, _storagePoolDao.findByUuid(poolList.get(0).getUuid())); + break; } + } - break; + if (!currentPoolAvailable) { + volumeToPoolObjectMap.put(volume, _storagePoolDao.findByUuid(poolList.get(0).getUuid())); } } - if (!currentPoolAvailable && !volumeToPool.containsKey(volume)) { + + if (!currentPoolAvailable && !volumeToPoolObjectMap.containsKey(volume)) { // Cannot find a pool for the volume. Throw an exception. throw new CloudRuntimeException("Cannot find a storage pool which is available for volume " + volume + " while migrating virtual machine " + profile.getVirtualMachine() + " to host " + host); @@ -1998,7 +2027,7 @@ private Map getPoolListForVolumesForMigration(VirtualMachin } } - return volumeToPool; + return volumeToPoolObjectMap; } private void moveVmToMigratingState(T vm, Long hostId, ItWorkVO work) throws ConcurrentOperationException { @@ -2028,7 +2057,7 @@ private void moveVmOutofMigratingStateOnSuccess(T vm, L } @Override - public void migrateWithStorage(String vmUuid, long srcHostId, long destHostId, Map volumeToPool) + public void migrateWithStorage(String vmUuid, long srcHostId, long destHostId, Map volumeToPool) throws ResourceUnavailableException, ConcurrentOperationException { AsyncJobExecutionContext jobContext = AsyncJobExecutionContext.getCurrentExecutionContext(); @@ -2072,7 +2101,7 @@ else if (jobException instanceof Throwable) } } - private void orchestrateMigrateWithStorage(String vmUuid, long srcHostId, long destHostId, Map volumeToPool) throws ResourceUnavailableException, + private void orchestrateMigrateWithStorage(String vmUuid, long srcHostId, long destHostId, Map volumeToPool) throws ResourceUnavailableException, ConcurrentOperationException { VMInstanceVO vm = _vmDao.findByUuid(vmUuid); @@ -2088,11 +2117,11 @@ private void orchestrateMigrateWithStorage(String vmUuid, long srcHostId, long d // Create a map of which volume should go in which storage pool. VirtualMachineProfile profile = new VirtualMachineProfileImpl(vm); - volumeToPool = getPoolListForVolumesForMigration(profile, destHost, volumeToPool); + Map volumeToPoolMap = getPoolListForVolumesForMigration(profile, destHost, volumeToPool); // If none of the volumes have to be migrated, fail the call. Administrator needs to make a call for migrating // a vm and not migrating a vm with storage. - if (volumeToPool.isEmpty()) { + if (volumeToPoolMap == null || volumeToPoolMap.isEmpty()) { throw new InvalidParameterValueException("Migration of the vm " + vm + "from host " + srcHost + " to destination host " + destHost + " doesn't involve migrating the volumes."); } @@ -2122,7 +2151,7 @@ private void orchestrateMigrateWithStorage(String vmUuid, long srcHostId, long d boolean migrated = false; try { // Migrate the vm and its volume. - volumeMgr.migrateVolumes(vm, to, srcHost, destHost, volumeToPool); + volumeMgr.migrateVolumes(vm, to, srcHost, destHost, volumeToPoolMap); // Put the vm back to running state. moveVmOutofMigratingStateOnSuccess(vm, destHost.getId(), work); @@ -2451,11 +2480,12 @@ private void orchestrateReboot(String vmUuid, Map vmMetadatum) { } VMInstanceVO vm = _vmDao.findVMByInstanceName(name); if (vm != null && vm.getType() == VirtualMachine.Type.User) { - // track platform info + boolean changed = false; UserVmVO userVm = _userVmDao.findById(vm.getId()); _userVmDao.loadDetails(userVm); - userVm.setDetail("platform", platform); + if ( userVm.details.containsKey("timeoffset")) { + userVm.details.remove("timeoffset"); + changed = true; + } + if (!userVm.details.containsKey("platform") || !userVm.details.get("platform").equals(platform)) { + userVm.setDetail("platform", platform); + changed = true; + } String pvdriver = "xenserver56"; if ( platform.contains("device_id")) { pvdriver = "xenserver61"; } - userVm.setDetail("hypervisortoolsversion", pvdriver); - _userVmDao.saveDetails(userVm); + if (!userVm.details.containsKey("hypervisortoolsversion") || !userVm.details.get("hypervisortoolsversion").equals(pvdriver)) { + userVm.setDetail("hypervisortoolsversion", pvdriver); + changed = true; + } + if ( changed ) { + _userVmDao.saveDetails(userVm); + } } } } - public void deltaSync(Map> newStates) { Map states = convertToInfos(newStates); @@ -3243,9 +3284,9 @@ protected class AgentVmInfo { @SuppressWarnings("unchecked") public AgentVmInfo(String name, VMInstanceVO vm, State state, String host) { - this.name = name; - this.state = state; - this.vm = vm; + name = name; + state = state; + vm = vm; hostUuid = host; } @@ -3422,7 +3463,7 @@ private NicProfile orchestrateAddVmToNetwork(VirtualMachine vm, Network network, long isDefault = (nic.isDefaultNic()) ? 1 : 0; // insert nic's Id into DB as resource_name UsageEventUtils.publishUsageEvent(EventTypes.EVENT_NETWORK_OFFERING_ASSIGN, vmVO.getAccountId(), vmVO.getDataCenterId(), vmVO.getId(), - Long.toString(nic.getId()), network.getNetworkOfferingId(), null, isDefault, VirtualMachine.class.getName(), vmVO.getUuid()); + Long.toString(nic.getId()), network.getNetworkOfferingId(), null, isDefault, VirtualMachine.class.getName(), vmVO.getUuid(), vm.isDisplay()); return nic; } else { s_logger.warn("Failed to plug nic to the vm " + vm + " in network " + network); @@ -3537,7 +3578,7 @@ private boolean orchestrateRemoveNicFromVm(VirtualMachine vm, Nic nic) throws Co s_logger.debug("Nic is unplugged successfully for vm " + vm + " in network " + network); long isDefault = (nic.isDefaultNic()) ? 1 : 0; UsageEventUtils.publishUsageEvent(EventTypes.EVENT_NETWORK_OFFERING_REMOVE, vm.getAccountId(), vm.getDataCenterId(), vm.getId(), - Long.toString(nic.getId()), network.getNetworkOfferingId(), null, isDefault, VirtualMachine.class.getName(), vm.getUuid()); + Long.toString(nic.getId()), network.getNetworkOfferingId(), null, isDefault, VirtualMachine.class.getName(), vm.getUuid(), vm.isDisplay()); } else { s_logger.warn("Failed to unplug nic for the vm " + vm + " from network " + network); return false; @@ -4100,7 +4141,7 @@ private void HandlePowerStateReport(String subject, String senderAddress, Object List pendingWorkJobs = _workJobDao.listPendingWorkJobs( VirtualMachine.Type.Instance, vmId); - if (pendingWorkJobs.size() == 0 || !_haMgr.hasPendingHaWork(vmId)) { + if (pendingWorkJobs.size() == 0 && !_haMgr.hasPendingHaWork(vmId)) { // there is no pending operation job VMInstanceVO vm = _vmDao.findById(vmId); if (vm != null) { @@ -4221,9 +4262,18 @@ private void handlePowerOffReportWithNoPendingJobsOnVM(VMInstanceVO vm) { case Stopped: case Migrating: s_logger.info("VM " + vm.getInstanceName() + " is at " + vm.getState() + " and we received a power-off report while there is no pending jobs on it"); + if(vm.isHaEnabled() && vm.getState() == State.Running && vm.getHypervisorType() != HypervisorType.VMware && vm.getHypervisorType() != HypervisorType.Hyperv) { + s_logger.info("Detected out-of-band stop of a HA enabled VM " + vm.getInstanceName() + ", will schedule restart"); + if(!_haMgr.hasPendingHaWork(vm.getId())) + _haMgr.scheduleRestart(vm, true); + else + s_logger.info("VM " + vm.getInstanceName() + " already has an pending HA task working on it"); + return; + } + VirtualMachineGuru vmGuru = getVmGuru(vm); VirtualMachineProfile profile = new VirtualMachineProfileImpl(vm); - sendStop(vmGuru, profile, true); + sendStop(vmGuru, profile, true, true); try { stateTransitTo(vm, VirtualMachine.Event.FollowAgentPowerOffReport, null); @@ -4406,8 +4456,9 @@ public VmStateSyncOutcome(final AsyncJob job, final PowerState desiredPowerState super(VirtualMachine.class, job, VmJobCheckInterval.value(), new Predicate() { @Override public boolean checkCondition() { - VMInstanceVO instance = _vmDao.findById(vmId); - if (instance.getPowerState() == desiredPowerState && (srcHostIdForMigration != null && srcHostIdForMigration.equals(instance.getPowerHostId()))) + AsyncJobVO jobVo = _entityMgr.findById(AsyncJobVO.class, job.getId()); + assert (jobVo != null); + if (jobVo == null || jobVo.getStatus() != JobInfo.Status.IN_PROGRESS) return true; return false; } @@ -4730,7 +4781,7 @@ public Object[] doInTransaction(TransactionStatus status) { public Outcome migrateVmWithStorageThroughJobQueue( final String vmUuid, final long srcHostId, final long destHostId, - final Map volumeToPool) { + final Map volumeToPool) { final CallContext context = CallContext.current(); final User user = context.getCallingUser(); diff --git a/engine/orchestration/src/com/cloud/vm/VmWorkMigrateWithStorage.java b/engine/orchestration/src/com/cloud/vm/VmWorkMigrateWithStorage.java index ee30c74abf..52fe9f2877 100644 --- a/engine/orchestration/src/com/cloud/vm/VmWorkMigrateWithStorage.java +++ b/engine/orchestration/src/com/cloud/vm/VmWorkMigrateWithStorage.java @@ -18,18 +18,15 @@ import java.util.Map; -import com.cloud.storage.StoragePool; -import com.cloud.storage.Volume; - public class VmWorkMigrateWithStorage extends VmWork { private static final long serialVersionUID = -5626053872453569165L; long srcHostId; long destHostId; - Map volumeToPool; + Map volumeToPool; public VmWorkMigrateWithStorage(long userId, long accountId, long vmId, String handlerName, long srcHostId, - long destHostId, Map volumeToPool) { + long destHostId, Map volumeToPool) { super(userId, accountId, vmId, handlerName); @@ -46,7 +43,7 @@ public long getDestHostId() { return destHostId; } - public Map getVolumeToPool() { + public Map getVolumeToPool() { return volumeToPool; } } diff --git a/engine/orchestration/src/org/apache/cloudstack/engine/orchestration/CloudOrchestrator.java b/engine/orchestration/src/org/apache/cloudstack/engine/orchestration/CloudOrchestrator.java index fc1b85c080..2b4995466b 100755 --- a/engine/orchestration/src/org/apache/cloudstack/engine/orchestration/CloudOrchestrator.java +++ b/engine/orchestration/src/org/apache/cloudstack/engine/orchestration/CloudOrchestrator.java @@ -45,7 +45,6 @@ import com.cloud.network.Network; import com.cloud.network.dao.NetworkDao; import com.cloud.network.dao.NetworkVO; -import com.cloud.offering.DiskOffering; import com.cloud.offering.DiskOfferingInfo; import com.cloud.service.ServiceOfferingVO; import com.cloud.service.dao.ServiceOfferingDao; @@ -181,14 +180,14 @@ public VirtualMachineEntity createVirtualMachine(String id, String owner, String // Else, a disk offering is optional, and if present will be used to create the data disk DiskOfferingInfo rootDiskOfferingInfo = new DiskOfferingInfo(); - LinkedHashMap dataDiskOfferings = new LinkedHashMap(); + List dataDiskOfferings = new ArrayList(); - ServiceOfferingVO offering = _serviceOfferingDao.findById(vm.getId(), vm.getServiceOfferingId()); + ServiceOfferingVO computeOffering = _serviceOfferingDao.findById(vm.getId(), vm.getServiceOfferingId()); - rootDiskOfferingInfo.setDiskOffering(offering); + rootDiskOfferingInfo.setDiskOffering(computeOffering); rootDiskOfferingInfo.setSize(rootDiskSize); - if (offering.isCustomizedIops() != null && offering.isCustomizedIops()) { + if (computeOffering.isCustomizedIops() != null && computeOffering.isCustomizedIops()) { Map userVmDetails = _userVmDetailsDao.listDetailsKeyPairs(vm.getId()); if (userVmDetails != null) { @@ -213,10 +212,28 @@ public VirtualMachineEntity createVirtualMachine(String id, String owner, String } _volumeMgr.validateVolumeSizeRange(size * 1024 * 1024 * 1024); } - dataDiskOfferings.put(diskOffering, size); + + DiskOfferingInfo dataDiskOfferingInfo = new DiskOfferingInfo(); + + dataDiskOfferingInfo.setDiskOffering(diskOffering); + dataDiskOfferingInfo.setSize(size); + + if (diskOffering.isCustomizedIops() != null && diskOffering.isCustomizedIops()) { + Map userVmDetails = _userVmDetailsDao.listDetailsKeyPairs(vm.getId()); + + if (userVmDetails != null) { + String minIops = userVmDetails.get("minIopsDo"); + String maxIops = userVmDetails.get("maxIopsDo"); + + dataDiskOfferingInfo.setMinIops(minIops != null && minIops.trim().length() > 0 ? Long.parseLong(minIops) : null); + dataDiskOfferingInfo.setMaxIops(maxIops != null && maxIops.trim().length() > 0 ? Long.parseLong(maxIops) : null); + } + } + + dataDiskOfferings.add(dataDiskOfferingInfo); } - _itMgr.allocate(vm.getInstanceName(), _templateDao.findById(new Long(templateId)), offering, rootDiskOfferingInfo, dataDiskOfferings, networkIpMap, plan, + _itMgr.allocate(vm.getInstanceName(), _templateDao.findById(new Long(templateId)), computeOffering, rootDiskOfferingInfo, dataDiskOfferings, networkIpMap, plan, hypervisorType); return vmEntity; @@ -234,13 +251,12 @@ public VirtualMachineEntity createVirtualMachineFromScratch(String id, String ow //load vm instance and offerings and call virtualMachineManagerImpl VMInstanceVO vm = _vmDao.findByUuid(id); - ServiceOfferingVO offering = _serviceOfferingDao.findById(vm.getId(), vm.getServiceOfferingId()); + ServiceOfferingVO computeOffering = _serviceOfferingDao.findById(vm.getId(), vm.getServiceOfferingId()); DiskOfferingInfo rootDiskOfferingInfo = new DiskOfferingInfo(); - rootDiskOfferingInfo.setDiskOffering(offering); + rootDiskOfferingInfo.setDiskOffering(computeOffering); - LinkedHashMap dataDiskOfferings = new LinkedHashMap(); Long diskOfferingId = vm.getDiskOfferingId(); if (diskOfferingId == null) { throw new InvalidParameterValueException("Installing from ISO requires a disk offering to be specified for the root disk."); @@ -261,6 +277,18 @@ public VirtualMachineEntity createVirtualMachineFromScratch(String id, String ow rootDiskOfferingInfo.setDiskOffering(diskOffering); rootDiskOfferingInfo.setSize(size); + if (diskOffering.isCustomizedIops() != null && diskOffering.isCustomizedIops()) { + Map userVmDetails = _userVmDetailsDao.listDetailsKeyPairs(vm.getId()); + + if (userVmDetails != null) { + String minIops = userVmDetails.get("minIopsDo"); + String maxIops = userVmDetails.get("maxIopsDo"); + + rootDiskOfferingInfo.setMinIops(minIops != null && minIops.trim().length() > 0 ? Long.parseLong(minIops) : null); + rootDiskOfferingInfo.setMaxIops(maxIops != null && maxIops.trim().length() > 0 ? Long.parseLong(maxIops) : null); + } + } + LinkedHashMap> networkIpMap = new LinkedHashMap>(); for (String uuid : networkNicMap.keySet()) { NetworkVO network = _networkDao.findByUuid(uuid); @@ -271,7 +299,7 @@ public VirtualMachineEntity createVirtualMachineFromScratch(String id, String ow HypervisorType hypervisorType = HypervisorType.valueOf(hypervisor); - _itMgr.allocate(vm.getInstanceName(), _templateDao.findById(new Long(isoId)), offering, rootDiskOfferingInfo, dataDiskOfferings, networkIpMap, plan, hypervisorType); + _itMgr.allocate(vm.getInstanceName(), _templateDao.findById(new Long(isoId)), computeOffering, rootDiskOfferingInfo, new ArrayList(), networkIpMap, plan, hypervisorType); return vmEntity; } diff --git a/engine/orchestration/src/org/apache/cloudstack/engine/orchestration/NetworkOrchestrator.java b/engine/orchestration/src/org/apache/cloudstack/engine/orchestration/NetworkOrchestrator.java index 6aa1e36ccd..96dafe947d 100755 --- a/engine/orchestration/src/org/apache/cloudstack/engine/orchestration/NetworkOrchestrator.java +++ b/engine/orchestration/src/org/apache/cloudstack/engine/orchestration/NetworkOrchestrator.java @@ -40,7 +40,6 @@ import org.apache.log4j.Logger; import org.apache.cloudstack.acl.ControlledEntity.ACLType; -import org.apache.cloudstack.acl.IAMEntityType; import org.apache.cloudstack.api.ApiConstants; import org.apache.cloudstack.context.CallContext; import org.apache.cloudstack.engine.orchestration.service.NetworkOrchestrationService; @@ -668,6 +667,7 @@ public void doInTransactionWithoutResult(TransactionStatus status) { NetworkVO vo = new NetworkVO(id, network, offering.getId(), guru.getName(), owner.getDomainId(), owner.getId(), relatedFile, name, displayText, predefined .getNetworkDomain(), offering.getGuestType(), plan.getDataCenterId(), plan.getPhysicalNetworkId(), aclType, offering.getSpecifyIpRanges(), vpcId); vo.setDisplayNetwork(isDisplayNetworkEnabled == null ? true : isDisplayNetworkEnabled); + vo.setStrechedL2Network(offering.getSupportsStrechedL2()); networks.add(_networksDao.persist(vo, vo.getGuestType() == Network.GuestType.Isolated, finalizeServicesAndProvidersForNetwork(offering, plan.getPhysicalNetworkId()))); @@ -675,7 +675,7 @@ public void doInTransactionWithoutResult(TransactionStatus status) { _networksDao.addDomainToNetwork(id, domainId, subdomainAccess == null ? true : subdomainAccess); //send event for storing the domain wide resource access Map params = new HashMap(); - params.put(ApiConstants.ENTITY_TYPE, IAMEntityType.Network); + params.put(ApiConstants.ENTITY_TYPE, Network.class); params.put(ApiConstants.ENTITY_ID, id); params.put(ApiConstants.DOMAIN_ID, domainId); params.put(ApiConstants.SUBDOMAIN_ACCESS, subdomainAccess == null ? true : subdomainAccess); @@ -2245,7 +2245,7 @@ public void doInTransactionWithoutResult(TransactionStatus status) { _networkAccountDao.remove(networkAccount.getId()); // remove its related ACL permission - Pair networkMsg = new Pair(IAMEntityType.Network, networkFinal.getId()); + Pair, Long> networkMsg = new Pair, Long>(Network.class, networkFinal.getId()); _messageBus.publish(_name, EntityManager.MESSAGE_REMOVE_ENTITY_EVENT, PublishScope.LOCAL, networkMsg); } diff --git a/engine/orchestration/src/org/apache/cloudstack/engine/orchestration/VolumeOrchestrator.java b/engine/orchestration/src/org/apache/cloudstack/engine/orchestration/VolumeOrchestrator.java index f3753a7417..064ffca6db 100644 --- a/engine/orchestration/src/org/apache/cloudstack/engine/orchestration/VolumeOrchestrator.java +++ b/engine/orchestration/src/org/apache/cloudstack/engine/orchestration/VolumeOrchestrator.java @@ -35,8 +35,10 @@ import org.apache.cloudstack.engine.orchestration.service.VolumeOrchestrationService; import org.apache.cloudstack.engine.subsystem.api.storage.ChapInfo; import org.apache.cloudstack.engine.subsystem.api.storage.DataStore; +import org.apache.cloudstack.engine.subsystem.api.storage.DataStoreDriver; import org.apache.cloudstack.engine.subsystem.api.storage.DataStoreManager; import org.apache.cloudstack.engine.subsystem.api.storage.PrimaryDataStore; +import org.apache.cloudstack.engine.subsystem.api.storage.PrimaryDataStoreDriver; import org.apache.cloudstack.engine.subsystem.api.storage.SnapshotDataFactory; import org.apache.cloudstack.engine.subsystem.api.storage.SnapshotInfo; import org.apache.cloudstack.engine.subsystem.api.storage.SnapshotService; @@ -109,10 +111,12 @@ import com.cloud.utils.fsm.NoTransitionException; import com.cloud.utils.fsm.StateMachine2; import com.cloud.vm.DiskProfile; +import com.cloud.vm.UserVmVO; import com.cloud.vm.VirtualMachine; import com.cloud.vm.VirtualMachine.State; import com.cloud.vm.VirtualMachineProfile; import com.cloud.vm.VirtualMachineProfileImpl; +import com.cloud.vm.dao.UserVmDao; public class VolumeOrchestrator extends ManagerBase implements VolumeOrchestrationService, Configurable { private static final Logger s_logger = Logger.getLogger(VolumeOrchestrator.class); @@ -149,6 +153,8 @@ public class VolumeOrchestrator extends ManagerBase implements VolumeOrchestrati HostDao _hostDao; @Inject SnapshotService _snapshotSrv; + @Inject + protected UserVmDao _userVmDao; private final StateMachine2 _volStateMachine; protected List _storagePoolAllocators; @@ -569,14 +575,17 @@ protected DiskProfile toDiskProfile(Volume vol, DiskOffering offering) { } @Override - public DiskProfile allocateRawVolume(Type type, String name, DiskOffering offering, Long size, VirtualMachine vm, VirtualMachineTemplate template, Account owner) { + public DiskProfile allocateRawVolume(Type type, String name, DiskOffering offering, Long size, Long minIops, Long maxIops, VirtualMachine vm, VirtualMachineTemplate template, Account owner) { if (size == null) { size = offering.getDiskSize(); } else { size = (size * 1024 * 1024 * 1024); } - VolumeVO vol = new VolumeVO(type, name, vm.getDataCenterId(), owner.getDomainId(), owner.getId(), offering.getId(), size, offering.getMinIops(), offering.getMaxIops(), - null); + + minIops = minIops != null ? minIops : offering.getMinIops(); + maxIops = maxIops != null ? maxIops : offering.getMaxIops(); + + VolumeVO vol = new VolumeVO(type, name, vm.getDataCenterId(), owner.getDomainId(), owner.getId(), offering.getId(), size, minIops, maxIops, null); if (vm != null) { vol.setInstanceId(vm.getId()); } @@ -589,6 +598,11 @@ public DiskProfile allocateRawVolume(Type type, String name, DiskOffering offeri if (template.getFormat() == ImageFormat.ISO) { vol.setIsoId(template.getId()); } + // display flag matters only for the User vms + if (vm.getType() == VirtualMachine.Type.User) { + UserVmVO userVm = _userVmDao.findById(vm.getId()); + vol.setDisplayVolume(userVm.isDisplayVm()); + } vol.setFormat(getSupportedImageFormatForCluster(vm.getHypervisorType())); vol = _volsDao.persist(vol); @@ -596,10 +610,10 @@ public DiskProfile allocateRawVolume(Type type, String name, DiskOffering offeri // Save usage event and update resource count for user vm volumes if (vm.getType() == VirtualMachine.Type.User) { UsageEventUtils.publishUsageEvent(EventTypes.EVENT_VOLUME_CREATE, vol.getAccountId(), vol.getDataCenterId(), vol.getId(), vol.getName(), offering.getId(), null, size, - Volume.class.getName(), vol.getUuid()); + Volume.class.getName(), vol.getUuid(), vol.isDisplayVolume()); - _resourceLimitMgr.incrementResourceCount(vm.getAccountId(), ResourceType.volume); - _resourceLimitMgr.incrementResourceCount(vm.getAccountId(), ResourceType.primary_storage, new Long(vol.getSize())); + _resourceLimitMgr.incrementResourceCount(vm.getAccountId(), ResourceType.volume, vol.isDisplayVolume()); + _resourceLimitMgr.incrementResourceCount(vm.getAccountId(), ResourceType.primary_storage, vol.isDisplayVolume(), new Long(vol.getSize())); } return toDiskProfile(vol, offering); } @@ -609,8 +623,14 @@ public DiskProfile allocateTemplatedVolume(Type type, String name, DiskOffering assert (template.getFormat() != ImageFormat.ISO) : "ISO is not a template really...."; Long size = _tmpltMgr.getTemplateSize(template.getId(), vm.getDataCenterId()); - if (rootDisksize != null) { - size = (rootDisksize * 1024 * 1024 * 1024); + if (rootDisksize != null ) { + rootDisksize = rootDisksize * 1024 * 1024 * 1024; + if (rootDisksize > size) { + s_logger.debug("Using root disk size of " + rootDisksize + " for volume " + name); + size = rootDisksize; + } else { + s_logger.debug("Using root disk size of " + size + " for volume " + name + "since specified root disk size of " + rootDisksize + " is smaller than template"); + } } minIops = minIops != null ? minIops : offering.getMinIops(); @@ -633,6 +653,12 @@ public DiskProfile allocateTemplatedVolume(Type type, String name, DiskOffering vol.setDeviceId(1l); } + if (vm.getType() == VirtualMachine.Type.User) { + UserVmVO userVm = _userVmDao.findById(vm.getId()); + vol.setDisplayVolume(userVm.isDisplayVm()); + } + + vol = _volsDao.persist(vol); // Create event and update resource count for volumes if vm is a user vm @@ -643,10 +669,10 @@ public DiskProfile allocateTemplatedVolume(Type type, String name, DiskOffering offeringId = offering.getId(); UsageEventUtils.publishUsageEvent(EventTypes.EVENT_VOLUME_CREATE, vol.getAccountId(), vol.getDataCenterId(), vol.getId(), vol.getName(), offeringId, null, size, - Volume.class.getName(), vol.getUuid()); + Volume.class.getName(), vol.getUuid(), vol.isDisplayVolume()); - _resourceLimitMgr.incrementResourceCount(vm.getAccountId(), ResourceType.volume); - _resourceLimitMgr.incrementResourceCount(vm.getAccountId(), ResourceType.primary_storage, new Long(vol.getSize())); + _resourceLimitMgr.incrementResourceCount(vm.getAccountId(), ResourceType.volume, vol.isDisplayVolume()); + _resourceLimitMgr.incrementResourceCount(vm.getAccountId(), ResourceType.primary_storage, vol.isDisplayVolume(), new Long(vol.getSize())); } return toDiskProfile(vol, offering); } @@ -661,16 +687,29 @@ private ImageFormat getSupportedImageFormatForCluster(HypervisorType hyperType) } else if (hyperType == HypervisorType.Ovm) { return ImageFormat.RAW; } else if (hyperType == HypervisorType.Hyperv) { - return ImageFormat.VHD; + return ImageFormat.VHDX; } else { return null; } } + private boolean isSupportedImageFormatForCluster(VolumeInfo volume, HypervisorType rootDiskHyperType) { + ImageFormat volumeFormat = volume.getFormat(); + if (rootDiskHyperType == HypervisorType.Hyperv) { + if (volumeFormat.equals(ImageFormat.VHDX) || volumeFormat.equals(ImageFormat.VHD)) { + return true; + } else { + return false; + } + } else { + return volume.getFormat().equals(getSupportedImageFormatForCluster(rootDiskHyperType)); + } + } + private VolumeInfo copyVolume(StoragePool rootDiskPool, VolumeInfo volume, VirtualMachine vm, VirtualMachineTemplate rootDiskTmplt, DataCenter dcVO, Pod pod, DiskOffering diskVO, ServiceOffering svo, HypervisorType rootDiskHyperType) throws NoTransitionException { - if (!volume.getFormat().equals(getSupportedImageFormatForCluster(rootDiskHyperType))) { + if (!isSupportedImageFormatForCluster(volume, rootDiskHyperType)) { throw new InvalidParameterValueException("Failed to attach volume to VM since volumes format " + volume.getFormat().getFileExtension() + " is not compatible with the vm hypervisor type"); } @@ -807,6 +846,15 @@ public void doInTransactionWithoutResult(TransactionStatus status) { } } + @Override + public void disconnectVolumeFromHost(VolumeInfo volumeInfo, Host host, DataStore dataStore) { + DataStoreDriver dataStoreDriver = dataStore != null ? dataStore.getDriver() : null; + + if (dataStoreDriver instanceof PrimaryDataStoreDriver) { + ((PrimaryDataStoreDriver)dataStoreDriver).disconnectVolumeFromHost(volumeInfo, host, dataStore); + } + } + @Override public void disconnectVolumesFromHost(long vmId, long hostId) { HostVO host = _hostDao.findById(hostId); @@ -1117,7 +1165,12 @@ private Pair recreateVolume(VolumeVO vol, VirtualMachinePro future = volService.createVolumeAsync(volume, destPool); } else { - TemplateInfo templ = tmplFactory.getTemplate(templateId, DataStoreRole.Image); + + TemplateInfo templ = tmplFactory.getReadyTemplateOnImageStore(templateId, dest.getDataCenter().getId()); + if (templ == null) { + s_logger.debug("can't find ready template: " + templateId + " for data center " + dest.getDataCenter().getId()); + throw new CloudRuntimeException("can't find ready template: " + templateId + " for data center " + dest.getDataCenter().getId()); + } PrimaryDataStore primaryDataStore = (PrimaryDataStore)destPool; @@ -1151,7 +1204,7 @@ private Pair recreateVolume(VolumeVO vol, VirtualMachinePro StoragePoolVO storagePool = _storagePoolDao.findById(destPool.getId()); - if (newVol.getVolumeType() == Type.DATADISK && storagePool.isManaged()) { + if (storagePool.isManaged()) { long hostId = vm.getVirtualMachine().getHostId(); Host host = _hostDao.findById(hostId); diff --git a/engine/orchestration/test/com/cloud/vm/VirtualMachineManagerImplTest.java b/engine/orchestration/test/com/cloud/vm/VirtualMachineManagerImplTest.java index 49b2fc5fb1..c39c6d1b41 100644 --- a/engine/orchestration/test/com/cloud/vm/VirtualMachineManagerImplTest.java +++ b/engine/orchestration/test/com/cloud/vm/VirtualMachineManagerImplTest.java @@ -84,10 +84,8 @@ import com.cloud.offering.ServiceOffering; import com.cloud.service.ServiceOfferingVO; import com.cloud.storage.DiskOfferingVO; -import com.cloud.storage.StoragePool; import com.cloud.storage.StoragePoolHostVO; import com.cloud.storage.VMTemplateVO; -import com.cloud.storage.Volume; import com.cloud.storage.VolumeVO; import com.cloud.storage.dao.DiskOfferingDao; import com.cloud.storage.dao.StoragePoolHostDao; @@ -196,7 +194,7 @@ public class VirtualMachineManagerImplTest { @Mock HostVO _destHostMock; @Mock - Map _volumeToPoolMock; + Map _volumeToPoolMock; @Mock EntityManager _entityMgr; @Mock @@ -355,11 +353,13 @@ private void initializeMockConfigForMigratingVmWithVolumes() throws OperationTim // Mock the disk offering and pool objects for a volume. when(_volumeMock.getDiskOfferingId()).thenReturn(5L); when(_volumeMock.getPoolId()).thenReturn(200L); + when(_volumeMock.getId()).thenReturn(5L); when(_diskOfferingDao.findById(anyLong())).thenReturn(_diskOfferingMock); - when(_storagePoolDao.findById(anyLong())).thenReturn(_srcStoragePoolMock); + when(_storagePoolDao.findById(200L)).thenReturn(_srcStoragePoolMock); + when(_storagePoolDao.findById(201L)).thenReturn(_destStoragePoolMock); // Mock the volume to pool mapping. - when(_volumeToPoolMock.get(_volumeMock)).thenReturn(_destStoragePoolMock); + when(_volumeToPoolMock.get(5L)).thenReturn(201L); when(_destStoragePoolMock.getId()).thenReturn(201L); when(_srcStoragePoolMock.getId()).thenReturn(200L); when(_destStoragePoolMock.isLocal()).thenReturn(false); @@ -465,12 +465,12 @@ public void testSendStopWithOkAnswer() throws Exception { VirtualMachineGuru guru = mock(VirtualMachineGuru.class); VirtualMachine vm = mock(VirtualMachine.class); VirtualMachineProfile profile = mock(VirtualMachineProfile.class); - StopAnswer answer = new StopAnswer(new StopCommand(vm, false), "ok", true); + StopAnswer answer = new StopAnswer(new StopCommand(vm, false, false), "ok", true); when(profile.getVirtualMachine()).thenReturn(vm); when(vm.getHostId()).thenReturn(1L); when(_agentMgr.send(anyLong(), (Command)any())).thenReturn(answer); - boolean actual = _vmMgr.sendStop(guru, profile, false); + boolean actual = _vmMgr.sendStop(guru, profile, false, false); Assert.assertTrue(actual); } @@ -480,12 +480,12 @@ public void testSendStopWithFailAnswer() throws Exception { VirtualMachineGuru guru = mock(VirtualMachineGuru.class); VirtualMachine vm = mock(VirtualMachine.class); VirtualMachineProfile profile = mock(VirtualMachineProfile.class); - StopAnswer answer = new StopAnswer(new StopCommand(vm, false), "fail", false); + StopAnswer answer = new StopAnswer(new StopCommand(vm, false, false), "fail", false); when(profile.getVirtualMachine()).thenReturn(vm); when(vm.getHostId()).thenReturn(1L); when(_agentMgr.send(anyLong(), (Command)any())).thenReturn(answer); - boolean actual = _vmMgr.sendStop(guru, profile, false); + boolean actual = _vmMgr.sendStop(guru, profile, false, false); Assert.assertFalse(actual); } @@ -499,7 +499,7 @@ public void testSendStopWithNullAnswer() throws Exception { when(vm.getHostId()).thenReturn(1L); when(_agentMgr.send(anyLong(), (Command)any())).thenReturn(null); - boolean actual = _vmMgr.sendStop(guru, profile, false); + boolean actual = _vmMgr.sendStop(guru, profile, false, false); Assert.assertFalse(actual); } diff --git a/engine/schema/resources/META-INF/cloudstack/core/spring-engine-schema-core-daos-context.xml b/engine/schema/resources/META-INF/cloudstack/core/spring-engine-schema-core-daos-context.xml index 489b37d04b..2ef0d206a6 100644 --- a/engine/schema/resources/META-INF/cloudstack/core/spring-engine-schema-core-daos-context.xml +++ b/engine/schema/resources/META-INF/cloudstack/core/spring-engine-schema-core-daos-context.xml @@ -195,6 +195,7 @@ + @@ -221,6 +222,7 @@ + @@ -258,7 +260,6 @@ - @@ -337,5 +338,8 @@ + + + diff --git a/engine/schema/src/com/cloud/event/EventVO.java b/engine/schema/src/com/cloud/event/EventVO.java index 3ae46d6244..9be37ddb96 100644 --- a/engine/schema/src/com/cloud/event/EventVO.java +++ b/engine/schema/src/com/cloud/event/EventVO.java @@ -29,8 +29,6 @@ import javax.persistence.Table; import javax.persistence.Transient; -import org.apache.cloudstack.acl.IAMEntityType; - import com.cloud.utils.db.GenericDao; @Entity @@ -223,7 +221,7 @@ public void setDisplay(boolean display) { } @Override - public IAMEntityType getEntityType() { - return IAMEntityType.Event; + public Class getEntityType() { + return Event.class; } } diff --git a/engine/schema/src/com/cloud/gpu/VGPUTypesVO.java b/engine/schema/src/com/cloud/gpu/VGPUTypesVO.java index 586a0c9279..fa6674c2c7 100644 --- a/engine/schema/src/com/cloud/gpu/VGPUTypesVO.java +++ b/engine/schema/src/com/cloud/gpu/VGPUTypesVO.java @@ -33,22 +33,55 @@ public class VGPUTypesVO implements InternalIdentity { @Column(name="id") private long id; + @Column(name="gpu_group_id") + private long gpuGroupId; + @Column(name="vgpu_type") private String vgpuType; - @Column(name="gpu_group_id") - private long gpuGroupId; + @Column(name="video_ram") + private long videoRam; + + @Column(name="max_heads") + private long maxHeads; - @Column(name="remaining_vm_capacity") + @Column(name="max_resolution_x") + private long maxResolutionX; + + @Column(name="max_resolution_y") + private long maxResolutionY; + + @Column(name="max_vgpu_per_pgpu") + private long maxVgpuPerPgpu; + + @Column(name="remaining_capacity") private long remainingCapacity; + @Column(name="max_capacity") + private long maxCapacity; + protected VGPUTypesVO() { } - public VGPUTypesVO(String vgpuType, long gpuGroupId, long remainingCapacity) { - this.vgpuType = vgpuType; + public VGPUTypesVO(long gpuGroupId, String vgpuType, long videoRam, long maxHeads, long maxResolutionX, long maxResolutionY, long maxVgpuPerPgpu, + long remainingCapacity, long maxCapacity) { this.gpuGroupId = gpuGroupId; + this.vgpuType = vgpuType; + this.videoRam = videoRam; + this.maxHeads = maxHeads; + this.maxResolutionX = maxResolutionX; + this.maxResolutionY = maxResolutionY; + this.maxVgpuPerPgpu = maxVgpuPerPgpu; this.remainingCapacity = remainingCapacity; + this.maxCapacity = maxCapacity; + } + + public long getGpuGroupId() { + return gpuGroupId; + } + + public void setGpuGroupId(long gpuGroupId) { + this.gpuGroupId = gpuGroupId; } public String getVgpuType() { @@ -59,12 +92,44 @@ public void setVgpuType(String vgpuType) { this.vgpuType = vgpuType; } - public long getGpuGroupId() { - return gpuGroupId; + public long getVideoRam() { + return videoRam; } - public void setGpuGroupId(long gpuGroupId) { - this.gpuGroupId = gpuGroupId; + public void setVideoRam(long videoRam) { + this.videoRam = videoRam; + } + + public long getMaxHeads() { + return maxHeads; + } + + public void setMaxHeads(long maxHeads) { + this.maxHeads = maxHeads; + } + + public long getMaxResolutionX() { + return maxResolutionX; + } + + public void setMaxResolutionX(long maxResolutionX) { + this.maxResolutionX = maxResolutionX; + } + + public long getMaxResolutionY() { + return maxResolutionY; + } + + public void setMaxResolutionY(long maxResolutionY) { + this.maxResolutionY = maxResolutionY; + } + + public long getMaxVgpuPerPgpu() { + return maxVgpuPerPgpu; + } + + public void setMaxVgpuPerPgpu(long maxVgpuPerPgpu) { + this.maxVgpuPerPgpu = maxVgpuPerPgpu; } public long getRemainingCapacity() { @@ -75,6 +140,14 @@ public void setRemainingCapacity(long remainingCapacity) { this.remainingCapacity = remainingCapacity; } + public long getMaxCapacity() { + return maxCapacity; + } + + public void setMaxCapacity(long maxCapacity) { + this.maxCapacity = maxCapacity; + } + @Override public long getId() { return id; diff --git a/engine/schema/src/com/cloud/gpu/dao/HostGpuGroupsDao.java b/engine/schema/src/com/cloud/gpu/dao/HostGpuGroupsDao.java index 5864144397..8e4f2f742a 100644 --- a/engine/schema/src/com/cloud/gpu/dao/HostGpuGroupsDao.java +++ b/engine/schema/src/com/cloud/gpu/dao/HostGpuGroupsDao.java @@ -24,7 +24,7 @@ public interface HostGpuGroupsDao extends GenericDao { /** - * Find host device by hostId and PCI ID + * Find host device by hostId and groupName * @param hostId the host * @param groupName GPU group * @return HostGpuGroupsVO diff --git a/engine/schema/src/com/cloud/gpu/dao/VGPUTypesDao.java b/engine/schema/src/com/cloud/gpu/dao/VGPUTypesDao.java index 2872cfda88..94d97c0073 100644 --- a/engine/schema/src/com/cloud/gpu/dao/VGPUTypesDao.java +++ b/engine/schema/src/com/cloud/gpu/dao/VGPUTypesDao.java @@ -19,30 +19,40 @@ import java.util.HashMap; import java.util.List; +import com.cloud.agent.api.VgpuTypesInfo; import com.cloud.gpu.VGPUTypesVO; import com.cloud.utils.db.GenericDao; public interface VGPUTypesDao extends GenericDao { - /** - * Find VGPU types by group Id - * @param groupId of the GPU group - * @return list of VGPUTypesVO - */ - List listByGroupId(long groupId); + /** + * List zonewide/podwide/clusterwide GPU card capacities. + * @param zoneId + * @param podId + * @param clusterId + * @return Custom Query result + */ + List listGPUCapacities(Long zoneId, Long podId, Long clusterId); - /** - * Find VGPU type by group Id and VGPU type - * @param groupId of the GPU group - * @param vgpuType name of VGPU type - * @return VGPUTypesVO - */ - VGPUTypesVO findByGroupIdVGPUType(long groupId, String vgpuType); + /** + * Find VGPU types by group Id + * @param groupId of the GPU group + * @return list of VGPUTypesVO + */ + List listByGroupId(long groupId); - /** - * Save the list of enabled VGPU types - * @param hostId the host - * @param groupDetails with enabled VGPU types - */ - void persist(long hostId, HashMap> groupDetails); + /** + * Find VGPU type by group Id and VGPU type + * @param groupId of the GPU group + * @param vgpuType name of VGPU type + * @return VGPUTypesVO + */ + VGPUTypesVO findByGroupIdVGPUType(long groupId, String vgpuType); + + /** + * Save the list of enabled VGPU types + * @param hostId the host + * @param groupDetails with enabled VGPU types + */ + void persist(long hostId, HashMap> groupDetails); } diff --git a/engine/schema/src/com/cloud/gpu/dao/VGPUTypesDaoImpl.java b/engine/schema/src/com/cloud/gpu/dao/VGPUTypesDaoImpl.java index 7cc83cc9eb..96e3a6277f 100644 --- a/engine/schema/src/com/cloud/gpu/dao/VGPUTypesDaoImpl.java +++ b/engine/schema/src/com/cloud/gpu/dao/VGPUTypesDaoImpl.java @@ -16,6 +16,10 @@ //under the License. package com.cloud.gpu.dao; +import java.sql.PreparedStatement; +import java.sql.ResultSet; +import java.sql.SQLException; +import java.util.ArrayList; import java.util.HashMap; import java.util.Iterator; import java.util.List; @@ -27,11 +31,14 @@ import org.apache.log4j.Logger; import org.springframework.stereotype.Component; +import com.cloud.agent.api.VgpuTypesInfo; import com.cloud.gpu.HostGpuGroupsVO; import com.cloud.gpu.VGPUTypesVO; import com.cloud.utils.db.GenericDaoBase; import com.cloud.utils.db.SearchBuilder; import com.cloud.utils.db.SearchCriteria; +import com.cloud.utils.db.TransactionLegacy; +import com.cloud.utils.exception.CloudRuntimeException; @Component @Local(value = VGPUTypesDao.class) @@ -40,11 +47,14 @@ public class VGPUTypesDaoImpl extends GenericDaoBase implemen private final SearchBuilder _searchByGroupId; private final SearchBuilder _searchByGroupIdVGPUType; - // private final SearchBuilder _searchByHostId; - // private final SearchBuilder _searchForStaleEntries; @Inject protected HostGpuGroupsDao _hostGpuGroupsDao; + private static final String LIST_ZONE_POD_CLUSTER_WIDE_GPU_CAPACITIES = + "SELECT host_gpu_groups.group_name, vgpu_type, max_vgpu_per_pgpu, SUM(remaining_capacity) AS remaining_capacity, SUM(max_capacity) AS total_capacity FROM" + + " `cloud`.`vgpu_types` INNER JOIN `cloud`.`host_gpu_groups` ON vgpu_types.gpu_group_id = host_gpu_groups.id INNER JOIN `cloud`.`host`" + + " ON host_gpu_groups.host_id = host.id WHERE host.type = 'Routing' AND host.data_center_id = ?"; + public VGPUTypesDaoImpl() { _searchByGroupId = createSearchBuilder(); @@ -57,6 +67,47 @@ public VGPUTypesDaoImpl() { _searchByGroupIdVGPUType.done(); } + @Override + public List listGPUCapacities(Long dcId, Long podId, Long clusterId) { + StringBuilder finalQuery = new StringBuilder(); + TransactionLegacy txn = TransactionLegacy.currentTxn(); + PreparedStatement pstmt = null; + List resourceIdList = new ArrayList(); + ArrayList result = new ArrayList(); + + resourceIdList.add(dcId); + finalQuery.append(LIST_ZONE_POD_CLUSTER_WIDE_GPU_CAPACITIES); + + if (podId != null) { + finalQuery.append(" AND host.pod_id = ?"); + resourceIdList.add(podId); + } + + if (clusterId != null) { + finalQuery.append(" AND host.cluster_id = ?"); + resourceIdList.add(clusterId); + } + finalQuery.append(" GROUP BY host_gpu_groups.group_name, vgpu_type"); + + try { + pstmt = txn.prepareAutoCloseStatement(finalQuery.toString()); + for (int i = 0; i < resourceIdList.size(); i++) { + pstmt.setLong(1 + i, resourceIdList.get(i)); + } + ResultSet rs = pstmt.executeQuery(); + while (rs.next()) { + + VgpuTypesInfo gpuCapacity = new VgpuTypesInfo(rs.getString(1), rs.getString(2), null, null, null, null, rs.getLong(3), rs.getLong(4), rs.getLong(5)); + result.add(gpuCapacity); + } + return result; + } catch (SQLException e) { + throw new CloudRuntimeException("DB Exception on: " + finalQuery, e); + } catch (Throwable e) { + throw new CloudRuntimeException("Caught: " + finalQuery, e); + } + } + @Override public List listByGroupId(long groupId) { SearchCriteria sc = _searchByGroupId.create(); @@ -73,20 +124,23 @@ public VGPUTypesVO findByGroupIdVGPUType(long groupId, String vgpuType) { } @Override - public void persist(long hostId, HashMap> groupDetails) { - Iterator>> it1 = groupDetails.entrySet().iterator(); + public void persist(long hostId, HashMap> groupDetails) { + Iterator>> it1 = groupDetails.entrySet().iterator(); while (it1.hasNext()) { - Entry> entry = it1.next(); + Entry> entry = it1.next(); HostGpuGroupsVO gpuGroup = _hostGpuGroupsDao.findByHostIdGroupName(hostId, entry.getKey()); - HashMap values = entry.getValue(); - Iterator> it2 = values.entrySet().iterator(); + HashMap values = entry.getValue(); + Iterator> it2 = values.entrySet().iterator(); while (it2.hasNext()) { - Entry record = it2.next(); + Entry record = it2.next(); + VgpuTypesInfo details = record.getValue(); VGPUTypesVO vgpuType = null; if ((vgpuType = findByGroupIdVGPUType(gpuGroup.getId(), record.getKey())) == null) { - persist(new VGPUTypesVO(record.getKey(), gpuGroup.getId(), record.getValue())); + persist(new VGPUTypesVO(gpuGroup.getId(), record.getKey(), details.getVideoRam(), details.getMaxHeads(), details.getMaxResolutionX(), + details.getMaxResolutionY(), details.getMaxVpuPerGpu(), details.getRemainingCapacity(), details.getMaxCapacity())); } else { - vgpuType.setRemainingCapacity(record.getValue()); + vgpuType.setRemainingCapacity(details.getRemainingCapacity()); + vgpuType.setMaxCapacity(details.getMaxCapacity()); update(vgpuType.getId(), vgpuType); } } diff --git a/engine/schema/src/com/cloud/host/HostVO.java b/engine/schema/src/com/cloud/host/HostVO.java index 25cc9544da..4af8fb73d8 100755 --- a/engine/schema/src/com/cloud/host/HostVO.java +++ b/engine/schema/src/com/cloud/host/HostVO.java @@ -38,6 +38,7 @@ import javax.persistence.TemporalType; import javax.persistence.Transient; +import com.cloud.agent.api.VgpuTypesInfo; import com.cloud.hypervisor.Hypervisor.HypervisorType; import com.cloud.resource.ResourceState; import com.cloud.storage.Storage.StoragePoolType; @@ -156,7 +157,7 @@ public class HostVO implements Host { // This value is only for saving and current cannot be loaded. @Transient - HashMap> groupDetails = new HashMap>(); + HashMap> groupDetails = new HashMap>(); @Override public String getStorageIpAddressDeux() { @@ -318,11 +319,11 @@ public void setHostTags(List hostTags) { this.hostTags = hostTags; } - public HashMap> getGpuGroupDetails() { + public HashMap> getGpuGroupDetails() { return groupDetails; } - public void setGpuGroups(HashMap> groupDetails) { + public void setGpuGroups(HashMap> groupDetails) { this.groupDetails = groupDetails; } diff --git a/engine/schema/src/com/cloud/host/dao/HostDaoImpl.java b/engine/schema/src/com/cloud/host/dao/HostDaoImpl.java index c2a9826405..4d7e83de59 100755 --- a/engine/schema/src/com/cloud/host/dao/HostDaoImpl.java +++ b/engine/schema/src/com/cloud/host/dao/HostDaoImpl.java @@ -34,6 +34,7 @@ import org.apache.log4j.Logger; import org.springframework.stereotype.Component; +import com.cloud.agent.api.VgpuTypesInfo; import com.cloud.cluster.agentlb.HostTransferMapVO; import com.cloud.cluster.agentlb.dao.HostTransferMapDao; import com.cloud.dc.ClusterVO; @@ -782,7 +783,7 @@ protected void saveHostTags(HostVO host) { } protected void saveGpuRecords(HostVO host) { - HashMap> groupDetails = host.getGpuGroupDetails(); + HashMap> groupDetails = host.getGpuGroupDetails(); if (groupDetails != null) { // Create/Update GPU group entries _hostGpuGroupsDao.persist(host.getId(), new ArrayList(groupDetails.keySet())); @@ -899,7 +900,8 @@ public long countRoutingHostsByDataCenter(long dcId) { @Override public boolean updateState(Status oldStatus, Event event, Status newStatus, Host vo, Object data) { - HostVO host = findById(vo.getId()); + // lock target row from beginning to avoid lock-promotion caused deadlock + HostVO host = lockRow(vo.getId(), true); if (host == null) { if (event == Event.Remove && newStatus == Status.Removed) { host = findByIdIncludingRemoved(vo.getId()); @@ -953,46 +955,49 @@ public boolean updateState(Status oldStatus, Event event, Status newStatus, Host int result = update(ub, sc, null); assert result <= 1 : "How can this update " + result + " rows? "; - if (status_logger.isDebugEnabled() && result == 0) { + if (result == 0) { HostVO ho = findById(host.getId()); assert ho != null : "How how how? : " + host.getId(); - StringBuilder str = new StringBuilder("Unable to update host for event:").append(event.toString()); - str.append(". Name=").append(host.getName()); - str.append("; New=[status=") - .append(newStatus.toString()) - .append(":msid=") - .append(newStatus.lostConnection() ? "null" : host.getManagementServerId()) - .append(":lastpinged=") - .append(host.getLastPinged()) - .append("]"); - str.append("; Old=[status=") - .append(oldStatus.toString()) - .append(":msid=") - .append(host.getManagementServerId()) - .append(":lastpinged=") - .append(oldPingTime) - .append("]"); - str.append("; DB=[status=") - .append(vo.getStatus().toString()) - .append(":msid=") - .append(vo.getManagementServerId()) - .append(":lastpinged=") - .append(vo.getLastPinged()) - .append(":old update count=") - .append(oldUpdateCount) - .append("]"); - status_logger.debug(str.toString()); - } else { - StringBuilder msg = new StringBuilder("Agent status update: ["); - msg.append("id = " + host.getId()); - msg.append("; name = " + host.getName()); - msg.append("; old status = " + oldStatus); - msg.append("; event = " + event); - msg.append("; new status = " + newStatus); - msg.append("; old update count = " + oldUpdateCount); - msg.append("; new update count = " + newUpdateCount + "]"); - status_logger.debug(msg.toString()); + if (status_logger.isDebugEnabled()) { + + StringBuilder str = new StringBuilder("Unable to update host for event:").append(event.toString()); + str.append(". Name=").append(host.getName()); + str.append("; New=[status=") + .append(newStatus.toString()) + .append(":msid=") + .append(newStatus.lostConnection() ? "null" : host.getManagementServerId()) + .append(":lastpinged=") + .append(host.getLastPinged()) + .append("]"); + str.append("; Old=[status=").append(oldStatus.toString()).append(":msid=").append(host.getManagementServerId()).append(":lastpinged=").append(oldPingTime) + .append("]"); + str.append("; DB=[status=") + .append(vo.getStatus().toString()) + .append(":msid=") + .append(vo.getManagementServerId()) + .append(":lastpinged=") + .append(vo.getLastPinged()) + .append(":old update count=") + .append(oldUpdateCount) + .append("]"); + status_logger.debug(str.toString()); + } else { + StringBuilder msg = new StringBuilder("Agent status update: ["); + msg.append("id = " + host.getId()); + msg.append("; name = " + host.getName()); + msg.append("; old status = " + oldStatus); + msg.append("; event = " + event); + msg.append("; new status = " + newStatus); + msg.append("; old update count = " + oldUpdateCount); + msg.append("; new update count = " + newUpdateCount + "]"); + status_logger.debug(msg.toString()); + } + + if (ho.getState() == newStatus) { + status_logger.debug("Host " + ho.getName() + " state has already been updated to " + newStatus); + return true; + } } return result > 0; diff --git a/engine/schema/src/com/cloud/network/LBHealthCheckPolicyVO.java b/engine/schema/src/com/cloud/network/LBHealthCheckPolicyVO.java index f1e8fe8f82..72dbf5cbdc 100644 --- a/engine/schema/src/com/cloud/network/LBHealthCheckPolicyVO.java +++ b/engine/schema/src/com/cloud/network/LBHealthCheckPolicyVO.java @@ -64,6 +64,9 @@ public class LBHealthCheckPolicyVO implements HealthCheckPolicy { @Column(name = "revoke") private boolean revoke = false; + @Column(name = "display", updatable = true, nullable = false) + protected boolean display = true; + protected LBHealthCheckPolicyVO() { this.uuid = UUID.randomUUID().toString(); } @@ -157,4 +160,13 @@ public String getUuid() { public void setUuid(String uuid) { this.uuid = uuid; } + + public void setDisplay(boolean display) { + this.display = display; + } + + @Override + public boolean isDisplay() { + return display; + } } diff --git a/engine/schema/src/com/cloud/network/UserIpv6AddressVO.java b/engine/schema/src/com/cloud/network/UserIpv6AddressVO.java index 9314993620..397c7b3b31 100644 --- a/engine/schema/src/com/cloud/network/UserIpv6AddressVO.java +++ b/engine/schema/src/com/cloud/network/UserIpv6AddressVO.java @@ -28,8 +28,6 @@ import javax.persistence.Id; import javax.persistence.Table; -import org.apache.cloudstack.acl.IAMEntityType; - import com.cloud.utils.db.GenericDao; @Entity @@ -188,7 +186,7 @@ public void setCreated(Date created) { } @Override - public IAMEntityType getEntityType() { - return IAMEntityType.UserIpv6Address; + public Class getEntityType() { + return UserIpv6Address.class; } } diff --git a/engine/schema/src/com/cloud/network/VpnUserVO.java b/engine/schema/src/com/cloud/network/VpnUserVO.java index 695aac0a9d..d6c4b60352 100644 --- a/engine/schema/src/com/cloud/network/VpnUserVO.java +++ b/engine/schema/src/com/cloud/network/VpnUserVO.java @@ -27,8 +27,6 @@ import javax.persistence.Id; import javax.persistence.Table; -import org.apache.cloudstack.acl.IAMEntityType; - import com.cloud.utils.db.Encrypt; @Entity @@ -129,7 +127,7 @@ public void setUuid(String uuid) { } @Override - public IAMEntityType getEntityType() { - return IAMEntityType.VpnUser; + public Class getEntityType() { + return VpnUser.class; } } diff --git a/engine/schema/src/com/cloud/network/as/AutoScalePolicyVO.java b/engine/schema/src/com/cloud/network/as/AutoScalePolicyVO.java index bde38f83d9..1842533000 100644 --- a/engine/schema/src/com/cloud/network/as/AutoScalePolicyVO.java +++ b/engine/schema/src/com/cloud/network/as/AutoScalePolicyVO.java @@ -30,7 +30,6 @@ import javax.persistence.Temporal; import javax.persistence.TemporalType; -import org.apache.cloudstack.acl.IAMEntityType; import org.apache.cloudstack.api.InternalIdentity; import com.cloud.utils.db.GenericDao; @@ -153,8 +152,8 @@ public void setLastQuiteTime(Date lastQuiteTime) { } @Override - public IAMEntityType getEntityType() { - return IAMEntityType.AutoScalePolicy; + public Class getEntityType() { + return AutoScalePolicy.class; } } diff --git a/engine/schema/src/com/cloud/network/as/AutoScaleVmGroupVO.java b/engine/schema/src/com/cloud/network/as/AutoScaleVmGroupVO.java index 3a05a7b909..d32e7f873a 100644 --- a/engine/schema/src/com/cloud/network/as/AutoScaleVmGroupVO.java +++ b/engine/schema/src/com/cloud/network/as/AutoScaleVmGroupVO.java @@ -30,7 +30,6 @@ import javax.persistence.Temporal; import javax.persistence.TemporalType; -import org.apache.cloudstack.acl.IAMEntityType; import org.apache.cloudstack.api.InternalIdentity; import com.cloud.utils.db.GenericDao; @@ -227,7 +226,7 @@ public boolean isDisplay() { } @Override - public IAMEntityType getEntityType() { - return IAMEntityType.AutoScaleVmGroup; + public Class getEntityType() { + return AutoScaleVmGroup.class; } } diff --git a/engine/schema/src/com/cloud/network/as/AutoScaleVmProfileVO.java b/engine/schema/src/com/cloud/network/as/AutoScaleVmProfileVO.java index 0b59394ddd..69e4c8190f 100644 --- a/engine/schema/src/com/cloud/network/as/AutoScaleVmProfileVO.java +++ b/engine/schema/src/com/cloud/network/as/AutoScaleVmProfileVO.java @@ -33,7 +33,6 @@ import javax.persistence.InheritanceType; import javax.persistence.Table; -import org.apache.cloudstack.acl.IAMEntityType; import org.apache.cloudstack.api.Identity; import org.apache.cloudstack.api.InternalIdentity; @@ -235,8 +234,8 @@ public boolean isDisplay() { } @Override - public IAMEntityType getEntityType() { - return IAMEntityType.AutoScaleVmProfile; + public Class getEntityType() { + return AutoScaleVmProfile.class; } } diff --git a/engine/schema/src/com/cloud/network/as/ConditionVO.java b/engine/schema/src/com/cloud/network/as/ConditionVO.java index e8c1d0bc59..5035f731b5 100644 --- a/engine/schema/src/com/cloud/network/as/ConditionVO.java +++ b/engine/schema/src/com/cloud/network/as/ConditionVO.java @@ -29,7 +29,6 @@ import javax.persistence.Id; import javax.persistence.Table; -import org.apache.cloudstack.acl.IAMEntityType; import org.apache.cloudstack.api.Identity; import org.apache.cloudstack.api.InternalIdentity; @@ -130,8 +129,8 @@ public Date getRemoved() { } @Override - public IAMEntityType getEntityType() { - return IAMEntityType.Condition; + public Class getEntityType() { + return Condition.class; } } diff --git a/engine/schema/src/com/cloud/network/dao/IPAddressVO.java b/engine/schema/src/com/cloud/network/dao/IPAddressVO.java index d06b8c51d7..de2d934630 100644 --- a/engine/schema/src/com/cloud/network/dao/IPAddressVO.java +++ b/engine/schema/src/com/cloud/network/dao/IPAddressVO.java @@ -31,8 +31,6 @@ import javax.persistence.TemporalType; import javax.persistence.Transient; -import org.apache.cloudstack.acl.IAMEntityType; - import com.cloud.network.IpAddress; import com.cloud.utils.net.Ip; @@ -350,7 +348,7 @@ public void setDisplay(boolean display) { } @Override - public IAMEntityType getEntityType() { - return IAMEntityType.IpAddress; + public Class getEntityType() { + return IpAddress.class; } } diff --git a/engine/schema/src/com/cloud/network/dao/LBHealthCheckPolicyDao.java b/engine/schema/src/com/cloud/network/dao/LBHealthCheckPolicyDao.java index 67a347d370..eed97d650c 100644 --- a/engine/schema/src/com/cloud/network/dao/LBHealthCheckPolicyDao.java +++ b/engine/schema/src/com/cloud/network/dao/LBHealthCheckPolicyDao.java @@ -26,7 +26,7 @@ public interface LBHealthCheckPolicyDao extends GenericDao listByLoadBalancerId(long loadBalancerId); + List listByLoadBalancerIdAndDisplayFlag(long loadBalancerId, Boolean forDisplay); List listByLoadBalancerId(long loadBalancerId, boolean revoke); } diff --git a/engine/schema/src/com/cloud/network/dao/LBHealthCheckPolicyDaoImpl.java b/engine/schema/src/com/cloud/network/dao/LBHealthCheckPolicyDaoImpl.java index ddebd3622d..52c1d0e1ea 100644 --- a/engine/schema/src/com/cloud/network/dao/LBHealthCheckPolicyDaoImpl.java +++ b/engine/schema/src/com/cloud/network/dao/LBHealthCheckPolicyDaoImpl.java @@ -48,9 +48,12 @@ public void remove(long loadBalancerId, Boolean revoke) { } @Override - public List listByLoadBalancerId(long loadBalancerId) { + public List listByLoadBalancerIdAndDisplayFlag(long loadBalancerId, Boolean forDisplay) { SearchCriteria sc = createSearchCriteria(); sc.addAnd("loadBalancerId", SearchCriteria.Op.EQ, loadBalancerId); + if (forDisplay != null) { + sc.addAnd("display", SearchCriteria.Op.EQ, forDisplay); + } return listBy(sc); } diff --git a/engine/schema/src/com/cloud/network/dao/LBStickinessPolicyDao.java b/engine/schema/src/com/cloud/network/dao/LBStickinessPolicyDao.java index 82e68d61e8..6669d70824 100644 --- a/engine/schema/src/com/cloud/network/dao/LBStickinessPolicyDao.java +++ b/engine/schema/src/com/cloud/network/dao/LBStickinessPolicyDao.java @@ -25,7 +25,7 @@ public interface LBStickinessPolicyDao extends GenericDao listByLoadBalancerId(long loadBalancerId); + List listByLoadBalancerIdAndDisplayFlag(long loadBalancerId, boolean forDisplay); List listByLoadBalancerId(long loadBalancerId, boolean revoke); } diff --git a/engine/schema/src/com/cloud/network/dao/LBStickinessPolicyDaoImpl.java b/engine/schema/src/com/cloud/network/dao/LBStickinessPolicyDaoImpl.java index fdce8c7596..e8295c592d 100644 --- a/engine/schema/src/com/cloud/network/dao/LBStickinessPolicyDaoImpl.java +++ b/engine/schema/src/com/cloud/network/dao/LBStickinessPolicyDaoImpl.java @@ -47,9 +47,10 @@ public void remove(long loadBalancerId, Boolean revoke) { } @Override - public List listByLoadBalancerId(long loadBalancerId) { + public List listByLoadBalancerIdAndDisplayFlag(long loadBalancerId, boolean forDisplay) { SearchCriteria sc = createSearchCriteria(); sc.addAnd("loadBalancerId", SearchCriteria.Op.EQ, loadBalancerId); + sc.addAnd("display", SearchCriteria.Op.EQ, forDisplay); return listBy(sc); } diff --git a/engine/schema/src/com/cloud/network/dao/LBStickinessPolicyVO.java b/engine/schema/src/com/cloud/network/dao/LBStickinessPolicyVO.java index 6e8dfbb032..9628a32ae4 100644 --- a/engine/schema/src/com/cloud/network/dao/LBStickinessPolicyVO.java +++ b/engine/schema/src/com/cloud/network/dao/LBStickinessPolicyVO.java @@ -64,6 +64,9 @@ public class LBStickinessPolicyVO implements StickinessPolicy { @Column(name = "revoke") private boolean revoke = false; + @Column(name = "display", updatable = true, nullable = false) + protected boolean display = true; + protected LBStickinessPolicyVO() { this.uuid = UUID.randomUUID().toString(); } @@ -150,4 +153,13 @@ public String getUuid() { public void setUuid(String uuid) { this.uuid = uuid; } + + public void setDisplay(boolean display) { + this.display = display; + } + + @Override + public boolean isDisplay() { + return display; + } } diff --git a/engine/schema/src/com/cloud/network/dao/LoadBalancerVMMapDao.java b/engine/schema/src/com/cloud/network/dao/LoadBalancerVMMapDao.java index 79eaf8e16b..a25534b701 100644 --- a/engine/schema/src/com/cloud/network/dao/LoadBalancerVMMapDao.java +++ b/engine/schema/src/com/cloud/network/dao/LoadBalancerVMMapDao.java @@ -34,4 +34,12 @@ public interface LoadBalancerVMMapDao extends GenericDao listByInstanceIp(String instanceIp); + + List listByLoadBalancerIdAndVmId(long loadBalancerId, long instanceId); + + LoadBalancerVMMapVO findByLoadBalancerIdAndVmIdVmIp(long loadBalancerId, long instanceId, String instanceIp); + + void remove(long id, long instanceId, String instanceIp, Boolean revoke); } diff --git a/engine/schema/src/com/cloud/network/dao/LoadBalancerVMMapDaoImpl.java b/engine/schema/src/com/cloud/network/dao/LoadBalancerVMMapDaoImpl.java index b0b14fc23c..cbfda8fadb 100644 --- a/engine/schema/src/com/cloud/network/dao/LoadBalancerVMMapDaoImpl.java +++ b/engine/schema/src/com/cloud/network/dao/LoadBalancerVMMapDaoImpl.java @@ -51,6 +51,21 @@ public void remove(long loadBalancerId, List instanceIds, Boolean revoke) expunge(sc); } + @Override + public void remove(long loadBalancerId, long instanceId, String instanceIp, Boolean revoke) { + SearchCriteria sc = createSearchCriteria(); + sc.addAnd("loadBalancerId", SearchCriteria.Op.EQ, loadBalancerId); + sc.addAnd("instanceId", SearchCriteria.Op.IN, instanceId); + sc.addAnd("instanceIp", SearchCriteria.Op.EQ, instanceIp); + + if (revoke != null) { + sc.addAnd("revoke", SearchCriteria.Op.EQ, revoke); + } + + expunge(sc); + } + + @Override public List listByInstanceId(long instanceId) { SearchCriteria sc = createSearchCriteria(); @@ -59,6 +74,14 @@ public List listByInstanceId(long instanceId) { return listBy(sc); } + @Override + public List listByInstanceIp(String instanceIp) { + SearchCriteria sc = createSearchCriteria(); + sc.addAnd("instanceIp", SearchCriteria.Op.EQ, instanceIp); + + return listBy(sc); + } + @Override public List listByLoadBalancerId(long loadBalancerId) { SearchCriteria sc = createSearchCriteria(); @@ -84,6 +107,18 @@ public LoadBalancerVMMapVO findByLoadBalancerIdAndVmId(long loadBalancerId, long return findOneBy(sc); } + + @Override + public LoadBalancerVMMapVO findByLoadBalancerIdAndVmIdVmIp(long loadBalancerId, long instanceId, String instanceIp) { + SearchCriteria sc = createSearchCriteria(); + sc.addAnd("loadBalancerId", SearchCriteria.Op.EQ, loadBalancerId); + sc.addAnd("instanceId", SearchCriteria.Op.EQ, instanceId); + sc.addAnd("instanceIp", SearchCriteria.Op.EQ, instanceIp); + + return findOneBy(sc); + } + + @Override public boolean isVmAttachedToLoadBalancer(long loadBalancerId) { GenericSearchBuilder CountByAccount = createSearchBuilder(Long.class); @@ -94,4 +129,12 @@ public boolean isVmAttachedToLoadBalancer(long loadBalancerId) { sc.setParameters("loadBalancerId", loadBalancerId); return customSearch(sc, null).get(0) > 0; } + + @Override + public List listByLoadBalancerIdAndVmId(long loadBalancerId, long instanceId) { + SearchCriteria sc = createSearchCriteria(); + sc.addAnd("loadBalancerId", SearchCriteria.Op.EQ, loadBalancerId); + sc.addAnd("instanceId", SearchCriteria.Op.EQ, instanceId); + return listBy(sc); + } } diff --git a/engine/schema/src/com/cloud/network/dao/LoadBalancerVMMapVO.java b/engine/schema/src/com/cloud/network/dao/LoadBalancerVMMapVO.java index 0a67106dc9..08b918475c 100644 --- a/engine/schema/src/com/cloud/network/dao/LoadBalancerVMMapVO.java +++ b/engine/schema/src/com/cloud/network/dao/LoadBalancerVMMapVO.java @@ -39,6 +39,9 @@ public class LoadBalancerVMMapVO implements InternalIdentity { @Column(name = "instance_id") private long instanceId; + @Column(name = "instance_ip") + private String instanceIp; + @Column(name = "revoke") private boolean revoke = false; @@ -59,6 +62,13 @@ public LoadBalancerVMMapVO(long loadBalancerId, long instanceId, boolean revoke) this.revoke = revoke; } + public LoadBalancerVMMapVO(long loadBalancerId, long instanceId, String vmIp, boolean revoke) { + this.loadBalancerId = loadBalancerId; + this.instanceId = instanceId; + this.instanceIp = vmIp; + this.revoke = revoke; + } + @Override public long getId() { return id; @@ -87,4 +97,13 @@ public String getState() { public void setState(String state) { this.state = state; } + + public String getInstanceIp() { + return instanceIp; + } + + public void setInstanceIp(String instanceIp) { + this.instanceIp = instanceIp; + } + } diff --git a/engine/schema/src/com/cloud/network/dao/MonitoringServiceVO.java b/engine/schema/src/com/cloud/network/dao/MonitoringServiceVO.java index 999fdfc649..01fba00d0b 100644 --- a/engine/schema/src/com/cloud/network/dao/MonitoringServiceVO.java +++ b/engine/schema/src/com/cloud/network/dao/MonitoringServiceVO.java @@ -25,8 +25,6 @@ import javax.persistence.Id; import javax.persistence.Table; -import org.apache.cloudstack.acl.IAMEntityType; - import com.cloud.network.MonitoringService; @Entity @@ -120,7 +118,7 @@ public String getProcessName() { } @Override - public IAMEntityType getEntityType() { - return IAMEntityType.MonitorService; + public Class getEntityType() { + return MonitoringService.class; } } diff --git a/engine/schema/src/com/cloud/network/dao/NetworkVO.java b/engine/schema/src/com/cloud/network/dao/NetworkVO.java index 13e8dbff09..8c0466fbfa 100644 --- a/engine/schema/src/com/cloud/network/dao/NetworkVO.java +++ b/engine/schema/src/com/cloud/network/dao/NetworkVO.java @@ -30,7 +30,6 @@ import javax.persistence.Transient; import org.apache.cloudstack.acl.ControlledEntity; -import org.apache.cloudstack.acl.IAMEntityType; import com.cloud.network.Network; import com.cloud.network.Networks.BroadcastDomainType; @@ -167,6 +166,9 @@ public class NetworkVO implements Network { @Column(name = "network_acl_id") Long networkACLId; + @Column(name = "streched_l2") + boolean strechedL2Network = false; + public NetworkVO() { uuid = UUID.randomUUID().toString(); } @@ -511,7 +513,7 @@ public boolean equals(Object obj) { @Override public String toString() { StringBuilder buf = new StringBuilder("Ntwk["); - buf.append(id).append("|").append(trafficType).append("|").append(networkOfferingId).append("]"); + buf.append(uuid).append("|").append(trafficType).append("|").append(networkOfferingId).append("]"); return buf.toString(); } @@ -575,6 +577,11 @@ public void setDisplayNetwork(boolean displayNetwork) { this.displayNetwork = displayNetwork; } + @Override + public boolean isDisplay(){ + return displayNetwork; + } + @Override public void setNetworkACLId(Long networkACLId) { this.networkACLId = networkACLId; @@ -586,7 +593,20 @@ public Long getNetworkACLId() { } @Override - public IAMEntityType getEntityType() { - return IAMEntityType.Network; + public Class getEntityType() { + return Network.class; + } + + @Override + public boolean isStrechedL2Network() { + return strechedL2Network; + } + + public void setStrechedL2Network(boolean strechedL2Network) { + this.strechedL2Network = strechedL2Network; + } + + public void setVpcId(long vpcId) { + this.vpcId = vpcId; } } diff --git a/engine/schema/src/com/cloud/network/dao/RemoteAccessVpnVO.java b/engine/schema/src/com/cloud/network/dao/RemoteAccessVpnVO.java index 8f95f184c4..0616939fc2 100644 --- a/engine/schema/src/com/cloud/network/dao/RemoteAccessVpnVO.java +++ b/engine/schema/src/com/cloud/network/dao/RemoteAccessVpnVO.java @@ -25,8 +25,6 @@ import javax.persistence.Id; import javax.persistence.Table; -import org.apache.cloudstack.acl.IAMEntityType; - import com.cloud.network.RemoteAccessVpn; @Entity @@ -168,7 +166,7 @@ public boolean isDisplay() { } @Override - public IAMEntityType getEntityType() { - return IAMEntityType.RemoteAccessVpn; + public Class getEntityType() { + return RemoteAccessVpn.class; } } diff --git a/engine/schema/src/com/cloud/network/dao/Site2SiteCustomerGatewayVO.java b/engine/schema/src/com/cloud/network/dao/Site2SiteCustomerGatewayVO.java index 6de4d429ce..5bcf361836 100644 --- a/engine/schema/src/com/cloud/network/dao/Site2SiteCustomerGatewayVO.java +++ b/engine/schema/src/com/cloud/network/dao/Site2SiteCustomerGatewayVO.java @@ -26,8 +26,6 @@ import javax.persistence.Id; import javax.persistence.Table; -import org.apache.cloudstack.acl.IAMEntityType; - import com.cloud.network.Site2SiteCustomerGateway; import com.cloud.utils.db.Encrypt; import com.cloud.utils.db.GenericDao; @@ -211,7 +209,7 @@ public long getAccountId() { } @Override - public IAMEntityType getEntityType() { - return IAMEntityType.Site2SiteCustomerGateway; + public Class getEntityType() { + return Site2SiteCustomerGateway.class; } } diff --git a/engine/schema/src/com/cloud/network/dao/Site2SiteVpnConnectionVO.java b/engine/schema/src/com/cloud/network/dao/Site2SiteVpnConnectionVO.java index f0074c04dc..85643fc043 100644 --- a/engine/schema/src/com/cloud/network/dao/Site2SiteVpnConnectionVO.java +++ b/engine/schema/src/com/cloud/network/dao/Site2SiteVpnConnectionVO.java @@ -28,7 +28,6 @@ import javax.persistence.Id; import javax.persistence.Table; -import org.apache.cloudstack.acl.IAMEntityType; import org.apache.cloudstack.api.InternalIdentity; import com.cloud.network.Site2SiteVpnConnection; @@ -175,7 +174,7 @@ public boolean isDisplay() { } @Override - public IAMEntityType getEntityType() { - return IAMEntityType.Site2SiteVpnConnection; + public Class getEntityType() { + return Site2SiteVpnConnection.class; } } diff --git a/engine/schema/src/com/cloud/network/dao/Site2SiteVpnGatewayVO.java b/engine/schema/src/com/cloud/network/dao/Site2SiteVpnGatewayVO.java index 33236b9d68..260e5fc4c0 100644 --- a/engine/schema/src/com/cloud/network/dao/Site2SiteVpnGatewayVO.java +++ b/engine/schema/src/com/cloud/network/dao/Site2SiteVpnGatewayVO.java @@ -26,8 +26,6 @@ import javax.persistence.Id; import javax.persistence.Table; -import org.apache.cloudstack.acl.IAMEntityType; - import com.cloud.network.Site2SiteVpnGateway; import com.cloud.utils.db.GenericDao; @@ -133,7 +131,7 @@ public boolean isDisplay() { } @Override - public IAMEntityType getEntityType() { - return IAMEntityType.Site2SiteVpnGateway; + public Class getEntityType() { + return Site2SiteVpnGateway.class; } } diff --git a/engine/schema/src/com/cloud/network/dao/SslCertVO.java b/engine/schema/src/com/cloud/network/dao/SslCertVO.java index 6ef7afd1c7..2676d611bd 100644 --- a/engine/schema/src/com/cloud/network/dao/SslCertVO.java +++ b/engine/schema/src/com/cloud/network/dao/SslCertVO.java @@ -23,8 +23,6 @@ import javax.persistence.Id; import javax.persistence.Table; -import org.apache.cloudstack.acl.IAMEntityType; - import com.cloud.network.lb.SslCert; import com.cloud.utils.db.Encrypt; @@ -124,8 +122,8 @@ public String getFingerPrint() { } @Override - public IAMEntityType getEntityType() { - return IAMEntityType.SSLCert; + public Class getEntityType() { + return SslCert.class; } } \ No newline at end of file diff --git a/engine/schema/src/com/cloud/network/rules/FirewallRuleVO.java b/engine/schema/src/com/cloud/network/rules/FirewallRuleVO.java index 5e22dd4f4e..169102af8c 100644 --- a/engine/schema/src/com/cloud/network/rules/FirewallRuleVO.java +++ b/engine/schema/src/com/cloud/network/rules/FirewallRuleVO.java @@ -34,8 +34,6 @@ import javax.persistence.Table; import javax.persistence.Transient; -import org.apache.cloudstack.acl.IAMEntityType; - import com.cloud.utils.db.GenericDao; import com.cloud.utils.net.NetUtils; @@ -285,7 +283,7 @@ public boolean isDisplay() { } @Override - public IAMEntityType getEntityType() { - return IAMEntityType.FirewallRule; + public Class getEntityType() { + return FirewallRule.class; } } diff --git a/engine/schema/src/com/cloud/network/security/SecurityGroupVO.java b/engine/schema/src/com/cloud/network/security/SecurityGroupVO.java index 26859f704e..4a4c83ae74 100644 --- a/engine/schema/src/com/cloud/network/security/SecurityGroupVO.java +++ b/engine/schema/src/com/cloud/network/security/SecurityGroupVO.java @@ -25,8 +25,6 @@ import javax.persistence.Id; import javax.persistence.Table; -import org.apache.cloudstack.acl.IAMEntityType; - @Entity @Table(name = ("security_group")) public class SecurityGroupVO implements SecurityGroup { @@ -97,7 +95,7 @@ public void setUuid(String uuid) { } @Override - public IAMEntityType getEntityType() { - return IAMEntityType.SecurityGroup; + public Class getEntityType() { + return SecurityGroup.class; } } diff --git a/engine/schema/src/com/cloud/network/vpc/NetworkACLItemCidrsDao.java b/engine/schema/src/com/cloud/network/vpc/NetworkACLItemCidrsDao.java new file mode 100644 index 0000000000..5e49368de7 --- /dev/null +++ b/engine/schema/src/com/cloud/network/vpc/NetworkACLItemCidrsDao.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 com.cloud.network.vpc; + +import java.util.List; + +import com.cloud.utils.db.DB; +import com.cloud.utils.db.GenericDao; + +/** + * @author daan + * + */ +public interface NetworkACLItemCidrsDao extends GenericDao { + + void persist(long networkACLItemId, List cidrs); + + List getCidrs(long networkACLItemId); + + @DB + List listByNetworkACLItemId(long networkACLItemId); + +} diff --git a/engine/schema/src/com/cloud/network/vpc/NetworkACLItemCidrsVO.java b/engine/schema/src/com/cloud/network/vpc/NetworkACLItemCidrsVO.java new file mode 100644 index 0000000000..c366f94796 --- /dev/null +++ b/engine/schema/src/com/cloud/network/vpc/NetworkACLItemCidrsVO.java @@ -0,0 +1,78 @@ +/** + * 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.vpc; + +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 org.apache.cloudstack.api.InternalIdentity; + +@Entity +@Table(name = "network_acl_item_cidrs") +public class NetworkACLItemCidrsVO implements InternalIdentity { + private static final long serialVersionUID = 7805284475485494754L; + + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) + @Column(name = "id") + private Long id; + + @Column(name = "network_acl_item_id") + private long networkACLItemId; + + @Column(name = "cidr") + private String cidrList; + + public NetworkACLItemCidrsVO() { + } + + public NetworkACLItemCidrsVO(long networkAclItemId, String cidrList) { + this.networkACLItemId = networkAclItemId; + this.cidrList = cidrList; + } + + /* (non-Javadoc) + * @see org.apache.cloudstack.api.InternalIdentity#getId() + */ + @Override + public long getId() { + return id; + } + + public long getNetworkACLItemId() { + return networkACLItemId; + } + + public String getCidr() { + return cidrList; + } + + public String getCidrList() { + return cidrList; + } + + public void setCidrList(String cidrList) { + this.cidrList = cidrList; + } + +} diff --git a/engine/schema/src/com/cloud/network/vpc/NetworkACLItemDao.java b/engine/schema/src/com/cloud/network/vpc/NetworkACLItemDao.java index e27848522f..9ab6365df1 100644 --- a/engine/schema/src/com/cloud/network/vpc/NetworkACLItemDao.java +++ b/engine/schema/src/com/cloud/network/vpc/NetworkACLItemDao.java @@ -34,4 +34,6 @@ public interface NetworkACLItemDao extends GenericDao { int getMaxNumberByACL(long aclId); NetworkACLItemVO findByAclAndNumber(long aclId, int number); + + void loadCidrs(NetworkACLItemVO item); } diff --git a/engine/schema/src/com/cloud/network/vpc/NetworkACLItemVO.java b/engine/schema/src/com/cloud/network/vpc/NetworkACLItemVO.java index 8031b001b8..6eb9cb0e99 100644 --- a/engine/schema/src/com/cloud/network/vpc/NetworkACLItemVO.java +++ b/engine/schema/src/com/cloud/network/vpc/NetworkACLItemVO.java @@ -16,9 +16,10 @@ // under the License. package com.cloud.network.vpc; -import java.util.ArrayList; import java.util.Date; +import java.util.LinkedList; import java.util.List; +import java.util.StringTokenizer; import java.util.UUID; import javax.persistence.Column; @@ -29,6 +30,7 @@ import javax.persistence.GenerationType; import javax.persistence.Id; import javax.persistence.Table; +import javax.persistence.Transient; import com.cloud.utils.db.GenericDao; import com.cloud.utils.net.NetUtils; @@ -37,6 +39,11 @@ @Table(name = "network_acl_item") public class NetworkACLItemVO implements NetworkACLItem { + /** + * + */ + private static final long serialVersionUID = 2790623532888742060L; + @Id @GeneratedValue(strategy = GenerationType.IDENTITY) @Column(name = "id") @@ -71,8 +78,11 @@ public class NetworkACLItemVO implements NetworkACLItem { @Enumerated(value = EnumType.STRING) TrafficType trafficType; - @Column(name = "cidr", length = 2048) - String sourceCidrs; + // This is a delayed load value. If the value is null, + // then this field has not been loaded yet. + // Call the NetworkACLItem dao to load it. + @Transient + List sourceCidrs; @Column(name = "uuid") String uuid; @@ -108,32 +118,12 @@ public NetworkACLItemVO(Integer portStart, Integer portEnd, String protocol, lon } public void setSourceCidrList(List sourceCidrs) { - if (sourceCidrs == null) { - this.sourceCidrs = null; - } else { - StringBuilder sb = new StringBuilder(); - for (String cidr : sourceCidrs) { - if (sb.length() != 0) { - sb.append(","); - } - sb.append(cidr); - } - this.sourceCidrs = sb.toString(); - } + this.sourceCidrs = sourceCidrs; } @Override public List getSourceCidrList() { - if (sourceCidrs == null || sourceCidrs.isEmpty()) { - return null; - } else { - List cidrList = new ArrayList(); - String[] cidrs = sourceCidrs.split(","); - for (String cidr : cidrs) { - cidrList.add(cidr); - } - return cidrList; - } + return sourceCidrs; } @Override @@ -234,7 +224,12 @@ public void setTrafficType(TrafficType trafficType) { } public void setSourceCidrs(String sourceCidrs) { - this.sourceCidrs = sourceCidrs; + List srcCidrs = new LinkedList(); + StringTokenizer st = new StringTokenizer(sourceCidrs,",;"); + while(st.hasMoreTokens()) { + srcCidrs.add(st.nextToken()); + } + this.sourceCidrs = srcCidrs; } public void setNumber(int number) { diff --git a/engine/schema/src/com/cloud/network/vpc/StaticRouteVO.java b/engine/schema/src/com/cloud/network/vpc/StaticRouteVO.java index a9ba05154b..2c2d53edb2 100644 --- a/engine/schema/src/com/cloud/network/vpc/StaticRouteVO.java +++ b/engine/schema/src/com/cloud/network/vpc/StaticRouteVO.java @@ -28,8 +28,6 @@ import javax.persistence.Id; import javax.persistence.Table; -import org.apache.cloudstack.acl.IAMEntityType; - import com.cloud.utils.db.GenericDao; @Entity @@ -139,7 +137,7 @@ public String toString() { } @Override - public IAMEntityType getEntityType() { - return IAMEntityType.StaticRoute; + public Class getEntityType() { + return StaticRoute.class; } } \ No newline at end of file diff --git a/engine/schema/src/com/cloud/network/vpc/VpcGatewayVO.java b/engine/schema/src/com/cloud/network/vpc/VpcGatewayVO.java index 48238b1971..23568b4923 100644 --- a/engine/schema/src/com/cloud/network/vpc/VpcGatewayVO.java +++ b/engine/schema/src/com/cloud/network/vpc/VpcGatewayVO.java @@ -28,8 +28,6 @@ import javax.persistence.Id; import javax.persistence.Table; -import org.apache.cloudstack.acl.IAMEntityType; - import com.cloud.utils.db.GenericDao; @Entity @@ -219,7 +217,7 @@ public long getNetworkACLId() { } @Override - public IAMEntityType getEntityType() { - return IAMEntityType.VpcGateway; + public Class getEntityType() { + return VpcGateway.class; } } diff --git a/engine/schema/src/com/cloud/network/vpc/VpcOfferingVO.java b/engine/schema/src/com/cloud/network/vpc/VpcOfferingVO.java index 53f6f6055e..a7d61b3692 100644 --- a/engine/schema/src/com/cloud/network/vpc/VpcOfferingVO.java +++ b/engine/schema/src/com/cloud/network/vpc/VpcOfferingVO.java @@ -70,6 +70,9 @@ public class VpcOfferingVO implements VpcOffering { @Column(name = "supports_distributed_router") boolean supportsDistributedRouter=false; + @Column(name = "supports_region_level_vpc") + boolean offersRegionLevelVPC = false; + public VpcOfferingVO() { this.uuid = UUID.randomUUID().toString(); } @@ -84,10 +87,11 @@ public VpcOfferingVO(String name, String displayText, Long serviceOfferingId) { } public VpcOfferingVO(String name, String displayText, boolean isDefault, Long serviceOfferingId, - boolean supportsDistributedRouter) { + boolean supportsDistributedRouter, boolean offersRegionLevelVPC) { this(name, displayText, serviceOfferingId); this.isDefault = isDefault; this.supportsDistributedRouter = supportsDistributedRouter; + this.offersRegionLevelVPC = offersRegionLevelVPC; } @Override @@ -155,4 +159,9 @@ public Long getServiceOfferingId() { public boolean supportsDistributedRouter() { return supportsDistributedRouter; } + + @Override + public boolean offersRegionLevelVPC() { + return offersRegionLevelVPC; + } } diff --git a/engine/schema/src/com/cloud/network/vpc/VpcVO.java b/engine/schema/src/com/cloud/network/vpc/VpcVO.java index dea8c314bc..22d51dd542 100644 --- a/engine/schema/src/com/cloud/network/vpc/VpcVO.java +++ b/engine/schema/src/com/cloud/network/vpc/VpcVO.java @@ -26,8 +26,6 @@ import javax.persistence.Id; import javax.persistence.Table; -import org.apache.cloudstack.acl.IAMEntityType; - import com.cloud.utils.db.GenericDao; @Entity @@ -84,12 +82,15 @@ public class VpcVO implements Vpc { @Column(name="uses_distributed_router") boolean usesDistributedRouter = false; + @Column(name = "region_level_vpc") + boolean regionLevelVpc = false; + public VpcVO() { uuid = UUID.randomUUID().toString(); } public VpcVO(long zoneId, String name, String displayText, long accountId, long domainId, long vpcOffId, String cidr, - String networkDomain, boolean useDistributedRouter) { + String networkDomain, boolean useDistributedRouter, boolean regionLevelVpc) { this.zoneId = zoneId; this.name = name; this.displayText = displayText; @@ -99,8 +100,9 @@ public VpcVO(long zoneId, String name, String displayText, long accountId, long uuid = UUID.randomUUID().toString(); state = State.Enabled; this.networkDomain = networkDomain; - this.vpcOfferingId = vpcOffId; - this.usesDistributedRouter = useDistributedRouter; + vpcOfferingId = vpcOffId; + usesDistributedRouter = useDistributedRouter; + this.regionLevelVpc = regionLevelVpc; } @Override @@ -193,6 +195,11 @@ public void setUuid(String uuid) { this.uuid = uuid; } + @Override + public boolean isRegionLevelVpc() { + return regionLevelVpc; + } + public void setDisplay(boolean display) { this.display = display; @@ -204,8 +211,8 @@ public boolean isDisplay() { } @Override - public IAMEntityType getEntityType() { - return IAMEntityType.Vpc; + public Class getEntityType() { + return Vpc.class; } @Override diff --git a/engine/schema/src/com/cloud/network/vpc/dao/NetworkACLItemCidrsDaoImpl.java b/engine/schema/src/com/cloud/network/vpc/dao/NetworkACLItemCidrsDaoImpl.java new file mode 100644 index 0000000000..7c02f8b554 --- /dev/null +++ b/engine/schema/src/com/cloud/network/vpc/dao/NetworkACLItemCidrsDaoImpl.java @@ -0,0 +1,94 @@ +/** + * 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.vpc.dao; + +import java.util.ArrayList; +import java.util.List; + +import javax.ejb.Local; + +import org.apache.log4j.Logger; +import org.springframework.stereotype.Component; + +import com.cloud.network.vpc.NetworkACLItemCidrsDao; +import com.cloud.network.vpc.NetworkACLItemCidrsVO; +import com.cloud.utils.db.GenericDaoBase; +import com.cloud.utils.db.SearchBuilder; +import com.cloud.utils.db.SearchCriteria; +import com.cloud.utils.db.TransactionLegacy; + +/** + * @author daan + * + */ +@Component +@Local(value = NetworkACLItemCidrsDao.class) +public class NetworkACLItemCidrsDaoImpl extends GenericDaoBase implements NetworkACLItemCidrsDao { + private static final Logger s_logger = Logger.getLogger(NetworkACLItemCidrsDaoImpl.class); + protected final SearchBuilder cidrsSearch; + + protected NetworkACLItemCidrsDaoImpl() { + cidrsSearch = createSearchBuilder(); + cidrsSearch.and("networkAclItemId", cidrsSearch.entity().getNetworkACLItemId(), SearchCriteria.Op.EQ); + cidrsSearch.done(); + } + + /* (non-Javadoc) + * @see com.cloud.network.dao.NetworkAclItemCidrsDao#persist(long, java.util.List) + */ + @Override + public void persist(long networkACLItemId, List cidrs) { + TransactionLegacy txn = TransactionLegacy.currentTxn(); + + txn.start(); + for (String cidr : cidrs) { + NetworkACLItemCidrsVO vo = new NetworkACLItemCidrsVO(networkACLItemId, cidr); + persist(vo); + } + txn.commit(); + } + + /* (non-Javadoc) + * @see com.cloud.network.dao.NetworkAclItemCidrsDao#getCidrs(long) + */ + @Override + public List getCidrs(long networkACLItemId) { + SearchCriteria sc = cidrsSearch.create(); + sc.setParameters("networkAclItemId", networkACLItemId); + + List results = search(sc, null); + List cidrs = new ArrayList(results.size()); + for (NetworkACLItemCidrsVO result : results) { + cidrs.add(result.getCidr()); + } + + return cidrs; + } + + @Override + public List listByNetworkACLItemId(long networkACLItemId) { + SearchCriteria sc = cidrsSearch.create(); + sc.setParameters("networkAclItemId", networkACLItemId); + + List results = search(sc, null); + + return results; + } + +} diff --git a/engine/schema/src/com/cloud/network/vpc/dao/NetworkACLItemDaoImpl.java b/engine/schema/src/com/cloud/network/vpc/dao/NetworkACLItemDaoImpl.java index 31ff6f259a..abd8bae563 100644 --- a/engine/schema/src/com/cloud/network/vpc/dao/NetworkACLItemDaoImpl.java +++ b/engine/schema/src/com/cloud/network/vpc/dao/NetworkACLItemDaoImpl.java @@ -19,10 +19,13 @@ import java.util.List; import javax.ejb.Local; +import javax.inject.Inject; +import org.apache.log4j.Logger; import org.springframework.stereotype.Component; import com.cloud.network.vpc.NetworkACLItem.State; +import com.cloud.network.vpc.NetworkACLItemCidrsDao; import com.cloud.network.vpc.NetworkACLItemDao; import com.cloud.network.vpc.NetworkACLItemVO; import com.cloud.utils.db.DB; @@ -31,17 +34,22 @@ import com.cloud.utils.db.SearchBuilder; import com.cloud.utils.db.SearchCriteria; import com.cloud.utils.db.SearchCriteria.Op; +import com.cloud.utils.db.TransactionLegacy; @Component @Local(value = NetworkACLItemDao.class) @DB() public class NetworkACLItemDaoImpl extends GenericDaoBase implements NetworkACLItemDao { + private static final Logger s_logger = Logger.getLogger(NetworkACLItemDaoImpl.class); protected final SearchBuilder AllFieldsSearch; protected final SearchBuilder NotRevokedSearch; protected final SearchBuilder ReleaseSearch; protected final GenericSearchBuilder MaxNumberSearch; + @Inject + protected NetworkACLItemCidrsDao _networkACLItemCidrsDao; + protected NetworkACLItemDaoImpl() { super(); @@ -75,6 +83,13 @@ protected NetworkACLItemDaoImpl() { MaxNumberSearch.done(); } + @Override + public NetworkACLItemVO findById(Long id) { + NetworkACLItemVO item = super.findById(id); + loadCidrs(item); + return item; + } + @Override public boolean setStateToAdd(NetworkACLItemVO rule) { SearchCriteria sc = AllFieldsSearch.create(); @@ -96,8 +111,11 @@ public boolean revoke(NetworkACLItemVO rule) { public List listByACL(long aclId) { SearchCriteria sc = AllFieldsSearch.create(); sc.setParameters("aclId", aclId); - - return listBy(sc); + List list = listBy(sc); + for(NetworkACLItemVO item :list) { + loadCidrs(item); + } + return list; } @Override @@ -113,6 +131,37 @@ public NetworkACLItemVO findByAclAndNumber(long aclId, int number) { SearchCriteria sc = AllFieldsSearch.create(); sc.setParameters("aclId", aclId); sc.setParameters("number", number); - return findOneBy(sc); + NetworkACLItemVO vo = findOneBy(sc); + if(vo != null) { + loadCidrs(vo); + } + return vo; + } + + @Override + @DB + public NetworkACLItemVO persist(NetworkACLItemVO networkAclItem) { + TransactionLegacy txn = TransactionLegacy.currentTxn(); + txn.start(); + + NetworkACLItemVO dbNetworkACLItem = super.persist(networkAclItem); + saveCidrs(networkAclItem, networkAclItem.getSourceCidrList()); + loadCidrs(dbNetworkACLItem); + + txn.commit(); + return dbNetworkACLItem; + } + + public void saveCidrs(NetworkACLItemVO networkACLItem, List cidrList) { + if (cidrList == null) { + return; + } + _networkACLItemCidrsDao.persist(networkACLItem.getId(), cidrList); + } + + @Override + public void loadCidrs(NetworkACLItemVO item) { + List cidrs = _networkACLItemCidrsDao.getCidrs(item.getId()); + item.setSourceCidrList(cidrs); } } diff --git a/engine/schema/src/com/cloud/offerings/NetworkOfferingVO.java b/engine/schema/src/com/cloud/offerings/NetworkOfferingVO.java index bf07807494..c3d849d134 100755 --- a/engine/schema/src/com/cloud/offerings/NetworkOfferingVO.java +++ b/engine/schema/src/com/cloud/offerings/NetworkOfferingVO.java @@ -139,6 +139,9 @@ public class NetworkOfferingVO implements NetworkOffering { @Column(name = "keep_alive_enabled") boolean keepAliveEnabled = false; + @Column(name="supports_streched_l2") + boolean supportsStrechedL2 = false; + @Override public String getDisplayText() { return displayText; @@ -331,7 +334,7 @@ public NetworkOfferingVO(String name, String displayText, TrafficType trafficTyp public NetworkOfferingVO(String name, String displayText, TrafficType trafficType, boolean systemOnly, boolean specifyVlan, Integer rateMbps, Integer multicastRateMbps, boolean isDefault, Availability availability, String tags, Network.GuestType guestType, boolean conserveMode, boolean dedicatedLb, boolean sharedSourceNat, boolean redundantRouter, boolean elasticIp, boolean elasticLb, boolean specifyIpRanges, boolean inline, boolean isPersistent, - boolean associatePublicIP, boolean publicLb, boolean internalLb, boolean egressdefaultpolicy) { + boolean associatePublicIP, boolean publicLb, boolean internalLb, boolean egressdefaultpolicy, boolean supportsStrechedL2) { this(name, displayText, trafficType, @@ -356,6 +359,7 @@ public NetworkOfferingVO(String name, String displayText, TrafficType trafficTyp this.inline = inline; this.eipAssociatePublicIp = associatePublicIP; this.egressdefaultpolicy = egressdefaultpolicy; + this.supportsStrechedL2 = supportsStrechedL2; } public NetworkOfferingVO() { @@ -486,4 +490,9 @@ public void setConcurrentConnections(Integer concurrentConnections) { public void setPublicLb(boolean publicLb) { this.publicLb = publicLb; } + + @Override + public boolean getSupportsStrechedL2() { + return supportsStrechedL2; + } } diff --git a/engine/schema/src/com/cloud/projects/ProjectInvitationVO.java b/engine/schema/src/com/cloud/projects/ProjectInvitationVO.java index 885c148c2b..9775135bea 100644 --- a/engine/schema/src/com/cloud/projects/ProjectInvitationVO.java +++ b/engine/schema/src/com/cloud/projects/ProjectInvitationVO.java @@ -28,8 +28,6 @@ import javax.persistence.Id; import javax.persistence.Table; -import org.apache.cloudstack.acl.IAMEntityType; - import com.cloud.utils.db.GenericDao; @Entity @@ -149,7 +147,7 @@ public long getAccountId() { } @Override - public IAMEntityType getEntityType() { - return IAMEntityType.ProjectInvitation; + public Class getEntityType() { + return ProjectInvitation.class; } } diff --git a/engine/schema/src/com/cloud/service/ServiceOfferingVO.java b/engine/schema/src/com/cloud/service/ServiceOfferingVO.java index 3873dd272f..0ea68b9a63 100755 --- a/engine/schema/src/com/cloud/service/ServiceOfferingVO.java +++ b/engine/schema/src/com/cloud/service/ServiceOfferingVO.java @@ -173,6 +173,7 @@ public ServiceOfferingVO(ServiceOfferingVO offering) { offering.getUseLocalStorage(), offering.getSystemUse(), true, + offering.isCustomizedIops()== null ? false:offering.isCustomizedIops(), offering.getDomainId()); cpu = offering.getCpu(); ramSize = offering.getRamSize(); diff --git a/engine/schema/src/com/cloud/storage/DiskOfferingVO.java b/engine/schema/src/com/cloud/storage/DiskOfferingVO.java index d1a48d20c9..99214b2190 100755 --- a/engine/schema/src/com/cloud/storage/DiskOfferingVO.java +++ b/engine/schema/src/com/cloud/storage/DiskOfferingVO.java @@ -207,7 +207,7 @@ public DiskOfferingVO(String name, String displayText, boolean mirrored, String } public DiskOfferingVO(long id, String name, String displayText, boolean mirrored, String tags, boolean recreatable, - boolean useLocalStorage, boolean systemUse, boolean customized, Long domainId) { + boolean useLocalStorage, boolean systemUse, boolean customized, boolean customizedIops, Long domainId) { this.id = id; type = Type.Service; this.name = name; @@ -217,6 +217,7 @@ public DiskOfferingVO(long id, String name, String displayText, boolean mirrored this.useLocalStorage = useLocalStorage; this.systemUse = systemUse; this.customized = customized; + this.customizedIops = customizedIops; this.domainId = domainId; uuid = UUID.randomUUID().toString(); state = State.Active; diff --git a/engine/schema/src/com/cloud/storage/GuestOSHypervisorVO.java b/engine/schema/src/com/cloud/storage/GuestOSHypervisorVO.java index 1fbc9d7178..087649b887 100644 --- a/engine/schema/src/com/cloud/storage/GuestOSHypervisorVO.java +++ b/engine/schema/src/com/cloud/storage/GuestOSHypervisorVO.java @@ -57,6 +57,9 @@ public class GuestOSHypervisorVO implements GuestOSHypervisor { @Column(name = GenericDao.CREATED_COLUMN) Date created; + @Column(name = "is_user_defined") + private boolean isUserDefined; + @Override public long getId() { return id; @@ -120,4 +123,13 @@ public void setUuid(String uuid) { public void setRemoved(Date removed) { this.removed = removed; } + + @Override + public boolean getIsUserDefined() { + return isUserDefined; + } + + public void setIsUserDefined(boolean isUserDefined) { + this.isUserDefined = isUserDefined; + } } diff --git a/engine/schema/src/com/cloud/storage/GuestOSVO.java b/engine/schema/src/com/cloud/storage/GuestOSVO.java index a0040beeaf..f04f9a4208 100644 --- a/engine/schema/src/com/cloud/storage/GuestOSVO.java +++ b/engine/schema/src/com/cloud/storage/GuestOSVO.java @@ -54,6 +54,9 @@ public class GuestOSVO implements GuestOS { @Column(name = GenericDao.CREATED_COLUMN) private Date created; + @Column(name = "is_user_defined") + private boolean isUserDefined; + @Override public long getId() { return id; @@ -108,4 +111,13 @@ public void setRemoved(Date removed) { public Date getRemoved() { return removed; } + + @Override + public boolean getIsUserDefined() { + return isUserDefined; + } + + public void setIsUserDefined(boolean isUserDefined) { + this.isUserDefined = isUserDefined; + } } diff --git a/engine/schema/src/com/cloud/storage/SnapshotVO.java b/engine/schema/src/com/cloud/storage/SnapshotVO.java index 4c8ceb7cdd..dae049f604 100644 --- a/engine/schema/src/com/cloud/storage/SnapshotVO.java +++ b/engine/schema/src/com/cloud/storage/SnapshotVO.java @@ -30,8 +30,6 @@ import com.google.gson.annotations.Expose; -import org.apache.cloudstack.acl.IAMEntityType; - import com.cloud.hypervisor.Hypervisor.HypervisorType; import com.cloud.utils.db.GenericDao; @@ -239,7 +237,7 @@ public void setUuid(String uuid) { } @Override - public IAMEntityType getEntityType() { - return IAMEntityType.Snapshot; + public Class getEntityType() { + return Snapshot.class; } } diff --git a/engine/schema/src/com/cloud/storage/VMTemplateVO.java b/engine/schema/src/com/cloud/storage/VMTemplateVO.java index c0b7d0fc02..9a77cbf873 100755 --- a/engine/schema/src/com/cloud/storage/VMTemplateVO.java +++ b/engine/schema/src/com/cloud/storage/VMTemplateVO.java @@ -31,8 +31,6 @@ import javax.persistence.TemporalType; import javax.persistence.Transient; -import org.apache.cloudstack.acl.IAMEntityType; - import com.cloud.hypervisor.Hypervisor.HypervisorType; import com.cloud.storage.Storage.ImageFormat; import com.cloud.storage.Storage.TemplateType; @@ -635,7 +633,7 @@ public void setUpdated(Date updated) { } @Override - public IAMEntityType getEntityType() { - return IAMEntityType.VirtualMachineTemplate; + public Class getEntityType() { + return VirtualMachineTemplate.class; } } diff --git a/engine/schema/src/com/cloud/storage/VolumeVO.java b/engine/schema/src/com/cloud/storage/VolumeVO.java index af99a16ffa..50b235e6c9 100755 --- a/engine/schema/src/com/cloud/storage/VolumeVO.java +++ b/engine/schema/src/com/cloud/storage/VolumeVO.java @@ -32,8 +32,6 @@ import javax.persistence.TemporalType; import javax.persistence.Transient; -import org.apache.cloudstack.acl.IAMEntityType; - import com.cloud.storage.Storage.StoragePoolType; import com.cloud.utils.NumbersUtil; import com.cloud.utils.db.GenericDao; @@ -554,6 +552,15 @@ public boolean isDisplayVolume() { return displayVolume; } + @Override + public boolean isDisplay(){ + return displayVolume; + } + + public void setDisplay(boolean display){ + this.displayVolume = display; + } + public void setDisplayVolume(boolean displayVolume) { this.displayVolume = displayVolume; } @@ -601,7 +608,7 @@ public Integer getHypervisorSnapshotReserve() { } @Override - public IAMEntityType getEntityType() { - return IAMEntityType.Volume; + public Class getEntityType() { + return Volume.class; } } diff --git a/engine/schema/src/com/cloud/storage/dao/GuestOSHypervisorDao.java b/engine/schema/src/com/cloud/storage/dao/GuestOSHypervisorDao.java index 5b6e7198f0..a777516526 100644 --- a/engine/schema/src/com/cloud/storage/dao/GuestOSHypervisorDao.java +++ b/engine/schema/src/com/cloud/storage/dao/GuestOSHypervisorDao.java @@ -27,4 +27,6 @@ public interface GuestOSHypervisorDao extends GenericDao guestOsSearch; protected final SearchBuilder mappingSearch; + protected final SearchBuilder userDefinedMappingSearch; protected GuestOSHypervisorDaoImpl() { guestOsSearch = createSearchBuilder(); @@ -45,6 +46,13 @@ protected GuestOSHypervisorDaoImpl() { mappingSearch.and("hypervisor_type", mappingSearch.entity().getHypervisorType(), SearchCriteria.Op.EQ); mappingSearch.and("hypervisor_version", mappingSearch.entity().getHypervisorVersion(), SearchCriteria.Op.EQ); mappingSearch.done(); + + userDefinedMappingSearch = createSearchBuilder(); + userDefinedMappingSearch.and("guest_os_id", userDefinedMappingSearch.entity().getGuestOsId(), SearchCriteria.Op.EQ); + userDefinedMappingSearch.and("hypervisor_type", userDefinedMappingSearch.entity().getHypervisorType(), SearchCriteria.Op.EQ); + userDefinedMappingSearch.and("hypervisor_version", userDefinedMappingSearch.entity().getHypervisorVersion(), SearchCriteria.Op.EQ); + userDefinedMappingSearch.and("is_user_defined", userDefinedMappingSearch.entity().getIsUserDefined(), SearchCriteria.Op.EQ); + userDefinedMappingSearch.done(); } @Override @@ -58,9 +66,27 @@ public HypervisorType findHypervisorTypeByGuestOsId(long guestOsId) { @Override public GuestOSHypervisorVO findByOsIdAndHypervisor(long guestOsId, String hypervisorType, String hypervisorVersion) { SearchCriteria sc = mappingSearch.create(); + String version = "default"; + if (!(hypervisorVersion == null || hypervisorVersion.isEmpty())) { + version = hypervisorVersion; + } + sc.setParameters("guest_os_id", guestOsId); + sc.setParameters("hypervisor_type", hypervisorType); + sc.setParameters("hypervisor_version", version); + return findOneBy(sc); + } + + @Override + public GuestOSHypervisorVO findByOsIdAndHypervisorAndUserDefined(long guestOsId, String hypervisorType, String hypervisorVersion, boolean isUserDefined) { + SearchCriteria sc = userDefinedMappingSearch.create(); + String version = "default"; + if (!(hypervisorVersion == null || hypervisorVersion.isEmpty())) { + version = hypervisorVersion; + } sc.setParameters("guest_os_id", guestOsId); sc.setParameters("hypervisor_type", hypervisorType); - sc.setParameters("hypervisor_version", hypervisorVersion); + sc.setParameters("hypervisor_version", version); + sc.setParameters("is_user_defined", isUserDefined); return findOneBy(sc); } diff --git a/engine/schema/src/com/cloud/tags/ResourceTagVO.java b/engine/schema/src/com/cloud/tags/ResourceTagVO.java index 6b743ffd23..eadddd1e31 100644 --- a/engine/schema/src/com/cloud/tags/ResourceTagVO.java +++ b/engine/schema/src/com/cloud/tags/ResourceTagVO.java @@ -27,8 +27,6 @@ import javax.persistence.Id; import javax.persistence.Table; -import org.apache.cloudstack.acl.IAMEntityType; - import com.cloud.server.ResourceTag; @@ -166,7 +164,7 @@ public String getResourceUuid() { } @Override - public IAMEntityType getEntityType() { - return IAMEntityType.ResourceTag; + public Class getEntityType() { + return ResourceTag.class; } } diff --git a/engine/schema/src/com/cloud/upgrade/dao/Upgrade410to420.java b/engine/schema/src/com/cloud/upgrade/dao/Upgrade410to420.java index 82b6d8481a..671cbb7269 100755 --- a/engine/schema/src/com/cloud/upgrade/dao/Upgrade410to420.java +++ b/engine/schema/src/com/cloud/upgrade/dao/Upgrade410to420.java @@ -738,8 +738,8 @@ private void updateOverCommitRatioClusterDetails(Connection conn) { pstmt2.execute(); } else { //update cluster_details table with the default overcommit ratios. - pstmt1.setLong(1, id); - pstmt1.setString(2, "1"); + pstmt1.setLong(1,id); + pstmt1.setString(2,global_cpu_overprovisioning_factor); pstmt1.execute(); pstmt2.setLong(1, id); pstmt2.setString(2, "1"); diff --git a/engine/schema/src/com/cloud/upgrade/dao/Upgrade420to421.java b/engine/schema/src/com/cloud/upgrade/dao/Upgrade420to421.java index c3a6b0688a..a0093f8fe4 100644 --- a/engine/schema/src/com/cloud/upgrade/dao/Upgrade420to421.java +++ b/engine/schema/src/com/cloud/upgrade/dao/Upgrade420to421.java @@ -23,6 +23,7 @@ import java.sql.ResultSet; import java.sql.SQLException; +import com.cloud.hypervisor.Hypervisor; import org.apache.log4j.Logger; import com.cloud.utils.exception.CloudRuntimeException; @@ -64,10 +65,12 @@ public File[] getCleanupScripts() { @Override public void performDataMigration(Connection conn) { upgradeResourceCount(conn); - updateCpuOverprovisioning(conn); + updateOverprovisioningPerVm(conn); } - private void updateCpuOverprovisioning(Connection conn) { + + + private void updateOverprovisioningPerVm(Connection conn) { PreparedStatement pstmt1 = null; PreparedStatement pstmt2 = null; PreparedStatement pstmt3 = null; @@ -79,28 +82,49 @@ private void updateCpuOverprovisioning(Connection conn) { try { pstmt1 = conn.prepareStatement("select value from `cloud`.`configuration` where name='cpu.overprovisioning.factor'"); result1 = pstmt1.executeQuery(); - String overprov = "1"; - if (result1.next()) { - overprov = result1.getString(1); + String cpuoverprov = "1"; + if(result1.next()){ + cpuoverprov = result1.getString(1); + } + pstmt1 = conn.prepareStatement("select value from `cloud`.`configuration` where name='mem.overprovisioning.factor'"); + result1 = pstmt1.executeQuery(); + String memoverprov = "1"; + if(result1.next()){ + memoverprov = result1.getString(1); } + // Need to populate only when overprovisioning factor doesn't pre exist. s_logger.debug("Starting updating user_vm_details with cpu/memory overprovisioning factors"); - pstmt2 = - conn.prepareStatement("select id from `cloud`.`vm_instance` where removed is null and id not in (select vm_id from `cloud`.`user_vm_details` where name='cpuOvercommitRatio')"); + pstmt2 = conn.prepareStatement("select id, hypervisor_type from `cloud`.`vm_instance` where removed is null and id not in (select vm_id from `cloud`.`user_vm_details` where name='cpuOvercommitRatio')"); pstmt3 = conn.prepareStatement("INSERT IGNORE INTO cloud.user_vm_details (vm_id, name, value) VALUES (?, ?, ?)"); result2 = pstmt2.executeQuery(); while (result2.next()) { - //For cpu - pstmt3.setLong(1, result2.getLong(1)); - pstmt3.setString(2, "cpuOvercommitRatio"); - pstmt3.setString(3, overprov); - pstmt3.executeUpdate(); + String hypervisor_type = result2.getString(2); + if (hypervisor_type.equalsIgnoreCase(Hypervisor.HypervisorType.VMware.name())) { + //For cpu + pstmt3.setLong(1, result2.getLong(1)); + pstmt3.setString(2, "cpuOvercommitRatio"); + pstmt3.setString(3, cpuoverprov); + pstmt3.executeUpdate(); + + // For memory + pstmt3.setLong(1, result2.getLong(1)); + pstmt3.setString(2, "memoryOvercommitRatio"); + pstmt3.setString(3, memoverprov); // memory overprovisioning was used to reserve memory in case of VMware. + pstmt3.executeUpdate(); + } else { + //For cpu + pstmt3.setLong(1, result2.getLong(1)); + pstmt3.setString(2, "cpuOvercommitRatio"); + pstmt3.setString(3, cpuoverprov); + pstmt3.executeUpdate(); - // For memory - pstmt3.setLong(1, result2.getLong(1)); - pstmt3.setString(2, "memoryOvercommitRatio"); - pstmt3.setString(3, "1"); // memory overprovisioning didn't exist earlier. - pstmt3.executeUpdate(); + // For memory + pstmt3.setLong(1, result2.getLong(1)); + pstmt3.setString(2, "memoryOvercommitRatio"); + pstmt3.setString(3, "1"); // memory overprovisioning didn't exist earlier. + pstmt3.executeUpdate(); + } } s_logger.debug("Done updating user_vm_details with cpu/memory overprovisioning factors"); @@ -108,13 +132,23 @@ private void updateCpuOverprovisioning(Connection conn) { throw new CloudRuntimeException("Unable to update cpu/memory overprovisioning factors", e); } finally { try { - if (pstmt1 != null) + if (pstmt1 != null && !pstmt1.isClosed()) { pstmt1.close(); - if (pstmt2 != null) + } + if (pstmt2 != null && !pstmt2.isClosed()) { pstmt2.close(); - if (pstmt3 != null) + } + if (pstmt3 != null && !pstmt3.isClosed()) { pstmt3.close(); - } catch (SQLException e) { + } + if (result1 != null) { + result1.close(); + } + if (result2 != null) { + result2.close(); + } + }catch (SQLException e){ + } } diff --git a/engine/schema/src/com/cloud/upgrade/dao/Upgrade430to440.java b/engine/schema/src/com/cloud/upgrade/dao/Upgrade430to440.java index 922a892be0..26277ddc67 100644 --- a/engine/schema/src/com/cloud/upgrade/dao/Upgrade430to440.java +++ b/engine/schema/src/com/cloud/upgrade/dao/Upgrade430to440.java @@ -61,6 +61,7 @@ public File[] getPrepareScripts() { public void performDataMigration(Connection conn) { populateIAMGroupAccountMap(conn); secondaryIpsAccountAndDomainIdsUpdate(conn); + moveCidrsToTheirOwnTable(conn); } // populate iam_group_account_map table for existing accounts @@ -244,7 +245,58 @@ private void secondaryIpsAccountAndDomainIdsUpdate(Connection conn) { } + private void moveCidrsToTheirOwnTable(Connection conn) { + PreparedStatement pstmtItem = null; + PreparedStatement pstmtCidr = null; + ResultSet rsItems = null; + String networkAclItemSql = "SELECT id, cidr FROM `cloud`.`network_acl_item`"; + + s_logger.debug("Moving network acl item cidrs to a row per cidr"); + try { + pstmtItem = conn.prepareStatement(networkAclItemSql); + rsItems = pstmtItem.executeQuery(); + + // for each network acl item + while(rsItems.next()) { + long itemId = rsItems.getLong(1); + // get the source cidr list + String cidrList = rsItems.getString(2); + s_logger.debug("Moving '" + cidrList + "' to a row per cidr"); + // split it + String[] cidrArray = cidrList.split(","); + // insert a record per cidr + String networkAclItemCidrSql = "INSERT INTO `cloud`.`network_acl_item_cidrs` (network_acl_item_id, cidr) VALUES (?,?)"; + for(String cidr: cidrArray) + { + pstmtCidr = conn.prepareStatement(networkAclItemCidrSql); + pstmtCidr.setLong(1,itemId); + pstmtCidr.setString(2,cidr); + pstmtCidr.executeUpdate(); + } + pstmtCidr.close(); + } + } catch (SQLException e) { + throw new CloudRuntimeException("Exception while Moving network acl item cidrs to a row per cidr", e); + } finally { + + if (pstmtItem != null) { + try { + pstmtItem.close(); + + } catch (SQLException e) { + } + } + if (pstmtCidr != null) { + try { + pstmtCidr.close(); + + } catch (SQLException e) { + } + } + } + s_logger.debug("Done moving network acl item cidrs to a row per cidr"); + } @Override diff --git a/engine/schema/src/com/cloud/user/AccountVO.java b/engine/schema/src/com/cloud/user/AccountVO.java index 674cdb9101..0f5a0446e9 100644 --- a/engine/schema/src/com/cloud/user/AccountVO.java +++ b/engine/schema/src/com/cloud/user/AccountVO.java @@ -28,8 +28,6 @@ import javax.persistence.Id; import javax.persistence.Table; -import org.apache.cloudstack.acl.IAMEntityType; - import com.cloud.utils.db.GenericDao; @Entity @@ -190,7 +188,7 @@ public boolean isDefault() { } @Override - public IAMEntityType getEntityType() { - return IAMEntityType.Account; + public Class getEntityType() { + return Account.class; } } diff --git a/engine/schema/src/com/cloud/user/SSHKeyPairVO.java b/engine/schema/src/com/cloud/user/SSHKeyPairVO.java index 4dc03c45b0..fd7173ee7a 100644 --- a/engine/schema/src/com/cloud/user/SSHKeyPairVO.java +++ b/engine/schema/src/com/cloud/user/SSHKeyPairVO.java @@ -24,8 +24,6 @@ import javax.persistence.Table; import javax.persistence.Transient; -import org.apache.cloudstack.acl.IAMEntityType; - @Entity @Table(name = "ssh_keypairs") public class SSHKeyPairVO implements SSHKeyPair { @@ -117,7 +115,7 @@ public void setPrivateKey(String privateKey) { } @Override - public IAMEntityType getEntityType() { - return IAMEntityType.SSHKeyPair; + public Class getEntityType() { + return SSHKeyPair.class; } } diff --git a/engine/schema/src/com/cloud/vm/InstanceGroupVO.java b/engine/schema/src/com/cloud/vm/InstanceGroupVO.java index 9b463d3428..395751b705 100644 --- a/engine/schema/src/com/cloud/vm/InstanceGroupVO.java +++ b/engine/schema/src/com/cloud/vm/InstanceGroupVO.java @@ -28,8 +28,6 @@ import javax.persistence.SecondaryTable; import javax.persistence.Table; -import org.apache.cloudstack.acl.IAMEntityType; - import com.cloud.utils.db.GenericDao; @Entity @@ -120,7 +118,7 @@ public Short getAccountType() { } @Override - public IAMEntityType getEntityType() { - return IAMEntityType.InstanceGroup; + public Class getEntityType() { + return InstanceGroup.class; } } diff --git a/engine/schema/src/com/cloud/vm/VMInstanceVO.java b/engine/schema/src/com/cloud/vm/VMInstanceVO.java index ddeebfeb75..3d4337f374 100644 --- a/engine/schema/src/com/cloud/vm/VMInstanceVO.java +++ b/engine/schema/src/com/cloud/vm/VMInstanceVO.java @@ -36,8 +36,6 @@ import javax.persistence.TemporalType; import javax.persistence.Transient; -import org.apache.cloudstack.acl.IAMEntityType; - import com.cloud.hypervisor.Hypervisor.HypervisorType; import com.cloud.utils.db.Encrypt; import com.cloud.utils.db.GenericDao; @@ -386,10 +384,16 @@ public boolean isHaEnabled() { return haEnabled; } + //FIXME - Remove this and use isDisplay() instead public boolean isDisplayVm() { return displayVm; } + @Override + public boolean isDisplay() { + return displayVm; + } + public void setDisplayVm(boolean displayVm) { this.displayVm = displayVm; } @@ -413,8 +417,8 @@ public Long getPodIdToDeployIn() { return podIdToDeployIn; } - public void setPodId(long podId) { - podIdToDeployIn = podId; + public void setPodId(Long podId) { + this.podIdToDeployIn = podId; } public void setPrivateMacAddress(String privateMacAddress) { @@ -461,7 +465,7 @@ public void setDetails(Map details) { @Override public String toString() { if (toString == null) { - toString = new StringBuilder("VM[").append(type.toString()).append("|").append(hostName).append("]").toString(); + toString = new StringBuilder("VM[").append(type.toString()).append("|").append(getInstanceName()).append("]").toString(); } return toString; } @@ -506,8 +510,8 @@ public Boolean isDynamicallyScalable() { } @Override - public IAMEntityType getEntityType() { - return IAMEntityType.VirtualMachine; + public Class getEntityType() { + return VirtualMachine.class; } public VirtualMachine.PowerState getPowerState() { diff --git a/engine/schema/src/com/cloud/vm/dao/DomainRouterDao.java b/engine/schema/src/com/cloud/vm/dao/DomainRouterDao.java index e3f75fabd7..72ff8a91dd 100755 --- a/engine/schema/src/com/cloud/vm/dao/DomainRouterDao.java +++ b/engine/schema/src/com/cloud/vm/dao/DomainRouterDao.java @@ -108,6 +108,8 @@ public interface DomainRouterDao extends GenericDao { */ List listByStateAndNetworkType(State state, Network.GuestType type, long mgmtSrvrId); + List listByStateAndManagementServer(State state, long mgmtSrvrId); + List findByNetworkOutsideThePod(long networkId, long podId, State state, Role role); List listByNetworkAndPodAndRole(long networkId, long podId, Role role); diff --git a/engine/schema/src/com/cloud/vm/dao/DomainRouterDaoImpl.java b/engine/schema/src/com/cloud/vm/dao/DomainRouterDaoImpl.java index 6b62f56873..ea919ac536 100755 --- a/engine/schema/src/com/cloud/vm/dao/DomainRouterDaoImpl.java +++ b/engine/schema/src/com/cloud/vm/dao/DomainRouterDaoImpl.java @@ -60,6 +60,7 @@ public class DomainRouterDaoImpl extends GenericDaoBase im protected SearchBuilder StateNetworkTypeSearch; protected SearchBuilder OutsidePodSearch; protected SearchBuilder clusterSearch; + protected SearchBuilder SearchByStateAndManagementServerId; @Inject HostDao _hostsDao; @Inject @@ -130,6 +131,14 @@ protected void init() { StateNetworkTypeSearch.join("host", joinHost, joinHost.entity().getId(), StateNetworkTypeSearch.entity().getHostId(), JoinType.INNER); StateNetworkTypeSearch.done(); + SearchByStateAndManagementServerId = createSearchBuilder(); + SearchByStateAndManagementServerId.and("state", SearchByStateAndManagementServerId.entity().getState(), Op.EQ); + + SearchBuilder joinHost2 = _hostsDao.createSearchBuilder(); + joinHost2.and("mgmtServerId", joinHost2.entity().getManagementServerId(), Op.EQ); + SearchByStateAndManagementServerId.join("host", joinHost2, joinHost2.entity().getId(), SearchByStateAndManagementServerId.entity().getHostId(), JoinType.INNER); + SearchByStateAndManagementServerId.done(); + OutsidePodSearch = createSearchBuilder(); SearchBuilder joinRouterNetwork2 = _routerNetworkDao.createSearchBuilder(); joinRouterNetwork2.and("networkId", joinRouterNetwork2.entity().getNetworkId(), Op.EQ); @@ -293,6 +302,15 @@ public List listByStateAndNetworkType(State state, Network.Guest return routers; } + @Override + public List listByStateAndManagementServer(State state, long mgmtSrvrId) { + SearchCriteria sc = SearchByStateAndManagementServerId.create(); + sc.setParameters("state", state); + sc.setJoinParameters("host", "mgmtServerId", mgmtSrvrId); + + return listBy(sc); + } + @Override public List findByNetworkOutsideThePod(long networkId, long podId, State state, Role role) { SearchCriteria sc = OutsidePodSearch.create(); diff --git a/engine/schema/src/com/cloud/vm/dao/NicIpAliasVO.java b/engine/schema/src/com/cloud/vm/dao/NicIpAliasVO.java index 3df9909620..2f000fde8a 100644 --- a/engine/schema/src/com/cloud/vm/dao/NicIpAliasVO.java +++ b/engine/schema/src/com/cloud/vm/dao/NicIpAliasVO.java @@ -28,8 +28,6 @@ import javax.persistence.Id; import javax.persistence.Table; -import org.apache.cloudstack.acl.IAMEntityType; - import com.cloud.utils.db.GenericDao; import com.cloud.utils.net.NetUtils; import com.cloud.vm.NicIpAlias; @@ -235,7 +233,7 @@ public String getStartIpOfSubnet() { } @Override - public IAMEntityType getEntityType() { - return IAMEntityType.NicIpAlias; + public Class getEntityType() { + return NicIpAlias.class; } } diff --git a/engine/schema/src/com/cloud/vm/dao/NicSecondaryIpVO.java b/engine/schema/src/com/cloud/vm/dao/NicSecondaryIpVO.java index 995da17ddc..f8730aac5d 100644 --- a/engine/schema/src/com/cloud/vm/dao/NicSecondaryIpVO.java +++ b/engine/schema/src/com/cloud/vm/dao/NicSecondaryIpVO.java @@ -26,8 +26,6 @@ import javax.persistence.Id; import javax.persistence.Table; -import org.apache.cloudstack.acl.IAMEntityType; - import com.cloud.utils.db.GenericDao; import com.cloud.vm.NicSecondaryIp; @@ -128,7 +126,7 @@ public long getVmId() { } @Override - public IAMEntityType getEntityType() { - return IAMEntityType.NicSecondaryIp; + public Class getEntityType() { + return NicSecondaryIp.class; } } diff --git a/engine/schema/src/com/cloud/vm/dao/VMInstanceDao.java b/engine/schema/src/com/cloud/vm/dao/VMInstanceDao.java index 453d222cdf..6ba7c36521 100644 --- a/engine/schema/src/com/cloud/vm/dao/VMInstanceDao.java +++ b/engine/schema/src/com/cloud/vm/dao/VMInstanceDao.java @@ -17,6 +17,7 @@ package com.cloud.vm.dao; import java.util.Date; +import java.util.HashMap; import java.util.List; import java.util.Map; @@ -133,4 +134,6 @@ public interface VMInstanceDao extends GenericDao, StateDao< void resetVmPowerStateTracking(long instanceId); void resetHostPowerStateTracking(long hostId); + + HashMap countVgpuVMs(Long dcId, Long podId, Long clusterId); } diff --git a/engine/schema/src/com/cloud/vm/dao/VMInstanceDaoImpl.java b/engine/schema/src/com/cloud/vm/dao/VMInstanceDaoImpl.java index 2f25f577f4..bcd6fa78a7 100644 --- a/engine/schema/src/com/cloud/vm/dao/VMInstanceDaoImpl.java +++ b/engine/schema/src/com/cloud/vm/dao/VMInstanceDaoImpl.java @@ -115,6 +115,13 @@ public class VMInstanceDaoImpl extends GenericDaoBase implem private static final String ORDER_HOSTS_NUMBER_OF_VMS_FOR_ACCOUNT_PART2 = " GROUP BY host.id ORDER BY 2 ASC "; + private static final String COUNT_VMS_BASED_ON_VGPU_TYPES1 = + "SELECT pci, type, SUM(vmcount) FROM (SELECT MAX(IF(offering.name = 'pciDevice',value,'')) AS pci, MAX(IF(offering.name = 'vgpuType', value,'')) " + + "AS type, COUNT(DISTINCT vm.id) AS vmcount FROM service_offering_details offering INNER JOIN vm_instance vm ON offering.service_offering_id = vm.service_offering_id " + + "INNER JOIN `cloud`.`host` ON vm.host_id = host.id WHERE vm.state = 'Running' AND host.data_center_id = ? "; + private static final String COUNT_VMS_BASED_ON_VGPU_TYPES2 = + "GROUP BY offering.service_offering_id) results GROUP BY pci, type"; + @Inject protected HostDao _hostDao; @@ -437,6 +444,9 @@ public boolean updateState(State oldState, Event event, State newState, VirtualM return true; } + // lock the target row at beginning to avoid lock-promotion caused deadlock + lockRow(vm.getId(), true); + SearchCriteria sc = StateChangeSearch.create(); sc.setParameters("id", vmi.getId()); sc.setParameters("states", oldState); @@ -452,41 +462,29 @@ public boolean updateState(State oldState, Event event, State newState, VirtualM ub.set(vmi, _updateTimeAttr, new Date()); int result = update(vmi, sc); - if (result == 0 && s_logger.isDebugEnabled()) { - + if (result == 0) { VMInstanceVO vo = findByIdIncludingRemoved(vm.getId()); - if (vo != null) { - StringBuilder str = new StringBuilder("Unable to update ").append(vo.toString()); - str.append(": DB Data={Host=") - .append(vo.getHostId()) - .append("; State=") - .append(vo.getState().toString()) - .append("; updated=") - .append(vo.getUpdated()) - .append("; time=") - .append(vo.getUpdateTime()); - str.append("} New Data: {Host=") - .append(vm.getHostId()) - .append("; State=") - .append(vm.getState().toString()) - .append("; updated=") - .append(vmi.getUpdated()) - .append("; time=") - .append(vo.getUpdateTime()); - str.append("} Stale Data: {Host=") - .append(oldHostId) - .append("; State=") - .append(oldState) - .append("; updated=") - .append(oldUpdated) - .append("; time=") - .append(oldUpdateDate) - .append("}"); - s_logger.debug(str.toString()); - - } else { - s_logger.debug("Unable to update the vm id=" + vm.getId() + "; the vm either doesn't exist or already removed"); + if (s_logger.isDebugEnabled()) { + if (vo != null) { + StringBuilder str = new StringBuilder("Unable to update ").append(vo.toString()); + str.append(": DB Data={Host=").append(vo.getHostId()).append("; State=").append(vo.getState().toString()).append("; updated=").append(vo.getUpdated()) + .append("; time=").append(vo.getUpdateTime()); + str.append("} New Data: {Host=").append(vm.getHostId()).append("; State=").append(vm.getState().toString()).append("; updated=").append(vmi.getUpdated()) + .append("; time=").append(vo.getUpdateTime()); + str.append("} Stale Data: {Host=").append(oldHostId).append("; State=").append(oldState).append("; updated=").append(oldUpdated).append("; time=") + .append(oldUpdateDate).append("}"); + s_logger.debug(str.toString()); + + } else { + s_logger.debug("Unable to update the vm id=" + vm.getId() + "; the vm either doesn't exist or already removed"); + } + } + + if (vo != null && vo.getState() == newState) { + // allow for concurrent update if target state has already been matched + s_logger.debug("VM " + vo.getInstanceName() + " state has been already been updated to " + newState); + return true; } } return result > 0; @@ -649,6 +647,45 @@ public List listHostIdsByVmCount(long dcId, Long podId, Long clusterId, lo } } + @Override + public HashMap countVgpuVMs(Long dcId, Long podId, Long clusterId) { + StringBuilder finalQuery = new StringBuilder(); + TransactionLegacy txn = TransactionLegacy.currentTxn(); + PreparedStatement pstmt = null; + List resourceIdList = new ArrayList(); + HashMap result = new HashMap(); + + resourceIdList.add(dcId); + finalQuery.append(COUNT_VMS_BASED_ON_VGPU_TYPES1); + + if (podId != null) { + finalQuery.append(" AND host.pod_id = ?"); + resourceIdList.add(podId); + } + + if (clusterId != null) { + finalQuery.append(" AND host.cluster_id = ?"); + resourceIdList.add(clusterId); + } + finalQuery.append(COUNT_VMS_BASED_ON_VGPU_TYPES2); + + try { + pstmt = txn.prepareAutoCloseStatement(finalQuery.toString()); + for (int i = 0; i < resourceIdList.size(); i++) { + pstmt.setLong(1 + i, resourceIdList.get(i)); + } + ResultSet rs = pstmt.executeQuery(); + while (rs.next()) { + result.put(rs.getString(1).concat(rs.getString(2)), rs.getLong(3)); + } + return result; + } catch (SQLException e) { + throw new CloudRuntimeException("DB Exception on: " + finalQuery, e); + } catch (Throwable e) { + throw new CloudRuntimeException("Caught: " + finalQuery, e); + } + } + @Override public Long countRunningByAccount(long accountId) { SearchCriteria sc = CountRunningByAccount.create(); diff --git a/engine/schema/src/com/cloud/vm/snapshot/VMSnapshotVO.java b/engine/schema/src/com/cloud/vm/snapshot/VMSnapshotVO.java index 042b276fe4..df2966d45b 100644 --- a/engine/schema/src/com/cloud/vm/snapshot/VMSnapshotVO.java +++ b/engine/schema/src/com/cloud/vm/snapshot/VMSnapshotVO.java @@ -33,7 +33,6 @@ import javax.persistence.TemporalType; import javax.persistence.Transient; -import org.apache.cloudstack.acl.IAMEntityType; import org.apache.cloudstack.engine.subsystem.api.storage.VMSnapshotOptions; import com.cloud.utils.db.GenericDao; @@ -246,7 +245,7 @@ public void setRemoved(Date removed) { } @Override - public IAMEntityType getEntityType() { - return IAMEntityType.VMSnapshot; + public Class getEntityType() { + return VMSnapshot.class; } } diff --git a/engine/schema/src/org/apache/cloudstack/affinity/AffinityGroupVO.java b/engine/schema/src/org/apache/cloudstack/affinity/AffinityGroupVO.java index b9fda8e9e3..03274ad438 100644 --- a/engine/schema/src/org/apache/cloudstack/affinity/AffinityGroupVO.java +++ b/engine/schema/src/org/apache/cloudstack/affinity/AffinityGroupVO.java @@ -28,7 +28,6 @@ import javax.persistence.Table; import org.apache.cloudstack.acl.ControlledEntity; -import org.apache.cloudstack.acl.IAMEntityType; @Entity @Table(name = ("affinity_group")) @@ -126,8 +125,8 @@ public String toString() { } @Override - public IAMEntityType getEntityType() { - return IAMEntityType.AffinityGroup; + public Class getEntityType() { + return AffinityGroup.class; } } diff --git a/engine/schema/src/org/apache/cloudstack/engine/cloud/entity/api/db/VMEntityVO.java b/engine/schema/src/org/apache/cloudstack/engine/cloud/entity/api/db/VMEntityVO.java index 7403d62fcf..b20cae320e 100644 --- a/engine/schema/src/org/apache/cloudstack/engine/cloud/entity/api/db/VMEntityVO.java +++ b/engine/schema/src/org/apache/cloudstack/engine/cloud/entity/api/db/VMEntityVO.java @@ -37,8 +37,6 @@ import javax.persistence.TemporalType; import javax.persistence.Transient; -import org.apache.cloudstack.acl.IAMEntityType; - import com.cloud.hypervisor.Hypervisor.HypervisorType; import com.cloud.utils.db.Encrypt; import com.cloud.utils.db.GenericDao; @@ -175,6 +173,9 @@ public class VMEntityVO implements VirtualMachine, FiniteStateObject getEntityType() { + return VirtualMachine.class; + } + + @Override + public boolean isDisplay() { + return display; + } + + public void setDisplay(boolean display) { + this.display = display; } } diff --git a/engine/schema/src/org/apache/cloudstack/region/gslb/GlobalLoadBalancerRuleVO.java b/engine/schema/src/org/apache/cloudstack/region/gslb/GlobalLoadBalancerRuleVO.java index a37fec2d51..88cd0003a2 100644 --- a/engine/schema/src/org/apache/cloudstack/region/gslb/GlobalLoadBalancerRuleVO.java +++ b/engine/schema/src/org/apache/cloudstack/region/gslb/GlobalLoadBalancerRuleVO.java @@ -28,8 +28,6 @@ import javax.persistence.Id; import javax.persistence.Table; -import org.apache.cloudstack.acl.IAMEntityType; - import com.cloud.region.ha.GlobalLoadBalancerRule; @Entity @@ -191,7 +189,7 @@ public GlobalLoadBalancerRule.State getState() { } @Override - public IAMEntityType getEntityType() { - return IAMEntityType.GlobalLoadBalancerRule; + public Class getEntityType() { + return GlobalLoadBalancerRule.class; } } diff --git a/engine/schema/src/org/apache/cloudstack/resourcedetail/LBHealthCheckPolicyDetailVO.java b/engine/schema/src/org/apache/cloudstack/resourcedetail/LBHealthCheckPolicyDetailVO.java new file mode 100644 index 0000000000..52b30ff18b --- /dev/null +++ b/engine/schema/src/org/apache/cloudstack/resourcedetail/LBHealthCheckPolicyDetailVO.java @@ -0,0 +1,78 @@ +// Copyright 2012 Citrix Systems, Inc. Licensed under the +// Apache License, Version 2.0 (the "License"); you may not use this +// file except in compliance with the License. Citrix Systems, Inc. +// reserves all rights not expressly granted by 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. +// +// Automatically generated by addcopyright.py at 04/03/2012 +package org.apache.cloudstack.resourcedetail; + +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 org.apache.cloudstack.api.ResourceDetail; + +@Entity +@Table(name = "load_balancer_healthcheck_policy_details") +public class LBHealthCheckPolicyDetailVO implements ResourceDetail{ + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) + @Column(name = "id") + private long id; + + @Column(name = "lb_policy_id") + private long resourceId; + + @Column(name = "name") + private String name; + + @Column(name = "value", length = 1024) + private String value; + + @Column(name = "display") + private boolean display = true; + + public LBHealthCheckPolicyDetailVO() { + } + + public LBHealthCheckPolicyDetailVO(long id, String name, String value, boolean display) { + this.resourceId = id; + this.name = name; + this.value = value; + this.display = display; + } + + @Override + public long getId() { + return id; + } + + @Override + public String getName() { + return name; + } + + @Override + public String getValue() { + return value; + } + + @Override + public long getResourceId() { + return resourceId; + } + + @Override + public boolean isDisplay() { + return display; + } +} diff --git a/engine/schema/src/org/apache/cloudstack/resourcedetail/LBStickinessPolicyDetailVO.java b/engine/schema/src/org/apache/cloudstack/resourcedetail/LBStickinessPolicyDetailVO.java new file mode 100644 index 0000000000..caa2d90000 --- /dev/null +++ b/engine/schema/src/org/apache/cloudstack/resourcedetail/LBStickinessPolicyDetailVO.java @@ -0,0 +1,82 @@ +// 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.resourcedetail; + +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 org.apache.cloudstack.api.ResourceDetail; + +@Entity +@Table(name = "load_balancer_stickiness_policy_details") +public class LBStickinessPolicyDetailVO implements ResourceDetail { + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) + @Column(name = "id") + private long id; + + @Column(name = "lb_policy_id") + private long resourceId; + + @Column(name = "name") + private String name; + + @Column(name = "value", length = 1024) + private String value; + + @Column(name = "display") + private boolean display = true; + + public LBStickinessPolicyDetailVO() { + } + + public LBStickinessPolicyDetailVO(long id, String name, String value, boolean display) { + this.resourceId = id; + this.name = name; + this.value = value; + this.display = display; + } + + @Override + public long getId() { + return id; + } + + @Override + public String getName() { + return name; + } + + @Override + public String getValue() { + return value; + } + + @Override + public long getResourceId() { + return resourceId; + } + + @Override + public boolean isDisplay() { + return display; + } +} diff --git a/engine/schema/src/org/apache/cloudstack/resourcedetail/dao/LBHealthCheckPolicyDetailsDao.java b/engine/schema/src/org/apache/cloudstack/resourcedetail/dao/LBHealthCheckPolicyDetailsDao.java new file mode 100644 index 0000000000..9f8fcddd1d --- /dev/null +++ b/engine/schema/src/org/apache/cloudstack/resourcedetail/dao/LBHealthCheckPolicyDetailsDao.java @@ -0,0 +1,22 @@ +// Copyright 2012 Citrix Systems, Inc. Licensed under the +// Apache License, Version 2.0 (the "License"); you may not use this +// file except in compliance with the License. Citrix Systems, Inc. +// reserves all rights not expressly granted by 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. +// +// Automatically generated by addcopyright.py at 04/03/2012 +package org.apache.cloudstack.resourcedetail.dao; + +import org.apache.cloudstack.resourcedetail.LBHealthCheckPolicyDetailVO; +import org.apache.cloudstack.resourcedetail.ResourceDetailsDao; + +import com.cloud.utils.db.GenericDao; + +public interface LBHealthCheckPolicyDetailsDao extends GenericDao, ResourceDetailsDao{ + +} diff --git a/engine/schema/src/org/apache/cloudstack/resourcedetail/dao/LBHealthCheckPolicyDetailsDaoImpl.java b/engine/schema/src/org/apache/cloudstack/resourcedetail/dao/LBHealthCheckPolicyDetailsDaoImpl.java new file mode 100644 index 0000000000..ab2e07f50d --- /dev/null +++ b/engine/schema/src/org/apache/cloudstack/resourcedetail/dao/LBHealthCheckPolicyDetailsDaoImpl.java @@ -0,0 +1,29 @@ +// Copyright 2012 Citrix Systems, Inc. Licensed under the +// Apache License, Version 2.0 (the "License"); you may not use this +// file except in compliance with the License. Citrix Systems, Inc. +// reserves all rights not expressly granted by 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. +// +// Automatically generated by addcopyright.py at 04/03/2012 +package org.apache.cloudstack.resourcedetail.dao; + +import javax.ejb.Local; + +import org.apache.cloudstack.resourcedetail.LBHealthCheckPolicyDetailVO; +import org.apache.cloudstack.resourcedetail.ResourceDetailsDaoBase; +import org.springframework.stereotype.Component; + +@Component +@Local(value = {LBHealthCheckPolicyDetailsDao.class}) +public class LBHealthCheckPolicyDetailsDaoImpl extends ResourceDetailsDaoBase implements LBHealthCheckPolicyDetailsDao { + + @Override + public void addDetail(long resourceId, String key, String value, boolean display) { + super.addDetail(new LBHealthCheckPolicyDetailVO(resourceId, key, value, display)); + } +} \ No newline at end of file diff --git a/engine/schema/src/org/apache/cloudstack/resourcedetail/dao/LBStickinessPolicyDetailsDao.java b/engine/schema/src/org/apache/cloudstack/resourcedetail/dao/LBStickinessPolicyDetailsDao.java new file mode 100644 index 0000000000..512debc38c --- /dev/null +++ b/engine/schema/src/org/apache/cloudstack/resourcedetail/dao/LBStickinessPolicyDetailsDao.java @@ -0,0 +1,22 @@ +// Copyright 2012 Citrix Systems, Inc. Licensed under the +// Apache License, Version 2.0 (the "License"); you may not use this +// file except in compliance with the License. Citrix Systems, Inc. +// reserves all rights not expressly granted by 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. +// +// Automatically generated by addcopyright.py at 04/03/2012 +package org.apache.cloudstack.resourcedetail.dao; + +import org.apache.cloudstack.resourcedetail.LBStickinessPolicyDetailVO; +import org.apache.cloudstack.resourcedetail.ResourceDetailsDao; + +import com.cloud.utils.db.GenericDao; + +public interface LBStickinessPolicyDetailsDao extends GenericDao, ResourceDetailsDao{ + +} diff --git a/engine/schema/src/org/apache/cloudstack/resourcedetail/dao/LBStickinessPolicyDetailsDaoImpl.java b/engine/schema/src/org/apache/cloudstack/resourcedetail/dao/LBStickinessPolicyDetailsDaoImpl.java new file mode 100644 index 0000000000..a9afa2280c --- /dev/null +++ b/engine/schema/src/org/apache/cloudstack/resourcedetail/dao/LBStickinessPolicyDetailsDaoImpl.java @@ -0,0 +1,29 @@ +// Copyright 2012 Citrix Systems, Inc. Licensed under the +// Apache License, Version 2.0 (the "License"); you may not use this +// file except in compliance with the License. Citrix Systems, Inc. +// reserves all rights not expressly granted by 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. +// +// Automatically generated by addcopyright.py at 04/03/2012 +package org.apache.cloudstack.resourcedetail.dao; + +import javax.ejb.Local; + +import org.apache.cloudstack.resourcedetail.LBStickinessPolicyDetailVO; +import org.apache.cloudstack.resourcedetail.ResourceDetailsDaoBase; +import org.springframework.stereotype.Component; + +@Component +@Local(value = {LBStickinessPolicyDetailsDao.class}) +public class LBStickinessPolicyDetailsDaoImpl extends ResourceDetailsDaoBase implements LBStickinessPolicyDetailsDao { + + @Override + public void addDetail(long resourceId, String key, String value, boolean display) { + super.addDetail(new LBStickinessPolicyDetailVO(resourceId, key, value, display)); + } +} \ No newline at end of file diff --git a/engine/schema/src/org/apache/cloudstack/storage/datastore/db/PrimaryDataStoreDao.java b/engine/schema/src/org/apache/cloudstack/storage/datastore/db/PrimaryDataStoreDao.java index 2c4369d047..19855d2324 100644 --- a/engine/schema/src/org/apache/cloudstack/storage/datastore/db/PrimaryDataStoreDao.java +++ b/engine/schema/src/org/apache/cloudstack/storage/datastore/db/PrimaryDataStoreDao.java @@ -113,4 +113,8 @@ public interface PrimaryDataStoreDao extends GenericDao { List findZoneWideStoragePoolsByTags(long dcId, String[] tags); List findZoneWideStoragePoolsByHypervisor(long dataCenterId, HypervisorType hypervisorType); + + List findLocalStoragePoolsByHostAndTags(long hostId, String[] tags); + + List findLocalStoragePoolsByHost(long hostId); } diff --git a/engine/schema/src/org/apache/cloudstack/storage/datastore/db/PrimaryDataStoreDaoImpl.java b/engine/schema/src/org/apache/cloudstack/storage/datastore/db/PrimaryDataStoreDaoImpl.java index 57afa16b50..4185dcf58a 100644 --- a/engine/schema/src/org/apache/cloudstack/storage/datastore/db/PrimaryDataStoreDaoImpl.java +++ b/engine/schema/src/org/apache/cloudstack/storage/datastore/db/PrimaryDataStoreDaoImpl.java @@ -24,6 +24,7 @@ import java.util.List; import java.util.Map; +import javax.annotation.PostConstruct; import javax.ejb.Local; import javax.inject.Inject; import javax.naming.ConfigurationException; @@ -31,10 +32,13 @@ import com.cloud.host.Status; import com.cloud.hypervisor.Hypervisor.HypervisorType; import com.cloud.storage.ScopeType; +import com.cloud.storage.StoragePoolHostVO; import com.cloud.storage.StoragePoolStatus; +import com.cloud.storage.dao.StoragePoolHostDao; import com.cloud.utils.db.DB; import com.cloud.utils.db.GenericDaoBase; import com.cloud.utils.db.GenericSearchBuilder; +import com.cloud.utils.db.JoinBuilder; import com.cloud.utils.db.QueryBuilder; import com.cloud.utils.db.SearchBuilder; import com.cloud.utils.db.SearchCriteria; @@ -51,9 +55,14 @@ public class PrimaryDataStoreDaoImpl extends GenericDaoBase protected final SearchBuilder DcPodAnyClusterSearch; protected final SearchBuilder DeleteLvmSearch; protected final GenericSearchBuilder StatusCountSearch; + protected SearchBuilder HostSearch; + protected SearchBuilder HostPoolSearch; + protected SearchBuilder TagPoolSearch; @Inject protected StoragePoolDetailsDao _detailsDao; + @Inject + protected StoragePoolHostDao _hostDao; private final String DetailsSqlPrefix = "SELECT storage_pool.* from storage_pool LEFT JOIN storage_pool_details ON storage_pool.id = storage_pool_details.pool_id WHERE storage_pool.removed is null and storage_pool.status = 'Up' and storage_pool.data_center_id = ? and (storage_pool.pod_id = ? or storage_pool.pod_id is null) and storage_pool.scope = ? and ("; @@ -111,6 +120,26 @@ public PrimaryDataStoreDaoImpl() { } + @PostConstruct + void init() { + HostSearch = createSearchBuilder(); + TagPoolSearch = _detailsDao.createSearchBuilder(); + HostPoolSearch = _hostDao.createSearchBuilder(); + // Search for pools on the host + HostPoolSearch.and("hostId", HostPoolSearch.entity().getHostId(), Op.EQ); + // Set criteria for pools + HostSearch.and("scope", HostSearch.entity().getScope(), Op.EQ); + HostSearch.and("removed", HostSearch.entity().getRemoved(), Op.NULL); + HostSearch.and("status", HostSearch.entity().getStatus(), Op.EQ); + HostSearch.join("hostJoin", HostPoolSearch, HostSearch.entity().getId(), HostPoolSearch.entity().getPoolId(), JoinBuilder.JoinType.INNER); + // Set criteria for tags + TagPoolSearch.and("name", TagPoolSearch.entity().getName(), Op.EQ); + TagPoolSearch.and("value", TagPoolSearch.entity().getValue(), Op.EQ); + + HostSearch.join("tagJoin", TagPoolSearch, HostSearch.entity().getId(), TagPoolSearch.entity().getResourceId(), JoinBuilder.JoinType.INNER); + HostSearch.done(); + } + @Override public List findPoolByName(String name) { SearchCriteria sc = AllFieldSearch.create(); @@ -314,6 +343,44 @@ public List findLocalStoragePoolsByTags(long dcId, long podId, Lo return storagePools; } + @Override + public List findLocalStoragePoolsByHostAndTags(long hostId, String[] tags) { + + SearchCriteria sc = HostSearch.create(); + sc.setJoinParameters("hostJoin", "hostId", hostId ); + sc.setParameters("scope", ScopeType.HOST.toString()); + sc.setParameters("status", Status.Up.toString()); + if (!(tags == null || tags.length == 0 )) { + Map details = tagsToDetails(tags); + for (Map.Entry detail : details.entrySet()) { + sc.setJoinParameters("tagJoin","name", detail.getKey()); + sc.setJoinParameters("tagJoin", "value", detail.getValue()); + } + } + return listBy(sc); + } + + @Override + public List findLocalStoragePoolsByHost(long hostId) { + + SearchBuilder hostSearch = createSearchBuilder(); + SearchBuilder hostPoolSearch = _hostDao.createSearchBuilder(); + + // Search for pools on the host + hostPoolSearch.and("hostId", hostPoolSearch.entity().getHostId(), Op.EQ); + // Set criteria for pools + hostSearch.and("scope", hostSearch.entity().getScope(), Op.EQ); + hostSearch.and("removed", hostSearch.entity().getRemoved(), Op.NULL); + hostSearch.and("status", hostSearch.entity().getStatus(), Op.EQ); + hostSearch.join("hostJoin", hostPoolSearch, hostSearch.entity().getId(), hostPoolSearch.entity().getPoolId(), JoinBuilder.JoinType.INNER); + + SearchCriteria sc = hostSearch.create(); + sc.setJoinParameters("hostJoin", "hostId", hostId ); + sc.setParameters("scope", ScopeType.HOST.toString()); + sc.setParameters("status", Status.Up.toString()); + return listBy(sc); + } + @Override public List findZoneWideStoragePoolsByTags(long dcId, String[] tags) { List storagePools = null; diff --git a/engine/schema/src/org/apache/cloudstack/storage/datastore/db/TemplateDataStoreDao.java b/engine/schema/src/org/apache/cloudstack/storage/datastore/db/TemplateDataStoreDao.java index ab458895e4..271bbcae14 100644 --- a/engine/schema/src/org/apache/cloudstack/storage/datastore/db/TemplateDataStoreDao.java +++ b/engine/schema/src/org/apache/cloudstack/storage/datastore/db/TemplateDataStoreDao.java @@ -65,6 +65,8 @@ public interface TemplateDataStoreDao extends GenericDao listByTemplate(long templateId); + TemplateDataStoreVO findByTemplateZoneReady(long templateId, Long zoneId); + void duplicateCacheRecordsOnRegionStore(long storeId); TemplateDataStoreVO findReadyOnCache(long templateId); diff --git a/engine/storage/datamotion/src/org/apache/cloudstack/storage/motion/AncientDataMotionStrategy.java b/engine/storage/datamotion/src/org/apache/cloudstack/storage/motion/AncientDataMotionStrategy.java index fbdacfa5aa..415a0772df 100644 --- a/engine/storage/datamotion/src/org/apache/cloudstack/storage/motion/AncientDataMotionStrategy.java +++ b/engine/storage/datamotion/src/org/apache/cloudstack/storage/motion/AncientDataMotionStrategy.java @@ -63,6 +63,7 @@ import com.cloud.storage.DataStoreRole; import com.cloud.storage.StoragePool; import com.cloud.storage.VolumeVO; +import com.cloud.storage.Storage.StoragePoolType; import com.cloud.storage.dao.VolumeDao; import com.cloud.utils.NumbersUtil; import com.cloud.utils.db.DB; @@ -389,10 +390,16 @@ protected Answer migrateVolumeToPool(DataObject srcData, DataObject destData) { VolumeVO volumeVo = volDao.findById(volume.getId()); Long oldPoolId = volume.getPoolId(); volumeVo.setPath(((MigrateVolumeAnswer)answer).getVolumePath()); - volumeVo.setFolder(destPool.getPath()); volumeVo.setPodId(destPool.getPodId()); volumeVo.setPoolId(destPool.getId()); volumeVo.setLastPoolId(oldPoolId); + // For SMB, pool credentials are also stored in the uri query string. We trim the query string + // part here to make sure the credentials do not get stored in the db unencrypted. + String folder = destPool.getPath(); + if (destPool.getPoolType() == StoragePoolType.SMB && folder != null && folder.contains("?")) { + folder = folder.substring(0, folder.indexOf("?")); + } + volumeVo.setFolder(folder); volDao.update(volume.getId(), volumeVo); } diff --git a/engine/storage/image/src/org/apache/cloudstack/storage/image/TemplateDataFactoryImpl.java b/engine/storage/image/src/org/apache/cloudstack/storage/image/TemplateDataFactoryImpl.java index db28a053c1..134e74d58f 100644 --- a/engine/storage/image/src/org/apache/cloudstack/storage/image/TemplateDataFactoryImpl.java +++ b/engine/storage/image/src/org/apache/cloudstack/storage/image/TemplateDataFactoryImpl.java @@ -23,9 +23,6 @@ import javax.inject.Inject; -import org.apache.log4j.Logger; -import org.springframework.stereotype.Component; - import org.apache.cloudstack.engine.subsystem.api.storage.DataObject; import org.apache.cloudstack.engine.subsystem.api.storage.DataStore; import org.apache.cloudstack.engine.subsystem.api.storage.DataStoreManager; @@ -34,6 +31,8 @@ import org.apache.cloudstack.storage.datastore.db.TemplateDataStoreDao; import org.apache.cloudstack.storage.datastore.db.TemplateDataStoreVO; import org.apache.cloudstack.storage.image.store.TemplateObject; +import org.apache.log4j.Logger; +import org.springframework.stereotype.Component; import com.cloud.storage.DataStoreRole; import com.cloud.storage.VMTemplateStoragePoolVO; @@ -106,6 +105,17 @@ public TemplateInfo getTemplate(long templateId, DataStoreRole storeRole, Long z return this.getTemplate(templateId, store); } + @Override + public TemplateInfo getReadyTemplateOnImageStore(long templateId, Long zoneId) { + TemplateDataStoreVO tmplStore = templateStoreDao.findByTemplateZoneReady(templateId, zoneId); + if (tmplStore != null) { + DataStore store = storeMgr.getDataStore(tmplStore.getDataStoreId(), DataStoreRole.Image); + return this.getTemplate(templateId, store); + } else { + return null; + } + } + @Override public TemplateInfo getTemplate(DataObject obj, DataStore store) { TemplateObject tmpObj = (TemplateObject)this.getTemplate(obj.getId(), store); diff --git a/engine/storage/image/src/org/apache/cloudstack/storage/image/store/TemplateObject.java b/engine/storage/image/src/org/apache/cloudstack/storage/image/store/TemplateObject.java index bd14df59b0..7288d454c3 100644 --- a/engine/storage/image/src/org/apache/cloudstack/storage/image/store/TemplateObject.java +++ b/engine/storage/image/src/org/apache/cloudstack/storage/image/store/TemplateObject.java @@ -23,7 +23,8 @@ import javax.inject.Inject; -import org.apache.cloudstack.acl.IAMEntityType; +import org.apache.log4j.Logger; + import org.apache.cloudstack.engine.subsystem.api.storage.DataObjectInStore; import org.apache.cloudstack.engine.subsystem.api.storage.DataStore; import org.apache.cloudstack.engine.subsystem.api.storage.ObjectInDataStoreStateMachine; @@ -35,7 +36,6 @@ import org.apache.cloudstack.storage.datastore.db.TemplateDataStoreDao; import org.apache.cloudstack.storage.datastore.db.TemplateDataStoreVO; import org.apache.cloudstack.storage.to.TemplateObjectTO; -import org.apache.log4j.Logger; import com.cloud.agent.api.Answer; import com.cloud.agent.api.to.DataObjectType; @@ -50,6 +50,7 @@ import com.cloud.storage.VMTemplateVO; import com.cloud.storage.dao.VMTemplateDao; import com.cloud.storage.dao.VMTemplatePoolDao; +import com.cloud.template.VirtualMachineTemplate; import com.cloud.utils.component.ComponentContext; import com.cloud.utils.exception.CloudRuntimeException; import com.cloud.utils.fsm.NoTransitionException; @@ -452,7 +453,7 @@ public boolean delete() { } @Override - public IAMEntityType getEntityType() { - return IAMEntityType.VirtualMachineTemplate; + public Class getEntityType() { + return VirtualMachineTemplate.class; } } diff --git a/engine/storage/snapshot/src/org/apache/cloudstack/storage/snapshot/SnapshotObject.java b/engine/storage/snapshot/src/org/apache/cloudstack/storage/snapshot/SnapshotObject.java index a8f1a56735..da8d341e49 100644 --- a/engine/storage/snapshot/src/org/apache/cloudstack/storage/snapshot/SnapshotObject.java +++ b/engine/storage/snapshot/src/org/apache/cloudstack/storage/snapshot/SnapshotObject.java @@ -24,7 +24,6 @@ import org.apache.log4j.Logger; -import org.apache.cloudstack.acl.IAMEntityType; import org.apache.cloudstack.engine.subsystem.api.storage.DataObjectInStore; import org.apache.cloudstack.engine.subsystem.api.storage.DataStore; import org.apache.cloudstack.engine.subsystem.api.storage.ObjectInDataStoreStateMachine; @@ -383,7 +382,7 @@ public boolean delete() { } @Override - public IAMEntityType getEntityType() { - return IAMEntityType.Snapshot; + public Class getEntityType() { + return Snapshot.class; } } diff --git a/engine/storage/snapshot/src/org/apache/cloudstack/storage/snapshot/SnapshotServiceImpl.java b/engine/storage/snapshot/src/org/apache/cloudstack/storage/snapshot/SnapshotServiceImpl.java index 8331012d1e..684b5bd29c 100644 --- a/engine/storage/snapshot/src/org/apache/cloudstack/storage/snapshot/SnapshotServiceImpl.java +++ b/engine/storage/snapshot/src/org/apache/cloudstack/storage/snapshot/SnapshotServiceImpl.java @@ -302,6 +302,10 @@ protected Void copySnapshotAsyncCallback(AsyncCallbackDispatcher params) throws ConfigurationException { @@ -108,7 +116,6 @@ public VMSnapshot takeVMSnapshot(VMSnapshot vmSnapshot) { boolean result = false; try { GuestOSVO guestOS = guestOSDao.findById(userVm.getGuestOSId()); - List volumeTOs = vmSnapshotHelper.getVolumeTOList(userVm.getId()); VMSnapshotTO current = null; @@ -126,7 +133,10 @@ public VMSnapshot takeVMSnapshot(VMSnapshot vmSnapshot) { else vmSnapshotVO.setParent(current.getId()); + HostVO host = hostDao.findById(hostId); + GuestOSHypervisorVO guestOsMapping = guestOsHypervisorDao.findByOsIdAndHypervisor(guestOS.getId(), host.getHypervisorType().toString(), host.getHypervisorVersion()); CreateVMSnapshotCommand ccmd = new CreateVMSnapshotCommand(userVm.getInstanceName(), target, volumeTOs, guestOS.getDisplayName(), userVm.getState()); + ccmd.setPlatformEmulator(guestOsMapping.getGuestOsName()); ccmd.setWait(_wait); answer = (CreateVMSnapshotAnswer)agentMgr.send(hostId, ccmd); @@ -334,7 +344,10 @@ public boolean revertVMSnapshot(VMSnapshot vmSnapshot) { snapshot.getCurrent(), parent, true); Long hostId = vmSnapshotHelper.pickRunningHost(vmSnapshot.getVmId()); GuestOSVO guestOS = guestOSDao.findById(userVm.getGuestOSId()); + HostVO host = hostDao.findById(hostId); + GuestOSHypervisorVO guestOsMapping = guestOsHypervisorDao.findByOsIdAndHypervisor(guestOS.getId(), host.getHypervisorType().toString(), host.getHypervisorVersion()); RevertToVMSnapshotCommand revertToSnapshotCommand = new RevertToVMSnapshotCommand(vmInstanceName, vmSnapshotTO, volumeTOs, guestOS.getDisplayName()); + revertToSnapshotCommand.setPlatformEmulator(guestOsMapping.getGuestOsName()); RevertToVMSnapshotAnswer answer = (RevertToVMSnapshotAnswer)agentMgr.send(hostId, revertToSnapshotCommand); if (answer != null && answer.getResult()) { diff --git a/engine/storage/snapshot/test/src/VMSnapshotStrategyTest.java b/engine/storage/snapshot/test/src/VMSnapshotStrategyTest.java index 9eaa7e19c1..6100c598f0 100644 --- a/engine/storage/snapshot/test/src/VMSnapshotStrategyTest.java +++ b/engine/storage/snapshot/test/src/VMSnapshotStrategyTest.java @@ -58,9 +58,14 @@ import com.cloud.agent.api.VMSnapshotTO; import com.cloud.exception.AgentUnavailableException; import com.cloud.exception.OperationTimedoutException; +import com.cloud.host.HostVO; +import com.cloud.host.dao.HostDao; +import com.cloud.hypervisor.Hypervisor.HypervisorType; +import com.cloud.storage.GuestOSHypervisorVO; import com.cloud.storage.GuestOSVO; import com.cloud.storage.dao.DiskOfferingDao; import com.cloud.storage.dao.GuestOSDao; +import com.cloud.storage.dao.GuestOSHypervisorDao; import com.cloud.storage.dao.VolumeDao; import com.cloud.utils.component.ComponentContext; import com.cloud.utils.exception.CloudRuntimeException; @@ -83,9 +88,13 @@ public class VMSnapshotStrategyTest extends TestCase { @Inject GuestOSDao guestOSDao; @Inject + GuestOSHypervisorDao guestOsHypervisorDao; + @Inject AgentManager agentMgr; @Inject VMSnapshotDao vmSnapshotDao; + @Inject + HostDao hostDao; @Override @Before @@ -98,6 +107,9 @@ public void testCreateVMSnapshot() throws AgentUnavailableException, OperationTi Long hostId = 1L; Long vmId = 1L; Long guestOsId = 1L; + HypervisorType hypervisorType = HypervisorType.Any; + String hypervisorVersion = "default"; + String guestOsName = "Other"; List volumeObjectTOs = new ArrayList(); VMSnapshotVO vmSnapshot = Mockito.mock(VMSnapshotVO.class); UserVmVO userVmVO = Mockito.mock(UserVmVO.class); @@ -108,7 +120,15 @@ public void testCreateVMSnapshot() throws AgentUnavailableException, OperationTi Mockito.when(userVmDao.findById(Matchers.anyLong())).thenReturn(userVmVO); GuestOSVO guestOSVO = Mockito.mock(GuestOSVO.class); Mockito.when(guestOSDao.findById(Matchers.anyLong())).thenReturn(guestOSVO); + GuestOSHypervisorVO guestOSHypervisorVO = Mockito.mock(GuestOSHypervisorVO.class); + Mockito.when(guestOSHypervisorVO.getGuestOsName()).thenReturn(guestOsName); + Mockito.when(guestOsHypervisorDao.findById(Matchers.anyLong())).thenReturn(guestOSHypervisorVO); + Mockito.when(guestOsHypervisorDao.findByOsIdAndHypervisor(Matchers.anyLong(), Matchers.anyString(), Matchers.anyString())).thenReturn(guestOSHypervisorVO); Mockito.when(agentMgr.send(Matchers.anyLong(), Matchers.any(Command.class))).thenReturn(null); + HostVO hostVO = Mockito.mock(HostVO.class); + Mockito.when(hostDao.findById(Matchers.anyLong())).thenReturn(hostVO); + Mockito.when(hostVO.getHypervisorType()).thenReturn(hypervisorType); + Mockito.when(hostVO.getHypervisorVersion()).thenReturn(hypervisorVersion); Exception e = null; try { vmSnapshotStrategy.takeVMSnapshot(vmSnapshot); @@ -131,6 +151,9 @@ public void testRevertSnapshot() throws AgentUnavailableException, OperationTime Long hostId = 1L; Long vmId = 1L; Long guestOsId = 1L; + HypervisorType hypervisorType = HypervisorType.Any; + String hypervisorVersion = "default"; + String guestOsName = "Other"; List volumeObjectTOs = new ArrayList(); VMSnapshotVO vmSnapshot = Mockito.mock(VMSnapshotVO.class); UserVmVO userVmVO = Mockito.mock(UserVmVO.class); @@ -141,12 +164,20 @@ public void testRevertSnapshot() throws AgentUnavailableException, OperationTime Mockito.when(userVmDao.findById(Matchers.anyLong())).thenReturn(userVmVO); GuestOSVO guestOSVO = Mockito.mock(GuestOSVO.class); Mockito.when(guestOSDao.findById(Matchers.anyLong())).thenReturn(guestOSVO); + GuestOSHypervisorVO guestOSHypervisorVO = Mockito.mock(GuestOSHypervisorVO.class); + Mockito.when(guestOsHypervisorDao.findById(Matchers.anyLong())).thenReturn(guestOSHypervisorVO); + Mockito.when(guestOsHypervisorDao.findByOsIdAndHypervisor(Matchers.anyLong(), Matchers.anyString(), Matchers.anyString())).thenReturn(guestOSHypervisorVO); + Mockito.when(guestOSHypervisorVO.getGuestOsName()).thenReturn(guestOsName); VMSnapshotTO vmSnapshotTO = Mockito.mock(VMSnapshotTO.class); Mockito.when(vmSnapshotHelper.getSnapshotWithParents(Matchers.any(VMSnapshotVO.class))).thenReturn(vmSnapshotTO); Mockito.when(vmSnapshotDao.findById(Matchers.anyLong())).thenReturn(vmSnapshot); Mockito.when(vmSnapshot.getId()).thenReturn(1L); Mockito.when(vmSnapshot.getCreated()).thenReturn(new Date()); Mockito.when(agentMgr.send(Matchers.anyLong(), Matchers.any(Command.class))).thenReturn(null); + HostVO hostVO = Mockito.mock(HostVO.class); + Mockito.when(hostDao.findById(Matchers.anyLong())).thenReturn(hostVO); + Mockito.when(hostVO.getHypervisorType()).thenReturn(hypervisorType); + Mockito.when(hostVO.getHypervisorVersion()).thenReturn(hypervisorVersion); Exception e = null; try { vmSnapshotStrategy.revertVMSnapshot(vmSnapshot); @@ -168,6 +199,9 @@ public void testDeleteVMSnapshot() throws AgentUnavailableException, OperationTi Long hostId = 1L; Long vmId = 1L; Long guestOsId = 1L; + HypervisorType hypervisorType = HypervisorType.Any; + String hypervisorVersion = "default"; + String guestOsName = "Other"; List volumeObjectTOs = new ArrayList(); VMSnapshotVO vmSnapshot = Mockito.mock(VMSnapshotVO.class); UserVmVO userVmVO = Mockito.mock(UserVmVO.class); @@ -178,13 +212,20 @@ public void testDeleteVMSnapshot() throws AgentUnavailableException, OperationTi Mockito.when(userVmDao.findById(Matchers.anyLong())).thenReturn(userVmVO); GuestOSVO guestOSVO = Mockito.mock(GuestOSVO.class); Mockito.when(guestOSDao.findById(Matchers.anyLong())).thenReturn(guestOSVO); + GuestOSHypervisorVO guestOSHypervisorVO = Mockito.mock(GuestOSHypervisorVO.class); + Mockito.when(guestOSHypervisorVO.getGuestOsName()).thenReturn(guestOsName); + Mockito.when(guestOsHypervisorDao.findById(Matchers.anyLong())).thenReturn(guestOSHypervisorVO); + Mockito.when(guestOsHypervisorDao.findByOsIdAndHypervisor(Matchers.anyLong(), Matchers.anyString(), Matchers.anyString())).thenReturn(guestOSHypervisorVO); VMSnapshotTO vmSnapshotTO = Mockito.mock(VMSnapshotTO.class); Mockito.when(vmSnapshotHelper.getSnapshotWithParents(Matchers.any(VMSnapshotVO.class))).thenReturn(vmSnapshotTO); Mockito.when(vmSnapshotDao.findById(Matchers.anyLong())).thenReturn(vmSnapshot); Mockito.when(vmSnapshot.getId()).thenReturn(1L); Mockito.when(vmSnapshot.getCreated()).thenReturn(new Date()); Mockito.when(agentMgr.send(Matchers.anyLong(), Matchers.any(Command.class))).thenReturn(null); - + HostVO hostVO = Mockito.mock(HostVO.class); + Mockito.when(hostDao.findById(Matchers.anyLong())).thenReturn(hostVO); + Mockito.when(hostVO.getHypervisorType()).thenReturn(hypervisorType); + Mockito.when(hostVO.getHypervisorVersion()).thenReturn(hypervisorVersion); Exception e = null; try { vmSnapshotStrategy.deleteVMSnapshot(vmSnapshot); @@ -227,6 +268,11 @@ public GuestOSDao guestOSDao() { return Mockito.mock(GuestOSDao.class); } + @Bean + public GuestOSHypervisorDao guestOsHypervisorDao() { + return Mockito.mock(GuestOSHypervisorDao.class); + } + @Bean public UserVmDao userVmDao() { return Mockito.mock(UserVmDao.class); @@ -256,5 +302,10 @@ public VolumeDao volumeDao() { public DiskOfferingDao diskOfferingDao() { return Mockito.mock(DiskOfferingDao.class); } + + @Bean + public HostDao hostDao() { + return Mockito.mock(HostDao.class); + } } } diff --git a/engine/storage/src/org/apache/cloudstack/storage/RemoteHostEndPoint.java b/engine/storage/src/org/apache/cloudstack/storage/RemoteHostEndPoint.java index 34f9c9d906..c54430fedb 100644 --- a/engine/storage/src/org/apache/cloudstack/storage/RemoteHostEndPoint.java +++ b/engine/storage/src/org/apache/cloudstack/storage/RemoteHostEndPoint.java @@ -25,8 +25,7 @@ import javax.inject.Inject; import org.apache.log4j.Logger; -import com.cloud.vm.SecondaryStorageVmVO; -import com.cloud.vm.dao.SecondaryStorageVmDao; + import org.apache.cloudstack.engine.subsystem.api.storage.EndPoint; import org.apache.cloudstack.framework.async.AsyncCompletionCallback; import org.apache.cloudstack.managed.context.ManagedContextRunnable; @@ -43,11 +42,15 @@ import com.cloud.exception.ConnectionException; import com.cloud.exception.OperationTimedoutException; import com.cloud.host.Host; +import com.cloud.host.HostVO; import com.cloud.host.Status; +import com.cloud.host.dao.HostDao; import com.cloud.hypervisor.HypervisorGuruManager; import com.cloud.utils.component.ComponentContext; import com.cloud.utils.concurrency.NamedThreadFactory; import com.cloud.utils.exception.CloudRuntimeException; +import com.cloud.vm.SecondaryStorageVmVO; +import com.cloud.vm.dao.SecondaryStorageVmDao; public class RemoteHostEndPoint implements EndPoint { private static final Logger s_logger = Logger.getLogger(RemoteHostEndPoint.class); @@ -60,6 +63,8 @@ public class RemoteHostEndPoint implements EndPoint { protected HypervisorGuruManager _hvGuruMgr; @Inject protected SecondaryStorageVmDao vmDao; + @Inject + protected HostDao _hostDao; private ScheduledExecutorService executor; public RemoteHostEndPoint() { @@ -67,14 +72,14 @@ public RemoteHostEndPoint() { } private void configure(Host host) { - this.hostId = host.getId(); - this.hostAddress = host.getPrivateIpAddress(); - this.publicAddress = host.getPublicIpAddress(); + hostId = host.getId(); + hostAddress = host.getPrivateIpAddress(); + publicAddress = host.getPublicIpAddress(); if (Host.Type.SecondaryStorageVM == host.getType()) { String vmName = host.getName(); SecondaryStorageVmVO ssvm = vmDao.findByInstanceName(vmName); if (ssvm != null) { - this.publicAddress = ssvm.getPublicIpAddress(); + publicAddress = ssvm.getPublicIpAddress(); } } } @@ -87,17 +92,25 @@ public static RemoteHostEndPoint getHypervisorHostEndPoint(Host host) { @Override public String getHostAddr() { - return this.hostAddress; + return hostAddress; } @Override public String getPublicAddr() { - return this.publicAddress; + return publicAddress; } @Override public long getId() { - return this.hostId; + return hostId; + } + + // used when HypervisorGuruManager choose a different host to send command + private void setId(long id) { + HostVO host = _hostDao.findById(hostId); + if (host != null) { + configure(host); + } } @Override @@ -105,6 +118,10 @@ public Answer sendMessage(Command cmd) { String errMsg = null; try { long newHostId = _hvGuruMgr.getGuruProcessedCommandTargetHost(hostId, cmd); + if (newHostId != hostId) { + // update endpoint with new host if changed + setId(newHostId); + } return agentMgr.send(newHostId, cmd); } catch (AgentUnavailableException e) { errMsg = e.toString(); @@ -126,7 +143,7 @@ public CmdRunner(AsyncCompletionCallback callback) { @Override public boolean processAnswers(long agentId, long seq, Answer[] answers) { - this.answer = answers[0]; + answer = answers[0]; executor.schedule(this, 10, TimeUnit.SECONDS); return true; } @@ -182,7 +199,11 @@ protected void runInContext() { @Override public void sendMessageAsync(Command cmd, AsyncCompletionCallback callback) { try { - long newHostId = _hvGuruMgr.getGuruProcessedCommandTargetHost(this.hostId, cmd); + long newHostId = _hvGuruMgr.getGuruProcessedCommandTargetHost(hostId, cmd); + if (newHostId != hostId) { + // update endpoint with new host if changed + setId(newHostId); + } if (s_logger.isDebugEnabled()) { s_logger.debug("Sending command " + cmd.toString() + " to host: " + newHostId); } diff --git a/engine/storage/src/org/apache/cloudstack/storage/allocator/LocalStoragePoolAllocator.java b/engine/storage/src/org/apache/cloudstack/storage/allocator/LocalStoragePoolAllocator.java index 678b2a3807..168dca3789 100644 --- a/engine/storage/src/org/apache/cloudstack/storage/allocator/LocalStoragePoolAllocator.java +++ b/engine/storage/src/org/apache/cloudstack/storage/allocator/LocalStoragePoolAllocator.java @@ -25,20 +25,17 @@ import javax.inject.Inject; import javax.naming.ConfigurationException; -import org.apache.log4j.Logger; -import org.springframework.stereotype.Component; - import org.apache.cloudstack.engine.subsystem.api.storage.StoragePoolAllocator; import org.apache.cloudstack.framework.config.dao.ConfigurationDao; import org.apache.cloudstack.storage.datastore.db.StoragePoolVO; +import org.apache.log4j.Logger; +import org.springframework.stereotype.Component; import com.cloud.capacity.dao.CapacityDao; import com.cloud.deploy.DeploymentPlan; import com.cloud.deploy.DeploymentPlanner.ExcludeList; import com.cloud.service.dao.ServiceOfferingDao; import com.cloud.storage.StoragePool; -import com.cloud.storage.StoragePoolHostVO; -import com.cloud.storage.Volume; import com.cloud.storage.dao.StoragePoolHostDao; import com.cloud.utils.NumbersUtil; import com.cloud.vm.DiskProfile; @@ -75,10 +72,16 @@ protected List select(DiskProfile dskCh, VirtualMachineProfile vmPr List suitablePools = new ArrayList(); // data disk and host identified from deploying vm (attach volume case) - if (dskCh.getType() == Volume.Type.DATADISK && plan.getHostId() != null) { - List hostPools = _poolHostDao.listByHostId(plan.getHostId()); - for (StoragePoolHostVO hostPool : hostPools) { - StoragePoolVO pool = _storagePoolDao.findById(hostPool.getPoolId()); + if (plan.getHostId() != null) { + List hostTagsPools = null; + String[] tags = dskCh.getTags(); + if (tags != null && tags.length > 0) { + hostTagsPools =_storagePoolDao.findLocalStoragePoolsByHostAndTags(plan.getHostId(), tags); + } else { + hostTagsPools =_storagePoolDao.findLocalStoragePoolsByHost(plan.getHostId()); + } + + for (StoragePoolVO pool : hostTagsPools) { if (pool != null && pool.isLocal()) { StoragePool storagePool = (StoragePool)this.dataStoreMgr.getPrimaryDataStore(pool.getId()); if (filter(avoid, storagePool, dskCh, plan)) { diff --git a/engine/storage/src/org/apache/cloudstack/storage/helper/HypervisorHelperImpl.java b/engine/storage/src/org/apache/cloudstack/storage/helper/HypervisorHelperImpl.java index b41c1fa14a..ff62fb8680 100644 --- a/engine/storage/src/org/apache/cloudstack/storage/helper/HypervisorHelperImpl.java +++ b/engine/storage/src/org/apache/cloudstack/storage/helper/HypervisorHelperImpl.java @@ -44,8 +44,12 @@ import com.cloud.agent.api.to.DataTO; import com.cloud.exception.AgentUnavailableException; import com.cloud.exception.OperationTimedoutException; +import com.cloud.host.HostVO; +import com.cloud.host.dao.HostDao; +import com.cloud.storage.GuestOSHypervisorVO; import com.cloud.storage.GuestOSVO; import com.cloud.storage.dao.GuestOSDao; +import com.cloud.storage.dao.GuestOSHypervisorDao; import com.cloud.utils.NumbersUtil; import com.cloud.utils.exception.CloudRuntimeException; import com.cloud.vm.VirtualMachine; @@ -60,9 +64,13 @@ public class HypervisorHelperImpl implements HypervisorHelper { @Inject GuestOSDao guestOSDao; @Inject + GuestOSHypervisorDao guestOsHypervisorDao; + @Inject ConfigurationDao configurationDao; @Inject AgentManager agentMgr; + @Inject + HostDao hostDao; @Override public DataTO introduceObject(DataTO object, Scope scope, Long storeId) { @@ -117,6 +125,9 @@ public VMSnapshotTO quiesceVm(VirtualMachine virtualMachine) { List volumeTOs = vmSnapshotHelper.getVolumeTOList(virtualMachine.getId()); CreateVMSnapshotCommand ccmd = new CreateVMSnapshotCommand(virtualMachine.getInstanceName(), vmSnapshotTO, volumeTOs, guestOS.getDisplayName(), virtualMachine.getState()); + HostVO host = hostDao.findById(hostId); + GuestOSHypervisorVO guestOsMapping = guestOsHypervisorDao.findByOsIdAndHypervisor(guestOS.getId(), host.getHypervisorType().toString(), host.getHypervisorVersion()); + ccmd.setPlatformEmulator(guestOsMapping.getGuestOsName()); ccmd.setWait(wait); try { Answer answer = agentMgr.send(hostId, ccmd); diff --git a/engine/storage/src/org/apache/cloudstack/storage/image/TemplateEntityImpl.java b/engine/storage/src/org/apache/cloudstack/storage/image/TemplateEntityImpl.java index fde13e17c8..c1aa8c2f0d 100644 --- a/engine/storage/src/org/apache/cloudstack/storage/image/TemplateEntityImpl.java +++ b/engine/storage/src/org/apache/cloudstack/storage/image/TemplateEntityImpl.java @@ -23,7 +23,6 @@ import java.util.List; import java.util.Map; -import org.apache.cloudstack.acl.IAMEntityType; import org.apache.cloudstack.engine.cloud.entity.api.TemplateEntity; import org.apache.cloudstack.engine.subsystem.api.storage.TemplateInfo; import org.apache.cloudstack.storage.image.datastore.ImageStoreInfo; @@ -31,6 +30,7 @@ import com.cloud.hypervisor.Hypervisor.HypervisorType; import com.cloud.storage.Storage.ImageFormat; import com.cloud.storage.Storage.TemplateType; +import com.cloud.template.VirtualMachineTemplate; public class TemplateEntityImpl implements TemplateEntity { protected TemplateInfo templateInfo; @@ -287,7 +287,7 @@ public long getVirtualSize() { } @Override - public IAMEntityType getEntityType() { - return IAMEntityType.VirtualMachineTemplate; + public Class getEntityType() { + return VirtualMachineTemplate.class; } } diff --git a/engine/storage/src/org/apache/cloudstack/storage/image/db/TemplateDataStoreDaoImpl.java b/engine/storage/src/org/apache/cloudstack/storage/image/db/TemplateDataStoreDaoImpl.java index d4b0445be7..cce7f08244 100644 --- a/engine/storage/src/org/apache/cloudstack/storage/image/db/TemplateDataStoreDaoImpl.java +++ b/engine/storage/src/org/apache/cloudstack/storage/image/db/TemplateDataStoreDaoImpl.java @@ -400,6 +400,22 @@ public TemplateDataStoreVO findByTemplateZone(long templateId, Long zoneId, Data return null; } + @Override + public TemplateDataStoreVO findByTemplateZoneReady(long templateId, Long zoneId) { + List imgStores = null; + imgStores = _storeMgr.getImageStoresByScope(new ZoneScope(zoneId)); + if (imgStores != null) { + Collections.shuffle(imgStores); + for (DataStore store : imgStores) { + List sRes = listByTemplateStoreStatus(templateId, store.getId(), State.Ready); + if (sRes != null && sRes.size() > 0) { + return sRes.get(0); + } + } + } + return null; + } + /** * Duplicate all image cache store entries */ diff --git a/engine/storage/src/org/apache/cloudstack/storage/snapshot/SnapshotEntityImpl.java b/engine/storage/src/org/apache/cloudstack/storage/snapshot/SnapshotEntityImpl.java index 848b165893..a660f41211 100644 --- a/engine/storage/src/org/apache/cloudstack/storage/snapshot/SnapshotEntityImpl.java +++ b/engine/storage/src/org/apache/cloudstack/storage/snapshot/SnapshotEntityImpl.java @@ -21,10 +21,10 @@ import java.util.List; import java.util.Map; -import org.apache.cloudstack.acl.IAMEntityType; import org.apache.cloudstack.engine.cloud.entity.api.SnapshotEntity; import com.cloud.hypervisor.Hypervisor.HypervisorType; +import com.cloud.storage.Snapshot; public class SnapshotEntityImpl implements SnapshotEntity { @@ -185,7 +185,7 @@ public Type getRecurringType() { } @Override - public IAMEntityType getEntityType() { - return IAMEntityType.Snapshot; + public Class getEntityType() { + return Snapshot.class; } } diff --git a/engine/storage/volume/src/org/apache/cloudstack/storage/datastore/PrimaryDataStoreImpl.java b/engine/storage/volume/src/org/apache/cloudstack/storage/datastore/PrimaryDataStoreImpl.java index 4fb37e2a18..f3c9e79027 100644 --- a/engine/storage/volume/src/org/apache/cloudstack/storage/datastore/PrimaryDataStoreImpl.java +++ b/engine/storage/volume/src/org/apache/cloudstack/storage/datastore/PrimaryDataStoreImpl.java @@ -24,8 +24,6 @@ import javax.inject.Inject; -import org.apache.log4j.Logger; - import org.apache.cloudstack.engine.subsystem.api.storage.ClusterScope; import org.apache.cloudstack.engine.subsystem.api.storage.DataObject; import org.apache.cloudstack.engine.subsystem.api.storage.DataStoreDriver; @@ -47,6 +45,7 @@ import org.apache.cloudstack.storage.datastore.db.StoragePoolVO; import org.apache.cloudstack.storage.to.PrimaryDataStoreTO; import org.apache.cloudstack.storage.volume.VolumeObject; +import org.apache.log4j.Logger; import com.cloud.agent.api.to.DataObjectType; import com.cloud.agent.api.to.DataStoreTO; @@ -391,6 +390,11 @@ public boolean isInMaintenance() { getStatus() == StoragePoolStatus.ErrorInMaintenance || getRemoved() != null; } + @Override + public HypervisorType getHypervisor() { + return pdsv.getHypervisor(); + } + @Override public String getStorageProviderName() { return pdsv.getStorageProviderName(); diff --git a/engine/storage/volume/src/org/apache/cloudstack/storage/datastore/provider/DefaultHostListener.java b/engine/storage/volume/src/org/apache/cloudstack/storage/datastore/provider/DefaultHostListener.java index fffd1e815c..e77d5489cb 100644 --- a/engine/storage/volume/src/org/apache/cloudstack/storage/datastore/provider/DefaultHostListener.java +++ b/engine/storage/volume/src/org/apache/cloudstack/storage/datastore/provider/DefaultHostListener.java @@ -81,7 +81,7 @@ public boolean hostConnect(long hostId, long poolId) { } StoragePoolVO poolVO = this.primaryStoreDao.findById(poolId); - poolVO.setUsedBytes(mspAnswer.getPoolInfo().getAvailableBytes()); + poolVO.setUsedBytes(mspAnswer.getPoolInfo().getCapacityBytes() - mspAnswer.getPoolInfo().getAvailableBytes()); poolVO.setCapacityBytes(mspAnswer.getPoolInfo().getCapacityBytes()); primaryStoreDao.update(pool.getId(), poolVO); diff --git a/engine/storage/volume/src/org/apache/cloudstack/storage/volume/VolumeObject.java b/engine/storage/volume/src/org/apache/cloudstack/storage/volume/VolumeObject.java index 1f05be21f2..0e7d5cc368 100644 --- a/engine/storage/volume/src/org/apache/cloudstack/storage/volume/VolumeObject.java +++ b/engine/storage/volume/src/org/apache/cloudstack/storage/volume/VolumeObject.java @@ -22,7 +22,6 @@ import org.apache.log4j.Logger; -import org.apache.cloudstack.acl.IAMEntityType; import org.apache.cloudstack.engine.subsystem.api.storage.DataObjectInStore; import org.apache.cloudstack.engine.subsystem.api.storage.DataStore; import org.apache.cloudstack.engine.subsystem.api.storage.ObjectInDataStoreStateMachine; @@ -168,6 +167,11 @@ public boolean isDisplayVolume() { return volumeVO.isDisplayVolume(); } + @Override + public boolean isDisplay() { + return volumeVO.isDisplay(); + } + public long getVolumeId() { return volumeVO.getId(); } @@ -670,7 +674,7 @@ public Long getVmSnapshotChainSize() { } @Override - public IAMEntityType getEntityType() { - return IAMEntityType.Volume; + public Class getEntityType() { + return Volume.class; } } diff --git a/engine/storage/volume/src/org/apache/cloudstack/storage/volume/VolumeServiceImpl.java b/engine/storage/volume/src/org/apache/cloudstack/storage/volume/VolumeServiceImpl.java index 68e5a5680e..3a71147f8a 100644 --- a/engine/storage/volume/src/org/apache/cloudstack/storage/volume/VolumeServiceImpl.java +++ b/engine/storage/volume/src/org/apache/cloudstack/storage/volume/VolumeServiceImpl.java @@ -527,7 +527,10 @@ protected Void managedCopyBaseImageCallback(AsyncCallbackDispatcher createManagedStorageAndVolumeFromTemplat details.put(PrimaryDataStore.MANAGED, Boolean.TRUE.toString()); details.put(PrimaryDataStore.STORAGE_HOST, destPrimaryDataStore.getHostAddress()); + details.put(PrimaryDataStore.STORAGE_PORT, String.valueOf(destPrimaryDataStore.getPort())); // for managed storage, the storage repository (XenServer) or datastore (ESX) name is based off of the iScsiName property of a volume details.put(PrimaryDataStore.MANAGED_STORE_TARGET, volumeInfo.get_iScsiName()); details.put(PrimaryDataStore.MANAGED_STORE_TARGET_ROOT_VOLUME, volumeInfo.getName()); diff --git a/framework/ipc/src/org/apache/cloudstack/framework/messagebus/MessageBusBase.java b/framework/ipc/src/org/apache/cloudstack/framework/messagebus/MessageBusBase.java index a9c433c62c..9432da0a72 100644 --- a/framework/ipc/src/org/apache/cloudstack/framework/messagebus/MessageBusBase.java +++ b/framework/ipc/src/org/apache/cloudstack/framework/messagebus/MessageBusBase.java @@ -58,10 +58,13 @@ public void subscribe(String subject, MessageSubscriber subscriber) { assert (subject != null); assert (subscriber != null); if (_gate.enter()) { - SubscriptionNode current = locate(subject, null, true); - assert (current != null); - current.addSubscriber(subscriber); - _gate.leave(); + try { + SubscriptionNode current = locate(subject, null, true); + assert (current != null); + current.addSubscriber(subscriber); + } finally { + _gate.leave(); + } } else { synchronized (_pendingActions) { _pendingActions.add(new ActionRecord(ActionType.Subscribe, subject, subscriber)); @@ -72,14 +75,17 @@ public void subscribe(String subject, MessageSubscriber subscriber) { @Override public void unsubscribe(String subject, MessageSubscriber subscriber) { if (_gate.enter()) { - if (subject != null) { - SubscriptionNode current = locate(subject, null, false); - if (current != null) - current.removeSubscriber(subscriber, false); - } else { - _subscriberRoot.removeSubscriber(subscriber, true); + try { + if (subject != null) { + SubscriptionNode current = locate(subject, null, false); + if (current != null) + current.removeSubscriber(subscriber, false); + } else { + _subscriberRoot.removeSubscriber(subscriber, true); + } + } finally { + _gate.leave(); } - _gate.leave(); } else { synchronized (_pendingActions) { _pendingActions.add(new ActionRecord(ActionType.Unsubscribe, subject, subscriber)); @@ -90,9 +96,12 @@ public void unsubscribe(String subject, MessageSubscriber subscriber) { @Override public void clearAll() { if (_gate.enter()) { - _subscriberRoot.clearAll(); - doPrune(); - _gate.leave(); + try { + _subscriberRoot.clearAll(); + doPrune(); + } finally { + _gate.leave(); + } } else { synchronized (_pendingActions) { _pendingActions.add(new ActionRecord(ActionType.ClearAll, null, null)); @@ -103,8 +112,11 @@ public void clearAll() { @Override public void prune() { if (_gate.enter()) { - doPrune(); - _gate.leave(); + try { + doPrune(); + } finally { + _gate.leave(); + } } else { synchronized (_pendingActions) { _pendingActions.add(new ActionRecord(ActionType.Prune, null, null)); @@ -132,18 +144,19 @@ private void doPrune() { public void publish(String senderAddress, String subject, PublishScope scope, Object args) { if (_gate.enter(true)) { + try { + List chainFromTop = new ArrayList(); + SubscriptionNode current = locate(subject, chainFromTop, false); - List chainFromTop = new ArrayList(); - SubscriptionNode current = locate(subject, chainFromTop, false); - - if (current != null) - current.notifySubscribers(senderAddress, subject, args); - - Collections.reverse(chainFromTop); - for (SubscriptionNode node : chainFromTop) - node.notifySubscribers(senderAddress, subject, args); + if (current != null) + current.notifySubscribers(senderAddress, subject, args); - _gate.leave(); + Collections.reverse(chainFromTop); + for (SubscriptionNode node : chainFromTop) + node.notifySubscribers(senderAddress, subject, args); + } finally { + _gate.leave(); + } } } diff --git a/framework/ipc/src/org/apache/cloudstack/framework/messagebus/MessageDetector.java b/framework/ipc/src/org/apache/cloudstack/framework/messagebus/MessageDetector.java index 3fb620c1b3..fae9bf3120 100644 --- a/framework/ipc/src/org/apache/cloudstack/framework/messagebus/MessageDetector.java +++ b/framework/ipc/src/org/apache/cloudstack/framework/messagebus/MessageDetector.java @@ -31,8 +31,10 @@ public MessageDetector() { } public boolean waitAny(long timeoutInMiliseconds) { - _signalled = false; synchronized (this) { + if (_signalled) + return true; + try { wait(timeoutInMiliseconds); } catch (InterruptedException e) { diff --git a/framework/jobs/src/org/apache/cloudstack/framework/jobs/AsyncJob.java b/framework/jobs/src/org/apache/cloudstack/framework/jobs/AsyncJob.java index e62482193a..0ad49e1e7b 100644 --- a/framework/jobs/src/org/apache/cloudstack/framework/jobs/AsyncJob.java +++ b/framework/jobs/src/org/apache/cloudstack/framework/jobs/AsyncJob.java @@ -30,6 +30,7 @@ public enum JournalType { public static interface Topics { public static final String JOB_HEARTBEAT = "job.heartbeat"; public static final String JOB_STATE = "job.state"; + public static final String JOB_EVENT_PUBLISH = "job.eventpublish"; } public static interface Constants { diff --git a/framework/jobs/src/org/apache/cloudstack/framework/jobs/dao/VmWorkJobDaoImpl.java b/framework/jobs/src/org/apache/cloudstack/framework/jobs/dao/VmWorkJobDaoImpl.java index cf3e17392b..ee8748adee 100644 --- a/framework/jobs/src/org/apache/cloudstack/framework/jobs/dao/VmWorkJobDaoImpl.java +++ b/framework/jobs/src/org/apache/cloudstack/framework/jobs/dao/VmWorkJobDaoImpl.java @@ -20,9 +20,10 @@ import java.sql.SQLException; import java.util.Date; import java.util.List; -import java.util.TimeZone; - import javax.annotation.PostConstruct; +import javax.inject.Inject; + +import org.apache.log4j.Logger; import org.apache.cloudstack.framework.jobs.impl.VmWorkJobVO; import org.apache.cloudstack.framework.jobs.impl.VmWorkJobVO.Step; @@ -41,9 +42,14 @@ import com.cloud.vm.VirtualMachine; public class VmWorkJobDaoImpl extends GenericDaoBase implements VmWorkJobDao { + private static final Logger s_logger = Logger.getLogger(VmWorkJobDaoImpl.class); protected SearchBuilder PendingWorkJobSearch; protected SearchBuilder PendingWorkJobByCommandSearch; + protected SearchBuilder ExpungingWorkJobSearch; + + @Inject + protected AsyncJobDao _baseJobDao; public VmWorkJobDaoImpl() { } @@ -63,6 +69,12 @@ public void init() { PendingWorkJobByCommandSearch.and("step", PendingWorkJobByCommandSearch.entity().getStep(), Op.NEQ); PendingWorkJobByCommandSearch.and("cmd", PendingWorkJobByCommandSearch.entity().getCmd(), Op.EQ); PendingWorkJobByCommandSearch.done(); + + ExpungingWorkJobSearch = createSearchBuilder(); + ExpungingWorkJobSearch.and("jobStatus", ExpungingWorkJobSearch.entity().getStatus(), Op.NEQ); + ExpungingWorkJobSearch.and("cutDate", ExpungingWorkJobSearch.entity().getLastUpdated(), Op.LT); + ExpungingWorkJobSearch.and("dispatcher", ExpungingWorkJobSearch.entity().getDispatcher(), Op.EQ); + ExpungingWorkJobSearch.done(); } @Override @@ -124,33 +136,19 @@ public void expungeCompletedWorkJobs(final Date cutDate) { expunge(sc); */ - Transaction.execute(new TransactionCallbackNoReturn() { - @Override - public void doInTransactionWithoutResult(TransactionStatus status) { - TransactionLegacy txn = TransactionLegacy.currentTxn(); - PreparedStatement pstmt = null; - try { - pstmt = txn.prepareAutoCloseStatement( - "DELETE FROM vm_work_job WHERE id IN (SELECT id FROM async_job WHERE job_dispatcher='VmWorkJobDispatcher' AND job_status != 0 AND last_updated < ?)"); - pstmt.setString(1, DateUtil.getDateDisplayString(TimeZone.getTimeZone("GMT"), cutDate)); - - pstmt.execute(); - } catch (SQLException e) { - } catch (Throwable e) { - } - - try { - pstmt = txn.prepareAutoCloseStatement( - "DELETE FROM async_job WHERE job_dispatcher='VmWorkJobDispatcher' AND job_status != 0 AND last_updated < ?"); - pstmt.setString(1, DateUtil.getDateDisplayString(TimeZone.getTimeZone("GMT"), cutDate)); - - pstmt.execute(); - } catch (SQLException e) { - } catch (Throwable e) { - } - } - }); + // loop at application level to avoid mysql deadlock issues + SearchCriteria sc = ExpungingWorkJobSearch.create(); + sc.setParameters("jobStatus", JobInfo.Status.IN_PROGRESS); + sc.setParameters("lastUpdated", cutDate); + sc.setParameters("dispatcher", "VmWorkJobDispatcher"); + List expungeList = listBy(sc); + for (VmWorkJobVO job : expungeList) { + if (s_logger.isDebugEnabled()) + s_logger.debug("Expunge completed work job-" + job.getId()); + expunge(job.getId()); + _baseJobDao.expunge(job.getId()); + } } @Override diff --git a/framework/jobs/src/org/apache/cloudstack/framework/jobs/impl/AsyncJobManagerImpl.java b/framework/jobs/src/org/apache/cloudstack/framework/jobs/impl/AsyncJobManagerImpl.java index 49c3032b12..24abcbe868 100644 --- a/framework/jobs/src/org/apache/cloudstack/framework/jobs/impl/AsyncJobManagerImpl.java +++ b/framework/jobs/src/org/apache/cloudstack/framework/jobs/impl/AsyncJobManagerImpl.java @@ -60,6 +60,7 @@ import com.cloud.cluster.ClusterManagerListener; import com.cloud.cluster.ManagementServerHost; import com.cloud.utils.DateUtil; +import com.cloud.utils.Pair; import com.cloud.utils.Predicate; import com.cloud.utils.component.ManagerBase; import com.cloud.utils.concurrency.NamedThreadFactory; @@ -256,13 +257,17 @@ public List doInTransaction(TransactionStatus status) { } }); - for (Long id : wakeupList) { - // TODO, we assume that all jobs in this category is API job only - AsyncJobVO jobToWakeup = _jobDao.findById(id); - if (jobToWakeup != null && (jobToWakeup.getPendingSignals() & AsyncJob.Constants.SIGNAL_MASK_WAKEUP) != 0) - scheduleExecution(jobToWakeup, false); - } - + // + // disable wakeup scheduling now, since all API jobs are currently using block-waiting for sub-jobs + // + /* + for (Long id : wakeupList) { + // TODO, we assume that all jobs in this category is API job only + AsyncJobVO jobToWakeup = _jobDao.findById(id); + if (jobToWakeup != null && (jobToWakeup.getPendingSignals() & AsyncJob.Constants.SIGNAL_MASK_WAKEUP) != 0) + scheduleExecution(jobToWakeup, false); + } + */ _messageBus.publish(null, AsyncJob.Topics.JOB_STATE, PublishScope.GLOBAL, jobId); } @@ -441,9 +446,9 @@ public void run() { CallContext.registerPlaceHolderContext(); if (job.getRelated() != null && !job.getRelated().isEmpty()) - NDC.push("Job-" + job.getRelated() + "/" + "Job-" + job.getId()); + NDC.push("job-" + job.getRelated() + "/" + "job-" + job.getId()); else - NDC.push("Job-" + job.getId()); + NDC.push("job-" + job.getId()); try { super.run(); } finally { @@ -556,17 +561,41 @@ private void executeQueueItem(SyncQueueItemVO item, boolean fromPreviousSession) job.setSyncSource(item); - job.setExecutingMsid(getMsid()); - _jobDao.update(job.getId(), job); + // + // TODO: a temporary solution to work-around DB deadlock situation + // + // to live with DB deadlocks, we will give a chance for job to be rescheduled + // in case of exceptions (most-likely DB deadlock exceptions) + try { + job.setExecutingMsid(getMsid()); + _jobDao.update(job.getId(), job); + } catch (Exception e) { + s_logger.warn("Unexpected exception while dispatching job-" + item.getContentId(), e); + + try { + _queueMgr.returnItem(item.getId()); + } catch (Throwable thr) { + s_logger.error("Unexpected exception while returning job-" + item.getContentId() + " to queue", thr); + } + } try { scheduleExecution(job); } catch (RejectedExecutionException e) { s_logger.warn("Execution for job-" + job.getId() + " is rejected, return it to the queue for next turn"); - _queueMgr.returnItem(item.getId()); - job.setExecutingMsid(null); - _jobDao.update(job.getId(), job); + try { + _queueMgr.returnItem(item.getId()); + } catch (Exception e2) { + s_logger.error("Unexpected exception while returning job-" + item.getContentId() + " to queue", e2); + } + + try { + job.setExecutingMsid(null); + _jobDao.update(job.getId(), job); + } catch (Exception e3) { + s_logger.warn("Unexpected exception while update job-" + item.getContentId() + " msid for bookkeeping"); + } } } else { @@ -981,4 +1010,8 @@ protected AsyncJobManagerImpl() { } + private void publishOnEventBus(AsyncJob job, String jobEvent) { + _messageBus.publish(null, AsyncJob.Topics.JOB_EVENT_PUBLISH, PublishScope.LOCAL, + new Pair(job, jobEvent)); + } } diff --git a/framework/security/src/org/apache/cloudstack/framework/security/keys/KeysManagerImpl.java b/framework/security/src/org/apache/cloudstack/framework/security/keys/KeysManagerImpl.java index 550bd155c9..15bb49c65f 100644 --- a/framework/security/src/org/apache/cloudstack/framework/security/keys/KeysManagerImpl.java +++ b/framework/security/src/org/apache/cloudstack/framework/security/keys/KeysManagerImpl.java @@ -61,7 +61,7 @@ public class KeysManagerImpl implements KeysManager, Configurable { public String getHashKey() { String value = HashKey.value(); if (value == null) { - _configDepot.set(HashKey, getBase64EncodedRandomKey(128)); + _configDao.getValueAndInitIfNotExist(HashKey.key(), HashKey.category(), getBase64EncodedRandomKey(128), HashKey.description()); } return HashKey.value(); @@ -71,7 +71,8 @@ public String getHashKey() { public String getEncryptionKey() { String value = EncryptionKey.value(); if (value == null) { - _configDepot.set(EncryptionKey, getBase64EncodedRandomKey(128)); + _configDao.getValueAndInitIfNotExist(EncryptionKey.key(), EncryptionKey.category(), getBase64EncodedRandomKey(128), + EncryptionKey.description()); } return EncryptionKey.value(); } @@ -80,7 +81,8 @@ public String getEncryptionKey() { public String getEncryptionIV() { String value = EncryptionIV.value(); if (value == null) { - _configDepot.set(EncryptionIV, getBase64EncodedRandomKey(128)); + _configDao.getValueAndInitIfNotExist(EncryptionIV.key(), EncryptionIV.category(), getBase64EncodedRandomKey(128), + EncryptionIV.description()); } return EncryptionIV.value(); } diff --git a/framework/security/src/org/apache/cloudstack/framework/security/keystore/KeystoreDao.java b/framework/security/src/org/apache/cloudstack/framework/security/keystore/KeystoreDao.java index e60e4b004c..67eea92886 100644 --- a/framework/security/src/org/apache/cloudstack/framework/security/keystore/KeystoreDao.java +++ b/framework/security/src/org/apache/cloudstack/framework/security/keystore/KeystoreDao.java @@ -28,4 +28,6 @@ public interface KeystoreDao extends GenericDao { void save(String alias, String certificate, Integer index, String domainSuffix); List findCertChain(); + + List findCertChain(String domainSuffix); } diff --git a/framework/security/src/org/apache/cloudstack/framework/security/keystore/KeystoreDaoImpl.java b/framework/security/src/org/apache/cloudstack/framework/security/keystore/KeystoreDaoImpl.java index cd24611a86..b856582ac1 100644 --- a/framework/security/src/org/apache/cloudstack/framework/security/keystore/KeystoreDaoImpl.java +++ b/framework/security/src/org/apache/cloudstack/framework/security/keystore/KeystoreDaoImpl.java @@ -38,6 +38,7 @@ public class KeystoreDaoImpl extends GenericDaoBase implements KeystoreDao { protected final SearchBuilder FindByNameSearch; protected final SearchBuilder CertChainSearch; + protected final SearchBuilder CertChainSearchForDomainSuffix; public KeystoreDaoImpl() { FindByNameSearch = createSearchBuilder(); @@ -47,6 +48,11 @@ public KeystoreDaoImpl() { CertChainSearch = createSearchBuilder(); CertChainSearch.and("key", CertChainSearch.entity().getKey(), Op.NULL); CertChainSearch.done(); + + CertChainSearchForDomainSuffix = createSearchBuilder(); + CertChainSearchForDomainSuffix.and("key", CertChainSearchForDomainSuffix.entity().getKey(), Op.NULL); + CertChainSearchForDomainSuffix.and("domainSuffix", CertChainSearchForDomainSuffix.entity().getDomainSuffix(), Op.EQ); + CertChainSearchForDomainSuffix.done(); } @Override @@ -64,6 +70,19 @@ public int compare(Object o1, Object o2) { return ks; } + @Override + public List findCertChain(String domainSuffix) { + SearchCriteria sc = CertChainSearchForDomainSuffix.create(); + sc.setParameters("domainSuffix", domainSuffix); + List ks = listBy(sc); + Collections.sort(ks, new Comparator() { public int compare(Object o1, Object o2) { + Integer seq1 = ((KeystoreVO)o1).getIndex(); + Integer seq2 = ((KeystoreVO)o2).getIndex(); + return seq1.compareTo(seq2); + }}); + return ks; + } + @Override public KeystoreVO findByName(String name) { assert (name != null); diff --git a/framework/security/src/org/apache/cloudstack/framework/security/keystore/KeystoreManager.java b/framework/security/src/org/apache/cloudstack/framework/security/keystore/KeystoreManager.java index 3b99947c4b..c44347c85e 100644 --- a/framework/security/src/org/apache/cloudstack/framework/security/keystore/KeystoreManager.java +++ b/framework/security/src/org/apache/cloudstack/framework/security/keystore/KeystoreManager.java @@ -28,15 +28,18 @@ public static class Certificates { private String privCert; @LogLevel(Log4jLevel.Off) private String certChain; + @LogLevel(Log4jLevel.Off) + private String rootCACert; public Certificates() { } - public Certificates(String prvKey, String privCert, String certChain) { - privKey = prvKey; + public Certificates(String prvKey, String privCert, String certChain, String rootCACert) { + this.privKey = prvKey; this.privCert = privCert; this.certChain = certChain; + this.rootCACert = rootCACert; } public String getPrivKey() { @@ -50,6 +53,10 @@ public String getPrivCert() { public String getCertChain() { return certChain; } + + public String getRootCACert() { + return rootCACert; + } } boolean validateCertificate(String certificate, String key, String domainSuffix); diff --git a/framework/security/src/org/apache/cloudstack/framework/security/keystore/KeystoreManagerImpl.java b/framework/security/src/org/apache/cloudstack/framework/security/keystore/KeystoreManagerImpl.java index 306083492a..374c080413 100644 --- a/framework/security/src/org/apache/cloudstack/framework/security/keystore/KeystoreManagerImpl.java +++ b/framework/security/src/org/apache/cloudstack/framework/security/keystore/KeystoreManagerImpl.java @@ -23,6 +23,7 @@ import java.security.cert.CertificateException; import java.security.spec.InvalidKeySpecException; import java.util.ArrayList; +import java.util.Collections; import java.util.List; import java.util.regex.Matcher; import java.util.regex.Pattern; @@ -30,6 +31,7 @@ import javax.ejb.Local; import javax.inject.Inject; +import org.apache.commons.lang.StringUtils; import org.apache.log4j.Logger; import org.springframework.stereotype.Component; @@ -129,17 +131,22 @@ public Certificates getCertificates(String name) { } String prvKey = ksVo.getKey(); String prvCert = ksVo.getCertificate(); + String domainSuffix = ksVo.getDomainSuffix(); String certChain = null; - List certchains = _ksDao.findCertChain(); + String rootCert = null; + List certchains = _ksDao.findCertChain(domainSuffix); if (certchains.size() > 0) { - StringBuilder chains = new StringBuilder(); + ArrayList chains = new ArrayList(); for (KeystoreVO cert : certchains) { - chains.append(cert.getCertificate()); - chains.append("\n"); + if (chains.size() == 0) {// For the first time it will be length 0 + rootCert = cert.getCertificate(); + } + chains.add(cert.getCertificate()); } - certChain = chains.toString(); + Collections.reverse(chains); + certChain = StringUtils.join(chains, "\n"); } - Certificates certs = new Certificates(prvKey, prvCert, certChain); + Certificates certs = new Certificates(prvKey, prvCert, certChain, rootCert); return certs; } diff --git a/packaging/centos63/cloud-agent.rc b/packaging/centos63/cloud-agent.rc index ece4c2732f..1f371e9fc2 100755 --- a/packaging/centos63/cloud-agent.rc +++ b/packaging/centos63/cloud-agent.rc @@ -26,7 +26,7 @@ # set environment variables -SHORTNAME=`basename $0` +SHORTNAME=$(basename $0 | sed -e 's/^[SK][0-9][0-9]//') PIDFILE=/var/run/"$SHORTNAME".pid LOCKFILE=/var/lock/subsys/"$SHORTNAME" LOGDIR=/var/log/cloudstack/agent diff --git a/packaging/centos63/cloud-usage.rc b/packaging/centos63/cloud-usage.rc index a9b6047887..7768d2b7ac 100755 --- a/packaging/centos63/cloud-usage.rc +++ b/packaging/centos63/cloud-usage.rc @@ -47,7 +47,7 @@ unset OPTIONS [ -r /etc/sysconfig/default/"$SHORTNAME" ] && source /etc/sysconfig/default/"$SHORTNAME" # The first existing directory is used for JAVA_HOME (if JAVA_HOME is not defined in $DEFAULT) -JDK_DIRS="/usr/lib/jvm/java-6-openjdk /usr/lib/jvm/java-6-openjdk-i386 /usr/lib/jvm/java-6-openjdk-amd64 /usr/lib/jvm/java-6-sun /usr/lib/jvm/jre-1.6.0 /usr/lib/j2sdk1.5-sun /usr/lib/jre-openjdk" +JDK_DIRS="/usr/lib/jvm/java-7-openjdk /usr/lib/jvm/java-7-openjdk-i386 /usr/lib/jvm/java-7-openjdk-amd64 /usr/lib/jvm/java-7-sun /usr/lib/jvm/jre-1.7.0 /usr/lib/j2sdk1.5-sun /usr/lib/jre-openjdk" for jdir in $JDK_DIRS; do if [ -r "$jdir/bin/java" -a -z "${JAVA_HOME}" ]; then @@ -59,9 +59,9 @@ export JAVA_HOME SCP="" DCP="" UCP=`ls /usr/share/cloudstack-usage/cloud-usage-*.jar`":"`ls /usr/share/cloudstack-usage/lib/*.jar | tr '\n' ':'` -JCP="/usr/share/java/commons-daemon.jar" +JCP="/usr/share/java/commons-daemon.jar":"/usr/share/java/mysql-connector-java.jar" -# We need to append the JSVC daemon JAR to the classpath +# We need to append the JSVC daemon and mysql-connector JAR to the classpath # AgentShell implements the JSVC daemon methods export CLASSPATH="$SCP:$DCP:$UCP:$JCP:/etc/cloudstack/usage" diff --git a/packaging/centos63/cloud.spec b/packaging/centos63/cloud.spec index 83c598b07a..e10aeaae66 100644 --- a/packaging/centos63/cloud.spec +++ b/packaging/centos63/cloud.spec @@ -60,7 +60,7 @@ intelligent IaaS cloud implementation. %package management Summary: CloudStack management server UI Requires: tomcat6 -Requires: java >= 1.7.0 +Requires: java7 Requires: python Requires: bash Requires: bzip2 @@ -112,7 +112,7 @@ The Apache CloudStack files shared between agent and management server %package agent Summary: CloudStack Agent for KVM hypervisors Requires: openssh-clients -Requires: java >= 1.7.0 +Requires: java7 Requires: %{name}-common = %{_ver} Requires: libvirt Requires: bridge-utils @@ -136,9 +136,21 @@ Group: System Environment/Libraries %description agent The CloudStack agent for KVM hypervisors +%package baremetal-agent +Summary: CloudStack baremetal agent +Requires: tftp-server +Requires: xinetd +Requires: syslinux +Requires: chkconfig +Requires: dhcp +Requires: httpd +Group: System Environment/Libraries +%description baremetal-agent +The CloudStack baremetal agent + %package usage Summary: CloudStack Usage calculation server -Requires: java >= 1.7.0 +Requires: java7 Requires: jsvc Requires: jakarta-commons-daemon Requires: jakarta-commons-daemon-jsvc @@ -225,7 +237,6 @@ mkdir -p ${RPM_BUILD_ROOT}%{_datadir}/%{name}-management/setup mkdir -p ${RPM_BUILD_ROOT}%{_localstatedir}/log/%{name}/management mkdir -p ${RPM_BUILD_ROOT}%{_localstatedir}/log/%{name}/awsapi mkdir -p ${RPM_BUILD_ROOT}%{_sysconfdir}/%{name}/management -mkdir -p ${RPM_BUILD_ROOT}%{_localstatedir}/log/%{name}-management # Specific for tomcat mkdir -p ${RPM_BUILD_ROOT}%{_sysconfdir}/%{name}/management/Catalina/localhost/client @@ -244,6 +255,7 @@ install -D client/target/utilities/bin/cloud-set-guest-sshkey ${RPM_BUILD_ROOT}% install -D client/target/utilities/bin/cloud-setup-databases ${RPM_BUILD_ROOT}%{_bindir}/%{name}-setup-databases install -D client/target/utilities/bin/cloud-setup-encryption ${RPM_BUILD_ROOT}%{_bindir}/%{name}-setup-encryption install -D client/target/utilities/bin/cloud-setup-management ${RPM_BUILD_ROOT}%{_bindir}/%{name}-setup-management +install -D client/target/utilities/bin/cloud-setup-baremetal ${RPM_BUILD_ROOT}%{_bindir}/%{name}-setup-baremetal install -D client/target/utilities/bin/cloud-sysvmadm ${RPM_BUILD_ROOT}%{_bindir}/%{name}-sysvmadm install -D client/target/utilities/bin/cloud-update-xenserver-licenses ${RPM_BUILD_ROOT}%{_bindir}/%{name}-update-xenserver-licenses @@ -282,7 +294,6 @@ chmod 770 ${RPM_BUILD_ROOT}%{_localstatedir}/cache/%{name}/management/work chmod 770 ${RPM_BUILD_ROOT}%{_localstatedir}/cache/%{name}/management/temp chmod 770 ${RPM_BUILD_ROOT}%{_localstatedir}/log/%{name}/management chmod 770 ${RPM_BUILD_ROOT}%{_localstatedir}/log/%{name}/agent -chmod 770 ${RPM_BUILD_ROOT}%{_localstatedir}/log/%{name}-management # KVM Agent mkdir -p ${RPM_BUILD_ROOT}%{_sysconfdir}/%{name}/agent @@ -571,7 +582,6 @@ fi %attr(0755,root,root) %{_bindir}/%{name}-external-ipallocator.py %attr(0755,root,root) %{_initrddir}/%{name}-ipallocator %dir %attr(0770,root,root) %{_localstatedir}/log/%{name}/ipallocator -%dir %attr(0770,root,root) %{_localstatedir}/log/%{name}-management %{_defaultdocdir}/%{name}-management-%{version}/LICENSE %{_defaultdocdir}/%{name}-management-%{version}/NOTICE %attr(0644,cloud,cloud) %{_localstatedir}/log/%{name}/management/catalina.out @@ -633,6 +643,9 @@ fi %{_defaultdocdir}/%{name}-awsapi-%{version}/LICENSE %{_defaultdocdir}/%{name}-awsapi-%{version}/NOTICE +%files baremetal-agent +%attr(0755,root,root) %{_bindir}/cloudstack-setup-baremetal + %changelog * Fri Oct 03 2012 Hugo Trippaers 4.1.0 diff --git a/packaging/debian/init/cloud-agent b/packaging/debian/init/cloud-agent index e7338752f3..ff550bb8f6 100755 --- a/packaging/debian/init/cloud-agent +++ b/packaging/debian/init/cloud-agent @@ -96,7 +96,7 @@ start() { wait_for_network - if start_daemon -p $PIDFILE $DAEMON -cp "$CLASSPATH" -pidfile "$PIDFILE" -errfile SYSLOG $CLASS + if start_daemon -p $PIDFILE $DAEMON -cp "$CLASSPATH" -Djna.nosys=true -pidfile "$PIDFILE" -errfile SYSLOG $CLASS RETVAL=$? then rc=0 diff --git a/plugins/database/mysql-ha/pom.xml b/plugins/database/mysql-ha/pom.xml index 5ce6d6f52b..28f136c5af 100644 --- a/plugins/database/mysql-ha/pom.xml +++ b/plugins/database/mysql-ha/pom.xml @@ -16,7 +16,7 @@ org.apache.cloudstack cloudstack-plugins 4.4.0-SNAPSHOT - ../pom.xml + ../../pom.xml diff --git a/plugins/event-bus/rabbitmq/src/org/apache/cloudstack/mom/rabbitmq/RabbitMQEventBus.java b/plugins/event-bus/rabbitmq/src/org/apache/cloudstack/mom/rabbitmq/RabbitMQEventBus.java index 8403271af8..a1f4c2b8b2 100644 --- a/plugins/event-bus/rabbitmq/src/org/apache/cloudstack/mom/rabbitmq/RabbitMQEventBus.java +++ b/plugins/event-bus/rabbitmq/src/org/apache/cloudstack/mom/rabbitmq/RabbitMQEventBus.java @@ -60,6 +60,18 @@ public class RabbitMQEventBus extends ManagerBase implements EventBus { private static String username; private static String password; + public static void setVirtualHost(String virtualHost) { + RabbitMQEventBus.virtualHost = virtualHost; + } + + private static String virtualHost; + + public static void setUseSsl(String useSsl) { + RabbitMQEventBus.useSsl = useSsl; + } + + private static String useSsl; + // AMQP exchange name where all CloudStack events will be published private static String amqpExchangeName; @@ -104,6 +116,12 @@ public boolean configure(String name, Map params) throws Configu throw new ConfigurationException("Unable to get the port details of AMQP server"); } + if (useSsl != null && !useSsl.isEmpty()) { + if (!useSsl.equalsIgnoreCase("true") && !useSsl.equalsIgnoreCase("false")) { + throw new ConfigurationException("Invalid configuration parameter for 'ssl'."); + } + } + if (retryInterval == null) { retryInterval = 10000;// default to 10s to try out reconnect } @@ -345,9 +363,18 @@ private synchronized Connection createConnection() throws Exception { ConnectionFactory factory = new ConnectionFactory(); factory.setUsername(username); factory.setPassword(password); - factory.setVirtualHost("/"); factory.setHost(amqpHost); factory.setPort(port); + + if (virtualHost != null && !virtualHost.isEmpty()) { + factory.setVirtualHost(virtualHost); + } else { + factory.setVirtualHost("/"); + } + + if (useSsl != null && !useSsl.isEmpty() && useSsl.equalsIgnoreCase("true")) { + factory.useSslProtocol(); + } Connection connection = factory.newConnection(); connection.addShutdownListener(disconnectHandler); s_connection = connection; diff --git a/plugins/hypervisors/baremetal/pom.xml b/plugins/hypervisors/baremetal/pom.xml index eb2a0d1870..8f1237e480 100755 --- a/plugins/hypervisors/baremetal/pom.xml +++ b/plugins/hypervisors/baremetal/pom.xml @@ -27,11 +27,11 @@ cloud-plugin-hypervisor-baremetal Apache CloudStack Plugin - Hypervisor Baremetal - - commons-lang - commons-lang - 2.6 - + + commons-lang + commons-lang + 2.6 + diff --git a/plugins/hypervisors/baremetal/resources/META-INF/cloudstack/baremetal-compute/spring-baremetal-compute-context.xml b/plugins/hypervisors/baremetal/resources/META-INF/cloudstack/baremetal-compute/spring-baremetal-compute-context.xml index cce6805123..d0b52a1bb0 100644 --- a/plugins/hypervisors/baremetal/resources/META-INF/cloudstack/baremetal-compute/spring-baremetal-compute-context.xml +++ b/plugins/hypervisors/baremetal/resources/META-INF/cloudstack/baremetal-compute/spring-baremetal-compute-context.xml @@ -31,5 +31,5 @@ - + diff --git a/plugins/hypervisors/baremetal/resources/META-INF/cloudstack/baremetal-discoverer/spring-baremetal-discoverer-context.xml b/plugins/hypervisors/baremetal/resources/META-INF/cloudstack/baremetal-discoverer/spring-baremetal-discoverer-context.xml index 8792909ffe..c01d9c62af 100644 --- a/plugins/hypervisors/baremetal/resources/META-INF/cloudstack/baremetal-discoverer/spring-baremetal-discoverer-context.xml +++ b/plugins/hypervisors/baremetal/resources/META-INF/cloudstack/baremetal-discoverer/spring-baremetal-discoverer-context.xml @@ -30,5 +30,5 @@ - + diff --git a/plugins/hypervisors/baremetal/resources/META-INF/cloudstack/baremetal-network/spring-baremetal-network-context.xml b/plugins/hypervisors/baremetal/resources/META-INF/cloudstack/baremetal-network/spring-baremetal-network-context.xml index 40d9f50577..c5068e7b14 100644 --- a/plugins/hypervisors/baremetal/resources/META-INF/cloudstack/baremetal-network/spring-baremetal-network-context.xml +++ b/plugins/hypervisors/baremetal/resources/META-INF/cloudstack/baremetal-network/spring-baremetal-network-context.xml @@ -42,5 +42,5 @@ - + diff --git a/plugins/hypervisors/baremetal/resources/META-INF/cloudstack/baremetal-planner/spring-baremetal-planner-context.xml b/plugins/hypervisors/baremetal/resources/META-INF/cloudstack/baremetal-planner/spring-baremetal-planner-context.xml index 8c14c3e290..046aca67e8 100644 --- a/plugins/hypervisors/baremetal/resources/META-INF/cloudstack/baremetal-planner/spring-baremetal-planner-context.xml +++ b/plugins/hypervisors/baremetal/resources/META-INF/cloudstack/baremetal-planner/spring-baremetal-planner-context.xml @@ -30,5 +30,5 @@ - + diff --git a/plugins/hypervisors/baremetal/resources/META-INF/cloudstack/core/spring-baremetal-core-context.xml b/plugins/hypervisors/baremetal/resources/META-INF/cloudstack/core/spring-baremetal-core-context.xml index 11cc6c89e3..a77406d98d 100644 --- a/plugins/hypervisors/baremetal/resources/META-INF/cloudstack/core/spring-baremetal-core-context.xml +++ b/plugins/hypervisors/baremetal/resources/META-INF/cloudstack/core/spring-baremetal-core-context.xml @@ -38,5 +38,5 @@ - + diff --git a/plugins/hypervisors/baremetal/resources/security_group_agent/cs-sgagent b/plugins/hypervisors/baremetal/resources/security_group_agent/cs-sgagent index 02426d0aa1..f8a5d7d2c9 100755 --- a/plugins/hypervisors/baremetal/resources/security_group_agent/cs-sgagent +++ b/plugins/hypervisors/baremetal/resources/security_group_agent/cs-sgagent @@ -18,9 +18,9 @@ # 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 @@ -29,31 +29,31 @@ # under the License. check_status() { - pidfile='/var/run/cssgagent.pid' - if [ ! -f $pidfile ]; then - echo "cloudstack baremetal security group agent is stopped" - exit 1 - else - pid=`cat $pidfile` - ps -p $pid > /dev/null - if [ $? -eq 0 ]; then - echo "cloudstack baremetal security group agent is running, pid is $pid" - exit 0 - else - echo "cloudstack baremetal security group agent is stopped, but pidfile at $pidfile is not cleaned. It may be caused by the agent crashed at last time, manually cleaning it would be ok" - exit 1 - fi - fi + pidfile='/var/run/cssgagent.pid' + if [ ! -f $pidfile ]; then + echo "cloudstack baremetal security group agent is stopped" + exit 1 + else + pid=`cat $pidfile` + ps -p $pid > /dev/null + if [ $? -eq 0 ]; then + echo "cloudstack baremetal security group agent is running, pid is $pid" + exit 0 + else + echo "cloudstack baremetal security group agent is stopped, but pidfile at $pidfile is not cleaned. It may be caused by the agent crashed at last time, manually cleaning it would be ok" + exit 1 + fi + fi } if [ $# -eq 0 ]; then - echo "usage: $0 + echo "usage: $0 [start|stop|restart|status]" - exit 1 + exit 1 fi if [ "$@" = "status" ]; then - check_status + check_status else python -c "from security_group_agent import cs_sg_agent; cs_sg_agent.main()" $@ fi diff --git a/plugins/hypervisors/baremetal/resources/security_group_agent/security_group_agent/__init__.py b/plugins/hypervisors/baremetal/resources/security_group_agent/security_group_agent/__init__.py index f7f5f60ff0..76bd5c1b21 100644 --- a/plugins/hypervisors/baremetal/resources/security_group_agent/security_group_agent/__init__.py +++ b/plugins/hypervisors/baremetal/resources/security_group_agent/security_group_agent/__init__.py @@ -5,14 +5,14 @@ # 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. -# +# # Automatically generated by addcopyright.py at 01/29/2013 diff --git a/plugins/hypervisors/baremetal/resources/security_group_agent/security_group_agent/cs_sg_agent.py b/plugins/hypervisors/baremetal/resources/security_group_agent/security_group_agent/cs_sg_agent.py index a292c0bcfb..0c49a3f786 100755 --- a/plugins/hypervisors/baremetal/resources/security_group_agent/security_group_agent/cs_sg_agent.py +++ b/plugins/hypervisors/baremetal/resources/security_group_agent/security_group_agent/cs_sg_agent.py @@ -5,16 +5,16 @@ # 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. -# +# # Automatically generated by addcopyright.py at 01/29/2013 ''' Created on Jan 2, 2013 @@ -234,4 +234,3 @@ def main(): agentdaemon.restart() sys.exit(0) - \ No newline at end of file diff --git a/plugins/hypervisors/baremetal/resources/security_group_agent/security_group_agent/sglib.py b/plugins/hypervisors/baremetal/resources/security_group_agent/security_group_agent/sglib.py index bf64effa19..bc675b540a 100755 --- a/plugins/hypervisors/baremetal/resources/security_group_agent/security_group_agent/sglib.py +++ b/plugins/hypervisors/baremetal/resources/security_group_agent/security_group_agent/sglib.py @@ -6,16 +6,16 @@ # 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. -# +# # Automatically generated by addcopyright.py at 01/29/2013 import sys, os, time, atexit @@ -31,7 +31,7 @@ def __init__(self): self.body = None self.method = None self.query_string = None - + @staticmethod def from_cherrypy_request(creq): req = Request() @@ -40,10 +40,10 @@ def from_cherrypy_request(creq): req.method = copy.copy(creq.method) req.query_string = copy.copy(creq.query_string) if creq.query_string else None return req - + class ShellError(Exception): '''shell error''' - + class ShellCmd(object): ''' classdocs @@ -57,11 +57,11 @@ def __init__(self, cmd, workdir=None, pipe=True): self.process = subprocess.Popen(cmd, shell=True, stdout=subprocess.PIPE, stdin=subprocess.PIPE, stderr=subprocess.PIPE, executable='/bin/sh', cwd=workdir) else: self.process = subprocess.Popen(cmd, shell=True, executable='/bin/sh', cwd=workdir) - + self.stdout = None self.stderr = None self.return_code = None - + def __call__(self, is_exception=True): (self.stdout, self.stderr) = self.process.communicate() if is_exception and self.process.returncode != 0: @@ -71,18 +71,18 @@ def __call__(self, is_exception=True): err.append('stdout: %s' % self.stdout) err.append('stderr: %s' % self.stderr) raise ShellError('\n'.join(err)) - + self.return_code = self.process.returncode return self.stdout class Daemon(object): """ A generic daemon class. - + Usage: subclass the Daemon class and override the run() method """ atexit_hooks = [] - + def __init__(self, pidfile, stdin='/dev/null', stdout='/dev/null', stderr='/dev/null'): self.stdin = stdin self.stdout = stdout @@ -102,37 +102,37 @@ def _atexit(): content = traceback.format_exc() err = 'Exception when calling atexit hook[%s]\n%s' % (hook.__name__, content) #logger.error(err) - + def daemonize(self): """ - do the UNIX double-fork magic, see Stevens' "Advanced + do the UNIX double-fork magic, see Stevens' "Advanced Programming in the UNIX Environment" for details (ISBN 0201563177) http://www.erlenstar.demon.co.uk/unix/faq_2.html#SEC16 """ - try: - pid = os.fork() + try: + pid = os.fork() if pid > 0: # exit first parent - sys.exit(0) - except OSError, e: + sys.exit(0) + except OSError, e: sys.stderr.write("fork #1 failed: %d (%s)\n" % (e.errno, e.strerror)) sys.exit(1) - + # decouple from parent environment - os.chdir("/") - os.setsid() - os.umask(0) - + os.chdir("/") + os.setsid() + os.umask(0) + # do second fork - try: - pid = os.fork() + try: + pid = os.fork() if pid > 0: # exit from second parent - sys.exit(0) - except OSError, e: + sys.exit(0) + except OSError, e: sys.stderr.write("fork #2 failed: %d (%s)\n" % (e.errno, e.strerror)) - sys.exit(1) - + sys.exit(1) + # redirect standard file descriptors sys.stdout.flush() sys.stderr.flush() @@ -142,13 +142,13 @@ def daemonize(self): os.dup2(si.fileno(), sys.stdin.fileno()) os.dup2(so.fileno(), sys.stdout.fileno()) os.dup2(se.fileno(), sys.stderr.fileno()) - + # write pidfile Daemon.register_atexit_hook(self.delpid) atexit.register(Daemon._atexit) pid = str(os.getpid()) file(self.pidfile,'w').write("%s\n" % pid) - + def delpid(self): os.remove(self.pidfile) @@ -163,7 +163,7 @@ def start(self): pf.close() except IOError: pid = None - + if pid: pscmd = ShellCmd('ps -p %s > /dev/null' % pid) pscmd(is_exception=False) @@ -171,7 +171,7 @@ def start(self): message = "Daemon already running, pid is %s\n" sys.stderr.write(message % pid) sys.exit(0) - + # Start the daemon self.daemonize() try: @@ -192,13 +192,13 @@ def stop(self): pf.close() except IOError: pid = None - + if not pid: message = "pidfile %s does not exist. Daemon not running?\n" sys.stderr.write(message % self.pidfile) return # not an error in a restart - # Try killing the daemon process + # Try killing the daemon process try: while 1: os.kill(pid, SIGTERM) diff --git a/plugins/hypervisors/baremetal/resources/security_group_agent/security_group_agent/xmlobject.py b/plugins/hypervisors/baremetal/resources/security_group_agent/security_group_agent/xmlobject.py index cb66d265a5..175349958c 100755 --- a/plugins/hypervisors/baremetal/resources/security_group_agent/security_group_agent/xmlobject.py +++ b/plugins/hypervisors/baremetal/resources/security_group_agent/security_group_agent/xmlobject.py @@ -5,16 +5,16 @@ # 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. -# +# # Automatically generated by addcopyright.py at 01/29/2013 ''' Created on Dec 25, 2012 diff --git a/plugins/hypervisors/baremetal/resources/security_group_agent/setup.py b/plugins/hypervisors/baremetal/resources/security_group_agent/setup.py index 384e04d6a9..ed106313ff 100755 --- a/plugins/hypervisors/baremetal/resources/security_group_agent/setup.py +++ b/plugins/hypervisors/baremetal/resources/security_group_agent/setup.py @@ -5,16 +5,16 @@ # 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. -# +# # Automatically generated by addcopyright.py at 01/29/2013 from setuptools import setup, find_packages import sys, os diff --git a/plugins/hypervisors/baremetal/src/com/cloud/baremetal/manager/BareMetalDiscoverer.java b/plugins/hypervisors/baremetal/src/com/cloud/baremetal/manager/BareMetalDiscoverer.java index c312df7b79..8b4b45348f 100755 --- a/plugins/hypervisors/baremetal/src/com/cloud/baremetal/manager/BareMetalDiscoverer.java +++ b/plugins/hypervisors/baremetal/src/com/cloud/baremetal/manager/BareMetalDiscoverer.java @@ -80,8 +80,8 @@ public boolean stop() { } @Override - public Map> - find(long dcId, Long podId, Long clusterId, URI url, String username, String password, List hostTags) throws DiscoveryException { + public Map> find(long dcId, Long podId, Long clusterId, URI url, String username, String password, List hostTags) + throws DiscoveryException { /* Enable this after we decide to use addBaremetalHostCmd instead of addHostCmd String discoverName = _params.get(ApiConstants.BAREMETAL_DISCOVER_NAME); @@ -130,18 +130,18 @@ public boolean stop() { String injectScript = "scripts/util/ipmi.py"; String scriptPath = Script.findScript("", injectScript); if (scriptPath == null) { - throw new CloudRuntimeException("Unable to find key ipmi script " + injectScript); + throw new CloudRuntimeException("Unable to find key ipmi script " + + injectScript); } final Script2 command = new Script2(scriptPath, s_logger); command.add("ping"); - command.add("hostname=" + ipmiIp); - command.add("usrname=" + username); - command.add("password=" + password, ParamType.PASSWORD); + command.add("hostname="+ipmiIp); + command.add("usrname="+username); + command.add("password="+password, ParamType.PASSWORD); final String result = command.execute(); if (result != null) { - s_logger.warn(String.format("Can not set up ipmi connection(ip=%1$s, username=%2$s, password=%3$s, args) because %4$s", ipmiIp, username, "******", - result)); + s_logger.warn(String.format("Can not set up ipmi connection(ip=%1$s, username=%2$s, password=%3$s, args) because %4$s", ipmiIp, username, "******", result)); return null; } @@ -155,21 +155,22 @@ public boolean stop() { params.putAll(_params); params.put("zone", Long.toString(dcId)); params.put("pod", Long.toString(podId)); - params.put("cluster", Long.toString(clusterId)); + params.put("cluster", Long.toString(clusterId)); params.put("guid", guid); params.put(ApiConstants.PRIVATE_IP, ipmiIp); params.put(ApiConstants.USERNAME, username); params.put(ApiConstants.PASSWORD, password); + params.put("vmDao", _vmDao); + params.put("configDao", _configDao); String resourceClassName = _configDao.getValue(Config.ExternalBaremetalResourceClassName.key()); BareMetalResourceBase resource = null; if (resourceClassName != null) { Class clazz = Class.forName(resourceClassName); - resource = (BareMetalResourceBase)clazz.newInstance(); + resource = (BareMetalResourceBase) clazz.newInstance(); String externalUrl = _configDao.getValue(Config.ExternalBaremetalSystemUrl.key()); if (externalUrl == null) { - throw new IllegalArgumentException( - String.format("You must specify ExternalBaremetalSystemUrl in global config page as ExternalBaremetalResourceClassName is not null")); + throw new IllegalArgumentException(String.format("You must specify ExternalBaremetalSystemUrl in global config page as ExternalBaremetalResourceClassName is not null")); } details.put(BaremetalManager.ExternalBaremetalSystemUrl, externalUrl); } else { @@ -206,8 +207,8 @@ public boolean stop() { zone.setDhcpProvider(Network.Provider.ExternalDhcpServer.getName()); _dcDao.update(zone.getId(), zone); - s_logger.debug(String.format("Discover Bare Metal host successfully(ip=%1$s, username=%2$s, password=%3%s," - + "cpuNum=%4$s, cpuCapacity-%5$s, memCapacity=%6$s)", ipmiIp, username, "******", cpuNum, cpuCapacity, memCapacity)); + s_logger.debug(String.format("Discover Bare Metal host successfully(ip=%1$s, username=%2$s, password=%3%s," + + "cpuNum=%4$s, cpuCapacity-%5$s, memCapacity=%6$s)", ipmiIp, username, "******", cpuNum, cpuCapacity, memCapacity)); return resources; } catch (Exception e) { s_logger.warn("Can not set up bare metal agent", e); @@ -217,7 +218,8 @@ public boolean stop() { } @Override - public void postDiscovery(List hosts, long msId) throws DiscoveryException { + public void postDiscovery(List hosts, long msId) + throws DiscoveryException { } @Override @@ -273,6 +275,8 @@ protected HashMap buildConfigParams(HostVO host) { HashMap params = super.buildConfigParams(host); params.put("hostId", host.getId()); params.put("ipaddress", host.getPrivateIpAddress()); + params.put("vmDao", _vmDao); + params.put("configDao", _configDao); return params; } diff --git a/plugins/hypervisors/baremetal/src/com/cloud/baremetal/networkservice/BareMetalResourceBase.java b/plugins/hypervisors/baremetal/src/com/cloud/baremetal/networkservice/BareMetalResourceBase.java index b729d9bb3e..828533708e 100755 --- a/plugins/hypervisors/baremetal/src/com/cloud/baremetal/networkservice/BareMetalResourceBase.java +++ b/plugins/hypervisors/baremetal/src/com/cloud/baremetal/networkservice/BareMetalResourceBase.java @@ -22,18 +22,6 @@ // Automatically generated by addcopyright.py at 04/03/2012 package com.cloud.baremetal.networkservice; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.concurrent.TimeUnit; - -import javax.ejb.Local; -import javax.naming.ConfigurationException; - -import org.apache.log4j.Logger; - -import org.apache.cloudstack.api.ApiConstants; - import com.cloud.agent.IAgentControl; import com.cloud.agent.api.Answer; import com.cloud.agent.api.CheckNetworkAnswer; @@ -48,6 +36,7 @@ import com.cloud.agent.api.MigrateCommand; import com.cloud.agent.api.PingCommand; import com.cloud.agent.api.PingRoutingCommand; +import com.cloud.agent.api.PingRoutingWithNwGroupsCommand; import com.cloud.agent.api.PrepareForMigrationAnswer; import com.cloud.agent.api.PrepareForMigrationCommand; import com.cloud.agent.api.ReadyAnswer; @@ -66,10 +55,11 @@ import com.cloud.agent.api.baremetal.IpmiBootorResetCommand; import com.cloud.agent.api.to.VirtualMachineTO; import com.cloud.baremetal.manager.BaremetalManager; +import com.cloud.configuration.Config; import com.cloud.host.Host.Type; import com.cloud.hypervisor.Hypervisor; import com.cloud.resource.ServerResource; -import com.cloud.utils.component.ComponentContext; +import com.cloud.utils.Pair; import com.cloud.utils.component.ManagerBase; import com.cloud.utils.exception.CloudRuntimeException; import com.cloud.utils.script.OutputInterpreter; @@ -81,6 +71,16 @@ import com.cloud.vm.VirtualMachine.PowerState; import com.cloud.vm.VirtualMachine.State; import com.cloud.vm.dao.VMInstanceDao; +import org.apache.cloudstack.api.ApiConstants; +import org.apache.cloudstack.framework.config.dao.ConfigurationDao; +import org.apache.log4j.Logger; + +import javax.ejb.Local; +import javax.naming.ConfigurationException; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.concurrent.TimeUnit; @Local(value = ServerResource.class) public class BareMetalResourceBase extends ManagerBase implements ServerResource { @@ -111,6 +111,9 @@ public class BareMetalResourceBase extends ManagerBase implements ServerResource protected Script2 _forcePowerOffCommand; protected Script2 _bootOrRebootCommand; protected String _vmName; + protected int ipmiRetryTimes = 5; + + protected ConfigurationDao configDao; protected VMInstanceDao vmDao; private void changeVmState(String vmName, VirtualMachine.State state) { @@ -128,27 +131,29 @@ private State removeVmState(String vmName) { @Override public boolean configure(String name, Map params) throws ConfigurationException { _name = name; - _uuid = (String)params.get("guid"); + _uuid = (String) params.get("guid"); try { - _memCapacity = Long.parseLong((String)params.get(ApiConstants.MEMORY)) * 1024L * 1024L; - _cpuCapacity = Long.parseLong((String)params.get(ApiConstants.CPU_SPEED)); - _cpuNum = Long.parseLong((String)params.get(ApiConstants.CPU_NUMBER)); + _memCapacity = Long.parseLong((String) params.get(ApiConstants.MEMORY)) * 1024L * 1024L; + _cpuCapacity = Long.parseLong((String) params.get(ApiConstants.CPU_SPEED)); + _cpuNum = Long.parseLong((String) params.get(ApiConstants.CPU_NUMBER)); } catch (NumberFormatException e) { throw new ConfigurationException(String.format("Unable to parse number of CPU or memory capacity " - + "or cpu capacity(cpu number = %1$s memCapacity=%2$s, cpuCapacity=%3$s", params.get(ApiConstants.CPU_NUMBER), params.get(ApiConstants.MEMORY), - params.get(ApiConstants.CPU_SPEED))); + + "or cpu capacity(cpu number = %1$s memCapacity=%2$s, cpuCapacity=%3$s", params.get(ApiConstants.CPU_NUMBER), + params.get(ApiConstants.MEMORY), params.get(ApiConstants.CPU_SPEED))); } - _zone = (String)params.get("zone"); - _pod = (String)params.get("pod"); - _cluster = (String)params.get("cluster"); - hostId = (Long)params.get("hostId"); - _ip = (String)params.get(ApiConstants.PRIVATE_IP); - _mac = (String)params.get(ApiConstants.HOST_MAC); - _username = (String)params.get(ApiConstants.USERNAME); - _password = (String)params.get(ApiConstants.PASSWORD); - _vmName = (String)params.get("vmName"); - String echoScAgent = (String)params.get(BaremetalManager.EchoSecurityGroupAgent); + _zone = (String) params.get("zone"); + _pod = (String) params.get("pod"); + _cluster = (String) params.get("cluster"); + hostId = (Long) params.get("hostId"); + _ip = (String) params.get(ApiConstants.PRIVATE_IP); + _mac = (String) params.get(ApiConstants.HOST_MAC); + _username = (String) params.get(ApiConstants.USERNAME); + _password = (String) params.get(ApiConstants.PASSWORD); + _vmName = (String) params.get("vmName"); + String echoScAgent = (String) params.get(BaremetalManager.EchoSecurityGroupAgent); + vmDao = (VMInstanceDao) params.get("vmDao"); + configDao = (ConfigurationDao) params.get("configDao"); if (_pod == null) { throw new ConfigurationException("Unable to get the pod"); @@ -167,7 +172,8 @@ public boolean configure(String name, Map params) throws Configu } if (_mac.split(":").length != 6) { - throw new ConfigurationException("Wrong MAC format(" + _mac + "). It must be in format of for example 00:11:ba:33:aa:dd which is not case sensitive"); + throw new ConfigurationException("Wrong MAC format(" + _mac + + "). It must be in format of for example 00:11:ba:33:aa:dd which is not case sensitive"); } if (_uuid == null) { @@ -178,6 +184,19 @@ public boolean configure(String name, Map params) throws Configu _isEchoScAgent = Boolean.valueOf(echoScAgent); } + String ipmiIface = "default"; + try { + ipmiIface = configDao.getValue(Config.BaremetalIpmiLanInterface.key()); + } catch (Exception e) { + s_logger.debug(e.getMessage(), e); + } + + try { + ipmiRetryTimes = Integer.valueOf(configDao.getValue(Config.BaremetalIpmiRetryTimes.key())); + } catch (Exception e) { + s_logger.debug(e.getMessage(), e); + } + String injectScript = "scripts/util/ipmi.py"; String scriptPath = Script.findScript("", injectScript); if (scriptPath == null) { @@ -187,6 +206,7 @@ public boolean configure(String name, Map params) throws Configu _pingCommand = new Script2(pythonPath, s_logger); _pingCommand.add(scriptPath); _pingCommand.add("ping"); + _pingCommand.add("interface=" + ipmiIface); _pingCommand.add("hostname=" + _ip); _pingCommand.add("usrname=" + _username); _pingCommand.add("password=" + _password, ParamType.PASSWORD); @@ -194,6 +214,7 @@ public boolean configure(String name, Map params) throws Configu _setPxeBootCommand = new Script2(pythonPath, s_logger); _setPxeBootCommand.add(scriptPath); _setPxeBootCommand.add("boot_dev"); + _setPxeBootCommand.add("interface=" + ipmiIface); _setPxeBootCommand.add("hostname=" + _ip); _setPxeBootCommand.add("usrname=" + _username); _setPxeBootCommand.add("password=" + _password, ParamType.PASSWORD); @@ -202,6 +223,7 @@ public boolean configure(String name, Map params) throws Configu _setDiskBootCommand = new Script2(pythonPath, s_logger); _setDiskBootCommand.add(scriptPath); _setDiskBootCommand.add("boot_dev"); + _setDiskBootCommand.add("interface=" + ipmiIface); _setDiskBootCommand.add("hostname=" + _ip); _setDiskBootCommand.add("usrname=" + _username); _setDiskBootCommand.add("password=" + _password, ParamType.PASSWORD); @@ -210,6 +232,7 @@ public boolean configure(String name, Map params) throws Configu _rebootCommand = new Script2(pythonPath, s_logger); _rebootCommand.add(scriptPath); _rebootCommand.add("reboot"); + _rebootCommand.add("interface=" + ipmiIface); _rebootCommand.add("hostname=" + _ip); _rebootCommand.add("usrname=" + _username); _rebootCommand.add("password=" + _password, ParamType.PASSWORD); @@ -217,6 +240,7 @@ public boolean configure(String name, Map params) throws Configu _getStatusCommand = new Script2(pythonPath, s_logger); _getStatusCommand.add(scriptPath); _getStatusCommand.add("ping"); + _getStatusCommand.add("interface=" + ipmiIface); _getStatusCommand.add("hostname=" + _ip); _getStatusCommand.add("usrname=" + _username); _getStatusCommand.add("password=" + _password, ParamType.PASSWORD); @@ -224,6 +248,7 @@ public boolean configure(String name, Map params) throws Configu _powerOnCommand = new Script2(pythonPath, s_logger); _powerOnCommand.add(scriptPath); _powerOnCommand.add("power"); + _powerOnCommand.add("interface=" + ipmiIface); _powerOnCommand.add("hostname=" + _ip); _powerOnCommand.add("usrname=" + _username); _powerOnCommand.add("password=" + _password, ParamType.PASSWORD); @@ -232,6 +257,7 @@ public boolean configure(String name, Map params) throws Configu _powerOffCommand = new Script2(pythonPath, s_logger); _powerOffCommand.add(scriptPath); _powerOffCommand.add("power"); + _powerOffCommand.add("interface=" + ipmiIface); _powerOffCommand.add("hostname=" + _ip); _powerOffCommand.add("usrname=" + _username); _powerOffCommand.add("password=" + _password, ParamType.PASSWORD); @@ -240,6 +266,7 @@ public boolean configure(String name, Map params) throws Configu _forcePowerOffCommand = new Script2(pythonPath, s_logger); _forcePowerOffCommand.add(scriptPath); _forcePowerOffCommand.add("power"); + _forcePowerOffCommand.add("interface=" + ipmiIface); _forcePowerOffCommand.add("hostname=" + _ip); _forcePowerOffCommand.add("usrname=" + _username); _forcePowerOffCommand.add("password=" + _password, ParamType.PASSWORD); @@ -248,6 +275,7 @@ public boolean configure(String name, Map params) throws Configu _bootOrRebootCommand = new Script2(pythonPath, s_logger); _bootOrRebootCommand.add(scriptPath); _bootOrRebootCommand.add("boot_or_reboot"); + _bootOrRebootCommand.add("interface=" + ipmiIface); _bootOrRebootCommand.add("hostname=" + _ip); _bootOrRebootCommand.add("usrname=" + _username); _bootOrRebootCommand.add("password=" + _password, ParamType.PASSWORD); @@ -259,8 +287,15 @@ protected boolean doScript(Script cmd) { return doScript(cmd, null); } + protected boolean doScript(Script cmd, int retry) { + return doScript(cmd, null, retry); + } + protected boolean doScript(Script cmd, OutputInterpreter interpreter) { - int retry = 5; + return doScript(cmd, interpreter, ipmiRetryTimes); + } + + protected boolean doScript(Script cmd, OutputInterpreter interpreter, int retry) { String res = null; while (retry-- > 0) { if (interpreter == null) { @@ -270,6 +305,10 @@ protected boolean doScript(Script cmd, OutputInterpreter interpreter) { } if (res != null && res.startsWith("Error: Unable to establish LAN")) { s_logger.warn("IPMI script timeout(" + cmd.toString() + "), will retry " + retry + " times"); + try { + TimeUnit.SECONDS.sleep(1); + } catch (InterruptedException e) { + } continue; } else if (res == null) { return true; @@ -318,7 +357,6 @@ protected State getVmState() { protected Map fullSync() { Map states = new HashMap(); if (hostId != null) { - vmDao = ComponentContext.getComponent(VMInstanceDao.class); final List vms = vmDao.listByHostId(hostId); for (VMInstanceVO vm : vms) { states.put(vm.getInstanceName(), vm.getState()); @@ -337,10 +375,14 @@ protected Map fullSync() { protected Map getHostVmStateReport() { Map states = new HashMap(); if (hostId != null) { - vmDao = ComponentContext.getComponent(VMInstanceDao.class); final List vms = vmDao.listByHostId(hostId); for (VMInstanceVO vm : vms) { - states.put(vm.getInstanceName(), new HostVmStateReportEntry(vm.getState() == State.Running ? PowerState.PowerOn : PowerState.PowerOff, "host-" + hostId)); + states.put( + vm.getInstanceName(), + new HostVmStateReportEntry( + vm.getState() == State.Running ? PowerState.PowerOn : PowerState.PowerOff, "host-" + hostId + ) + ); } } /* @@ -355,7 +397,8 @@ protected Map getHostVmStateReport() { @Override public StartupCommand[] initialize() { - StartupRoutingCommand cmd = new StartupRoutingCommand(0, 0, 0, 0, null, Hypervisor.HypervisorType.BareMetal, new HashMap(), null, null); + StartupRoutingCommand cmd = new StartupRoutingCommand(0, 0, 0, 0, null, Hypervisor.HypervisorType.BareMetal, + new HashMap(), null, null); cmd.setDataCenter(_zone); cmd.setPod(_pod); @@ -365,13 +408,13 @@ public StartupCommand[] initialize() { cmd.setPrivateIpAddress(_ip); cmd.setStorageIpAddress(_ip); cmd.setVersion(BareMetalResourceBase.class.getPackage().getImplementationVersion()); - cmd.setCpus((int)_cpuNum); + cmd.setCpus((int) _cpuNum); cmd.setSpeed(_cpuCapacity); cmd.setMemory(_memCapacity); cmd.setPrivateMacAddress(_mac); cmd.setPublicMacAddress(_mac); cmd.setStateChanges(fullSync()); - return new StartupCommand[] {cmd}; + return new StartupCommand[] { cmd }; } private boolean ipmiPing() { @@ -393,7 +436,19 @@ public PingCommand getCurrentStatus(long id) { return null; } - return new PingRoutingCommand(getType(), id, deltaSync(), getHostVmStateReport()); + if (hostId != null) { + final List vms = vmDao.listByHostId(hostId); + if (vms.isEmpty()) { + return new PingRoutingCommand(getType(), id, deltaSync(), getHostVmStateReport()); + } else { + VMInstanceVO vm = vms.get(0); + SecurityGroupHttpClient client = new SecurityGroupHttpClient(); + HashMap> nwGrpStates = client.sync(vm.getInstanceName(), vm.getId(), vm.getPrivateIpAddress()); + return new PingRoutingWithNwGroupsCommand(getType(), id, null, getHostVmStateReport(), nwGrpStates); + } + } else { + return new PingRoutingCommand(getType(), id, deltaSync(), getHostVmStateReport()); + } } protected Answer execute(IpmISetBootDevCommand cmd) { @@ -456,29 +511,29 @@ protected Answer execute(SecurityGroupRulesCmd cmd) { public Answer executeRequest(Command cmd) { try { if (cmd instanceof ReadyCommand) { - return execute((ReadyCommand)cmd); + return execute((ReadyCommand) cmd); } else if (cmd instanceof StartCommand) { - return execute((StartCommand)cmd); + return execute((StartCommand) cmd); } else if (cmd instanceof StopCommand) { - return execute((StopCommand)cmd); + return execute((StopCommand) cmd); } else if (cmd instanceof RebootCommand) { - return execute((RebootCommand)cmd); + return execute((RebootCommand) cmd); } else if (cmd instanceof IpmISetBootDevCommand) { - return execute((IpmISetBootDevCommand)cmd); + return execute((IpmISetBootDevCommand) cmd); } else if (cmd instanceof MaintainCommand) { - return execute((MaintainCommand)cmd); + return execute((MaintainCommand) cmd); } else if (cmd instanceof PrepareForMigrationCommand) { - return execute((PrepareForMigrationCommand)cmd); + return execute((PrepareForMigrationCommand) cmd); } else if (cmd instanceof MigrateCommand) { - return execute((MigrateCommand)cmd); + return execute((MigrateCommand) cmd); } else if (cmd instanceof CheckVirtualMachineCommand) { - return execute((CheckVirtualMachineCommand)cmd); + return execute((CheckVirtualMachineCommand) cmd); } else if (cmd instanceof IpmiBootorResetCommand) { - return execute((IpmiBootorResetCommand)cmd); + return execute((IpmiBootorResetCommand) cmd); } else if (cmd instanceof SecurityGroupRulesCmd) { - return execute((SecurityGroupRulesCmd)cmd); + return execute((SecurityGroupRulesCmd) cmd); } else if (cmd instanceof CheckNetworkCommand) { - return execute((CheckNetworkCommand)cmd); + return execute((CheckNetworkCommand) cmd); } else { return Answer.createUnsupportedCommandAnswer(cmd); } @@ -499,8 +554,17 @@ protected boolean isPowerOn(String str) { } protected RebootAnswer execute(final RebootCommand cmd) { - if (!doScript(_rebootCommand)) { - return new RebootAnswer(cmd, "IPMI reboot failed", false); + String infoStr = "Command not supported in present state"; + OutputInterpreter.AllLinesParser interpreter = new OutputInterpreter.AllLinesParser(); + if (!doScript(_rebootCommand, interpreter, 10)) { + if (interpreter.getLines().contains(infoStr)) { + // try again, this error should be temporary + if (!doScript(_rebootCommand, interpreter, 10)) { + return new RebootAnswer(cmd, "IPMI reboot failed", false); + } + } else { + return new RebootAnswer(cmd, "IPMI reboot failed", false); + } } return new RebootAnswer(cmd, "reboot succeeded", true); @@ -524,7 +588,8 @@ protected StopAnswer execute(final StopCommand cmd) { OutputInterpreter.AllLinesParser interpreter = new OutputInterpreter.AllLinesParser(); if (!doScript(_getStatusCommand, interpreter)) { - s_logger.warn("Cannot get power status of " + _name + ", assume VM state was not changed"); + success = true; + s_logger.warn("Cannot get power status of " + _name + ", assume VM state changed successfully"); break; } diff --git a/plugins/hypervisors/baremetal/src/com/cloud/baremetal/networkservice/BaremetalPxeManagerImpl.java b/plugins/hypervisors/baremetal/src/com/cloud/baremetal/networkservice/BaremetalPxeManagerImpl.java index ca2f8fe703..261534a3dd 100755 --- a/plugins/hypervisors/baremetal/src/com/cloud/baremetal/networkservice/BaremetalPxeManagerImpl.java +++ b/plugins/hypervisors/baremetal/src/com/cloud/baremetal/networkservice/BaremetalPxeManagerImpl.java @@ -193,7 +193,7 @@ public List listPxeServers(ListBaremetalPxeServersCmd cmd) @Override public boolean addUserData(NicProfile nic, VirtualMachineProfile profile) { - UserVmVO vm = (UserVmVO)profile.getVirtualMachine(); + UserVmVO vm = _vmDao.findById(profile.getVirtualMachine().getId()); _vmDao.loadDetails(vm); String serviceOffering = _serviceOfferingDao.findByIdIncludingRemoved(vm.getId(), vm.getServiceOfferingId()).getDisplayText(); diff --git a/plugins/hypervisors/baremetal/src/com/cloud/baremetal/networkservice/SecurityGroupHttpClient.java b/plugins/hypervisors/baremetal/src/com/cloud/baremetal/networkservice/SecurityGroupHttpClient.java index a3998a3bc7..b9e4858895 100755 --- a/plugins/hypervisors/baremetal/src/com/cloud/baremetal/networkservice/SecurityGroupHttpClient.java +++ b/plugins/hypervisors/baremetal/src/com/cloud/baremetal/networkservice/SecurityGroupHttpClient.java @@ -1,38 +1,205 @@ -// 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. -// -// Automatically generated by addcopyright.py at 01/29/2013 -// Apache License, Version 2.0 (the "License"); you may not use this -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -package com.cloud.baremetal.networkservice; - -import com.cloud.agent.api.Answer; -import com.cloud.agent.api.SecurityGroupRulesCmd; - -public class SecurityGroupHttpClient { - - public Answer call(String guestIp, SecurityGroupRulesCmd cmd) { - // TODO Auto-generated method stub - return null; - } - - public boolean echo(String ip, long millis, long millis2) { - // TODO Auto-generated method stub - return false; - } - -} +// 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. +// +// Automatically generated by addcopyright.py at 01/29/2013 +// Apache License, Version 2.0 (the "License"); you may not use this +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// +// Automatically generated by addcopyright.py at 04/03/2012 + +package com.cloud.baremetal.networkservice; + +import com.cloud.agent.api.SecurityGroupRuleAnswer; +import com.cloud.agent.api.SecurityGroupRulesCmd; +import com.cloud.agent.api.SecurityGroupRulesCmd.IpPortAndProto; +import com.cloud.baremetal.networkservice.schema.SecurityGroupRule; +import com.cloud.baremetal.networkservice.schema.SecurityGroupVmRuleSet; +import com.cloud.utils.Pair; +import com.cloud.utils.exception.CloudRuntimeException; +import org.apache.commons.httpclient.HttpClient; +import org.apache.commons.httpclient.MultiThreadedHttpConnectionManager; +import org.apache.commons.httpclient.methods.PostMethod; +import org.apache.commons.httpclient.methods.StringRequestEntity; +import org.apache.log4j.Logger; + +import javax.xml.bind.JAXBContext; +import javax.xml.bind.Marshaller; +import java.io.StringWriter; +import java.net.SocketTimeoutException; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.concurrent.TimeUnit; + +public class SecurityGroupHttpClient { + private static final Logger logger = Logger.getLogger(SecurityGroupHttpClient.class); + private static final String ARG_NAME = "args"; + private static final String COMMAND = "command"; + private JAXBContext context; + private int port; + private static HttpClient httpClient; + static { + MultiThreadedHttpConnectionManager connman = new MultiThreadedHttpConnectionManager(); + httpClient = new HttpClient(connman); + httpClient.setConnectionTimeout(5000); + } + + private enum OpConstant { + setRules, echo, + } + + public SecurityGroupHttpClient() { + try { + context = JAXBContext.newInstance(SecurityGroupRule.class, SecurityGroupVmRuleSet.class); + port = 9988; + } catch (Exception e) { + throw new CloudRuntimeException( + "Unable to create JAXBContext for security group", e); + } + } + + private List generateRules(IpPortAndProto[] ipps) { + List rules = new ArrayList( + ipps.length); + for (SecurityGroupRulesCmd.IpPortAndProto ipp : ipps) { + SecurityGroupRule r = new SecurityGroupRule(); + r.setProtocol(ipp.getProto()); + r.setStartPort(ipp.getStartPort()); + r.setEndPort(ipp.getEndPort()); + for (String cidr : ipp.getAllowedCidrs()) { + r.getIp().add(cidr); + } + rules.add(r); + } + return rules; + } + + public HashMap> sync(String vmName, Long vmId, String agentIp) { + HashMap> states = new HashMap>(); + PostMethod post = new PostMethod(String.format("http://%s:%s/", agentIp, getPort())); + try { + post.addRequestHeader("command", "sync"); + if (httpClient.executeMethod(post) != 200) { + logger.debug(String.format("echoing baremetal security group agent on %s got error: %s", agentIp, post.getResponseBodyAsString())); + } else { + String res = post.getResponseBodyAsString(); + // res = ';'.join([vmName, vmId, seqno]) + String[] rulelogs = res.split(","); + if (rulelogs.length != 6) { + logger.debug(String.format("host[%s] returns invalid security group sync document[%s], reset rules", agentIp, res)); + states.put(vmName, new Pair(vmId, -1L)); + return states; + } + Pair p = new Pair(Long.valueOf(rulelogs[1]), Long.valueOf(rulelogs[5])); + states.put(rulelogs[0], p); + return states; + } + } catch (SocketTimeoutException se) { + logger.warn(String.format("unable to sync security group rules on host[%s], %s", agentIp, se.getMessage())); + } catch (Exception e) { + logger.warn(String.format("unable to sync security group rules on host[%s]", agentIp), e); + } finally { + if (post != null) { + post.releaseConnection(); + } + } + return states; + } + + + public boolean echo(String agentIp, long l, long m) { + boolean ret = false; + int count = 1; + while (true) { + try { + Thread.sleep(m); + count++; + } catch (InterruptedException e1) { + logger.warn("", e1); + break; + } + PostMethod post = new PostMethod(String.format("http://%s:%s/", agentIp, getPort())); + try { + post.addRequestHeader("command", "echo"); + if (httpClient.executeMethod(post) != 200) { + logger.debug(String.format("echoing baremetal security group agent on %s got error: %s", agentIp, post.getResponseBodyAsString())); + } else { + ret = true; + } + break; + } catch (Exception e) { + if (count*m >= l) { + logger.debug(String.format("ping security group agent on vm[%s] timeout after %s minutes, starting vm failed, count=%s", agentIp, TimeUnit.MILLISECONDS.toSeconds(l), count)); + break; + } else { + logger.debug(String.format("Having pinged security group agent on vm[%s] %s times, continue to wait...", agentIp, count)); + } + } finally { + if (post != null) { + post.releaseConnection(); + } + } + } + return ret; + } + + public SecurityGroupRuleAnswer call(String agentIp, SecurityGroupRulesCmd cmd) { + PostMethod post = new PostMethod(String.format( + "http://%s:%s", agentIp, getPort())); + try { + SecurityGroupVmRuleSet rset = new SecurityGroupVmRuleSet(); + rset.getEgressRules().addAll(generateRules(cmd.getEgressRuleSet())); + rset.getIngressRules().addAll( + generateRules(cmd.getIngressRuleSet())); + rset.setVmName(cmd.getVmName()); + rset.setVmIp(cmd.getGuestIp()); + rset.setVmMac(cmd.getGuestMac()); + rset.setVmId(cmd.getVmId()); + rset.setSignature(cmd.getSignature()); + rset.setSequenceNumber(cmd.getSeqNum()); + Marshaller marshaller = context.createMarshaller(); + StringWriter writer = new StringWriter(); + marshaller.marshal(rset, writer); + String xmlContents = writer.toString(); + logger.debug(xmlContents); + + post.addRequestHeader("command", "set_rules"); + StringRequestEntity entity = new StringRequestEntity(xmlContents); + post.setRequestEntity(entity); + if (httpClient.executeMethod(post) != 200) { + return new SecurityGroupRuleAnswer(cmd, false, + post.getResponseBodyAsString()); + } else { + return new SecurityGroupRuleAnswer(cmd); + } + } catch (Exception e) { + return new SecurityGroupRuleAnswer(cmd, false, e.getMessage()); + } finally { + if (post != null) { + post.releaseConnection(); + } + } + } + + public int getPort() { + return port; + } + + public void setPort(int port) { + this.port = port; + } +} diff --git a/plugins/hypervisors/baremetal/src/com/cloud/baremetal/networkservice/schema/ObjectFactory.java b/plugins/hypervisors/baremetal/src/com/cloud/baremetal/networkservice/schema/ObjectFactory.java new file mode 100644 index 0000000000..b5bc694516 --- /dev/null +++ b/plugins/hypervisors/baremetal/src/com/cloud/baremetal/networkservice/schema/ObjectFactory.java @@ -0,0 +1,55 @@ +// +// This file was generated by the JavaTM Architecture for XML Binding(JAXB) Reference Implementation, vJAXB 2.1.10 +// See http://java.sun.com/xml/jaxb +// Any modifications to this file will be lost upon recompilation of the source schema. +// Generated on: 2012.07.11 at 03:24:15 PM PDT +// + + +package com.cloud.baremetal.networkservice.schema; + +import javax.xml.bind.annotation.XmlRegistry; + + +/** + * This object contains factory methods for each + * Java content interface and Java element interface + * generated in the com.cloud.network.security.schema package. + *

An ObjectFactory allows you to programatically + * construct new instances of the Java representation + * for XML content. The Java representation of XML + * content can consist of schema derived interfaces + * and classes representing the binding of schema + * type definitions, element declarations and model + * groups. Factory methods for each of these are + * provided in this class. + * + */ +@XmlRegistry +public class ObjectFactory { + + + /** + * Create a new ObjectFactory that can be used to create new instances of schema derived classes for package: com.cloud.network.security.schema + * + */ + public ObjectFactory() { + } + + /** + * Create an instance of {@link SecurityGroupRule } + * + */ + public SecurityGroupRule createSecurityGroupRule() { + return new SecurityGroupRule(); + } + + /** + * Create an instance of {@link SecurityGroupVmRuleSet } + * + */ + public SecurityGroupVmRuleSet createSecurityGroupVmRuleSet() { + return new SecurityGroupVmRuleSet(); + } + +} diff --git a/plugins/hypervisors/baremetal/src/com/cloud/baremetal/networkservice/schema/SecurityGroupRule.java b/plugins/hypervisors/baremetal/src/com/cloud/baremetal/networkservice/schema/SecurityGroupRule.java new file mode 100644 index 0000000000..050c3fdee7 --- /dev/null +++ b/plugins/hypervisors/baremetal/src/com/cloud/baremetal/networkservice/schema/SecurityGroupRule.java @@ -0,0 +1,146 @@ +// +// This file was generated by the JavaTM Architecture for XML Binding(JAXB) Reference Implementation, vJAXB 2.1.10 +// See http://java.sun.com/xml/jaxb +// Any modifications to this file will be lost upon recompilation of the source schema. +// Generated on: 2012.07.11 at 03:24:15 PM PDT +// + + +package com.cloud.baremetal.networkservice.schema; + +import java.util.ArrayList; +import java.util.List; +import javax.xml.bind.annotation.XmlAccessType; +import javax.xml.bind.annotation.XmlAccessorType; +import javax.xml.bind.annotation.XmlElement; +import javax.xml.bind.annotation.XmlSchemaType; +import javax.xml.bind.annotation.XmlType; + + +/** + *

Java class for SecurityGroupRule complex type. + * + *

The following schema fragment specifies the expected content contained within this class. + * + *

+ * <complexType name="SecurityGroupRule">
+ *   <complexContent>
+ *     <restriction base="{http://www.w3.org/2001/XMLSchema}anyType">
+ *       <sequence>
+ *         <element name="protocol" type="{http://www.w3.org/2001/XMLSchema}string"/>
+ *         <element name="startPort" type="{http://www.w3.org/2001/XMLSchema}unsignedInt"/>
+ *         <element name="endPort" type="{http://www.w3.org/2001/XMLSchema}unsignedInt"/>
+ *         <sequence maxOccurs="unbounded" minOccurs="0">
+ *           <element name="ip" type="{http://www.w3.org/2001/XMLSchema}string"/>
+ *         </sequence>
+ *       </sequence>
+ *     </restriction>
+ *   </complexContent>
+ * </complexType>
+ * 
+ * + * + */ +@XmlAccessorType(XmlAccessType.FIELD) +@XmlType(name = "SecurityGroupRule", propOrder = { + "protocol", + "startPort", + "endPort", + "ip" +}) +public class SecurityGroupRule { + + @XmlElement(required = true) + protected String protocol; + @XmlSchemaType(name = "unsignedInt") + protected long startPort; + @XmlSchemaType(name = "unsignedInt") + protected long endPort; + protected List ip; + + /** + * Gets the value of the protocol property. + * + * @return + * possible object is + * {@link String } + * + */ + public String getProtocol() { + return protocol; + } + + /** + * Sets the value of the protocol property. + * + * @param value + * allowed object is + * {@link String } + * + */ + public void setProtocol(String value) { + this.protocol = value; + } + + /** + * Gets the value of the startPort property. + * + */ + public long getStartPort() { + return startPort; + } + + /** + * Sets the value of the startPort property. + * + */ + public void setStartPort(long value) { + this.startPort = value; + } + + /** + * Gets the value of the endPort property. + * + */ + public long getEndPort() { + return endPort; + } + + /** + * Sets the value of the endPort property. + * + */ + public void setEndPort(long value) { + this.endPort = value; + } + + /** + * Gets the value of the ip property. + * + *

+ * This accessor method returns a reference to the live list, + * not a snapshot. Therefore any modification you make to the + * returned list will be present inside the JAXB object. + * This is why there is not a set method for the ip property. + * + *

+ * For example, to add a new item, do as follows: + *

+     *    getIp().add(newItem);
+     * 
+ * + * + *

+ * Objects of the following type(s) are allowed in the list + * {@link String } + * + * + */ + public List getIp() { + if (ip == null) { + ip = new ArrayList(); + } + return this.ip; + } + +} diff --git a/plugins/hypervisors/baremetal/src/com/cloud/baremetal/networkservice/schema/SecurityGroupVmRuleSet.java b/plugins/hypervisors/baremetal/src/com/cloud/baremetal/networkservice/schema/SecurityGroupVmRuleSet.java new file mode 100644 index 0000000000..2c50c0e24d --- /dev/null +++ b/plugins/hypervisors/baremetal/src/com/cloud/baremetal/networkservice/schema/SecurityGroupVmRuleSet.java @@ -0,0 +1,263 @@ +// +// This file was generated by the JavaTM Architecture for XML Binding(JAXB) Reference Implementation, vJAXB 2.1.10 +// See http://java.sun.com/xml/jaxb +// Any modifications to this file will be lost upon recompilation of the source schema. +// Generated on: 2012.07.11 at 03:24:15 PM PDT +// + + +package com.cloud.baremetal.networkservice.schema; + +import java.util.ArrayList; +import java.util.List; +import javax.xml.bind.annotation.XmlAccessType; +import javax.xml.bind.annotation.XmlAccessorType; +import javax.xml.bind.annotation.XmlElement; +import javax.xml.bind.annotation.XmlRootElement; +import javax.xml.bind.annotation.XmlType; + + +/** + *

Java class for anonymous complex type. + * + *

The following schema fragment specifies the expected content contained within this class. + * + *

+ * <complexType>
+ *   <complexContent>
+ *     <restriction base="{http://www.w3.org/2001/XMLSchema}anyType">
+ *       <sequence>
+ *         <element name="vmName" type="{http://www.w3.org/2001/XMLSchema}string"/>
+ *         <element name="vmId" type="{http://www.w3.org/2001/XMLSchema}long"/>
+ *         <element name="vmIp" type="{http://www.w3.org/2001/XMLSchema}string"/>
+ *         <element name="vmMac" type="{http://www.w3.org/2001/XMLSchema}string"/>
+ *         <element name="signature" type="{http://www.w3.org/2001/XMLSchema}string"/>
+ *         <element name="sequenceNumber" type="{http://www.w3.org/2001/XMLSchema}long"/>
+ *         <sequence maxOccurs="unbounded" minOccurs="0">
+ *           <element name="ingressRules" type="{}SecurityGroupRule"/>
+ *         </sequence>
+ *         <sequence maxOccurs="unbounded" minOccurs="0">
+ *           <element name="egressRules" type="{}SecurityGroupRule"/>
+ *         </sequence>
+ *       </sequence>
+ *     </restriction>
+ *   </complexContent>
+ * </complexType>
+ * 
+ * + * + */ +@XmlAccessorType(XmlAccessType.FIELD) +@XmlType(name = "", propOrder = { + "vmName", + "vmId", + "vmIp", + "vmMac", + "signature", + "sequenceNumber", + "ingressRules", + "egressRules" +}) +@XmlRootElement(name = "SecurityGroupVmRuleSet") +public class SecurityGroupVmRuleSet { + + @XmlElement(required = true) + protected String vmName; + protected long vmId; + @XmlElement(required = true) + protected String vmIp; + @XmlElement(required = true) + protected String vmMac; + @XmlElement(required = true) + protected String signature; + protected long sequenceNumber; + protected List ingressRules; + protected List egressRules; + + /** + * Gets the value of the vmName property. + * + * @return + * possible object is + * {@link String } + * + */ + public String getVmName() { + return vmName; + } + + /** + * Sets the value of the vmName property. + * + * @param value + * allowed object is + * {@link String } + * + */ + public void setVmName(String value) { + this.vmName = value; + } + + /** + * Gets the value of the vmId property. + * + */ + public long getVmId() { + return vmId; + } + + /** + * Sets the value of the vmId property. + * + */ + public void setVmId(long value) { + this.vmId = value; + } + + /** + * Gets the value of the vmIp property. + * + * @return + * possible object is + * {@link String } + * + */ + public String getVmIp() { + return vmIp; + } + + /** + * Sets the value of the vmIp property. + * + * @param value + * allowed object is + * {@link String } + * + */ + public void setVmIp(String value) { + this.vmIp = value; + } + + /** + * Gets the value of the vmMac property. + * + * @return + * possible object is + * {@link String } + * + */ + public String getVmMac() { + return vmMac; + } + + /** + * Sets the value of the vmMac property. + * + * @param value + * allowed object is + * {@link String } + * + */ + public void setVmMac(String value) { + this.vmMac = value; + } + + /** + * Gets the value of the signature property. + * + * @return + * possible object is + * {@link String } + * + */ + public String getSignature() { + return signature; + } + + /** + * Sets the value of the signature property. + * + * @param value + * allowed object is + * {@link String } + * + */ + public void setSignature(String value) { + this.signature = value; + } + + /** + * Gets the value of the sequenceNumber property. + * + */ + public long getSequenceNumber() { + return sequenceNumber; + } + + /** + * Sets the value of the sequenceNumber property. + * + */ + public void setSequenceNumber(long value) { + this.sequenceNumber = value; + } + + /** + * Gets the value of the ingressRules property. + * + *

+ * This accessor method returns a reference to the live list, + * not a snapshot. Therefore any modification you make to the + * returned list will be present inside the JAXB object. + * This is why there is not a set method for the ingressRules property. + * + *

+ * For example, to add a new item, do as follows: + *

+     *    getIngressRules().add(newItem);
+     * 
+ * + * + *

+ * Objects of the following type(s) are allowed in the list + * {@link SecurityGroupRule } + * + * + */ + public List getIngressRules() { + if (ingressRules == null) { + ingressRules = new ArrayList(); + } + return this.ingressRules; + } + + /** + * Gets the value of the egressRules property. + * + *

+ * This accessor method returns a reference to the live list, + * not a snapshot. Therefore any modification you make to the + * returned list will be present inside the JAXB object. + * This is why there is not a set method for the egressRules property. + * + *

+ * For example, to add a new item, do as follows: + *

+     *    getEgressRules().add(newItem);
+     * 
+ * + * + *

+ * Objects of the following type(s) are allowed in the list + * {@link SecurityGroupRule } + * + * + */ + public List getEgressRules() { + if (egressRules == null) { + egressRules = new ArrayList(); + } + return this.egressRules; + } + +} diff --git a/plugins/hypervisors/hyperv/DotNet/ServerResource/.nuget/NuGet.Config b/plugins/hypervisors/hyperv/DotNet/ServerResource/.nuget/NuGet.Config index 5181cb8103..3bdbf2e7f0 100644 --- a/plugins/hypervisors/hyperv/DotNet/ServerResource/.nuget/NuGet.Config +++ b/plugins/hypervisors/hyperv/DotNet/ServerResource/.nuget/NuGet.Config @@ -1,13 +1,4 @@ - - + diff --git a/plugins/hypervisors/hyperv/DotNet/ServerResource/AgentShell/AgentSettings.settings b/plugins/hypervisors/hyperv/DotNet/ServerResource/AgentShell/AgentSettings.settings index fb5b962fca..695ebe2ce9 100644 --- a/plugins/hypervisors/hyperv/DotNet/ServerResource/AgentShell/AgentSettings.settings +++ b/plugins/hypervisors/hyperv/DotNet/ServerResource/AgentShell/AgentSettings.settings @@ -1,23 +1,4 @@ - - - + diff --git a/plugins/hypervisors/hyperv/DotNet/ServerResource/AgentShell/AgentShell.csproj b/plugins/hypervisors/hyperv/DotNet/ServerResource/AgentShell/AgentShell.csproj index a4c6b1fc07..f804ef6f67 100644 --- a/plugins/hypervisors/hyperv/DotNet/ServerResource/AgentShell/AgentShell.csproj +++ b/plugins/hypervisors/hyperv/DotNet/ServerResource/AgentShell/AgentShell.csproj @@ -137,6 +137,10 @@ + + + + + + 4.0.0 + cloud-plugin-storage-volume-cloudbyte + Apache CloudStack Plugin - Storage Volume CloudByte Provider + + org.apache.cloudstack + cloudstack-plugins + 4.4.0-SNAPSHOT + ../../../pom.xml + + + + org.apache.cloudstack + cloud-plugin-storage-volume-default + ${project.version} + + + org.apache.cloudstack + cloud-engine-storage-volume + ${project.version} + + + mysql + mysql-connector-java + ${cs.mysql.version} + provided + + + com.google.code.gson + gson + ${cs.gson.version} + + + com.sun.jersey + jersey-bundle + 1.17.1 + + + + install + src + test + + + maven-surefire-plugin + + true + + + + integration-test + + test + + + + + + + diff --git a/plugins/storage/volume/cloudbyte/resources/META-INF/cloudstack/storage-volume-cloudbyte/module.properties b/plugins/storage/volume/cloudbyte/resources/META-INF/cloudstack/storage-volume-cloudbyte/module.properties new file mode 100755 index 0000000000..730e376c92 --- /dev/null +++ b/plugins/storage/volume/cloudbyte/resources/META-INF/cloudstack/storage-volume-cloudbyte/module.properties @@ -0,0 +1,18 @@ +# 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. +name=storage-volume-cloudbyte +parent=storage \ No newline at end of file diff --git a/plugins/storage/volume/cloudbyte/resources/META-INF/cloudstack/storage-volume-cloudbyte/spring-storage-volume-cloudbyte-context.xml b/plugins/storage/volume/cloudbyte/resources/META-INF/cloudstack/storage-volume-cloudbyte/spring-storage-volume-cloudbyte-context.xml new file mode 100755 index 0000000000..87c5f51393 --- /dev/null +++ b/plugins/storage/volume/cloudbyte/resources/META-INF/cloudstack/storage-volume-cloudbyte/spring-storage-volume-cloudbyte-context.xml @@ -0,0 +1,40 @@ + + + + + + + + + + + + + diff --git a/plugins/storage/volume/cloudbyte/src/org/apache/cloudstack/storage/datastore/driver/ElastistorPrimaryDataStoreDriver.java b/plugins/storage/volume/cloudbyte/src/org/apache/cloudstack/storage/datastore/driver/ElastistorPrimaryDataStoreDriver.java new file mode 100755 index 0000000000..99d1e2aaa4 --- /dev/null +++ b/plugins/storage/volume/cloudbyte/src/org/apache/cloudstack/storage/datastore/driver/ElastistorPrimaryDataStoreDriver.java @@ -0,0 +1,97 @@ +/* + * 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.storage.datastore.driver; + + +import javax.inject.Inject; + +import org.apache.cloudstack.engine.subsystem.api.storage.ChapInfo; +import org.apache.cloudstack.engine.subsystem.api.storage.CopyCommandResult; +import org.apache.cloudstack.engine.subsystem.api.storage.CreateCmdResult; +import org.apache.cloudstack.engine.subsystem.api.storage.DataObject; +import org.apache.cloudstack.engine.subsystem.api.storage.DataStore; +import org.apache.cloudstack.engine.subsystem.api.storage.PrimaryDataStoreDriver; +import org.apache.cloudstack.engine.subsystem.api.storage.SnapshotInfo; +import org.apache.cloudstack.engine.subsystem.api.storage.VolumeInfo; +import org.apache.cloudstack.framework.async.AsyncCompletionCallback; +import org.apache.cloudstack.storage.command.CommandResult; +import org.apache.log4j.Logger; + +import com.cloud.agent.api.to.DataStoreTO; +import com.cloud.agent.api.to.DataTO; +import com.cloud.storage.dao.DiskOfferingDao; +import com.cloud.user.AccountManager; + +public class ElastistorPrimaryDataStoreDriver extends CloudStackPrimaryDataStoreDriverImpl implements PrimaryDataStoreDriver{ + + private static final Logger s_logger = Logger.getLogger(ElastistorPrimaryDataStoreDriver.class); + + @Inject + AccountManager _accountMgr; + @Inject + DiskOfferingDao _diskOfferingDao; + @Override + public DataTO getTO(DataObject data) { + return null; + } + + @Override + public DataStoreTO getStoreTO(DataStore store) { + return null; + } + + public void createAsync(DataStore dataStore, DataObject dataObject, AsyncCompletionCallback callback) { + super.createAsync(dataStore, dataObject, callback); + } + + public void deleteAsync(DataStore dataStore, DataObject dataObject, AsyncCompletionCallback callback) { + super.deleteAsync(dataStore, dataObject, callback); + } + + @Override + public void copyAsync(DataObject srcdata, DataObject destData, AsyncCompletionCallback callback) { + throw new UnsupportedOperationException(); + + } + + @Override + public boolean canCopy(DataObject srcData, DataObject destData) { + return false; + } + + @Override + public void resize(DataObject data, AsyncCompletionCallback callback) { + throw new UnsupportedOperationException(); + } + + public ChapInfo getChapInfo(VolumeInfo volumeInfo) { + return super.getChapInfo(volumeInfo); + } + + @Override + public void takeSnapshot(SnapshotInfo snapshot, AsyncCompletionCallback callback) { + throw new UnsupportedOperationException(); + } + + @Override + public void revertSnapshot(SnapshotInfo snapshot, AsyncCompletionCallback callback) { + throw new UnsupportedOperationException(); + } + +} diff --git a/plugins/storage/volume/cloudbyte/src/org/apache/cloudstack/storage/datastore/lifecycle/ElastistorPrimaryDataStoreLifeCycle.java b/plugins/storage/volume/cloudbyte/src/org/apache/cloudstack/storage/datastore/lifecycle/ElastistorPrimaryDataStoreLifeCycle.java new file mode 100755 index 0000000000..aa33b2f1d1 --- /dev/null +++ b/plugins/storage/volume/cloudbyte/src/org/apache/cloudstack/storage/datastore/lifecycle/ElastistorPrimaryDataStoreLifeCycle.java @@ -0,0 +1,497 @@ +/* + * 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.storage.datastore.lifecycle; + +import java.util.ArrayList; +import java.util.List; +import java.util.Map; +import java.util.StringTokenizer; + +import javax.inject.Inject; + +import org.apache.cloudstack.engine.subsystem.api.storage.ClusterScope; +import org.apache.cloudstack.engine.subsystem.api.storage.DataStore; +import org.apache.cloudstack.engine.subsystem.api.storage.HostScope; +import org.apache.cloudstack.engine.subsystem.api.storage.PrimaryDataStoreInfo; +import org.apache.cloudstack.engine.subsystem.api.storage.PrimaryDataStoreLifeCycle; +import org.apache.cloudstack.engine.subsystem.api.storage.PrimaryDataStoreParameters; +import org.apache.cloudstack.engine.subsystem.api.storage.ZoneScope; +import org.apache.cloudstack.storage.datastore.db.PrimaryDataStoreDao; +import org.apache.cloudstack.storage.datastore.db.StoragePoolDetailsDao; +import org.apache.cloudstack.storage.datastore.db.StoragePoolVO; +import org.apache.cloudstack.storage.datastore.util.ElastistorUtil; +import org.apache.cloudstack.storage.datastore.util.ElastistorUtil.CreateTsmCmdResponse; +import org.apache.cloudstack.storage.datastore.util.ElastistorUtil.CreateVolumeCmdResponse; +import org.apache.cloudstack.storage.volume.datastore.PrimaryDataStoreHelper; +import org.apache.log4j.Logger; + +import com.cloud.agent.AgentManager; +import com.cloud.agent.api.Answer; +import com.cloud.agent.api.CreateStoragePoolCommand; +import com.cloud.agent.api.DeleteStoragePoolCommand; +import com.cloud.agent.api.StoragePoolInfo; +import com.cloud.dc.dao.DataCenterDao; +import com.cloud.host.Host; +import com.cloud.host.HostVO; +import com.cloud.host.dao.HostDao; +import com.cloud.hypervisor.Hypervisor.HypervisorType; +import com.cloud.resource.ResourceManager; +import com.cloud.storage.Storage.StoragePoolType; +import com.cloud.storage.StorageManager; +import com.cloud.storage.StoragePool; +import com.cloud.storage.StoragePoolAutomation; +import com.cloud.storage.StoragePoolHostVO; +import com.cloud.storage.dao.StoragePoolHostDao; +import com.cloud.utils.exception.CloudRuntimeException; + +public class ElastistorPrimaryDataStoreLifeCycle implements PrimaryDataStoreLifeCycle { + private static final Logger s_logger = Logger.getLogger(ElastistorPrimaryDataStoreLifeCycle.class); + + @Inject + HostDao _hostDao; + @Inject + StoragePoolHostDao _storagePoolHostDao; + @Inject + protected ResourceManager _resourceMgr; + @Inject + PrimaryDataStoreDao primaryDataStoreDao; + @Inject + AgentManager agentMgr; + @Inject + StorageManager storageMgr; + @Inject + PrimaryDataStoreHelper dataStoreHelper; + @Inject + PrimaryDataStoreDao _storagePoolDao; + @Inject + PrimaryDataStoreHelper _dataStoreHelper; + @Inject + StoragePoolAutomation _storagePoolAutomation; + @Inject + StoragePoolDetailsDao _storagePoolDetailsDao; + @Inject + DataCenterDao _zoneDao; + + @Override + public DataStore initialize(Map dsInfos) { + + String url = (String) dsInfos.get("url"); + Long zoneId = (Long) dsInfos.get("zoneId"); + Long podId = (Long) dsInfos.get("podId"); + Long clusterId = (Long) dsInfos.get("clusterId"); + String storagePoolName = (String) dsInfos.get("name"); + String providerName = (String) dsInfos.get("providerName"); + Long capacityBytes = (Long) dsInfos.get("capacityBytes"); + Long capacityIops = (Long) dsInfos.get("capacityIops"); + String tags = (String) dsInfos.get("tags"); + Map details = (Map) dsInfos.get("details"); + String storageIp = getStorageIp(url); + int storagePort = getDefaultStoragePort(url); + StoragePoolType storagetype = getStorageType(url); + String accesspath = getAccessPath(url); + String protocoltype = getProtocolType(url); + String[] mp = accesspath.split("/"); + String mountpoint = mp[1]; + String uuid = null ; + + /** + * if the elastistor params which are required for plugin configuration + * are not injected through spring-storage-volume-cloudbyte-context.xml, it can be set from details map. + */ + if(details.get("esaccountid") != null) + ElastistorUtil.setElastistorAccountId(details.get("esaccountid")); + if(details.get("esapikey") != null) + ElastistorUtil.setElastistorApiKey(details.get("esapikey")); + if(details.get("esdefaultgateway") != null) + ElastistorUtil.setElastistorGateway(details.get("esdefaultgateway")); + if(details.get("estntinterface") != null) + ElastistorUtil.setElastistorInterface(details.get("estntinterface")); + if(details.get("esmanagementip") != null) + ElastistorUtil.setElastistorManagementIp(details.get("esmanagementip")); + if(details.get("espoolid") != null) + ElastistorUtil.setElastistorPoolId(details.get("espoolid")); + if(details.get("essubnet") != null) + ElastistorUtil.setElastistorSubnet(details.get("essubnet")); + + if (capacityBytes == null || capacityBytes <= 0) { + throw new IllegalArgumentException("'capacityBytes' must be present and greater than 0."); + } + + if (capacityIops == null || capacityIops <= 0) { + throw new IllegalArgumentException("'capacityIops' must be present and greater than 0."); + } + + // elastistor does not allow same name and ip pools. + List storagePoolVO = _storagePoolDao.listAll(); + for(StoragePoolVO poolVO : storagePoolVO){ + if (storagePoolName.equals(poolVO.getName())) { + throw new IllegalArgumentException("storage pool with that name already exists in elastistor,please specify a unique name ."); + } + if (storageIp.equals(poolVO.getHostAddress())) { + throw new IllegalArgumentException("storage pool with that ip already exists in elastistor,please specify a unique ip ."); + } + } + + PrimaryDataStoreParameters parameters = new PrimaryDataStoreParameters(); + + // creates the volume in elastistor + parameters = createElastistorVolume(parameters, storagePoolName, storageIp, capacityBytes, capacityIops, protocoltype, mountpoint); + + parameters.setHost(storageIp); + parameters.setPort(storagePort); + if(protocoltype.contentEquals("nfs")){ + parameters.setPath(accesspath); + } + parameters.setType(storagetype); + parameters.setZoneId(zoneId); + parameters.setPodId(podId); + parameters.setName(storagePoolName); + parameters.setProviderName(providerName); + parameters.setManaged(false); + parameters.setCapacityBytes(capacityBytes); + parameters.setUsedBytes(0); + parameters.setCapacityIops(capacityIops); + parameters.setHypervisorType(HypervisorType.Any); + parameters.setTags(tags); + parameters.setDetails(details); + parameters.setClusterId(clusterId); + + return _dataStoreHelper.createPrimaryDataStore(parameters); + } + + private PrimaryDataStoreParameters createElastistorVolume(PrimaryDataStoreParameters parameters, String storagePoolName, String storageIp, Long capacityBytes, Long capacityIops, String protocoltype, String mountpoint){ + + s_logger.info("creation of elastistor volume started"); + try { + + CreateTsmCmdResponse tsmCmdResponse = ElastistorUtil.createElastistorTsm(storagePoolName, storageIp, capacityBytes, capacityIops); + + String uuid = tsmCmdResponse.getTsm().getUuid(); + parameters.setUuid(uuid); + + CreateVolumeCmdResponse volumeCmdResponse = ElastistorUtil.createElastistorVolume(storagePoolName, tsmCmdResponse, capacityBytes, capacityIops, protocoltype ,mountpoint); + + if(protocoltype.contentEquals("iscsi")){ + String accesspath = "/"+volumeCmdResponse.getFileSystem().getIqn()+"/0"; + parameters.setPath(accesspath); + } + s_logger.info("creation of elastistor volume complete"); + + return parameters; + } catch (Throwable e) { + throw new CloudRuntimeException("Failed to create volume in elastistor" + e.toString()); + } + + } + + private String getAccessPath(String url) { + StringTokenizer st = new StringTokenizer(url ,"/"); + int count = 0; + while (st.hasMoreElements()) { + if(count == 2) + { String s = "/" ; + return s.concat(st.nextElement().toString()); + } + st.nextElement(); + count++; + } + return null; + } + + + private StoragePoolType getStorageType(String url) { + + StringTokenizer st = new StringTokenizer(url ,":"); + + while (st.hasMoreElements()) + { + String accessprotocol = st.nextElement().toString(); + + if(accessprotocol.contentEquals("nfs")) + { + return StoragePoolType.NetworkFilesystem; + } + else if(accessprotocol.contentEquals("iscsi")) + { + return StoragePoolType.IscsiLUN; + } + + else + + break; + + } + return null; + } + + private String getProtocolType(String url) { + StringTokenizer st = new StringTokenizer(url ,":"); + + while (st.hasMoreElements()) + { + String accessprotocol = st.nextElement().toString(); + + if(accessprotocol.contentEquals("nfs")){ + return "nfs"; + }else if(accessprotocol.contentEquals("iscsi")){ + return "iscsi"; + } else + break; + } + return null; + } + + // this method parses the url and gets the default storage port based on access protocol + private int getDefaultStoragePort(String url) { + + StringTokenizer st = new StringTokenizer(url ,":"); + + while (st.hasMoreElements()) + { + + String accessprotocol = st.nextElement().toString(); + + if(accessprotocol.contentEquals("nfs")){ + return 2049; + } + else if(accessprotocol.contentEquals("iscsi")){ + return 3260; + } + else + break; + + } + return -1; + + } + + // parses the url and returns the storage volume ip + private String getStorageIp(String url) { + + StringTokenizer st = new StringTokenizer(url ,"/"); + int count = 0; + + while (st.hasMoreElements()) { + if(count == 1) + return st.nextElement().toString(); + + st.nextElement(); + count++; + } + return null; + } + + @Override + public boolean attachCluster(DataStore store, ClusterScope scope) { + + dataStoreHelper.attachCluster(store); + + PrimaryDataStoreInfo primarystore = (PrimaryDataStoreInfo) store; + // Check if there is host up in this cluster + List allHosts = _resourceMgr.listAllUpAndEnabledHosts(Host.Type.Routing, primarystore.getClusterId(), + primarystore.getPodId(), primarystore.getDataCenterId()); + if (allHosts.isEmpty()) { + primaryDataStoreDao.expunge(primarystore.getId()); + throw new CloudRuntimeException("No host up to associate a storage pool with in cluster " + + primarystore.getClusterId()); + } + + + boolean success = false; + for (HostVO h : allHosts) { + success = createStoragePool(h.getId(), primarystore); + if (success) { + break; + } + } + + s_logger.debug("In createPool Adding the pool to each of the hosts"); + List poolHosts = new ArrayList(); + for (HostVO h : allHosts) { + try { + storageMgr.connectHostToSharedPool(h.getId(), primarystore.getId()); + poolHosts.add(h); + } catch (Exception e) { + s_logger.warn("Unable to establish a connection between " + h + " and " + primarystore, e); + } + + if (poolHosts.isEmpty()) { + s_logger.warn("No host can access storage pool " + primarystore + " on cluster " + + primarystore.getClusterId()); + primaryDataStoreDao.expunge(primarystore.getId()); + throw new CloudRuntimeException("Failed to access storage pool"); + } + } + + return true; + } + + private boolean createStoragePool(long hostId, StoragePool pool) { + s_logger.debug("creating pool " + pool.getName() + " on host " + hostId); + if (pool.getPoolType() != StoragePoolType.NetworkFilesystem && pool.getPoolType() != StoragePoolType.Filesystem + && pool.getPoolType() != StoragePoolType.IscsiLUN && pool.getPoolType() != StoragePoolType.Iscsi + && pool.getPoolType() != StoragePoolType.VMFS && pool.getPoolType() != StoragePoolType.SharedMountPoint + && pool.getPoolType() != StoragePoolType.PreSetup && pool.getPoolType() != StoragePoolType.OCFS2 + && pool.getPoolType() != StoragePoolType.RBD && pool.getPoolType() != StoragePoolType.CLVM) { + s_logger.warn(" Doesn't support storage pool type " + pool.getPoolType()); + return false; + } + CreateStoragePoolCommand cmd = new CreateStoragePoolCommand(true, pool); + final Answer answer = agentMgr.easySend(hostId, cmd); + if (answer != null && answer.getResult()) { + return true; + } else { + primaryDataStoreDao.expunge(pool.getId()); + String msg = ""; + if (answer != null) { + msg = "Can not create storage pool through host " + hostId + " due to " + answer.getDetails(); + s_logger.warn(msg); + } else { + msg = "Can not create storage pool through host " + hostId + " due to CreateStoragePoolCommand returns null"; + s_logger.warn(msg); + } + throw new CloudRuntimeException(msg); + } + } + + + @Override + public boolean attachHost(DataStore store, HostScope scope, StoragePoolInfo existingInfo) { + _dataStoreHelper.attachHost(store, scope, existingInfo); + return true; + } + + @Override + public boolean attachZone(DataStore dataStore, ZoneScope scope, HypervisorType hypervisorType) { + List hosts = _resourceMgr.listAllUpAndEnabledHostsInOneZoneByHypervisor(hypervisorType, scope.getScopeId()); + s_logger.debug("In createPool. Attaching the pool to each of the hosts."); + List poolHosts = new ArrayList(); + for (HostVO host : hosts) { + try { + storageMgr.connectHostToSharedPool(host.getId(), dataStore.getId()); + poolHosts.add(host); + } catch (Exception e) { + s_logger.warn("Unable to establish a connection between " + host + " and " + dataStore, e); + } + } + if (poolHosts.isEmpty()) { + s_logger.warn("No host can access storage pool " + dataStore + " in this zone."); + primaryDataStoreDao.expunge(dataStore.getId()); + throw new CloudRuntimeException("Failed to create storage pool as it is not accessible to hosts."); + } + dataStoreHelper.attachZone(dataStore, hypervisorType); + return true; + } + + @Override + public boolean maintain(DataStore store) { + _storagePoolAutomation.maintain(store); + _dataStoreHelper.maintain(store); + return true; + } + + @Override + public boolean cancelMaintain(DataStore store) { + _dataStoreHelper.cancelMaintain(store); + _storagePoolAutomation.cancelMaintain(store); + return true; + } + + @SuppressWarnings("finally") + @Override + public boolean deleteDataStore(DataStore store) { + List hostPoolRecords = _storagePoolHostDao.listByPoolId(store.getId()); + StoragePool pool = (StoragePool) store; + + // find the hypervisor where the storage is attached to. + HypervisorType hType = null; + if(hostPoolRecords.size() > 0 ){ + hType = getHypervisorType(hostPoolRecords.get(0).getHostId()); + } + + // Remove the SR associated with the Xenserver + for (StoragePoolHostVO host : hostPoolRecords) { + DeleteStoragePoolCommand deleteCmd = new DeleteStoragePoolCommand(pool); + final Answer answer = agentMgr.easySend(host.getHostId(), deleteCmd); + + if (answer != null && answer.getResult()) { + // if host is KVM hypervisor then send deleteStoragepoolcmd to all the kvm hosts. + if (HypervisorType.KVM != hType) { + break; + } + } else { + if (answer != null) { + s_logger.error("Failed to delete storage pool: " + answer.getResult()); + } + } + } + + //delete the Elastistor volume at backend + deleteElastistorVolume(pool); + + return _dataStoreHelper.deletePrimaryDataStore(store); + } + + private void deleteElastistorVolume(StoragePool pool){ + + String poolip = pool.getHostAddress(); + String esip = null; + String apikey = null; + + // check if apikey and managentip is empty, if so getting it from stragepooldetails + if(ElastistorUtil.s_esIPVAL == "" && ElastistorUtil.s_esAPIKEYVAL == ""){ + Map detailsMap = _storagePoolDetailsDao.listDetailsKeyPairs(pool.getId()); + ElastistorUtil.setElastistorManagementIp(detailsMap.get("esmanagementip")); + esip=ElastistorUtil.s_esIPVAL; + ElastistorUtil.setElastistorApiKey(detailsMap.get("esapikey")); + apikey = ElastistorUtil.s_esAPIKEYVAL; + }else{ + esip = ElastistorUtil.s_esIPVAL; + apikey = ElastistorUtil.s_esAPIKEYVAL; + } + + boolean status; + try { + status = ElastistorUtil.deleteElastistorVolume(poolip,esip,apikey); + } catch (Throwable e) { + throw new CloudRuntimeException("Failed to delete primary storage on elastistor" + e); + } + + if(status == true){ + s_logger.info("deletion of elastistor primary storage complete"); + }else{ + s_logger.error("deletion of elastistor volume failed"); + } + + } + + private HypervisorType getHypervisorType(long hostId) { + HostVO host = _hostDao.findById(hostId); + if (host != null) + return host.getHypervisorType(); + return HypervisorType.None; + } + + @Override + public boolean migrateToObjectStore(DataStore store) { + return false; + } + + +} diff --git a/plugins/storage/volume/cloudbyte/src/org/apache/cloudstack/storage/datastore/provider/ElastistorHostListener.java b/plugins/storage/volume/cloudbyte/src/org/apache/cloudstack/storage/datastore/provider/ElastistorHostListener.java new file mode 100755 index 0000000000..de4711a140 --- /dev/null +++ b/plugins/storage/volume/cloudbyte/src/org/apache/cloudstack/storage/datastore/provider/ElastistorHostListener.java @@ -0,0 +1,87 @@ +/* + * 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.storage.datastore.provider; + +import javax.inject.Inject; + +import org.apache.cloudstack.engine.subsystem.api.storage.DataStoreManager; +import org.apache.cloudstack.engine.subsystem.api.storage.HypervisorHostListener; +import org.apache.cloudstack.storage.datastore.db.PrimaryDataStoreDao; +import org.apache.log4j.Logger; + +import com.cloud.agent.AgentManager; +import com.cloud.agent.api.Answer; +import com.cloud.agent.api.ModifyStoragePoolAnswer; +import com.cloud.agent.api.ModifyStoragePoolCommand; +import com.cloud.alert.AlertManager; +import com.cloud.storage.DataStoreRole; +import com.cloud.storage.StoragePool; +import com.cloud.storage.StoragePoolHostVO; +import com.cloud.storage.dao.StoragePoolHostDao; +import com.cloud.utils.exception.CloudRuntimeException; + +public class ElastistorHostListener implements HypervisorHostListener { + private static final Logger s_logger = Logger.getLogger(DefaultHostListener.class); + @Inject + AgentManager agentMgr; + @Inject + DataStoreManager dataStoreMgr; + @Inject + AlertManager alertMgr; + @Inject + StoragePoolHostDao storagePoolHostDao; + @Inject + PrimaryDataStoreDao primaryStoreDao; + + @Override + public boolean hostConnect(long hostId, long poolId) { + StoragePool pool = (StoragePool) this.dataStoreMgr.getDataStore(poolId, DataStoreRole.Primary); + ModifyStoragePoolCommand cmd = new ModifyStoragePoolCommand(true, pool); + final Answer answer = agentMgr.easySend(hostId, cmd); + + if (answer == null) { + throw new CloudRuntimeException("Unable to get an answer to the modify storage pool command" + pool.getId()); + } + + if (!answer.getResult()) { + String msg = "Unable to attach storage pool" + poolId + " to the host" + hostId; + + alertMgr.sendAlert(AlertManager.AlertType.ALERT_TYPE_HOST,pool.getDataCenterId(), pool.getPodId(), msg, msg); + + throw new CloudRuntimeException("Unable establish connection from storage head to storage pool " + pool.getId() + " due to " + answer.getDetails() + pool.getId()); + } + + assert (answer instanceof ModifyStoragePoolAnswer) : "Well, now why won't you actually return the ModifyStoragePoolAnswer when it's ModifyStoragePoolCommand? Pool=" + pool.getId() + "Host=" + hostId; + + s_logger.info("Connection established between " + pool + " host + " + hostId); + return true; + } + + @Override + public boolean hostDisconnected(long hostId, long poolId) { + StoragePoolHostVO storagePoolHost = storagePoolHostDao.findByPoolHost( + poolId, hostId); + + if (storagePoolHost != null) { + storagePoolHostDao.deleteStoragePoolHostDetails(hostId, poolId); + } + return false; + } + +} diff --git a/plugins/storage/volume/cloudbyte/src/org/apache/cloudstack/storage/datastore/provider/ElastistorPrimaryDataStoreProvider.java b/plugins/storage/volume/cloudbyte/src/org/apache/cloudstack/storage/datastore/provider/ElastistorPrimaryDataStoreProvider.java new file mode 100755 index 0000000000..e59108299a --- /dev/null +++ b/plugins/storage/volume/cloudbyte/src/org/apache/cloudstack/storage/datastore/provider/ElastistorPrimaryDataStoreProvider.java @@ -0,0 +1,175 @@ +/* + * 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.storage.datastore.provider; + +import java.util.HashSet; +import java.util.Map; +import java.util.Set; + +import javax.inject.Inject; + +import org.apache.cloudstack.engine.subsystem.api.storage.DataStoreLifeCycle; +import org.apache.cloudstack.engine.subsystem.api.storage.DataStoreManager; +import org.apache.cloudstack.engine.subsystem.api.storage.HypervisorHostListener; +import org.apache.cloudstack.engine.subsystem.api.storage.PrimaryDataStoreDriver; +import org.apache.cloudstack.engine.subsystem.api.storage.PrimaryDataStoreProvider; +import org.apache.cloudstack.storage.datastore.db.PrimaryDataStoreDao; +import org.apache.cloudstack.storage.datastore.driver.ElastistorPrimaryDataStoreDriver; +import org.apache.cloudstack.storage.datastore.lifecycle.ElastistorPrimaryDataStoreLifeCycle; +import org.apache.cloudstack.storage.datastore.util.ElastistorUtil; +import org.apache.log4j.Logger; +import org.springframework.stereotype.Component; + +import com.cloud.agent.AgentManager; +import com.cloud.alert.AlertManager; +import com.cloud.storage.dao.StoragePoolHostDao; +import com.cloud.utils.component.ComponentContext; + +@Component +public class ElastistorPrimaryDataStoreProvider implements PrimaryDataStoreProvider { + + private static final Logger s_logger = Logger.getLogger(DefaultHostListener.class); + + //these classes will be injected by spring + private ElastistorPrimaryDataStoreLifeCycle lifecycle; + private PrimaryDataStoreDriver driver; + private HypervisorHostListener listener; + + // these params will be initialized with respective values given in spring-storage-volume-cloudbyte-context.xml bean for the elastistor porpose only. + private String esmanagementip; + private String esapikey; + private String esaccountid; + private String espoolid; + private String esdefaultgateway; + private String essubnet; + private String estntinterface; + + @Inject + AgentManager agentMgr; + @Inject + DataStoreManager dataStoreMgr; + @Inject + AlertManager alertMgr; + @Inject + StoragePoolHostDao storagePoolHostDao; + @Inject + PrimaryDataStoreDao primaryStoreDao; + + + @Override + public String getName() { + return ElastistorUtil.ES_PROVIDER_NAME; + } + + @Override + public DataStoreLifeCycle getDataStoreLifeCycle() { + return lifecycle; + } + + @Override + public PrimaryDataStoreDriver getDataStoreDriver() { + return driver; + } + + @Override + public HypervisorHostListener getHostListener() { + return listener; + } + + @Override + public boolean configure(Map params) { + + lifecycle = ComponentContext.inject(ElastistorPrimaryDataStoreLifeCycle.class); + driver = ComponentContext.inject(ElastistorPrimaryDataStoreDriver.class); + listener = ComponentContext.inject(ElastistorHostListener.class); + + ElastistorUtil.setElastistorAccountId(esaccountid); + ElastistorUtil.setElastistorApiKey(esapikey); + ElastistorUtil.setElastistorManagementIp(esmanagementip); + ElastistorUtil.setElastistorPoolId(espoolid); + ElastistorUtil.setElastistorGateway(esdefaultgateway); + ElastistorUtil.setElastistorInterface(estntinterface); + ElastistorUtil.setElastistorSubnet(essubnet); + + return true; + } + + @Override + public Set getTypes() { + Set types = new HashSet(); + + types.add(DataStoreProviderType.PRIMARY); + + return types; + } + public String getEspoolid() { + return espoolid; + } + + public void setEspoolid(String espoolid) { + this.espoolid = espoolid; + } + + public String getEsmanagementip() { + return esmanagementip; + } + + public void setEsmanagementip(String esmanagementip) { + this.esmanagementip = esmanagementip; + } + + public String getEsaccountid() { + return esaccountid; + } + + public void setEsaccountid(String esaccountid) { + this.esaccountid = esaccountid; + } + + public String getEsapikey() { + return esapikey; + } + + public void setEsapikey(String esapikey) { + this.esapikey = esapikey; + } + + public String getesdefaultgateway() { + return esdefaultgateway; + } + + public void setesdefaultgateway(String esdefaultgateway) { + this.esdefaultgateway = esdefaultgateway; + } + public String getEssubnet() { + return essubnet; + } + + public void setEssubnet(String essubnet) { + this.essubnet = essubnet; + } + + public String getEstntinterface(){ + return estntinterface; + } + + public void setEstntinterface(String estntinterface){ + this.estntinterface = estntinterface; + } +} diff --git a/plugins/storage/volume/cloudbyte/src/org/apache/cloudstack/storage/datastore/util/ElastistorUtil.java b/plugins/storage/volume/cloudbyte/src/org/apache/cloudstack/storage/datastore/util/ElastistorUtil.java new file mode 100755 index 0000000000..b75d12a6a4 --- /dev/null +++ b/plugins/storage/volume/cloudbyte/src/org/apache/cloudstack/storage/datastore/util/ElastistorUtil.java @@ -0,0 +1,1156 @@ +/* + * 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.storage.datastore.util; + +import java.net.ConnectException; +import java.security.InvalidParameterException; +import java.security.SecureRandom; +import java.security.cert.X509Certificate; +import java.util.HashMap; + +import javax.naming.ServiceUnavailableException; +import javax.net.ssl.HostnameVerifier; +import javax.net.ssl.HttpsURLConnection; +import javax.net.ssl.SSLContext; +import javax.net.ssl.SSLHandshakeException; +import javax.net.ssl.SSLSession; +import javax.net.ssl.TrustManager; +import javax.net.ssl.X509TrustManager; +import javax.ws.rs.core.MediaType; +import javax.ws.rs.core.MultivaluedMap; +import javax.ws.rs.core.UriBuilder; + +import org.apache.http.auth.InvalidCredentialsException; +import org.apache.log4j.Logger; + +import com.cloud.utils.exception.CloudRuntimeException; +import com.google.gson.Gson; +import com.google.gson.annotations.SerializedName; +import com.sun.jersey.api.client.Client; +import com.sun.jersey.api.client.ClientResponse; +import com.sun.jersey.api.client.WebResource; +import com.sun.jersey.api.client.config.ClientConfig; +import com.sun.jersey.api.client.config.DefaultClientConfig; +import com.sun.jersey.core.util.MultivaluedMapImpl; + +public class ElastistorUtil { + + private static final Logger s_logger = Logger.getLogger(ElastistorUtil.class); + + + /** + * Elastistor REST API Param Keys. These should match exactly with the + * elastistor API commands' params. + */ + public static final String REST_PARAM_COMMAND = "command"; + public static final String REST_PARAM_APIKEY = "apikey"; + public static final String REST_PARAM_KEYWORD = "keyword"; + public static final String REST_PARAM_ID = "id"; + public static final String REST_PARAM_QUOTA_SIZE = "quotasize"; + public static final String REST_PARAM_READONLY = "readonly"; + public static final String REST_PARAM_RESPONSE = "response"; + public static final String REST_PARAM_POOLID = "poolid"; + public static final String REST_PARAM_ACCOUNTID = "accountid"; + public static final String REST_PARAM_GATEWAY = "router"; + public static final String REST_PARAM_SUBNET = "subnet"; + public static final String REST_PARAM_INTERFACE = "tntinterface"; + public static final String REST_PARAM_IPADDRESS = "ipaddress"; + public static final String REST_PARAM_JOBID = "jobId"; + public static final String REST_PARAM_FORECEDELETE = "forcedelete"; + public static final String REST_PARAM_TSM_THROUGHPUT = "totalthroughput"; + public static final String REST_PARAM_NAME = "name"; + public static final String REST_PARAM_NOOFCOPIES = "noofcopies"; + public static final String REST_PARAM_RECORDSIZE = "recordsize"; + public static final String REST_PARAM_TOTALIOPS = "totaliops"; + public static final String REST_PARAM_LATENCY = "latency"; + public static final String REST_PARAM_BLOCKSIZE = "blocksize"; + public static final String REST_PARAM_GRACEALLOWED = "graceallowed"; + public static final String REST_PARAM_IOPS = "iops"; + public static final String REST_PARAM_THROUGHPUT = "throughput"; + public static final String REST_PARAM_MEMLIMIT= "memlimit"; + public static final String REST_PARAM_NETWORKSPEED = "networkspeed"; + public static final String REST_PARAM_TSMID = "tsmid"; + public static final String REST_PARAM_DATASETID = "datasetid"; + public static final String REST_PARAM_QOSGROUPID = "qosgroupid"; + public static final String REST_PARAM_DEDUPLICATION = "deduplication"; + public static final String REST_PARAM_COMPRESSION = "compression"; + public static final String REST_PARAM_SYNC = "sync"; + public static final String REST_PARAM_MOUNTPOINT= "mountpoint"; + public static final String REST_PARAM_CASESENSITIVITY = "casesensitivity"; + public static final String REST_PARAM_UNICODE = "unicode"; + public static final String REST_PARAM_PROTOCOLTYPE= "protocoltype"; + public static final String REST_PARAM_AUTHNETWORK = "authnetwork"; + public static final String REST_PARAM_MAPUSERSTOROOT = "mapuserstoroot"; + + /** + * Constants related to elastistor which are persisted in cloudstack + * databases as keys. + */ + public static final String ES_SUBNET = "essubnet"; + public static final String ES_INTERFACE = "estntinterface"; + public static final String ES_GATEWAY = "esdefaultgateway"; + public static final String ES_PROVIDER_NAME = "elastistor"; + public static final String ES_ACCOUNT_ID = "esAccountId"; + public static final String ES_POOL_ID = "esPoolId"; + public static final String ES_ACCOUNT_NAME = "esAccountName"; + public static final String ES_STORAGE_IP = "esStorageIp"; + public static final String ES_STORAGE_PORT = "esStoragePort"; + public static final String ES_STORAGE_TYPE = "esStorageType"; + public static final String ES_MANAGEMENT_IP = "esMgmtIp"; + public static final String ES_MANAGEMENT_PORT = "esMgmtPort"; + public static final String ES_API_KEY = "esApiKey"; + public static final String ES_VOLUME_ID = "esVolumeId"; + public static final String ES_VOLUME_GROUP_ID = "esVolumeGroupId"; + public static final String ES_FILE_SYSTEM_ID = "esFilesystemId"; + + /** + * Values from configuration that are required for every invocation of + * ElastiCenter API. These might in turn be saved as DB updates along with + * above keys. + */ + public static String s_esIPVAL = ""; + public static String s_esAPIKEYVAL = ""; + public static String s_esACCOUNTIDVAL = ""; + public static String s_esPOOLIDVAL = ""; + public static String s_esSUBNETVAL = ""; + public static String s_esINTERFACEVAL = ""; + public static String s_esGATEWAYVAL = ""; + + /** + * hardcoded constants for elastistor api calls. + */ + private static final String ES_NOOFCOPIES_VAL = "1"; + private static final String ES_BLOCKSIZE_VAL = "4K"; + private static final String ES_LATENCY_VAL = "15"; + private static final String ES_GRACEALLOWED_VAL = "false"; + private static final String ES_MEMLIMIT_VAL = "0"; + private static final String ES_NETWORKSPEED_VAL = "0"; + private static final String ES_DEDUPLICATION_VAL = "off"; + private static final String ES_COMPRESSION_VAL = "off"; + private static final String ES_CASESENSITIVITY_VAL = "sensitive"; + private static final String ES_READONLY_VAL = "off"; + private static final String ES_UNICODE_VAL = "off"; + private static final String ES_AUTHNETWORK_VAL = "all"; + private static final String ES_MAPUSERSTOROOT_VAL = "yes"; + private static final String ES_SYNC_VAL = "always"; + + + /** + * Private constructor s.t. its never instantiated. + */ + private ElastistorUtil() { + + } + + /** + * This intializes a new jersey restclient for http call with elasticenter + */ + public static ElastiCenterClient getElastistorRestClient(String managementIp , String apiKey) { + ElastiCenterClient restclient = null; + try { + + restclient = new ElastiCenterClient(managementIp, apiKey); + + } catch (InvalidCredentialsException e) { + throw new CloudRuntimeException("InvalidCredentialsException", e); + } catch (InvalidParameterException e) { + throw new CloudRuntimeException("InvalidParameterException", e); + } catch (SSLHandshakeException e) { + throw new CloudRuntimeException("SSLHandshakeException", e); + } catch (ServiceUnavailableException e) { + throw new CloudRuntimeException("ServiceUnavailableException", e); + } + return restclient; + } + + public static void setElastistorApiKey(String value) { + s_esAPIKEYVAL = value; + } + + public static void setElastistorManagementIp(String value) { + s_esIPVAL = value; + } + + public static void setElastistorPoolId(String value) { + s_esPOOLIDVAL = value; + } + + public static void setElastistorAccountId(String value) { + s_esACCOUNTIDVAL = value; + } + + public static void setElastistorGateway(String value) { + s_esGATEWAYVAL = value; + } + + public static void setElastistorInterface(String value) { + s_esINTERFACEVAL = value; + } + + public static void setElastistorSubnet(String value) { + s_esSUBNETVAL = value; + } + + /** + * This creates a new tenant storage machine(TSM) for the given storagepool ip in elastistor. + */ + public static CreateTsmCmdResponse createElastistorTsm(String storagePoolName, String storageIp, Long capacityBytes, Long capacityIops) throws Throwable { + + String totalthroughput = String.valueOf(capacityIops*4); + String totaliops = String.valueOf(capacityIops); + + String quotasize = convertCapacityBytes(capacityBytes); + + CreateTsmCmd createTsmCmd = new CreateTsmCmd(); + + if ( null != ElastistorUtil.s_esACCOUNTIDVAL ) createTsmCmd.putCommandParameter(ElastistorUtil.REST_PARAM_ACCOUNTID, ElastistorUtil.s_esACCOUNTIDVAL); + if ( null != totalthroughput ) createTsmCmd.putCommandParameter(ElastistorUtil.REST_PARAM_TSM_THROUGHPUT, totalthroughput); + if ( null != ElastistorUtil.s_esPOOLIDVAL ) createTsmCmd.putCommandParameter(ElastistorUtil.REST_PARAM_POOLID, ElastistorUtil.s_esPOOLIDVAL); + if ( null != storagePoolName ) createTsmCmd.putCommandParameter(ElastistorUtil.REST_PARAM_NAME, "TSM"+storagePoolName); + if ( null != quotasize ) createTsmCmd.putCommandParameter(ElastistorUtil.REST_PARAM_QUOTA_SIZE, quotasize); + if ( null != storageIp ) createTsmCmd.putCommandParameter(ElastistorUtil.REST_PARAM_IPADDRESS, storageIp); + if ( null != ElastistorUtil.s_esSUBNETVAL ) createTsmCmd.putCommandParameter(ElastistorUtil.REST_PARAM_SUBNET, ElastistorUtil.s_esSUBNETVAL); + if ( null != ElastistorUtil.s_esGATEWAYVAL ) createTsmCmd.putCommandParameter(ElastistorUtil.REST_PARAM_GATEWAY, ElastistorUtil.s_esGATEWAYVAL); + if ( null != ElastistorUtil.s_esINTERFACEVAL ) createTsmCmd.putCommandParameter(ElastistorUtil.REST_PARAM_INTERFACE, ElastistorUtil.s_esINTERFACEVAL); + if ( null != ElastistorUtil.ES_NOOFCOPIES_VAL ) createTsmCmd.putCommandParameter(ElastistorUtil.REST_PARAM_NOOFCOPIES, ElastistorUtil.ES_NOOFCOPIES_VAL); + if ( null != ElastistorUtil.ES_BLOCKSIZE_VAL ) createTsmCmd.putCommandParameter(ElastistorUtil.REST_PARAM_RECORDSIZE, ElastistorUtil.ES_BLOCKSIZE_VAL); + if ( null != totaliops ) createTsmCmd.putCommandParameter(ElastistorUtil.REST_PARAM_TOTALIOPS, totaliops); + if ( null != ElastistorUtil.ES_LATENCY_VAL ) createTsmCmd.putCommandParameter(ElastistorUtil.REST_PARAM_LATENCY, ElastistorUtil.ES_LATENCY_VAL); + if ( null != ElastistorUtil.ES_BLOCKSIZE_VAL ) createTsmCmd.putCommandParameter(ElastistorUtil.REST_PARAM_BLOCKSIZE, ElastistorUtil.ES_BLOCKSIZE_VAL); + if ( null != ElastistorUtil.ES_GRACEALLOWED_VAL ) createTsmCmd.putCommandParameter(ElastistorUtil.REST_PARAM_GRACEALLOWED, ElastistorUtil.ES_GRACEALLOWED_VAL); + + CreateTsmCmdResponse cmdResponse; + + try { + cmdResponse = (CreateTsmCmdResponse) getElastistorRestClient(s_esIPVAL, s_esAPIKEYVAL).executeCommand(createTsmCmd); + + if ( cmdResponse.getTsm().getUuid() == null ){ + throw new CloudRuntimeException("tsm creation failed , contact elatistor admin"); + } + return cmdResponse; + } catch (Exception e) { + throw new CloudRuntimeException("tsm creation failed , contact elatistor admin" + e.toString()); + } + + } + + /** + * This creates the specified volume on the created tsm. + */ + public static CreateVolumeCmdResponse createElastistorVolume(String storagePoolName, CreateTsmCmdResponse cmdResponse, Long capacityBytes, Long capacityIops,String protocoltype, String mountpoint) throws Throwable { + + String datasetid; + String tsmid; + String qosgroupid; + String VolumeName = storagePoolName; + String totaliops = String.valueOf(capacityIops); + String totalthroughput = String.valueOf(capacityIops*4); + + String quotasize = convertCapacityBytes(capacityBytes); + + AddQosGroupCmd addQosGroupCmd = new AddQosGroupCmd(); + + + tsmid = cmdResponse.getTsm().getUuid(); + datasetid = cmdResponse.getTsm().getDatasetid(); + + if (null != VolumeName)addQosGroupCmd.putCommandParameter(ElastistorUtil.REST_PARAM_NAME, "QOS_" + VolumeName); + if (null != totaliops)addQosGroupCmd.putCommandParameter(ElastistorUtil.REST_PARAM_IOPS, totaliops); + if (null != ElastistorUtil.ES_LATENCY_VAL)addQosGroupCmd.putCommandParameter(ElastistorUtil.REST_PARAM_LATENCY, ElastistorUtil.ES_LATENCY_VAL); + if (null != ElastistorUtil.ES_BLOCKSIZE_VAL)addQosGroupCmd.putCommandParameter(ElastistorUtil.REST_PARAM_BLOCKSIZE, ElastistorUtil.ES_BLOCKSIZE_VAL); + if (null != totalthroughput)addQosGroupCmd.putCommandParameter(ElastistorUtil.REST_PARAM_THROUGHPUT, totalthroughput); + if (null != ElastistorUtil.ES_MEMLIMIT_VAL)addQosGroupCmd.putCommandParameter(ElastistorUtil.REST_PARAM_MEMLIMIT, ElastistorUtil.ES_MEMLIMIT_VAL); + if (null != ElastistorUtil.ES_NETWORKSPEED_VAL)addQosGroupCmd.putCommandParameter(ElastistorUtil.REST_PARAM_NETWORKSPEED, ElastistorUtil.ES_NETWORKSPEED_VAL); + if (null != tsmid)addQosGroupCmd.putCommandParameter(ElastistorUtil.REST_PARAM_TSMID, tsmid); + if (null != datasetid)addQosGroupCmd.putCommandParameter(ElastistorUtil.REST_PARAM_DATASETID, datasetid); + if (null != ElastistorUtil.ES_GRACEALLOWED_VAL)addQosGroupCmd.putCommandParameter(ElastistorUtil.REST_PARAM_GRACEALLOWED, ElastistorUtil.ES_GRACEALLOWED_VAL); + + AddQosGroupCmdResponse addQosGroupCmdResponse = (AddQosGroupCmdResponse) getElastistorRestClient(s_esIPVAL, s_esAPIKEYVAL).executeCommand(addQosGroupCmd); + + if (addQosGroupCmdResponse.getQoSGroup().getUuid() == null) { + + throw new CloudRuntimeException("adding qos group failed , contact elatistor admin"); + + } + + else { + + CreateVolumeCmd createVolumeCmd = new CreateVolumeCmd(); + + qosgroupid = addQosGroupCmdResponse.getQoSGroup().getUuid(); + + if (null != ElastistorUtil.s_esACCOUNTIDVAL)createVolumeCmd.putCommandParameter(ElastistorUtil.REST_PARAM_ACCOUNTID,ElastistorUtil.s_esACCOUNTIDVAL); + if (null != qosgroupid)createVolumeCmd.putCommandParameter(ElastistorUtil.REST_PARAM_QOSGROUPID, qosgroupid); + if (null != tsmid)createVolumeCmd.putCommandParameter(ElastistorUtil.REST_PARAM_TSMID, tsmid); + if (null != ElastistorUtil.s_esPOOLIDVAL)createVolumeCmd.putCommandParameter(ElastistorUtil.REST_PARAM_POOLID,ElastistorUtil.s_esPOOLIDVAL); + if (null != VolumeName)createVolumeCmd.putCommandParameter(ElastistorUtil.REST_PARAM_NAME, VolumeName); + if (null != quotasize)createVolumeCmd.putCommandParameter(ElastistorUtil.REST_PARAM_QUOTA_SIZE, quotasize); + if(protocoltype.equalsIgnoreCase("nfs")){ + if ( null != ElastistorUtil.ES_BLOCKSIZE_VAL ) createVolumeCmd.putCommandParameter(ElastistorUtil.REST_PARAM_BLOCKSIZE, ElastistorUtil.ES_BLOCKSIZE_VAL); + if ( null != ElastistorUtil.ES_BLOCKSIZE_VAL ) createVolumeCmd.putCommandParameter(ElastistorUtil.REST_PARAM_RECORDSIZE, ElastistorUtil.ES_BLOCKSIZE_VAL); + } + else{ + if ( null != ElastistorUtil.ES_BLOCKSIZE_VAL ) createVolumeCmd.putCommandParameter(ElastistorUtil.REST_PARAM_BLOCKSIZE, "512B"); + if ( null != ElastistorUtil.ES_BLOCKSIZE_VAL ) createVolumeCmd.putCommandParameter(ElastistorUtil.REST_PARAM_RECORDSIZE, "512B"); + } + if (null != ElastistorUtil.ES_DEDUPLICATION_VAL)createVolumeCmd.putCommandParameter(ElastistorUtil.REST_PARAM_DEDUPLICATION, ElastistorUtil.ES_DEDUPLICATION_VAL); + if (null != ElastistorUtil.ES_SYNC_VAL)createVolumeCmd.putCommandParameter(ElastistorUtil.REST_PARAM_SYNC, ElastistorUtil.ES_SYNC_VAL); + if (null != ElastistorUtil.ES_COMPRESSION_VAL)createVolumeCmd.putCommandParameter(ElastistorUtil.REST_PARAM_COMPRESSION, ElastistorUtil.ES_COMPRESSION_VAL); + if (null != ElastistorUtil.ES_NOOFCOPIES_VAL)createVolumeCmd.putCommandParameter(ElastistorUtil.REST_PARAM_NOOFCOPIES, ElastistorUtil.ES_NOOFCOPIES_VAL); + createVolumeCmd.putCommandParameter(ElastistorUtil.REST_PARAM_MOUNTPOINT, mountpoint); + if (null != ElastistorUtil.ES_CASESENSITIVITY_VAL)createVolumeCmd.putCommandParameter(ElastistorUtil.REST_PARAM_CASESENSITIVITY, ElastistorUtil.ES_CASESENSITIVITY_VAL); + if (null != ElastistorUtil.ES_READONLY_VAL)createVolumeCmd.putCommandParameter(ElastistorUtil.REST_PARAM_READONLY, ElastistorUtil.ES_READONLY_VAL); + if (null != datasetid)createVolumeCmd.putCommandParameter(ElastistorUtil.REST_PARAM_DATASETID, datasetid); + if (null != ElastistorUtil.ES_UNICODE_VAL)createVolumeCmd.putCommandParameter(ElastistorUtil.REST_PARAM_UNICODE, ElastistorUtil.ES_UNICODE_VAL); + createVolumeCmd.putCommandParameter(ElastistorUtil.REST_PARAM_PROTOCOLTYPE, protocoltype); + if (null != ElastistorUtil.ES_AUTHNETWORK_VAL)createVolumeCmd.putCommandParameter(ElastistorUtil.REST_PARAM_AUTHNETWORK, ElastistorUtil.ES_AUTHNETWORK_VAL); + if (null != ElastistorUtil.ES_MAPUSERSTOROOT_VAL)createVolumeCmd.putCommandParameter(ElastistorUtil.REST_PARAM_MAPUSERSTOROOT, ElastistorUtil.ES_MAPUSERSTOROOT_VAL); + + CreateVolumeCmdResponse createVolumeCmdResponse; + try { + createVolumeCmdResponse = (CreateVolumeCmdResponse) getElastistorRestClient(s_esIPVAL, s_esAPIKEYVAL).executeCommand(createVolumeCmd); + + if (createVolumeCmdResponse.getFileSystem().getUuid() == null) { + + throw new CloudRuntimeException("creating volume failed , contact elatistor admin"); + + } else { + return createVolumeCmdResponse; + } + + } catch (Exception e) { + throw new CloudRuntimeException("creating volume failed , contact elatistor admin", e); + } + + } + + } + + /** + * This deletes both the volume and the tsm in elastistor. + */ + public static boolean deleteElastistorVolume(String poolip, String esmanagementip, String esapikey) throws Throwable { + + String esvolumeid = null; + String estsmid = null; + + ListTsmsResponse listTsmsResponse = listTsm(poolip); + + if (listTsmsResponse.getTsmsCount() != 0) { + int i; + + for (i = 0; i < listTsmsResponse.getTsmsCount(); i++) { + if (poolip.compareTo(listTsmsResponse.getTsms().getTsm(i).getIpaddress()) == 0) { + estsmid = listTsmsResponse.getTsms().getTsm(i).getUuid(); + break; + } + } + + if (listTsmsResponse.getTsms().getTsm(i).checkvolume()) { + esvolumeid = listTsmsResponse.getTsms().getTsm(i).getVolumeProperties(0).getid(); + DeleteVolumeResponse deleteVolumeResponse = deleteVolume(esvolumeid, null); + + if (deleteVolumeResponse != null) { + String jobid = deleteVolumeResponse.getJobId(); + int jobstatus = queryAsyncJobResult(jobid); + + if (jobstatus == 1) { + s_logger.info("elastistor volume successfully deleted"); + } else { + s_logger.info("now farce deleting the volume"); + + while (jobstatus != 1) { + DeleteVolumeResponse deleteVolumeResponse1 = deleteVolume(esvolumeid, "true"); + + if (deleteVolumeResponse1 != null) { + String jobid1 = deleteVolumeResponse1.getJobId(); + jobstatus = queryAsyncJobResult(jobid1); + } + } + s_logger.info("elastistor volume successfully deleted"); + } + } + } else { + s_logger.info("no volume present in on the given tsm"); + } + s_logger.info("now trying to delete elastistor tsm"); + + if (estsmid != null) { + DeleteTsmCmd deleteTsmCmd = new DeleteTsmCmd(); + deleteTsmCmd.putCommandParameter(ElastistorUtil.REST_PARAM_ID,estsmid); + DeleteTsmResponse deleteTsmResponse = (DeleteTsmResponse) getElastistorRestClient(s_esIPVAL, s_esAPIKEYVAL).executeCommand(deleteTsmCmd); + + if (deleteTsmResponse != null) { + String jobstatus = deleteTsmResponse.getJobStatus(); + + if (jobstatus.equalsIgnoreCase("true")) { + s_logger.info("deletion of elastistor tsm successful"); + return true; + } else { + s_logger.info("failed to delete elastistor tsm"); + return false; + } + } else { + s_logger.info("elastistor tsm id not present"); + } + } + else { + s_logger.error("no volume is present in the tsm"); + } + } else { + s_logger.error("List tsm failed, no tsm present in the eastistor for the given IP "); + return false; + } + return false; + + } + + /** + * This give a json response containing the list of tsm's in elastistor. + */ + private static ListTsmsResponse listTsm(String poolip) throws Throwable { + + ListTsmCmd listTsmCmd = new ListTsmCmd(); + + listTsmCmd.putCommandParameter(ElastistorUtil.REST_PARAM_IPADDRESS,poolip); + + ListTsmsResponse listTsmsResponse = (ListTsmsResponse) getElastistorRestClient(s_esIPVAL, s_esAPIKEYVAL).executeCommand(listTsmCmd); + + return listTsmsResponse; + } + + private static DeleteVolumeResponse deleteVolume(String esvolumeid, String forcedelete)throws Throwable { + + DeleteVolumeCmd deleteVolumeCmd = new DeleteVolumeCmd(); + + deleteVolumeCmd.putCommandParameter(ElastistorUtil.REST_PARAM_ID,esvolumeid); + deleteVolumeCmd.putCommandParameter(ElastistorUtil.REST_PARAM_FORECEDELETE, forcedelete); + + DeleteVolumeResponse deleteVolumeResponse = (DeleteVolumeResponse) getElastistorRestClient(s_esIPVAL, s_esAPIKEYVAL).executeCommand(deleteVolumeCmd); + + return deleteVolumeResponse; + } + + private static int queryAsyncJobResult(String jobid) throws Throwable { + + QueryAsyncJobResultCmd asyncJobResultCmd = new QueryAsyncJobResultCmd(); + ElastiCenterClient restclient = getElastistorRestClient(s_esIPVAL, s_esAPIKEYVAL); + + asyncJobResultCmd.putCommandParameter(ElastistorUtil.REST_PARAM_JOBID, jobid); + + QueryAsyncJobResultResponse asyncJobResultResponse = (QueryAsyncJobResultResponse) restclient.executeCommand(asyncJobResultCmd); + + if (asyncJobResultResponse != null) { + int jobstatus = asyncJobResultResponse.getAsync().getJobStatus(); + + while (jobstatus == 0) { + + QueryAsyncJobResultResponse jobResultResponse = (QueryAsyncJobResultResponse) restclient.executeCommand(asyncJobResultCmd); + + jobstatus = jobResultResponse.getAsync().getJobStatus(); + } + return jobstatus; + } + return 0; + + } + + /** + * this method converts the long capacitybytes to string format, which is feasible for elastistor rest api + * 214748364800 = 200G. + */ + private static String convertCapacityBytes(Long capacityBytes){ + + String quotasize; + + if((1099511627776L)>capacityBytes &&(capacityBytes>(1073741824))){ + return quotasize =(String.valueOf(capacityBytes/(1024*1024*1024))+"G"); + }else + { int temp1 = (int) (capacityBytes/(1024*1024*1024)); + int temp2 = temp1/1024; + return quotasize =(String.valueOf(temp2)+"T"); + } + } + + static interface ElastiCenterCommand { + + /* + * Returns the command string to be sent to the ElastiCenter + */ + public String getCommandName(); + + /* + * Utility method to allow the client to validate the input parameters + * before sending to the ElastiCenter. + * + * This command will be executed by the ElastiCenterClient only this method + * returns true. + */ + public boolean validate(); + + /* + * Returns the query parameters that have to be passed to execute the + * command. + * + * Returns null if there are query parameters associated with the command + */ + public MultivaluedMap getCommandParameters(); + + /* + * Adds new key-value pair to the query paramters lists. + */ + public void putCommandParameter(String key, String value); + + /* + * Return an instance of the Response Object Type. + * + * Return null if no response is expected. + */ + public Object getResponseObject(); + } + + private static class BaseCommand implements ElastiCenterCommand { + + private String commandName = null; + private MultivaluedMap commandParameters = null; + private Object responseObject = null; + + /* + * Enforce the Commands to be initialized with command name and optional + * response object + */ + protected BaseCommand(String cmdName, Object responseObj) { + commandName = cmdName; + responseObject = responseObj; + } + + @Override + public String getCommandName() { + return commandName; + } + + @Override + public boolean validate() { + // TODO This method can be extended to do some generic + // validations. + return true; + } + + @Override + public MultivaluedMap getCommandParameters() { + return commandParameters; + } + + @Override + public void putCommandParameter(String key, String value) { + if (null == commandParameters) { + commandParameters = new MultivaluedMapImpl(); + } + commandParameters.add(key, value); + } + + @Override + public Object getResponseObject() { + return responseObject; + } + + } + +/** + * this is a rest client which is used to call the http rest calls to elastistor + * @author punith + * + */ + private static final class ElastiCenterClient { + + public static boolean debug = false; + + private boolean initialized = false; + + private String apiKey = null; + private String elastiCenterAddress = null; + private String responseType = "json"; + private boolean ignoreSSLCertificate = false; + + private String restprotocol = "https://"; + private String restpath = "/client/api"; + private String restdefaultcommand = "listCapabilities"; + + private String queryparamcommand = "command"; + private String queryparamapikey = "apikey"; + private String queryparamresponse = "response"; + + public ElastiCenterClient(String address, String key)throws InvalidCredentialsException, InvalidParameterException,SSLHandshakeException, ServiceUnavailableException { + this.elastiCenterAddress = address; + this.apiKey = key; + this.initialize(); + } + + public void initialize() throws InvalidParameterException, + SSLHandshakeException, InvalidCredentialsException, + ServiceUnavailableException { + + if (apiKey == null || apiKey.trim().isEmpty()) { + throw new InvalidParameterException("Unable to initialize. Please specify a valid API Key."); + } + + if (elastiCenterAddress == null || elastiCenterAddress.trim().isEmpty()) { + // TODO : Validate the format, like valid IP address or hostname. + throw new InvalidParameterException("Unable to initialize. Please specify a valid ElastiCenter IP Address or Hostname."); + } + + if (ignoreSSLCertificate) { + // Create a trust manager that does not validate certificate chains + TrustManager[] trustAllCerts = new TrustManager[] { new X509TrustManager() { + public X509Certificate[] getAcceptedIssuers() { + return null; + } + + public void checkClientTrusted(X509Certificate[] certs, + String authType) { + } + + public void checkServerTrusted(X509Certificate[] certs, + String authType) { + } + } }; + + HostnameVerifier hv = new HostnameVerifier() { + @Override + public boolean verify(String urlHostName, SSLSession session) { + return true; + } + }; + + // Install the all-trusting trust manager + try { + SSLContext sc = SSLContext.getInstance("TLS"); + sc.init(null, trustAllCerts, new SecureRandom()); + HttpsURLConnection.setDefaultSSLSocketFactory(sc.getSocketFactory()); + HttpsURLConnection.setDefaultHostnameVerifier(hv); + } catch (Exception e) { + ; + } + } + + ListCapabilitiesResponse listCapabilitiesResponse = null; + try { + initialized = true; + listCapabilitiesResponse = (ListCapabilitiesResponse) executeCommand(restdefaultcommand, null, new ListCapabilitiesResponse()); + + } catch (Throwable t) { + initialized = false; + if (t instanceof InvalidCredentialsException) { + throw (InvalidCredentialsException) t; + } else if (t instanceof ServiceUnavailableException) { + throw (ServiceUnavailableException) t; + } else if (t.getCause() instanceof SSLHandshakeException) { + throw new SSLHandshakeException( + "Unable to initialize. An untrusted SSL Certificate was received from " + + elastiCenterAddress + + ". Please verify your truststore or configure ElastiCenterClient to skip the SSL Validation. "); + } else if (t.getCause() instanceof ConnectException) { + throw new ServiceUnavailableException( + "Unable to initialize. Failed to connect to " + + elastiCenterAddress + + ". Please verify the IP Address, Network Connectivity and ensure that Services are running on the ElastiCenter Server. "); + } + throw new ServiceUnavailableException("Unable to initialize. Please contact your ElastiCenter Administrator. Exception " + t.getMessage()); + } + + if (null == listCapabilitiesResponse || null == listCapabilitiesResponse.getCapabilities() || null == listCapabilitiesResponse.getCapabilities().getVersion()) { + initialized = false; + throw new ServiceUnavailableException("Unable to execute command on the server"); + } + + } + + public Object executeCommand(ElastiCenterCommand cmd) throws Throwable { + return executeCommand(cmd.getCommandName(), cmd.getCommandParameters(),cmd.getResponseObject()); + } + + public Object executeCommand(String command,MultivaluedMap params, Object responeObj) throws Throwable { + + if (!initialized) { + throw new IllegalStateException("Error : ElastiCenterClient is not initialized."); + } + + if (command == null || command.trim().isEmpty()) { + throw new InvalidParameterException("No command to execute."); + } + + try { + ClientConfig config = new DefaultClientConfig(); + Client client = Client.create(config); + WebResource webResource = client.resource(UriBuilder.fromUri(restprotocol + elastiCenterAddress + restpath).build()); + + MultivaluedMap queryParams = new MultivaluedMapImpl(); + queryParams.add(queryparamapikey, apiKey); + queryParams.add(queryparamresponse, responseType); + + queryParams.add(queryparamcommand, command); + + if (null != params) { + for (String key : params.keySet()) { + queryParams.add(key, params.getFirst(key)); + } + } + if (debug) { + System.out.println("Command Sent " + command + " : "+ queryParams); + } + ClientResponse response = webResource.queryParams(queryParams).accept(MediaType.APPLICATION_JSON).get(ClientResponse.class); + + if (response.getStatus() >= 300) { + if (debug) + System.out.println("ElastiCenter returned error code : " + response.getStatus()); + if (401 == response.getStatus()) { + throw new InvalidCredentialsException("Please specify a valid API Key."); + } else if (431 == response.getStatus()) { + throw new InvalidParameterException(response.getHeaders().getFirst("X-Description")); + } else if (432 == response.getStatus()) { + throw new InvalidParameterException(command + " does not exist on the ElastiCenter server. Please specify a valid command or contact your ElastiCenter Administrator."); + } else { + throw new ServiceUnavailableException("Internal Error. Please contact your ElastiCenter Administrator."); + } + } else if (null != responeObj) { + String jsonResponse = response.getEntity(String.class); + if (debug) { + System.out.println("Command Response : " + jsonResponse); + } + Gson gson = new Gson(); + return gson.fromJson(jsonResponse, responeObj.getClass()); + } else { + return "Success"; + } + } catch (Throwable t) { + throw t; + } + } + } + + /** + * these are the list of Elastistor rest commands being called from the plugin. + * + */ + private static final class CreateTsmCmd extends BaseCommand { + + public CreateTsmCmd() { + super("createTsm", new CreateTsmCmdResponse()); + + } + + } + + private static final class AddQosGroupCmd extends BaseCommand { + + public AddQosGroupCmd() { + + super("addQosGroup", new AddQosGroupCmdResponse()); + + } + + } + + private static final class CreateVolumeCmd extends BaseCommand { + + public CreateVolumeCmd() { + super("createVolume", new CreateVolumeCmdResponse()); + + } + + } + + private static final class DeleteTsmCmd extends BaseCommand { + + public DeleteTsmCmd() { + super("deleteTsm", new DeleteTsmResponse()); + } + + } + + private static final class DeleteVolumeCmd extends BaseCommand { + + public DeleteVolumeCmd() { + super("deleteFileSystem", new DeleteVolumeResponse()); + } + + } + + private static final class QueryAsyncJobResultCmd extends BaseCommand { + + public QueryAsyncJobResultCmd() { + super("queryAsyncJobResult", new QueryAsyncJobResultResponse()); + } + + } + + private static final class ListTsmCmd extends BaseCommand { + + public ListTsmCmd() { + super("listTsm", new ListTsmsResponse()); + } + + } + + /** + * these are the list of Elastistor rest json response classes for parsing the json response sent by elastistor. + * + */ + public static final class CreateTsmCmdResponse { + + @SerializedName("createTsmResponse") + private TsmWrapper tsmWrapper; + + public Tsm getTsm() { + return tsmWrapper.getTsm(); + } + + } + + public static final class Tsm { + + @SerializedName("id") + private String uuid; + + @SerializedName("name") + private String name; + + @SerializedName("datasetid") + private String datasetid; + + @SerializedName("ipaddress") + private String ipaddress; + + @SerializedName("volumes") + private VolumeProperties[] volumeProperties; + + public String getUuid() { + return uuid; + } + + public String getName() { + return name; + } + + public String getIpaddress() { + return ipaddress; + } + + public String getDatasetid() { + return datasetid; + } + + public boolean checkvolume() { + + if(volumeProperties != null){ + return true; + } + else{ + return false; + } + + } + + public VolumeProperties getVolumeProperties(int i) { + return volumeProperties[i]; + } + + } + + public static final class VolumeProperties { + + @SerializedName("id") + private String id; + + @SerializedName("groupid") + private String groupid; + + @SerializedName("iops") + private String iops; + + @SerializedName("name") + private String name; + + public String getid() { + return id; + } + + public String getQosgroupid() { + return groupid; + } + + public String getName() { + return name; + } + + public String getIops() { + return iops; + } + } + + public static final class TsmWrapper { + + @SerializedName("tsm") + private Tsm tsm; + + public Tsm getTsm() { + return tsm; + } + + } + + public static final class AddQosGroupCmdResponse { + + @SerializedName("addqosgroupresponse") + private QoSGroupWrapper qosGroupWrapper; + + public QoSGroup getQoSGroup() { + return qosGroupWrapper.getQosGroup(); + } + } + + public static final class QoSGroupWrapper { + + @SerializedName("qosgroup") + private QoSGroup qoSGroup; + + public QoSGroup getQosGroup() { + + return qoSGroup; + } + + } + + public static final class QoSGroup { + + @SerializedName("id") + private String uuid; + + @SerializedName("name") + private String name; + + @SerializedName("qosgroupproperties") + private HashMap qosGroupProperties; + + public String getName() { + return name; + } + + public String getUuid() { + return uuid; + } + + public String getIops() { + return qosGroupProperties.get("iops"); + } + + public String getThroughput() { + return qosGroupProperties.get("throughput"); + } + + public String getLatency() { + return qosGroupProperties.get("latency"); + } + } + + public static final class CreateVolumeCmdResponse { + + @SerializedName("adddatasetresponse") + private FileSystemWrapper fileSystemWrapper; + + public FileSystem getFileSystem() { + + return fileSystemWrapper.getFileSystem(); + } + + } + + public static final class FileSystemWrapper { + + @SerializedName("filesystem") + private FileSystem fileSystem; + + public FileSystem getFileSystem() { + return fileSystem; + } + + } + + public static final class FileSystem { + + @SerializedName("id") + private String uuid; + + @SerializedName("name") + private String name; + + @SerializedName("quota") + private String quota; + + @SerializedName("timestamp") + private String timestamp; + + @SerializedName("iqnname") + private String iqnname; + + @SerializedName("filesystemproperties") + private HashMap[] filesystemproperties; + + public String getUuid() { + return uuid; + } + + public String getName() { + return name; + } + + public String getIqn() { + return iqnname; + } + + public String getQuota() { + return quota; + } + + public String getTimestamp() { + return timestamp; + } + + } + + public static final class DeleteTsmResponse { + + @SerializedName("deleteTsmResponse") + private JobId jobId; + + public String getJobStatus() { + return jobId.getJobStatus(); + } + + } + + public static final class JobId { + + @SerializedName("jobid") + private String jobid; + + @SerializedName("success") + private String jobStatus; + + public String getJobid() { + return jobid; + } + + public String getJobStatus() { + return jobStatus; + } + + } + + public static final class DeleteVolumeResponse { + + @SerializedName("deleteFileSystemResponse") + private JobId jobId; + + public String getJobId() { + return jobId.getJobid(); + } + + } + + public static final class ListCapabilitiesResponse { + + @SerializedName("listcapabilitiesresponse") + private Capabilities capabilities; + + public Capabilities getCapabilities() { + return capabilities; + } + } + + public static final class ListTsmsResponse { + + @SerializedName("listTsmResponse") + private Tsms tsms; + + public int getTsmsCount() { + return tsms.getCount(); + } + + public Tsms getTsms() { + return tsms; + } + } + + public static final class Tsms { + + @SerializedName("count") + private int count; + + @SerializedName("listTsm") + private Tsm[] tsms; + + public int getCount() { + return count; + } + + public Tsm getTsm(int i) { + return tsms[i]; + } + } + + public static final class QueryAsyncJobResultResponse { + + @SerializedName("queryasyncjobresultresponse") + private Async async; + + public Async getAsync() { + return async; + } + } + + public static final class Async { + + @SerializedName("jobstatus") + private int jobstatus; + + @SerializedName("cmd") + private String cmd; + + public int getJobStatus() { + return jobstatus; + } + + public String getCmd() { + return cmd; + } + + } + + public static final class Capabilities { + + @SerializedName("capability") + private HashMap capabilites; + + public String getVersion() { + return capabilites.get("cloudByteVersion"); + } + } +} diff --git a/plugins/storage/volume/default/src/org/apache/cloudstack/storage/datastore/driver/CloudStackPrimaryDataStoreDriverImpl.java b/plugins/storage/volume/default/src/org/apache/cloudstack/storage/datastore/driver/CloudStackPrimaryDataStoreDriverImpl.java index ae217b6359..5983a05a53 100644 --- a/plugins/storage/volume/default/src/org/apache/cloudstack/storage/datastore/driver/CloudStackPrimaryDataStoreDriverImpl.java +++ b/plugins/storage/volume/default/src/org/apache/cloudstack/storage/datastore/driver/CloudStackPrimaryDataStoreDriverImpl.java @@ -24,7 +24,6 @@ import javax.inject.Inject; -import org.apache.cloudstack.engine.orchestration.service.VolumeOrchestrationService; import org.apache.cloudstack.engine.subsystem.api.storage.ChapInfo; import org.apache.cloudstack.engine.subsystem.api.storage.CopyCommandResult; import org.apache.cloudstack.engine.subsystem.api.storage.CreateCmdResult; @@ -99,8 +98,6 @@ public Map getCapabilities() { @Inject StorageManager storageMgr; @Inject - VolumeOrchestrationService volumeMgr; - @Inject VMInstanceDao vmDao; @Inject SnapshotDao snapshotDao; @@ -151,10 +148,13 @@ public ChapInfo getChapInfo(VolumeInfo volumeInfo) { } @Override - public boolean connectVolumeToHost(VolumeInfo volumeInfo, Host host, DataStore dataStore) { return false; } + public boolean connectVolumeToHost(VolumeInfo volumeInfo, Host host, DataStore dataStore) { + return false; + } @Override - public void disconnectVolumeFromHost(VolumeInfo volumeInfo, Host host, DataStore dataStore) {} + public void disconnectVolumeFromHost(VolumeInfo volumeInfo, Host host, DataStore dataStore) { + } @Override public long getVolumeSizeIncludingHypervisorSnapshotReserve(Volume volume, StoragePool pool) { @@ -168,7 +168,7 @@ public void createAsync(DataStore dataStore, DataObject data, AsyncCompletionCal CreateCmdResult result = new CreateCmdResult(null, null); if (data.getType() == DataObjectType.VOLUME) { try { - answer = createVolume((VolumeInfo)data); + answer = createVolume((VolumeInfo) data); if ((answer == null) || (!answer.getResult())) { result.setSuccess(false); if (answer != null) { @@ -260,7 +260,7 @@ public boolean canCopy(DataObject srcData, DataObject destData) { DataStore store = destData.getDataStore(); if (store.getRole() == DataStoreRole.Primary) { if ((srcData.getType() == DataObjectType.TEMPLATE && destData.getType() == DataObjectType.TEMPLATE) || - (srcData.getType() == DataObjectType.TEMPLATE && destData.getType() == DataObjectType.VOLUME)) { + (srcData.getType() == DataObjectType.TEMPLATE && destData.getType() == DataObjectType.VOLUME)) { StoragePoolVO storagePoolVO = primaryStoreDao.findById(store.getId()); if (storagePoolVO != null && storagePoolVO.getPoolType() == Storage.StoragePoolType.CLVM) { return true; @@ -274,10 +274,10 @@ public boolean canCopy(DataObject srcData, DataObject destData) { public void takeSnapshot(SnapshotInfo snapshot, AsyncCompletionCallback callback) { CreateCmdResult result = null; try { - SnapshotObjectTO snapshotTO = (SnapshotObjectTO)snapshot.getTO(); + SnapshotObjectTO snapshotTO = (SnapshotObjectTO) snapshot.getTO(); Object payload = snapshot.getPayload(); if (payload != null && payload instanceof CreateSnapshotPayload) { - CreateSnapshotPayload snapshotPayload = (CreateSnapshotPayload)payload; + CreateSnapshotPayload snapshotPayload = (CreateSnapshotPayload) payload; snapshotTO.setQuiescevm(snapshotPayload.getQuiescevm()); } @@ -285,7 +285,7 @@ public void takeSnapshot(SnapshotInfo snapshot, AsyncCompletionCallback callback) { - VolumeObject vol = (VolumeObject)data; - StoragePool pool = (StoragePool)data.getDataStore(); - ResizeVolumePayload resizeParameter = (ResizeVolumePayload)vol.getpayload(); + VolumeObject vol = (VolumeObject) data; + StoragePool pool = (StoragePool) data.getDataStore(); + ResizeVolumePayload resizeParameter = (ResizeVolumePayload) vol.getpayload(); ResizeVolumeCommand resizeCmd = - new ResizeVolumeCommand(vol.getPath(), new StorageFilerTO(pool), vol.getSize(), resizeParameter.newSize, resizeParameter.shrinkOk, - resizeParameter.instanceName); + new ResizeVolumeCommand(vol.getPath(), new StorageFilerTO(pool), vol.getSize(), resizeParameter.newSize, resizeParameter.shrinkOk, + resizeParameter.instanceName); CreateCmdResult result = new CreateCmdResult(null, null); try { - ResizeVolumeAnswer answer = (ResizeVolumeAnswer)storageMgr.sendToPool(pool, resizeParameter.hosts, resizeCmd); + ResizeVolumeAnswer answer = (ResizeVolumeAnswer) storageMgr.sendToPool(pool, resizeParameter.hosts, resizeCmd); if (answer != null && answer.getResult()) { long finalSize = answer.getNewSize(); s_logger.debug("Resize: volume started at size " + vol.getSize() + " and ended at size " + finalSize); diff --git a/plugins/user-authenticators/ldap/src/org/apache/cloudstack/api/command/LdapCreateAccountCmd.java b/plugins/user-authenticators/ldap/src/org/apache/cloudstack/api/command/LdapCreateAccountCmd.java index 626bb8fee6..b753952aec 100644 --- a/plugins/user-authenticators/ldap/src/org/apache/cloudstack/api/command/LdapCreateAccountCmd.java +++ b/plugins/user-authenticators/ldap/src/org/apache/cloudstack/api/command/LdapCreateAccountCmd.java @@ -23,9 +23,6 @@ import javax.inject.Inject; import javax.naming.NamingException; -import org.apache.log4j.Logger; -import org.bouncycastle.util.encoders.Base64; - import org.apache.cloudstack.api.APICommand; import org.apache.cloudstack.api.ApiConstants; import org.apache.cloudstack.api.ApiErrorCode; @@ -38,13 +35,16 @@ import org.apache.cloudstack.context.CallContext; import org.apache.cloudstack.ldap.LdapManager; import org.apache.cloudstack.ldap.LdapUser; +import org.apache.log4j.Logger; +import org.bouncycastle.util.encoders.Base64; +import com.cloud.domain.DomainVO; import com.cloud.user.Account; import com.cloud.user.AccountService; +import com.cloud.user.User; import com.cloud.user.UserAccount; -@APICommand(name = "ldapCreateAccount", description = "Creates an account from an LDAP user", responseObject = AccountResponse.class, since = "4.2.0", - requestHasSensitiveInfo = false, responseHasSensitiveInfo = false) +@APICommand(name = "ldapCreateAccount", description = "Creates an account from an LDAP user", responseObject = AccountResponse.class, since = "4.2.0", requestHasSensitiveInfo = false, responseHasSensitiveInfo = false) public class LdapCreateAccountCmd extends BaseCmd { public static final Logger s_logger = Logger.getLogger(LdapCreateAccountCmd.class.getName()); private static final String s_name = "createaccountresponse"; @@ -52,23 +52,16 @@ public class LdapCreateAccountCmd extends BaseCmd { @Inject private LdapManager _ldapManager; - @Parameter(name = ApiConstants.ACCOUNT, - type = CommandType.STRING, - description = "Creates the user under the specified account. If no account is specified, the username will be used as the account name.") + @Parameter(name = ApiConstants.ACCOUNT, type = CommandType.STRING, description = "Creates the user under the specified account. If no account is specified, the username will be used as the account name.") private String accountName; - @Parameter(name = ApiConstants.ACCOUNT_TYPE, - type = CommandType.SHORT, - required = true, - description = "Type of the account. Specify 0 for user, 1 for root admin, and 2 for domain admin") + @Parameter(name = ApiConstants.ACCOUNT_TYPE, type = CommandType.SHORT, required = true, description = "Type of the account. Specify 0 for user, 1 for root admin, and 2 for domain admin") private Short accountType; @Parameter(name = ApiConstants.DOMAIN_ID, type = CommandType.UUID, entityType = DomainResponse.class, description = "Creates the user under the specified domain.") private Long domainId; - @Parameter(name = ApiConstants.TIMEZONE, - type = CommandType.STRING, - description = "Specifies a timezone for this command. For more information on the timezone parameter, see Time Zone Format.") + @Parameter(name = ApiConstants.TIMEZONE, type = CommandType.STRING, description = "Specifies a timezone for this command. For more information on the timezone parameter, see Time Zone Format.") private String timezone; @Parameter(name = ApiConstants.USERNAME, type = CommandType.STRING, required = true, description = "Unique username.") @@ -96,22 +89,46 @@ public LdapCreateAccountCmd(final LdapManager ldapManager, final AccountService _accountService = accountService; } - UserAccount createCloudstackUserAccount(final LdapUser user) { - return _accountService.createUserAccount(username, generatePassword(), user.getFirstname(), user.getLastname(), user.getEmail(), timezone, accountName, - accountType, domainId, networkDomain, details, accountUUID, userUUID); + UserAccount createCloudstackUserAccount(final LdapUser user, String accountName, Long domainId) { + Account account = _accountService.getActiveAccountByName(accountName, domainId); + if (account == null) { + return _accountService.createUserAccount(username, generatePassword(), user.getFirstname(), user.getLastname(), user.getEmail(), timezone, accountName, accountType, + domainId, networkDomain, details, accountUUID, userUUID); + } else { + User newUser = _accountService.createUser(username, generatePassword(), user.getFirstname(), user.getLastname(), user.getEmail(), timezone, accountName, domainId, + userUUID); + return _accountService.getUserAccountById(newUser.getId()); + } + } + + private String getAccountName() { + String name = accountName; + if (accountName == null) { + name = username; + } + return name; + } + + private Long getDomainId() { + Long id = domainId; + if (id == null) { + id = DomainVO.ROOT_DOMAIN; + } + return id; } @Override public void execute() throws ServerApiException { final CallContext callContext = getCurrentContext(); - callContext.setEventDetails("Account Name: " + accountName + ", Domain Id:" + domainId); + String finalAccountName = getAccountName(); + Long finalDomainId = getDomainId(); + callContext.setEventDetails("Account Name: " + finalAccountName + ", Domain Id:" + finalDomainId); try { final LdapUser user = _ldapManager.getUser(username); validateUser(user); - final UserAccount userAccount = createCloudstackUserAccount(user); + final UserAccount userAccount = createCloudstackUserAccount(user, finalAccountName, finalDomainId); if (userAccount != null) { - final AccountResponse response = _responseGenerator - .createUserAccountResponse(ResponseView.Full, userAccount); + final AccountResponse response = _responseGenerator.createUserAccountResponse(ResponseView.Full, userAccount); response.setResponseName(getCommandName()); setResponseObject(response); } else { @@ -159,4 +176,4 @@ private boolean validateUser(final LdapUser user) throws ServerApiException { } return true; } -} \ No newline at end of file +} diff --git a/plugins/user-authenticators/ldap/src/org/apache/cloudstack/api/command/LdapImportUsersCmd.java b/plugins/user-authenticators/ldap/src/org/apache/cloudstack/api/command/LdapImportUsersCmd.java index 887ad009fd..6f7be90fd2 100644 --- a/plugins/user-authenticators/ldap/src/org/apache/cloudstack/api/command/LdapImportUsersCmd.java +++ b/plugins/user-authenticators/ldap/src/org/apache/cloudstack/api/command/LdapImportUsersCmd.java @@ -25,6 +25,7 @@ import javax.inject.Inject; +import com.cloud.user.Account; import org.apache.cloudstack.api.APICommand; import org.apache.cloudstack.api.ApiConstants; import org.apache.cloudstack.api.ApiErrorCode; @@ -87,6 +88,9 @@ public class LdapImportUsersCmd extends BaseListCmd { private Domain _domain; + @Parameter(name = ApiConstants.ACCOUNT, type = CommandType.STRING, description = "Creates the user under the specified account. If no account is specified, the username will be used as the account name.") + private String accountName; + @Inject private LdapManager _ldapManager; @@ -101,6 +105,17 @@ public LdapImportUsersCmd(final LdapManager ldapManager, final DomainService dom _accountService = accountService; } + private void createCloudstackUserAccount(LdapUser user, String accountName, Domain domain) { + Account account = _accountService.getActiveAccountByName(accountName, domain.getId()); + if (account == null) { + _accountService.createUserAccount(user.getUsername(), generatePassword(), user.getFirstname(), user.getLastname(), user.getEmail(), timezone, accountName, accountType, + domain.getId(), domain.getNetworkDomain(), details, UUID.randomUUID().toString(), UUID.randomUUID().toString()); + } else { + _accountService.createUser(user.getUsername(), generatePassword(), user.getFirstname(), user.getLastname(), user.getEmail(), timezone, accountName, domain.getId(), + UUID.randomUUID().toString()); + } + } + @Override public void execute() throws ResourceUnavailableException, InsufficientCapacityException, ServerApiException, ConcurrentOperationException, ResourceAllocationException, NetworkRuleConflictException { @@ -122,8 +137,7 @@ public void execute() throws ResourceUnavailableException, InsufficientCapacityE for (LdapUser user : users) { Domain domain = getDomain(user); try { - _accountService.createUserAccount(user.getUsername(), generatePassword(), user.getFirstname(), user.getLastname(), user.getEmail(), timezone, - user.getUsername(), accountType, domain.getId(), domain.getNetworkDomain(), details, UUID.randomUUID().toString(), UUID.randomUUID().toString()); + createCloudstackUserAccount(user, getAccountName(user), domain); addedUsers.add(user); } catch (InvalidParameterValueException ex) { s_logger.error("Failed to create user with username: " + user.getUsername() + " ::: " + ex.getMessage()); @@ -135,6 +149,14 @@ public void execute() throws ResourceUnavailableException, InsufficientCapacityE setResponseObject(response); } + private String getAccountName(LdapUser user) { + String finalAccountName = accountName; + if(finalAccountName == null ) { + finalAccountName = user.getUsername(); + } + return finalAccountName; + } + private Domain getDomainForName(String name) { Domain domain = null; if (StringUtils.isNotBlank(name)) { diff --git a/plugins/user-authenticators/ldap/src/org/apache/cloudstack/ldap/LdapContextFactory.java b/plugins/user-authenticators/ldap/src/org/apache/cloudstack/ldap/LdapContextFactory.java index 4f6bb618c2..5811c32a3e 100644 --- a/plugins/user-authenticators/ldap/src/org/apache/cloudstack/ldap/LdapContextFactory.java +++ b/plugins/user-authenticators/ldap/src/org/apache/cloudstack/ldap/LdapContextFactory.java @@ -53,9 +53,10 @@ private DirContext createInitialDirContext(final String principal, final String return createInitialDirContext(principal, password, null, isSystemContext); } - private DirContext createInitialDirContext(final String principal, final String password, final String providerUrl, final boolean isSystemContext) - throws NamingException { - return new InitialDirContext(getEnvironment(principal, password, providerUrl, isSystemContext)); + private DirContext createInitialDirContext(final String principal, final String password, final String providerUrl, final boolean isSystemContext) throws NamingException { + Hashtable environment = getEnvironment(principal, password, providerUrl, isSystemContext); + s_logger.debug("initializing ldap with provider url: " + environment.get(Context.PROVIDER_URL)); + return new InitialDirContext(environment); } public DirContext createUserContext(final String principal, final String password) throws NamingException { diff --git a/plugins/user-authenticators/ldap/src/org/apache/cloudstack/ldap/LdapManagerImpl.java b/plugins/user-authenticators/ldap/src/org/apache/cloudstack/ldap/LdapManagerImpl.java index 6d71f4f17d..0e3bde840f 100644 --- a/plugins/user-authenticators/ldap/src/org/apache/cloudstack/ldap/LdapManagerImpl.java +++ b/plugins/user-authenticators/ldap/src/org/apache/cloudstack/ldap/LdapManagerImpl.java @@ -81,6 +81,7 @@ public LdapConfigurationResponse addConfiguration(final String hostname, final i s_logger.info("Added new ldap server with hostname: " + hostname); return new LdapConfigurationResponse(hostname, port); } catch (final NamingException e) { + s_logger.debug("NamingException while doing an LDAP bind", e); throw new InvalidParameterValueException("Unable to bind to the given LDAP server"); } } else { @@ -98,6 +99,7 @@ public boolean canAuthenticate(final String username, final String password) { closeContext(context); return true; } catch (final NamingException e) { + s_logger.debug("NamingException: while doing an LDAP bind for user "+" "+username, e); s_logger.info("Failed to authenticate user: " + username + ". incorrect password."); return false; } @@ -109,7 +111,7 @@ private void closeContext(final DirContext context) { context.close(); } } catch (final NamingException e) { - s_logger.warn(e.getMessage()); + s_logger.warn(e.getMessage(),e); } } @@ -183,6 +185,7 @@ public List getUsers() throws NoLdapUserMatchingQueryException { context = _ldapContextFactory.createBindContext(); return _ldapUserManager.getUsers(context); } catch (final NamingException e) { + s_logger.debug("ldap NamingException: ",e); throw new NoLdapUserMatchingQueryException("*"); } finally { closeContext(context); @@ -196,6 +199,7 @@ public List getUsersInGroup(String groupName) throws NoLdapUserMatchin context = _ldapContextFactory.createBindContext(); return _ldapUserManager.getUsersInGroup(groupName, context); } catch (final NamingException e) { + s_logger.debug("ldap NamingException: ",e); throw new NoLdapUserMatchingQueryException("groupName=" + groupName); } finally { closeContext(context); @@ -223,6 +227,7 @@ public List searchUsers(final String username) throws NoLdapUserMatchi final String escapedUsername = LdapUtils.escapeLDAPSearchFilter(username); return _ldapUserManager.getUsers("*" + escapedUsername + "*", context); } catch (final NamingException e) { + s_logger.debug("ldap NamingException: ",e); throw new NoLdapUserMatchingQueryException(username); } finally { closeContext(context); diff --git a/plugins/user-authenticators/ldap/test/groovy/org/apache/cloudstack/ldap/LdapImportUsersCmdSpec.groovy b/plugins/user-authenticators/ldap/test/groovy/org/apache/cloudstack/ldap/LdapImportUsersCmdSpec.groovy index a66da1f3cf..79eba93d89 100644 --- a/plugins/user-authenticators/ldap/test/groovy/org/apache/cloudstack/ldap/LdapImportUsersCmdSpec.groovy +++ b/plugins/user-authenticators/ldap/test/groovy/org/apache/cloudstack/ldap/LdapImportUsersCmdSpec.groovy @@ -19,9 +19,14 @@ package groovy.org.apache.cloudstack.ldap import com.cloud.domain.Domain import com.cloud.domain.DomainVO import com.cloud.user.AccountService +import com.cloud.user.AccountVO import com.cloud.user.DomainService +import com.cloud.user.UserAccountVO +import com.cloud.user.UserVO +import org.apache.cloudstack.api.command.LdapCreateAccountCmd import org.apache.cloudstack.api.command.LdapImportUsersCmd import org.apache.cloudstack.api.response.LdapUserResponse +import org.apache.cloudstack.context.CallContext import org.apache.cloudstack.ldap.LdapManager import org.apache.cloudstack.ldap.LdapUser @@ -193,4 +198,59 @@ class LdapImportUsersCmdSpec extends spock.lang.Specification { } + + def "Test create ldap import account for an already existing cloudstack account"() { + given: "We have an LdapManager, DomainService, two users and a LdapImportUsersCmd" + def ldapManager = Mock(LdapManager) + List users = new ArrayList() + users.add(new LdapUser("rmurphy", "rmurphy@test.com", "Ryan", "Murphy", "cn=rmurphy,ou=engineering,dc=cloudstack,dc=org", "engineering")) + ldapManager.getUsers() >> users + LdapUserResponse response1 = new LdapUserResponse("rmurphy", "rmurphy@test.com", "Ryan", "Murphy", "cn=rmurphy,ou=engineering,dc=cloudstack,dc=org", "engineering") + ldapManager.createLdapUserResponse(_) >>> response1 + + def domainService = Mock(DomainService) + 1 * domainService.getDomain(1L) >> new DomainVO("DOMAIN", 1L, 1L, "DOMAIN", UUID.randomUUID().toString());; + + def accountService = Mock(AccountService) + 1 * accountService.getActiveAccountByName('ACCOUNT', 0) >> Mock(AccountVO) + 1 * accountService.createUser('rmurphy', _ , 'Ryan', 'Murphy', 'rmurphy@test.com', null, 'ACCOUNT', 0, _) >> Mock(UserVO) + 0 * accountService.createUserAccount('rmurphy', _, 'Ryan', 'Murphy', 'rmurphy@test.com', null, 'ACCOUNT', 2, 0, 'DOMAIN', null, _, _) + + def ldapImportUsersCmd = new LdapImportUsersCmd(ldapManager, domainService, accountService) + ldapImportUsersCmd.accountName = "ACCOUNT" + ldapImportUsersCmd.accountType = 2; + ldapImportUsersCmd.domainId = 1L; + + when: "create account is called" + ldapImportUsersCmd.execute() + then: "expect 1 call on accountService createUser and 0 on account service create user account" + } + + def "Test create ldap import account for a new cloudstack account"() { + given: "We have an LdapManager, DomainService, two users and a LdapImportUsersCmd" + def ldapManager = Mock(LdapManager) + List users = new ArrayList() + users.add(new LdapUser("rmurphy", "rmurphy@test.com", "Ryan", "Murphy", "cn=rmurphy,ou=engineering,dc=cloudstack,dc=org", "engineering")) + ldapManager.getUsers() >> users + LdapUserResponse response1 = new LdapUserResponse("rmurphy", "rmurphy@test.com", "Ryan", "Murphy", "cn=rmurphy,ou=engineering,dc=cloudstack,dc=org", "engineering") + ldapManager.createLdapUserResponse(_) >>> response1 + + def domainService = Mock(DomainService) + 1 * domainService.getDomain(1L) >> new DomainVO("DOMAIN", 1L, 1L, "DOMAIN", UUID.randomUUID().toString());; + + def accountService = Mock(AccountService) + 1 * accountService.getActiveAccountByName('ACCOUNT', 0) >> null + 0 * accountService.createUser('rmurphy', _ , 'Ryan', 'Murphy', 'rmurphy@test.com', null, 'ACCOUNT', 0, _) + 1 * accountService.createUserAccount('rmurphy', _, 'Ryan', 'Murphy', 'rmurphy@test.com', null, 'ACCOUNT', 2, 0, 'DOMAIN', null, _, _) + + def ldapImportUsersCmd = new LdapImportUsersCmd(ldapManager, domainService, accountService) + ldapImportUsersCmd.accountName = "ACCOUNT" + ldapImportUsersCmd.accountType = 2; + ldapImportUsersCmd.domainId = 1L; + + when: "create account is called" + ldapImportUsersCmd.execute() + then: "expect 1 call on accountService createUser and 0 on account service create user account" + } + } diff --git a/pom.xml b/pom.xml index 02b1808727..b9067575d3 100644 --- a/pom.xml +++ b/pom.xml @@ -58,7 +58,7 @@ 1.9.0 build213-svnkit-1.3-patch 2.6.6 - 1.7.1 + 1.7.2 14.0-rc1 6.2.0-1-SNAPSHOT 3.1 @@ -86,7 +86,7 @@ 0.10 build/replace.properties 0.5.1 - 0.1.3 + 0.1.4 target 1.0.10 4.0.0 @@ -746,6 +746,7 @@ plugins/hypervisors/hyperv/DotNet/ServerResource/**/packages.config plugins/hypervisors/hyperv/DotNet/ServerResource/**/App.config plugins/hypervisors/hyperv/DotNet/ServerResource/**/*.csproj + plugins/hypervisors/hyperv/DotNet/ServerResource/**/*.settings plugins/hypervisors/hyperv/conf/agent.properties scripts/vm/systemvm/id_rsa.cloud services/console-proxy/server/conf/agent.properties diff --git a/scripts/vm/hypervisor/xenserver/check_heartbeat.sh b/scripts/vm/hypervisor/xenserver/check_heartbeat.sh index 22befe9165..e1b18278dd 100755 --- a/scripts/vm/hypervisor/xenserver/check_heartbeat.sh +++ b/scripts/vm/hypervisor/xenserver/check_heartbeat.sh @@ -72,3 +72,4 @@ do done echo "=====> DEAD <======" +exit 1 diff --git a/scripts/vm/hypervisor/xenserver/cloudstack_pluginlib.py b/scripts/vm/hypervisor/xenserver/cloudstack_pluginlib.py index 4ebb435a82..d3d234fdf5 100644 --- a/scripts/vm/hypervisor/xenserver/cloudstack_pluginlib.py +++ b/scripts/vm/hypervisor/xenserver/cloudstack_pluginlib.py @@ -22,6 +22,7 @@ import os import subprocess import simplejson as json +import copy from time import localtime, asctime @@ -38,6 +39,23 @@ OFCTL_PATH = "/usr/bin/ovs-ofctl" XE_PATH = "/opt/xensource/bin/xe" +# OpenFlow tables set in a pipeline processing fashion for the bridge created for a VPC's that are enabled for +# distributed routing. +# L2 path (intra-tier traffic) CLASSIFIER-> L2 lookup -> L2 flooding tables +# L3 path (inter-tier traffic) CLASSIFIER-> EGRESS ACL -> L3 lookup -> INGRESS ACL-> L2 lookup -> L2 flooding tables + +# Classifier table has the rules to separate broadcast/multi-cast traffic, inter-tier traffic, intra-tier traffic +CLASSIFIER_TABLE=0 +# Lookup table to determine the output port (vif/tunnel port) based on the MAC address +L2_LOOKUP_TABLE=1 +# flooding table has the rules to flood on ports (both VIF, tunnel ports) except on the port on which packet arrived +L2_FLOOD_TABLE=2 +# table has flow rules derived from egress ACL's +EGRESS_ACL_TABLE=3 +# Lookup table to determine the output port (vif/tunnel port) based on the IP address +L3_LOOKUP_TABLE=4 +# table has flow rules derived from egress ACL's +INGRESS_ACL_TABLE=5 class PluginError(Exception): """Base Exception class for all plugin errors.""" @@ -178,9 +196,10 @@ def _build_flow_expr(**kwargs): nw_src = 'nw_src' in kwargs and ",nw_src=%s" % kwargs['nw_src'] or '' nw_dst = 'nw_dst' in kwargs and ",nw_dst=%s" % kwargs['nw_dst'] or '' table = 'table' in kwargs and ",table=%s" % kwargs['table'] or '' + cookie = 'cookie' in kwargs and ",cookie=%s" % kwargs['cookie'] or '' proto = 'proto' in kwargs and ",%s" % kwargs['proto'] or '' ip = ('nw_src' in kwargs or 'nw_dst' in kwargs) and ',ip' or '' - flow = (flow + in_port + dl_type + dl_src + dl_dst + + flow = (flow + cookie+ in_port + dl_type + dl_src + dl_dst + (ip or proto) + nw_src + nw_dst + table) return flow @@ -224,7 +243,9 @@ def del_port(bridge, port): def get_network_id_for_vif(vif_name): domain_id, device_id = vif_name[3:len(vif_name)].split(".") - dom_uuid = do_cmd([XE_PATH, "vm-list", "dom-id=%s" % domain_id, "--minimal"]) + hostname = do_cmd(["/bin/bash", "-c", "hostname"]) + this_host_uuid = do_cmd([XE_PATH, "host-list", "hostname=%s" % hostname, "--minimal"]) + dom_uuid = do_cmd([XE_PATH, "vm-list", "dom-id=%s" % domain_id, "resident-on=%s" %this_host_uuid, "--minimal"]) vif_uuid = do_cmd([XE_PATH, "vif-list", "vm-uuid=%s" % dom_uuid, "device=%s" % device_id, "--minimal"]) vnet = do_cmd([XE_PATH, "vif-param-get", "uuid=%s" % vif_uuid, "param-name=other-config", "param-key=cloudstack-network-id"]) @@ -235,11 +256,14 @@ def get_network_id_for_tunnel_port(tunnelif_name): return vnet def clear_flooding_rules_for_port(bridge, ofport): - del_flows(bridge, in_port=ofport, table=2) + del_flows(bridge, in_port=ofport, table=L2_FLOOD_TABLE) + +def clear_flooding_rules_for_all_ports(bridge): + del_flows(bridge, cookie=111, table=L2_FLOOD_TABLE) def add_flooding_rules_for_port(bridge, in_ofport, out_ofports): action = "".join("output:%s," %ofport for ofport in out_ofports)[:-1] - add_flow(bridge, priority=1100, in_port=in_ofport, table=2, actions=action) + add_flow(bridge, cookie=111, priority=1100, in_port=in_ofport, table=L2_FLOOD_TABLE, actions=action) def get_ofport_for_vif(vif_name): return do_cmd([VSCTL_PATH, "get", "interface", vif_name, "ofport"]) @@ -260,18 +284,18 @@ def get_vif_name_from_macaddress(macaddress): def add_mac_lookup_table_entry(bridge, mac_address, out_of_port): action = "output=%s" %out_of_port - add_flow(bridge, priority=1100, dl_dst=mac_address, table=1, actions=action) + add_flow(bridge, priority=1100, dl_dst=mac_address, table=L2_LOOKUP_TABLE, actions=action) def delete_mac_lookup_table_entry(bridge, mac_address): - del_flows(bridge, dl_dst=mac_address, table=1) + del_flows(bridge, dl_dst=mac_address, table=L2_LOOKUP_TABLE) def add_ip_lookup_table_entry(bridge, ip, dst_tier_gateway_mac, dst_vm_mac): - action_str = "mod_dl_src:%s" % dst_tier_gateway_mac + ",mod_dl_dst:%s" % dst_vm_mac + ",resubmit(,5)" - action_str = "table=4, ip, nw_dst=%s" % ip + ", actions=%s" %action_str + action_str = "mod_dl_src:%s" % dst_tier_gateway_mac + ",mod_dl_dst:%s" % dst_vm_mac + ",resubmit(,%s)"%INGRESS_ACL_TABLE + action_str = "table=%s"%L3_LOOKUP_TABLE + ", ip, nw_dst=%s" % ip + ", actions=%s" %action_str addflow = [OFCTL_PATH, "add-flow", bridge, action_str] do_cmd(addflow) -def get_vms_on_host(vpc, host_id): +def get_vpc_vms_on_host(vpc, host_id): all_vms = vpc.vms vms_on_host = [] for vm in all_vms: @@ -313,44 +337,198 @@ def __repr__(self): def __str__(self): return '{%s}' % str(', '.join('%s : %s' % (k, repr(v)) for (k, v) in self.__dict__.iteritems())) +def get_acl(vpcconfig, required_acl_id): + acls = vpcconfig.acls + for acl in acls: + if acl.id == required_acl_id: + return acl + return None -def configure_bridge_for_network_topology(bridge, this_host_id, json_config): - vpconfig = jsonLoader(json.loads(json_config)).vpc +def check_tunnel_exists(bridge, tunnel_name): + try: + res = do_cmd([VSCTL_PATH, "port-to-br", tunnel_name]) + return res == bridge + except: + return False + +def create_tunnel(bridge, remote_ip, gre_key, src_host, dst_host, network_uuid): + + logging.debug("Creating tunnel from host %s" %src_host + " to host %s" %dst_host + " with GRE key %s" %gre_key) + + res = check_switch() + if res != "SUCCESS": + logging.debug("Openvswitch running: NO") + return "FAILURE:%s" % res + + # We need to keep the name below 14 characters + # src and target are enough - consider a fixed length hash + name = "t%s-%s-%s" % (gre_key, src_host, dst_host) + + # Verify the xapi bridge to be created + # NOTE: Timeout should not be necessary anymore + wait = [VSCTL_PATH, "--timeout=30", "wait-until", "bridge", + bridge, "--", "get", "bridge", bridge, "name"] + res = do_cmd(wait) + if bridge not in res: + logging.debug("WARNING:Can't find bridge %s for creating " + + "tunnel!" % bridge) + return "FAILURE:NO_BRIDGE" + logging.debug("bridge %s for creating tunnel - VERIFIED" % bridge) + tunnel_setup = False + drop_flow_setup = False + try: + # Create a port and configure the tunnel interface for it + add_tunnel = [VSCTL_PATH, "add-port", bridge, + name, "--", "set", "interface", + name, "type=gre", "options:key=%s" % gre_key, + "options:remote_ip=%s" % remote_ip] + do_cmd(add_tunnel) + tunnel_setup = True + # verify port + verify_port = [VSCTL_PATH, "get", "port", name, "interfaces"] + res = do_cmd(verify_port) + # Expecting python-style list as output + iface_list = [] + if len(res) > 2: + iface_list = res.strip()[1:-1].split(',') + if len(iface_list) != 1: + logging.debug("WARNING: Unexpected output while verifying " + + "port %s on bridge %s" % (name, bridge)) + return "FAILURE:VERIFY_PORT_FAILED" + + # verify interface + iface_uuid = iface_list[0] + verify_interface_key = [VSCTL_PATH, "get", "interface", + iface_uuid, "options:key"] + verify_interface_ip = [VSCTL_PATH, "get", "interface", + iface_uuid, "options:remote_ip"] + + key_validation = do_cmd(verify_interface_key) + ip_validation = do_cmd(verify_interface_ip) + + if not gre_key in key_validation or not remote_ip in ip_validation: + logging.debug("WARNING: Unexpected output while verifying " + + "interface %s on bridge %s" % (name, bridge)) + return "FAILURE:VERIFY_INTERFACE_FAILED" + logging.debug("Tunnel interface validated:%s" % verify_interface_ip) + cmd_tun_ofport = [VSCTL_PATH, "get", "interface", + iface_uuid, "ofport"] + tun_ofport = do_cmd(cmd_tun_ofport) + # Ensure no trailing LF + if tun_ofport.endswith('\n'): + tun_ofport = tun_ofport[:-1] + # find xs network for this bridge, verify is used for ovs tunnel network + xs_nw_uuid = do_cmd([XE_PATH, "network-list", + "bridge=%s" % bridge, "--minimal"]) + ovs_tunnel_network = False + try: + ovs_tunnel_network = do_cmd([XE_PATH,"network-param-get", + "uuid=%s" % xs_nw_uuid, + "param-name=other-config", + "param-key=is-ovs-tun-network", "--minimal"]) + except: + pass + + ovs_vpc_distributed_vr_network = False + try: + ovs_vpc_distributed_vr_network = do_cmd([XE_PATH,"network-param-get", + "uuid=%s" % xs_nw_uuid, + "param-name=other-config", + "param-key=is-ovs-vpc-distributed-vr-network", "--minimal"]) + except: + pass + + if ovs_tunnel_network == 'True': + # add flow entryies for dropping broadcast coming in from gre tunnel + add_flow(bridge, priority=1000, in_port=tun_ofport, + dl_dst='ff:ff:ff:ff:ff:ff', actions='drop') + add_flow(bridge, priority=1000, in_port=tun_ofport, + nw_dst='224.0.0.0/24', actions='drop') + drop_flow_setup = True + logging.debug("Broadcast drop rules added") + + if ovs_vpc_distributed_vr_network == 'True': + # add flow rules for dropping broadcast coming in from tunnel ports + add_flow(bridge, priority=1000, in_port=tun_ofport, table=0, + dl_dst='ff:ff:ff:ff:ff:ff', actions='drop') + add_flow(bridge, priority=1000, in_port=tun_ofport, table=0, + nw_dst='224.0.0.0/24', actions='drop') + + # add flow rule to send the traffic from tunnel ports to L2 switching table only + add_flow(bridge, priority=1100, in_port=tun_ofport, table=0, actions='resubmit(,1)') + + # mark tunnel interface with network id for which this tunnel was created + do_cmd([VSCTL_PATH, "set", "interface", name, "options:cloudstack-network-id=%s" % network_uuid]) + update_flooding_rules_on_port_plug_unplug(bridge, name, 'online', network_uuid) + + logging.debug("Successfully created tunnel from host %s" %src_host + " to host %s" %dst_host + + " with GRE key %s" %gre_key) + return "SUCCESS:%s" % name + except: + logging.debug("An unexpected error occured. Rolling back") + if tunnel_setup: + logging.debug("Deleting GRE interface") + # Destroy GRE port and interface + del_port(bridge, name) + if drop_flow_setup: + # Delete flows + logging.debug("Deleting flow entries from GRE interface") + del_flows(bridge, in_port=tun_ofport) + # This will not cancel the original exception + raise +# Configures the bridge created for a VPC that is enabled for distributed routing. Management server sends VPC +# physical topology details (which VM from which tier running on which host etc). Based on the VPC physical topology L2 +# lookup table and L3 lookup tables are updated by this function. +def configure_vpc_bridge_for_network_topology(bridge, this_host_id, json_config, sequence_no): + + vpconfig = jsonLoader(json.loads(json_config)).vpc if vpconfig is None: - logging.debug("WARNING:Can't find VPC info in json config file") + logging.debug("WARNING:Can't find VPC topology information in the json configuration file") return "FAILURE:IMPROPER_JSON_CONFG_FILE" try: - # get the list of Vm's in the VPC from the JSON config - this_host_vms = get_vms_on_host(vpconfig, this_host_id) + if not os.path.exists('/var/run/cloud'): + os.makedirs('/var/run/cloud') + + # create a temporary file to store OpenFlow rules corresponding to L2 and L3 lookup table updates + ofspec_filename = "/var/run/cloud/" + bridge + sequence_no + ".ofspec" + ofspec = open(ofspec_filename, 'w+') + + # get the list of VM's in all the tiers of VPC running in this host from the JSON config + this_host_vms = get_vpc_vms_on_host(vpconfig, this_host_id) for vm in this_host_vms: for nic in vm.nics: mac_addr = nic.macaddress ip = nic.ipaddress vif_name = get_vif_name_from_macaddress(mac_addr) - of_port = get_ofport_for_vif(vif_name) - network = get_network_details(vpconfig, nic.networkuuid) - - # Add flow rule in L2 look up table, if the destination mac = MAC of the nic send packet on the found OFPORT - add_mac_lookup_table_entry(bridge, mac_addr, of_port) - - # Add flow rule in L3 look up table: if the destination IP = VM's IP then modify the packet - # to set DST MAC = VM's MAC, SRC MAC=tier gateway MAC and send to egress table - add_ip_lookup_table_entry(bridge, ip, network.gatewaymac, mac_addr) - - # Add flow entry to send with intra tier traffic from the NIC to L2 lookup path) - action_str = "table=0, in_port=%s," %of_port + " ip, nw_dst=%s," %network.cidr + " actions=resubmit(,1)" - addflow = [OFCTL_PATH, "add-flow", bridge, action_str] - do_cmd(addflow) - - #add flow entry to send inter-tier traffic from the NIC to egress ACL table(to L3 lookup path) - action_str = "table=0, in_port=%s," % of_port + " ip, dl_dst=%s," %network.gatewaymac +\ - "nw_dst=%s," %vpconfig.cidr + "actions=resubmit(,3)" - addflow = [OFCTL_PATH, "add-flow", bridge, action_str] - - do_cmd(addflow) + of_port = get_ofport_for_vif(vif_name) + network = get_network_details(vpconfig, nic.networkuuid) + + # Add OF rule in L2 look up table, if packet's destination mac matches MAC of the VM's nic + # then send packet on the found OFPORT + ofspec.write("table=%s" %L2_LOOKUP_TABLE + " priority=1100 dl_dst=%s " %mac_addr + + " actions=output:%s" %of_port + "\n") + + # Add OF rule in L3 look up table: if packet's destination IP matches VM's IP then modify the packet + # to set DST MAC = VM's MAC, SRC MAC= destination tier gateway MAC and send to egress table. This step + # emulates steps VPC virtual router would have done on the current host itself. + action_str = " mod_dl_src:%s"%network.gatewaymac + ",mod_dl_dst:%s" % mac_addr \ + + ",resubmit(,%s)"%INGRESS_ACL_TABLE + action_str = "table=%s"%L3_LOOKUP_TABLE + " ip nw_dst=%s"%ip + " actions=%s" %action_str + ofspec.write(action_str + "\n") + + # Add OF rule to send intra-tier traffic from this nic of the VM to L2 lookup path (L2 switching) + action_str = "table=%s" %CLASSIFIER_TABLE + " priority=1200 in_port=%s " %of_port + \ + " ip nw_dst=%s " %network.cidr + " actions=resubmit(,%s)" %L2_LOOKUP_TABLE + ofspec.write(action_str + "\n") + + # Add OF rule to send inter-tier traffic from this nic of the VM to egress ACL table(L3 lookup path) + action_str = "table=%s "%CLASSIFIER_TABLE + " priority=1100 in_port=%s " %of_port +\ + " ip dl_dst=%s " %network.gatewaymac + " nw_dst=%s " %vpconfig.cidr + \ + " actions=resubmit(,%s)" %EGRESS_ACL_TABLE + ofspec.write(action_str + "\n") # get the list of hosts on which VPC spans from the JSON config vpc_spanning_hosts = vpconfig.hosts @@ -358,7 +536,9 @@ def configure_bridge_for_network_topology(bridge, this_host_id, json_config): for host in vpc_spanning_hosts: if str(this_host_id) == str(host.hostid): continue - other_host_vms = get_vms_on_host(vpconfig, host.hostid) + + other_host_vms = get_vpc_vms_on_host(vpconfig, str(host.hostid)) + for vm in other_host_vms: for nic in vm.nics: mac_addr = nic.macaddress @@ -366,42 +546,78 @@ def configure_bridge_for_network_topology(bridge, this_host_id, json_config): network = get_network_details(vpconfig, nic.networkuuid) gre_key = network.grekey - # generate tunnel name from tunnel naming convention + # generate tunnel name as per the tunnel naming convention tunnel_name = "t%s-%s-%s" % (gre_key, this_host_id, host.hostid) + + # check if tunnel exists already, if not create a tunnel from this host to remote host + if not check_tunnel_exists(bridge, tunnel_name): + create_tunnel(bridge, str(host.ipaddress), str(gre_key), this_host_id, + host.hostid, network.networkuuid) + of_port = get_ofport_for_vif(tunnel_name) - # Add flow rule in L2 look up table, if the destination mac = MAC of the nic send packet tunnel port - add_mac_lookup_table_entry(bridge, mac_addr, of_port) + # Add flow rule in L2 look up table, if packet's destination mac matches MAC of the VM's nic + # on the remote host then send packet on the found OFPORT corresponding to the tunnel + ofspec.write("table=%s" %L2_LOOKUP_TABLE + " priority=1100 dl_dst=%s " %mac_addr + + " actions=output:%s" %of_port + "\n") - # Add flow tule in L3 look up table: if the destination IP = VM's IP then modify the packet - # set DST MAC = VM's MAC, SRC MAC=tier gateway MAC and send to egress table - add_ip_lookup_table_entry(bridge, ip, network.gatewaymac, mac_addr) + # Add flow rule in L3 look up table. if packet's destination IP matches VM's IP then modify the + # packet to set DST MAC = VM's MAC, SRC MAC=tier gateway MAC and send to ingress table. This step + # emulates steps VPC virtual router would have done on the current host itself. + action_str = "mod_dl_src:%s"%network.gatewaymac + ",mod_dl_dst:%s" % mac_addr + \ + ",resubmit(,%s)"%INGRESS_ACL_TABLE + action_str = "table=%s"%L3_LOOKUP_TABLE + " ip nw_dst=%s"%ip + " actions=%s" %action_str + ofspec.write(action_str + "\n") - return "SUCCESS: successfully configured bridge as per the VPC topology" - except: - logging.debug("An unexpected error occurred while configuring bridge as per VPC topology.") - raise + # add a default rule in L2_LOOKUP_TABLE to send unknown mac address to L2 flooding table + ofspec.write("table=%s "%L2_LOOKUP_TABLE + " priority=0 " + " actions=resubmit(,%s)"%L2_FLOOD_TABLE + "\n") -def get_acl(vpcconfig, required_acl_id): - acls = vpcconfig.acls - for acl in acls: - if acl.id == required_acl_id: - return acl - return None + # add a default rule in L3 lookup table to forward (unknown destination IP) packets to L2 lookup table. This + # is fallback option to send the packet to VPC VR, when routing can not be performed at the host + ofspec.write("table=%s "%L3_LOOKUP_TABLE + " priority=0 " + " actions=resubmit(,%s)"%L2_LOOKUP_TABLE + "\n") -def configure_ovs_bridge_for_routing_policies(bridge, json_config): - vpconfig = jsonLoader(json.loads(json_config)).vpc + # First flush current L2_LOOKUP_TABLE & L3_LOOKUP_TABLE before re-applying L2 & L3 lookup entries + del_flows(bridge, table=L2_LOOKUP_TABLE) + del_flows(bridge, table=L3_LOOKUP_TABLE) + + ofspec.seek(0) + logging.debug("Adding below flows rules in L2 & L3 lookup tables:\n" + ofspec.read()) + ofspec.close() + + # update bridge with the flow-rules for L2 lookup and L3 lookup in the file in one attempt + do_cmd([OFCTL_PATH, 'add-flows', bridge, ofspec_filename]) + + # now that we updated the bridge with flow rules close and delete the file. + os.remove(ofspec_filename) + + return "SUCCESS: successfully configured bridge as per the VPC topology update with sequence no: %s"%sequence_no + + except Exception,e: + error_message = "An unexpected error occurred while configuring bridge " + bridge + \ + " as per latest VPC topology update with sequence no: %s" %sequence_no + logging.debug(error_message + " due to " + str(e)) + if os.path.isfile(ofspec_filename): + os.remove(ofspec_filename) + raise error_message + +# Configures the bridge created for a VPC that is enabled for distributed firewall. Management server sends VPC routing +# policy (network ACL applied on the tiers etc) details. Based on the VPC routing policies ingress ACL table and +# egress ACL tables are updated by this function. +def configure_vpc_bridge_for_routing_policies(bridge, json_config, sequence_no): + vpconfig = jsonLoader(json.loads(json_config)).vpc if vpconfig is None: - logging.debug("WARNING:Can't find VPC info in json config file") + logging.debug("WARNING: Can't find VPC routing policies info in json config file") return "FAILURE:IMPROPER_JSON_CONFG_FILE" try: - # First flush current egress ACL's before re-applying the ACL's - del_flows(bridge, table=3) - egress_rules_added = False - ingress_rules_added = False + if not os.path.exists('/var/run/cloud'): + os.makedirs('/var/run/cloud') + + # create a temporary file to store OpenFlow rules corresponding to ingress and egress ACL table updates + ofspec_filename = "/var/run/cloud/" + bridge + sequence_no + ".ofspec" + ofspec = open(ofspec_filename, 'w+') tiers = vpconfig.tiers for tier in tiers: @@ -416,64 +632,239 @@ def configure_ovs_bridge_for_routing_policies(bridge, json_config): source_port_start = acl_item.sourceportstart source_port_end = acl_item.sourceportend protocol = acl_item.protocol + if protocol == "all": + protocol = "*" + elif protocol == "tcp": + protocol = "6" + elif protocol == "udp": + protocol == "17" + elif protocol == "icmp": + protocol == "1" source_cidrs = acl_item.sourcecidrs acl_priority = 1000 + number + if direction == "ingress": + matching_table = INGRESS_ACL_TABLE + resubmit_table = L2_LOOKUP_TABLE + elif direction == "egress": + matching_table = EGRESS_ACL_TABLE + resubmit_table = L3_LOOKUP_TABLE + for source_cidr in source_cidrs: - if direction is "ingress": - ingress_rules_added = True - - if source_port_start is None and source_port_end is None: - if action is "deny": - add_flow(bridge, priority= acl_priority, table=5, nw_src=source_cidr, nw_dst=tier_cidr, - nw_proto=protocol, actions='drop') - if action is "allow": - add_flow(bridge, priority= acl_priority,table=5, nw_src=source_cidr, nw_dst=tier_cidr, - nw_proto=protocol, actions='resubmit(,1)') - continue - - # add flow rule to do action (allow/deny) for flows where source IP of the packet is in - # source_cidr and destination ip is in tier_cidr - port = source_port_start - while (port < source_port_end): - if action is "deny": - add_flow(bridge, priority= acl_priority, table=5, nw_src=source_cidr, nw_dst=tier_cidr, tp_dst=port, - nw_proto=protocol, actions='drop') - if action is "allow": - add_flow(bridge, priority= acl_priority,table=5, nw_src=source_cidr, nw_dst=tier_cidr, tp_dst=port, - nw_proto=protocol, actions='resubmit(,1)') - port = port + 1 - - elif direction in "egress": - egress_rules_added = True - - if source_port_start is None and source_port_end is None: - if action is "deny": - add_flow(bridge, priority= acl_priority, table=3, nw_src=source_cidr, nw_dst=tier_cidr, - nw_proto=protocol, actions='drop') - if action is "allow": - add_flow(bridge, priority= acl_priority,table=3, nw_src=source_cidr, nw_dst=tier_cidr, - nw_proto=protocol, actions='resubmit(,1)') - continue - - # add flow rule to do action (allow/deny) for flows where destination IP of the packet is in - # source_cidr and source ip is in tier_cidr - port = source_port_start - while (port < source_port_end): - if action is "deny": - add_flow(bridge, priority= acl_priority, table=3, nw_src=tier_cidr, nw_dst=source_cidr, tp_dst=port, - nw_proto=protocol, actions='drop') - if action is "allow": - add_flow(bridge, priority= acl_priority, table=3, nw_src=tier_cidr, nw_dst=source_cidr, tp_dst=port, - nw_proto=protocol, actions='resubmit(,1)') - port = port + 1 - - if egress_rules_added is False: - # add a default rule in egress table to forward packet to L3 lookup table - add_flow(bridge, priority=0, table=3, actions='resubmit(,4)') - - if ingress_rules_added is False: - # add a default rule in egress table drop packets - add_flow(bridge, priority=0, table=5, actions='drop') - except: - logging.debug("An unexpected error occurred while configuring bridge as per VPC's routing policies.") - raise \ No newline at end of file + if source_port_start is None and source_port_end is None: + if source_cidr.startswith('0.0.0.0'): + if action == "deny": + if direction == "ingress": + ofspec.write("table=%s "%matching_table + " priority=%s " %acl_priority + " ip " + + " nw_dst=%s " %tier_cidr + " nw_proto=%s " %protocol + + " actions=drop" + "\n") + else: + ofspec.write("table=%s "%matching_table + " priority=%s " %acl_priority + " ip " + + " nw_src=%s " %tier_cidr + " nw_proto=%s " %protocol + + " actions=drop" + "\n") + if action == "allow": + if direction == "ingress": + ofspec.write("table=%s "%matching_table + " priority=%s " %acl_priority + " ip " + + " nw_dst=%s " %tier_cidr + " nw_proto=%s " %protocol + + " actions=resubmit(,%s)"%resubmit_table + "\n") + else: + ofspec.write("table=%s "%matching_table + " priority=%s " %acl_priority + " ip " + + " nw_src=%s " %tier_cidr + " nw_proto=%s " %protocol + + " actions=resubmit(,%s)"%resubmit_table + "\n") + else: + if action == "deny": + if direction == "ingress": + ofspec.write("table=%s "%matching_table + " priority=%s " %acl_priority + " ip " + + " nw_src=%s " %source_cidr + " nw_dst=%s " %tier_cidr + + " nw_proto=%s " %protocol + " actions=drop" + "\n") + else: + ofspec.write("table=%s "%matching_table + " priority=%s " %acl_priority + " ip " + + " nw_src=%s " %tier_cidr + " nw_dst=%s " %source_cidr + + " nw_proto=%s " %protocol + " actions=drop" + "\n") + if action == "allow": + if direction == "ingress": + ofspec.write("table=%s "%matching_table + " priority=%s " %acl_priority + " ip " + + " nw_src=%s "%source_cidr + " nw_dst=%s " %tier_cidr + + " nw_proto=%s " %protocol + + " actions=resubmit(,%s)"%resubmit_table + "\n") + else: + ofspec.write("table=%s "%matching_table + " priority=%s " %acl_priority + " ip " + + " nw_src=%s "%tier_cidr + " nw_dst=%s " %source_cidr + + " nw_proto=%s " %protocol + + " actions=resubmit(,%s)"%resubmit_table + "\n") + continue + + # add flow rule to do action (allow/deny) for flows where source IP of the packet is in + # source_cidr and destination ip is in tier_cidr + port = int(source_port_start) + while (port <= int(source_port_end)): + if source_cidr.startswith('0.0.0.0'): + if action == "deny": + if direction == "ingress": + ofspec.write("table=%s "%matching_table + " priority=%s " %acl_priority + " ip " + + " tp_dst=%s " %port + " nw_dst=%s " %tier_cidr + + " nw_proto=%s " %protocol + " actions=drop" + "\n") + else: + ofspec.write("table=%s "%matching_table + " priority=%s " %acl_priority + " ip " + + " tp_dst=%s " %port + " nw_src=%s " %tier_cidr + + " nw_proto=%s " %protocol + " actions=drop" + "\n") + if action == "allow": + if direction == "ingress": + ofspec.write("table=%s "%matching_table + " priority=%s " %acl_priority + " ip " + + " tp_dst=%s " %port + " nw_dst=%s " %tier_cidr + + " nw_proto=%s " %protocol + + " actions=resubmit(,%s)"%resubmit_table + "\n") + else: + ofspec.write("table=%s "%matching_table + " priority=%s " %acl_priority + " ip " + + " tp_dst=%s " %port + " nw_src=%s " %tier_cidr + + " nw_proto=%s " %protocol + + " actions=resubmit(,%s)"%resubmit_table + "\n") + else: + if action == "deny": + if direction == "ingress": + ofspec.write("table=%s "%matching_table + " priority=%s " %acl_priority + " ip " + + " tp_dst=%s " %port + " nw_src=%s " %source_cidr + + " nw_dst=%s " %tier_cidr + + " nw_proto=%s " %protocol + " actions=drop" + "\n") + else: + ofspec.write("table=%s "%matching_table + " priority=%s " %acl_priority + " ip " + + " tp_dst=%s " %port + " nw_src=%s " %tier_cidr + + " nw_dst=%s " %source_cidr + + " nw_proto=%s " %protocol + " actions=drop" + "\n") + if action == "allow": + if direction == "ingress": + ofspec.write("table=%s "%matching_table + " priority=%s " %acl_priority + " ip " + + " tp_dst=%s " %port + " nw_src=%s "%source_cidr + + " nw_dst=%s " %tier_cidr + + " nw_proto=%s " %protocol + + " actions=resubmit(,%s)"%resubmit_table + "\n") + else: + ofspec.write("table=%s "%matching_table + " priority=%s " %acl_priority + " ip " + + " tp_dst=%s " %port + " nw_src=%s "%tier_cidr + + " nw_dst=%s " %source_cidr + + " nw_proto=%s " %protocol + + " actions=resubmit(,%s)"%resubmit_table + "\n") + port = port + 1 + + # add a default rule in egress table to allow packets (so forward packet to L3 lookup table) + ofspec.write("table=%s " %EGRESS_ACL_TABLE + " priority=0 actions=resubmit(,%s)" %L3_LOOKUP_TABLE + "\n") + + # add a default rule in ingress table to drop packets + ofspec.write("table=%s " %INGRESS_ACL_TABLE + " priority=0 actions=drop" + "\n") + + # First flush current ingress and egress ACL's before re-applying the ACL's + del_flows(bridge, table=EGRESS_ACL_TABLE) + del_flows(bridge, table=INGRESS_ACL_TABLE) + + ofspec.seek(0) + logging.debug("Adding below flows rules Ingress & Egress ACL tables:\n" + ofspec.read()) + ofspec.close() + + # update bridge with the flow-rules for ingress and egress ACL's added in the file in one attempt + do_cmd([OFCTL_PATH, 'add-flows', bridge, ofspec_filename]) + + # now that we updated the bridge with flow rules delete the file. + os.remove(ofspec_filename) + + return "SUCCESS: successfully configured bridge as per the latest routing policies update with " \ + "sequence no: %s"%sequence_no + + except Exception,e: + error_message = "An unexpected error occurred while configuring bridge " + bridge + \ + " as per latest VPC's routing policy update with sequence number %s." %sequence_no + logging.debug(error_message + " due to " + str(e)) + if os.path.isfile(ofspec_filename): + os.remove(ofspec_filename) + raise error_message + +# configures bridge L2 flooding rules stored in table=2. Single bridge is used for all the tiers of VPC. So controlled +# flooding is required to restrict the broadcast to only to the ports (vifs and tunnel interfaces) in the tier. Also +# packets arrived from the tunnel ports should not be flooded on the other tunnel ports. +def update_flooding_rules_on_port_plug_unplug(bridge, interface, command, if_network_id): + + class tier_ports: + tier_vif_ofports = [] + tier_tunnelif_ofports = [] + tier_all_ofports = [] + + logging.debug("Updating the flooding rules on bridge " + bridge + " as interface %s" %interface + + " is %s"%command + " now.") + try: + + if not os.path.exists('/var/run/cloud'): + os.makedirs('/var/run/cloud') + + # create a temporary file to store OpenFlow rules corresponding L2 flooding table + ofspec_filename = "/var/run/cloud/" + bridge + "-" +interface + "-" + command + ".ofspec" + ofspec = open(ofspec_filename, 'w+') + + all_tiers = dict() + + vsctl_output = do_cmd([VSCTL_PATH, 'list-ports', bridge]) + ports = vsctl_output.split('\n') + + for port in ports: + + if_ofport = do_cmd([VSCTL_PATH, 'get', 'Interface', port, 'ofport']) + + if port.startswith('vif'): + network_id = get_network_id_for_vif(port) + if network_id not in all_tiers.keys(): + all_tiers[network_id] = tier_ports() + tier_ports_info = all_tiers[network_id] + tier_ports_info.tier_vif_ofports.append(if_ofport) + tier_ports_info.tier_all_ofports.append(if_ofport) + all_tiers[network_id] = tier_ports_info + + if port.startswith('t'): + network_id = get_network_id_for_tunnel_port(port)[1:-1] + if network_id not in all_tiers.keys(): + all_tiers[network_id] = tier_ports() + tier_ports_info = all_tiers[network_id] + tier_ports_info.tier_tunnelif_ofports.append(if_ofport) + tier_ports_info.tier_all_ofports.append(if_ofport) + all_tiers[network_id] = tier_ports_info + + for network_id, tier_ports_info in all_tiers.items(): + if len(tier_ports_info.tier_all_ofports) == 1 : + continue + + # for a packet arrived from tunnel port, flood only on to VIF ports connected to bridge for this tier + for port in tier_ports_info.tier_tunnelif_ofports: + action = "".join("output:%s," %ofport for ofport in tier_ports_info.tier_vif_ofports)[:-1] + ofspec.write("table=%s " %L2_FLOOD_TABLE + " priority=1100 in_port=%s " %port + + "actions=%s " %action + "\n") + + # for a packet arrived from VIF port send on all VIF and tunnel ports corresponding to the tier excluding + # the port on which packet arrived + for port in tier_ports_info.tier_vif_ofports: + tier_all_ofports_copy = copy.copy(tier_ports_info.tier_all_ofports) + tier_all_ofports_copy.remove(port) + action = "".join("output:%s," %ofport for ofport in tier_all_ofports_copy)[:-1] + ofspec.write("table=%s " %L2_FLOOD_TABLE + " priority=1100 in_port=%s " %port + + "actions=%s " %action + "\n") + + # add a default rule in L2 flood table to drop packet + ofspec.write("table=%s " %L2_FLOOD_TABLE + " priority=0 actions=drop") + + # First flush current L2 flooding table before re-populating the tables + del_flows(bridge, table=L2_FLOOD_TABLE) + + ofspec.seek(0) + logging.debug("Adding below flows rules L2 flooding table: \n" + ofspec.read()) + ofspec.close() + + # update bridge with the flow-rules for broadcast rules added in the file in one attempt + do_cmd([OFCTL_PATH, 'add-flows', bridge, ofspec_filename]) + + # now that we updated the bridge with flow rules delete the file. + os.remove(ofspec_filename) + + logging.debug("successfully configured bridge %s as per the latest flooding rules " %bridge) + + except Exception,e: + if os.path.isfile(ofspec_filename): + os.remove(ofspec_filename) + error_message = "An unexpected error occurred while updating the flooding rules for the bridge " + \ + bridge + " when interface " + " %s" %interface + " is %s" %command + logging.debug(error_message + " due to " + str(e)) + raise error_message \ No newline at end of file diff --git a/scripts/vm/hypervisor/xenserver/hostvmstats.py b/scripts/vm/hypervisor/xenserver/hostvmstats.py deleted file mode 100644 index 61cf2de99f..0000000000 --- a/scripts/vm/hypervisor/xenserver/hostvmstats.py +++ /dev/null @@ -1,61 +0,0 @@ -#!/usr/bin/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. -# $Id: hostvmstats.py 10054 2010-06-29 22:09:31Z abhishek $ $HeadURL: svn://svn.lab.vmops.com/repos/vmdev/java/scripts/vm/hypervisor/xenserver/hostvmstats.py $ - -import XenAPI -import urllib -import time -import logging -import logging.handlers - -LOG_FILENAME = '/tmp/xapilog' -logging.basicConfig(filename=LOG_FILENAME,level=logging.DEBUG) -stats_logger = logging.getLogger('statsLogger') -stats_logger.setLevel(logging.DEBUG) - -#handler with maxBytes=10MiB -handler = logging.handlers.RotatingFileHandler(LOG_FILENAME, maxBytes=10*1024*1024, backupCount=5) -stats_logger.addHandler(handler) - -def get_stats(session, collect_host_stats, consolidation_function, interval, start_time): - try: - - if collect_host_stats == "true" : - url = "http://localhost/rrd_updates?" - url += "session_id=" + session._session - url += "&host=" + collect_host_stats - url += "&cf=" + consolidation_function - url += "&interval=" + str(interval) - url += "&start=" + str(int(time.time())-100) - else : - url = "http://localhost/rrd_updates?" - url += "session_id=" + session._session - url += "&host=" + collect_host_stats - url += "&cf=" + consolidation_function - url += "&interval=" + str(interval) - url += "&start=" + str(int(time.time())-100) - - stats_logger.debug("Calling URL: %s",url) - sock = urllib.URLopener().open(url) - xml = sock.read() - sock.close() - stats_logger.debug("Size of returned XML: %s",len(xml)) - return xml - except Exception,e: - stats_logger.exception("get_stats() failed") - raise diff --git a/scripts/vm/hypervisor/xenserver/ovs-vif-flows.py b/scripts/vm/hypervisor/xenserver/ovs-vif-flows.py index 1445d940ef..ba5f41a5d5 100644 --- a/scripts/vm/hypervisor/xenserver/ovs-vif-flows.py +++ b/scripts/vm/hypervisor/xenserver/ovs-vif-flows.py @@ -15,8 +15,8 @@ # specific language governing permissions and limitations # under the License. -# A simple script for enabling and disabling per-vif rules for explicitly -# allowing broadcast/multicast traffic on the port where the VIF is attached +# A simple script for enabling and disabling per-vif and tunnel interface rules for explicitly +# allowing broadcast/multicast traffic from the tunnel ports and on the port where the VIF is attached import copy import os @@ -28,9 +28,11 @@ pluginlib.setup_logging("/var/log/cloud/ovstunnel.log") def clear_flows(bridge, this_vif_ofport, vif_ofports): + action = "".join("output:%s," %ofport + for ofport in vif_ofports)[:-1] # Remove flow entries originating from given ofport pluginlib.del_flows(bridge, in_port=this_vif_ofport) - # The following will remove the port being delete from actions + # The following will remove the port being delete from actions pluginlib.add_flow(bridge, priority=1100, dl_dst='ff:ff:ff:ff:ff:ff', actions=action) pluginlib.add_flow(bridge, priority=1100, @@ -40,7 +42,7 @@ def clear_flows(bridge, this_vif_ofport, vif_ofports): def apply_flows(bridge, this_vif_ofport, vif_ofports): action = "".join("output:%s," %ofport for ofport in vif_ofports)[:-1] - # Ensure {b|m}casts sent from VIF ports are always allowed + # Ensure {b|m}casts sent from VIF ports are always allowed pluginlib.add_flow(bridge, priority=1200, in_port=this_vif_ofport, dl_dst='ff:ff:ff:ff:ff:ff', @@ -49,7 +51,7 @@ def apply_flows(bridge, this_vif_ofport, vif_ofports): in_port=this_vif_ofport, nw_dst='224.0.0.0/24', actions='NORMAL') - # Ensure {b|m}casts are always propagated to VIF ports + # Ensure {b|m}casts are always propagated to VIF ports pluginlib.add_flow(bridge, priority=1100, dl_dst='ff:ff:ff:ff:ff:ff', actions=action) pluginlib.add_flow(bridge, priority=1100, @@ -102,7 +104,7 @@ def main(command, vif_raw): ovs_vpc_distributed_vr_network = pluginlib.do_cmd([pluginlib.XE_PATH,"network-param-get", "uuid=%s" % xs_nw_uuid, "param-name=other-config", - "param-key=is-ovs_vpc_distributed_vr_network", "--minimal"]) + "param-key=is-ovs-vpc-distributed-vr-network", "--minimal"]) except: pass @@ -116,6 +118,7 @@ def main(command, vif_raw): 'list-ports', bridge]) vifs = vsctl_output.split('\n') vif_ofports = [] + vif_other_ofports = [] for vif in vifs: vif_ofport = pluginlib.do_cmd([pluginlib.VSCTL_PATH, 'get', 'Interface', vif, 'ofport']) @@ -125,82 +128,23 @@ def main(command, vif_raw): vif_ofports.append(vif_ofport) if command == 'offline': - clear_flows(bridge, this_vif_ofport, vif_ofports) + vif_other_ofports = copy.copy(vif_ofports) + vif_other_ofports.remove(this_vif_ofport) + clear_flows(bridge, this_vif_ofport, vif_other_ofports) if command == 'online': apply_flows(bridge, this_vif_ofport, vif_ofports) - # handle case where brdige is setup for VPC and VPC is enabled for distributed routing + # handle case where bridge is setup for VPC which is enabled for distributed routing if ovs_vpc_distributed_vr_network == 'True': vlan = pluginlib.do_cmd([pluginlib.VSCTL_PATH, 'br-to-vlan', bridge]) if vlan != '0': # We need the REAL bridge name bridge = pluginlib.do_cmd([pluginlib.VSCTL_PATH, 'br-to-parent', bridge]) - vsctl_output = pluginlib.do_cmd([pluginlib.VSCTL_PATH, - 'list-ports', bridge]) vif_network_id = pluginlib.get_network_id_for_vif(this_vif) - vnet_vif_ofports = [] - vnet_tunnelif_ofports = [] - vnet_all_ofports = [] - - ports = vsctl_output.split('\n') - for port in ports: - if_ofport = pluginlib.do_cmd([pluginlib.VSCTL_PATH, 'get', 'Interface', port, 'ofport']) - if port.startswith('vif'): - # check VIF is in same network as that of plugged vif - if vif_network_id != pluginlib.get_network_id_for_vif(port): - continue - vnet_vif_ofports.append(if_ofport) - vnet_all_ofports.append(if_ofport) - - if port.startswith('t'): - # check tunnel port is in same network as that of plugged vif - if vif_network_id != pluginlib.get_network_id_for_tunnel_port(port): - continue - vnet_tunnelif_ofports.append(if_ofport) - vnet_all_ofports.append(if_ofport) - - if command == 'online': - for port in vnet_all_ofports: - pluginlib.clear_flooding_rules_for_port(bridge, port) - - # for a packet arrived from tunnel port, flood only on VIF ports - for port in vnet_tunnelif_ofports: - pluginlib.add_flooding_rules_for_port(bridge, port, vnet_vif_ofports) - - # for a packet arrived from VIF port send on all VIF and tunnel port excluding the port - # on which packet arrived - for port in vnet_vif_ofports: - vnet_all_ofports_copy = copy.copy(vnet_all_ofports) - vnet_all_ofports_copy.remove(port) - pluginlib.add_flooding_rules_for_port(bridge, port, vnet_all_ofports_copy) - - #learn that MAC is reachable through the VIF port - mac = pluginlib.get_macaddress_of_vif(this_vif) - this_vif_ofport = pluginlib.do_cmd([pluginlib.VSCTL_PATH, 'get', 'Interface', this_vif, 'ofport']) - pluginlib.add_mac_lookup_table_entry(bridge, mac, this_vif_ofport) - - if command == 'offline': - for port in vnet_all_ofports: - pluginlib.clear_flooding_rules_for_port(bridge, port) - vnet_all_ofports.remove(this_vif_ofport) - vnet_vif_ofports.remove(this_vif_ofport) - - # for a packet arrived from tunnel port, flood only on VIF ports - for port in vnet_tunnelif_ofports: - pluginlib.add_flooding_rules_for_port(bridge, port, vnet_vif_ofports) - - # for a packet from VIF port send on all VIF's and tunnel ports excluding the port on which packet arrived - for port in vnet_vif_ofports: - vnet_all_ofports_copy = copy.copy(vnet_all_ofports) - vnet_all_ofports_copy.remove(port) - pluginlib.add_flooding_rules_for_port(bridge, port, vnet_all_ofports_copy) - - #un-learn that MAC is reachable through the VIF port - mac = pluginlib.get_macaddress_of_vif(this_vif) - pluginlib.delete_mac_lookup_table_entry(bridge, mac) + pluginlib.update_flooding_rules_on_port_plug_unplug(bridge, this_vif, command, vif_network_id) return diff --git a/scripts/vm/hypervisor/xenserver/ovstunnel b/scripts/vm/hypervisor/xenserver/ovstunnel index 98a9d0b82f..0ae99f595b 100755 --- a/scripts/vm/hypervisor/xenserver/ovstunnel +++ b/scripts/vm/hypervisor/xenserver/ovstunnel @@ -37,7 +37,6 @@ from time import localtime as _localtime, asctime as _asctime xePath = "/opt/xensource/bin/xe" lib.setup_logging("/var/log/cloud/ovstunnel.log") - def block_ipv6_v5(bridge): lib.add_flow(bridge, priority=65000, dl_type='0x86dd', actions='drop') @@ -97,16 +96,16 @@ def setup_ovs_bridge(session, args): result = "SUCCESS:%s" % bridge else: result = "FAILURE:%s" % res + lib.do_cmd([lib.XE_PATH, "network-param-set", "uuid=%s" % xs_nw_uuid, + "other-config:is-ovs-tun-network=True"]) # Finally note in the xenapi network object that the network has # been configured xs_nw_uuid = lib.do_cmd([lib.XE_PATH, "network-list", "bridge=%s" % bridge, "--minimal"]) - lib.do_cmd([lib.XE_PATH, "network-param-set", "uuid=%s" % xs_nw_uuid, - "other-config:is-ovs-tun-network=True"]) conf_hosts = lib.do_cmd([lib.XE_PATH, "network-param-get", "uuid=%s" % xs_nw_uuid, "param-name=other-config", - "param-key=ovs-host-setup", "--minimal"]) + "param-key=ovs-host-setup"]) conf_hosts = cs_host_id + (conf_hosts and ',%s' % conf_hosts or '') lib.do_cmd([lib.XE_PATH, "network-param-set", "uuid=%s" % xs_nw_uuid, "other-config:ovs-host-setup=%s" % conf_hosts]) @@ -124,6 +123,7 @@ def setup_ovs_bridge(session, args): logging.debug("Setup_ovs_bridge completed with result:%s" % result) return result + @echo def setup_ovs_bridge_for_distributed_routing(session, args): bridge = args.pop("bridge") @@ -156,36 +156,45 @@ def setup_ovs_bridge_for_distributed_routing(session, args): xs_nw_uuid = lib.do_cmd([lib.XE_PATH, "network-list", "bridge=%s" % bridge, "--minimal"]) lib.do_cmd([lib.XE_PATH, "network-param-set", "uuid=%s" % xs_nw_uuid, - "other-config:is-ovs_vpc_distributed_vr_network=True"]) + "other-config:is-ovs-vpc-distributed-vr-network=True"]) conf_hosts = lib.do_cmd([lib.XE_PATH, "network-param-get", "uuid=%s" % xs_nw_uuid, "param-name=other-config", - "param-key=ovs-host-setup", "--minimal"]) + "param-key=ovs-host-setup"]) conf_hosts = cs_host_id + (conf_hosts and ',%s' % conf_hosts or '') lib.do_cmd([lib.XE_PATH, "network-param-set", "uuid=%s" % xs_nw_uuid, "other-config:ovs-host-setup=%s" % conf_hosts]) + # first clear the default rule (rule for 'NORMAL' processing which makes a bridge simple L2 learn & flood switch) + lib.del_flows(bridge, table=0) + # add a default flow rule to send broadcast and multi-cast packets to L2 flooding table - lib.add_flow(bridge, priority=1000, dl_dst='ff:ff:ff:ff:ff:ff', table=0, actions='resubmit(,2)') - lib.add_flow(bridge, priority=1000, nw_dst='224.0.0.0/24', table=0, actions='resubmit(,2)') + lib.add_flow(bridge, priority=1200, dl_dst='ff:ff:ff:ff:ff:ff', table=lib.CLASSIFIER_TABLE, + actions='resubmit(,%s)'%lib.L2_FLOOD_TABLE) + lib.add_flow(bridge, priority=1200, nw_dst='224.0.0.0/24', table=lib.CLASSIFIER_TABLE, + actions='resubmit(,%s)'%lib.L2_FLOOD_TABLE) # add a default flow rule to send uni-cast traffic to L2 lookup table - lib.add_flow(bridge, priority=0, table=0, actions='resubmit(,1)') + lib.add_flow(bridge, priority=0, table=lib.CLASSIFIER_TABLE, actions='resubmit(,%s)'%lib.L2_LOOKUP_TABLE) # add a default rule to send unknown mac address to L2 flooding table - lib.add_flow(bridge, priority=0, table=1, actions='resubmit(,2)') + lib.add_flow(bridge, priority=0, table=lib.L2_LOOKUP_TABLE, actions='resubmit(,%s)'%lib.L2_FLOOD_TABLE) # add a default rule in L2 flood table to drop packet - lib.add_flow(bridge, priority=0, table=2, actions='drop') + lib.add_flow(bridge, priority=0, table=lib.L2_FLOOD_TABLE, actions='drop') - # add a default rule in egress table to forward packet to L3 lookup table - lib.add_flow(bridge, priority=0, table=3, actions='resubmit(,4)') + # add a default rule in egress ACL table to forward packet to L3 lookup table + lib.add_flow(bridge, priority=0, table=lib.EGRESS_ACL_TABLE, actions='resubmit(,%s)'%lib.L3_LOOKUP_TABLE) # add a default rule in L3 lookup table to forward packet to L2 lookup table - lib.add_flow(bridge, priority=0, table=4, actions='resubmit(,1)') + lib.add_flow(bridge, priority=0, table=lib.L3_LOOKUP_TABLE, actions='resubmit(,%s)'%lib.L2_LOOKUP_TABLE) # add a default rule in ingress table to drop in bound packets - lib.add_flow(bridge, priority=0, table=5, actions='drop') + lib.add_flow(bridge, priority=0, table=lib.INGRESS_ACL_TABLE, actions='drop') + + # initialize the sequence number for the bridge + lib.do_cmd([lib.VSCTL_PATH, "set", "bridge", bridge, "other-config:topology-update-sequence-number=0"]) + lib.do_cmd([lib.VSCTL_PATH, "set", "bridge", bridge, "other-config:route-policy-update-sequence-number=0"]) result = "SUCCESS: successfully setup bridge with flow rules" @@ -195,6 +204,7 @@ def setup_ovs_bridge_for_distributed_routing(session, args): @echo def destroy_ovs_bridge(session, args): bridge = args.pop("bridge") + this_host_id = args.pop("cs_host_id") res = lib.check_switch() if res != "SUCCESS": return res @@ -204,11 +214,21 @@ def destroy_ovs_bridge(session, args): result = "FAILURE:%s" % res else: # Note that the bridge has been removed on xapi network object - xs_nw_uuid = lib.do_cmd([xePath, "network-list", + xs_nw_uuid = lib.do_cmd([lib.XE_PATH, "network-list", "bridge=%s" % bridge, "--minimal"]) - #FIXME: WOW, this an error - #lib.do_cmd([xePath,"network-param-set", "uuid=%s" % xs_nw_uuid, - # "other-config:ovs-setup=False"]) + conf_hosts = lib.do_cmd([lib.XE_PATH, "network-param-get", + "uuid=%s" % xs_nw_uuid, + "param-name=other-config", + "param-key=ovs-host-setup"]) + new_conf_hosts = "" + hosts = conf_hosts.split(',') + for host in hosts: + if str(host) == str(this_host_id): + continue + new_conf_hosts = host + "," + new_conf_hosts + new_conf_hosts = new_conf_hosts[:-1] + lib.do_cmd([lib.XE_PATH, "network-param-set", "uuid=%s" % xs_nw_uuid, + "other-config:ovs-host-setup=%s" % new_conf_hosts]) result = "SUCCESS:%s" % bridge logging.debug("Destroy_ovs_bridge completed with result:%s" % result) @@ -224,115 +244,7 @@ def create_tunnel(session, args): dst_host = args.pop("to") network_uuid = args.pop("cloudstack-network-id") - logging.debug("Entering create_tunnel") - - res = lib.check_switch() - if res != "SUCCESS": - logging.debug("Openvswitch running: NO") - return "FAILURE:%s" % res - - # We need to keep the name below 14 characters - # src and target are enough - consider a fixed length hash - name = "t%s-%s-%s" % (gre_key, src_host, dst_host) - - # Verify the xapi bridge to be created - # NOTE: Timeout should not be necessary anymore - wait = [lib.VSCTL_PATH, "--timeout=30", "wait-until", "bridge", - bridge, "--", "get", "bridge", bridge, "name"] - res = lib.do_cmd(wait) - if bridge not in res: - logging.debug("WARNING:Can't find bridge %s for creating " + - "tunnel!" % bridge) - return "FAILURE:NO_BRIDGE" - logging.debug("bridge %s for creating tunnel - VERIFIED" % bridge) - tunnel_setup = False - drop_flow_setup = False - try: - # Create a port and configure the tunnel interface for it - add_tunnel = [lib.VSCTL_PATH, "add-port", bridge, - name, "--", "set", "interface", - name, "type=gre", "options:key=%s" % gre_key, - "options:remote_ip=%s" % remote_ip] - lib.do_cmd(add_tunnel) - tunnel_setup = True - # verify port - verify_port = [lib.VSCTL_PATH, "get", "port", name, "interfaces"] - res = lib.do_cmd(verify_port) - # Expecting python-style list as output - iface_list = [] - if len(res) > 2: - iface_list = res.strip()[1:-1].split(',') - if len(iface_list) != 1: - logging.debug("WARNING: Unexpected output while verifying " + - "port %s on bridge %s" % (name, bridge)) - return "FAILURE:VERIFY_PORT_FAILED" - - # verify interface - iface_uuid = iface_list[0] - verify_interface_key = [lib.VSCTL_PATH, "get", "interface", - iface_uuid, "options:key"] - verify_interface_ip = [lib.VSCTL_PATH, "get", "interface", - iface_uuid, "options:remote_ip"] - - key_validation = lib.do_cmd(verify_interface_key) - ip_validation = lib.do_cmd(verify_interface_ip) - - if not gre_key in key_validation or not remote_ip in ip_validation: - logging.debug("WARNING: Unexpected output while verifying " + - "interface %s on bridge %s" % (name, bridge)) - return "FAILURE:VERIFY_INTERFACE_FAILED" - logging.debug("Tunnel interface validated:%s" % verify_interface_ip) - cmd_tun_ofport = [lib.VSCTL_PATH, "get", "interface", - iface_uuid, "ofport"] - tun_ofport = lib.do_cmd(cmd_tun_ofport) - # Ensure no trailing LF - if tun_ofport.endswith('\n'): - tun_ofport = tun_ofport[:-1] - # find xs network for this bridge, verify is used for ovs tunnel network - xs_nw_uuid = lib.do_cmd([lib.XE_PATH, "network-list", - "bridge=%s" % bridge, "--minimal"]) - ovs_tunnel_network = lib.do_cmd([lib.XE_PATH,"network-param-get", - "uuid=%s" % xs_nw_uuid, - "param-name=other-config", - "param-key=is-ovs-tun-network", "--minimal"]) - ovs_vpc_distributed_vr_network = lib.do_cmd([lib.XE_PATH,"network-param-get", - "uuid=%s" % xs_nw_uuid, - "param-name=other-config", - "param-key=is-ovs_vpc_distributed_vr_network", "--minimal"]) - if ovs_tunnel_network == 'True': - # add flow entryies for dropping broadcast coming in from gre tunnel - lib.add_flow(bridge, priority=1000, in_port=tun_ofport, - dl_dst='ff:ff:ff:ff:ff:ff', actions='drop') - lib.add_flow(bridge, priority=1000, in_port=tun_ofport, - nw_dst='224.0.0.0/24', actions='drop') - drop_flow_setup = True - logging.debug("Broadcast drop rules added") - - if ovs_vpc_distributed_vr_network == 'True': - # add flow rules for dropping broadcast coming in from tunnel ports - lib.add_flow(bridge, priority=1000, in_port=tun_ofport, table=0, - dl_dst='ff:ff:ff:ff:ff:ff', actions='drop') - lib.add_flow(bridge, priority=1000, in_port=tun_ofport, table=0, - nw_dst='224.0.0.0/24', actions='drop') - - # add flow rule to send the traffic from tunnel ports to L2 switching table only - lib.add_flow(bridge, priority=1000, in_port=tun_ofport, table=0, actions='resubmit(,1)') - lib.do_cmd([lib.VSCTL_PATH, "set", "interface", name, "options:cloudstack-network-id=%s" % network_uuid]) - - return "SUCCESS:%s" % name - except: - logging.debug("An unexpected error occured. Rolling back") - if tunnel_setup: - logging.debug("Deleting GRE interface") - # Destroy GRE port and interface - lib.del_port(bridge, name) - if drop_flow_setup: - # Delete flows - logging.debug("Deleting flow entries from GRE interface") - lib.del_flows(bridge, in_port=tun_ofport) - # This will not cancel the original exception - raise - + return lib.create_tunnel(bridge, remote_ip, gre_key, src_host, dst_host, network_uuid) @echo def destroy_tunnel(session, args): @@ -390,15 +302,36 @@ def configure_ovs_bridge_for_network_topology(session, args): bridge = args.pop("bridge") json_config = args.pop("config") this_host_id = args.pop("host-id") - - return lib.configure_bridge_for_network_topology(bridge, this_host_id, json_config) + sequence_no = args.pop("seq-no") + + # get the last update sequence number + last_seq_no = lib.do_cmd([lib.VSCTL_PATH, "get", "bridge", bridge, "other-config:topology-update-sequence-number"]) + last_seq_no = last_seq_no[1:-1] + if long(sequence_no) > long(last_seq_no): + lib.do_cmd([lib.VSCTL_PATH, "set", "bridge", bridge, + "other-config:topology-update-sequence-number=%s"%sequence_no]) + return lib.configure_vpc_bridge_for_network_topology(bridge, this_host_id, json_config, sequence_no) + else: + return "SUCCESS: Ignoring the update with the sequence number %s" %sequence_no + " as there is already recent" \ + " update received and applied with sequence number %s" %last_seq_no @echo def configure_ovs_bridge_for_routing_policies(session, args): bridge = args.pop("bridge") json_config = args.pop("config") - - return lib.configure_ovs_bridge_for_router_policies(bridge, json_config) + sequence_no = args.pop("seq-no") + + # get the last update sequence number + last_seq_no = lib.do_cmd([lib.VSCTL_PATH, "get", "bridge", bridge, + "other-config:route-policy-update-sequence-number"]) + last_seq_no = last_seq_no[1:-1] + if long(sequence_no) > long(last_seq_no): + lib.do_cmd([lib.VSCTL_PATH, "set", "bridge", bridge, + "other-config:route-policy-update-sequence-number=%s"%sequence_no]) + return lib.configure_vpc_bridge_for_routing_policies(bridge, json_config, sequence_no) + else: + return "SUCCESS: Ignoring the update with the sequence number %s" %sequence_no + " as there is already recent" \ + " update received and applied with sequence number %s" %last_seq_no if __name__ == "__main__": XenAPIPlugin.dispatch({"create_tunnel": create_tunnel, @@ -409,4 +342,4 @@ if __name__ == "__main__": "getLabel": getLabel, "setup_ovs_bridge_for_distributed_routing": setup_ovs_bridge_for_distributed_routing, "configure_ovs_bridge_for_network_topology": configure_ovs_bridge_for_network_topology, - "configure_ovs_bridge_for_routing_policies": "configure_ovs_bridge_for_routing_policies"}) + "configure_ovs_bridge_for_routing_policies": configure_ovs_bridge_for_routing_policies}) \ No newline at end of file diff --git a/scripts/vm/hypervisor/xenserver/vmops b/scripts/vm/hypervisor/xenserver/vmops index 4174ef24f7..3f25a2e7f9 100755 --- a/scripts/vm/hypervisor/xenserver/vmops +++ b/scripts/vm/hypervisor/xenserver/vmops @@ -27,7 +27,6 @@ if os.path.exists("/opt/xensource/sm"): if os.path.exists("/usr/lib/xcp/sm"): sys.path.extend(["/usr/lib/xcp/sm/", "/usr/local/sbin/", "/sbin/"]) import base64 -import hostvmstats import socket import stat import tempfile @@ -61,15 +60,6 @@ def add_to_VCPUs_params_live(session, args): return 'false' return 'true' -@echo -def gethostvmstats(session, args): - collect_host_stats = args['collectHostStats'] - consolidation_function = args['consolidationFunction'] - interval = args['interval'] - start_time = args['startTime'] - result = hostvmstats.get_stats(session, collect_host_stats, consolidation_function, interval, start_time) - return result - @echo def setup_iscsi(session, args): uuid=args['uuid'] @@ -207,20 +197,6 @@ def setLinkLocalIP(session, args): txt = 'success' return txt -@echo -def routerProxy(session, args): - sargs = args['args'] - cmd = sargs.split(' ') - cmd.insert(0, "/opt/cloud/bin/router_proxy.sh") - cmd.insert(0, "/bin/bash") - try: - txt = util.pread2(cmd) - txt = 'succ#' + txt - except: - logging.debug("routerProxy command " + sargs + " failed " ) - txt = 'fail#' + txt - return txt - @echo def createFile(session, args): file_path = args['filepath'] @@ -1502,10 +1478,9 @@ def network_rules(session, args): logging.debug("Failed to network rule !") if __name__ == "__main__": - XenAPIPlugin.dispatch({"pingtest": pingtest, "setup_iscsi":setup_iscsi, "gethostvmstats": gethostvmstats, + XenAPIPlugin.dispatch({"pingtest": pingtest, "setup_iscsi":setup_iscsi, "getgateway": getgateway, "preparemigration": preparemigration, "setIptables": setIptables, "pingdomr": pingdomr, "pingxenserver": pingxenserver, - "routerProxy": routerProxy, "createFile": createFile, "deleteFile": deleteFile, "network_rules":network_rules, "can_bridge_firewall":can_bridge_firewall, "default_network_rules":default_network_rules, diff --git a/scripts/vm/hypervisor/xenserver/vmopspremium b/scripts/vm/hypervisor/xenserver/vmopspremium index 06b0a51f7e..2887436670 100755 --- a/scripts/vm/hypervisor/xenserver/vmopspremium +++ b/scripts/vm/hypervisor/xenserver/vmopspremium @@ -123,18 +123,7 @@ def setup_heartbeat_file(session, args): txt = '' return txt -@echo -def check_heartbeat(session, args): - host = args['host'] - interval = args['interval'] - try: - cmd = ["bash", "/opt/cloud/bin/check_heartbeat.sh", host, interval] - txt = util.pread2(cmd) - except: - txt='' - return txt - - + @echo def heartbeat(session, args): host = args['host'] @@ -156,5 +145,4 @@ def asmonitor(session, args): return 'fail' if __name__ == "__main__": - XenAPIPlugin.dispatch({"forceShutdownVM":forceShutdownVM, "upgrade_snapshot":upgrade_snapshot, "create_privatetemplate_from_snapshot":create_privatetemplate_from_snapshot, "copy_vhd_to_secondarystorage":copy_vhd_to_secondarystorage, "copy_vhd_from_secondarystorage":copy_vhd_from_secondarystorage, "setup_heartbeat_sr":setup_heartbeat_sr, "setup_heartbeat_file":setup_heartbeat_file, "check_heartbeat":check_heartbeat, "heartbeat": heartbeat, "asmonitor": asmonitor}) - + XenAPIPlugin.dispatch({"forceShutdownVM":forceShutdownVM, "upgrade_snapshot":upgrade_snapshot, "create_privatetemplate_from_snapshot":create_privatetemplate_from_snapshot, "copy_vhd_to_secondarystorage":copy_vhd_to_secondarystorage, "copy_vhd_from_secondarystorage":copy_vhd_from_secondarystorage, "setup_heartbeat_sr":setup_heartbeat_sr, "setup_heartbeat_file":setup_heartbeat_file, "heartbeat": heartbeat, "asmonitor": asmonitor}) diff --git a/scripts/vm/hypervisor/xenserver/xcposs/copy_vhd_from_secondarystorage.sh b/scripts/vm/hypervisor/xenserver/xcposs/copy_vhd_from_secondarystorage.sh new file mode 100755 index 0000000000..a4e977bdd5 --- /dev/null +++ b/scripts/vm/hypervisor/xenserver/xcposs/copy_vhd_from_secondarystorage.sh @@ -0,0 +1,188 @@ +#!/bin/bash +# 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. + +#set -x + +usage() { + printf "Usage: %s [vhd file in secondary storage] [uuid of the source sr] [name label] \n" $(basename $0) +} + +cleanup() +{ + if [ ! -z $localmp ]; then + umount -fl $localmp + if [ $? -eq 0 ]; then + rmdir $localmp + fi + fi +} + +if [ -z $1 ]; then + usage + echo "2#no mountpoint" + exit 0 +else + mountpoint=${1%/*} + vhdfilename=${1##*/} +fi + +if [ -z $2 ]; then + usage + echo "3#no uuid of the source sr" + exit 0 +else + sruuid=$2 +fi + +type=$(xe sr-param-get uuid=$sruuid param-name=type) +if [ $? -ne 0 ]; then + echo "4#sr $sruuid doesn't exist" + exit 0 +fi + +if [ -z $3 ]; then + usage + echo "3#no namelabel" + exit 0 +else + namelabel=$3 +fi + +localmp=/var/run/cloud_mount/$(uuidgen -r) + +mkdir -p $localmp +if [ $? -ne 0 ]; then + echo "5#can't make dir $localmp" + exit 0 +fi + +mount -o tcp,soft,ro,timeo=133,retrans=1 $mountpoint $localmp +if [ $? -ne 0 ]; then + echo "6#can't mount $mountpoint to $localmp" + exit 0 +fi + +vhdfile=$localmp/$vhdfilename +if [ ${vhdfile%.vhd} == ${vhdfile} ] ; then + vhdfile=$(ls $vhdfile/*.vhd) + if [ $? -ne 0 ]; then + echo "7#There is no vhd file under $mountpoint" + cleanup + exit 0 + fi +fi + + + +VHDUTIL="/usr/bin/vhd-util" + +copyvhd() +{ + local desvhd=$1 + local srcvhd=$2 + local vsize=$3 + local type=$4 + local parent=`$VHDUTIL query -p -n $srcvhd` + if [ $? -ne 0 ]; then + echo "30#failed to query $srcvhd" + cleanup + exit 0 + fi + if [ "${parent##*vhd has}" = " no parent" ]; then + dd if=$srcvhd of=$desvhd bs=2M + if [ $? -ne 0 ]; then + echo "31#failed to dd $srcvhd to $desvhd" + cleanup + exit 0 + fi + if [ $type != "nfs" -a $type != "ext" -a $type != "file" ]; then + dd if=$srcvhd of=$desvhd bs=512 seek=$(($(($vsize/512))-1)) count=1 + $VHDUTIL modify -s $vsize -n $desvhd + if [ $? -ne 0 ]; then + echo "32#failed to set new vhd physical size for vdi vdi $uuid" + cleanup + exit 0 + fi + fi + else + copyvhd $desvhd $parent $vsize $type + $VHDUTIL coalesce -p $desvhd -n $srcvhd + if [ $? -ne 0 ]; then + echo "32#failed to coalesce $desvhd to $srcvhd" + cleanup + exit 0 + fi + fi +} + +size=$($VHDUTIL query -v -n $vhdfile) +uuid=$(xe vdi-create sr-uuid=$sruuid virtual-size=${size}MiB type=user name-label=$namelabel) +if [ $? -ne 0 ]; then + echo "9#can not create vdi in sr $sruuid" + cleanup + exit 0 +fi + + +if [ $type == "nfs" -o $type == "ext" ]; then + desvhd=/run/sr-mount/$sruuid/$uuid.vhd + copyvhd $desvhd $vhdfile 0 $type + +elif [ $type == "lvmoiscsi" -o $type == "lvm" -o $type == "lvmohba" ]; then + lvsize=$(xe vdi-param-get uuid=$uuid param-name=physical-utilisation) + if [ $? -ne 0 ]; then + echo "12#failed to get physical size of vdi $uuid" + cleanup + exit 0 + fi + desvhd=/dev/VG_XenStorage-$sruuid/VHD-$uuid + lvchange -ay $desvhd + if [ $? -ne 0 ]; then + echo "10#lvm can not make VDI $uuid visible" + cleanup + exit 0 + fi + copyvhd $desvhd $vhdfile $lvsize $type +elif [ $type == "file" ]; then + pbd=`xe sr-param-list uuid=$sruuid |grep PBDs | awk '{print $3}'` + path=`xe pbd-param-list uuid=$pbd |grep device-config |awk '{print $4}'` + desvhd=$path/$uuid.vhd + copyvhd $desvhd $vhdfile 0 $type + +else + echo "15#doesn't support sr type $type" + cleanup + exit 0 +fi + +$VHDUTIL set -n $desvhd -f "hidden" -v "0" > /dev/null +if [ $? -ne 0 ]; then + echo "21#failed to set hidden to 0 $desvhd" + cleanup + exit 0 +fi +xe sr-scan uuid=$sruuid +if [ $? -ne 0 ]; then + echo "14#failed to scan sr $sruuid" + cleanup + exit 0 +fi + +echo "0#$uuid" +cleanup +exit 0 diff --git a/scripts/vm/hypervisor/xenserver/xcposs/copy_vhd_to_secondarystorage.sh b/scripts/vm/hypervisor/xenserver/xcposs/copy_vhd_to_secondarystorage.sh new file mode 100755 index 0000000000..b315c07b35 --- /dev/null +++ b/scripts/vm/hypervisor/xenserver/xcposs/copy_vhd_to_secondarystorage.sh @@ -0,0 +1,130 @@ +#!/bin/bash +# 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. + +#set -x + +usage() { + printf "Usage: %s [mountpoint in secondary storage] [uuid of the source vdi] [uuid of the source sr]\n" $(basename $0) +} + +cleanup() +{ + if [ ! -z $localmp ]; then + umount $localmp + if [ $? -eq 0 ]; then + rmdir $localmp + fi + fi +} + +if [ -z $1 ]; then + usage + echo "1#no mountpoint" + exit 0 +else + mountpoint=$1 +fi + +if [ -z $2 ]; then + usage + echo "2#no uuid of the source sr" + exit 0 +else + vdiuuid=$2 +fi + + +if [ -z $3 ]; then + usage + echo "3#no uuid of the source sr" + exit 0 +else + sruuid=$3 +fi + +type=$(xe sr-param-get uuid=$sruuid param-name=type) +if [ $? -ne 0 ]; then + echo "4#sr $sruuid doesn't exist" + exit 0 +fi + +localmp=/var/run/cloud_mount/$(uuidgen -r) + +mkdir -p $localmp +if [ $? -ne 0 ]; then + echo "5#can't make dir $localmp" + exit 0 +fi + +mount -o tcp,soft,timeo=133,retrans=1 $mountpoint $localmp +if [ $? -ne 0 ]; then + echo "6#can't mount $mountpoint to $localmp" + exit 0 +fi + +vhdfile=$localmp/${vdiuuid}.vhd + +if [ $type == "nfs" -o $type == "ext" ]; then + dd if=/var/run/sr-mount/$sruuid/${vdiuuid}.vhd of=$vhdfile bs=2M + if [ $? -ne 0 ]; then + rm -f $vhdfile + echo "8#failed to copy /var/run/sr-mount/$sruuid/${vdiuuid}.vhd to secondarystorage" + cleanup + exit 0 + fi +elif [ $type == "lvmoiscsi" -o $type == "lvm" -o $type == "lvmohba" ]; then + lvchange -ay /dev/VG_XenStorage-$sruuid/VHD-$vdiuuid + if [ $? -ne 0 ]; then + echo "9#lvm can not make VDI $vdiuuid visible" + cleanup + exit 0 + fi + size=$(vhd-util query -s -n /dev/VG_XenStorage-$sruuid/VHD-$vdiuuid) + if [ $? -ne 0 ]; then + echo "10#can not get physical size of /dev/VG_XenStorage-$sruuid/VHD-$vdiuuid" + cleanup + exit 0 + fi +#in 2M unit + size=$((size>>21)) + size=$((size+1)) + dd if=/dev/VG_XenStorage-$sruuid/VHD-$vdiuuid of=$vhdfile bs=2M count=$size + if [ $? -ne 0 ]; then + rm -f $vhdfile + echo "8#failed to copy /dev/VG_XenStorage-$sruuid/VHD-$vdiuuid to secondarystorage" + cleanup + exit 0 + fi +#in byte unit + size=$((size<<21)) + vhd-util modify -s $size -n $vhdfile + if [ $? -ne 0 ]; then + rm -f $vhdfile + echo "11#failed to change $vhdfile physical size" + cleanup + exit 0 + fi +else + echo "15#doesn't support sr type $type" + cleanup + exit 0 +fi + +echo "0#$vdiuuid" +cleanup +exit 0 diff --git a/scripts/vm/hypervisor/xenserver/xcposs/patch b/scripts/vm/hypervisor/xenserver/xcposs/patch index 08da883e54..ac04a3e14d 100644 --- a/scripts/vm/hypervisor/xenserver/xcposs/patch +++ b/scripts/vm/hypervisor/xenserver/xcposs/patch @@ -27,11 +27,12 @@ # If [source path] starts with '~', then it is path relative to management server home directory. # If [source path] does not start with '/' or '~', then it is relative path to the location of the patch file. NFSSR.py=/usr/lib/xcp/sm -vmops=..,0755,/usr/lib/xcp/plugins +vmops=,0755,/usr/lib/xcp/plugins +cloudstack_pluginlib.py=..,0755,/usr/lib/xcp/plugins +cloudstack_plugins.conf=..,0644,/etc/xcp ovsgre=..,0755,/usr/lib/xcp/plugins ovstunnel=..,0755,/usr/lib/xcp/plugins -vmopsSnapshot=..,0755,/usr/lib/xcp/plugins -hostvmstats.py=..,0755,/usr/lib/xcp/sm +vmopsSnapshot=,0755,/usr/lib/xcp/plugins systemvm.iso=../../../../../vms,0644,/usr/share/xcp/packages/iso/ id_rsa.cloud=../../../systemvm,0600,/root/.ssh network_info.sh=..,0755,/opt/cloud/bin @@ -40,8 +41,8 @@ make_migratable.sh=..,0755,/opt/cloud/bin setup_iscsi.sh=..,0755,/opt/cloud/bin pingtest.sh=../../..,0755,/opt/cloud/bin cloud-setup-bonding.sh=..,0755,/opt/cloud/bin -copy_vhd_to_secondarystorage.sh=..,0755,/opt/cloud/bin -copy_vhd_from_secondarystorage.sh=..,0755,/opt/cloud/bin +copy_vhd_to_secondarystorage.sh=,0755,/opt/cloud/bin +copy_vhd_from_secondarystorage.sh=,0755,/opt/cloud/bin setup_heartbeat_sr.sh=..,0755,/opt/cloud/bin setup_heartbeat_file.sh=..,0755,/opt/cloud/bin check_heartbeat.sh=..,0755,/opt/cloud/bin diff --git a/scripts/vm/hypervisor/xenserver/xcposs/vmops b/scripts/vm/hypervisor/xenserver/xcposs/vmops new file mode 100644 index 0000000000..1792a46773 --- /dev/null +++ b/scripts/vm/hypervisor/xenserver/xcposs/vmops @@ -0,0 +1,1476 @@ +#!/usr/bin/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. + +# Version @VERSION@ +# +# A plugin for executing script needed by vmops cloud + +import os, sys, time +import XenAPIPlugin +sys.path.extend(["/usr/lib/xcp/sm/", "/usr/local/sbin/", "/sbin/"]) +import base64 +import hostvmstats +import socket +import stat +import tempfile +import util +import subprocess +import zlib +from util import CommandException + +def echo(fn): + def wrapped(*v, **k): + name = fn.__name__ + util.SMlog("#### VMOPS enter %s ####" % name ) + res = fn(*v, **k) + util.SMlog("#### VMOPS exit %s ####" % name ) + return res + return wrapped + +@echo +def gethostvmstats(session, args): + collect_host_stats = args['collectHostStats'] + consolidation_function = args['consolidationFunction'] + interval = args['interval'] + start_time = args['startTime'] + result = hostvmstats.get_stats(session, collect_host_stats, consolidation_function, interval, start_time) + return result + +@echo +def setup_iscsi(session, args): + uuid=args['uuid'] + try: + cmd = ["b", "/opt/cloud/bin/setup_iscsi.sh", uuid] + txt = util.pread2(cmd) + except: + txt = '' + return '> DONE <' + + +@echo +def getgateway(session, args): + mgmt_ip = args['mgmtIP'] + try: + cmd = ["bash", "/opt/cloud/bin/network_info.sh", "-g", mgmt_ip] + txt = util.pread2(cmd) + except: + txt = '' + + return txt + +@echo +def preparemigration(session, args): + uuid = args['uuid'] + try: + cmd = ["/opt/cloud/bin/make_migratable.sh", uuid] + util.pread2(cmd) + txt = 'success' + except: + util.SMlog("Catch prepare migration exception" ) + txt = '' + + return txt + +@echo +def setIptables(session, args): + try: + '''cmd = ["/bin/bash", "/opt/cloud/bin/setupxenserver.sh"] + txt = util.pread2(cmd)''' + txt = 'success' + except: + util.SMlog(" setIptables execution failed " ) + txt = '' + + return txt + +@echo +def pingdomr(session, args): + host = args['host'] + port = args['port'] + socket.setdefaulttimeout(3) + s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) + try: + s.connect((host,int(port))) + txt = 'success' + except: + txt = '' + + s.close() + + return txt + +@echo +def kill_copy_process(session, args): + namelabel = args['namelabel'] + try: + cmd = ["bash", "/opt/cloud/bin/kill_copy_process.sh", namelabel] + txt = util.pread2(cmd) + except: + txt = 'false' + return txt + +@echo +def pingxenserver(session, args): + txt = 'success' + return txt + +@echo +def ipassoc(session, args): + sargs = args['args'] + cmd = sargs.split(' ') + cmd.insert(0, "/opt/cloud/bin/ipassoc.sh") + cmd.insert(0, "/bin/bash") + try: + txt = util.pread2(cmd) + txt = 'success' + except: + util.SMlog(" ip associate failed " ) + txt = '' + + return txt + +def pingtest(session, args): + sargs = args['args'] + cmd = sargs.split(' ') + cmd.insert(0, "/opt/cloud/bin/pingtest.sh") + cmd.insert(0, "/bin/bash") + try: + txt = util.pread2(cmd) + txt = 'success' + except: + util.SMlog(" pingtest failed " ) + txt = '' + + return txt + +@echo +def savePassword(session, args): + sargs = args['args'] + cmd = sargs.split(' ') + cmd.insert(0, "/opt/cloud/bin/save_password_to_domr.sh") + cmd.insert(0, "/bin/bash") + try: + txt = util.pread2(cmd) + txt = 'success' + except: + util.SMlog(" save password to domr failed " ) + txt = '' + + return txt + +@echo +def saveDhcpEntry(session, args): + sargs = args['args'] + cmd = sargs.split(' ') + cmd.insert(0, "/opt/cloud/bin/dhcp_entry.sh") + cmd.insert(0, "/bin/bash") + try: + txt = util.pread2(cmd) + txt = 'success' + except: + util.SMlog(" save dhcp entry failed " ) + txt = '' + + return txt + +@echo +def lt2p_vpn(session, args): + sargs = args['args'] + cmd = sargs.split(' ') + cmd.insert(0, "/opt/cloud/bin/l2tp_vpn.sh") + cmd.insert(0, "/bin/bash") + try: + txt = util.pread2(cmd) + txt = 'success' + except: + util.SMlog("l2tp vpn failed " ) + txt = '' + + return txt + +@echo +def setLinkLocalIP(session, args): + brName = args['brName'] + try: + cmd = ["ip", "route", "del", "169.254.0.0/16"] + txt = util.pread2(cmd) + except: + txt = '' + try: + cmd = ["ifconfig", brName, "169.254.0.1", "netmask", "255.255.0.0"] + txt = util.pread2(cmd) + except: + + try: + cmd = ["brctl", "addbr", brName] + txt = util.pread2(cmd) + except: + pass + + try: + cmd = ["ifconfig", brName, "169.254.0.1", "netmask", "255.255.0.0"] + txt = util.pread2(cmd) + except: + pass + try: + cmd = ["ip", "route", "add", "169.254.0.0/16", "dev", brName, "src", "169.254.0.1"] + txt = util.pread2(cmd) + except: + txt = '' + txt = 'success' + return txt + +@echo +def setFirewallRule(session, args): + sargs = args['args'] + cmd = sargs.split(' ') + cmd.insert(0, "/opt/cloud/bin/call_firewall.sh") + cmd.insert(0, "/bin/bash") + try: + txt = util.pread2(cmd) + txt = 'success' + except: + util.SMlog(" set firewall rule failed " ) + txt = '' + + return txt + +@echo +def setLoadBalancerRule(session, args): + sargs = args['args'] + cmd = sargs.split(' ') + cmd.insert(0, "/opt/cloud/bin/call_loadbalancer.sh") + cmd.insert(0, "/bin/bash") + try: + txt = util.pread2(cmd) + txt = 'success' + except: + util.SMlog(" set loadbalancer rule failed " ) + txt = '' + + return txt + +@echo +def createFile(session, args): + file_path = args['filepath'] + file_contents = args['filecontents'] + + try: + f = open(file_path, "w") + f.write(file_contents) + f.close() + txt = 'success' + except: + util.SMlog(" failed to create HA proxy cfg file ") + txt = '' + + return txt + +@echo +def deleteFile(session, args): + file_path = args["filepath"] + + try: + if os.path.isfile(file_path): + os.remove(file_path) + txt = 'success' + except: + util.SMlog(" failed to remove HA proxy cfg file ") + txt = '' + + return txt + + +@echo +def networkUsage(session, args): + sargs = args['args'] + cmd = sargs.split(' ') + cmd.insert(0, "/opt/cloud/bin/networkUsage.sh") + cmd.insert(0, "/bin/bash") + try: + txt = util.pread2(cmd) + except: + util.SMlog(" network usage error " ) + txt = '' + + return txt + +def get_private_nic(session, args): + vms = session.xenapi.VM.get_all() + host_uuid = args.get('host_uuid') + host = session.xenapi.host.get_by_uuid(host_uuid) + piflist = session.xenapi.host.get_PIFs(host) + mgmtnic = 'eth0' + for pif in piflist: + pifrec = session.xenapi.PIF.get_record(pif) + network = pifrec.get('network') + nwrec = session.xenapi.network.get_record(network) + if nwrec.get('name_label') == 'cloud-guest': + return pifrec.get('device') + if pifrec.get('management'): + mgmtnic = pifrec.get('device') + + return mgmtnic + +def chain_name(vm_name): + if vm_name.startswith('i-') or vm_name.startswith('r-'): + if vm_name.endswith('untagged'): + return '-'.join(vm_name.split('-')[:-1]) + return vm_name + +def chain_name_def(vm_name): + if vm_name.startswith('i-'): + if vm_name.endswith('untagged'): + return '-'.join(vm_name.split('-')[:-2]) + "-def" + return '-'.join(vm_name.split('-')[:-1]) + "-def" + return vm_name + +def egress_chain_name(vm_name): + return chain_name(vm_name) + "-eg" + +@echo +def can_bridge_firewall(session, args): + try: + util.pread2(['ebtables', '-V']) + util.pread2(['ipset', '-V']) + except: + return 'false' + + host_uuid = args.get('host_uuid') + try: + util.pread2(['iptables', '-N', 'BRIDGE-FIREWALL']) + util.pread2(['iptables', '-I', 'BRIDGE-FIREWALL', '-m', 'state', '--state', 'RELATED,ESTABLISHED', '-j', 'ACCEPT']) + util.pread2(['iptables', '-A', 'BRIDGE-FIREWALL', '-m', 'physdev', '--physdev-is-bridged', '-p', 'udp', '--dport', '67', '--sport', '68', '-j', 'ACCEPT']) + util.pread2(['iptables', '-A', 'BRIDGE-FIREWALL', '-m', 'physdev', '--physdev-is-bridged', '-p', 'udp', '--dport', '68', '--sport', '67', '-j', 'ACCEPT']) + util.pread2(['iptables', '-D', 'FORWARD', '-j', 'RH-Firewall-1-INPUT']) + except: + util.SMlog('Chain BRIDGE-FIREWALL already exists') + privnic = get_private_nic(session, args) + result = 'true' + try: + util.pread2(['/bin/bash', '-c', 'iptables -n -L FORWARD | grep BRIDGE-FIREWALL']) + except: + try: + util.pread2(['iptables', '-I', 'FORWARD', '-m', 'physdev', '--physdev-is-bridged', '-j', 'BRIDGE-FIREWALL']) + util.pread2(['iptables', '-A', 'FORWARD', '-m', 'physdev', '--physdev-is-bridged', '--physdev-out', privnic, '-j', 'ACCEPT']) + util.pread2(['iptables', '-A', 'FORWARD', '-j', 'DROP']) + except: + return 'false' + default_ebtables_rules() + allow_egress_traffic(session) + if not os.path.exists('/var/run/cloud'): + os.makedirs('/var/run/cloud') + if not os.path.exists('/var/cache/cloud'): + os.makedirs('/var/cache/cloud') + #get_ipset_keyword() + + cleanup_rules_for_dead_vms(session) + cleanup_rules(session, args) + + return result + +@echo +def default_ebtables_rules(): + try: + util.pread2(['ebtables', '-N', 'DEFAULT_EBTABLES']) + util.pread2(['ebtables', '-A', 'FORWARD', '-j' 'DEFAULT_EBTABLES']) + util.pread2(['ebtables', '-A', 'DEFAULT_EBTABLES', '-p', 'IPv4', '--ip-dst', '255.255.255.255', '--ip-proto', 'udp', '--ip-dport', '67', '-j', 'ACCEPT']) + util.pread2(['ebtables', '-A', 'DEFAULT_EBTABLES', '-p', 'ARP', '--arp-op', 'Request', '-j', 'ACCEPT']) + util.pread2(['ebtables', '-A', 'DEFAULT_EBTABLES', '-p', 'ARP', '--arp-op', 'Reply', '-j', 'ACCEPT']) + # deny mac broadcast and multicast + util.pread2(['ebtables', '-A', 'DEFAULT_EBTABLES', '-p', 'IPv4', '-d', 'Broadcast', '-j', 'DROP']) + util.pread2(['ebtables', '-A', 'DEFAULT_EBTABLES', '-p', 'IPv4', '-d', 'Multicast', '-j', 'DROP']) + # deny ip broadcast and multicast + util.pread2(['ebtables', '-A', 'DEFAULT_EBTABLES', '-p', 'IPv4', '--ip-dst', '255.255.255.255', '-j', 'DROP']) + util.pread2(['ebtables', '-A', 'DEFAULT_EBTABLES', '-p', 'IPv4', '--ip-dst', '224.0.0.0/4', '-j', 'DROP']) + util.pread2(['ebtables', '-A', 'DEFAULT_EBTABLES', '-p', 'IPv4', '-j', 'RETURN']) + # deny ipv6 + util.pread2(['ebtables', '-A', 'DEFAULT_EBTABLES', '-p', 'IPv6', '-j', 'DROP']) + # deny vlan + util.pread2(['ebtables', '-A', 'DEFAULT_EBTABLES', '-p', '802_1Q', '-j', 'DROP']) + # deny all others (e.g., 802.1d, CDP) + util.pread2(['ebtables', '-A', 'DEFAULT_EBTABLES', '-j', 'DROP']) + except: + util.SMlog('Chain DEFAULT_EBTABLES already exists') + + +@echo +def allow_egress_traffic(session): + devs = [] + for pif in session.xenapi.PIF.get_all(): + pif_rec = session.xenapi.PIF.get_record(pif) + vlan = pif_rec.get('VLAN') + dev = pif_rec.get('device') + if vlan == '-1': + devs.append(dev) + else: + devs.append(dev + "." + vlan) + for d in devs: + try: + util.pread2(['/bin/bash', '-c', "iptables -n -L FORWARD | grep '%s '" % d]) + except: + try: + util.pread2(['iptables', '-I', 'FORWARD', '2', '-m', 'physdev', '--physdev-is-bridged', '--physdev-out', d, '-j', 'ACCEPT']) + except: + util.SMlog("Failed to add FORWARD rule through to %s" % d) + return 'false' + return 'true' + + +def ipset(ipsetname, proto, start, end, ips): + try: + util.pread2(['ipset', '-N', ipsetname, 'iptreemap']) + except: + util.SMlog("ipset chain already exists" + ipsetname) + + result = True + ipsettmp = ''.join(''.join(ipsetname.split('-')).split('_')) + str(int(time.time()) % 1000) + + try: + util.pread2(['ipset', '-N', ipsettmp, 'iptreemap']) + except: + util.SMlog("Failed to create temp ipset, reusing old name= " + ipsettmp) + try: + util.pread2(['ipset', '-F', ipsettmp]) + except: + util.SMlog("Failed to clear old temp ipset name=" + ipsettmp) + return False + + try: + for ip in ips: + try: + util.pread2(['ipset', '-A', ipsettmp, ip]) + except CommandException, cex: + if cex.reason.rfind('already in set') == -1: + raise + except: + util.SMlog("Failed to program ipset " + ipsetname) + util.pread2(['ipset', '-F', ipsettmp]) + util.pread2(['ipset', '-X', ipsettmp]) + return False + + try: + util.pread2(['ipset', '-W', ipsettmp, ipsetname]) + except: + util.SMlog("Failed to swap ipset " + ipsetname) + result = False + + try: + util.pread2(['ipset', '-F', ipsettmp]) + util.pread2(['ipset', '-X', ipsettmp]) + except: + # if the temporary name clashes next time we'll just reuse it + util.SMlog("Failed to delete temp ipset " + ipsettmp) + + return result + +@echo +def destroy_network_rules_for_vm(session, args): + vm_name = args.pop('vmName') + vmchain = chain_name(vm_name) + vmchain_egress = egress_chain_name(vm_name) + vmchain_default = chain_name_def(vm_name) + + delete_rules_for_vm_in_bridge_firewall_chain(vm_name) + if vm_name.startswith('i-') or vm_name.startswith('r-') or vm_name.startswith('l-'): + try: + util.pread2(['iptables', '-F', vmchain_default]) + util.pread2(['iptables', '-X', vmchain_default]) + except: + util.SMlog("Ignoring failure to delete chain " + vmchain_default) + + destroy_ebtables_rules(vmchain) + + try: + util.pread2(['iptables', '-F', vmchain]) + util.pread2(['iptables', '-X', vmchain]) + except: + util.SMlog("Ignoring failure to delete ingress chain " + vmchain) + + + try: + util.pread2(['iptables', '-F', vmchain_egress]) + util.pread2(['iptables', '-X', vmchain_egress]) + except: + util.SMlog("Ignoring failure to delete egress chain " + vmchain_egress) + + remove_rule_log_for_vm(vm_name) + + if 1 in [ vm_name.startswith(c) for c in ['r-', 's-', 'v-', 'l-'] ]: + return 'true' + + try: + setscmd = "ipset --save | grep " + vmchain + " | grep '^-N' | awk '{print $2}'" + setsforvm = util.pread2(['/bin/bash', '-c', setscmd]).split('\n') + for set in setsforvm: + if set != '': + util.pread2(['ipset', '-F', set]) + util.pread2(['ipset', '-X', set]) + except: + util.SMlog("Failed to destroy ipsets for %" % vm_name) + + + return 'true' + +@echo +def destroy_ebtables_rules(vm_chain): + + delcmd = "ebtables-save | grep " + vm_chain + " | sed 's/-A/-D/'" + delcmds = util.pread2(['/bin/bash', '-c', delcmd]).split('\n') + delcmds.pop() + for cmd in delcmds: + try: + dc = cmd.split(' ') + dc.insert(0, 'ebtables') + util.pread2(dc) + except: + util.SMlog("Ignoring failure to delete ebtables rules for vm " + vm_chain) + try: + util.pread2(['ebtables', '-F', vm_chain]) + util.pread2(['ebtables', '-X', vm_chain]) + except: + util.SMlog("Ignoring failure to delete ebtables chain for vm " + vm_chain) + +@echo +def destroy_arptables_rules(vm_chain): + delcmd = "arptables -vL FORWARD | grep " + vm_chain + " | sed 's/-i any//' | sed 's/-o any//' | awk '{print $1,$2,$3,$4}' " + delcmds = util.pread2(['/bin/bash', '-c', delcmd]).split('\n') + delcmds.pop() + for cmd in delcmds: + try: + dc = cmd.split(' ') + dc.insert(0, 'arptables') + dc.insert(1, '-D') + dc.insert(2, 'FORWARD') + util.pread2(dc) + except: + util.SMlog("Ignoring failure to delete arptables rules for vm " + vm_chain) + + try: + util.pread2(['arptables', '-F', vm_chain]) + util.pread2(['arptables', '-X', vm_chain]) + except: + util.SMlog("Ignoring failure to delete arptables chain for vm " + vm_chain) + +@echo +def default_ebtables_antispoof_rules(vm_chain, vifs, vm_ip, vm_mac): + if vm_mac == 'ff:ff:ff:ff:ff:ff': + util.SMlog("Ignoring since mac address is not valid") + return 'true' + + try: + util.pread2(['ebtables', '-N', vm_chain]) + except: + try: + util.pread2(['ebtables', '-F', vm_chain]) + except: + util.SMlog("Failed to create ebtables antispoof chain, skipping") + return 'true' + + # note all rules for packets into the bridge (-i) precede all output rules (-o) + # always start after the first rule in the FORWARD chain that jumps to DEFAULT_EBTABLES chain + try: + for vif in vifs: + util.pread2(['ebtables', '-I', 'FORWARD', '2', '-i', vif, '-j', vm_chain]) + util.pread2(['ebtables', '-A', 'FORWARD', '-o', vif, '-j', vm_chain]) + except: + util.SMlog("Failed to program default ebtables FORWARD rules for %s" % vm_chain) + return 'false' + + try: + for vif in vifs: + # only allow source mac that belongs to the vm + util.pread2(['ebtables', '-A', vm_chain, '-i', vif, '-s', '!', vm_mac, '-j', 'DROP']) + # do not allow fake dhcp responses + util.pread2(['ebtables', '-A', vm_chain, '-i', vif, '-p', 'IPv4', '--ip-proto', 'udp', '--ip-dport', '68', '-j', 'DROP']) + # do not allow snooping of dhcp requests + util.pread2(['ebtables', '-A', vm_chain, '-o', vif, '-p', 'IPv4', '--ip-proto', 'udp', '--ip-dport', '67', '-j', 'DROP']) + except: + util.SMlog("Failed to program default ebtables antispoof rules for %s" % vm_chain) + return 'false' + + return 'true' + +@echo +def default_arp_antispoof(vm_chain, vifs, vm_ip, vm_mac): + if vm_mac == 'ff:ff:ff:ff:ff:ff': + util.SMlog("Ignoring since mac address is not valid") + return 'true' + + try: + util.pread2(['arptables', '-N', vm_chain]) + except: + try: + util.pread2(['arptables', '-F', vm_chain]) + except: + util.SMlog("Failed to create arptables rule, skipping") + return 'true' + + # note all rules for packets into the bridge (-i) precede all output rules (-o) + try: + for vif in vifs: + util.pread2(['arptables', '-I', 'FORWARD', '-i', vif, '-j', vm_chain]) + util.pread2(['arptables', '-A', 'FORWARD', '-o', vif, '-j', vm_chain]) + except: + util.SMlog("Failed to program default arptables rules in FORWARD chain vm=" + vm_chain) + return 'false' + + try: + for vif in vifs: + #accept arp replies into the bridge as long as the source mac and ips match the vm + util.pread2(['arptables', '-A', vm_chain, '-i', vif, '--opcode', 'Reply', '--source-mac', vm_mac, '--source-ip', vm_ip, '-j', 'ACCEPT']) + #accept any arp requests from this vm. In the future this can be restricted to deny attacks on hosts + #also important to restrict source ip and src mac in these requests as they can be used to update arp tables on destination + util.pread2(['arptables', '-A', vm_chain, '-i', vif, '--opcode', 'Request', '--source-mac', vm_mac, '--source-ip', vm_ip, '-j', 'RETURN']) + #accept any arp requests to this vm as long as the request is for this vm's ip + util.pread2(['arptables', '-A', vm_chain, '-o', vif, '--opcode', 'Request', '--destination-ip', vm_ip, '-j', 'ACCEPT']) + #accept any arp replies to this vm as long as the mac and ip matches + util.pread2(['arptables', '-A', vm_chain, '-o', vif, '--opcode', 'Reply', '--destination-mac', vm_mac, '--destination-ip', vm_ip, '-j', 'ACCEPT']) + util.pread2(['arptables', '-A', vm_chain, '-j', 'DROP']) + + except: + util.SMlog("Failed to program default arptables rules") + return 'false' + + return 'true' + +@echo +def default_network_rules_systemvm(session, args): + vm_name = args.pop('vmName') + try: + vm = session.xenapi.VM.get_by_name_label(vm_name) + if len(vm) != 1: + return 'false' + vm_rec = session.xenapi.VM.get_record(vm[0]) + vm_vifs = vm_rec.get('VIFs') + vifnums = [session.xenapi.VIF.get_record(vif).get('device') for vif in vm_vifs] + domid = vm_rec.get('domid') + except: + util.SMlog("### Failed to get domid or vif list for vm ##" + vm_name) + return 'false' + + if domid == '-1': + util.SMlog("### Failed to get domid for vm (-1): " + vm_name) + return 'false' + + vifs = ["vif" + domid + "." + v for v in vifnums] + #vm_name = '-'.join(vm_name.split('-')[:-1]) + vmchain = chain_name(vm_name) + + + delete_rules_for_vm_in_bridge_firewall_chain(vm_name) + + try: + util.pread2(['iptables', '-N', vmchain]) + except: + util.pread2(['iptables', '-F', vmchain]) + + allow_egress_traffic(session) + + for vif in vifs: + try: + util.pread2(['iptables', '-A', 'BRIDGE-FIREWALL', '-m', 'physdev', '--physdev-is-bridged', '--physdev-out', vif, '-j', vmchain]) + util.pread2(['iptables', '-I', 'BRIDGE-FIREWALL', '4', '-m', 'physdev', '--physdev-is-bridged', '--physdev-in', vif, '-j', vmchain]) + util.pread2(['iptables', '-I', vmchain, '-m', 'physdev', '--physdev-is-bridged', '--physdev-in', vif, '-j', 'RETURN']) + except: + util.SMlog("Failed to program default rules") + return 'false' + + + util.pread2(['iptables', '-A', vmchain, '-j', 'ACCEPT']) + + if write_rule_log_for_vm(vm_name, '-1', '_ignore_', domid, '_initial_', '-1') == False: + util.SMlog("Failed to log default network rules for systemvm, ignoring") + return 'true' + + +@echo +def default_network_rules(session, args): + vm_name = args.pop('vmName') + vm_ip = args.pop('vmIP') + vm_id = args.pop('vmID') + vm_mac = args.pop('vmMAC') + + try: + vm = session.xenapi.VM.get_by_name_label(vm_name) + if len(vm) != 1: + util.SMlog("### Failed to get record for vm " + vm_name) + return 'false' + vm_rec = session.xenapi.VM.get_record(vm[0]) + domid = vm_rec.get('domid') + except: + util.SMlog("### Failed to get domid for vm " + vm_name) + return 'false' + if domid == '-1': + util.SMlog("### Failed to get domid for vm (-1): " + vm_name) + return 'false' + + vif = "vif" + domid + ".0" + tap = "tap" + domid + ".0" + vifs = [vif] + try: + util.pread2(['ifconfig', tap]) + vifs.append(tap) + except: + pass + + delete_rules_for_vm_in_bridge_firewall_chain(vm_name) + + + vmchain = chain_name(vm_name) + vmchain_egress = egress_chain_name(vm_name) + vmchain_default = chain_name_def(vm_name) + + destroy_ebtables_rules(vmchain) + + + try: + util.pread2(['iptables', '-N', vmchain]) + except: + util.pread2(['iptables', '-F', vmchain]) + + try: + util.pread2(['iptables', '-N', vmchain_egress]) + except: + util.pread2(['iptables', '-F', vmchain_egress]) + + try: + util.pread2(['iptables', '-N', vmchain_default]) + except: + util.pread2(['iptables', '-F', vmchain_default]) + + try: + for v in vifs: + util.pread2(['iptables', '-A', 'BRIDGE-FIREWALL', '-m', 'physdev', '--physdev-is-bridged', '--physdev-out', v, '-j', vmchain_default]) + util.pread2(['iptables', '-I', 'BRIDGE-FIREWALL', '2', '-m', 'physdev', '--physdev-is-bridged', '--physdev-in', v, '-j', vmchain_default]) + util.pread2(['iptables', '-A', vmchain_default, '-m', 'state', '--state', 'RELATED,ESTABLISHED', '-j', 'ACCEPT']) + #allow dhcp + for v in vifs: + util.pread2(['iptables', '-A', vmchain_default, '-m', 'physdev', '--physdev-is-bridged', '--physdev-in', v, '-p', 'udp', '--dport', '67', '--sport', '68', '-j', 'ACCEPT']) + util.pread2(['iptables', '-A', vmchain_default, '-m', 'physdev', '--physdev-is-bridged', '--physdev-out', v, '-p', 'udp', '--dport', '68', '--sport', '67', '-j', 'ACCEPT']) + + #don't let vm spoof its ip address + for v in vifs: + util.pread2(['iptables', '-A', vmchain_default, '-m', 'physdev', '--physdev-is-bridged', '--physdev-in', v, '--source', vm_ip,'-p', 'udp', '--dport', '53', '-j', 'RETURN']) + util.pread2(['iptables', '-A', vmchain_default, '-m', 'physdev', '--physdev-is-bridged', '--physdev-in', v, '--source', '!', vm_ip, '-j', 'DROP']) + util.pread2(['iptables', '-A', vmchain_default, '-m', 'physdev', '--physdev-is-bridged', '--physdev-out', v, '--destination', '!', vm_ip, '-j', 'DROP']) + util.pread2(['iptables', '-A', vmchain_default, '-m', 'physdev', '--physdev-is-bridged', '--physdev-in', v, '--source', vm_ip, '-j', vmchain_egress]) + + for v in vifs: + util.pread2(['iptables', '-A', vmchain_default, '-m', 'physdev', '--physdev-is-bridged', '--physdev-out', v, '-j', vmchain]) + except: + util.SMlog("Failed to program default rules for vm " + vm_name) + return 'false' + + default_arp_antispoof(vmchain, vifs, vm_ip, vm_mac) + default_ebtables_antispoof_rules(vmchain, vifs, vm_ip, vm_mac) + + if write_rule_log_for_vm(vm_name, vm_id, vm_ip, domid, '_initial_', '-1', vm_mac) == False: + util.SMlog("Failed to log default network rules, ignoring") + + util.SMlog("Programmed default rules for vm " + vm_name) + return 'true' + +@echo +def check_domid_changed(session, vmName): + curr_domid = '-1' + try: + vm = session.xenapi.VM.get_by_name_label(vmName) + if len(vm) != 1: + util.SMlog("### Could not get record for vm ## " + vmName) + else: + vm_rec = session.xenapi.VM.get_record(vm[0]) + curr_domid = vm_rec.get('domid') + except: + util.SMlog("### Failed to get domid for vm ## " + vmName) + + + logfilename = "/var/run/cloud/" + vmName +".log" + if not os.path.exists(logfilename): + return ['-1', curr_domid] + + lines = (line.rstrip() for line in open(logfilename)) + + [_vmName,_vmID,_vmIP,old_domid,_signature,_seqno, _vmMac] = ['_', '-1', '_', '-1', '_', '-1', 'ff:ff:ff:ff:ff:ff'] + for line in lines: + try: + [_vmName,_vmID,_vmIP,old_domid,_signature,_seqno,_vmMac] = line.split(',') + except ValueError,v: + [_vmName,_vmID,_vmIP,old_domid,_signature,_seqno] = line.split(',') + break + + return [curr_domid, old_domid] + +@echo +def delete_rules_for_vm_in_bridge_firewall_chain(vmName): + vm_name = vmName + vmchain = chain_name_def(vm_name) + + delcmd = "iptables-save | grep '\-A BRIDGE-FIREWALL' | grep " + vmchain + " | sed 's/-A/-D/'" + delcmds = util.pread2(['/bin/bash', '-c', delcmd]).split('\n') + delcmds.pop() + for cmd in delcmds: + try: + dc = cmd.split(' ') + dc.insert(0, 'iptables') + dc.pop() + util.pread2(filter(None, dc)) + except: + util.SMlog("Ignoring failure to delete rules for vm " + vmName) + + +@echo +def network_rules_for_rebooted_vm(session, vmName): + vm_name = vmName + [curr_domid, old_domid] = check_domid_changed(session, vm_name) + + if curr_domid == old_domid: + return True + + if old_domid == '-1': + return True + + if curr_domid == '-1': + return True + + util.SMlog("Found a rebooted VM -- reprogramming rules for " + vm_name) + + delete_rules_for_vm_in_bridge_firewall_chain(vm_name) + if 1 in [ vm_name.startswith(c) for c in ['r-', 's-', 'v-', 'l-'] ]: + default_network_rules_systemvm(session, {"vmName":vm_name}) + return True + + vif = "vif" + curr_domid + ".0" + tap = "tap" + curr_domid + ".0" + vifs = [vif] + try: + util.pread2(['ifconfig', tap]) + vifs.append(tap) + except: + pass + vmchain = chain_name(vm_name) + vmchain_default = chain_name_def(vm_name) + + for v in vifs: + util.pread2(['iptables', '-A', 'BRIDGE-FIREWALL', '-m', 'physdev', '--physdev-is-bridged', '--physdev-out', v, '-j', vmchain_default]) + util.pread2(['iptables', '-I', 'BRIDGE-FIREWALL', '2', '-m', 'physdev', '--physdev-is-bridged', '--physdev-in', v, '-j', vmchain_default]) + + #change antispoof rule in vmchain + try: + delcmd = "iptables-save | grep '\-A " + vmchain_default + "' | grep physdev-in | sed 's/-A/-D/'" + delcmd2 = "iptables-save | grep '\-A " + vmchain_default + "' | grep physdev-out | sed 's/-A/-D/'" + inscmd = "iptables-save | grep '\-A " + vmchain_default + "' | grep physdev-in | grep vif | sed -r 's/vif[0-9]+.0/" + vif + "/' " + inscmd2 = "iptables-save| grep '\-A " + vmchain_default + "' | grep physdev-in | grep tap | sed -r 's/tap[0-9]+.0/" + tap + "/' " + inscmd3 = "iptables-save | grep '\-A " + vmchain_default + "' | grep physdev-out | grep vif | sed -r 's/vif[0-9]+.0/" + vif + "/' " + inscmd4 = "iptables-save| grep '\-A " + vmchain_default + "' | grep physdev-out | grep tap | sed -r 's/tap[0-9]+.0/" + tap + "/' " + + ipts = [] + for cmd in [delcmd, delcmd2, inscmd, inscmd2, inscmd3, inscmd4]: + cmds = util.pread2(['/bin/bash', '-c', cmd]).split('\n') + cmds.pop() + for c in cmds: + ipt = c.split(' ') + ipt.insert(0, 'iptables') + ipt.pop() + ipts.append(ipt) + + for ipt in ipts: + try: + util.pread2(filter(None,ipt)) + except: + util.SMlog("Failed to rewrite antispoofing rules for vm " + vm_name) + + util.pread2(['/bin/bash', '-c', 'iptables -D ' + vmchain_default + " -j " + vmchain]) + util.pread2(['/bin/bash', '-c', 'iptables -A ' + vmchain_default + " -j " + vmchain]) + except: + util.SMlog("No rules found for vm " + vm_name) + + destroy_ebtables_rules(vmchain) + destroy_arptables_rules(vmchain) + [vm_ip, vm_mac] = get_vm_mac_ip_from_log(vmchain) + default_arp_antispoof(vmchain, vifs, vm_ip, vm_mac) + default_ebtables_antispoof_rules(vmchain, vifs, vm_ip, vm_mac) + rewrite_rule_log_for_vm(vm_name, curr_domid) + return True + +def rewrite_rule_log_for_vm(vm_name, new_domid): + logfilename = "/var/run/cloud/" + vm_name +".log" + if not os.path.exists(logfilename): + return + lines = (line.rstrip() for line in open(logfilename)) + + [_vmName,_vmID,_vmIP,_domID,_signature,_seqno,_vmMac] = ['_', '-1', '_', '-1', '_', '-1','ff:ff:ff:ff:ff:ff'] + for line in lines: + try: + [_vmName,_vmID,_vmIP,_domID,_signature,_seqno,_vmMac] = line.split(',') + break + except ValueError,v: + [_vmName,_vmID,_vmIP,_domID,_signature,_seqno] = line.split(',') + + write_rule_log_for_vm(_vmName, _vmID, _vmIP, new_domid, _signature, '-1', _vmMac) + +def get_rule_log_for_vm(session, vmName): + vm_name = vmName; + logfilename = "/var/run/cloud/" + vm_name +".log" + if not os.path.exists(logfilename): + return '' + + lines = (line.rstrip() for line in open(logfilename)) + + [_vmName,_vmID,_vmIP,_domID,_signature,_seqno,_vmMac] = ['_', '-1', '_', '-1', '_', '-1', 'ff:ff:ff:ff:ff:ff'] + for line in lines: + try: + [_vmName,_vmID,_vmIP,_domID,_signature,_seqno,_vmMac] = line.split(',') + break + except ValueError,v: + [_vmName,_vmID,_vmIP,_domID,_signature,_seqno] = line.split(',') + + return ','.join([_vmName, _vmID, _vmIP, _domID, _signature, _seqno]) + +@echo +def get_vm_mac_ip_from_log(vm_name): + [_vmName,_vmID,_vmIP,_domID,_signature,_seqno,_vmMac] = ['_', '-1', '0.0.0.0', '-1', '_', '-1','ff:ff:ff:ff:ff:ff'] + logfilename = "/var/run/cloud/" + vm_name +".log" + if not os.path.exists(logfilename): + return ['_', '_'] + + lines = (line.rstrip() for line in open(logfilename)) + for line in lines: + try: + [_vmName,_vmID,_vmIP,_domID,_signature,_seqno,_vmMac] = line.split(',') + break + except ValueError,v: + [_vmName,_vmID,_vmIP,_domID,_signature,_seqno] = line.split(',') + + return [ _vmIP, _vmMac] + +@echo +def get_rule_logs_for_vms(session, args): + host_uuid = args.pop('host_uuid') + try: + thishost = session.xenapi.host.get_by_uuid(host_uuid) + hostrec = session.xenapi.host.get_record(thishost) + vms = hostrec.get('resident_VMs') + except: + util.SMlog("Failed to get host from uuid " + host_uuid) + return ' ' + + result = [] + try: + for name in [session.xenapi.VM.get_name_label(x) for x in vms]: + if 1 not in [ name.startswith(c) for c in ['r-', 's-', 'v-', 'i-', 'l-'] ]: + continue + network_rules_for_rebooted_vm(session, name) + if name.startswith('i-'): + log = get_rule_log_for_vm(session, name) + result.append(log) + except: + util.SMlog("Failed to get rule logs, better luck next time!") + + return ";".join(result) + +@echo +def cleanup_rules_for_dead_vms(session): + try: + vms = session.xenapi.VM.get_all() + cleaned = 0 + for vm_name in [session.xenapi.VM.get_name_label(x) for x in vms]: + if 1 in [ vm_name.startswith(c) for c in ['r-', 'i-', 's-', 'v-', 'l-'] ]: + vm = session.xenapi.VM.get_by_name_label(vm_name) + if len(vm) != 1: + continue + vm_rec = session.xenapi.VM.get_record(vm[0]) + state = vm_rec.get('power_state') + if state != 'Running' and state != 'Paused': + util.SMlog("vm " + vm_name + " is not running, cleaning up") + destroy_network_rules_for_vm(session, {'vmName':vm_name}) + cleaned = cleaned+1 + + util.SMlog("Cleaned up rules for " + str(cleaned) + " vms") + except: + util.SMlog("Failed to cleanup rules for dead vms!") + + +@echo +def cleanup_rules(session, args): + instance = args.get('instance') + if not instance: + instance = 'VM' + resident_vms = [] + try: + hostname = util.pread2(['/bin/bash', '-c', 'hostname']).split('\n') + if len(hostname) < 1: + raise Exception('Could not find hostname of this host') + thishost = session.xenapi.host.get_by_name_label(hostname[0]) + if len(thishost) < 1: + raise Exception("Could not find host record from hostname %s of this host"%hostname[0]) + hostrec = session.xenapi.host.get_record(thishost[0]) + vms = hostrec.get('resident_VMs') + resident_vms = [session.xenapi.VM.get_name_label(x) for x in vms] + util.SMlog('cleanup_rules: found %s resident vms on this host %s' % (len(resident_vms)-1, hostname[0])) + + chainscmd = "iptables-save | grep '^:' | awk '{print $1}' | cut -d':' -f2 | sed 's/-def/-%s/'| sed 's/-eg//' | sort|uniq" % instance + chains = util.pread2(['/bin/bash', '-c', chainscmd]).split('\n') + vmchains = [ch for ch in chains if 1 in [ ch.startswith(c) for c in ['r-', 'i-', 's-', 'v-', 'l-']]] + util.SMlog('cleanup_rules: found %s iptables chains for vms on this host %s' % (len(vmchains), hostname[0])) + cleaned = 0 + cleanup = [] + for chain in vmchains: + vm = session.xenapi.VM.get_by_name_label(chain) + if len(vm) != 1: + vm = session.xenapi.VM.get_by_name_label(chain + "-untagged") + if len(vm) != 1: + util.SMlog("chain " + chain + " does not correspond to a vm, cleaning up") + cleanup.append(chain) + continue + if chain not in resident_vms: + util.SMlog("vm " + chain + " is not running, cleaning up") + cleanup.append(chain) + + for vm_name in cleanup: + destroy_network_rules_for_vm(session, {'vmName':vm_name}) + + util.SMlog("Cleaned up rules for " + str(len(cleanup)) + " chains") + return str(len(cleanup)) + except Exception, ex: + util.SMlog("Failed to cleanup rules, reason= " + str(ex)) + return '-1'; + +@echo +def check_rule_log_for_vm(vmName, vmID, vmIP, domID, signature, seqno): + vm_name = vmName; + logfilename = "/var/run/cloud/" + vm_name +".log" + if not os.path.exists(logfilename): + util.SMlog("Failed to find logfile %s" %logfilename) + return [True, True, True] + + lines = (line.rstrip() for line in open(logfilename)) + + [_vmName,_vmID,_vmIP,_domID,_signature,_seqno,_vmMac] = ['_', '-1', '_', '-1', '_', '-1', 'ff:ff:ff:ff:ff:ff'] + try: + for line in lines: + try: + [_vmName,_vmID,_vmIP,_domID,_signature,_seqno, _vmMac] = line.split(',') + except ValueError,v: + [_vmName,_vmID,_vmIP,_domID,_signature,_seqno] = line.split(',') + break + except: + util.SMlog("Failed to parse log file for vm " + vmName) + remove_rule_log_for_vm(vmName) + return [True, True, True] + + reprogramDefault = False + if (domID != _domID) or (vmID != _vmID) or (vmIP != _vmIP): + util.SMlog("Change in default info set of vm %s" % vmName) + return [True, True, True] + else: + util.SMlog("No change in default info set of vm %s" % vmName) + + reprogramChain = False + rewriteLog = True + if (int(seqno) > int(_seqno)): + if (_signature != signature): + reprogramChain = True + util.SMlog("Seqno increased from %s to %s: reprogamming "\ + "ingress rules for vm %s" % (_seqno, seqno, vmName)) + else: + util.SMlog("Seqno increased from %s to %s: but no change "\ + "in signature for vm: skip programming ingress "\ + "rules %s" % (_seqno, seqno, vmName)) + elif (int(seqno) < int(_seqno)): + util.SMlog("Seqno decreased from %s to %s: ignoring these "\ + "ingress rules for vm %s" % (_seqno, seqno, vmName)) + rewriteLog = False + elif (signature != _signature): + util.SMlog("Seqno %s stayed the same but signature changed from "\ + "%s to %s for vm %s" % (seqno, _signature, signature, vmName)) + rewriteLog = True + reprogramChain = True + else: + util.SMlog("Seqno and signature stayed the same: %s : ignoring these "\ + "ingress rules for vm %s" % (seqno, vmName)) + rewriteLog = False + + return [reprogramDefault, reprogramChain, rewriteLog] + + +@echo +def write_rule_log_for_vm(vmName, vmID, vmIP, domID, signature, seqno, vmMac='ff:ff:ff:ff:ff:ff'): + vm_name = vmName + logfilename = "/var/run/cloud/" + vm_name +".log" + util.SMlog("Writing log to " + logfilename) + logf = open(logfilename, 'w') + output = ','.join([vmName, vmID, vmIP, domID, signature, seqno, vmMac]) + result = True + try: + logf.write(output) + logf.write('\n') + except: + util.SMlog("Failed to write to rule log file " + logfilename) + result = False + + logf.close() + + return result + +@echo +def remove_rule_log_for_vm(vmName): + vm_name = vmName + logfilename = "/var/run/cloud/" + vm_name +".log" + + result = True + try: + os.remove(logfilename) + except: + util.SMlog("Failed to delete rule log file " + logfilename) + result = False + + return result + +@echo +def inflate_rules (zipped): + return zlib.decompress(base64.b64decode(zipped)) + +@echo +def cache_ipset_keyword(): + tmpname = 'ipsetqzvxtmp' + try: + util.pread2(['/bin/bash', '-c', 'ipset -N ' + tmpname + ' iptreemap']) + except: + util.pread2(['/bin/bash', '-c', 'ipset -F ' + tmpname]) + + try: + util.pread2(['/bin/bash', '-c', 'iptables -A INPUT -m set --set ' + tmpname + ' src' + ' -j ACCEPT']) + util.pread2(['/bin/bash', '-c', 'iptables -D INPUT -m set --set ' + tmpname + ' src' + ' -j ACCEPT']) + keyword = 'set' + except: + keyword = 'match-set' + + try: + util.pread2(['/bin/bash', '-c', 'ipset -X ' + tmpname]) + except: + pass + + cachefile = "/var/cache/cloud/ipset.keyword" + util.SMlog("Writing ipset keyword to " + cachefile) + cachef = open(cachefile, 'w') + try: + cachef.write(keyword) + cachef.write('\n') + except: + util.SMlog("Failed to write to cache file " + cachef) + + cachef.close() + return keyword + +@echo +def get_ipset_keyword(): + cachefile = "/var/cache/cloud/ipset.keyword" + keyword = 'match-set' + + if not os.path.exists(cachefile): + util.SMlog("Failed to find ipset keyword cachefile %s" %cachefile) + keyword = cache_ipset_keyword() + else: + lines = (line.rstrip() for line in open(cachefile)) + for line in lines: + keyword = line + break + + return keyword + +@echo +def network_rules(session, args): + try: + vm_name = args.get('vmName') + vm_ip = args.get('vmIP') + vm_id = args.get('vmID') + vm_mac = args.get('vmMAC') + signature = args.pop('signature') + seqno = args.pop('seqno') + deflated = 'false' + if 'deflated' in args: + deflated = args.pop('deflated') + + try: + vm = session.xenapi.VM.get_by_name_label(vm_name) + if len(vm) != 1: + util.SMlog("### Could not get record for vm ## " + vm_name) + return 'false' + vm_rec = session.xenapi.VM.get_record(vm[0]) + domid = vm_rec.get('domid') + except: + util.SMlog("### Failed to get domid for vm ## " + vm_name) + return 'false' + if domid == '-1': + util.SMlog("### Failed to get domid for vm (-1): " + vm_name) + return 'false' + + vif = "vif" + domid + ".0" + tap = "tap" + domid + ".0" + vifs = [vif] + try: + util.pread2(['ifconfig', tap]) + vifs.append(tap) + except: + pass + + + reason = 'seqno_change_or_sig_change' + [reprogramDefault, reprogramChain, rewriteLog] = \ + check_rule_log_for_vm (vm_name, vm_id, vm_ip, domid, signature, seqno) + + if not reprogramDefault and not reprogramChain: + util.SMlog("No changes detected between current state and received state") + reason = 'seqno_same_sig_same' + if rewriteLog: + reason = 'seqno_increased_sig_same' + write_rule_log_for_vm(vm_name, vm_id, vm_ip, domid, signature, seqno, vm_mac) + util.SMlog("Programming network rules for vm %s seqno=%s signature=%s guestIp=%s,"\ + " do nothing, reason=%s" % (vm_name, seqno, signature, vm_ip, reason)) + return 'true' + + if not reprogramChain: + util.SMlog("###Not programming any ingress rules since no changes detected?") + return 'true' + + if reprogramDefault: + util.SMlog("Change detected in vmId or vmIp or domId, resetting default rules") + default_network_rules(session, args) + reason = 'domid_change' + + rules = args.pop('rules') + if deflated.lower() == 'true': + rules = inflate_rules (rules) + keyword = '--' + get_ipset_keyword() + lines = rules.split(' ') + + util.SMlog("Programming network rules for vm %s seqno=%s numrules=%s signature=%s guestIp=%s,"\ + " update iptables, reason=%s" % (vm_name, seqno, len(lines), signature, vm_ip, reason)) + + cmds = [] + egressrules = 0 + for line in lines: + tokens = line.split(':') + if len(tokens) != 5: + continue + type = tokens[0] + protocol = tokens[1] + start = tokens[2] + end = tokens[3] + cidrs = tokens.pop(); + ips = cidrs.split(",") + ips.pop() + allow_any = False + + if type == 'E': + vmchain = egress_chain_name(vm_name) + action = "RETURN" + direction = "dst" + egressrules = egressrules + 1 + else: + vmchain = chain_name(vm_name) + action = "ACCEPT" + direction = "src" + if '0.0.0.0/0' in ips: + i = ips.index('0.0.0.0/0') + del ips[i] + allow_any = True + range = start + ":" + end + if ips: + ipsetname = vmchain + "_" + protocol + "_" + start + "_" + end + if start == "-1": + ipsetname = vmchain + "_" + protocol + "_any" + + if ipset(ipsetname, protocol, start, end, ips) == False: + util.SMlog(" failed to create ipset for rule " + str(tokens)) + + if protocol == 'all': + iptables = ['iptables', '-I', vmchain, '-m', 'state', '--state', 'NEW', '-m', 'set', keyword, ipsetname, direction, '-j', action] + elif protocol != 'icmp': + iptables = ['iptables', '-I', vmchain, '-p', protocol, '-m', protocol, '--dport', range, '-m', 'state', '--state', 'NEW', '-m', 'set', keyword, ipsetname, direction, '-j', action] + else: + range = start + "/" + end + if start == "-1": + range = "any" + iptables = ['iptables', '-I', vmchain, '-p', 'icmp', '--icmp-type', range, '-m', 'set', keyword, ipsetname, direction, '-j', action] + + cmds.append(iptables) + util.SMlog(iptables) + + if allow_any and protocol != 'all': + if protocol != 'icmp': + iptables = ['iptables', '-I', vmchain, '-p', protocol, '-m', protocol, '--dport', range, '-m', 'state', '--state', 'NEW', '-j', action] + else: + range = start + "/" + end + if start == "-1": + range = "any" + iptables = ['iptables', '-I', vmchain, '-p', 'icmp', '--icmp-type', range, '-j', action] + cmds.append(iptables) + util.SMlog(iptables) + + vmchain = chain_name(vm_name) + util.pread2(['iptables', '-F', vmchain]) + egress_vmchain = egress_chain_name(vm_name) + util.pread2(['iptables', '-F', egress_vmchain]) + + for cmd in cmds: + util.pread2(cmd) + + if egressrules == 0 : + util.pread2(['iptables', '-A', egress_vmchain, '-j', 'RETURN']) + else: + util.pread2(['iptables', '-A', egress_vmchain, '-j', 'DROP']) + + util.pread2(['iptables', '-A', vmchain, '-j', 'DROP']) + + if write_rule_log_for_vm(vm_name, vm_id, vm_ip, domid, signature, seqno, vm_mac) == False: + return 'false' + + return 'true' + except: + util.SMlog("Failed to network rule !") + +@echo +def checkRouter(session, args): + sargs = args['args'] + cmd = sargs.split(' ') + cmd.insert(0, "/opt/cloud/bin/getRouterStatus.sh") + cmd.insert(0, "/bin/bash") + try: + txt = util.pread2(cmd) + except: + util.SMlog(" check router status fail! ") + txt = '' + + return txt + +@echo +def bumpUpPriority(session, args): + sargs = args['args'] + cmd = sargs.split(' ') + cmd.insert(0, "/opt/cloud/bin/bumpUpPriority.sh") + cmd.insert(0, "/bin/bash") + try: + txt = util.pread2(cmd) + txt = 'success' + except: + util.SMlog("bump up priority fail! ") + txt = '' + + return txt + +@echo +def setDNATRule(session, args): + add = args["add"] + if add == "false": + util.pread2(["iptables", "-t", "nat", "-F"]) + else: + ip = args["ip"] + port = args["port"] + util.pread2(["iptables", "-t", "nat", "-F"]) + util.pread2(["iptables", "-t", "nat", "-A", "PREROUTING", "-i", "xenbr0", "-p", "tcp", "--dport", port, "-m", "state", "--state", "NEW", "-j", "DNAT", "--to-destination", ip +":443"]) + return "" + +@echo +def createISOVHD(session, args): + # Should not create the VDI if the systemvm.iso does not exist + if not os.path.exists('/usr/share/xcp/packages/iso/systemvm.iso'): + return "Failed" + #hack for XCP on ubuntu 12.04, as can't attach iso to a vm + vdis = session.xenapi.VDI.get_by_name_label("systemvm-vdi"); + util.SMlog(vdis) + if len(vdis) > 0: + vdi_record = session.xenapi.VDI.get_record(vdis[0]) + vdi_uuid = vdi_record['uuid'] + return vdi_uuid + localsrUUid = args['uuid']; + sr = session.xenapi.SR.get_by_uuid(localsrUUid) + data = {'name_label': "systemvm-vdi", + 'SR': sr, + 'virtual_size': '50000000', + 'type': 'user', + 'sharable':False, + 'read_only':False, + 'other_config':{}, + } + vdi = session.xenapi.VDI.create(data); + vdi_record = session.xenapi.VDI.get_record(vdi) + + vdi_uuid = vdi_record['uuid'] + + vms = session.xenapi.VM.get_all() + ctrldom = None + for vm in vms: + dom0 = session.xenapi.VM.get_is_control_domain(vm) + if dom0 is False: + continue + else: + ctrldom = vm + + if ctrldom is None: + return "Failed" + + vbds = session.xenapi.VM.get_VBDs(ctrldom) + if len(vbds) == 0: + vbd = session.xenapi.VBD.create({"VDI": vdi, "VM": ctrldom, "type":"Disk", "device": "xvda4", "bootable": False, "mode": "RW", "userdevice": "4", "empty":False, + "other_config":{}, "qos_algorithm_type":"", "qos_algorithm_params":{}}) + else: + vbd = vbds[0] + + vbdr = session.xenapi.VBD.get_record(vbd) + if session.xenapi.VBD.get_currently_attached(vbd) is False: + session.xenapi.VBD.plug(vbd) + vbdr = session.xenapi.VBD.get_record(vbd) + util.pread2(["dd", "if=/usr/share/xcp/packages/iso/systemvm.iso", "of=" + "/dev/" + vbdr["device"]]) + session.xenapi.VBD.unplug(vbd) + session.xenapi.VBD.destroy(vbd) + return vdi_uuid + +@echo +def getDomRVersion(session, args): + sargs = args['args'] + cmd = sargs.split(' ') + cmd.insert(0, "/opt/cloud/bin/getDomRVersion.sh") + cmd.insert(0, "/bin/bash") + try: + txt = util.pread2(cmd) + except: + util.SMlog(" get domR version fail! ") + txt = '' + + return txt + +if __name__ == "__main__": + XenAPIPlugin.dispatch({"pingtest": pingtest, "setup_iscsi":setup_iscsi, "gethostvmstats": gethostvmstats, + "getgateway": getgateway, "preparemigration": preparemigration, + "setIptables": setIptables, "pingdomr": pingdomr, "pingxenserver": pingxenserver, + "ipassoc": ipassoc, "savePassword": savePassword, + "saveDhcpEntry": saveDhcpEntry, "setFirewallRule": setFirewallRule, + "setLoadBalancerRule": setLoadBalancerRule, "createFile": createFile, "deleteFile": deleteFile, + "networkUsage": networkUsage, "network_rules":network_rules, + "can_bridge_firewall":can_bridge_firewall, "default_network_rules":default_network_rules, + "destroy_network_rules_for_vm":destroy_network_rules_for_vm, + "default_network_rules_systemvm":default_network_rules_systemvm, + "get_rule_logs_for_vms":get_rule_logs_for_vms, + "setLinkLocalIP":setLinkLocalIP, "lt2p_vpn":lt2p_vpn, + "cleanup_rules":cleanup_rules, "checkRouter":checkRouter, + "bumpUpPriority":bumpUpPriority, "getDomRVersion":getDomRVersion, + "kill_copy_process":kill_copy_process, + "createISOVHD":createISOVHD, + "setDNATRule":setDNATRule}) diff --git a/scripts/vm/hypervisor/xenserver/xcposs/vmopsSnapshot b/scripts/vm/hypervisor/xenserver/xcposs/vmopsSnapshot new file mode 100644 index 0000000000..53f31a99ee --- /dev/null +++ b/scripts/vm/hypervisor/xenserver/xcposs/vmopsSnapshot @@ -0,0 +1,601 @@ +#!/usr/bin/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. + +# Version @VERSION@ +# +# A plugin for executing script needed by vmops cloud + +import os, sys, time +import XenAPIPlugin +sys.path.append("/usr/lib/xcp/sm/") +import SR, VDI, SRCommand, util, lvutil +from util import CommandException +import vhdutil +import shutil +import lvhdutil +import errno +import subprocess +import xs_errors +import cleanup +import stat +import random + +VHD_UTIL = 'vhd-util' +VHD_PREFIX = 'VHD-' +CLOUD_DIR = '/run/cloud_mount' + +def echo(fn): + def wrapped(*v, **k): + name = fn.__name__ + util.SMlog("#### VMOPS enter %s ####" % name ) + res = fn(*v, **k) + util.SMlog("#### VMOPS exit %s ####" % name ) + return res + return wrapped + + +@echo +def create_secondary_storage_folder(session, args): + local_mount_path = None + + util.SMlog("create_secondary_storage_folder, args: " + str(args)) + + try: + try: + # Mount the remote resource folder locally + remote_mount_path = args["remoteMountPath"] + local_mount_path = os.path.join(CLOUD_DIR, util.gen_uuid()) + mount(remote_mount_path, local_mount_path) + + # Create the new folder + new_folder = local_mount_path + "/" + args["newFolder"] + if not os.path.isdir(new_folder): + current_umask = os.umask(0) + os.makedirs(new_folder) + os.umask(current_umask) + except OSError, (errno, strerror): + errMsg = "create_secondary_storage_folder failed: errno: " + str(errno) + ", strerr: " + strerror + util.SMlog(errMsg) + raise xs_errors.XenError(errMsg) + except: + errMsg = "create_secondary_storage_folder failed." + util.SMlog(errMsg) + raise xs_errors.XenError(errMsg) + finally: + if local_mount_path != None: + # Unmount the local folder + umount(local_mount_path) + # Remove the local folder + os.system("rmdir " + local_mount_path) + + return "1" + +@echo +def delete_secondary_storage_folder(session, args): + local_mount_path = None + + util.SMlog("delete_secondary_storage_folder, args: " + str(args)) + + try: + try: + # Mount the remote resource folder locally + remote_mount_path = args["remoteMountPath"] + local_mount_path = os.path.join(CLOUD_DIR, util.gen_uuid()) + mount(remote_mount_path, local_mount_path) + + # Delete the specified folder + folder = local_mount_path + "/" + args["folder"] + if os.path.isdir(folder): + os.system("rm -f " + folder + "/*") + os.system("rmdir " + folder) + except OSError, (errno, strerror): + errMsg = "delete_secondary_storage_folder failed: errno: " + str(errno) + ", strerr: " + strerror + util.SMlog(errMsg) + raise xs_errors.XenError(errMsg) + except: + errMsg = "delete_secondary_storage_folder failed." + util.SMlog(errMsg) + raise xs_errors.XenError(errMsg) + finally: + if local_mount_path != None: + # Unmount the local folder + umount(local_mount_path) + # Remove the local folder + os.system("rmdir " + local_mount_path) + + return "1" + +@echo +def post_create_private_template(session, args): + local_mount_path = None + try: + try: + # get local template folder + templatePath = args["templatePath"] + local_mount_path = os.path.join(CLOUD_DIR, util.gen_uuid()) + mount(templatePath, local_mount_path) + # Retrieve args + filename = args["templateFilename"] + name = args["templateName"] + description = args["templateDescription"] + checksum = args["checksum"] + file_size = args["size"] + virtual_size = args["virtualSize"] + template_id = args["templateId"] + + # Create the template.properties file + template_properties_install_path = local_mount_path + "/template.properties" + f = open(template_properties_install_path, "w") + f.write("filename=" + filename + "\n") + f.write("vhd=true\n") + f.write("id=" + template_id + "\n") + f.write("vhd.filename=" + filename + "\n") + f.write("public=false\n") + f.write("uniquename=" + name + "\n") + f.write("vhd.virtualsize=" + virtual_size + "\n") + f.write("virtualsize=" + virtual_size + "\n") + f.write("checksum=" + checksum + "\n") + f.write("hvm=true\n") + f.write("description=" + description + "\n") + f.write("vhd.size=" + str(file_size) + "\n") + f.write("size=" + str(file_size) + "\n") + f.close() + util.SMlog("Created template.properties file") + + # Set permissions + permissions = stat.S_IREAD | stat.S_IWRITE | stat.S_IRGRP | stat.S_IWGRP | stat.S_IROTH | stat.S_IWOTH + os.chmod(template_properties_install_path, permissions) + util.SMlog("Set permissions on template and template.properties") + + except: + errMsg = "post_create_private_template failed." + util.SMlog(errMsg) + raise xs_errors.XenError(errMsg) + + finally: + if local_mount_path != None: + # Unmount the local folder + umount(local_mount_path) + # Remove the local folder + os.system("rmdir " + local_mount_path) + return "1" + +def isfile(path, isISCSI): + errMsg = '' + exists = True + if isISCSI: + exists = checkVolumeAvailablility(path) + else: + exists = os.path.isfile(path) + + if not exists: + errMsg = "File " + path + " does not exist." + util.SMlog(errMsg) + raise xs_errors.XenError(errMsg) + return errMsg + +def copyfile(fromFile, toFile, isISCSI): + util.SMlog("Starting to copy " + fromFile + " to " + toFile) + errMsg = '' + try: + cmd = ['dd', 'if=' + fromFile, 'of=' + toFile, 'bs=4M'] + txt = util.pread2(cmd) + except: + try: + os.system("rm -f " + toFile) + except: + txt = '' + txt = '' + errMsg = "Error while copying " + fromFile + " to " + toFile + " in secondary storage" + util.SMlog(errMsg) + raise xs_errors.XenError(errMsg) + + util.SMlog("Successfully copied " + fromFile + " to " + toFile) + return errMsg + +def chdir(path): + try: + os.chdir(path) + except OSError, (errno, strerror): + errMsg = "Unable to chdir to " + path + " because of OSError with errno: " + str(errno) + " and strerr: " + strerror + util.SMlog(errMsg) + raise xs_errors.XenError(errMsg) + util.SMlog("Chdired to " + path) + return + +def scanParent(path): + # Do a scan for the parent for ISCSI volumes + # Note that the parent need not be visible on the XenServer + parentUUID = '' + try: + lvName = os.path.basename(path) + dirname = os.path.dirname(path) + vgName = os.path.basename(dirname) + vhdInfo = vhdutil.getVHDInfoLVM(lvName, lvhdutil.extractUuid, vgName) + parentUUID = vhdInfo.parentUuid + except: + errMsg = "Could not get vhd parent of " + path + util.SMlog(errMsg) + raise xs_errors.XenError(errMsg) + return parentUUID + +def getParent(path, isISCSI): + parentUUID = '' + try : + if isISCSI: + parentUUID = vhdutil.getParent(path, lvhdutil.extractUuid) + else: + parentUUID = vhdutil.getParent(path, cleanup.FileVDI.extractUuid) + except: + errMsg = "Could not get vhd parent of " + path + util.SMlog(errMsg) + raise xs_errors.XenError(errMsg) + return parentUUID + +def getParentOfSnapshot(snapshotUuid, primarySRPath, isISCSI): + snapshotVHD = getVHD(snapshotUuid, isISCSI) + snapshotPath = os.path.join(primarySRPath, snapshotVHD) + + baseCopyUuid = '' + if isISCSI: + checkVolumeAvailablility(snapshotPath) + baseCopyUuid = scanParent(snapshotPath) + else: + baseCopyUuid = getParent(snapshotPath, isISCSI) + + util.SMlog("Base copy of snapshotUuid: " + snapshotUuid + " is " + baseCopyUuid) + return baseCopyUuid + +def setParent(parent, child): + try: + cmd = [VHD_UTIL, "modify", "-p", parent, "-n", child] + txt = util.pread2(cmd) + except: + errMsg = "Unexpected error while trying to set parent of " + child + " to " + parent + util.SMlog(errMsg) + raise xs_errors.XenError(errMsg) + util.SMlog("Successfully set parent of " + child + " to " + parent) + return + +def rename(originalVHD, newVHD): + try: + os.rename(originalVHD, newVHD) + except OSError, (errno, strerror): + errMsg = "OSError while renaming " + origiinalVHD + " to " + newVHD + "with errno: " + str(errno) + " and strerr: " + strerror + util.SMlog(errMsg) + raise xs_errors.XenError(errMsg) + return + +def makedirs(path): + if not os.path.isdir(path): + try: + os.makedirs(path) + except OSError, (errno, strerror): + umount(path) + if os.path.isdir(path): + return + errMsg = "OSError while creating " + path + " with errno: " + str(errno) + " and strerr: " + strerror + util.SMlog(errMsg) + raise xs_errors.XenError(errMsg) + return + +def mount(remoteDir, localDir): + makedirs(localDir) + options = "soft,tcp,timeo=133,retrans=1" + try: + cmd = ['mount', '-o', options, remoteDir, localDir] + txt = util.pread2(cmd) + except: + txt = '' + errMsg = "Unexpected error while trying to mount " + remoteDir + " to " + localDir + util.SMlog(errMsg) + raise xs_errors.XenError(errMsg) + util.SMlog("Successfully mounted " + remoteDir + " to " + localDir) + + return + +def umount(localDir): + try: + cmd = ['umount', localDir] + util.pread2(cmd) + except CommandException: + errMsg = "CommandException raised while trying to umount " + localDir + util.SMlog(errMsg) + raise xs_errors.XenError(errMsg) + + util.SMlog("Successfully unmounted " + localDir) + return + +def mountSnapshotsDir(secondaryStorageMountPath, localMountPointPath, path): + # The aim is to mount secondaryStorageMountPath on + # And create / dir on it, if it doesn't exist already. + # Assuming that secondaryStorageMountPath exists remotely + + # Just mount secondaryStorageMountPath//SecondaryStorageHost/ everytime + # Never unmount. + # path is like "snapshots/account/volumeId", we mount secondary_storage:/snapshots + relativeDir = path.split("/")[0] + restDir = "/".join(path.split("/")[1:]) + snapshotsDir = os.path.join(secondaryStorageMountPath, relativeDir) + + makedirs(localMountPointPath) + # if something is not mounted already on localMountPointPath, + # mount secondaryStorageMountPath on localMountPath + if os.path.ismount(localMountPointPath): + # There is more than one secondary storage per zone. + # And we are mounting each sec storage under a zone-specific directory + # So two secondary storage snapshot dirs will never get mounted on the same point on the same XenServer. + util.SMlog("The remote snapshots directory has already been mounted on " + localMountPointPath) + else: + mount(snapshotsDir, localMountPointPath) + + # Create accountId/instanceId dir on localMountPointPath, if it doesn't exist + backupsDir = os.path.join(localMountPointPath, restDir) + makedirs(backupsDir) + return backupsDir + +def unmountAll(path): + try: + for dir in os.listdir(path): + if dir.isdigit(): + util.SMlog("Unmounting Sub-Directory: " + dir) + localMountPointPath = os.path.join(path, dir) + umount(localMountPointPath) + except: + util.SMlog("Ignoring the error while trying to unmount the snapshots dir") + +@echo +def unmountSnapshotsDir(session, args): + dcId = args['dcId'] + localMountPointPath = os.path.join(CLOUD_DIR, dcId) + localMountPointPath = os.path.join(localMountPointPath, "snapshots") + unmountAll(localMountPointPath) + try: + umount(localMountPointPath) + except: + util.SMlog("Ignoring the error while trying to unmount the snapshots dir.") + + return "1" + +def getPrimarySRPath(session, primaryStorageSRUuid, isISCSI): + sr = session.xenapi.SR.get_by_uuid(primaryStorageSRUuid) + srrec = session.xenapi.SR.get_record(sr) + srtype = srrec["type"] + if srtype == "file": + pbd = session.xenapi.SR.get_PBDs(sr)[0] + pbdrec = session.xenapi.PBD.get_record(pbd) + primarySRPath = pbdrec["device_config"]["location"] + return primarySRPath + elif isISCSI: + primarySRDir = lvhdutil.VG_PREFIX + primaryStorageSRUuid + return os.path.join(lvhdutil.VG_LOCATION, primarySRDir) + else: + return os.path.join(SR.MOUNT_BASE, primaryStorageSRUuid) + +def getBackupVHD(UUID): + return UUID + '.' + SR.DEFAULT_TAP + +def getVHD(UUID, isISCSI): + if isISCSI: + return VHD_PREFIX + UUID + else: + return UUID + '.' + SR.DEFAULT_TAP + +def getIsTrueString(stringValue): + booleanValue = False + if (stringValue and stringValue == 'true'): + booleanValue = True + return booleanValue + +def makeUnavailable(uuid, primarySRPath, isISCSI): + if not isISCSI: + return + VHD = getVHD(uuid, isISCSI) + path = os.path.join(primarySRPath, VHD) + manageAvailability(path, '-an') + return + +def manageAvailability(path, value): + if path.__contains__("/var/run/sr-mount"): + return + util.SMlog("Setting availability of " + path + " to " + value) + try: + cmd = ['/usr/sbin/lvchange', value, path] + util.pread2(cmd) + except: #CommandException, (rc, cmdListStr, stderr): + #errMsg = "CommandException thrown while executing: " + cmdListStr + " with return code: " + str(rc) + " and stderr: " + stderr + errMsg = "Unexpected exception thrown by lvchange" + util.SMlog(errMsg) + if value == "-ay": + # Raise an error only if we are trying to make it available. + # Just warn if we are trying to make it unavailable after the + # snapshot operation is done. + raise xs_errors.XenError(errMsg) + return + + +def checkVolumeAvailablility(path): + try: + if not isVolumeAvailable(path): + # The VHD file is not available on XenSever. The volume is probably + # inactive or detached. + # Do lvchange -ay to make it available on XenServer + manageAvailability(path, '-ay') + except: + errMsg = "Could not determine status of ISCSI path: " + path + util.SMlog(errMsg) + raise xs_errors.XenError(errMsg) + + success = False + i = 0 + while i < 6: + i = i + 1 + # Check if the vhd is actually visible by checking for the link + # set isISCSI to true + success = isVolumeAvailable(path) + if success: + util.SMlog("Made vhd: " + path + " available and confirmed that it is visible") + break + + # Sleep for 10 seconds before checking again. + time.sleep(10) + + # If not visible within 1 min fail + if not success: + util.SMlog("Could not make vhd: " + path + " available despite waiting for 1 minute. Does it exist?") + + return success + +def isVolumeAvailable(path): + # Check if iscsi volume is available on this XenServer. + status = "0" + try: + p = subprocess.Popen(["/bin/bash", "-c", "if [ -L " + path + " ]; then echo 1; else echo 0;fi"], stdout=subprocess.PIPE) + status = p.communicate()[0].strip("\n") + except: + errMsg = "Could not determine status of ISCSI path: " + path + util.SMlog(errMsg) + raise xs_errors.XenError(errMsg) + + return (status == "1") + +def getVhdParent(session, args): + util.SMlog("getParent with " + str(args)) + primaryStorageSRUuid = args['primaryStorageSRUuid'] + snapshotUuid = args['snapshotUuid'] + isISCSI = getIsTrueString(args['isISCSI']) + + primarySRPath = getPrimarySRPath(session, primaryStorageSRUuid, isISCSI) + util.SMlog("primarySRPath: " + primarySRPath) + + baseCopyUuid = getParentOfSnapshot(snapshotUuid, primarySRPath, isISCSI) + + return baseCopyUuid + + +def backupSnapshot(session, args): + util.SMlog("Called backupSnapshot with " + str(args)) + primaryStorageSRUuid = args['primaryStorageSRUuid'] + secondaryStorageMountPath = args['secondaryStorageMountPath'] + snapshotUuid = args['snapshotUuid'] + prevBackupUuid = args['prevBackupUuid'] + backupUuid = args['backupUuid'] + isISCSI = getIsTrueString(args['isISCSI']) + path = args['path'] + localMountPoint = args['localMountPoint'] + primarySRPath = getPrimarySRPath(session, primaryStorageSRUuid, isISCSI) + util.SMlog("primarySRPath: " + primarySRPath) + + baseCopyUuid = getParentOfSnapshot(snapshotUuid, primarySRPath, isISCSI) + baseCopyVHD = getVHD(baseCopyUuid, isISCSI) + baseCopyPath = os.path.join(primarySRPath, baseCopyVHD) + util.SMlog("Base copy path: " + baseCopyPath) + + + # Mount secondary storage mount path on XenServer along the path + # /var/run/sr-mount//snapshots/ and create / dir + # on it. + backupsDir = mountSnapshotsDir(secondaryStorageMountPath, localMountPoint, path) + util.SMlog("Backups dir " + backupsDir) + prevBackupUuid = prevBackupUuid.split("/")[-1] + # Check existence of snapshot on primary storage + isfile(baseCopyPath, isISCSI) + if prevBackupUuid: + # Check existence of prevBackupFile + prevBackupVHD = getBackupVHD(prevBackupUuid) + prevBackupFile = os.path.join(backupsDir, prevBackupVHD) + isfile(prevBackupFile, False) + + # copy baseCopyPath to backupsDir with new uuid + backupVHD = getBackupVHD(backupUuid) + backupFile = os.path.join(backupsDir, backupVHD) + util.SMlog("Back up " + baseCopyUuid + " to Secondary Storage as " + backupUuid) + copyfile(baseCopyPath, backupFile, isISCSI) + vhdutil.setHidden(backupFile, False) + + # Because the primary storage is always scanned, the parent of this base copy is always the first base copy. + # We don't want that, we want a chain of VHDs each of which is a delta from the previous. + # So set the parent of the current baseCopyVHD to prevBackupVHD + if prevBackupUuid: + # If there was a previous snapshot + setParent(prevBackupFile, backupFile) + + txt = "1#" + backupUuid + return txt + +@echo +def deleteSnapshotBackup(session, args): + util.SMlog("Calling deleteSnapshotBackup with " + str(args)) + secondaryStorageMountPath = args['secondaryStorageMountPath'] + backupUUID = args['backupUUID'] + path = args['path'] + localMountPoint = args['localMountPoint'] + + backupsDir = mountSnapshotsDir(secondaryStorageMountPath, localMountPoint, path) + # chdir to the backupsDir for convenience + chdir(backupsDir) + + backupVHD = getBackupVHD(backupUUID) + util.SMlog("checking existence of " + backupVHD) + + # The backupVHD is on secondary which is NFS and not ISCSI. + if not os.path.isfile(backupVHD): + util.SMlog("backupVHD " + backupVHD + "does not exist. Not trying to delete it") + return "1" + util.SMlog("backupVHD " + backupVHD + " exists.") + + # Just delete the backupVHD + try: + os.remove(backupVHD) + except OSError, (errno, strerror): + errMsg = "OSError while removing " + backupVHD + " with errno: " + str(errno) + " and strerr: " + strerror + util.SMlog(errMsg) + raise xs_errors.XenError(errMsg) + + return "1" + +@echo +def revert_memory_snapshot(session, args): + util.SMlog("Calling revert_memory_snapshot with " + str(args)) + vmName = args['vmName'] + snapshotUUID = args['snapshotUUID'] + oldVmUuid = args['oldVmUuid'] + snapshotMemory = args['snapshotMemory'] + hostUUID = args['hostUUID'] + try: + cmd = '''xe vbd-list vm-uuid=%s | grep 'vdi-uuid' | grep -v 'not in database' | sed -e 's/vdi-uuid ( RO)://g' ''' % oldVmUuid + vdiUuids = os.popen(cmd).read().split() + cmd2 = '''xe vm-param-get param-name=power-state uuid=''' + oldVmUuid + if os.popen(cmd2).read().split()[0] != 'halted': + os.system("xe vm-shutdown force=true vm=" + vmName) + os.system("xe vm-destroy uuid=" + oldVmUuid) + os.system("xe snapshot-revert snapshot-uuid=" + snapshotUUID) + if snapshotMemory == 'true': + os.system("xe vm-resume vm=" + vmName + " on=" + hostUUID) + for vdiUuid in vdiUuids: + os.system("xe vdi-destroy uuid=" + vdiUuid) + except OSError, (errno, strerror): + errMsg = "OSError while reverting vm " + vmName + " to snapshot " + snapshotUUID + " with errno: " + str(errno) + " and strerr: " + strerror + util.SMlog(errMsg) + raise xs_errors.XenError(errMsg) + return "0" + +if __name__ == "__main__": + XenAPIPlugin.dispatch({"getVhdParent":getVhdParent, "create_secondary_storage_folder":create_secondary_storage_folder, "delete_secondary_storage_folder":delete_secondary_storage_folder, "post_create_private_template":post_create_private_template, "backupSnapshot": backupSnapshot, "deleteSnapshotBackup": deleteSnapshotBackup, "unmountSnapshotsDir": unmountSnapshotsDir, "revert_memory_snapshot":revert_memory_snapshot}) + + diff --git a/scripts/vm/hypervisor/xenserver/xcpserver/patch b/scripts/vm/hypervisor/xenserver/xcpserver/patch index 2376424ff5..0f9d9a0cec 100644 --- a/scripts/vm/hypervisor/xenserver/xcpserver/patch +++ b/scripts/vm/hypervisor/xenserver/xcpserver/patch @@ -31,7 +31,6 @@ NFSSR.py=/opt/xensource/sm vmops=..,0755,/etc/xapi.d/plugins ovstunnel=..,0755,/etc/xapi.d/plugins vmopsSnapshot=..,0755,/etc/xapi.d/plugins -hostvmstats.py=..,0755,/opt/xensource/sm systemvm.iso=../../../../../vms,0644,/opt/xensource/packages/iso id_rsa.cloud=../../../systemvm,0600,/root/.ssh network_info.sh=..,0755,/opt/cloud/bin diff --git a/scripts/vm/hypervisor/xenserver/xenserver56/patch b/scripts/vm/hypervisor/xenserver/xenserver56/patch index 16dcb5746a..e24136d8ea 100644 --- a/scripts/vm/hypervisor/xenserver/xenserver56/patch +++ b/scripts/vm/hypervisor/xenserver/xenserver56/patch @@ -30,7 +30,6 @@ NFSSR.py=/opt/xensource/sm vmops=..,0755,/etc/xapi.d/plugins vmopsSnapshot=..,0755,/etc/xapi.d/plugins cloudstack_pluginlib.py=..,0755,/etc/xapi.d/plugins -hostvmstats.py=..,0755,/opt/xensource/sm systemvm.iso=../../../../../vms,0644,/opt/xensource/packages/iso id_rsa.cloud=../../../systemvm,0600,/root/.ssh network_info.sh=..,0755,/opt/cloud/bin diff --git a/scripts/vm/hypervisor/xenserver/xenserver56fp1/patch b/scripts/vm/hypervisor/xenserver/xenserver56fp1/patch index 11bda07369..5e1559898d 100644 --- a/scripts/vm/hypervisor/xenserver/xenserver56fp1/patch +++ b/scripts/vm/hypervisor/xenserver/xenserver56fp1/patch @@ -30,7 +30,6 @@ NFSSR.py=/opt/xensource/sm vmops=..,0755,/etc/xapi.d/plugins vmopsSnapshot=..,0755,/etc/xapi.d/plugins cloudstack_pluginlib.py=..,0755,/etc/xapi.d/plugins -hostvmstats.py=..,0755,/opt/xensource/sm systemvm.iso=../../../../../vms,0644,/opt/xensource/packages/iso id_rsa.cloud=../../../systemvm,0600,/root/.ssh network_info.sh=..,0755,/opt/cloud/bin diff --git a/scripts/vm/hypervisor/xenserver/xenserver60/patch b/scripts/vm/hypervisor/xenserver/xenserver60/patch index 662327b6a8..84472a608d 100644 --- a/scripts/vm/hypervisor/xenserver/xenserver60/patch +++ b/scripts/vm/hypervisor/xenserver/xenserver60/patch @@ -34,7 +34,6 @@ cloudstack_plugins.conf=..,0644,/etc/xensource cloudstack_pluginlib.py=..,0755,/etc/xapi.d/plugins ovstunnel=..,0755,/etc/xapi.d/plugins vmopsSnapshot=..,0755,/etc/xapi.d/plugins -hostvmstats.py=..,0755,/opt/xensource/sm systemvm.iso=../../../../../vms,0644,/opt/xensource/packages/iso id_rsa.cloud=../../../systemvm,0600,/root/.ssh network_info.sh=..,0755,/opt/cloud/bin diff --git a/scripts/vm/hypervisor/xenserver/xenserver62/patch b/scripts/vm/hypervisor/xenserver/xenserver62/patch index 05c619b70c..03cdfadbb2 100644 --- a/scripts/vm/hypervisor/xenserver/xenserver62/patch +++ b/scripts/vm/hypervisor/xenserver/xenserver62/patch @@ -28,13 +28,13 @@ # If [source path] does not start with '/' or '~', then it is relative path to the location of the patch file. vmops=..,0755,/etc/xapi.d/plugins vmopspremium=..,0755,/etc/xapi.d/plugins +vmopsSnapshot=..,0755,/etc/xapi.d/plugins xen-ovs-vif-flows.rules=..,0644,/etc/udev/rules.d ovs-vif-flows.py=..,0755,/etc/xapi.d/plugins cloudstack_plugins.conf=..,0644,/etc/xensource cloudstack_pluginlib.py=..,0755,/etc/xapi.d/plugins ovstunnel=..,0755,/etc/xapi.d/plugins cloud-plugin-storage=,0755,/etc/xapi.d/plugins -hostvmstats.py=..,0755,/opt/xensource/sm systemvm.iso=../../../../../vms,0644,/opt/xensource/packages/iso id_rsa.cloud=../../../systemvm,0600,/root/.ssh network_info.sh=..,0755,/opt/cloud/bin @@ -50,7 +50,6 @@ setup_heartbeat_file.sh=..,0755,/opt/cloud/bin check_heartbeat.sh=..,0755,/opt/cloud/bin xenheartbeat.sh=..,0755,/opt/cloud/bin launch_hb.sh=..,0755,/opt/cloud/bin -vhd-util=..,0755,/opt/cloud/bin upgrade_snapshot.sh=..,0755,/opt/cloud/bin cloud-clean-vlan.sh=..,0755,/opt/cloud/bin cloud-prepare-upgrade.sh=..,0755,/opt/cloud/bin diff --git a/scripts/vm/network/security_group.py b/scripts/vm/network/security_group.py index 1d94de3d60..704b279820 100755 --- a/scripts/vm/network/security_group.py +++ b/scripts/vm/network/security_group.py @@ -978,7 +978,7 @@ def addFWFramework(brname): execute("iptables -N " + brfwin) try: - refs = execute("""iptables -n -L " + brfw + " | awk '/%s(.*)references/ {gsub(/\(/, "") ;print $3}'""" % brfw).strip() + refs = execute("""iptables -n -L %s | awk '/%s(.*)references/ {gsub(/\(/, "") ;print $3}'""" % (brfw,brfw)).strip() if refs == "0": execute("iptables -I FORWARD -i " + brname + " -j DROP") execute("iptables -I FORWARD -o " + brname + " -j DROP") diff --git a/scripts/vm/network/vnet/ovstunnel.py b/scripts/vm/network/vnet/ovstunnel.py index 57085d8592..c108c2952f 100755 --- a/scripts/vm/network/vnet/ovstunnel.py +++ b/scripts/vm/network/vnet/ovstunnel.py @@ -27,7 +27,7 @@ import sys import subprocess import time -import simplejson as json +import json from optparse import OptionParser, OptionGroup, OptParseError, BadOptionError, OptionError, OptionConflictError, OptionValueError from time import localtime as _localtime, asctime as _asctime @@ -73,7 +73,6 @@ def setup_ovs_bridge(bridge, key, cs_host_id): logging.debug("Setup_ovs_bridge completed with result:%s" % result) return result -@echo def setup_ovs_bridge_for_distributed_routing(bridge, cs_host_id): res = lib.check_switch() @@ -281,7 +280,7 @@ def get_field_of_interface(iface_name, field): parser.add_option("--src_host", dest="src_host") parser.add_option("--dst_host", dest="dst_host") parser.add_option("--iface_name", dest="iface_name") - parser.ad_option("--config", dest="config") + parser.add_option("--config", dest="config") (option, args) = parser.parse_args() if len(args) == 0: logging.debug("No command to execute") diff --git a/server/resources/META-INF/cloudstack/core/spring-server-core-managers-context.xml b/server/resources/META-INF/cloudstack/core/spring-server-core-managers-context.xml index fc1c7e23b9..09abcb767b 100644 --- a/server/resources/META-INF/cloudstack/core/spring-server-core-managers-context.xml +++ b/server/resources/META-INF/cloudstack/core/spring-server-core-managers-context.xml @@ -74,6 +74,7 @@ + diff --git a/server/resources/META-INF/cloudstack/core/spring-server-core-misc-context.xml b/server/resources/META-INF/cloudstack/core/spring-server-core-misc-context.xml index 91401e3354..479dc9ce96 100644 --- a/server/resources/META-INF/cloudstack/core/spring-server-core-misc-context.xml +++ b/server/resources/META-INF/cloudstack/core/spring-server-core-misc-context.xml @@ -52,7 +52,9 @@ - + + + diff --git a/server/src/com/cloud/acl/DomainChecker.java b/server/src/com/cloud/acl/DomainChecker.java index cb6921d9fa..9ee65db935 100755 --- a/server/src/com/cloud/acl/DomainChecker.java +++ b/server/src/com/cloud/acl/DomainChecker.java @@ -19,6 +19,7 @@ import javax.ejb.Local; import javax.inject.Inject; +import org.apache.log4j.Logger; import org.springframework.stereotype.Component; import org.apache.cloudstack.acl.ControlledEntity; @@ -50,6 +51,8 @@ @Local(value = SecurityChecker.class) public class DomainChecker extends AdapterBase implements SecurityChecker { + public static final Logger s_logger = Logger.getLogger(DomainChecker.class); + @Inject DomainDao _domainDao; @Inject @@ -101,6 +104,15 @@ public boolean checkAccess(User user, Domain domain) throws PermissionDeniedExce @Override public boolean checkAccess(Account caller, ControlledEntity entity, AccessType accessType) throws PermissionDeniedException { + + if (caller.getId() == Account.ACCOUNT_ID_SYSTEM || _accountService.isRootAdmin(caller.getId())) { + // no need to make permission checks if the system/root admin makes the call + if (s_logger.isTraceEnabled()) { + s_logger.trace("No need to make permission check for System/RootAdmin account, returning true"); + } + return true; + } + if (entity instanceof VirtualMachineTemplate) { VirtualMachineTemplate template = (VirtualMachineTemplate)entity; @@ -328,6 +340,34 @@ else if (_accountService.isDomainAdmin(account.getId())) { @Override public boolean checkAccess(Account caller, ControlledEntity entity, AccessType accessType, String action) throws PermissionDeniedException { + + if (action != null && ("SystemCapability".equals(action))) { + if (caller != null && caller.getType() == Account.ACCOUNT_TYPE_ADMIN) { + return true; + } + + } else if (action != null && ("DomainCapability".equals(action))) { + if (caller != null && caller.getType() == Account.ACCOUNT_TYPE_DOMAIN_ADMIN) { + return true; + } + } else if (action != null && ("DomainResourceCapability".equals(action))) { + if (caller != null && caller.getType() == Account.ACCOUNT_TYPE_RESOURCE_DOMAIN_ADMIN) { + return true; + } + } return checkAccess(caller, entity, accessType); } + + @Override + public boolean checkAccess(Account caller, AccessType accessType, String action, ControlledEntity... entities) + throws PermissionDeniedException { + + // returns true only if access to all entities is granted + for (ControlledEntity entity : entities) { + if (!checkAccess(caller, entity, accessType, action)) { + return false; + } + } + return true; + } } diff --git a/server/src/com/cloud/agent/manager/allocator/impl/FirstFitAllocator.java b/server/src/com/cloud/agent/manager/allocator/impl/FirstFitAllocator.java index 37368846da..3bd5c94377 100755 --- a/server/src/com/cloud/agent/manager/allocator/impl/FirstFitAllocator.java +++ b/server/src/com/cloud/agent/manager/allocator/impl/FirstFitAllocator.java @@ -243,7 +243,7 @@ protected List allocateTo(DeploymentPlan plan, ServiceOffering offering, V // We will try to reorder the host lists such that we give priority to hosts that have // the minimums to support a VM's requirements - hosts = prioritizeHosts(template, hosts); + hosts = prioritizeHosts(template, offering, hosts); if (s_logger.isDebugEnabled()) { s_logger.debug("Found " + hosts.size() + " hosts for allocation after prioritization: " + hosts); @@ -278,10 +278,12 @@ protected List allocateTo(DeploymentPlan plan, ServiceOffering offering, V } // Check if GPU device is required by offering and host has the availability - if ((offeringDetails = _serviceOfferingDetailsDao.findDetail(serviceOfferingId, GPU.Keys.vgpuType.toString())) != null - && !_resourceMgr.isGPUDeviceAvailable(host.getId(), offeringDetails.getValue())){ - s_logger.info("Host name: " + host.getName() + ", hostId: "+ host.getId() +" does not have required GPU devices available"); - continue; + if ((offeringDetails = _serviceOfferingDetailsDao.findDetail(serviceOfferingId, GPU.Keys.vgpuType.toString())) != null) { + ServiceOfferingDetailsVO groupName = _serviceOfferingDetailsDao.findDetail(serviceOfferingId, GPU.Keys.pciDevice.toString()); + if(!_resourceMgr.isGPUDeviceAvailable(host.getId(), groupName.getValue(), offeringDetails.getValue())){ + s_logger.info("Host name: " + host.getName() + ", hostId: "+ host.getId() +" does not have required GPU devices available"); + continue; + } } int cpu_requested = offering.getCpu() * offering.getSpeed(); @@ -353,7 +355,7 @@ public boolean isVirtualMachineUpgradable(VirtualMachine vm, ServiceOffering off return true; } - protected List prioritizeHosts(VMTemplateVO template, List hosts) { + protected List prioritizeHosts(VMTemplateVO template, ServiceOffering offering, List hosts) { if (template == null) { return hosts; } @@ -416,6 +418,22 @@ protected List prioritizeHosts(VMTemplateVO template, List gpuEnabledHosts = new ArrayList(); + // Check for GPU enabled hosts. + for (Host host : prioritizedHosts) { + if (_resourceMgr.isHostGpuEnabled(host.getId())) { + gpuEnabledHosts.add(host); + } + } + // Move GPU enabled hosts to the end of list + if(!gpuEnabledHosts.isEmpty()) { + prioritizedHosts.removeAll(gpuEnabledHosts); + prioritizedHosts.addAll(gpuEnabledHosts); + } + } return prioritizedHosts; } diff --git a/server/src/com/cloud/api/ApiAsyncJobDispatcher.java b/server/src/com/cloud/api/ApiAsyncJobDispatcher.java index f037f2e81a..71adf2ad34 100644 --- a/server/src/com/cloud/api/ApiAsyncJobDispatcher.java +++ b/server/src/com/cloud/api/ApiAsyncJobDispatcher.java @@ -75,6 +75,9 @@ public void runJob(final AsyncJob job) { // whenever we deserialize, the UserContext needs to be updated String userIdStr = params.get("ctxUserId"); String acctIdStr = params.get("ctxAccountId"); + String contextDetails = params.get("ctxDetails"); + + Long userId = null; Account accountObject = null; @@ -94,7 +97,12 @@ public void runJob(final AsyncJob job) { accountObject = _entityMgr.findById(Account.class, Long.parseLong(acctIdStr)); } - CallContext.register(user, accountObject); + CallContext ctx = CallContext.register(user, accountObject); + if(contextDetails != null){ + Type objectMapType = new TypeToken>() {}.getType(); + ctx.putContextParameters((Map) gson.fromJson(contextDetails, objectMapType)); + } + try { // dispatch could ultimately queue the job _dispatcher.dispatch(cmdObj, params, true); diff --git a/server/src/com/cloud/api/ApiDBUtils.java b/server/src/com/cloud/api/ApiDBUtils.java index 432eb941ab..a953cd645e 100755 --- a/server/src/com/cloud/api/ApiDBUtils.java +++ b/server/src/com/cloud/api/ApiDBUtils.java @@ -18,7 +18,9 @@ import java.util.ArrayList; import java.util.EnumSet; +import java.util.HashMap; import java.util.List; +import java.util.ListIterator; import java.util.Map; import java.util.Set; @@ -63,6 +65,7 @@ import org.apache.cloudstack.storage.datastore.db.PrimaryDataStoreDao; import org.apache.cloudstack.storage.datastore.db.StoragePoolVO; +import com.cloud.agent.api.VgpuTypesInfo; import com.cloud.api.query.dao.AccountJoinDao; import com.cloud.api.query.dao.AffinityGroupJoinDao; import com.cloud.api.query.dao.AsyncJobJoinDao; @@ -236,6 +239,7 @@ import com.cloud.storage.Snapshot; import com.cloud.storage.SnapshotVO; import com.cloud.storage.Storage.ImageFormat; +import com.cloud.storage.Storage.StoragePoolType; import com.cloud.storage.StorageManager; import com.cloud.storage.StoragePool; import com.cloud.storage.StorageStats; @@ -1071,6 +1075,26 @@ public static HypervisorType getHypervisorTypeFromFormat(long dcId, ImageFormat if (xenClusters.isEmpty()) { type = HypervisorType.Hyperv; } + } if (format == ImageFormat.RAW) { + // Currently, KVM only suppoorts RBD images of type RAW. + // This results in a weird collision with OVM volumes which + // can only be raw, thus making KVM RBD volumes show up as OVM + // rather than RBD. This block of code can (hopefuly) by checking to + // see if the pool is using either RBD or NFS. However, it isn't + // quite clear what to do if both storage types are used. If the image + // format is RAW, it narrows the hypervisor choice down to OVM and KVM / RBD or KVM / CLVM + // This would be better implemented at a cluster level. + List pools = s_storagePoolDao.listByDataCenterId(dcId); + ListIterator itr = pools.listIterator(); + while(itr.hasNext()) { + StoragePoolVO pool = itr.next(); + if(pool.getPoolType() == StoragePoolType.RBD || pool.getPoolType() == StoragePoolType.CLVM) { + // This case will note the presence of non-qcow2 primary stores, suggesting KVM without NFS. Otherwse, + // If this check is not passed, the hypervisor type will remain OVM. + type = HypervisorType.KVM; + break; + } + } } return type; } @@ -1079,6 +1103,14 @@ public static List getGpuGroups(long hostId) { return s_hostGpuGroupsDao.listByHostId(hostId); } + public static List getGpuCapacites(Long zoneId, Long podId, Long clusterId) { + return s_vgpuTypesDao.listGPUCapacities(zoneId, podId, clusterId); + } + + public static HashMap getVgpuVmsCount(Long zoneId, Long podId, Long clusterId) { + return s_vmDao.countVgpuVMs(zoneId, podId, clusterId); + } + public static List getVgpus(long groupId) { return s_vgpuTypesDao.listByGroupId(groupId); } @@ -1091,6 +1123,16 @@ public static List listUserVMsByHostId(long hostId) { return s_userVmDao.listByHostId(hostId); } + public static List listUserVMsByNetworkId(long networkId) { + return s_userVmDao.listByNetworkIdAndStates(networkId, VirtualMachine.State.Running, + VirtualMachine.State.Starting, VirtualMachine.State.Stopping, VirtualMachine.State.Unknown, + VirtualMachine.State.Migrating); + } + + public static List listDomainRoutersByNetworkId(long networkId) { + return s_domainRouterDao.findByNetwork(networkId); + } + public static List listZones() { return s_zoneDao.listAll(); } @@ -1819,7 +1861,7 @@ public static Map getResourceDetails(long resourceId, ResourceOb } public static boolean isAdmin(Account account) { - return s_accountService.isAdmin(account.getType()); + return s_accountService.isAdmin(account.getId()); } public static List listResourceTagViewByResourceUUID(String resourceUUID, ResourceObjectType resourceType) { diff --git a/server/src/com/cloud/api/ApiDispatcher.java b/server/src/com/cloud/api/ApiDispatcher.java index 95074e24bb..b6b9b2915a 100755 --- a/server/src/com/cloud/api/ApiDispatcher.java +++ b/server/src/com/cloud/api/ApiDispatcher.java @@ -23,10 +23,6 @@ import org.apache.log4j.Logger; -import org.apache.cloudstack.acl.ControlledEntity; -import org.apache.cloudstack.acl.InfrastructureEntity; -import org.apache.cloudstack.acl.SecurityChecker.AccessType; -import org.apache.cloudstack.api.APICommand; import org.apache.cloudstack.api.ApiConstants; import org.apache.cloudstack.api.BaseAsyncCmd; import org.apache.cloudstack.api.BaseAsyncCreateCmd; @@ -40,11 +36,7 @@ import com.cloud.api.dispatch.DispatchChain; import com.cloud.api.dispatch.DispatchChainFactory; import com.cloud.api.dispatch.DispatchTask; -import com.cloud.event.EventTypes; -import com.cloud.user.Account; import com.cloud.user.AccountManager; -import com.cloud.utils.ReflectUtil; -import com.cloud.vm.VirtualMachine; public class ApiDispatcher { private static final Logger s_logger = Logger.getLogger(ApiDispatcher.class.getName()); @@ -80,24 +72,6 @@ public void setCreateSnapshotQueueSizeLimit(final Long snapshotLimit) { public void dispatchCreateCmd(final BaseAsyncCreateCmd cmd, final Map params) throws Exception { asyncCreationDispatchChain.dispatch(new DispatchTask(cmd, params)); - CallContext.current().setEventDisplayEnabled(cmd.isDisplayResourceEnabled()); - } - - private void doAccessChecks(BaseCmd cmd, Map entitiesToAccess) { - Account caller = CallContext.current().getCallingAccount(); - - APICommand commandAnnotation = cmd.getClass().getAnnotation(APICommand.class); - String apiName = commandAnnotation != null ? commandAnnotation.name() : null; - - if (!entitiesToAccess.isEmpty()) { - for (Object entity : entitiesToAccess.keySet()) { - if (entity instanceof ControlledEntity) { - _accountMgr.checkAccess(caller, entitiesToAccess.get(entity), false, apiName, (ControlledEntity) entity); - } else if (entity instanceof InfrastructureEntity) { - //FIXME: Move this code in adapter, remove code from Account manager - } - } - } } public void dispatch(final BaseCmd cmd, final Map params, final boolean execute) throws Exception { @@ -105,26 +79,15 @@ public void dispatch(final BaseCmd cmd, final Map params, final standardDispatchChain.dispatch(new DispatchTask(cmd, params)); final CallContext ctx = CallContext.current(); - ctx.setEventDisplayEnabled(cmd.isDisplayResourceEnabled()); + ctx.setEventDisplayEnabled(cmd.isDisplay()); // TODO This if shouldn't be here. Use polymorphism and move it to validateSpecificParameters if (cmd instanceof BaseAsyncCmd) { final BaseAsyncCmd asyncCmd = (BaseAsyncCmd)cmd; final String startEventId = params.get(ApiConstants.CTX_START_EVENT_ID); - String uuid = params.get(ApiConstants.UUID); ctx.setStartEventId(Long.valueOf(startEventId)); - // Fow now use the key from EventTypes.java rather than getInstanceType bcz the later doesn't refer to the interfaces - // Add the resource id in the call context, also add some other first class object ids (for now vm) if available. - // TODO - this should be done for all the uuids passed in the cmd - so should be moved where uuid to id conversion happens. - if(EventTypes.getEntityForEvent(asyncCmd.getEventType()) != null){ - ctx.putContextParameter(EventTypes.getEntityForEvent(asyncCmd.getEventType()), uuid); - } - if(params.get(ApiConstants.VIRTUAL_MACHINE_ID) != null){ - ctx.putContextParameter(ReflectUtil.getEntityName(VirtualMachine.class), params.get(ApiConstants.VIRTUAL_MACHINE_ID)); - } - // Synchronise job on the object if needed if (asyncCmd.getJob() != null && asyncCmd.getSyncObjId() != null && asyncCmd.getSyncObjType() != null) { Long queueSizeLimit = null; diff --git a/server/src/com/cloud/api/ApiResponseHelper.java b/server/src/com/cloud/api/ApiResponseHelper.java index a37bf7b2d4..ce685c6dff 100755 --- a/server/src/com/cloud/api/ApiResponseHelper.java +++ b/server/src/com/cloud/api/ApiResponseHelper.java @@ -150,6 +150,7 @@ import org.apache.cloudstack.usage.UsageService; import org.apache.cloudstack.usage.UsageTypes; +import com.cloud.agent.api.VgpuTypesInfo; import com.cloud.api.query.ViewResponseHelper; import com.cloud.api.query.vo.AccountJoinVO; import com.cloud.api.query.vo.AsyncJobJoinVO; @@ -193,6 +194,7 @@ import com.cloud.event.Event; import com.cloud.exception.InvalidParameterValueException; import com.cloud.exception.PermissionDeniedException; +import com.cloud.gpu.GPU; import com.cloud.host.Host; import com.cloud.host.HostVO; import com.cloud.hypervisor.HypervisorCapabilities; @@ -1735,6 +1737,48 @@ public List createCapacityResponse(List re capacityResponses.add(capacityResponse); } + List gpuCapacities; + if (!result.isEmpty() && (gpuCapacities = ApiDBUtils.getGpuCapacites(result.get(0).getDataCenterId(), result.get(0).getPodId(), result.get(0).getClusterId())) != null) { + HashMap vgpuVMs = ApiDBUtils.getVgpuVmsCount(result.get(0).getDataCenterId(), result.get(0).getPodId(), result.get(0).getClusterId()); + + float capacityUsed = 0; + long capacityMax = 0; + for (VgpuTypesInfo capacity : gpuCapacities) { + if (vgpuVMs.containsKey(capacity.getGroupName().concat(capacity.getModelName()))) { + capacityUsed += (float)vgpuVMs.get(capacity.getGroupName().concat(capacity.getModelName())) / capacity.getMaxVpuPerGpu(); + } + if (capacity.getModelName().equals(GPU.vGPUType.passthrough.toString())) { + capacityMax += capacity.getMaxCapacity(); + } + } + + DataCenter zone = ApiDBUtils.findZoneById(result.get(0).getDataCenterId()); + CapacityResponse capacityResponse = new CapacityResponse(); + if (zone != null) { + capacityResponse.setZoneId(zone.getUuid()); + capacityResponse.setZoneName(zone.getName()); + } + if (result.get(0).getPodId() != null) { + HostPodVO pod = ApiDBUtils.findPodById(result.get(0).getPodId()); + capacityResponse.setPodId(pod.getUuid()); + capacityResponse.setPodName(pod.getName()); + } + if (result.get(0).getClusterId() != null) { + ClusterVO cluster = ApiDBUtils.findClusterById(result.get(0).getClusterId()); + capacityResponse.setClusterId(cluster.getUuid()); + capacityResponse.setClusterName(cluster.getName()); + } + capacityResponse.setCapacityType(Capacity.CAPACITY_TYPE_GPU); + capacityResponse.setCapacityUsed((long)Math.ceil(capacityUsed)); + capacityResponse.setCapacityTotal(capacityMax); + if (capacityMax > 0) { + capacityResponse.setPercentUsed(format.format(capacityUsed / capacityMax * 100f)); + } else { + capacityResponse.setPercentUsed(format.format(0)); + } + capacityResponse.setObjectName("capacity"); + capacityResponses.add(capacityResponse); + } return capacityResponses; } @@ -1811,7 +1855,7 @@ public AsyncJobResponse queryJobResult(QueryAsyncJobResultCmd cmd) { throw new PermissionDeniedException("Account " + caller + " is not authorized to see job id=" + job.getId()); } } else if (_accountMgr.isDomainAdmin(caller.getId())) { - _accountMgr.checkAccess(caller, null, true, jobOwner); + _accountMgr.checkAccess(caller, null, jobOwner); } return createAsyncJobResponse(_jobMgr.queryJob(cmd.getId(), true)); @@ -1901,6 +1945,7 @@ public NetworkOfferingResponse createNetworkOfferingResponse(NetworkOffering off response.setNetworkRate(ApiDBUtils.getNetworkRate(offering.getId())); response.setEgressDefaultPolicy(offering.getEgressDefaultPolicy()); response.setConcurrentConnections(offering.getConcurrentConnections()); + response.setSupportsStrechedL2Subnet(offering.getSupportsStrechedL2()); Long so = null; if (offering.getServiceOfferingId() != null) { so = offering.getServiceOfferingId(); @@ -2204,6 +2249,18 @@ public NetworkResponse createNetworkResponse(ResponseView view, Network network) } } + response.setStrechedL2Subnet(network.isStrechedL2Network()); + if (network.isStrechedL2Network()) { + Set networkSpannedZones = new HashSet(); + List vmInstances = new ArrayList(); + vmInstances.addAll(ApiDBUtils.listUserVMsByNetworkId(network.getId())); + vmInstances.addAll(ApiDBUtils.listDomainRoutersByNetworkId(network.getId())); + for (VirtualMachine vm : vmInstances) { + DataCenter vmZone = ApiDBUtils.findZoneById(vm.getDataCenterId()); + networkSpannedZones.add(vmZone.getUuid()); + } + response.setNetworkSpannedZones(networkSpannedZones); + } response.setObjectName("network"); return response; } @@ -2766,6 +2823,7 @@ public VpcOfferingResponse createVpcOfferingResponse(VpcOffering offering) { response.setIsDefault(offering.isDefault()); response.setState(offering.getState().name()); response.setSupportsDistributedRouter(offering.supportsDistributedRouter()); + response.setSupportsRegionLevelVpc(offering.offersRegionLevelVPC()); Map> serviceProviderMap = ApiDBUtils.listVpcOffServices(offering.getId()); List serviceResponses = new ArrayList(); @@ -2809,6 +2867,7 @@ public VpcResponse createVpcResponse(ResponseView view, Vpc vpc) { response.setNetworkDomain(vpc.getNetworkDomain()); response.setForDisplay(vpc.isDisplay()); response.setUsesDistributedRouter(vpc.usesDistributedRouter()); + response.setRegionLevelVpc(vpc.isRegionLevelVpc()); Map> serviceProviderMap = ApiDBUtils.listVpcOffServices(vpc.getVpcOfferingId()); List serviceResponses = new ArrayList(); @@ -3143,6 +3202,7 @@ public GuestOSResponse createGuestOSResponse(GuestOS guestOS) { GuestOSResponse response = new GuestOSResponse(); response.setDescription(guestOS.getDisplayName()); response.setId(guestOS.getUuid()); + response.setIsUserDefined(Boolean.valueOf(guestOS.getIsUserDefined()).toString()); GuestOSCategoryVO category = ApiDBUtils.findGuestOsCategoryById(guestOS.getCategoryId()); if (category != null) { response.setOsCategoryId(category.getUuid()); @@ -3159,6 +3219,7 @@ public GuestOsMappingResponse createGuestOSMappingResponse(GuestOSHypervisor gue response.setHypervisor(guestOSHypervisor.getHypervisorType()); response.setHypervisorVersion(guestOSHypervisor.getHypervisorVersion()); response.setOsNameForHypervisor((guestOSHypervisor.getGuestOsName())); + response.setIsUserDefined(Boolean.valueOf(guestOSHypervisor.getIsUserDefined()).toString()); GuestOS guestOs = ApiDBUtils.findGuestOSById(guestOSHypervisor.getGuestOsId()); if (guestOs != null) { response.setOsStdName(guestOs.getDisplayName()); @@ -3221,8 +3282,10 @@ public UsageRecordResponse createUsageResponse(Usage usageRecord) { usageRecResponse.setUsage(usageRecord.getUsageDisplay()); usageRecResponse.setUsageType(usageRecord.getUsageType()); if (usageRecord.getVmInstanceId() != null) { - VMInstanceVO vm = _entityMgr.findById(VMInstanceVO.class, usageRecord.getVmInstanceId()); - usageRecResponse.setVirtualMachineId(vm.getUuid()); + VMInstanceVO vm = _entityMgr.findByIdIncludingRemoved(VMInstanceVO.class, usageRecord.getVmInstanceId()); + if (vm != null) { + usageRecResponse.setVirtualMachineId(vm.getUuid()); + } } usageRecResponse.setVmName(usageRecord.getVmName()); if (usageRecord.getTemplateId() != null) { @@ -3237,8 +3300,10 @@ public UsageRecordResponse createUsageResponse(Usage usageRecord) { //Service Offering Id usageRecResponse.setOfferingId(svcOffering.getUuid()); //VM Instance ID - VMInstanceVO vm = _entityMgr.findById(VMInstanceVO.class, usageRecord.getUsageId().toString()); - usageRecResponse.setUsageId(vm.getUuid()); + VMInstanceVO vm = _entityMgr.findByIdIncludingRemoved(VMInstanceVO.class, usageRecord.getUsageId().toString()); + if (vm != null) { + usageRecResponse.setUsageId(vm.getUuid()); + } //Hypervisor Type usageRecResponse.setType(usageRecord.getType()); @@ -3248,52 +3313,69 @@ public UsageRecordResponse createUsageResponse(Usage usageRecord) { //isSystem usageRecResponse.setSystem((usageRecord.getSize() == 1) ? true : false); //IP Address ID - IPAddressVO ip = _entityMgr.findById(IPAddressVO.class, usageRecord.getUsageId().toString()); - usageRecResponse.setUsageId(ip.getUuid()); + IPAddressVO ip = _entityMgr.findByIdIncludingRemoved(IPAddressVO.class, usageRecord.getUsageId().toString()); + if (ip != null) { + usageRecResponse.setUsageId(ip.getUuid()); + } } else if (usageRecord.getUsageType() == UsageTypes.NETWORK_BYTES_SENT || usageRecord.getUsageType() == UsageTypes.NETWORK_BYTES_RECEIVED) { //Device Type usageRecResponse.setType(usageRecord.getType()); if (usageRecord.getType().equals("DomainRouter")) { //Domain Router Id - VMInstanceVO vm = _entityMgr.findById(VMInstanceVO.class, usageRecord.getUsageId().toString()); - usageRecResponse.setUsageId(vm.getUuid()); + VMInstanceVO vm = _entityMgr.findByIdIncludingRemoved(VMInstanceVO.class, usageRecord.getUsageId().toString()); + if (vm != null) { + usageRecResponse.setUsageId(vm.getUuid()); + } } else { //External Device Host Id - HostVO host = _entityMgr.findById(HostVO.class, usageRecord.getUsageId().toString()); - usageRecResponse.setUsageId(host.getUuid()); + HostVO host = _entityMgr.findByIdIncludingRemoved(HostVO.class, usageRecord.getUsageId().toString()); + if (host != null) { + usageRecResponse.setUsageId(host.getUuid()); + } } //Network ID - NetworkVO network = _entityMgr.findById(NetworkVO.class, usageRecord.getNetworkId().toString()); - usageRecResponse.setNetworkId(network.getUuid()); + NetworkVO network = _entityMgr.findByIdIncludingRemoved(NetworkVO.class, usageRecord.getNetworkId().toString()); + if (network != null) { + usageRecResponse.setNetworkId(network.getUuid()); + } } else if (usageRecord.getUsageType() == UsageTypes.VM_DISK_IO_READ || usageRecord.getUsageType() == UsageTypes.VM_DISK_IO_WRITE || usageRecord.getUsageType() == UsageTypes.VM_DISK_BYTES_READ || usageRecord.getUsageType() == UsageTypes.VM_DISK_BYTES_WRITE) { //Device Type usageRecResponse.setType(usageRecord.getType()); //VM Instance Id - VMInstanceVO vm = _entityMgr.findById(VMInstanceVO.class, usageRecord.getVmInstanceId().toString()); - usageRecResponse.setVirtualMachineId(vm.getUuid()); + VMInstanceVO vm = _entityMgr.findByIdIncludingRemoved(VMInstanceVO.class, usageRecord.getVmInstanceId().toString()); + if (vm != null) { + usageRecResponse.setVirtualMachineId(vm.getUuid()); + } //Volume ID - VolumeVO volume = _entityMgr.findById(VolumeVO.class, usageRecord.getUsageId().toString()); - usageRecResponse.setUsageId(volume.getUuid()); + VolumeVO volume = _entityMgr.findByIdIncludingRemoved(VolumeVO.class, usageRecord.getUsageId().toString()); + if (volume != null) { + usageRecResponse.setUsageId(volume.getUuid()); + } } else if (usageRecord.getUsageType() == UsageTypes.VOLUME) { //Volume ID - VolumeVO volume = _entityMgr.findById(VolumeVO.class, usageRecord.getUsageId().toString()); - usageRecResponse.setUsageId(volume.getUuid()); + VolumeVO volume = _entityMgr.findByIdIncludingRemoved(VolumeVO.class, usageRecord.getUsageId().toString()); + if (volume != null) { + usageRecResponse.setUsageId(volume.getUuid()); + } //Volume Size usageRecResponse.setSize(usageRecord.getSize()); //Disk Offering Id if (usageRecord.getOfferingId() != null) { - DiskOfferingVO diskOff = _entityMgr.findById(DiskOfferingVO.class, usageRecord.getOfferingId().toString()); + DiskOfferingVO diskOff = _entityMgr.findByIdIncludingRemoved(DiskOfferingVO.class, usageRecord.getOfferingId().toString()); usageRecResponse.setOfferingId(diskOff.getUuid()); } } else if (usageRecord.getUsageType() == UsageTypes.TEMPLATE || usageRecord.getUsageType() == UsageTypes.ISO) { //Template/ISO ID - VMTemplateVO tmpl = _entityMgr.findById(VMTemplateVO.class, usageRecord.getUsageId().toString()); + VMTemplateVO tmpl = _entityMgr.findByIdIncludingRemoved(VMTemplateVO.class, usageRecord.getUsageId().toString()); usageRecResponse.setUsageId(tmpl.getUuid()); + if (tmpl != null) { + usageRecResponse.setUsageId(tmpl.getUuid()); + } //Template/ISO Size usageRecResponse.setSize(usageRecord.getSize()); if (usageRecord.getUsageType() == UsageTypes.ISO) { @@ -3304,46 +3386,52 @@ public UsageRecordResponse createUsageResponse(Usage usageRecord) { } else if (usageRecord.getUsageType() == UsageTypes.SNAPSHOT) { //Snapshot ID - SnapshotVO snap = _entityMgr.findById(SnapshotVO.class, usageRecord.getUsageId().toString()); - usageRecResponse.setUsageId(snap.getUuid()); + SnapshotVO snap = _entityMgr.findByIdIncludingRemoved(SnapshotVO.class, usageRecord.getUsageId().toString()); + if (snap != null) { + usageRecResponse.setUsageId(snap.getUuid()); + } //Snapshot Size usageRecResponse.setSize(usageRecord.getSize()); } else if (usageRecord.getUsageType() == UsageTypes.LOAD_BALANCER_POLICY) { //Load Balancer Policy ID - LoadBalancerVO lb = _entityMgr.findById(LoadBalancerVO.class, usageRecord.getUsageId().toString()); + LoadBalancerVO lb = _entityMgr.findByIdIncludingRemoved(LoadBalancerVO.class, usageRecord.getUsageId().toString()); if (lb != null) { usageRecResponse.setUsageId(lb.getUuid()); } } else if (usageRecord.getUsageType() == UsageTypes.PORT_FORWARDING_RULE) { //Port Forwarding Rule ID - PortForwardingRuleVO pf = _entityMgr.findById(PortForwardingRuleVO.class, usageRecord.getUsageId().toString()); + PortForwardingRuleVO pf = _entityMgr.findByIdIncludingRemoved(PortForwardingRuleVO.class, usageRecord.getUsageId().toString()); if (pf != null) { usageRecResponse.setUsageId(pf.getUuid()); } } else if (usageRecord.getUsageType() == UsageTypes.NETWORK_OFFERING) { //Network Offering Id - NetworkOfferingVO netOff = _entityMgr.findById(NetworkOfferingVO.class, usageRecord.getOfferingId().toString()); + NetworkOfferingVO netOff = _entityMgr.findByIdIncludingRemoved(NetworkOfferingVO.class, usageRecord.getOfferingId().toString()); usageRecResponse.setOfferingId(netOff.getUuid()); //is Default usageRecResponse.setDefault((usageRecord.getUsageId() == 1) ? true : false); } else if (usageRecord.getUsageType() == UsageTypes.VPN_USERS) { //VPN User ID - VpnUserVO vpnUser = _entityMgr.findById(VpnUserVO.class, usageRecord.getUsageId().toString()); + VpnUserVO vpnUser = _entityMgr.findByIdIncludingRemoved(VpnUserVO.class, usageRecord.getUsageId().toString()); if (vpnUser != null) { usageRecResponse.setUsageId(vpnUser.getUuid()); } } else if (usageRecord.getUsageType() == UsageTypes.SECURITY_GROUP) { //Security Group Id - SecurityGroupVO sg = _entityMgr.findById(SecurityGroupVO.class, usageRecord.getUsageId().toString()); - usageRecResponse.setUsageId(sg.getUuid()); + SecurityGroupVO sg = _entityMgr.findByIdIncludingRemoved(SecurityGroupVO.class, usageRecord.getUsageId().toString()); + if (sg != null) { + usageRecResponse.setUsageId(sg.getUuid()); + } } else if (usageRecord.getUsageType() == UsageTypes.VM_SNAPSHOT) { - VMInstanceVO vm = _entityMgr.findById(VMInstanceVO.class, usageRecord.getVmInstanceId().toString()); - usageRecResponse.setVmName(vm.getInstanceName()); - usageRecResponse.setUsageId(vm.getUuid()); + VMInstanceVO vm = _entityMgr.findByIdIncludingRemoved(VMInstanceVO.class, usageRecord.getVmInstanceId().toString()); + if (vm != null) { + usageRecResponse.setVmName(vm.getInstanceName()); + usageRecResponse.setUsageId(vm.getUuid()); + } usageRecResponse.setSize(usageRecord.getSize()); if (usageRecord.getOfferingId() != null) { usageRecResponse.setOfferingId(usageRecord.getOfferingId().toString()); diff --git a/server/src/com/cloud/api/ApiServer.java b/server/src/com/cloud/api/ApiServer.java index e4486c1fee..18eb4d96f3 100755 --- a/server/src/com/cloud/api/ApiServer.java +++ b/server/src/com/cloud/api/ApiServer.java @@ -82,6 +82,7 @@ import org.apache.http.protocol.ResponseDate; import org.apache.http.protocol.ResponseServer; import org.apache.log4j.Logger; +import org.springframework.beans.factory.NoSuchBeanDefinitionException; import org.springframework.stereotype.Component; import org.apache.cloudstack.acl.APIChecker; @@ -95,10 +96,14 @@ import org.apache.cloudstack.api.ResponseObject; import org.apache.cloudstack.api.ResponseObject.ResponseView; import org.apache.cloudstack.api.ServerApiException; +import org.apache.cloudstack.api.command.admin.account.ListAccountsCmdByAdmin; import org.apache.cloudstack.api.command.admin.host.ListHostsCmd; import org.apache.cloudstack.api.command.admin.router.ListRoutersCmd; import org.apache.cloudstack.api.command.admin.storage.ListStoragePoolsCmd; import org.apache.cloudstack.api.command.admin.user.ListUsersCmd; +import org.apache.cloudstack.api.command.admin.vm.ListVMsCmdByAdmin; +import org.apache.cloudstack.api.command.admin.volume.ListVolumesCmdByAdmin; +import org.apache.cloudstack.api.command.admin.zone.ListZonesCmdByAdmin; 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.event.ListEventsCmd; @@ -119,9 +124,14 @@ import org.apache.cloudstack.context.CallContext; import org.apache.cloudstack.framework.config.dao.ConfigurationDao; import org.apache.cloudstack.framework.config.impl.ConfigurationVO; +import org.apache.cloudstack.framework.events.EventBus; +import org.apache.cloudstack.framework.events.EventBusException; import org.apache.cloudstack.framework.jobs.AsyncJob; import org.apache.cloudstack.framework.jobs.AsyncJobManager; import org.apache.cloudstack.framework.jobs.impl.AsyncJobVO; +import org.apache.cloudstack.framework.messagebus.MessageBus; +import org.apache.cloudstack.framework.messagebus.MessageDispatcher; +import org.apache.cloudstack.framework.messagebus.MessageHandler; import org.apache.cloudstack.managed.context.ManagedContextRunnable; import com.cloud.api.dispatch.DispatchChainFactory; @@ -130,7 +140,9 @@ import com.cloud.configuration.Config; import com.cloud.domain.Domain; import com.cloud.domain.DomainVO; +import com.cloud.domain.dao.DomainDao; import com.cloud.event.ActionEventUtils; +import com.cloud.event.EventCategory; import com.cloud.event.EventTypes; import com.cloud.exception.AccountLimitException; import com.cloud.exception.CloudAuthenticationException; @@ -148,7 +160,6 @@ import com.cloud.user.UserVO; import com.cloud.utils.NumbersUtil; import com.cloud.utils.Pair; -import com.cloud.utils.ReflectUtil; import com.cloud.utils.StringUtils; import com.cloud.utils.component.ComponentContext; import com.cloud.utils.component.ManagerBase; @@ -159,7 +170,6 @@ import com.cloud.utils.db.TransactionLegacy; import com.cloud.utils.exception.CloudRuntimeException; import com.cloud.utils.exception.ExceptionProxyObject; -import com.cloud.vm.VirtualMachine; @Component public class ApiServer extends ManagerBase implements HttpRequestHandler, ApiServerService { @@ -183,6 +193,9 @@ public class ApiServer extends ManagerBase implements HttpRequestHandler, ApiSer private AccountManager _accountMgr; @Inject private DomainManager _domainMgr; + @Inject + private DomainDao _domainDao; + @Inject private AsyncJobManager _asyncMgr; @Inject @@ -201,16 +214,93 @@ public class ApiServer extends ManagerBase implements HttpRequestHandler, ApiSer private static Map>> s_apiNameCmdClassMap = new HashMap>>(); private static ExecutorService s_executor = new ThreadPoolExecutor(10, 150, 60, TimeUnit.SECONDS, new LinkedBlockingQueue(), new NamedThreadFactory( - "ApiServer")); + "ApiServer")); + @Inject + MessageBus _messageBus; public ApiServer() { } @Override public boolean configure(final String name, final Map params) throws ConfigurationException { + _messageBus.subscribe(AsyncJob.Topics.JOB_EVENT_PUBLISH, MessageDispatcher.getDispatcher(this)); return true; } + @MessageHandler(topic = AsyncJob.Topics.JOB_EVENT_PUBLISH) + private void handleAsyncJobPublishEvent(String subject, String senderAddress, Object args) { + assert (args != null); + + @SuppressWarnings("unchecked") + Pair eventInfo = (Pair)args; + AsyncJob job = eventInfo.first(); + String jobEvent = eventInfo.second(); + + if (s_logger.isTraceEnabled()) + s_logger.trace("Handle asyjob publish event " + jobEvent); + + EventBus eventBus = null; + try { + eventBus = ComponentContext.getComponent(EventBus.class); + } catch (NoSuchBeanDefinitionException nbe) { + return; // no provider is configured to provide events bus, so just return + } + + if (!job.getDispatcher().equalsIgnoreCase("ApiAsyncJobDispatcher")) { + return; + } + + User userJobOwner = _accountMgr.getUserIncludingRemoved(job.getUserId()); + Account jobOwner = _accountMgr.getAccount(userJobOwner.getAccountId()); + + // Get the event type from the cmdInfo json string + String info = job.getCmdInfo(); + String cmdEventType; + if (info == null) { + cmdEventType = "unknown"; + } else { + String marker = "\"cmdEventType\""; + int begin = info.indexOf(marker); + cmdEventType = info.substring(begin + marker.length() + 2, info.indexOf(",", begin) - 1); + } + + // For some reason, the instanceType / instanceId are not abstract, which means we may get null values. + org.apache.cloudstack.framework.events.Event event = new org.apache.cloudstack.framework.events.Event( + "management-server", + EventCategory.ASYNC_JOB_CHANGE_EVENT.getName(), + jobEvent, + (job.getInstanceType() != null ? job.getInstanceType().toString() : "unknown"), null); + + Map eventDescription = new HashMap(); + eventDescription.put("command", job.getCmd()); + eventDescription.put("user", userJobOwner.getUuid()); + eventDescription.put("account", jobOwner.getUuid()); + eventDescription.put("processStatus", "" + job.getProcessStatus()); + eventDescription.put("resultCode", "" + job.getResultCode()); + eventDescription.put("instanceUuid", ApiDBUtils.findJobInstanceUuid(job)); + eventDescription.put("instanceType", (job.getInstanceType() != null ? job.getInstanceType().toString() : "unknown")); + eventDescription.put("commandEventType", cmdEventType); + eventDescription.put("jobId", job.getUuid()); + // If the event.accountinfo boolean value is set, get the human readable value for the username / domainname + Map configs = _configDao.getConfiguration("management-server", new HashMap()); + if (Boolean.valueOf(configs.get("event.accountinfo"))) { + DomainVO domain = _domainDao.findById(jobOwner.getDomainId()); + eventDescription.put("username", userJobOwner.getUsername()); + eventDescription.put("domainname", domain.getName()); + } + event.setDescription(eventDescription); + + try { + eventBus.publish(event); + } catch (EventBusException evx) { + String errMsg = "F" + + "" + + "ailed to publish async job event on the the event bus."; + s_logger.warn(errMsg, evx); + throw new CloudRuntimeException(errMsg); + } + } + @Override public boolean start() { Integer apiPort = null; // api port, null by default @@ -356,7 +446,7 @@ public void checkCharacterInkParams(final Map params) { final Matcher matcher = pattern.matcher(value[0]); if (matcher.find()) { throw new ServerApiException(ApiErrorCode.PARAM_ERROR, "Received value " + value[0] + " for parameter " + key + - " is invalid, contains illegal ASCII non-printable characters"); + " is invalid, contains illegal ASCII non-printable characters"); } } stringMap.put(key, value[0]); @@ -420,7 +510,7 @@ public String handleRequest(final Map params, final String responseType, final S StringUtils.cleanString(response)); } else - buildAuditTrail(auditTrailSb, command[0], response); + buildAuditTrail(auditTrailSb, command[0], response); } else { if (!command[0].equalsIgnoreCase("login") && !command[0].equalsIgnoreCase("logout")) { final String errorString = "Unknown API command: " + command[0]; @@ -511,7 +601,6 @@ private String queueCommand(final BaseCmd cmdObj, final Map para final CallContext ctx = CallContext.current(); final Long callerUserId = ctx.getCallingUserId(); final Account caller = ctx.getCallingAccount(); - String vmUUID = params.get(ApiConstants.VIRTUAL_MACHINE_ID); // Queue command based on Cmd super class: // BaseCmd: cmd is dispatched to ApiDispatcher, executed, serialized and returned. @@ -526,6 +615,9 @@ private String queueCommand(final BaseCmd cmdObj, final Map para objectId = createCmd.getEntityId(); objectUuid = createCmd.getEntityUuid(); params.put("id", objectId.toString()); + Class entityClass = EventTypes.getEntityClassForEvent(createCmd.getEventType()); + if (entityClass != null) + ctx.putContextParameter(entityClass.getName(), objectId); } else { // Extract the uuid before params are processed and id reflects internal db id objectUuid = params.get(ApiConstants.ID); @@ -540,7 +632,7 @@ private String queueCommand(final BaseCmd cmdObj, final Map para if (caller != null) { params.put("ctxAccountId", String.valueOf(caller.getId())); } - if(objectUuid != null){ + if (objectUuid != null) { params.put("uuid", objectUuid); } @@ -549,17 +641,14 @@ private String queueCommand(final BaseCmd cmdObj, final Map para // Add the resource id in the call context, also add some other first class object ids (for now vm) if available. // TODO - this should be done for all the uuids passed in the cmd - so should be moved where uuid to id conversion happens. - if(EventTypes.getEntityForEvent(asyncCmd.getEventType()) != null){ + if (EventTypes.getEntityForEvent(asyncCmd.getEventType()) != null) { ctx.putContextParameter(EventTypes.getEntityForEvent(asyncCmd.getEventType()), objectUuid); } - if(vmUUID != null){ - ctx.putContextParameter(ReflectUtil.getEntityName(VirtualMachine.class), vmUUID); - } // save the scheduled event final Long eventId = - ActionEventUtils.onScheduledActionEvent((callerUserId == null) ? User.UID_SYSTEM : callerUserId, asyncCmd.getEntityOwnerId(), asyncCmd.getEventType(), - asyncCmd.getEventDescription(), asyncCmd.isDisplayResourceEnabled(), startEventId); + ActionEventUtils.onScheduledActionEvent((callerUserId == null) ? User.UID_SYSTEM : callerUserId, asyncCmd.getEntityOwnerId(), asyncCmd.getEventType(), + asyncCmd.getEventDescription(), asyncCmd.isDisplay(), startEventId); if (startEventId == 0) { // There was no create event before, set current event id as start eventId startEventId = eventId; @@ -567,6 +656,7 @@ private String queueCommand(final BaseCmd cmdObj, final Map para params.put("ctxStartEventId", String.valueOf(startEventId)); params.put("cmdEventType", asyncCmd.getEventType().toString()); + params.put("ctxDetails", ApiGsonHelper.getBuilder().create().toJson(ctx.getContextParameters())); Long instanceId = (objectId == null) ? asyncCmd.getInstanceId() : objectId; AsyncJobVO job = new AsyncJobVO("", callerUserId, caller.getId(), cmdObj.getClass().getName(), @@ -595,13 +685,15 @@ private String queueCommand(final BaseCmd cmdObj, final Map para // if the command is of the listXXXCommand, we will need to also return the // the job id and status if possible // For those listXXXCommand which we have already created DB views, this step is not needed since async job is joined in their db views. - if (cmdObj instanceof BaseListCmd && !(cmdObj instanceof ListVMsCmd) && !(cmdObj instanceof ListRoutersCmd) && !(cmdObj instanceof ListSecurityGroupsCmd) && - !(cmdObj instanceof ListTagsCmd) && !(cmdObj instanceof ListEventsCmd) && !(cmdObj instanceof ListVMGroupsCmd) && !(cmdObj instanceof ListProjectsCmd) && - !(cmdObj instanceof ListProjectAccountsCmd) && !(cmdObj instanceof ListProjectInvitationsCmd) && !(cmdObj instanceof ListHostsCmd) && - !(cmdObj instanceof ListVolumesCmd) && !(cmdObj instanceof ListUsersCmd) && !(cmdObj instanceof ListAccountsCmd) && - !(cmdObj instanceof ListStoragePoolsCmd) && !(cmdObj instanceof ListDiskOfferingsCmd) && !(cmdObj instanceof ListServiceOfferingsCmd) && - !(cmdObj instanceof ListZonesCmd)) { - buildAsyncListResponse((BaseListCmd) cmdObj, caller); + if (cmdObj instanceof BaseListCmd && !(cmdObj instanceof ListVMsCmd) && !(cmdObj instanceof ListVMsCmdByAdmin) && !(cmdObj instanceof ListRoutersCmd) + && !(cmdObj instanceof ListSecurityGroupsCmd) && + !(cmdObj instanceof ListTagsCmd) && !(cmdObj instanceof ListEventsCmd) && !(cmdObj instanceof ListVMGroupsCmd) && !(cmdObj instanceof ListProjectsCmd) && + !(cmdObj instanceof ListProjectAccountsCmd) && !(cmdObj instanceof ListProjectInvitationsCmd) && !(cmdObj instanceof ListHostsCmd) && + !(cmdObj instanceof ListVolumesCmd) && !(cmdObj instanceof ListVolumesCmdByAdmin) && !(cmdObj instanceof ListUsersCmd) && !(cmdObj instanceof ListAccountsCmd) + && !(cmdObj instanceof ListAccountsCmdByAdmin) && + !(cmdObj instanceof ListStoragePoolsCmd) && !(cmdObj instanceof ListDiskOfferingsCmd) && !(cmdObj instanceof ListServiceOfferingsCmd) && + !(cmdObj instanceof ListZonesCmd) && !(cmdObj instanceof ListZonesCmdByAdmin)) { + buildAsyncListResponse((BaseListCmd)cmdObj, caller); } SerializationContext.current().setUuidTranslation(true); @@ -775,7 +867,7 @@ public boolean verifyRequest(final Map requestParameters, fina if (user.getState() != Account.State.enabled || !account.getState().equals(Account.State.enabled)) { s_logger.info("disabled or locked user accessing the api, userid = " + user.getId() + "; name = " + user.getUsername() + "; state: " + user.getState() + - "; accountState: " + account.getState()); + "; accountState: " + account.getState()); return false; } @@ -831,7 +923,7 @@ public Long fetchDomainId(final String domainUUID) { @Override public void loginUser(final HttpSession session, final String username, final String password, Long domainId, final String domainPath, final String loginIpAddress, - final Map requestParameters) throws CloudAuthenticationException { + final Map requestParameters) throws CloudAuthenticationException { // We will always use domainId first. If that does not exist, we will use domain name. If THAT doesn't exist // we will default to ROOT if (domainId == null) { @@ -920,7 +1012,7 @@ public boolean verifyUser(final Long userId) { } if ((user == null) || (user.getRemoved() != null) || !user.getState().equals(Account.State.enabled) || (account == null) || - !account.getState().equals(Account.State.enabled)) { + !account.getState().equals(Account.State.enabled)) { s_logger.warn("Deleted/Disabled/Locked user with id=" + userId + " attempting to access public API"); return false; } @@ -1016,10 +1108,10 @@ public ListenerThread(final ApiServer requestHandler, final int port) { _params = new BasicHttpParams(); _params.setIntParameter(CoreConnectionPNames.SO_TIMEOUT, 30000) - .setIntParameter(CoreConnectionPNames.SOCKET_BUFFER_SIZE, 8 * 1024) - .setBooleanParameter(CoreConnectionPNames.STALE_CONNECTION_CHECK, false) - .setBooleanParameter(CoreConnectionPNames.TCP_NODELAY, true) - .setParameter(CoreProtocolPNames.ORIGIN_SERVER, "HttpComponents/1.1"); + .setIntParameter(CoreConnectionPNames.SOCKET_BUFFER_SIZE, 8 * 1024) + .setBooleanParameter(CoreConnectionPNames.STALE_CONNECTION_CHECK, false) + .setBooleanParameter(CoreConnectionPNames.TCP_NODELAY, true) + .setParameter(CoreProtocolPNames.ORIGIN_SERVER, "HttpComponents/1.1"); // Set up the HTTP protocol processor final BasicHttpProcessor httpproc = new BasicHttpProcessor(); diff --git a/server/src/com/cloud/api/dispatch/CommandCreationWorker.java b/server/src/com/cloud/api/dispatch/CommandCreationWorker.java index 30d4637d37..25846f9083 100644 --- a/server/src/com/cloud/api/dispatch/CommandCreationWorker.java +++ b/server/src/com/cloud/api/dispatch/CommandCreationWorker.java @@ -23,6 +23,7 @@ import org.apache.cloudstack.api.ServerApiException; import com.cloud.exception.ResourceAllocationException; +import org.apache.cloudstack.context.CallContext; /** @@ -42,6 +43,7 @@ public void handle(final DispatchTask task) { if (cmd instanceof BaseAsyncCreateCmd) { try { + CallContext.current().setEventDisplayEnabled(cmd.isDisplay()); ((BaseAsyncCreateCmd)cmd).create(); } catch (final ResourceAllocationException e) { throw new ServerApiException(ApiErrorCode.RESOURCE_ALLOCATION_ERROR, diff --git a/server/src/com/cloud/api/dispatch/ParamGenericValidationWorker.java b/server/src/com/cloud/api/dispatch/ParamGenericValidationWorker.java index 7a73b8aef9..d6b0cf26bf 100644 --- a/server/src/com/cloud/api/dispatch/ParamGenericValidationWorker.java +++ b/server/src/com/cloud/api/dispatch/ParamGenericValidationWorker.java @@ -80,9 +80,17 @@ public void handle(final DispatchTask task) { final StringBuilder errorMsg = new StringBuilder(ERROR_MSG_PREFIX); boolean foundUnknownParam = false; - for (final Object paramName : params.keySet()) { - if (!expectedParamNames.contains(paramName)) { - errorMsg.append(" ").append(paramName); + for (final Object actualParamName : params.keySet()) { + // If none of the expected params matches, we have an unknown param + boolean matchedCurrentParam = false; + for (final String expectedName : expectedParamNames) { + if (expectedName.equalsIgnoreCase((String) actualParamName)) { + matchedCurrentParam = true; + break; + } + } + if (!matchedCurrentParam) { + errorMsg.append(" ").append(actualParamName); foundUnknownParam= true; } } diff --git a/server/src/com/cloud/api/dispatch/ParamProcessWorker.java b/server/src/com/cloud/api/dispatch/ParamProcessWorker.java index e9bdd8b107..ba5bebff64 100644 --- a/server/src/com/cloud/api/dispatch/ParamProcessWorker.java +++ b/server/src/com/cloud/api/dispatch/ParamProcessWorker.java @@ -37,16 +37,18 @@ import org.apache.cloudstack.acl.ControlledEntity; import org.apache.cloudstack.acl.InfrastructureEntity; +import org.apache.cloudstack.acl.SecurityChecker; import org.apache.cloudstack.acl.SecurityChecker.AccessType; import org.apache.cloudstack.api.ACL; +import org.apache.cloudstack.api.APICommand; import org.apache.cloudstack.api.ApiErrorCode; import org.apache.cloudstack.api.BaseAsyncCreateCmd; import org.apache.cloudstack.api.BaseCmd; +import org.apache.cloudstack.api.BaseCmd.CommandType; import org.apache.cloudstack.api.EntityReference; import org.apache.cloudstack.api.InternalIdentity; import org.apache.cloudstack.api.Parameter; import org.apache.cloudstack.api.ServerApiException; -import org.apache.cloudstack.api.BaseCmd.CommandType; import org.apache.cloudstack.api.command.admin.resource.ArchiveAlertsCmd; import org.apache.cloudstack.api.command.admin.resource.DeleteAlertsCmd; import org.apache.cloudstack.api.command.user.event.ArchiveEventsCmd; @@ -54,7 +56,11 @@ import org.apache.cloudstack.api.command.user.event.ListEventsCmd; import org.apache.cloudstack.context.CallContext; +import com.cloud.dc.DataCenter; import com.cloud.exception.InvalidParameterValueException; +import com.cloud.exception.PermissionDeniedException; +import com.cloud.offering.DiskOffering; +import com.cloud.offering.ServiceOffering; import com.cloud.user.Account; import com.cloud.user.AccountManager; import com.cloud.utils.DateUtil; @@ -71,6 +77,17 @@ public class ParamProcessWorker implements DispatchWorker { @Inject protected EntityManager _entityMgr; + List _secChecker; + + public List getSecChecker() { + return _secChecker; + } + + @Inject + public void setSecChecker(List secChecker) { + _secChecker = secChecker; + } + @Override public void handle(final DispatchTask task) { processParameters(task.getCmd(), task.getParams()); @@ -130,71 +147,63 @@ public void processParameters(final BaseCmd cmd, final Map params) { final CommandType fieldType = parameterAnnotation.type(); if (checkAccess != null) { - // Verify that caller can perform actions in behalf of vm owner - //acumulate all Controlled Entities together. - - //parse the array of resource types and in case of map check access on key or value or both as specified in @acl - //implement external dao for classes that need findByName - //for maps, specify access to be checkd on key or value. - - // find the controlled entity DBid by uuid - if (parameterAnnotation.entityType() != null) { + // Verify that caller can perform actions in behalf of vm + // owner acumulate all Controlled Entities together. + // parse the array of resource types and in case of map + // check access on key or value or both as specified in @acl + // implement external dao for classes that need findByName + // for maps, specify access to be checkd on key or value. + // Find the controlled entity DBid by uuid + + if (parameterAnnotation.entityType() != null && parameterAnnotation.entityType().length > 0 + && parameterAnnotation.entityType()[0].getAnnotation(EntityReference.class) != null) { final Class[] entityList = parameterAnnotation.entityType()[0].getAnnotation(EntityReference.class).value(); - for (final Class entity : entityList) { - // Check if the parameter type is a single - // Id or list of id's/name's - switch (fieldType) { - case LIST: - final CommandType listType = parameterAnnotation.collectionType(); - switch (listType) { - case LONG: - case UUID: - final List listParam = (List)field.get(cmd); - for (final Long entityId : listParam) { + // Check if the parameter type is a single + // Id or list of id's/name's + switch (fieldType) { + case LIST: + final CommandType listType = parameterAnnotation.collectionType(); + switch (listType) { + case LONG: + case UUID: + final List listParam = (List) field.get(cmd); + for (final Long entityId : listParam) { + for (final Class entity : entityList) { final Object entityObj = _entityMgr.findById(entity, entityId); - entitiesToAccess.put(entityObj, checkAccess.accessType()); + if(entityObj != null){ + entitiesToAccess.put(entityObj, checkAccess.accessType()); + break; + } } - break; - /* - * case STRING: List listParam = - * new ArrayList(); listParam = - * (List)field.get(cmd); for(String - * entityName: listParam){ - * ControlledEntity entityObj = - * (ControlledEntity - * )daoClassInstance(entityId); - * entitiesToAccess.add(entityObj); } - * break; - */ - default: - break; - } - break; - case LONG: - case UUID: - final Object entityObj = _entityMgr.findById(entity, (Long)field.get(cmd)); - entitiesToAccess.put(entityObj, checkAccess.accessType()); - break; - default: - break; - } - - if (ControlledEntity.class.isAssignableFrom(entity)) { - if (s_logger.isDebugEnabled()) { - s_logger.debug("ControlledEntity name is:" + entity.getName()); + } + break; + /* + * case STRING: List listParam = new + * ArrayList(); listParam = + * (List)field.get(cmd); for(String entityName: + * listParam){ ControlledEntity entityObj = + * (ControlledEntity )daoClassInstance(entityId); + * entitiesToAccess.add(entityObj); } break; + */ + default: + break; } - } - - if (InfrastructureEntity.class.isAssignableFrom(entity)) { - if (s_logger.isDebugEnabled()) { - s_logger.debug("InfrastructureEntity name is:" + entity.getName()); + break; + case LONG: + case UUID: + for (final Class entity : entityList) { + final Object entityObj = _entityMgr.findById(entity, (Long) field.get(cmd)); + if(entityObj != null){ + entitiesToAccess.put(entityObj, checkAccess.accessType()); + break; + } } - } + break; + default: + break; } - } - } } catch (final IllegalArgumentException e) { @@ -214,27 +223,111 @@ public void processParameters(final BaseCmd cmd, final Map params) { private void doAccessChecks(final BaseCmd cmd, final Map entitiesToAccess) { - final Account caller = CallContext.current().getCallingAccount(); - final Account owner = _accountMgr.getActiveAccountById(cmd.getEntityOwnerId()); + Account caller = CallContext.current().getCallingAccount(); + Account owner = _accountMgr.getAccount(cmd.getEntityOwnerId()); + if (owner == null) { + owner = caller; + } if (cmd instanceof BaseAsyncCreateCmd) { - //check that caller can access the owner account. - _accountMgr.checkAccess(caller, null, true, owner); + if (owner.getId() != caller.getId()) { + // mimic impersonation either by passing (account, domainId) or through derived owner from other api parameters + // in this case, we should check access using the owner + _accountMgr.checkAccess(caller, null, owner); + } + } else { + // check access using the caller for other operational cmds + owner = caller; } + APICommand commandAnnotation = cmd.getClass().getAnnotation(APICommand.class); + + String apiName = commandAnnotation != null ? commandAnnotation.name() : null; + if (!entitiesToAccess.isEmpty()) { - //check that caller can access the owner account. - _accountMgr.checkAccess(caller, null, true, owner); - for (final Object entity : entitiesToAccess.keySet()) { + List entitiesToOperate = new ArrayList(); + for (Object entity : entitiesToAccess.keySet()) { if (entity instanceof ControlledEntity) { - _accountMgr.checkAccess(caller, entitiesToAccess.get(entity), true, (ControlledEntity)entity); + + if (AccessType.OperateEntry == entitiesToAccess.get(entity)) { + entitiesToOperate.add((ControlledEntity) entity); + } else { + _accountMgr.checkAccess(owner, entitiesToAccess.get(entity), apiName, + (ControlledEntity) entity); + } } else if (entity instanceof InfrastructureEntity) { - //FIXME: Move this code in adapter, remove code from Account manager + if (entity instanceof DataCenter) { + checkZoneAccess(owner, (DataCenter)entity); + } else if (entity instanceof ServiceOffering) { + checkServiceOfferingAccess(owner, (ServiceOffering)entity); + } else if (entity instanceof DiskOffering) { + checkDiskOfferingAccess(owner, (DiskOffering)entity); + } } } + + if (!entitiesToOperate.isEmpty()) { + _accountMgr.checkAccess(owner, AccessType.OperateEntry, apiName, + entitiesToOperate.toArray(new ControlledEntity[entitiesToOperate.size()])); + } + } } + private void checkDiskOfferingAccess(Account caller, DiskOffering dof) { + for (SecurityChecker checker : _secChecker) { + if (checker.checkAccess(caller, dof)) { + if (s_logger.isDebugEnabled()) { + s_logger.debug("Access granted to " + caller + " to disk offering:" + dof.getId() + " by " + + checker.getName()); + } + return; + } else { + throw new PermissionDeniedException("Access denied to " + caller + " by " + checker.getName()); + } + } + + assert false : "How can all of the security checkers pass on checking this caller?"; + throw new PermissionDeniedException("There's no way to confirm " + caller + " has access to disk offering:" + + dof.getId()); + } + + private void checkServiceOfferingAccess(Account caller, ServiceOffering sof) { + for (SecurityChecker checker : _secChecker) { + if (checker.checkAccess(caller, sof)) { + if (s_logger.isDebugEnabled()) { + s_logger.debug("Access granted to " + caller + " to service offering:" + sof.getId() + " by " + + checker.getName()); + } + return; + } else { + throw new PermissionDeniedException("Access denied to " + caller + " by " + checker.getName()); + } + } + + assert false : "How can all of the security checkers pass on checking this caller?"; + throw new PermissionDeniedException("There's no way to confirm " + caller + " has access to service offering:" + + sof.getId()); + } + + private void checkZoneAccess(Account caller, DataCenter zone) { + for (SecurityChecker checker : _secChecker) { + if (checker.checkAccess(caller, zone)) { + if (s_logger.isDebugEnabled()) { + s_logger.debug("Access granted to " + caller + " to zone:" + zone.getId() + " by " + + checker.getName()); + } + return; + } else { + throw new PermissionDeniedException("Access denied to " + caller + " by " + checker.getName() + + " for zone " + zone.getId()); + } + } + + assert false : "How can all of the security checkers pass on checking this caller?"; + throw new PermissionDeniedException("There's no way to confirm " + caller + " has access to zone:" + + zone.getId()); + } @SuppressWarnings({"unchecked", "rawtypes"}) private void setFieldValue(final Field field, final BaseCmd cmdObj, final Object paramObj, final Parameter annotation) throws IllegalArgumentException, ParseException { @@ -384,6 +477,11 @@ private Long translateUuidToInternalId(final String uuid, final Parameter annota // Enforce that it's uuid for newly added apis from version 3.x if (!isPre3x && !isUuid) return null; + + // There may be multiple entities defined on the @EntityReference of a Response.class + // UUID CommandType would expect only one entityType, so use the first entityType + final Class[] entities = annotation.entityType()[0].getAnnotation(EntityReference.class).value(); + // Allow both uuid and internal id for pre3x apis if (isPre3x && !isUuid) { try { @@ -391,12 +489,15 @@ private Long translateUuidToInternalId(final String uuid, final Parameter annota } catch (final NumberFormatException e) { internalId = null; } - if (internalId != null) + if (internalId != null){ + // Populate CallContext for each of the entity. + for (final Class entity : entities) { + CallContext.current().putContextParameter(entity.getName(), internalId); + } return internalId; + } } - // There may be multiple entities defined on the @EntityReference of a Response.class - // UUID CommandType would expect only one entityType, so use the first entityType - final Class[] entities = annotation.entityType()[0].getAnnotation(EntityReference.class).value(); + // Go through each entity which is an interface to a VO class and get a VO object // Try to getId() for the object using reflection, break on first non-null value for (final Class entity : entities) { @@ -407,15 +508,17 @@ private Long translateUuidToInternalId(final String uuid, final Parameter annota continue; } // Invoke the getId method, get the internal long ID - // If that fails hide exceptions as the uuid may not exist + // If that fails hide exceptions as the uuid may not exist s try { internalId = ((InternalIdentity)objVO).getId(); } catch (final IllegalArgumentException e) { } catch (final NullPointerException e) { } // Return on first non-null Id for the uuid entity - if (internalId != null) + if (internalId != null){ + CallContext.current().putContextParameter(entity.getName(), internalId); break; + } } if (internalId == null) { if (s_logger.isDebugEnabled()) diff --git a/server/src/com/cloud/api/query/QueryManagerImpl.java b/server/src/com/cloud/api/query/QueryManagerImpl.java index b932d422db..6848ba03fe 100644 --- a/server/src/com/cloud/api/query/QueryManagerImpl.java +++ b/server/src/com/cloud/api/query/QueryManagerImpl.java @@ -92,6 +92,7 @@ import org.apache.cloudstack.api.response.ZoneResponse; import org.apache.cloudstack.context.CallContext; import org.apache.cloudstack.engine.subsystem.api.storage.DataStore; +import org.apache.cloudstack.engine.subsystem.api.storage.DataStoreCapabilities; import org.apache.cloudstack.engine.subsystem.api.storage.DataStoreDriver; import org.apache.cloudstack.engine.subsystem.api.storage.DataStoreManager; import org.apache.cloudstack.engine.subsystem.api.storage.TemplateState; @@ -684,7 +685,7 @@ private Pair, Integer> searchForVmGroupsInternal(ListV cmd.getDomainId(), cmd.isRecursive(), null); _accountMgr.buildACLSearchParameters(caller, id, cmd.getAccountName(), cmd.getProjectId(), permittedDomains, permittedAccounts, permittedResources, domainIdRecursiveListProject, cmd.listAll(), false, "listInstanceGroups"); - Long domainId = domainIdRecursiveListProject.first(); + // Long domainId = domainIdRecursiveListProject.first(); Boolean isRecursive = domainIdRecursiveListProject.second(); ListProjectResourcesCriteria listProjectResourcesCriteria = domainIdRecursiveListProject.third(); @@ -776,7 +777,7 @@ private Pair, Integer> searchForUserVMsInternal(ListVMsCmd cm Object keyword = cmd.getKeyword(); boolean isAdmin = false; boolean isRootAdmin = false; - if (_accountMgr.isAdmin(caller.getType())) { + if (_accountMgr.isAdmin(caller.getId())) { isAdmin = true; } if (_accountMgr.isRootAdmin(caller.getId())) { @@ -1005,7 +1006,7 @@ private Pair, Integer> searchForSecurityGroupsInternal if (userVM == null) { throw new InvalidParameterValueException("Unable to list network groups for virtual machine instance " + instanceId + "; instance not found."); } - _accountMgr.checkAccess(caller, null, true, userVM); + _accountMgr.checkAccess(caller, null, userVM); return listSecurityGroupRulesByVM(instanceId.longValue(), cmd.getStartIndex(), cmd.getPageSizeVal()); } @@ -1278,7 +1279,7 @@ private Pair, Integer> listProjectsInternal(ListProjectsCmd sb.select(null, Func.DISTINCT, sb.entity().getId()); // select distinct // ids - if (_accountMgr.isAdmin(caller.getType())) { + if (_accountMgr.isAdmin(caller.getId())) { if (domainId != null) { DomainVO domain = _domainDao.findById(domainId); if (domain == null) { @@ -1482,7 +1483,7 @@ public Pair, Integer> listProjectAccountsInternal(Lis // verify permissions - only accounts belonging to the project can list // project's account - if (!_accountMgr.isAdmin(caller.getType()) && _projectAccountDao.findByProjectIdAccountId(projectId, caller.getAccountId()) == null) { + if (!_accountMgr.isAdmin(caller.getId()) && _projectAccountDao.findByProjectIdAccountId(projectId, caller.getAccountId()) == null) { throw new PermissionDeniedException("Account " + caller + " is not authorized to list users of the project id=" + projectId); } @@ -1643,6 +1644,28 @@ public ListResponse searchForVolumes(ListVolumesCmd cmd) { List volumeResponses = ViewResponseHelper.createVolumeResponse(respView, result.first().toArray( new VolumeJoinVO[result.first().size()])); + for(VolumeResponse vr : volumeResponses) { + String poolId = vr.getStoragePoolId(); + if (poolId == null) { + continue; + } + + DataStore store = dataStoreManager.getPrimaryDataStore(poolId); + if (store == null) { + continue; + } + + DataStoreDriver driver = store.getDriver(); + if (driver == null) { + continue; + } + + Map caps = driver.getCapabilities(); + if (caps != null) { + boolean quiescevm = Boolean.parseBoolean(caps.get(DataStoreCapabilities.VOLUME_SNAPSHOT_QUIESCEVM.toString())); + vr.setNeedQuiescevm(quiescevm); + } + } response.setResponses(volumeResponses, result.second()); return response; } @@ -1812,52 +1835,19 @@ public ListResponse searchForAccounts(ListAccountsCmd cmd) { private Pair, Integer> searchForAccountsInternal(ListAccountsCmd cmd) { Account caller = CallContext.current().getCallingAccount(); - Long domainId = cmd.getDomainId(); - Long accountId = cmd.getId(); - String accountName = cmd.getSearchName(); - boolean isRecursive = cmd.isRecursive(); - boolean listAll = cmd.listAll(); - Boolean listForDomain = false; - - if (accountId != null) { - Account account = _accountDao.findById(accountId); - if (account == null || account.getId() == Account.ACCOUNT_ID_SYSTEM) { - throw new InvalidParameterValueException("Unable to find account by id " + accountId); - } - - _accountMgr.checkAccess(caller, null, true, account); - } - - if (domainId != null) { - Domain domain = _domainDao.findById(domainId); - if (domain == null) { - throw new InvalidParameterValueException("Domain id=" + domainId + " doesn't exist"); - } - - _accountMgr.checkAccess(caller, domain); - - if (accountName != null) { - Account account = _accountDao.findActiveAccount(accountName, domainId); - if (account == null || account.getId() == Account.ACCOUNT_ID_SYSTEM) { - throw new InvalidParameterValueException("Unable to find account by name " + accountName + " in domain " + domainId); - } - _accountMgr.checkAccess(caller, null, true, account); - } - } + List permittedDomains = new ArrayList(); + List permittedAccounts = new ArrayList(); + List permittedResources = new ArrayList(); - if (accountId == null) { - if (_accountMgr.isAdmin(caller.getType()) && listAll && domainId == null) { - listForDomain = true; - isRecursive = true; - if (domainId == null) { - domainId = caller.getDomainId(); - } - } else if (_accountMgr.isAdmin(caller.getType()) && domainId != null) { - listForDomain = true; - } else { - accountId = caller.getAccountId(); - } - } + boolean listAll = cmd.listAll(); + Long id = cmd.getId(); + String accountName = cmd.getSearchName(); + Ternary domainIdRecursiveListProject = new Ternary( + cmd.getDomainId(), cmd.isRecursive(), null); + // ListAccountsCmd is not BaseListAccountResourcesCmd, so no (domainId, accountName) combination + _accountMgr.buildACLSearchParameters(caller, id, null, null, permittedDomains, permittedAccounts, permittedResources, + domainIdRecursiveListProject, listAll, false, "listAccounts"); + Boolean isRecursive = domainIdRecursiveListProject.second(); Filter searchFilter = new Filter(AccountJoinVO.class, "id", true, cmd.getStartIndex(), cmd.getPageSizeVal()); @@ -1868,7 +1858,6 @@ private Pair, Integer> searchForAccountsInternal(ListAccount SearchBuilder sb = _accountJoinDao.createSearchBuilder(); sb.and("accountName", sb.entity().getAccountName(), SearchCriteria.Op.EQ); - sb.and("domainId", sb.entity().getDomainId(), SearchCriteria.Op.EQ); sb.and("id", sb.entity().getId(), SearchCriteria.Op.EQ); sb.and("type", sb.entity().getType(), SearchCriteria.Op.EQ); sb.and("state", sb.entity().getState(), SearchCriteria.Op.EQ); @@ -1876,11 +1865,31 @@ private Pair, Integer> searchForAccountsInternal(ListAccount sb.and("typeNEQ", sb.entity().getType(), SearchCriteria.Op.NEQ); sb.and("idNEQ", sb.entity().getId(), SearchCriteria.Op.NEQ); - if (listForDomain && isRecursive) { - sb.and("path", sb.entity().getDomainPath(), SearchCriteria.Op.LIKE); - } - SearchCriteria sc = sb.create(); + SearchCriteria aclSc = _accountJoinDao.createSearchCriteria(); + // building ACL search criteria. Here we cannot use the common accountMgr.buildACLViewSearchCriteria because + // 1) AccountJoinVO does not have accountId field, permittedAccounts correspond to list of resource ids. + // 2) AccountJoinVO use type not accountType field to indicate its type + if (!permittedDomains.isEmpty() || !permittedAccounts.isEmpty() || !permittedResources.isEmpty()) { + if (!permittedDomains.isEmpty()) { + if (isRecursive) { + for (int i = 0; i < permittedDomains.size(); i++) { + Domain domain = _domainDao.findById(permittedDomains.get(i)); + aclSc.addOr("domainPath", SearchCriteria.Op.LIKE, domain.getPath() + "%"); + } + } else { + aclSc.addOr("domainId", SearchCriteria.Op.IN, permittedDomains.toArray()); + } + } + if (!permittedAccounts.isEmpty()) { + aclSc.addOr("id", SearchCriteria.Op.IN, permittedAccounts.toArray()); + } + if (!permittedResources.isEmpty()) { + aclSc.addOr("id", SearchCriteria.Op.IN, permittedResources.toArray()); + } + + sc.addAnd("id", SearchCriteria.Op.SC, aclSc); + } sc.setParameters("idNEQ", Account.ACCOUNT_ID_SYSTEM); @@ -1908,19 +1917,10 @@ private Pair, Integer> searchForAccountsInternal(ListAccount } // don't return account of type project to the end user - sc.setParameters("typeNEQ", 5); + sc.setParameters("typeNEQ", Account.ACCOUNT_TYPE_PROJECT); - if (accountId != null) { - sc.setParameters("id", accountId); - } - - if (listForDomain) { - if (isRecursive) { - Domain domain = _domainDao.findById(domainId); - sc.setParameters("path", domain.getPath() + "%"); - } else { - sc.setParameters("domainId", domainId); - } + if (id != null) { + sc.setParameters("id", id); } return _accountJoinDao.searchAndCount(sc, searchFilter); @@ -2466,7 +2466,7 @@ private Pair, Integer> searchForServiceOfferingsInte throw ex; } - _accountMgr.checkAccess(caller, null, true, vmInstance); + _accountMgr.checkAccess(caller, null, vmInstance); ServiceOfferingVO offering = _srvOfferingDao.findByIdIncludingRemoved(vmInstance.getId(), vmInstance.getServiceOfferingId()); sc.addAnd("id", SearchCriteria.Op.NEQ, offering.getId()); @@ -2806,7 +2806,8 @@ public ListResponse listTemplates(ListTemplatesCmd cmd) { return response; } - private Pair, Integer> searchForTemplatesInternal(ListTemplatesCmd cmd) { + // Temporarily disable this method which used IAM model to do template list + private Pair, Integer> searchForTemplatesInternalIAM(ListTemplatesCmd cmd) { TemplateFilter templateFilter = TemplateFilter.valueOf(cmd.getTemplateFilter()); Long id = cmd.getId(); Map tags = cmd.getTags(); @@ -2838,12 +2839,13 @@ private Pair, Integer> searchForTemplatesInternal(ListTempl boolean showDomr = ((templateFilter != TemplateFilter.selfexecutable) && (templateFilter != TemplateFilter.featured)); HypervisorType hypervisorType = HypervisorType.getType(cmd.getHypervisor()); - return searchForTemplatesInternal(id, cmd.getTemplateName(), cmd.getKeyword(), templateFilter, false, null, + return searchForTemplatesInternalIAM(id, cmd.getTemplateName(), cmd.getKeyword(), templateFilter, false, null, cmd.getPageSizeVal(), cmd.getStartIndex(), cmd.getZoneId(), hypervisorType, showDomr, cmd.listInReadyState(), permittedDomains, permittedAccounts, permittedResources, isRecursive, caller, listProjectResourcesCriteria, tags, showRemovedTmpl); } - private Pair, Integer> searchForTemplatesInternal(Long templateId, String name, + // Temporarily disable this method which used IAM model to do template list + private Pair, Integer> searchForTemplatesInternalIAM(Long templateId, String name, String keyword, TemplateFilter templateFilter, boolean isIso, Boolean bootable, Long pageSize, Long startIndex, Long zoneId, HypervisorType hyperType, boolean showDomr, boolean onlyReady, List permittedDomains, List permittedAccounts, List permittedResources, boolean isRecursive, Account caller, @@ -2891,7 +2893,7 @@ private Pair, Integer> searchForTemplatesInternal(Long temp // if template is not public, perform permission check here if (!template.isPublicTemplate() && !_accountMgr.isRootAdmin(caller.getId())) { Account owner = _accountMgr.getAccount(template.getAccountId()); - _accountMgr.checkAccess(caller, null, true, owner); + _accountMgr.checkAccess(caller, null, owner); } // if templateId is specified, then we will just use the id to @@ -3079,6 +3081,386 @@ private Pair, Integer> searchForTemplatesInternal(Long temp } + // This method should only be used for keeping old listTemplates and listAffinityGroups behavior, PLEASE DON'T USE IT FOR USE LIST APIs + private void buildTemplateAffinityGroupSearchParameters(Account caller, Long id, String accountName, Long projectId, List + permittedAccounts, Ternary domainIdRecursiveListProject, + boolean listAll, boolean forProjectInvitation) { + Long domainId = domainIdRecursiveListProject.first(); + if (domainId != null) { + Domain domain = _domainDao.findById(domainId); + if (domain == null) { + throw new InvalidParameterValueException("Unable to find domain by id " + domainId); + } + // check permissions + _accountMgr.checkAccess(caller, domain); + } + + if (accountName != null) { + if (projectId != null) { + throw new InvalidParameterValueException("Account and projectId can't be specified together"); + } + + Account userAccount = null; + Domain domain = null; + if (domainId != null) { + userAccount = _accountDao.findActiveAccount(accountName, domainId); + domain = _domainDao.findById(domainId); + } else { + userAccount = _accountDao.findActiveAccount(accountName, caller.getDomainId()); + domain = _domainDao.findById(caller.getDomainId()); + } + + if (userAccount != null) { + _accountMgr.checkAccess(caller, null, userAccount); + // check permissions + permittedAccounts.add(userAccount.getId()); + } else { + throw new InvalidParameterValueException("could not find account " + accountName + " in domain " + domain.getUuid()); + } + } + + // set project information + if (projectId != null) { + if (!forProjectInvitation) { + if (projectId.longValue() == -1) { + if (_accountMgr.isNormalUser(caller.getId())) { + permittedAccounts.addAll(_projectMgr.listPermittedProjectAccounts(caller.getId())); + } else { + domainIdRecursiveListProject.third(Project.ListProjectResourcesCriteria.ListProjectResourcesOnly); + } + } else { + Project project = _projectMgr.getProject(projectId); + if (project == null) { + throw new InvalidParameterValueException("Unable to find project by id " + projectId); + } + if (!_projectMgr.canAccessProjectAccount(caller, project.getProjectAccountId())) { + throw new PermissionDeniedException("Account " + caller + " can't access project id=" + projectId); + } + permittedAccounts.add(project.getProjectAccountId()); + } + } + } else { + if (id == null) { + domainIdRecursiveListProject.third(Project.ListProjectResourcesCriteria.SkipProjectResources); + } + if (permittedAccounts.isEmpty() && domainId == null) { + if (_accountMgr.isNormalUser(caller.getId())) { + permittedAccounts.add(caller.getId()); + } else if (!listAll) { + if (id == null) { + permittedAccounts.add(caller.getId()); + } else if (!_accountMgr.isRootAdmin(caller.getId())) { + domainIdRecursiveListProject.first(caller.getDomainId()); + domainIdRecursiveListProject.second(true); + } + } else if (domainId == null) { + if (_accountMgr.isDomainAdmin(caller.getId())) { + domainIdRecursiveListProject.first(caller.getDomainId()); + domainIdRecursiveListProject.second(true); + } + } + } else if (domainId != null) { + if (_accountMgr.isNormalUser(caller.getId())) { + permittedAccounts.add(caller.getId()); + } + } + } + } + + private Pair, Integer> searchForTemplatesInternal(ListTemplatesCmd cmd) { + TemplateFilter templateFilter = TemplateFilter.valueOf(cmd.getTemplateFilter()); + Long id = cmd.getId(); + Map tags = cmd.getTags(); + boolean showRemovedTmpl = cmd.getShowRemoved(); + Account caller = CallContext.current().getCallingAccount(); + + boolean listAll = false; + if (templateFilter != null && templateFilter == TemplateFilter.all) { + if (caller.getType() == Account.ACCOUNT_TYPE_NORMAL) { + throw new InvalidParameterValueException("Filter " + TemplateFilter.all + + " can be specified by admin only"); + } + listAll = true; + } + + List permittedAccountIds = new ArrayList(); + Ternary domainIdRecursiveListProject = new Ternary( + cmd.getDomainId(), cmd.isRecursive(), null); + buildTemplateAffinityGroupSearchParameters(caller, id, cmd.getAccountName(), cmd.getProjectId(), permittedAccountIds, + domainIdRecursiveListProject, listAll, false); + ListProjectResourcesCriteria listProjectResourcesCriteria = domainIdRecursiveListProject.third(); + List permittedAccounts = new ArrayList(); + for (Long accountId : permittedAccountIds) { + permittedAccounts.add(_accountMgr.getAccount(accountId)); + } + + boolean showDomr = ((templateFilter != TemplateFilter.selfexecutable) && (templateFilter != TemplateFilter.featured)); + HypervisorType hypervisorType = HypervisorType.getType(cmd.getHypervisor()); + + return searchForTemplatesInternal(id, cmd.getTemplateName(), cmd.getKeyword(), templateFilter, false, null, + cmd.getPageSizeVal(), cmd.getStartIndex(), cmd.getZoneId(), hypervisorType, showDomr, + cmd.listInReadyState(), permittedAccounts, caller, listProjectResourcesCriteria, tags, showRemovedTmpl); + } + + private Pair, Integer> searchForTemplatesInternal(Long templateId, String name, + String keyword, TemplateFilter templateFilter, boolean isIso, Boolean bootable, Long pageSize, + Long startIndex, Long zoneId, HypervisorType hyperType, boolean showDomr, boolean onlyReady, + List permittedAccounts, Account caller, ListProjectResourcesCriteria listProjectResourcesCriteria, + Map tags, boolean showRemovedTmpl) { + + // check if zone is configured, if not, just return empty list + List hypers = null; + if (!isIso) { + hypers = _resourceMgr.listAvailHypervisorInZone(null, null); + if (hypers == null || hypers.isEmpty()) { + return new Pair, Integer>(new ArrayList(), 0); + } + } + + VMTemplateVO template = null; + + Boolean isAscending = Boolean.parseBoolean(_configDao.getValue("sortkey.algorithm")); + isAscending = (isAscending == null ? true : isAscending); + Filter searchFilter = new Filter(TemplateJoinVO.class, "sortKey", isAscending, startIndex, pageSize); + + SearchBuilder sb = _templateJoinDao.createSearchBuilder(); + sb.select(null, Func.DISTINCT, sb.entity().getTempZonePair()); // select distinct (templateId, zoneId) pair + SearchCriteria sc = sb.create(); + + // verify templateId parameter and specially handle it + if (templateId != null) { + template = _templateDao.findByIdIncludingRemoved(templateId); // Done for backward compatibility - Bug-5221 + if (template == null) { + throw new InvalidParameterValueException("Please specify a valid template ID."); + }// If ISO requested then it should be ISO. + if (isIso && template.getFormat() != ImageFormat.ISO) { + s_logger.error("Template Id " + templateId + " is not an ISO"); + InvalidParameterValueException ex = new InvalidParameterValueException( + "Specified Template Id is not an ISO"); + ex.addProxyObject(template.getUuid(), "templateId"); + throw ex; + }// If ISO not requested then it shouldn't be an ISO. + if (!isIso && template.getFormat() == ImageFormat.ISO) { + s_logger.error("Incorrect format of the template id " + templateId); + InvalidParameterValueException ex = new InvalidParameterValueException("Incorrect format " + + template.getFormat() + " of the specified template id"); + ex.addProxyObject(template.getUuid(), "templateId"); + throw ex; + } + + // if template is not public, perform permission check here + if (!template.isPublicTemplate() && caller.getType() != Account.ACCOUNT_TYPE_ADMIN) { + Account owner = _accountMgr.getAccount(template.getAccountId()); + _accountMgr.checkAccess(caller, null, owner); + } + + // if templateId is specified, then we will just use the id to + // search and ignore other query parameters + sc.addAnd("id", SearchCriteria.Op.EQ, templateId); + } else { + + DomainVO domain = null; + if (!permittedAccounts.isEmpty()) { + domain = _domainDao.findById(permittedAccounts.get(0).getDomainId()); + } else { + domain = _domainDao.findById(DomainVO.ROOT_DOMAIN); + } + + // List hypers = null; + // if (!isIso) { + // hypers = _resourceMgr.listAvailHypervisorInZone(null, null); + // } + + // add criteria for project or not + if (listProjectResourcesCriteria == ListProjectResourcesCriteria.SkipProjectResources) { + sc.addAnd("accountType", SearchCriteria.Op.NEQ, Account.ACCOUNT_TYPE_PROJECT); + } else if (listProjectResourcesCriteria == ListProjectResourcesCriteria.ListProjectResourcesOnly) { + sc.addAnd("accountType", SearchCriteria.Op.EQ, Account.ACCOUNT_TYPE_PROJECT); + } + + // add criteria for domain path in case of domain admin + if ((templateFilter == TemplateFilter.self || templateFilter == TemplateFilter.selfexecutable) + && (caller.getType() == Account.ACCOUNT_TYPE_DOMAIN_ADMIN || caller.getType() == Account.ACCOUNT_TYPE_RESOURCE_DOMAIN_ADMIN)) { + sc.addAnd("domainPath", SearchCriteria.Op.LIKE, domain.getPath() + "%"); + } + + List relatedDomainIds = new ArrayList(); + List permittedAccountIds = new ArrayList(); + if (!permittedAccounts.isEmpty()) { + for (Account account : permittedAccounts) { + permittedAccountIds.add(account.getId()); + boolean publicTemplates = (templateFilter == TemplateFilter.featured || templateFilter == TemplateFilter.community); + + // get all parent domain ID's all the way till root domain + DomainVO domainTreeNode = null; + //if template filter is featured, or community, all child domains should be included in search + if (publicTemplates) { + domainTreeNode = _domainDao.findById(Domain.ROOT_DOMAIN); + + } else { + domainTreeNode = _domainDao.findById(account.getDomainId()); + } + relatedDomainIds.add(domainTreeNode.getId()); + while (domainTreeNode.getParent() != null) { + domainTreeNode = _domainDao.findById(domainTreeNode.getParent()); + relatedDomainIds.add(domainTreeNode.getId()); + } + + // get all child domain ID's + if (_accountMgr.isAdmin(account.getId()) || publicTemplates) { + List allChildDomains = _domainDao.findAllChildren(domainTreeNode.getPath(), domainTreeNode.getId()); + for (DomainVO childDomain : allChildDomains) { + relatedDomainIds.add(childDomain.getId()); + } + } + } + } + + if (!isIso) { + // add hypervisor criteria for template case + if (hypers != null && !hypers.isEmpty()) { + String[] relatedHypers = new String[hypers.size()]; + for (int i = 0; i < hypers.size(); i++) { + relatedHypers[i] = hypers.get(i).toString(); + } + sc.addAnd("hypervisorType", SearchCriteria.Op.IN, relatedHypers); + } + } + + // control different template filters + if (templateFilter == TemplateFilter.featured || templateFilter == TemplateFilter.community) { + sc.addAnd("publicTemplate", SearchCriteria.Op.EQ, true); + if (templateFilter == TemplateFilter.featured) { + sc.addAnd("featured", SearchCriteria.Op.EQ, true); + } else { + sc.addAnd("featured", SearchCriteria.Op.EQ, false); + } + if (!permittedAccounts.isEmpty()) { + SearchCriteria scc = _templateJoinDao.createSearchCriteria(); + scc.addOr("domainId", SearchCriteria.Op.IN, relatedDomainIds.toArray()); + scc.addOr("domainId", SearchCriteria.Op.NULL); + sc.addAnd("domainId", SearchCriteria.Op.SC, scc); + } + } else if (templateFilter == TemplateFilter.self || templateFilter == TemplateFilter.selfexecutable) { + if (!permittedAccounts.isEmpty()) { + sc.addAnd("accountId", SearchCriteria.Op.IN, permittedAccountIds.toArray()); + } + } else if (templateFilter == TemplateFilter.sharedexecutable || templateFilter == TemplateFilter.shared) { + // only show templates shared by others + sc.addAnd("sharedAccountId", SearchCriteria.Op.IN, permittedAccountIds.toArray()); + } else if (templateFilter == TemplateFilter.executable) { + SearchCriteria scc = _templateJoinDao.createSearchCriteria(); + scc.addOr("publicTemplate", SearchCriteria.Op.EQ, true); + if (!permittedAccounts.isEmpty()) { + scc.addOr("accountId", SearchCriteria.Op.IN, permittedAccountIds.toArray()); + } + sc.addAnd("publicTemplate", SearchCriteria.Op.SC, scc); + } + + // add tags criteria + if (tags != null && !tags.isEmpty()) { + SearchCriteria scc = _templateJoinDao.createSearchCriteria(); + for (String key : tags.keySet()) { + SearchCriteria scTag = _templateJoinDao.createSearchCriteria(); + scTag.addAnd("tagKey", SearchCriteria.Op.EQ, key); + scTag.addAnd("tagValue", SearchCriteria.Op.EQ, tags.get(key)); + if (isIso) { + scTag.addAnd("tagResourceType", SearchCriteria.Op.EQ, ResourceObjectType.ISO); + } else { + scTag.addAnd("tagResourceType", SearchCriteria.Op.EQ, ResourceObjectType.Template); + } + scc.addOr("tagKey", SearchCriteria.Op.SC, scTag); + } + sc.addAnd("tagKey", SearchCriteria.Op.SC, scc); + } + + // other criteria + + if (keyword != null) { + sc.addAnd("name", SearchCriteria.Op.LIKE, "%" + keyword + "%"); + } else if (name != null) { + sc.addAnd("name", SearchCriteria.Op.EQ, name); + } + + if (isIso) { + sc.addAnd("format", SearchCriteria.Op.EQ, "ISO"); + + } else { + sc.addAnd("format", SearchCriteria.Op.NEQ, "ISO"); + } + + if (!hyperType.equals(HypervisorType.None)) { + sc.addAnd("hypervisorType", SearchCriteria.Op.EQ, hyperType); + } + + if (bootable != null) { + sc.addAnd("bootable", SearchCriteria.Op.EQ, bootable); + } + + if (onlyReady) { + SearchCriteria readySc = _templateJoinDao.createSearchCriteria(); + readySc.addOr("state", SearchCriteria.Op.EQ, TemplateState.Ready); + readySc.addOr("format", SearchCriteria.Op.EQ, ImageFormat.BAREMETAL); + SearchCriteria isoPerhostSc = _templateJoinDao.createSearchCriteria(); + isoPerhostSc.addAnd("format", SearchCriteria.Op.EQ, ImageFormat.ISO); + isoPerhostSc.addAnd("templateType", SearchCriteria.Op.EQ, TemplateType.PERHOST); + readySc.addOr("templateType", SearchCriteria.Op.SC, isoPerhostSc); + sc.addAnd("state", SearchCriteria.Op.SC, readySc); + } + + if (!showDomr) { + // excluding system template + sc.addAnd("templateType", SearchCriteria.Op.NEQ, Storage.TemplateType.SYSTEM); + } + } + + if (zoneId != null) { + SearchCriteria zoneSc = _templateJoinDao.createSearchCriteria(); + zoneSc.addOr("dataCenterId", SearchCriteria.Op.EQ, zoneId); + zoneSc.addOr("dataStoreScope", SearchCriteria.Op.EQ, ScopeType.REGION); + // handle the case where xs-tools.iso and vmware-tools.iso do not + // have data_center information in template_view + SearchCriteria isoPerhostSc = _templateJoinDao.createSearchCriteria(); + isoPerhostSc.addAnd("format", SearchCriteria.Op.EQ, ImageFormat.ISO); + isoPerhostSc.addAnd("templateType", SearchCriteria.Op.EQ, TemplateType.PERHOST); + zoneSc.addOr("templateType", SearchCriteria.Op.SC, isoPerhostSc); + sc.addAnd("dataCenterId", SearchCriteria.Op.SC, zoneSc); + } + + // don't return removed template, this should not be needed since we + // changed annotation for removed field in TemplateJoinVO. + // sc.addAnd("removed", SearchCriteria.Op.NULL); + + // search unique templates and find details by Ids + Pair, Integer> uniqueTmplPair = null; + if (showRemovedTmpl) { + uniqueTmplPair = _templateJoinDao.searchIncludingRemovedAndCount(sc, searchFilter); + } else { + sc.addAnd("templateState", SearchCriteria.Op.EQ, State.Active); + uniqueTmplPair = _templateJoinDao.searchAndCount(sc, searchFilter); + } + + Integer count = uniqueTmplPair.second(); + if (count.intValue() == 0) { + // empty result + return uniqueTmplPair; + } + List uniqueTmpls = uniqueTmplPair.first(); + String[] tzIds = new String[uniqueTmpls.size()]; + int i = 0; + for (TemplateJoinVO v : uniqueTmpls) { + tzIds[i++] = v.getTempZonePair(); + } + List vrs = _templateJoinDao.searchByTemplateZonePair(showRemovedTmpl, tzIds); + return new Pair, Integer>(vrs, count); + + // TODO: revisit the special logic for iso search in + // VMTemplateDaoImpl.searchForTemplates and understand why we need to + // specially handle ISO. The original logic is very twisted and no idea + // about what the code was doing. + + } + @Override public ListResponse listIsos(ListIsosCmd cmd) { Pair, Integer> result = searchForIsosInternal(cmd); @@ -3102,6 +3484,40 @@ private Pair, Integer> searchForIsosInternal(ListIsosCmd cm boolean showRemovedISO = cmd.getShowRemoved(); Account caller = CallContext.current().getCallingAccount(); + boolean listAll = false; + if (isoFilter != null && isoFilter == TemplateFilter.all) { + if (caller.getType() == Account.ACCOUNT_TYPE_NORMAL) { + throw new InvalidParameterValueException("Filter " + TemplateFilter.all + + " can be specified by admin only"); + } + listAll = true; + } + + List permittedAccountIds = new ArrayList(); + Ternary domainIdRecursiveListProject = new Ternary( + cmd.getDomainId(), cmd.isRecursive(), null); + buildTemplateAffinityGroupSearchParameters(caller, id, cmd.getAccountName(), cmd.getProjectId(), permittedAccountIds, + domainIdRecursiveListProject, listAll, false); + ListProjectResourcesCriteria listProjectResourcesCriteria = domainIdRecursiveListProject.third(); + List permittedAccounts = new ArrayList(); + for (Long accountId : permittedAccountIds) { + permittedAccounts.add(_accountMgr.getAccount(accountId)); + } + + HypervisorType hypervisorType = HypervisorType.getType(cmd.getHypervisor()); + + return searchForTemplatesInternal(cmd.getId(), cmd.getIsoName(), cmd.getKeyword(), isoFilter, true, + cmd.isBootable(), cmd.getPageSizeVal(), cmd.getStartIndex(), cmd.getZoneId(), hypervisorType, true, + cmd.listInReadyState(), permittedAccounts, caller, listProjectResourcesCriteria, tags, showRemovedISO); + } + + private Pair, Integer> searchForIsosInternalIAM(ListIsosCmd cmd) { + TemplateFilter isoFilter = TemplateFilter.valueOf(cmd.getIsoFilter()); + Long id = cmd.getId(); + Map tags = cmd.getTags(); + boolean showRemovedISO = cmd.getShowRemoved(); + Account caller = CallContext.current().getCallingAccount(); + boolean listAll = false; if (isoFilter != null && isoFilter == TemplateFilter.all) { if (_accountMgr.isNormalUser(caller.getId())) { @@ -3128,7 +3544,7 @@ private Pair, Integer> searchForIsosInternal(ListIsosCmd cm HypervisorType hypervisorType = HypervisorType.getType(cmd.getHypervisor()); - return searchForTemplatesInternal(cmd.getId(), cmd.getIsoName(), cmd.getKeyword(), isoFilter, true, + return searchForTemplatesInternalIAM(cmd.getId(), cmd.getIsoName(), cmd.getKeyword(), isoFilter, true, cmd.isBootable(), cmd.getPageSizeVal(), cmd.getStartIndex(), cmd.getZoneId(), hypervisorType, true, cmd.listInReadyState(), permittedDomains, permittedAccounts, permittedResources, isRecursive, caller, listProjectResourcesCriteria, tags, showRemovedISO); } @@ -3154,12 +3570,167 @@ public Pair, Integer> listAffinityGroupsInternal(Long caller.getAccountId(); + if (vmId != null) { + UserVmVO userVM = _userVmDao.findById(vmId); + if (userVM == null) { + throw new InvalidParameterValueException("Unable to list affinity groups for virtual machine instance " + + vmId + "; instance not found."); + } + _accountMgr.checkAccess(caller, null, userVM); + return listAffinityGroupsByVM(vmId.longValue(), startIndex, pageSize); + } + + List permittedAccounts = new ArrayList(); + Ternary domainIdRecursiveListProject = new Ternary( + domainId, isRecursive, null); + buildTemplateAffinityGroupSearchParameters(caller, affinityGroupId, accountName, null, permittedAccounts, + domainIdRecursiveListProject, listAll, true); + domainId = domainIdRecursiveListProject.first(); + isRecursive = domainIdRecursiveListProject.second(); + ListProjectResourcesCriteria listProjectResourcesCriteria = domainIdRecursiveListProject.third(); + + Filter searchFilter = new Filter(AffinityGroupJoinVO.class, "id", true, startIndex, pageSize); + SearchCriteria sc = buildAffinityGroupSearchCriteria(domainId, isRecursive, + permittedAccounts, listProjectResourcesCriteria, affinityGroupId, affinityGroupName, affinityGroupType, keyword); + + Pair, Integer> uniqueGroupsPair = _affinityGroupJoinDao.searchAndCount(sc, + searchFilter); + // search group details by ids + List vrs = new ArrayList(); + Integer count = uniqueGroupsPair.second(); + if (count.intValue() != 0) { + List uniqueGroups = uniqueGroupsPair.first(); + Long[] vrIds = new Long[uniqueGroups.size()]; + int i = 0; + for (AffinityGroupJoinVO v : uniqueGroups) { + vrIds[i++] = v.getId(); + } + vrs = _affinityGroupJoinDao.searchByIds(vrIds); + } + + if (!permittedAccounts.isEmpty()) { + // add domain level affinity groups + if (domainId != null) { + SearchCriteria scDomain = buildAffinityGroupSearchCriteria(null, isRecursive, + new ArrayList(), listProjectResourcesCriteria, affinityGroupId, affinityGroupName, + affinityGroupType, keyword); + vrs.addAll(listDomainLevelAffinityGroups(scDomain, searchFilter, domainId)); + } else { + + for (Long permAcctId : permittedAccounts) { + Account permittedAcct = _accountDao.findById(permAcctId); + SearchCriteria scDomain = buildAffinityGroupSearchCriteria( + null, isRecursive, new ArrayList(), + listProjectResourcesCriteria, affinityGroupId, affinityGroupName, affinityGroupType, keyword); + + vrs.addAll(listDomainLevelAffinityGroups(scDomain, searchFilter, permittedAcct.getDomainId())); + } + } + } else if (((permittedAccounts.isEmpty()) && (domainId != null) && isRecursive)) { + // list all domain level affinity groups for the domain admin case + SearchCriteria scDomain = buildAffinityGroupSearchCriteria(null, isRecursive, + new ArrayList(), listProjectResourcesCriteria, affinityGroupId, affinityGroupName, + affinityGroupType, keyword); + vrs.addAll(listDomainLevelAffinityGroups(scDomain, searchFilter, domainId)); + } + + return new Pair, Integer>(vrs, vrs.size()); + + } + + private void buildAffinityGroupViewSearchBuilder(SearchBuilder sb, Long domainId, + boolean isRecursive, List permittedAccounts, ListProjectResourcesCriteria listProjectResourcesCriteria) { + + sb.and("accountIdIN", sb.entity().getAccountId(), SearchCriteria.Op.IN); + sb.and("domainId", sb.entity().getDomainId(), SearchCriteria.Op.EQ); + + if (((permittedAccounts.isEmpty()) && (domainId != null) && isRecursive)) { + // if accountId isn't specified, we can do a domain match for the + // admin case if isRecursive is true + sb.and("domainPath", sb.entity().getDomainPath(), SearchCriteria.Op.LIKE); + } + + if (listProjectResourcesCriteria != null) { + if (listProjectResourcesCriteria == Project.ListProjectResourcesCriteria.ListProjectResourcesOnly) { + sb.and("accountType", sb.entity().getAccountType(), SearchCriteria.Op.EQ); + } else if (listProjectResourcesCriteria == Project.ListProjectResourcesCriteria.SkipProjectResources) { + sb.and("accountType", sb.entity().getAccountType(), SearchCriteria.Op.NEQ); + } + } + + } + + private void buildAffinityGroupViewSearchCriteria(SearchCriteria sc, + Long domainId, boolean isRecursive, List permittedAccounts, ListProjectResourcesCriteria listProjectResourcesCriteria) { + + if (listProjectResourcesCriteria != null) { + sc.setParameters("accountType", Account.ACCOUNT_TYPE_PROJECT); + } + + if (!permittedAccounts.isEmpty()) { + sc.setParameters("accountIdIN", permittedAccounts.toArray()); + } else if (domainId != null) { + DomainVO domain = _domainDao.findById(domainId); + if (isRecursive) { + sc.setParameters("domainPath", domain.getPath() + "%"); + } else { + sc.setParameters("domainId", domainId); + } + } + } + + private SearchCriteria buildAffinityGroupSearchCriteria(Long domainId, boolean isRecursive, + List permittedAccounts, ListProjectResourcesCriteria listProjectResourcesCriteria, + Long affinityGroupId, String affinityGroupName, String affinityGroupType, String keyword) { + + SearchBuilder groupSearch = _affinityGroupJoinDao.createSearchBuilder(); + buildAffinityGroupViewSearchBuilder(groupSearch, domainId, isRecursive, permittedAccounts, + listProjectResourcesCriteria); + + groupSearch.select(null, Func.DISTINCT, groupSearch.entity().getId()); // select + // distinct + + SearchCriteria sc = groupSearch.create(); + buildAffinityGroupViewSearchCriteria(sc, domainId, isRecursive, permittedAccounts, + listProjectResourcesCriteria); + + if (affinityGroupId != null) { + sc.addAnd("id", SearchCriteria.Op.EQ, affinityGroupId); + } + + if (affinityGroupName != null) { + sc.addAnd("name", SearchCriteria.Op.EQ, affinityGroupName); + } + + if (affinityGroupType != null) { + sc.addAnd("type", SearchCriteria.Op.EQ, affinityGroupType); + } + + if (keyword != null) { + SearchCriteria ssc = _affinityGroupJoinDao.createSearchCriteria(); + ssc.addOr("name", SearchCriteria.Op.LIKE, "%" + keyword + "%"); + ssc.addOr("type", SearchCriteria.Op.LIKE, "%" + keyword + "%"); + + sc.addAnd("name", SearchCriteria.Op.SC, ssc); + } + + return sc; + } + + public Pair, Integer> listAffinityGroupsInternalIAM(Long affinityGroupId, + String affinityGroupName, String affinityGroupType, Long vmId, String accountName, Long domainId, + boolean isRecursive, boolean listAll, Long startIndex, Long pageSize, String keyword) { + + Account caller = CallContext.current().getCallingAccount(); + + caller.getAccountId(); + if (vmId != null) { UserVmVO userVM = _userVmDao.findById(vmId); if (userVM == null) { throw new InvalidParameterValueException("Unable to list affinity groups for virtual machine instance " + vmId + "; instance not found."); } - _accountMgr.checkAccess(caller, null, true, userVM); + _accountMgr.checkAccess(caller, null, userVM); return listAffinityGroupsByVM(vmId.longValue(), startIndex, pageSize); } @@ -3175,7 +3746,7 @@ public Pair, Integer> listAffinityGroupsInternal(Long ListProjectResourcesCriteria listProjectResourcesCriteria = domainIdRecursiveListProject.third(); Filter searchFilter = new Filter(AffinityGroupJoinVO.class, "id", true, startIndex, pageSize); - SearchCriteria sc = buildAffinityGroupSearchCriteria(isRecursive, + SearchCriteria sc = buildAffinityGroupSearchCriteriaIAM(isRecursive, permittedDomains, permittedAccounts, permittedResources, listProjectResourcesCriteria, affinityGroupId, affinityGroupName, affinityGroupType, keyword); Pair, Integer> uniqueGroupsPair = _affinityGroupJoinDao.searchAndCount(sc, searchFilter); @@ -3224,7 +3795,7 @@ public Pair, Integer> listAffinityGroupsInternal(Long } - private SearchCriteria buildAffinityGroupSearchCriteria(boolean isRecursive, + private SearchCriteria buildAffinityGroupSearchCriteriaIAM(boolean isRecursive, List permittedDomains, List permittedAccounts, List permittedResources, ListProjectResourcesCriteria listProjectResourcesCriteria, Long affinityGroupId, String affinityGroupName, String affinityGroupType, String keyword) { @@ -3321,7 +3892,7 @@ private List listDomainLevelAffinityGroups(SearchCriteria listResourceDetails(ListResourceDetailsCmd cmd) { String key = cmd.getKey(); - Boolean forDisplay = cmd.forDisplay(); + Boolean forDisplay = cmd.getDisplay(); ResourceTag.ResourceObjectType resourceType = cmd.getResourceType(); String resourceIdStr = cmd.getResourceId(); Long resourceId = null; @@ -3338,7 +3909,7 @@ public List listResourceDetails(ListResourceDetailsCmd c detailList = _resourceMetaDataMgr.getDetailsList(resourceId, resourceType, forDisplay); } else { requestedDetail = _resourceMetaDataMgr.getDetail(resourceId, resourceType, key); - if (forDisplay != null && requestedDetail.isDisplay() != forDisplay) { + if (requestedDetail != null && forDisplay != null && requestedDetail.isDisplay() != forDisplay) { requestedDetail = null; } } diff --git a/server/src/com/cloud/api/query/dao/HostJoinDaoImpl.java b/server/src/com/cloud/api/query/dao/HostJoinDaoImpl.java index 6c890fc830..9a4b38efbb 100644 --- a/server/src/com/cloud/api/query/dao/HostJoinDaoImpl.java +++ b/server/src/com/cloud/api/query/dao/HostJoinDaoImpl.java @@ -108,7 +108,13 @@ public HostResponse newHostResponse(HostJoinVO host, EnumSet detail for (VGPUTypesVO vgpuType : vgpuTypes) { VgpuResponse vgpuResponse = new VgpuResponse(); vgpuResponse.setName(vgpuType.getVgpuType()); - vgpuResponse.setCapacity(vgpuType.getRemainingCapacity()); + vgpuResponse.setVideoRam(vgpuType.getVideoRam()); + vgpuResponse.setMaxHeads(vgpuType.getMaxHeads()); + vgpuResponse.setMaxResolutionX(vgpuType.getMaxResolutionX()); + vgpuResponse.setMaxResolutionY(vgpuType.getMaxResolutionY()); + vgpuResponse.setMaxVgpuPerPgpu(vgpuType.getMaxVgpuPerPgpu()); + vgpuResponse.setRemainingCapacity(vgpuType.getRemainingCapacity()); + vgpuResponse.setmaxCapacity(vgpuType.getMaxCapacity()); vgpus.add(vgpuResponse); } gpuResponse.setVgpu(vgpus); diff --git a/server/src/com/cloud/api/query/dao/TemplateJoinDaoImpl.java b/server/src/com/cloud/api/query/dao/TemplateJoinDaoImpl.java index 1cab6e8040..80ef0f6ed7 100644 --- a/server/src/com/cloud/api/query/dao/TemplateJoinDaoImpl.java +++ b/server/src/com/cloud/api/query/dao/TemplateJoinDaoImpl.java @@ -302,7 +302,7 @@ public TemplateResponse newIsoResponse(TemplateJoinVO iso) { Account caller = CallContext.current().getCallingAccount(); boolean isAdmin = false; - if ((caller == null) || _accountService.isAdmin(caller.getType())) { + if ((caller == null) || _accountService.isAdmin(caller.getId())) { isAdmin = true; } diff --git a/server/src/com/cloud/api/query/dao/VolumeJoinDaoImpl.java b/server/src/com/cloud/api/query/dao/VolumeJoinDaoImpl.java index 8a0431baaa..9e1ee37ceb 100644 --- a/server/src/com/cloud/api/query/dao/VolumeJoinDaoImpl.java +++ b/server/src/com/cloud/api/query/dao/VolumeJoinDaoImpl.java @@ -215,6 +215,14 @@ public VolumeResponse newVolumeResponse(ResponseView view, VolumeJoinVO volume) volResponse.setDisplayVolume(volume.isDisplayVolume()); volResponse.setChainInfo(volume.getChainInfo()); + volResponse.setTemplateId(volume.getTemplateUuid()); + volResponse.setTemplateName(volume.getTemplateName()); + volResponse.setTemplateDisplayText(volume.getTemplateDisplayText()); + + volResponse.setIsoId(volume.getIsoUuid()); + volResponse.setIsoName(volume.getIsoName()); + volResponse.setIsoDisplayText(volume.getIsoDisplayText()); + // set async job if (volume.getJobId() != null) { volResponse.setJobId(volume.getJobUuid()); diff --git a/server/src/com/cloud/api/query/vo/AffinityGroupJoinVO.java b/server/src/com/cloud/api/query/vo/AffinityGroupJoinVO.java index f659ed95bb..bcd0fdcbb9 100644 --- a/server/src/com/cloud/api/query/vo/AffinityGroupJoinVO.java +++ b/server/src/com/cloud/api/query/vo/AffinityGroupJoinVO.java @@ -24,7 +24,7 @@ import javax.persistence.Table; import org.apache.cloudstack.acl.ControlledEntity; -import org.apache.cloudstack.acl.IAMEntityType; +import org.apache.cloudstack.affinity.AffinityGroup; import com.cloud.vm.VirtualMachine; @@ -194,8 +194,8 @@ public ControlledEntity.ACLType getAclType() { } @Override - public IAMEntityType getEntityType() { - return IAMEntityType.AffinityGroup; + public Class getEntityType() { + return AffinityGroup.class; } } diff --git a/server/src/com/cloud/api/query/vo/AsyncJobJoinVO.java b/server/src/com/cloud/api/query/vo/AsyncJobJoinVO.java index 7889b760a1..be85c2a62b 100644 --- a/server/src/com/cloud/api/query/vo/AsyncJobJoinVO.java +++ b/server/src/com/cloud/api/query/vo/AsyncJobJoinVO.java @@ -25,8 +25,8 @@ import javax.persistence.Id; import javax.persistence.Table; -import org.apache.cloudstack.acl.IAMEntityType; import org.apache.cloudstack.api.ApiCommandJobType; +import org.apache.cloudstack.framework.jobs.AsyncJob; import com.cloud.utils.db.GenericDao; @@ -203,8 +203,8 @@ public String getInstanceUuid() { } @Override - public IAMEntityType getEntityType() { - return IAMEntityType.AsyncJob; + public Class getEntityType() { + return AsyncJob.class; } @Override diff --git a/server/src/com/cloud/api/query/vo/DomainRouterJoinVO.java b/server/src/com/cloud/api/query/vo/DomainRouterJoinVO.java index ac32859ea1..79eb3bfb70 100644 --- a/server/src/com/cloud/api/query/vo/DomainRouterJoinVO.java +++ b/server/src/com/cloud/api/query/vo/DomainRouterJoinVO.java @@ -26,13 +26,12 @@ import javax.persistence.Id; import javax.persistence.Table; -import org.apache.cloudstack.acl.IAMEntityType; - import com.cloud.network.Network.GuestType; import com.cloud.network.Networks.TrafficType; import com.cloud.network.router.VirtualRouter; import com.cloud.network.router.VirtualRouter.RedundantState; import com.cloud.utils.db.GenericDao; +import com.cloud.vm.VirtualMachine; import com.cloud.vm.VirtualMachine.State; @Entity @@ -514,7 +513,7 @@ public VirtualRouter.Role getRole() { } @Override - public IAMEntityType getEntityType() { - return IAMEntityType.VirtualMachine; + public Class getEntityType() { + return VirtualMachine.class; } } diff --git a/server/src/com/cloud/api/query/vo/EventJoinVO.java b/server/src/com/cloud/api/query/vo/EventJoinVO.java index b6b023ef6e..8fba938876 100644 --- a/server/src/com/cloud/api/query/vo/EventJoinVO.java +++ b/server/src/com/cloud/api/query/vo/EventJoinVO.java @@ -25,8 +25,7 @@ import javax.persistence.Id; import javax.persistence.Table; -import org.apache.cloudstack.acl.IAMEntityType; - +import com.cloud.event.Event; import com.cloud.event.Event.State; import com.cloud.utils.db.GenericDao; @@ -227,7 +226,7 @@ public boolean getDisplay() { } @Override - public IAMEntityType getEntityType() { - return IAMEntityType.Event; + public Class getEntityType() { + return Event.class; } } diff --git a/server/src/com/cloud/api/query/vo/InstanceGroupJoinVO.java b/server/src/com/cloud/api/query/vo/InstanceGroupJoinVO.java index 98d1a523e7..857cebf75f 100644 --- a/server/src/com/cloud/api/query/vo/InstanceGroupJoinVO.java +++ b/server/src/com/cloud/api/query/vo/InstanceGroupJoinVO.java @@ -23,9 +23,8 @@ import javax.persistence.Id; import javax.persistence.Table; -import org.apache.cloudstack.acl.IAMEntityType; - import com.cloud.utils.db.GenericDao; +import com.cloud.vm.InstanceGroup; @Entity @Table(name = "instance_group_view") @@ -160,7 +159,7 @@ public Date getCreated() { } @Override - public IAMEntityType getEntityType() { - return IAMEntityType.InstanceGroup; + public Class getEntityType() { + return InstanceGroup.class; } } diff --git a/server/src/com/cloud/api/query/vo/ProjectInvitationJoinVO.java b/server/src/com/cloud/api/query/vo/ProjectInvitationJoinVO.java index ba619a9a08..8b4918561c 100644 --- a/server/src/com/cloud/api/query/vo/ProjectInvitationJoinVO.java +++ b/server/src/com/cloud/api/query/vo/ProjectInvitationJoinVO.java @@ -25,8 +25,7 @@ import javax.persistence.Id; import javax.persistence.Table; -import org.apache.cloudstack.acl.IAMEntityType; - +import com.cloud.projects.ProjectInvitation; import com.cloud.projects.ProjectInvitation.State; import com.cloud.utils.db.GenericDao; @@ -164,7 +163,7 @@ public String getDomainPath() { } @Override - public IAMEntityType getEntityType() { - return IAMEntityType.ProjectInvitation; + public Class getEntityType() { + return ProjectInvitation.class; } } diff --git a/server/src/com/cloud/api/query/vo/ResourceTagJoinVO.java b/server/src/com/cloud/api/query/vo/ResourceTagJoinVO.java index e1b8b812ae..2c1ff47509 100644 --- a/server/src/com/cloud/api/query/vo/ResourceTagJoinVO.java +++ b/server/src/com/cloud/api/query/vo/ResourceTagJoinVO.java @@ -23,8 +23,7 @@ import javax.persistence.Id; import javax.persistence.Table; -import org.apache.cloudstack.acl.IAMEntityType; - +import com.cloud.server.ResourceTag; import com.cloud.server.ResourceTag.ResourceObjectType; @Entity @@ -182,7 +181,7 @@ public String getCustomer() { } @Override - public IAMEntityType getEntityType() { - return IAMEntityType.ResourceTag; + public Class getEntityType() { + return ResourceTag.class; } } diff --git a/server/src/com/cloud/api/query/vo/SecurityGroupJoinVO.java b/server/src/com/cloud/api/query/vo/SecurityGroupJoinVO.java index 3c9e3bf87a..69604e8286 100644 --- a/server/src/com/cloud/api/query/vo/SecurityGroupJoinVO.java +++ b/server/src/com/cloud/api/query/vo/SecurityGroupJoinVO.java @@ -23,8 +23,7 @@ import javax.persistence.Id; import javax.persistence.Table; -import org.apache.cloudstack.acl.IAMEntityType; - +import com.cloud.network.security.SecurityGroup; import com.cloud.network.security.SecurityRule.SecurityRuleType; import com.cloud.server.ResourceTag.ResourceObjectType; @@ -306,7 +305,7 @@ public String getTagCustomer() { } @Override - public IAMEntityType getEntityType() { - return IAMEntityType.SecurityGroup; + public Class getEntityType() { + return SecurityGroup.class; } } diff --git a/server/src/com/cloud/api/query/vo/TemplateJoinVO.java b/server/src/com/cloud/api/query/vo/TemplateJoinVO.java index de0da2f1e5..834a9cedd0 100644 --- a/server/src/com/cloud/api/query/vo/TemplateJoinVO.java +++ b/server/src/com/cloud/api/query/vo/TemplateJoinVO.java @@ -27,7 +27,6 @@ import javax.persistence.Temporal; import javax.persistence.TemporalType; -import org.apache.cloudstack.acl.IAMEntityType; import org.apache.cloudstack.engine.subsystem.api.storage.ObjectInDataStoreStateMachine; import com.cloud.hypervisor.Hypervisor.HypervisorType; @@ -35,6 +34,7 @@ import com.cloud.storage.ScopeType; import com.cloud.storage.Storage; import com.cloud.storage.VMTemplateStorageResourceAssoc.Status; +import com.cloud.template.VirtualMachineTemplate; import com.cloud.template.VirtualMachineTemplate.State; import com.cloud.utils.db.GenericDao; @@ -544,7 +544,7 @@ public State getTemplateState() { } @Override - public IAMEntityType getEntityType() { - return IAMEntityType.VirtualMachineTemplate; + public Class getEntityType() { + return VirtualMachineTemplate.class; } } diff --git a/server/src/com/cloud/api/query/vo/UserVmJoinVO.java b/server/src/com/cloud/api/query/vo/UserVmJoinVO.java index fcee393207..f3f48fc9ae 100644 --- a/server/src/com/cloud/api/query/vo/UserVmJoinVO.java +++ b/server/src/com/cloud/api/query/vo/UserVmJoinVO.java @@ -28,8 +28,6 @@ import javax.persistence.Table; import javax.persistence.Transient; -import org.apache.cloudstack.acl.IAMEntityType; - import com.cloud.hypervisor.Hypervisor.HypervisorType; import com.cloud.network.Network.GuestType; import com.cloud.network.Networks.TrafficType; @@ -913,7 +911,7 @@ public String getDetailValue() { } @Override - public IAMEntityType getEntityType() { - return IAMEntityType.VirtualMachine; + public Class getEntityType() { + return VirtualMachine.class; } } diff --git a/server/src/com/cloud/api/query/vo/VolumeJoinVO.java b/server/src/com/cloud/api/query/vo/VolumeJoinVO.java index 289b0b85af..cb6dc4d1b6 100644 --- a/server/src/com/cloud/api/query/vo/VolumeJoinVO.java +++ b/server/src/com/cloud/api/query/vo/VolumeJoinVO.java @@ -27,8 +27,6 @@ import javax.persistence.Temporal; import javax.persistence.TemporalType; -import org.apache.cloudstack.acl.IAMEntityType; - import com.cloud.hypervisor.Hypervisor.HypervisorType; import com.cloud.server.ResourceTag.ResourceObjectType; import com.cloud.storage.Storage; @@ -214,12 +212,30 @@ public class VolumeJoinVO extends BaseViewVO implements ControlledViewEntity { @Column(name = "template_uuid") private String templateUuid; + @Column(name = "template_name") + private String templateName; + + @Column(name = "template_display_text", length = 4096) + private String templateDisplayText; + @Column(name = "extractable") private boolean extractable; @Column(name = "template_type") private Storage.TemplateType templateType; + @Column(name = "iso_id", updatable = true, nullable = true, length = 17) + private long isoId; + + @Column(name = "iso_uuid") + private String isoUuid; + + @Column(name = "iso_name") + private String isoName; + + @Column(name = "iso_display_text", length = 4096) + private String isoDisplayText; + @Column(name = "job_id") private Long jobId; @@ -496,6 +512,30 @@ public Storage.TemplateType getTemplateType() { return templateType; } + public String getTemplateName() { + return templateName; + } + + public String getTemplateDisplayText() { + return templateDisplayText; + } + + public long getIsoId() { + return isoId; + } + + public String getIsoUuid() { + return isoUuid; + } + + public String getIsoName() { + return isoName; + } + + public String getIsoDisplayText() { + return isoDisplayText; + } + public Long getJobId() { return jobId; } @@ -578,7 +618,7 @@ public String getChainInfo() { } @Override - public IAMEntityType getEntityType() { - return IAMEntityType.Volume; + public Class getEntityType() { + return Volume.class; } } diff --git a/server/src/com/cloud/api/response/SecurityGroupResultObject.java b/server/src/com/cloud/api/response/SecurityGroupResultObject.java index 66ba487641..c2cd423bef 100644 --- a/server/src/com/cloud/api/response/SecurityGroupResultObject.java +++ b/server/src/com/cloud/api/response/SecurityGroupResultObject.java @@ -22,7 +22,6 @@ import java.util.Map; import org.apache.cloudstack.acl.ControlledEntity; -import org.apache.cloudstack.acl.IAMEntityType; import org.apache.cloudstack.api.InternalIdentity; import com.cloud.api.ApiDBUtils; @@ -212,7 +211,7 @@ public static List transposeNetworkGroups(List getEntityType() { + return SecurityGroup.class; } } diff --git a/server/src/com/cloud/capacity/CapacityManagerImpl.java b/server/src/com/cloud/capacity/CapacityManagerImpl.java index 69e8cfa169..14fbe7f80b 100755 --- a/server/src/com/cloud/capacity/CapacityManagerImpl.java +++ b/server/src/com/cloud/capacity/CapacityManagerImpl.java @@ -182,6 +182,10 @@ public boolean stop() { @DB @Override public boolean releaseVmCapacity(VirtualMachine vm, final boolean moveFromReserved, final boolean moveToReservered, final Long hostId) { + if (hostId == null) { + return true; + } + final ServiceOfferingVO svo = _offeringsDao.findById(vm.getId(), vm.getServiceOfferingId()); CapacityVO capacityCpu = _capacityDao.findByHostIdType(hostId, Capacity.CAPACITY_TYPE_CPU); CapacityVO capacityMemory = _capacityDao.findByHostIdType(hostId, Capacity.CAPACITY_TYPE_MEMORY); @@ -544,7 +548,7 @@ public long getAllocatedPoolCapacity(StoragePoolVO pool, VMTemplateVO templateFo // if the storage pool is managed, the used bytes can be larger than the sum of the sizes of all of the non-destroyed volumes // in this case, call getUsedBytes(StoragePoolVO) if (pool.isManaged()) { - totalAllocatedSize = getUsedBytes(pool); + return getUsedBytes(pool); } else { // Get size for all the non-destroyed volumes diff --git a/server/src/com/cloud/configuration/Config.java b/server/src/com/cloud/configuration/Config.java index f2fe68a78a..bf72dc2246 100755 --- a/server/src/com/cloud/configuration/Config.java +++ b/server/src/com/cloud/configuration/Config.java @@ -16,15 +16,6 @@ // under the License. package com.cloud.configuration; -import java.util.ArrayList; -import java.util.HashMap; -import java.util.List; -import java.util.StringTokenizer; - -import org.apache.cloudstack.engine.orchestration.service.NetworkOrchestrationService; -import org.apache.cloudstack.engine.subsystem.api.storage.StoragePoolAllocator; -import org.apache.cloudstack.framework.config.ConfigKey; - import com.cloud.agent.AgentManager; import com.cloud.consoleproxy.ConsoleProxyManager; import com.cloud.ha.HighAvailabilityManager; @@ -38,6 +29,14 @@ import com.cloud.template.TemplateManager; import com.cloud.vm.UserVmManager; import com.cloud.vm.snapshot.VMSnapshotManager; +import org.apache.cloudstack.engine.orchestration.service.NetworkOrchestrationService; +import org.apache.cloudstack.engine.subsystem.api.storage.StoragePoolAllocator; +import org.apache.cloudstack.framework.config.ConfigKey; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.StringTokenizer; public enum Config { @@ -702,7 +701,7 @@ public enum Config { "system.vm.use.local.storage", "false", "Indicates whether to use local storage pools or shared storage pools for system VMs.", - null), + null, ConfigKey.Scope.Zone.toString()), SystemVMAutoReserveCapacity( "Advanced", ManagementServer.class, @@ -1803,6 +1802,23 @@ public enum Config { "Timeout to echo baremetal security group agent, in seconds, the provisioning process will be treated as a failure", null), + BaremetalIpmiLanInterface( + "Advanced", + ManagementServer.class, + String.class, + "baremetal.ipmi.lan.interface", + "default", + "option specified in -I option of impitool. candidates are: open/bmc/lipmi/lan/lanplus/free/imb, see ipmitool man page for details. default valule 'default' means using default option of ipmitool", + null), + + BaremetalIpmiRetryTimes("Advanced", + ManagementServer.class, + String.class, + "baremetal.ipmi.fail.retry", + "5", + "ipmi interface will be temporary out of order after power opertions(e.g. cycle, on), it leads following commands fail immediately. The value specifies retry times before accounting it as real failure", + null), + ApiLimitEnabled("Advanced", ManagementServer.class, Boolean.class, "api.throttling.enabled", "false", "Enable/disable Api rate limit", null), ApiLimitInterval("Advanced", ManagementServer.class, Integer.class, "api.throttling.interval", "1", "Time interval (in seconds) to reset API count", null), ApiLimitMax("Advanced", ManagementServer.class, Integer.class, "api.throttling.max", "25", "Max allowed number of APIs within fixed interval", null), @@ -1898,6 +1914,24 @@ public enum Config { "the interval cloudstack sync with UCS manager for available blades in case user remove blades from chassis without notifying CloudStack", null), + RedundantRouterVrrpInterval( + "Advanced", + NetworkOrchestrationService.class, + Integer.class, + "router.redundant.vrrp.interval", + "1", + "seconds between VRRP broadcast. It would 3 times broadcast fail to trigger fail-over mechanism of redundant router", + null), + + RouterAggregationCommandEachTimeout( + "Advanced", + NetworkOrchestrationService.class, + Integer.class, + "router.aggregation.command.each.timeout", + "3", + "timeout in seconds for each Virtual Router command being aggregated. The final aggregation command timeout would be determined by this timeout * commands counts ", + null), + ManagementServerVendor("Advanced", ManagementServer.class, String.class, "mgt.server.vendor", "ACS", "the vendor of management server", null); private final String _category; diff --git a/server/src/com/cloud/configuration/ConfigurationManagerImpl.java b/server/src/com/cloud/configuration/ConfigurationManagerImpl.java index 9b9bd13d26..231b5e1dc2 100755 --- a/server/src/com/cloud/configuration/ConfigurationManagerImpl.java +++ b/server/src/com/cloud/configuration/ConfigurationManagerImpl.java @@ -39,6 +39,7 @@ import org.apache.log4j.Logger; import org.apache.cloudstack.acl.SecurityChecker; +import org.apache.cloudstack.acl.SecurityChecker.AccessType; import org.apache.cloudstack.affinity.AffinityGroup; import org.apache.cloudstack.affinity.AffinityGroupService; import org.apache.cloudstack.affinity.dao.AffinityGroupDao; @@ -153,6 +154,7 @@ import com.cloud.network.dao.PhysicalNetworkTrafficTypeDao; import com.cloud.network.dao.PhysicalNetworkTrafficTypeVO; import com.cloud.network.dao.PhysicalNetworkVO; +import com.cloud.network.element.NetworkElement; import com.cloud.network.rules.LoadBalancerContainer.Scheme; import com.cloud.network.vpc.VpcManager; import com.cloud.offering.DiskOffering; @@ -2083,47 +2085,36 @@ protected ServiceOfferingVO createServiceOffering(long userId, boolean isSystem, offering.setHypervisorSnapshotReserve(hypervisorSnapshotReserve); List detailsVO = null; - if (details != null) { - // Check if the user has passed the gpu-type before passing the VGPU type - if (!details.containsKey(GPU.Keys.pciDevice.toString()) && details.containsKey(GPU.Keys.vgpuType.toString())) { - throw new InvalidParameterValueException("Please specify the gpu type"); + if (details != null) { + // To have correct input, either both gpu card name and VGPU type should be passed or nothing should be passed. + // Use XOR condition to verify that. + boolean entry1 = details.containsKey(GPU.Keys.pciDevice.toString()); + boolean entry2 = details.containsKey(GPU.Keys.vgpuType.toString()); + if ((entry1 || entry2) && !(entry1 && entry2)) { + throw new InvalidParameterValueException("Please specify the pciDevice and vgpuType correctly."); } detailsVO = new ArrayList(); - for (Entry detailEntry : details.entrySet()) { + for (Entry detailEntry : details.entrySet()) { String value = null; if (detailEntry.getKey().equals(GPU.Keys.pciDevice.toString())) { - for (GPU.Type type : GPU.Type.values()) { - if (detailEntry.getValue().equals(type.toString())) { - value = detailEntry.getValue(); - } - } - if (value == null) { - throw new InvalidParameterValueException("Please specify valid gpu type"); + if (detailEntry.getValue() == null) { + throw new InvalidParameterValueException("Please specify a GPU Card."); } } if (detailEntry.getKey().equals(GPU.Keys.vgpuType.toString())) { - if (details.get(GPU.Keys.pciDevice.toString()).equals(GPU.Type.GPU_Passthrough.toString())) { - throw new InvalidParameterValueException("vgpuTypes are supported only with vGPU pciDevice"); - } if (detailEntry.getValue() == null) { - throw new InvalidParameterValueException("With vGPU as pciDevice, vGPUType value cannot be null"); + throw new InvalidParameterValueException("vGPUType value cannot be null"); } for (GPU.vGPUType entry : GPU.vGPUType.values()) { if (detailEntry.getValue().equals(entry.getType())) { value = entry.getType(); } } - if (value == null || detailEntry.getValue().equals(GPU.vGPUType.passthrough.getType())) { + if (value == null) { throw new InvalidParameterValueException("Please specify valid vGPU type"); } } - detailsVO.add(new ServiceOfferingDetailsVO(offering.getId(), detailEntry.getKey(), detailEntry.getValue(), true)); - } - // If pciDevice type is passed, put the default VGPU type as 'passthrough' - if (details.containsKey(GPU.Keys.pciDevice.toString()) - && !details.containsKey(GPU.Keys.vgpuType.toString())) { - detailsVO.add(new ServiceOfferingDetailsVO(offering.getId(), - GPU.Keys.vgpuType.toString(), GPU.vGPUType.passthrough.getType(), true)); + detailsVO.add(new ServiceOfferingDetailsVO(offering.getId(), detailEntry.getKey(), detailEntry.getValue(), true)); } } @@ -3814,10 +3805,21 @@ public NetworkOffering createNetworkOffering(CreateNetworkOfferingCmd cmd) { } validateStaticNatServiceCapablities(staticNatServiceCapabilityMap); + // validate the 'Connectivity' service capabilities specified in the network offering, if 'Connectivity' service + // is in the supported services of network offering + Map connectivityServiceCapabilityMap = cmd.getServiceCapabilities(Service.Connectivity); + if (!serviceProviderMap.containsKey(Service.Connectivity) && + (connectivityServiceCapabilityMap != null && !connectivityServiceCapabilityMap.isEmpty())) { + throw new InvalidParameterValueException("Capabilities for 'Connectivity' service can be specified " + + "only when Connectivity service is enabled for network offering."); + } + validateConnectivityServiceCapablities(serviceProviderMap.get(Service.Connectivity), connectivityServiceCapabilityMap); + Map> serviceCapabilityMap = new HashMap>(); serviceCapabilityMap.put(Service.Lb, lbServiceCapabilityMap); serviceCapabilityMap.put(Service.SourceNat, sourceNatServiceCapabilityMap); serviceCapabilityMap.put(Service.StaticNat, staticNatServiceCapabilityMap); + serviceCapabilityMap.put(Service.Connectivity, connectivityServiceCapabilityMap); // if Firewall service is missing, add Firewall service/provider // combination @@ -3952,6 +3954,37 @@ void validateStaticNatServiceCapablities(Map staticNatServic } } + void validateConnectivityServiceCapablities(Set providers, Map connectivityServiceCapabilityMap) { + if (connectivityServiceCapabilityMap != null && !connectivityServiceCapabilityMap.isEmpty()) { + for (Capability capability: connectivityServiceCapabilityMap.keySet()) { + if (capability == Capability.StretchedL2Subnet) { + String value = connectivityServiceCapabilityMap.get(capability).toLowerCase(); + if (!(value.contains("true") ^ value.contains("false"))) { + throw new InvalidParameterValueException("Invalid value (" + value + ") for " + capability + + " should be true/false"); + } + } else { + throw new InvalidParameterValueException("Capability " + capability.getName() + " can not be " + + " specified with connectivity service."); + } + } + + // validate connectivity service provider actually supports specified capabilities + if (providers != null && !providers.isEmpty()) { + for (Provider provider: providers) { + NetworkElement element = _networkModel.getElementImplementingProvider(provider.getName()); + Map> capabilities = element.getCapabilities(); + if (capabilities != null && !capabilities.isEmpty()) { + Map connectivityCapabilities = capabilities.get(Service.Connectivity); + if (connectivityCapabilities == null || (connectivityCapabilities != null && !connectivityCapabilities.keySet().contains(Capability.StretchedL2Subnet))) { + throw new InvalidParameterValueException("Provider: " + provider.getName() + " does not support " + + Capability.StretchedL2Subnet.getName()); + } + } + } + } + } + } @Override @DB public NetworkOfferingVO createNetworkOffering(String name, String displayText, TrafficType trafficType, String tags, boolean specifyVlan, Availability availability, @@ -4012,6 +4045,8 @@ public NetworkOfferingVO createNetworkOffering(String name, String displayText, boolean inline = false; boolean publicLb = false; boolean internalLb = false; + boolean strechedL2Subnet = false; + if (serviceCapabilityMap != null && !serviceCapabilityMap.isEmpty()) { Map lbServiceCapabilityMap = serviceCapabilityMap.get(Service.Lb); @@ -4079,6 +4114,14 @@ public NetworkOfferingVO createNetworkOffering(String name, String displayText, } } } + + Map connectivityServiceCapabilityMap = serviceCapabilityMap.get(Service.Connectivity); + if (connectivityServiceCapabilityMap != null && !connectivityServiceCapabilityMap.isEmpty()) { + String value = connectivityServiceCapabilityMap.get(Capability.StretchedL2Subnet); + if ("true".equalsIgnoreCase(value)) { + strechedL2Subnet = true; + } + } } if (serviceProviderMap != null && serviceProviderMap.containsKey(Service.Lb) && !internalLb && !publicLb) { @@ -4088,7 +4131,7 @@ public NetworkOfferingVO createNetworkOffering(String name, String displayText, final NetworkOfferingVO offeringFinal = new NetworkOfferingVO(name, displayText, trafficType, systemOnly, specifyVlan, networkRate, multicastRate, isDefault, availability, tags, type, conserveMode, dedicatedLb, sharedSourceNat, redundantRouter, elasticIp, elasticLb, specifyIpRanges, inline, isPersistent, associatePublicIp, publicLb, - internalLb, egressDefaultPolicy); + internalLb, egressDefaultPolicy, strechedL2Subnet); if (serviceOfferingId != null) { offeringFinal.setServiceOfferingId(serviceOfferingId); @@ -4285,7 +4328,7 @@ public List searchForNetworkOfferings(ListNetworkOffe throw new InvalidParameterValueException("Can't update system networks"); } - _accountMgr.checkAccess(caller, null, true, network); + _accountMgr.checkAccess(caller, AccessType.ListEntry, network); List offeringIds = _networkModel.listNetworkOfferingsForUpgrade(networkId); diff --git a/server/src/com/cloud/deploy/DeploymentPlanningManagerImpl.java b/server/src/com/cloud/deploy/DeploymentPlanningManagerImpl.java index 9cbbb10c84..c2a5ff5f0d 100644 --- a/server/src/com/cloud/deploy/DeploymentPlanningManagerImpl.java +++ b/server/src/com/cloud/deploy/DeploymentPlanningManagerImpl.java @@ -198,6 +198,8 @@ public void setHostAllocators(List hostAllocators) { @Inject protected StoragePoolHostDao _poolHostDao; + @Inject + protected DataCenterDao _zoneDao; @Inject protected VolumeDao _volsDao; @Inject @@ -316,6 +318,15 @@ public DeployDestination planDeployment(VirtualMachineProfile vmProfile, Deploym host.getClusterId()); } + Pod pod = _podDao.findById(host.getPodId()); + Cluster cluster = _clusterDao.findById(host.getClusterId()); + + if (vm.getHypervisorType() == HypervisorType.BareMetal) { + DeployDestination dest = new DeployDestination(dc, pod, cluster, host, new HashMap()); + s_logger.debug("Returning Deployment Destination: " + dest); + return dest; + } + // search for storage under the zone, pod, cluster of the host. DataCenterDeployment lastPlan = new DataCenterDeployment(host.getDataCenterId(), host.getPodId(), host.getClusterId(), hostIdSpecified, plan.getPoolId(), null, @@ -333,8 +344,6 @@ public DeployDestination planDeployment(VirtualMachineProfile vmProfile, Deploym suitableHosts, suitableVolumeStoragePools, avoids, getPlannerUsage(planner, vmProfile, plan, avoids), readyAndReusedVolumes); if (potentialResources != null) { - Pod pod = _podDao.findById(host.getPodId()); - Cluster cluster = _clusterDao.findById(host.getClusterId()); Map storageVolMap = potentialResources.second(); // remove the reused vol<->pool from destination, since // we don't have to prepare this volume. @@ -363,9 +372,11 @@ public DeployDestination planDeployment(VirtualMachineProfile vmProfile, Deploym } else if (_capacityMgr.checkIfHostReachMaxGuestLimit(host)) { s_logger.debug("The last Host, hostId: " + host.getId() + " already has max Running VMs(count includes system VMs), skipping this and trying other available hosts"); - } else if ((offeringDetails = _serviceOfferingDetailsDao.findDetail(offering.getId(), GPU.Keys.vgpuType.toString())) != null - && !_resourceMgr.isGPUDeviceAvailable(host.getId(), offeringDetails.getValue())){ - s_logger.debug("The last host of this VM does not have required GPU devices available"); + } else if ((offeringDetails = _serviceOfferingDetailsDao.findDetail(offering.getId(), GPU.Keys.vgpuType.toString())) != null) { + ServiceOfferingDetailsVO groupName = _serviceOfferingDetailsDao.findDetail(offering.getId(), GPU.Keys.pciDevice.toString()); + if(!_resourceMgr.isGPUDeviceAvailable(host.getId(), groupName.getValue(), offeringDetails.getValue())){ + s_logger.debug("The last host of this VM does not have required GPU devices available"); + } } else { if (host.getStatus() == Status.Up && host.getResourceState() == ResourceState.Enabled) { boolean hostTagsMatch = true; @@ -393,10 +404,22 @@ public DeployDestination planDeployment(VirtualMachineProfile vmProfile, Deploym // search for storage under the zone, pod, cluster // of // the last host. - DataCenterDeployment lastPlan = new DataCenterDeployment(host.getDataCenterId(), - host.getPodId(), host.getClusterId(), host.getId(), plan.getPoolId(), null); - Pair>, List> result = findSuitablePoolsForVolumes( - vmProfile, lastPlan, avoids, HostAllocator.RETURN_UPTO_ALL); + + + Pod pod = _podDao.findById(host.getPodId()); + Cluster cluster = _clusterDao.findById(host.getClusterId()); + + if (vm.getHypervisorType() == HypervisorType.BareMetal) { + DeployDestination dest = new DeployDestination(dc, pod, cluster, host, new HashMap()); + s_logger.debug("Returning Deployment Destination: " + dest); + return dest; + } + + DataCenterDeployment lastPlan = new DataCenterDeployment(host.getDataCenterId(), + host.getPodId(), host.getClusterId(), host.getId(), plan.getPoolId(), null); + Pair>, List> result = findSuitablePoolsForVolumes( + vmProfile, lastPlan, avoids, HostAllocator.RETURN_UPTO_ALL); + Map> suitableVolumeStoragePools = result.first(); List readyAndReusedVolumes = result.second(); @@ -409,8 +432,6 @@ public DeployDestination planDeployment(VirtualMachineProfile vmProfile, Deploym suitableHosts, suitableVolumeStoragePools, avoids, getPlannerUsage(planner, vmProfile, plan, avoids), readyAndReusedVolumes); if (potentialResources != null) { - Pod pod = _podDao.findById(host.getPodId()); - Cluster cluster = _clusterDao.findById(host.getClusterId()); Map storageVolMap = potentialResources.second(); // remove the reused vol<->pool from // destination, since we don't have to @@ -1252,7 +1273,18 @@ protected Pair>, List> findSuitablePoolsFo boolean useLocalStorage = false; if (vmProfile.getType() != VirtualMachine.Type.User) { String ssvmUseLocalStorage = _configDao.getValue(Config.SystemVMUseLocalStorage.key()); - if (ssvmUseLocalStorage.equalsIgnoreCase("true")) { + + DataCenterVO zone = _zoneDao.findById(plan.getDataCenterId()); + + // It should not happen to have a "null" zone here. There can be NO instance if there is NO zone, + // so this part of the code would never be reached if no zone has been created. + // + // Added the check and the comment just to make it clear. + boolean zoneUsesLocalStorage = zone != null ? zone.isLocalStorageEnabled() : false; + + // Local storage is used for the NON User VMs if, and only if, the Zone is marked to use local storage AND + // the global settings (ssvmUseLocalStorage) is set to true. Otherwise, the global settings won't be applied. + if (ssvmUseLocalStorage.equalsIgnoreCase("true") && zoneUsesLocalStorage) { useLocalStorage = true; } } else { diff --git a/server/src/com/cloud/event/ActionEventUtils.java b/server/src/com/cloud/event/ActionEventUtils.java index 28e5680b63..363bb93b4d 100755 --- a/server/src/com/cloud/event/ActionEventUtils.java +++ b/server/src/com/cloud/event/ActionEventUtils.java @@ -26,7 +26,8 @@ import javax.inject.Inject; import com.cloud.utils.ReflectUtil; -import com.cloud.vm.VirtualMachine; +import com.cloud.utils.db.EntityManager; +import org.apache.cloudstack.api.Identity; import org.apache.log4j.Logger; import org.springframework.beans.factory.NoSuchBeanDefinitionException; @@ -54,6 +55,7 @@ public class ActionEventUtils { private static ProjectDao s_projectDao; protected static UserDao s_userDao; protected static EventBus s_eventBus = null; + protected static EntityManager s_entityMgr; public static final String EventDetails = "event_details"; public static final String EventId = "event_id"; @@ -69,6 +71,8 @@ public class ActionEventUtils { UserDao userDao; @Inject ProjectDao projectDao; + @Inject + EntityManager entityMgr; public ActionEventUtils() { } @@ -79,6 +83,7 @@ void init() { s_accountDao = accountDao; s_userDao = userDao; s_projectDao = projectDao; + s_entityMgr = entityMgr; } public static Long onActionEvent(Long userId, Long accountId, Long domainId, String type, String description) { @@ -188,19 +193,24 @@ private static void publishOnEventBus(long userId, long accountId, String eventC String entityType = null; String entityUuid = null; CallContext context = CallContext.current(); - String vmEntityName = ReflectUtil.getEntityName(VirtualMachine.class); - String vmuuid = (String) context.getContextParameter(vmEntityName); Class entityKey = getEntityKey(eventType); - if (entityKey != null) - { + if (entityKey != null){ //FIXME - Remove this since it should be covered by the else if condition below. entityUuid = (String)context.getContextParameter(entityKey); if (entityUuid != null) entityType = entityKey.getName(); - }else if (EventTypes.getEntityForEvent(eventType) != null){ - entityType = EventTypes.getEntityForEvent(eventType); - if (entityType != null){ - entityUuid = (String)context.getContextParameter(entityType); + }else if (EventTypes.getEntityClassForEvent(eventType) != null){ + //Get entity Class(Example - VirtualMachine.class) from the event Type eg. - VM.CREATE + Class entityClass = EventTypes.getEntityClassForEvent(eventType); + + //Get uuid from id + if(context.getContextParameter(entityClass.getName()) != null){ + try { + final Object objVO = s_entityMgr.findByIdIncludingRemoved(entityClass, getInternalId(context.getContextParameter(entityClass.getName()))); + entityUuid = ((Identity)objVO).getUuid(); + } catch (Exception e){ + s_logger.debug("Caught exception while finding entityUUID, moving on"); + } } } @@ -225,7 +235,7 @@ private static void publishOnEventBus(long userId, long accountId, String eventC eventDescription.put("entity", entityType); eventDescription.put("entityuuid", entityUuid); //Put all the first class entities that are touched during the action. For now atleast put in the vmid. - eventDescription.put(vmEntityName, vmuuid); + populateFirstClassEntities(eventDescription); eventDescription.put("description", description); String eventDate = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss Z").format(new Date()); @@ -240,6 +250,19 @@ private static void publishOnEventBus(long userId, long accountId, String eventC } } + private static Long getInternalId(Object internalIdObj){ + Long internalId = null; + + // In case its an async job the value would be a string because of json deserialization + if(internalIdObj instanceof String){ + internalId = Long.valueOf((String) internalIdObj); + }else if (internalIdObj instanceof Long){ + internalId = (Long) internalIdObj; + } + + return internalId; + } + private static long getDomainId(long accountId) { AccountVO account = s_accountDao.findByIdIncludingRemoved(accountId); if (account == null) { @@ -249,6 +272,27 @@ private static long getDomainId(long accountId) { return account.getDomainId(); } + private static void populateFirstClassEntities(Map eventDescription){ + + CallContext context = CallContext.current(); + Map contextMap = context.getContextParameters(); + + try{ + for(Map.Entry entry : contextMap.entrySet()){ + Object key = entry.getKey(); + Class clz = Class.forName((String)key); + if(clz instanceof Class && Identity.class.isAssignableFrom(clz)){ + final Object objVO = s_entityMgr.findById(clz, getInternalId(entry.getValue())); + String uuid = ((Identity) objVO).getUuid(); + eventDescription.put(ReflectUtil.getEntityName(clz), uuid); + } + } + }catch (Exception e){ + s_logger.debug("Caught exception while populating first class entities for event bus, moving on", e); + } + + } + private static Class getEntityKey(String eventType) { // FIXME - Remove this diff --git a/server/src/com/cloud/ha/HighAvailabilityManagerImpl.java b/server/src/com/cloud/ha/HighAvailabilityManagerImpl.java index 48d998a53d..1318d9b8c7 100755 --- a/server/src/com/cloud/ha/HighAvailabilityManagerImpl.java +++ b/server/src/com/cloud/ha/HighAvailabilityManagerImpl.java @@ -72,7 +72,6 @@ import com.cloud.utils.component.ManagerBase; import com.cloud.utils.concurrency.NamedThreadFactory; import com.cloud.utils.exception.CloudRuntimeException; -import com.cloud.utils.fsm.StateListener; import com.cloud.vm.VMInstanceVO; import com.cloud.vm.VirtualMachine; import com.cloud.vm.VirtualMachine.State; @@ -103,8 +102,7 @@ * before retrying the stop | seconds | 120 || * } **/ @Local(value = { HighAvailabilityManager.class }) -public class HighAvailabilityManagerImpl extends ManagerBase implements HighAvailabilityManager, ClusterManagerListener, - StateListener { +public class HighAvailabilityManagerImpl extends ManagerBase implements HighAvailabilityManager, ClusterManagerListener { protected static final Logger s_logger = Logger.getLogger(HighAvailabilityManagerImpl.class); WorkerThread[] _workers; @@ -236,7 +234,7 @@ public void scheduleRestartForVmsOnHost(final HostVO host, boolean investigate) return; } - s_logger.warn("Scheduling restart for VMs on host " + host.getId()); + s_logger.warn("Scheduling restart for VMs on host " + host.getId() + "-" + host.getName()); final List vms = _instanceDao.listByHostId(host.getId()); final DataCenterVO dcVO = _dcDao.findById(host.getDataCenterId()); @@ -269,12 +267,12 @@ public void scheduleRestartForVmsOnHost(final HostVO host, boolean investigate) for (VMInstanceVO vm : vms) { if (s_logger.isDebugEnabled()) { - s_logger.debug("Notifying HA Mgr of to restart vm " + vm.getId() + "-" + vm.getHostName()); + s_logger.debug("Notifying HA Mgr of to restart vm " + vm.getId() + "-" + vm.getInstanceName()); } vm = _instanceDao.findByUuid(vm.getUuid()); Long hostId = vm.getHostId(); if ( hostId != null && !hostId.equals(host.getId()) ) { - s_logger.debug("VM " + vm.getHostName() + " is not on down host " + host.getId() + " it is on other host " + s_logger.debug("VM " + vm.getInstanceName() + " is not on down host " + host.getId() + " it is on other host " + hostId + " VM HA is done"); continue; } @@ -503,7 +501,7 @@ protected Long restart(HaWorkVO work) { } else if (!alive) { fenced = true; } else { - s_logger.debug("VM " + vm.getHostName() + " is found to be alive by " + investigator.getName()); + s_logger.debug("VM " + vm.getInstanceName() + " is found to be alive by " + investigator.getName()); if (host.getStatus() == Status.Up) { s_logger.info(vm + " is alive and host is up. No need to restart it."); return null; @@ -806,7 +804,6 @@ public boolean configure(final String name, final Map xmlParams) _stopped = true; _executor = Executors.newScheduledThreadPool(count, new NamedThreadFactory("HA")); - VirtualMachine.State.getStateMachine().registerListener(this); return true; } @@ -921,6 +918,12 @@ private void runWithContext() { work.setTimeToTry(nextTime); work.setServerId(null); work.setDateTaken(null); + + // if restart failed in the middle due to exception, VM state may has been changed + // recapture into the HA worker so that it can really continue in it next turn + VMInstanceVO vm = _instanceDao.findById(work.getInstanceId()); + work.setUpdateTime(vm.getUpdated()); + work.setPreviousState(vm.getState()); } _haDao.update(work.getId(), work); } catch (final Throwable th) { @@ -962,38 +965,9 @@ public DeploymentPlanner getHAPlanner() { return _haPlanners.get(0); } - @Override - public boolean preStateTransitionEvent(State oldState, VirtualMachine.Event event, State newState, VirtualMachine vo, boolean status, Object opaque) { - return true; - } - - @Override - public boolean postStateTransitionEvent(State oldState, VirtualMachine.Event event, State newState, VirtualMachine vo, boolean status, Object opaque) { - if (oldState == State.Running && event == VirtualMachine.Event.FollowAgentPowerOffReport && newState == State.Stopped) { - final VMInstanceVO vm = _instanceDao.findById(vo.getId()); - if (vm.isHaEnabled()) { - if (vm.getState() != State.Stopped) - s_logger.warn("Sanity check failed. postStateTransitionEvent reports transited to Stopped but VM " + vm + " is still at state " + vm.getState()); - - s_logger.info("Detected out-of-band stop of a HA enabled VM " + vm.getInstanceName() + ", will schedule restart"); - _executor.submit(new ManagedContextRunnable() { - @Override - protected void runInContext() { - try { - scheduleRestart(vm, false); - } catch (Exception e) { - s_logger.warn("Unexpected exception when scheduling a HA restart", e); - } - } - }); - } - } - return true; - } - @Override public boolean hasPendingHaWork(long vmId) { - List haWorks = _haDao.listRunningHaWorkForVm(vmId); + List haWorks = _haDao.listPendingHaWorkForVm(vmId); return haWorks.size() > 0; } } diff --git a/server/src/com/cloud/ha/dao/HighAvailabilityDao.java b/server/src/com/cloud/ha/dao/HighAvailabilityDao.java index 7f532f2ae1..85135bb979 100644 --- a/server/src/com/cloud/ha/dao/HighAvailabilityDao.java +++ b/server/src/com/cloud/ha/dao/HighAvailabilityDao.java @@ -81,4 +81,6 @@ public interface HighAvailabilityDao extends GenericDao { * @return List of work items */ List listRunningHaWorkForVm(long vmId); + + List listPendingHaWorkForVm(long vmId); } diff --git a/server/src/com/cloud/ha/dao/HighAvailabilityDaoImpl.java b/server/src/com/cloud/ha/dao/HighAvailabilityDaoImpl.java index c0da88396c..d25c6a7937 100644 --- a/server/src/com/cloud/ha/dao/HighAvailabilityDaoImpl.java +++ b/server/src/com/cloud/ha/dao/HighAvailabilityDaoImpl.java @@ -49,6 +49,7 @@ public class HighAvailabilityDaoImpl extends GenericDaoBase impl private final SearchBuilder ReleaseSearch; private final SearchBuilder FutureHaWorkSearch; private final SearchBuilder RunningHaWorkSearch; + private final SearchBuilder PendingHaWorkSearch; protected HighAvailabilityDaoImpl() { super(); @@ -106,6 +107,22 @@ protected HighAvailabilityDaoImpl() { RunningHaWorkSearch.and("taken", RunningHaWorkSearch.entity().getDateTaken(), Op.NNULL); RunningHaWorkSearch.and("step", RunningHaWorkSearch.entity().getStep(), Op.NIN); RunningHaWorkSearch.done(); + + PendingHaWorkSearch = createSearchBuilder(); + PendingHaWorkSearch.and("instance", PendingHaWorkSearch.entity().getInstanceId(), Op.EQ); + PendingHaWorkSearch.and("type", PendingHaWorkSearch.entity().getType(), Op.EQ); + PendingHaWorkSearch.and("step", PendingHaWorkSearch.entity().getStep(), Op.NIN); + PendingHaWorkSearch.done(); + } + + @Override + public List listPendingHaWorkForVm(long vmId) { + SearchCriteria sc = PendingHaWorkSearch.create(); + sc.setParameters("instance", vmId); + sc.setParameters("type", WorkType.HA); + sc.setParameters("step", Step.Done, Step.Error, Step.Cancelled); + + return search(sc, null); } @Override diff --git a/server/src/com/cloud/hypervisor/HypervisorGuruBase.java b/server/src/com/cloud/hypervisor/HypervisorGuruBase.java index b643ec41fa..e2520d26ff 100644 --- a/server/src/com/cloud/hypervisor/HypervisorGuruBase.java +++ b/server/src/com/cloud/hypervisor/HypervisorGuruBase.java @@ -144,7 +144,8 @@ protected VirtualMachineTO toVirtualMachineTO(VirtualMachineProfile vmProfile) { // Set GPU details ServiceOfferingDetailsVO offeringDetail = null; if ((offeringDetail = _serviceOfferingDetailsDao.findDetail(offering.getId(), GPU.Keys.vgpuType.toString())) != null) { - to.setGpuDevice(_resourceMgr.getGPUDevice(vm.getHostId(), offeringDetail.getValue())); + ServiceOfferingDetailsVO groupName = _serviceOfferingDetailsDao.findDetail(offering.getId(), GPU.Keys.pciDevice.toString()); + to.setGpuDevice(_resourceMgr.getGPUDevice(vm.getHostId(), groupName.getValue(), offeringDetail.getValue())); } // Workaround to make sure the TO has the UUID we need for Niciri integration diff --git a/server/src/com/cloud/hypervisor/KVMGuru.java b/server/src/com/cloud/hypervisor/KVMGuru.java index e47e699b02..4225232064 100644 --- a/server/src/com/cloud/hypervisor/KVMGuru.java +++ b/server/src/com/cloud/hypervisor/KVMGuru.java @@ -19,16 +19,28 @@ import javax.ejb.Local; import javax.inject.Inject; +import org.apache.cloudstack.storage.command.StorageSubSystemCommand; + +import com.cloud.agent.api.Command; import com.cloud.agent.api.to.VirtualMachineTO; +import com.cloud.host.HostVO; +import com.cloud.host.dao.HostDao; import com.cloud.hypervisor.Hypervisor.HypervisorType; +import com.cloud.storage.GuestOSHypervisorVO; import com.cloud.storage.GuestOSVO; import com.cloud.storage.dao.GuestOSDao; +import com.cloud.storage.dao.GuestOSHypervisorDao; +import com.cloud.utils.Pair; import com.cloud.vm.VirtualMachineProfile; @Local(value = HypervisorGuru.class) public class KVMGuru extends HypervisorGuruBase implements HypervisorGuru { @Inject GuestOSDao _guestOsDao; + @Inject + GuestOSHypervisorDao _guestOsHypervisorDao; + @Inject + HostDao _hostDao; @Override public HypervisorType getHypervisorType() { @@ -40,16 +52,29 @@ protected KVMGuru() { } @Override + public VirtualMachineTO implement(VirtualMachineProfile vm) { VirtualMachineTO to = toVirtualMachineTO(vm); // Determine the VM's OS description GuestOSVO guestOS = _guestOsDao.findById(vm.getVirtualMachine().getGuestOSId()); to.setOs(guestOS.getDisplayName()); + HostVO host = _hostDao.findById(vm.getVirtualMachine().getHostId()); + GuestOSHypervisorVO guestOsMapping = _guestOsHypervisorDao.findByOsIdAndHypervisor(guestOS.getId(), getHypervisorType().toString(), host.getHypervisorVersion()); + to.setPlatformEmulator(guestOsMapping.getGuestOsName()); return to; } + @Override + public Pair getCommandHostDelegation(long hostId, Command cmd) { + if (cmd instanceof StorageSubSystemCommand) { + StorageSubSystemCommand c = (StorageSubSystemCommand)cmd; + c.setExecuteInSequence(false); + } + return new Pair(false, new Long(hostId)); + } + @Override public boolean trackVmHostChange() { return false; diff --git a/server/src/com/cloud/hypervisor/kvm/discoverer/LibvirtServerDiscoverer.java b/server/src/com/cloud/hypervisor/kvm/discoverer/LibvirtServerDiscoverer.java index d127256d0f..8eb6c89e6f 100644 --- a/server/src/com/cloud/hypervisor/kvm/discoverer/LibvirtServerDiscoverer.java +++ b/server/src/com/cloud/hypervisor/kvm/discoverer/LibvirtServerDiscoverer.java @@ -16,18 +16,6 @@ // under the License. package com.cloud.hypervisor.kvm.discoverer; -import java.net.InetAddress; -import java.net.URI; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.UUID; - -import javax.inject.Inject; -import javax.naming.ConfigurationException; - -import org.apache.log4j.Logger; - import com.cloud.agent.AgentManager; import com.cloud.agent.Listener; import com.cloud.agent.api.AgentControlAnswer; @@ -55,6 +43,16 @@ import com.cloud.resource.ServerResource; import com.cloud.resource.UnableDeleteHostException; import com.cloud.utils.ssh.SSHCmdHelper; +import org.apache.log4j.Logger; + +import javax.inject.Inject; +import javax.naming.ConfigurationException; +import java.net.InetAddress; +import java.net.URI; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.UUID; public abstract class LibvirtServerDiscoverer extends DiscovererBase implements Discoverer, Listener, ResourceStateAdapter { private static final Logger s_logger = Logger.getLogger(LibvirtServerDiscoverer.class); @@ -211,6 +209,8 @@ public boolean processTimeout(long agentId, long seq) { KvmDummyResourceBase kvmResource = new KvmDummyResourceBase(); Map params = new HashMap(); + params.put("router.aggregation.command.each.timeout", _configDao.getValue(Config.RouterAggregationCommandEachTimeout.toString())); + params.put("zone", Long.toString(dcId)); params.put("pod", Long.toString(podId)); params.put("cluster", Long.toString(clusterId)); diff --git a/server/src/com/cloud/metadata/ResourceMetaDataManagerImpl.java b/server/src/com/cloud/metadata/ResourceMetaDataManagerImpl.java index d91da921eb..f7b092c5bd 100644 --- a/server/src/com/cloud/metadata/ResourceMetaDataManagerImpl.java +++ b/server/src/com/cloud/metadata/ResourceMetaDataManagerImpl.java @@ -40,7 +40,10 @@ import org.apache.cloudstack.resourcedetail.dao.UserIpAddressDetailsDao; import org.apache.cloudstack.resourcedetail.dao.VpcDetailsDao; import org.apache.cloudstack.resourcedetail.dao.VpcGatewayDetailsDao; +import org.apache.cloudstack.resourcedetail.dao.LBStickinessPolicyDetailsDao; +import org.apache.cloudstack.resourcedetail.dao.LBHealthCheckPolicyDetailsDao; import org.apache.cloudstack.storage.datastore.db.StoragePoolDetailsDao; + import org.apache.log4j.Logger; import org.springframework.stereotype.Component; @@ -113,6 +116,10 @@ public class ResourceMetaDataManagerImpl extends ManagerBase implements Resource AutoScaleVmProfileDetailsDao _autoScaleVmProfileDetailsDao; @Inject AutoScaleVmGroupDetailsDao _autoScaleVmGroupDetailsDao; + @Inject + LBStickinessPolicyDetailsDao _stickinessPolicyDao; + @Inject + LBHealthCheckPolicyDetailsDao _healthcheckPolicyDao; private static Map> s_daoMap = new HashMap>(); @@ -142,6 +149,8 @@ public boolean configure(String name, Map params) throws Configu s_daoMap.put(ResourceObjectType.User, _userDetailsDao); s_daoMap.put(ResourceObjectType.AutoScaleVmProfile, _autoScaleVmProfileDetailsDao); s_daoMap.put(ResourceObjectType.AutoScaleVmGroup, _autoScaleVmGroupDetailsDao); + s_daoMap.put(ResourceObjectType.LBStickinessPolicy, _stickinessPolicyDao); + s_daoMap.put(ResourceObjectType.LBHealthCheckPolicy, _healthcheckPolicyDao); return true; } diff --git a/server/src/com/cloud/network/IpAddressManagerImpl.java b/server/src/com/cloud/network/IpAddressManagerImpl.java index 9b1f9bd7ed..746221fca1 100644 --- a/server/src/com/cloud/network/IpAddressManagerImpl.java +++ b/server/src/com/cloud/network/IpAddressManagerImpl.java @@ -29,6 +29,8 @@ import javax.inject.Inject; +import org.apache.log4j.Logger; + import org.apache.cloudstack.acl.ControlledEntity.ACLType; import org.apache.cloudstack.acl.SecurityChecker.AccessType; import org.apache.cloudstack.context.CallContext; @@ -40,7 +42,6 @@ import org.apache.cloudstack.region.PortableIpDao; import org.apache.cloudstack.region.PortableIpVO; import org.apache.cloudstack.region.Region; -import org.apache.log4j.Logger; import com.cloud.agent.AgentManager; import com.cloud.alert.AlertManager; @@ -409,7 +410,7 @@ private IpAddress allocateIP(Account ipOwner, boolean isSystem, long zoneId) thr Account caller = CallContext.current().getCallingAccount(); long callerUserId = CallContext.current().getCallingUserId(); // check permissions - _accountMgr.checkAccess(caller, null, false, ipOwner); + _accountMgr.checkAccess(caller, null, ipOwner); DataCenter zone = _entityMgr.findById(DataCenter.class, zoneId); @@ -1164,15 +1165,14 @@ public IPAddressVO associateIPToGuestNetwork(long ipId, long networkId, boolean if (zone.getNetworkType() == NetworkType.Advanced) { if (network.getGuestType() == Network.GuestType.Shared) { if (isSharedNetworkOfferingWithServices(network.getNetworkOfferingId())) { - _accountMgr.checkAccess(CallContext.current().getCallingAccount(), AccessType.UseEntry, false, - network); + _accountMgr.checkAccess(CallContext.current().getCallingAccount(), AccessType.UseEntry, 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); + _accountMgr.checkAccess(caller, null, ipToAssoc); } owner = _accountMgr.getAccount(ipToAssoc.getAllocatedToAccountId()); } else { @@ -1187,7 +1187,7 @@ public IPAddressVO associateIPToGuestNetwork(long ipId, long networkId, boolean Network network = _networksDao.findById(networkId); if (network != null) { - _accountMgr.checkAccess(owner, AccessType.UseEntry, false, network); + _accountMgr.checkAccess(owner, AccessType.UseEntry, network); } else { s_logger.debug("Unable to find ip address by id: " + ipId); return null; @@ -1319,11 +1319,10 @@ public IPAddressVO disassociatePortableIPToGuestNetwork(long ipId, long networkI if (zone.getNetworkType() == NetworkType.Advanced) { if (network.getGuestType() == Network.GuestType.Shared) { assert (isSharedNetworkOfferingWithServices(network.getNetworkOfferingId())); - _accountMgr.checkAccess(CallContext.current().getCallingAccount(), AccessType.UseEntry, false, - network); + _accountMgr.checkAccess(CallContext.current().getCallingAccount(), AccessType.UseEntry, network); } } else { - _accountMgr.checkAccess(caller, null, true, ipToAssoc); + _accountMgr.checkAccess(caller, null, ipToAssoc); } owner = _accountMgr.getAccount(ipToAssoc.getAllocatedToAccountId()); } else { diff --git a/server/src/com/cloud/network/NetworkModelImpl.java b/server/src/com/cloud/network/NetworkModelImpl.java index 7b4b2bebdb..f84eccd9af 100755 --- a/server/src/com/cloud/network/NetworkModelImpl.java +++ b/server/src/com/cloud/network/NetworkModelImpl.java @@ -34,7 +34,9 @@ import org.apache.log4j.Logger; +import org.apache.cloudstack.acl.SecurityChecker; import org.apache.cloudstack.acl.ControlledEntity.ACLType; +import org.apache.cloudstack.acl.SecurityChecker.AccessType; import org.apache.cloudstack.framework.config.dao.ConfigurationDao; import org.apache.cloudstack.lb.dao.ApplicationLoadBalancerRuleDao; @@ -97,6 +99,7 @@ import com.cloud.projects.dao.ProjectAccountDao; import com.cloud.server.ConfigurationServer; import com.cloud.user.Account; +import com.cloud.user.AccountManager; import com.cloud.user.AccountVO; import com.cloud.user.DomainManager; import com.cloud.user.dao.AccountDao; @@ -173,7 +176,8 @@ public void setNetworkElements(List networkElements) { FirewallRulesDao _firewallDao; @Inject DomainManager _domainMgr; - + @Inject + AccountManager _accountMgr; @Inject NetworkOfferingServiceMapDao _ntwkOfferingSrvcDao; @Inject @@ -216,6 +220,16 @@ public void setNetworkElements(List networkElements) { static HashMap> s_serviceToImplementedProvidersMap = new HashMap>(); static HashMap s_providerToNetworkElementMap = new HashMap(); + List _securityCheckers; + + public List getSecurityCheckers() { + return _securityCheckers; + } + + public void setSecurityCheckers(List securityCheckers) { + _securityCheckers = securityCheckers; + } + /** * */ @@ -1566,6 +1580,35 @@ public void checkNetworkPermissions(Account owner, Network network) { } } + @Override + public void checkNetworkPermissions(Account owner, Network network, AccessType accessType) { + if (network == null) { + throw new CloudRuntimeException("cannot check permissions on (Network) "); + } + + AccountVO networkOwner = _accountDao.findById(network.getAccountId()); + if (networkOwner == null) { + throw new PermissionDeniedException("Unable to use network with id= " + ((NetworkVO) network).getUuid() + + ", network does not have an owner"); + } + if (owner.getType() != Account.ACCOUNT_TYPE_PROJECT && networkOwner.getType() == Account.ACCOUNT_TYPE_PROJECT) { + if (!_projectAccountDao.canAccessProjectAccount(owner.getAccountId(), network.getAccountId())) { + throw new PermissionDeniedException("Unable to use network with id= " + ((NetworkVO) network).getUuid() + + ", permission denied"); + } + } else { + // Go through IAM (SecurityCheckers) + for (SecurityChecker checker : _securityCheckers) { + if (checker.checkAccess(owner, accessType, null, network)) { + if (s_logger.isDebugEnabled()) { + s_logger.debug("Access to " + network + " granted to " + owner + " by " + checker.getName()); + } + break; + } + } + } + } + @Override public String getDefaultPublicTrafficLabel(long dcId, HypervisorType hypervisorType) { try { diff --git a/server/src/com/cloud/network/NetworkServiceImpl.java b/server/src/com/cloud/network/NetworkServiceImpl.java index 9238a1e8ce..ec9fa12b14 100755 --- a/server/src/com/cloud/network/NetworkServiceImpl.java +++ b/server/src/com/cloud/network/NetworkServiceImpl.java @@ -105,6 +105,7 @@ import com.cloud.network.dao.FirewallRulesDao; import com.cloud.network.dao.IPAddressDao; import com.cloud.network.dao.IPAddressVO; +import com.cloud.network.dao.LoadBalancerVMMapDao; import com.cloud.network.dao.NetworkDao; import com.cloud.network.dao.NetworkDomainDao; import com.cloud.network.dao.NetworkDomainVO; @@ -122,6 +123,7 @@ import com.cloud.network.element.VirtualRouterElement; import com.cloud.network.element.VpcVirtualRouterElement; import com.cloud.network.guru.NetworkGuru; +import com.cloud.network.lb.LoadBalancingRulesService; import com.cloud.network.rules.FirewallRule.Purpose; import com.cloud.network.rules.FirewallRuleVO; import com.cloud.network.rules.RulesManager; @@ -307,6 +309,11 @@ public class NetworkServiceImpl extends ManagerBase implements NetworkService { IpAddressManager _ipAddrMgr; @Inject EntityManager _entityMgr; + @Inject + LoadBalancerVMMapDao _lbVmMapDao; + + @Inject + LoadBalancingRulesService _lbService; int _cidrLimit; boolean _allowSubdomainNetworkAccess; @@ -535,7 +542,7 @@ public IpAddress allocateIP(Account ipOwner, long zoneId, Long networkId, Boolea // 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.UseEntry, false, network); + _accountMgr.checkAccess(caller, AccessType.UseEntry, network); if (s_logger.isDebugEnabled()) { s_logger.debug("Associate IP address called by the user " + callerUserId + " account " + ipOwner.getId()); } @@ -547,7 +554,7 @@ public IpAddress allocateIP(Account ipOwner, long zoneId, Long networkId, Boolea } } } else { - _accountMgr.checkAccess(caller, null, false, ipOwner); + _accountMgr.checkAccess(caller, null, ipOwner); } return _ipAddrMgr.allocateIp(ipOwner, false, caller, callerUserId, zone, displayIp); @@ -578,7 +585,7 @@ public IpAddress allocatePortableIP(Account ipOwner, int regionId, Long zoneId, // 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.UseEntry, false, network); + _accountMgr.checkAccess(caller, AccessType.UseEntry, network); if (s_logger.isDebugEnabled()) { s_logger.debug("Associate IP address called by the user " + callerUserId + " account " + ipOwner.getId()); } @@ -598,7 +605,7 @@ public IpAddress allocatePortableIP(Account ipOwner, int regionId, Long zoneId, } } - _accountMgr.checkAccess(caller, null, false, ipOwner); + _accountMgr.checkAccess(caller, null, ipOwner); return _ipAddrMgr.allocatePortableIp(ipOwner, caller, zoneId, null, null); } @@ -664,7 +671,7 @@ public NicSecondaryIp allocateSecondaryGuestIP(final long nicId, String requeste final Account ipOwner = _accountMgr.getAccount(vm.getAccountId()); // verify permissions - _accountMgr.checkAccess(caller, null, true, vm); + _accountMgr.checkAccess(caller, null, vm); Network network = _networksDao.findById(networkId); if (network == null) { @@ -760,7 +767,7 @@ public boolean releaseSecondaryIpFromNic(long ipAddressId) { throw new InvalidParameterValueException("There is no vm with the given secondary ip"); } // verify permissions - _accountMgr.checkAccess(caller, null, true, vm); + _accountMgr.checkAccess(caller, null, vm); Network network = _networksDao.findById(secIpVO.getNetworkId()); @@ -806,7 +813,13 @@ public boolean releaseSecondaryIpFromNic(long ipAddressId) { s_logger.debug("VM nic IP " + secondaryIp + " is associated with the static NAT rule public IP address id " + publicIpVO.getId()); throw new InvalidParameterValueException("Can' remove the ip " + secondaryIp + "is associate with static NAT rule public IP address id " + publicIpVO.getId()); } - } else if (dc.getNetworkType() == NetworkType.Basic || ntwkOff.getGuestType() == Network.GuestType.Shared) { + + if (_lbService.isLbRuleMappedToVmGuestIp(secondaryIp)) { + s_logger.debug("VM nic IP " + secondaryIp + " is mapped to load balancing rule"); + throw new InvalidParameterValueException("Can't remove the secondary ip " + secondaryIp + " is mapped to load balancing rule"); + } + + } else if (dc.getNetworkType() == NetworkType.Basic || ntwkOff.getGuestType() == Network.GuestType.Shared) { final IPAddressVO ip = _ipAddressDao.findByIpAndSourceNetworkId(secIpVO.getNetworkId(), secIpVO.getIp4Address()); if (ip != null) { Transaction.execute(new TransactionCallbackNoReturn() { @@ -878,7 +891,7 @@ private boolean releaseIpAddressInternal(long ipAddressId) throws InsufficientAd // verify permissions if (ipVO.getAllocatedToAccountId() != null) { - _accountMgr.checkAccess(caller, null, true, ipVO); + _accountMgr.checkAccess(caller, null, ipVO); } if (ipVO.isSourceNat()) { @@ -1072,14 +1085,14 @@ public Network createGuestNetwork(CreateNetworkCmd cmd) throws InsufficientCapac } // Only Admin can create Shared networks - if (ntwkOff.getGuestType() == GuestType.Shared && !_accountMgr.isAdmin(caller.getType())) { + if (ntwkOff.getGuestType() == GuestType.Shared && !_accountMgr.isAdmin(caller.getId())) { throw new InvalidParameterValueException("Only Admins can create network with guest type " + GuestType.Shared); } // Check if the network is domain specific if (aclType == ACLType.Domain) { // only Admin can create domain with aclType=Domain - if (!_accountMgr.isAdmin(caller.getType())) { + if (!_accountMgr.isAdmin(caller.getId())) { throw new PermissionDeniedException("Only admin can create networks with aclType=Domain"); } @@ -1419,12 +1432,12 @@ public Pair, Integer> searchForNetworks(ListNetworksCmd throw new InvalidParameterValueException("Unable to find account " + accountName + " in specified domain"); } - _accountMgr.checkAccess(caller, null, true, owner); + _accountMgr.checkAccess(caller, null, owner); permittedAccounts.add(owner.getId()); } } - if (!_accountMgr.isAdmin(caller.getType()) || (projectId != null && projectId.longValue() != -1 && domainId == null)) { + if (!_accountMgr.isAdmin(caller.getId()) || (projectId != null && projectId.longValue() != -1 && domainId == null)) { permittedAccounts.add(caller.getId()); domainId = caller.getDomainId(); } @@ -1433,7 +1446,7 @@ public Pair, Integer> searchForNetworks(ListNetworksCmd boolean skipProjectNetworks = true; if (projectId != null) { if (projectId.longValue() == -1) { - if (!_accountMgr.isAdmin(caller.getType())) { + if (!_accountMgr.isAdmin(caller.getId())) { permittedAccounts.addAll(_projectMgr.listPermittedProjectAccounts(caller.getId())); } } else { @@ -1452,7 +1465,7 @@ public Pair, Integer> searchForNetworks(ListNetworksCmd //add project account permittedAccounts.add(project.getProjectAccountId()); //add caller account (if admin) - if (_accountMgr.isAdmin(caller.getType())) { + if (_accountMgr.isAdmin(caller.getId())) { permittedAccounts.add(caller.getId()); } } @@ -1803,7 +1816,7 @@ public boolean deleteNetwork(long networkId, boolean forced) { Account owner = _accountMgr.getAccount(network.getAccountId()); // Perform permission check - _accountMgr.checkAccess(caller, null, true, network); + _accountMgr.checkAccess(caller, null, network); if (forced && !_accountMgr.isRootAdmin(caller.getId())) { throw new InvalidParameterValueException("Delete network with 'forced' option can only be called by root admins"); @@ -1847,7 +1860,7 @@ public boolean restartNetwork(RestartNetworkCmd cmd, boolean cleanup) throws Con throw new InvalidParameterException("Unable to restart a running SDN network."); } - _accountMgr.checkAccess(callerAccount, null, true, network); + _accountMgr.checkAccess(callerAccount, null, network); boolean success = _networkMgr.restartNetwork(networkId, callerAccount, callerUser, cleanup); @@ -1983,7 +1996,7 @@ public Network updateGuestNetwork(final long networkId, String name, String disp throw new InvalidParameterValueException("Can't allow networks which traffic type is not " + TrafficType.Guest); } - _accountMgr.checkAccess(callerAccount, null, true, network); + _accountMgr.checkAccess(callerAccount, null, network); if (name != null) { network.setName(name); @@ -2265,9 +2278,9 @@ public void doInTransactionWithoutResult(TransactionStatus status) { long isDefault = (nic.isDefaultNic()) ? 1 : 0; String nicIdString = Long.toString(nic.getId()); UsageEventUtils.publishUsageEvent(EventTypes.EVENT_NETWORK_OFFERING_REMOVE, vm.getAccountId(), vm.getDataCenterId(), vm.getId(), nicIdString, - oldNetworkOfferingId, null, isDefault, VirtualMachine.class.getName(), vm.getUuid()); + oldNetworkOfferingId, null, isDefault, VirtualMachine.class.getName(), vm.getUuid(), vm.isDisplay()); UsageEventUtils.publishUsageEvent(EventTypes.EVENT_NETWORK_OFFERING_ASSIGN, vm.getAccountId(), vm.getDataCenterId(), vm.getId(), nicIdString, - networkOfferingId, null, isDefault, VirtualMachine.class.getName(), vm.getUuid()); + networkOfferingId, null, isDefault, VirtualMachine.class.getName(), vm.getUuid(), vm.isDisplay()); } } }); @@ -3819,12 +3832,12 @@ private PhysicalNetworkServiceProvider addDefaultBaremetalProvidersToPhysicalNet PhysicalNetworkVO pvo = _physicalNetworkDao.findById(physicalNetworkId); DataCenterVO dvo = _dcDao.findById(pvo.getDataCenterId()); if (dvo.getNetworkType() == NetworkType.Basic) { - - Provider provider = Network.Provider.getProvider("BaremetalDhcpProvider"); - if (provider == null) { + + Provider provider = Network.Provider.getProvider("BaremetalDhcpProvider"); + if (provider == null) { // baremetal is not loaded return null; - } + } addProviderToPhysicalNetwork(physicalNetworkId, "BaremetalDhcpProvider", null, null); addProviderToPhysicalNetwork(physicalNetworkId, "BaremetalPxeProvider", null, null); @@ -3955,12 +3968,16 @@ public Network doInTransaction(TransactionStatus status) throws ResourceAllocati DataCenterVO dc = _dcDao.lockRow(pNtwk.getDataCenterId(), true); //check if we need to create guest network - Network privateNetwork = _networksDao.getPrivateNetwork(uriString, cidr, networkOwnerId, pNtwk.getDataCenterId(), networkOfferingId); + Network privateNetwork = _networksDao.getPrivateNetwork(uriString, cidr, networkOwnerId, pNtwk.getDataCenterId(), networkOfferingId); if (privateNetwork == null) { //create Guest network - privateNetwork = _networkMgr.createGuestNetwork(ntwkOffFinal.getId(), networkName, displayText, gateway, cidr, uriString, null, owner, null, pNtwk, + privateNetwork = _networkMgr.createGuestNetwork(ntwkOffFinal.getId(), networkName, displayText, gateway, cidr, uriString, null, owner, null, pNtwk, pNtwk.getDataCenterId(), ACLType.Account, null, vpcId, null, null, true, null); - s_logger.debug("Created private network " + privateNetwork); + if (privateNetwork != null) { + s_logger.debug("Successfully created guest network " + privateNetwork); + } else { + throw new CloudRuntimeException("Creating guest network failed"); + } } else { s_logger.debug("Private network already exists: " + privateNetwork); //Do not allow multiple private gateways with same Vlan within a VPC @@ -4028,7 +4045,7 @@ public List listNics(ListNicsCmd cmd) { throw ex; } - _accountMgr.checkAccess(caller, null, true, userVm); + _accountMgr.checkAccess(caller, null, userVm); return _networkMgr.listVmNics(vmId, nicId, networkId); } @@ -4052,7 +4069,7 @@ public IpAddress updateIP(Long id, String customId, Boolean displayIp) { // verify permissions if (ipVO.getAllocatedToAccountId() != null) { - _accountMgr.checkAccess(caller, null, true, ipVO); + _accountMgr.checkAccess(caller, null, ipVO); } else if (caller.getType() != Account.ACCOUNT_TYPE_ADMIN) { throw new PermissionDeniedException("Only Root admin can update non-allocated ip addresses"); } diff --git a/server/src/com/cloud/network/as/AutoScaleManagerImpl.java b/server/src/com/cloud/network/as/AutoScaleManagerImpl.java index 99189fe43a..09c6694701 100644 --- a/server/src/com/cloud/network/as/AutoScaleManagerImpl.java +++ b/server/src/com/cloud/network/as/AutoScaleManagerImpl.java @@ -240,7 +240,7 @@ private VO getEntityInDatabase(Account caller, Str throw new InvalidParameterValueException("Unable to find " + paramName); } - _accountMgr.checkAccess(caller, null, false, (ControlledEntity)vo); + _accountMgr.checkAccess(caller, null, (ControlledEntity)vo); return vo; } @@ -342,7 +342,7 @@ public AutoScaleVmProfile createAutoScaleVmProfile(CreateAutoScaleVmProfileCmd c Account owner = _accountDao.findById(cmd.getAccountId()); Account caller = CallContext.current().getCallingAccount(); - _accountMgr.checkAccess(caller, null, true, owner); + _accountMgr.checkAccess(caller, null, owner); long zoneId = cmd.getZoneId(); long serviceOfferingId = cmd.getServiceOfferingId(); @@ -527,7 +527,7 @@ public AutoScalePolicyVO doInTransaction(TransactionStatus status) { ControlledEntity[] sameOwnerEntities = conditions.toArray(new ControlledEntity[conditions.size() + 1]); sameOwnerEntities[sameOwnerEntities.length - 1] = autoScalePolicyVO; - _accountMgr.checkAccess(CallContext.current().getCallingAccount(), null, true, sameOwnerEntities); + _accountMgr.checkAccess(CallContext.current().getCallingAccount(), null, sameOwnerEntities); if (conditionIds.size() != conditions.size()) { // TODO report the condition id which could not be found @@ -621,7 +621,7 @@ public void checkCallerAccess(String accountName, Long domainId) { idList.add(ApiDBUtils.findDomainById(domainId).getUuid()); throw new InvalidParameterValueException("Unable to find account " + accountName + " in domain with specifed domainId"); } - _accountMgr.checkAccess(caller, null, false, owner); + _accountMgr.checkAccess(caller, null, owner); } private class SearchWrapper { @@ -980,7 +980,7 @@ protected AutoScaleVmGroupVO checkValidityAndPersist(final AutoScaleVmGroupVO vm ControlledEntity[] sameOwnerEntities = policies.toArray(new ControlledEntity[policies.size() + 2]); sameOwnerEntities[sameOwnerEntities.length - 2] = loadBalancer; sameOwnerEntities[sameOwnerEntities.length - 1] = profileVO; - _accountMgr.checkAccess(CallContext.current().getCallingAccount(), null, true, sameOwnerEntities); + _accountMgr.checkAccess(CallContext.current().getCallingAccount(), null, sameOwnerEntities); return Transaction.execute(new TransactionCallback() { @Override @@ -1414,7 +1414,7 @@ private boolean assignLBruleToNewVm(long vmId, AutoScaleVmGroupVO asGroup) { } } lstVmId.add(new Long(vmId)); - return _loadBalancingRulesService.assignToLoadBalancer(lbId, lstVmId); + return _loadBalancingRulesService.assignToLoadBalancer(lbId, lstVmId, new HashMap>()); } @@ -1431,7 +1431,7 @@ private long removeLBrule(AutoScaleVmGroupVO asGroup) { List lstVmId = new ArrayList(); if (instanceId != -1) lstVmId.add(instanceId); - if (_loadBalancingRulesService.removeFromLoadBalancer(lbId, lstVmId)) + if (_loadBalancingRulesService.removeFromLoadBalancer(lbId, lstVmId, new HashMap>())) return instanceId; else return -1; diff --git a/server/src/com/cloud/network/element/VirtualRouterElement.java b/server/src/com/cloud/network/element/VirtualRouterElement.java index 3f4ba5b5d3..3b3cacd094 100755 --- a/server/src/com/cloud/network/element/VirtualRouterElement.java +++ b/server/src/com/cloud/network/element/VirtualRouterElement.java @@ -188,10 +188,16 @@ public boolean implement(Network network, NetworkOffering offering, DeployDestin Map params = new HashMap(1); params.put(VirtualMachineProfile.Param.ReProgramGuestNetworks, true); - List routers = - _routerMgr.deployVirtualRouterInGuestNetwork(network, dest, _accountMgr.getAccount(network.getAccountId()), params, offering.getRedundantRouter()); - if ((routers == null) || (routers.size() == 0)) { - throw new ResourceUnavailableException("Can't find at least one running router!", DataCenter.class, network.getDataCenterId()); + List routers = _routerMgr.deployVirtualRouterInGuestNetwork(network, dest, + _accountMgr.getAccount(network.getAccountId()), params, + offering.getRedundantRouter()); + int routerCounts = 1; + if (offering.getRedundantRouter()) { + routerCounts = 2; + } + if ((routers == null) || (routers.size() < routerCounts)) { + throw new ResourceUnavailableException("Can't find all necessary running routers!", + DataCenter.class, network.getDataCenterId()); } return true; diff --git a/server/src/com/cloud/network/firewall/FirewallManagerImpl.java b/server/src/com/cloud/network/firewall/FirewallManagerImpl.java index c312d3d1ba..730606816b 100644 --- a/server/src/com/cloud/network/firewall/FirewallManagerImpl.java +++ b/server/src/com/cloud/network/firewall/FirewallManagerImpl.java @@ -27,12 +27,13 @@ import javax.inject.Inject; import javax.naming.ConfigurationException; +import org.apache.log4j.Logger; +import org.springframework.stereotype.Component; + import org.apache.cloudstack.api.command.user.firewall.ListFirewallRulesCmd; import org.apache.cloudstack.context.CallContext; import org.apache.cloudstack.engine.orchestration.service.NetworkOrchestrationService; import org.apache.cloudstack.framework.config.dao.ConfigurationDao; -import org.apache.log4j.Logger; -import org.springframework.stereotype.Component; import com.cloud.configuration.Config; import com.cloud.domain.dao.DomainDao; @@ -271,7 +272,7 @@ public Pair, Integer> listFirewallRules(ListFirewal if (ipAddressVO == null || !ipAddressVO.readyToUse()) { throw new InvalidParameterValueException("Ip address id=" + ipId + " not ready for firewall rules yet"); } - _accountMgr.checkAccess(caller, null, true, ipAddressVO); + _accountMgr.checkAccess(caller, null, ipAddressVO); } Ternary domainIdRecursiveListProject = new Ternary(cmd.getDomainId(), cmd.isRecursive(), null); @@ -463,7 +464,7 @@ public void validateFirewallRule(Account caller, IPAddressVO ipAddress, Integer } // Validate ip address - _accountMgr.checkAccess(caller, null, true, ipAddress); + _accountMgr.checkAccess(caller, null, ipAddress); } //network id either has to be passed explicitly, or implicitly as a part of ipAddress object @@ -475,7 +476,7 @@ public void validateFirewallRule(Account caller, IPAddressVO ipAddress, Integer assert network != null : "Can't create rule as network associated with public ip address is null?"; if (trafficType == FirewallRule.TrafficType.Egress) { - _accountMgr.checkAccess(caller, null, true, network); + _accountMgr.checkAccess(caller, null, network); } // Verify that the network guru supports the protocol specified @@ -638,7 +639,7 @@ public boolean applyFirewallRules(List rules, boolean continueOn } if (caller != null) { - _accountMgr.checkAccess(caller, null, true, rules.toArray(new FirewallRuleVO[rules.size()])); + _accountMgr.checkAccess(caller, null, rules.toArray(new FirewallRuleVO[rules.size()])); } try { @@ -692,7 +693,7 @@ protected boolean revokeFirewallRule(long ruleId, boolean apply, Account caller, throw new InvalidParameterValueException("Only root admin can delete the system wide firewall rule"); } - _accountMgr.checkAccess(caller, null, true, rule); + _accountMgr.checkAccess(caller, null, rule); revokeRule(rule, caller, userId, false); @@ -742,7 +743,7 @@ protected FirewallRule updateFirewallRule(long ruleId, String customId, Account throw new InvalidParameterValueException("Only root admin can update the system wide firewall rule"); } - _accountMgr.checkAccess(caller, null, true, rule); + _accountMgr.checkAccess(caller, null, rule); if (customId != null) { rule.setUuid(customId); @@ -761,7 +762,7 @@ protected FirewallRule updateFirewallRule(long ruleId, String customId, Account @DB public void revokeRule(final FirewallRuleVO rule, Account caller, long userId, final boolean needUsageEvent) { if (caller != null) { - _accountMgr.checkAccess(caller, null, true, rule); + _accountMgr.checkAccess(caller, null, rule); } Transaction.execute(new TransactionCallbackNoReturn() { diff --git a/server/src/com/cloud/network/guru/ExternalGuestNetworkGuru.java b/server/src/com/cloud/network/guru/ExternalGuestNetworkGuru.java index 13246a74a5..ddf1f9c3d8 100644 --- a/server/src/com/cloud/network/guru/ExternalGuestNetworkGuru.java +++ b/server/src/com/cloud/network/guru/ExternalGuestNetworkGuru.java @@ -127,6 +127,10 @@ public Network implement(Network config, NetworkOffering offering, DeployDestina throws InsufficientVirtualNetworkCapcityException { assert (config.getState() == State.Implementing) : "Why are we implementing " + config; + if (_networkModel.areServicesSupportedInNetwork(config.getId(), Network.Service.Connectivity)) { + return null; + } + if (!_networkModel.networkIsConfiguredForExternalNetworking(config.getDataCenterId(), config.getId())) { return super.implement(config, offering, dest, context); } diff --git a/server/src/com/cloud/network/lb/LoadBalancingRulesManagerImpl.java b/server/src/com/cloud/network/lb/LoadBalancingRulesManagerImpl.java index 9f280ef7a8..05fb32597e 100755 --- a/server/src/com/cloud/network/lb/LoadBalancingRulesManagerImpl.java +++ b/server/src/com/cloud/network/lb/LoadBalancingRulesManagerImpl.java @@ -163,6 +163,7 @@ import com.cloud.vm.UserVmVO; import com.cloud.vm.VirtualMachine.State; import com.cloud.vm.dao.NicDao; +import com.cloud.vm.dao.NicSecondaryIpDao; import com.cloud.vm.dao.UserVmDao; import com.google.gson.Gson; import com.google.gson.reflect.TypeToken; @@ -258,6 +259,9 @@ public class LoadBalancingRulesManagerImpl extends ManagerBase implements @Inject LoadBalancerCertMapDao _lbCertMapDao; + @Inject + NicSecondaryIpDao _nicSecondaryIpDao; + // Will return a string. For LB Stickiness this will be a json, for // autoscale this will be "," separated values @Override @@ -523,7 +527,7 @@ public StickinessPolicy createLBStickinessPolicy(CreateLBStickinessPolicyCmd cmd throw new InvalidParameterValueException("Failed: LB rule id: " + cmd.getLbRuleId() + " not present "); } - _accountMgr.checkAccess(caller.getCallingAccount(), null, true, loadBalancer); + _accountMgr.checkAccess(caller.getCallingAccount(), null, loadBalancer); if (loadBalancer.getState() == FirewallRule.State.Revoke) { throw new InvalidParameterValueException("Failed: LB rule id: " + cmd.getLbRuleId() + " is in deleting state: "); } @@ -551,6 +555,10 @@ public StickinessPolicy createLBStickinessPolicy(CreateLBStickinessPolicyCmd cmd /* Finally Insert into DB */ LBStickinessPolicyVO policy = new LBStickinessPolicyVO(loadBalancer.getId(), cmd.getLBStickinessPolicyName(), cmd.getStickinessMethodName(), cmd.getparamList(), cmd.getDescription()); + Boolean forDisplay = cmd.getDisplay(); + if (forDisplay != null) { + policy.setDisplay(forDisplay); + } policy = _lb2stickinesspoliciesDao.persist(policy); return policy; @@ -578,7 +586,7 @@ public HealthCheckPolicy createLBHealthCheckPolicy(CreateLBHealthCheckPolicyCmd throw new InvalidParameterValueException("Failed: LB rule id: " + cmd.getLbRuleId() + " not present "); } - _accountMgr.checkAccess(caller.getCallingAccount(), null, true, loadBalancer); + _accountMgr.checkAccess(caller.getCallingAccount(), null, loadBalancer); if (loadBalancer.getState() == FirewallRule.State.Revoke) { throw new InvalidParameterValueException("Failed: LB rule id: " + cmd.getLbRuleId() + " is in deleting state: "); @@ -615,6 +623,11 @@ public HealthCheckPolicy createLBHealthCheckPolicy(CreateLBHealthCheckPolicyCmd new LBHealthCheckPolicyVO(loadBalancer.getId(), cmd.getPingPath(), cmd.getDescription(), cmd.getResponsTimeOut(), cmd.getHealthCheckInterval(), cmd.getHealthyThreshold(), cmd.getUnhealthyThreshold()); + Boolean forDisplay = cmd.getDisplay(); + if (forDisplay != null) { + policy.setDisplay(forDisplay); + } + policy = _lb2healthcheckDao.persist(policy); return policy; } @@ -735,7 +748,7 @@ public boolean deleteLBStickinessPolicy(long stickinessPolicyId, boolean apply) } long loadBalancerId = loadBalancer.getId(); FirewallRule.State backupState = loadBalancer.getState(); - _accountMgr.checkAccess(caller.getCallingAccount(), null, true, loadBalancer); + _accountMgr.checkAccess(caller.getCallingAccount(), null, loadBalancer); if (apply) { if (loadBalancer.getState() == FirewallRule.State.Active) { @@ -788,7 +801,7 @@ public boolean deleteLBHealthCheckPolicy(long healthCheckPolicyId, boolean apply } final long loadBalancerId = loadBalancer.getId(); FirewallRule.State backupState = loadBalancer.getState(); - _accountMgr.checkAccess(caller.getCallingAccount(), null, true, loadBalancer); + _accountMgr.checkAccess(caller.getCallingAccount(), null, loadBalancer); if (apply) { if (loadBalancer.getState() == FirewallRule.State.Active) { @@ -882,7 +895,8 @@ public void updateLBHealthChecks(Scheme scheme) throws ResourceUnavailableExcept for (LoadBalancerVMMapVO lbVmMap : lbVmMaps) { UserVm vm = _vmDao.findById(lbVmMap.getInstanceId()); Nic nic = _nicDao.findByInstanceIdAndNetworkIdIncludingRemoved(ulb.getNetworkId(), vm.getId()); - String dstIp = nic.getIp4Address(); + String dstIp = lbVmMap.getInstanceIp() == null ? nic.getIp4Address(): lbVmMap.getInstanceIp(); + for (int i = 0; i < lbto.getDestinations().length; i++) { LoadBalancerTO.DestinationTO des = lbto.getDestinations()[i]; if (dstIp.equalsIgnoreCase(lbto.getDestinations()[i].getDestIp())) { @@ -923,7 +937,7 @@ private boolean isRollBackAllowedForProvider(LoadBalancerVO loadBalancer) { @Override @DB @ActionEvent(eventType = EventTypes.EVENT_ASSIGN_TO_LOAD_BALANCER_RULE, eventDescription = "assigning to load balancer", async = true) - public boolean assignToLoadBalancer(long loadBalancerId, List instanceIds) { + public boolean assignToLoadBalancer(long loadBalancerId, List instanceIds, Map> vmIdIpMap) { CallContext ctx = CallContext.current(); Account caller = ctx.getCallingAccount(); @@ -932,24 +946,53 @@ public boolean assignToLoadBalancer(long loadBalancerId, List instanceIds) throw new InvalidParameterValueException("Failed to assign to load balancer " + loadBalancerId + ", the load balancer was not found."); } + + if (instanceIds == null && vmIdIpMap.isEmpty()) { + throw new InvalidParameterValueException("Both instanceids and vmidipmap can't be null"); + } + + // instanceIds and vmIdipmap is passed + if (instanceIds != null && !vmIdIpMap.isEmpty()) { + for(long instanceId: instanceIds) { + if (!vmIdIpMap.containsKey(instanceId)) { + vmIdIpMap.put(instanceId, null); + } + } + } + + //only instanceids list passed + if (instanceIds != null && vmIdIpMap.isEmpty()){ + vmIdIpMap = new HashMap>(); + for (long instanceId: instanceIds){ + vmIdIpMap.put(instanceId, null); + } + } + List mappedInstances = _lb2VmMapDao.listByLoadBalancerId(loadBalancerId, false); Set mappedInstanceIds = new HashSet(); for (LoadBalancerVMMapVO mappedInstance : mappedInstances) { mappedInstanceIds.add(Long.valueOf(mappedInstance.getInstanceId())); } - final List vmsToAdd = new ArrayList(); + Map> existingVmIdIps = new HashMap>(); + // now get the ips of vm and add it to map + for (LoadBalancerVMMapVO mappedInstance : mappedInstances) { - if (instanceIds == null || instanceIds.isEmpty()) { - s_logger.warn("List of vms to assign to the lb, is empty"); - return false; + List ipsList = null; + if (existingVmIdIps.containsKey(mappedInstance.getInstanceId())) { + ipsList = existingVmIdIps.get(mappedInstance.getInstanceId()); + } else { + ipsList = new ArrayList(); + } + ipsList.add(mappedInstance.getInstanceIp()); + existingVmIdIps.put(mappedInstance.getInstanceId(), ipsList); } - for (Long instanceId : instanceIds) { - if (mappedInstanceIds.contains(instanceId)) { - throw new InvalidParameterValueException("VM " + instanceId + " is already mapped to load balancer."); - } + final List vmsToAdd = new ArrayList(); + // check for conflict + Set passedInstanceIds = vmIdIpMap.keySet(); + for (Long instanceId : passedInstanceIds) { UserVm vm = _vmDao.findById(instanceId); if (vm == null || vm.getState() == State.Destroyed || vm.getState() == State.Expunging) { InvalidParameterValueException ex = new InvalidParameterValueException("Invalid instance id specified"); @@ -985,18 +1028,75 @@ public boolean assignToLoadBalancer(long loadBalancerId, List instanceIds) throw ex; } + String priIp = nicInSameNetwork.getIp4Address(); + + if (existingVmIdIps.containsKey(instanceId)) { + // now check for ip address + List mappedIps = existingVmIdIps.get(instanceId); + List newIps = vmIdIpMap.get(instanceId); + + if (newIps == null) { + newIps = new ArrayList(); + newIps.add(priIp); + } + + for (String newIp: newIps) { + if (mappedIps.contains(newIp)) { + throw new InvalidParameterValueException("VM " + instanceId + " with " + newIp +" is already mapped to load balancer."); + } + } + } + + List vmIpsList = vmIdIpMap.get(instanceId); + String vmLbIp = null; + + if (vmIpsList != null) { + + //check if the ips belongs to nic secondary ip + for (String ip: vmIpsList) { + // skip the primary ip from vm secondary ip comparisions + if (ip.equals(priIp)) { + continue; + } + if(_nicSecondaryIpDao.findByIp4AddressAndNicId(ip,nicInSameNetwork.getId()) == null) { + throw new InvalidParameterValueException("VM ip "+ ip + " specified does not belong to " + + "nic in network " + nicInSameNetwork.getNetworkId()); + } + } + } else { + vmIpsList = new ArrayList(); + vmIpsList.add(priIp); + } + + // when vm id is passed in instance ids and in vmidipmap + // assign for primary ip and ip passed in vmidipmap + if (instanceIds != null ) { + if (instanceIds.contains(instanceId)) { + vmIpsList.add(priIp); + } + } + + vmIdIpMap.put(instanceId, vmIpsList); + if (s_logger.isDebugEnabled()) { s_logger.debug("Adding " + vm + " to the load balancer pool"); } vmsToAdd.add(vm); } + final Set vmIds = vmIdIpMap.keySet(); + final Map> newMap = vmIdIpMap; + Transaction.execute(new TransactionCallbackNoReturn() { @Override public void doInTransactionWithoutResult(TransactionStatus status) { - for (UserVm vm : vmsToAdd) { - LoadBalancerVMMapVO map = new LoadBalancerVMMapVO(loadBalancer.getId(), vm.getId(), false); - map = _lb2VmMapDao.persist(map); + + for (Long vmId : vmIds) { + final Set lbVmIps = new HashSet(newMap.get(vmId)); + for (String vmIp: lbVmIps) { + LoadBalancerVMMapVO map = new LoadBalancerVMMapVO(loadBalancer.getId(), vmId, vmIp, false); + map = _lb2VmMapDao.persist(map); + } } } }); @@ -1015,13 +1115,16 @@ public void doInTransactionWithoutResult(TransactionStatus status) { applyLoadBalancerConfig(loadBalancerId); success = true; } catch (ResourceUnavailableException e) { - if (isRollBackAllowedForProvider(loadBalancer)) { + s_logger.warn("Unable to apply the load balancer config because resource is unavaliable.", e); + success = false; + } finally { + if (!success) { final List vmInstanceIds = new ArrayList(); Transaction.execute(new TransactionCallbackNoReturn() { @Override public void doInTransactionWithoutResult(TransactionStatus status) { - for (UserVm vm : vmsToAdd) { - vmInstanceIds.add(vm.getId()); + for (Long vmId : vmIds) { + vmInstanceIds.add(vmId); } } }); @@ -1031,16 +1134,14 @@ public void doInTransactionWithoutResult(TransactionStatus status) { } loadBalancer.setState(backupState); _lbDao.persist(loadBalancer); + CloudRuntimeException ex = new CloudRuntimeException("Failed to add specified loadbalancerruleid for vms " + + instanceIds); + ex.addProxyObject(loadBalancer.getUuid(), "loadBalancerId"); + // TBD: Also pack in the instanceIds in the exception using the + // right VO object or table name. + throw ex; } - s_logger.warn("Unable to apply the load balancer config because resource is unavaliable.", e); - } - if (!success) { - CloudRuntimeException ex = new CloudRuntimeException("Failed to add specified loadbalancerruleid for vms " + instanceIds); - ex.addProxyObject(loadBalancer.getUuid(), "loadBalancerId"); - // TBD: Also pack in the instanceIds in the exception using the - // right VO object or table name. - throw ex; } return success; @@ -1056,8 +1157,8 @@ public boolean assignSSLCertToLoadBalancerRule(Long lbId, String certName, Strin @Override @ActionEvent(eventType = EventTypes.EVENT_REMOVE_FROM_LOAD_BALANCER_RULE, eventDescription = "removing from load balancer", async = true) - public boolean removeFromLoadBalancer(long loadBalancerId, List instanceIds) { - return removeFromLoadBalancerInternal(loadBalancerId, instanceIds, true); + public boolean removeFromLoadBalancer(long loadBalancerId, List instanceIds, Map> vmIdIpsMap) { + return removeFromLoadBalancerInternal(loadBalancerId, instanceIds, true, vmIdIpsMap); } @Override @@ -1092,7 +1193,7 @@ public boolean assignCertToLoadBalancer(long lbRuleId, Long certId) { throw new InvalidParameterException("Invalid certificate id: " + certId); } - _accountMgr.checkAccess(caller.getCallingAccount(), null, true, loadBalancer); + _accountMgr.checkAccess(caller.getCallingAccount(), null, loadBalancer); // check if LB and Cert belong to the same account if (loadBalancer.getAccountId() != certVO.getAccountId()) { @@ -1155,7 +1256,7 @@ public boolean removeCertFromLoadBalancer(long lbRuleId) { throw new InvalidParameterException("No certificate is bound to lb with id: " + lbRuleId); } - _accountMgr.checkAccess(caller.getCallingAccount(), null, true, loadBalancer); + _accountMgr.checkAccess(caller.getCallingAccount(), null, loadBalancer); boolean success = false; FirewallRule.State backupState = loadBalancer.getState(); @@ -1191,7 +1292,7 @@ public boolean removeCertFromLoadBalancer(long lbRuleId) { return success; } - private boolean removeFromLoadBalancerInternal(long loadBalancerId, List instanceIds, boolean rollBack) { + private boolean removeFromLoadBalancerInternal(long loadBalancerId, List instanceIds, boolean rollBack, Map> vmIdIpMap) { CallContext caller = CallContext.current(); LoadBalancerVO loadBalancer = _lbDao.findById(Long.valueOf(loadBalancerId)); @@ -1199,19 +1300,67 @@ private boolean removeFromLoadBalancerInternal(long loadBalancerId, List i throw new InvalidParameterException("Invalid load balancer value: " + loadBalancerId); } - _accountMgr.checkAccess(caller.getCallingAccount(), null, true, loadBalancer); + _accountMgr.checkAccess(caller.getCallingAccount(), null, loadBalancer); + + if (instanceIds == null && vmIdIpMap.isEmpty()) { + throw new InvalidParameterValueException("Both instanceids and vmidipmap can't be null"); + } + + // instanceIds and vmIdipmap is passed + if (instanceIds != null && !vmIdIpMap.isEmpty()) { + for(long instanceId: instanceIds) { + if (!vmIdIpMap.containsKey(instanceId)) { + vmIdIpMap.put(instanceId, null); + } + } + } + + //only instanceids list passed + if (instanceIds != null && vmIdIpMap.isEmpty()){ + vmIdIpMap = new HashMap>(); + for (long instanceId: instanceIds){ + vmIdIpMap.put(instanceId, null); + } + } boolean success = false; FirewallRule.State backupState = loadBalancer.getState(); + Set vmIds = vmIdIpMap.keySet(); try { loadBalancer.setState(FirewallRule.State.Add); _lbDao.persist(loadBalancer); - for (long instanceId : instanceIds) { - LoadBalancerVMMapVO map = _lb2VmMapDao.findByLoadBalancerIdAndVmId(loadBalancerId, instanceId); - map.setRevoke(true); - _lb2VmMapDao.persist(map); - s_logger.debug("Set load balancer rule for revoke: rule id " + loadBalancerId + ", vmId " + instanceId); + for (long instanceId : vmIds) { + List lbVmIps = vmIdIpMap.get(instanceId); + + if (lbVmIps == null || lbVmIps.isEmpty()) { + List lbVms = _lb2VmMapDao.listByLoadBalancerIdAndVmId(loadBalancerId, instanceId); + if (lbVms == null) { + throw new InvalidParameterValueException("The instance id: "+ instanceId +" is not configured " + + " for LB rule id " + loadBalancerId); + } + + for (LoadBalancerVMMapVO lbvm: lbVms) { + lbvm.setRevoke(true); + _lb2VmMapDao.persist(lbvm); + } + s_logger.debug("Set load balancer rule for revoke: rule id " + loadBalancerId + ", vmId " + instanceId); + + } else { + for (String vmIp: lbVmIps) { + LoadBalancerVMMapVO map = _lb2VmMapDao.findByLoadBalancerIdAndVmIdVmIp (loadBalancerId, instanceId, vmIp); + if (map == null) { + throw new InvalidParameterValueException("The instance id: "+ instanceId +" is not configured " + + " for LB rule id " + loadBalancerId); + } + map.setRevoke(true); + _lb2VmMapDao.persist(map); + s_logger.debug("Set load balancer rule for revoke: rule id " + loadBalancerId + ", vmId " + + instanceId + ", vmip " + vmIp); + + } + + } } if (_autoScaleVmGroupDao.isAutoScaleLoadBalancer(loadBalancerId)) { @@ -1233,11 +1382,23 @@ private boolean removeFromLoadBalancerInternal(long loadBalancerId, List i } catch (ResourceUnavailableException e) { if (rollBack && isRollBackAllowedForProvider(loadBalancer)) { - for (long instanceId : instanceIds) { - LoadBalancerVMMapVO map = _lb2VmMapDao.findByLoadBalancerIdAndVmId(loadBalancerId, instanceId); - map.setRevoke(false); - _lb2VmMapDao.persist(map); - s_logger.debug("LB Rollback rule id: " + loadBalancerId + ",while removing vmId " + instanceId); + for (long instanceId : vmIds) { + List lbVmIps = vmIdIpMap.get(instanceId); + + if (lbVmIps == null || lbVmIps.isEmpty()) { + LoadBalancerVMMapVO map = _lb2VmMapDao.findByLoadBalancerIdAndVmId(loadBalancerId, instanceId); + map.setRevoke(false); + _lb2VmMapDao.persist(map); + s_logger.debug("LB Rollback rule id: " + loadBalancerId + ",while removing vmId " + instanceId); + }else { + for (String vmIp: lbVmIps) { + LoadBalancerVMMapVO map = _lb2VmMapDao.findByLoadBalancerIdAndVmIdVmIp (loadBalancerId, instanceId, vmIp); + map.setRevoke(true); + _lb2VmMapDao.persist(map); + s_logger.debug("LB Rollback rule id: " + loadBalancerId + ",while removing vmId " + + instanceId + ", vmip " + vmIp); + } + } } loadBalancer.setState(backupState); @@ -1247,7 +1408,7 @@ private boolean removeFromLoadBalancerInternal(long loadBalancerId, List i s_logger.warn("Unable to apply the load balancer config because resource is unavaliable.", e); } if (!success) { - CloudRuntimeException ex = new CloudRuntimeException("Failed to remove specified load balancer rule id for vms " + instanceIds); + CloudRuntimeException ex = new CloudRuntimeException("Failed to remove specified load balancer rule id for vms " + vmIds); ex.addProxyObject(loadBalancer.getUuid(), "loadBalancerId"); throw ex; } @@ -1282,7 +1443,7 @@ public boolean removeVmFromLoadBalancers(long instanceId) { // Reapply all lbs that had the vm assigned if (lbsToReconfigure != null) { for (Map.Entry> lb : lbsToReconfigure.entrySet()) { - if (!removeFromLoadBalancerInternal(lb.getKey(), lb.getValue(), false)) { + if (!removeFromLoadBalancerInternal(lb.getKey(), lb.getValue(), false, new HashMap>())) { success = false; } } @@ -1301,7 +1462,7 @@ public boolean deleteLoadBalancerRule(long loadBalancerId, boolean apply) { if (rule == null) { throw new InvalidParameterValueException("Unable to find load balancer rule " + loadBalancerId); } - _accountMgr.checkAccess(caller, null, true, rule); + _accountMgr.checkAccess(caller, null, rule); boolean result = deleteLoadBalancerRule(loadBalancerId, apply, caller, ctx.getCallingUserId(), true); if (!result) { @@ -1340,7 +1501,7 @@ public List doInTransaction(TransactionStatus status) { } } - List hcPolicies = _lb2healthcheckDao.listByLoadBalancerId(loadBalancerId); + List hcPolicies = _lb2healthcheckDao.listByLoadBalancerIdAndDisplayFlag(loadBalancerId, null); for (LBHealthCheckPolicyVO lbHealthCheck : hcPolicies) { lbHealthCheck.setRevoke(true); _lb2healthcheckDao.persist(lbHealthCheck); @@ -1525,7 +1686,7 @@ public LoadBalancer createPublicLoadBalancer(final String xId, final String name throw ex; } - _accountMgr.checkAccess(caller.getCallingAccount(), null, true, ipAddr); + _accountMgr.checkAccess(caller.getCallingAccount(), null, ipAddr); final Long networkId = ipAddr.getAssociatedWithNetworkId(); if (networkId == null) { @@ -1727,12 +1888,11 @@ public Boolean doInTransaction(TransactionStatus status) { for (LoadBalancerVMMapVO lbVmMap : lbVmMaps) { instanceIds.add(lbVmMap.getInstanceId()); + _lb2VmMapDao.remove(lb.getId(), lbVmMap.getInstanceId(), lbVmMap.getInstanceIp(), null); + s_logger.debug("Load balancer rule id " + lb.getId() + " is removed for vm " + + lbVmMap.getInstanceId() + " instance ip " + lbVmMap.getInstanceIp()); } - if (!instanceIds.isEmpty()) { - _lb2VmMapDao.remove(lb.getId(), instanceIds, null); - s_logger.debug("Load balancer rule id " + lb.getId() + " is removed for vms " + instanceIds); - } if (_lb2VmMapDao.listByLoadBalancerId(lb.getId()).isEmpty()) { lb.setState(FirewallRule.State.Add); @@ -1853,7 +2013,7 @@ public List getStickinessPolicies(long lbId) { @Override public List getHealthCheckPolicies(long lbId) { List healthCheckPolicies = new ArrayList(); - List hcDbpolicies = _lb2healthcheckDao.listByLoadBalancerId(lbId); + List hcDbpolicies = _lb2healthcheckDao.listByLoadBalancerIdAndDisplayFlag(lbId, null); for (LBHealthCheckPolicyVO policy : hcDbpolicies) { String pingpath = policy.getpingpath(); @@ -1875,7 +2035,7 @@ public List getExistingDestinations(long lbId) { for (LoadBalancerVMMapVO lbVmMap : lbVmMaps) { UserVm vm = _vmDao.findById(lbVmMap.getInstanceId()); Nic nic = _nicDao.findByInstanceIdAndNetworkIdIncludingRemoved(lb.getNetworkId(), vm.getId()); - dstIp = nic.getIp4Address(); + dstIp = lbVmMap.getInstanceIp() == null ? nic.getIp4Address(): lbVmMap.getInstanceIp(); LbDestination lbDst = new LbDestination(lb.getDefaultPortStart(), lb.getDefaultPortEnd(), dstIp, lbVmMap.isRevoke()); dstList.add(lbDst); } @@ -1900,7 +2060,7 @@ public LoadBalancer updateLoadBalancerRule(UpdateLoadBalancerRuleCmd cmd) { } // check permissions - _accountMgr.checkAccess(caller, null, true, lb); + _accountMgr.checkAccess(caller, null, lb); if (name != null) { lb.setName(name); @@ -1979,7 +2139,7 @@ public Pair, List> listLoadBalancerInstances(List return null; } - _accountMgr.checkAccess(caller, null, true, loadBalancer); + _accountMgr.checkAccess(caller, null, loadBalancer); List loadBalancerInstances = new ArrayList(); List serviceStates = new ArrayList(); @@ -2022,6 +2182,18 @@ public Pair, List> listLoadBalancerInstances(List return new Pair, List>(loadBalancerInstances, serviceStates); } + @Override + public List listLbVmIpAddress (long id, long vmId) { + + List listLbvmMapVo = _lb2VmMapDao.listByLoadBalancerIdAndVmId(id, vmId); + + List vmIps = new ArrayList(); + for (LoadBalancerVMMapVO lbVmVo : listLbvmMapVo) { + vmIps.add(lbVmVo.getInstanceIp()); + } + return vmIps; + } + @Override public List getStickinessMethods(long networkid) { String capability = getLBCapability(networkid, Capability.SupportedStickinessMethods.getName()); @@ -2039,14 +2211,16 @@ public List getStickinessMethods(long networkid) { public List searchForLBStickinessPolicies(ListLBStickinessPoliciesCmd cmd) throws PermissionDeniedException { Account caller = CallContext.current().getCallingAccount(); Long loadBalancerId = cmd.getLbRuleId(); + boolean forDisplay = cmd.getDisplay(); + LoadBalancerVO loadBalancer = _lbDao.findById(loadBalancerId); if (loadBalancer == null) { return null; } - _accountMgr.checkAccess(caller, null, true, loadBalancer); + _accountMgr.checkAccess(caller, null, loadBalancer); - List sDbpolicies = _lb2stickinesspoliciesDao.listByLoadBalancerId(cmd.getLbRuleId()); + List sDbpolicies = _lb2stickinesspoliciesDao.listByLoadBalancerIdAndDisplayFlag(cmd.getLbRuleId(), forDisplay); return sDbpolicies; } @@ -2055,12 +2229,14 @@ public List searchForLBStickinessPolicies(ListLBStickiness public List searchForLBHealthCheckPolicies(ListLBHealthCheckPoliciesCmd cmd) throws PermissionDeniedException { Account caller = CallContext.current().getCallingAccount(); Long loadBalancerId = cmd.getLbRuleId(); + boolean forDisplay = cmd.getDisplay(); + LoadBalancerVO loadBalancer = _lbDao.findById(loadBalancerId); if (loadBalancer == null) { return null; } - _accountMgr.checkAccess(caller, null, true, loadBalancer); - List hcDbpolicies = _lb2healthcheckDao.listByLoadBalancerId(cmd.getLbRuleId()); + _accountMgr.checkAccess(caller, null, loadBalancer); + List hcDbpolicies = _lb2healthcheckDao.listByLoadBalancerIdAndDisplayFlag(cmd.getLbRuleId(), forDisplay); return hcDbpolicies; } @@ -2074,6 +2250,7 @@ public Pair, Integer> searchForLoadBalancers(ListLo Long instanceId = cmd.getVirtualMachineId(); Long networkId = cmd.getNetworkId(); Map tags = cmd.getTags(); + Boolean forDisplay = cmd.getDisplay(); Account caller = CallContext.current().getCallingAccount(); List permittedDomains = new ArrayList(); @@ -2097,6 +2274,7 @@ public Pair, Integer> searchForLoadBalancers(ListLo sb.and("sourceIpAddress", sb.entity().getSourceIpAddressId(), SearchCriteria.Op.EQ); sb.and("networkId", sb.entity().getNetworkId(), SearchCriteria.Op.EQ); sb.and("scheme", sb.entity().getScheme(), SearchCriteria.Op.EQ); + sb.and("display", sb.entity().isDisplay(), SearchCriteria.Op.EQ); if (instanceId != null) { SearchBuilder lbVMSearch = _lb2VmMapDao.createSearchBuilder(); @@ -2166,6 +2344,10 @@ public Pair, Integer> searchForLoadBalancers(ListLo } } + if (forDisplay != null) { + sc.setParameters("display", forDisplay); + } + //list only Public load balancers using this command sc.setParameters("scheme", Scheme.Public); @@ -2241,6 +2423,15 @@ public Map getLbInstances(long lbId) { return dstList; } + @Override + public boolean isLbRuleMappedToVmGuestIp(String vmSecondaryIp) { + List lbVmMap = _lb2VmMapDao.listByInstanceIp(vmSecondaryIp); + if (lbVmMap == null || lbVmMap.isEmpty()) { + return false; + } + return true; + } + @Override public void isLbServiceSupportedInNetwork(long networkId, Scheme scheme) { Network network = _networkDao.findById(networkId); @@ -2280,4 +2471,58 @@ public void setLbProviders(List lbProviders) { this._lbProviders = lbProviders; } + @Override + @ActionEvent(eventType = EventTypes.EVENT_LB_STICKINESSPOLICY_UPDATE, eventDescription = "updating lb stickiness policy", async = true) + public StickinessPolicy updateLBStickinessPolicy(long id, String customId, Boolean forDisplay) { + LBStickinessPolicyVO policy = _lb2stickinesspoliciesDao.findById(id); + if (policy == null) { + throw new InvalidParameterValueException("Fail to find stickiness policy with " + id); + } + + LoadBalancerVO loadBalancer = _lbDao.findById(Long.valueOf(policy.getLoadBalancerId())); + if (loadBalancer == null) { + throw new InvalidParameterException("Invalid Load balancer : " + policy.getLoadBalancerId() + " for Stickiness policy id: " + id); + } + + _accountMgr.checkAccess(CallContext.current().getCallingAccount(), null, loadBalancer); + + if (customId != null) { + policy.setUuid(customId); + } + + if (forDisplay != null) { + policy.setDisplay(forDisplay); + } + + _lb2stickinesspoliciesDao.update(id, policy); + return _lb2stickinesspoliciesDao.findById(id); + } + + @Override + @ActionEvent(eventType = EventTypes.EVENT_LB_HEALTHCHECKPOLICY_UPDATE, eventDescription = "updating lb healthcheck policy", async = true) + public HealthCheckPolicy updateLBHealthCheckPolicy(long id, String customId, Boolean forDisplay) { + LBHealthCheckPolicyVO policy = _lb2healthcheckDao.findById(id); + if (policy == null) { + throw new InvalidParameterValueException("Fail to find stickiness policy with " + id); + } + + LoadBalancerVO loadBalancer = _lbDao.findById(Long.valueOf(policy.getLoadBalancerId())); + if (loadBalancer == null) { + throw new InvalidParameterException("Invalid Load balancer : " + policy.getLoadBalancerId() + " for Stickiness policy id: " + id); + } + + _accountMgr.checkAccess(CallContext.current().getCallingAccount(), null, loadBalancer); + + if (customId != null) { + policy.setUuid(customId); + } + + if (forDisplay != null) { + policy.setDisplay(forDisplay); + } + + _lb2healthcheckDao.update(id, policy); + return _lb2healthcheckDao.findById(id); + } + } diff --git a/server/src/com/cloud/network/router/VirtualNetworkApplianceManager.java b/server/src/com/cloud/network/router/VirtualNetworkApplianceManager.java index e3597acc31..ae418d239c 100644 --- a/server/src/com/cloud/network/router/VirtualNetworkApplianceManager.java +++ b/server/src/com/cloud/network/router/VirtualNetworkApplianceManager.java @@ -51,6 +51,7 @@ public interface VirtualNetworkApplianceManager extends Manager, VirtualNetworkA static final String RouterTemplateHyperVCK = "router.template.hyperv"; static final String RouterTemplateLxcCK = "router.template.lxc"; static final String SetServiceMonitorCK = "network.router.EnableServiceMonitoring"; + static final String RouterAlertsCheckIntervalCK = "router.alerts.check.interval"; static final ConfigKey RouterTemplateXen = new ConfigKey(String.class, RouterTemplateXenCK, "Advanced", "SystemVM Template (XenServer)", "Name of the default router template on Xenserver.", true, ConfigKey.Scope.Zone, null); @@ -66,6 +67,9 @@ public interface VirtualNetworkApplianceManager extends Manager, VirtualNetworkA static final ConfigKey SetServiceMonitor = new ConfigKey(String.class, SetServiceMonitorCK, "Advanced", "true", "service monitoring in router enable/disable option, default true", true, ConfigKey.Scope.Zone, null); + static final ConfigKey RouterAlertsCheckInterval = new ConfigKey(Integer.class, RouterAlertsCheckIntervalCK, "Advanced", "1800", + "Interval (in seconds) to check for alerts in Virtual Router.", false, ConfigKey.Scope.Global, null); + public static final int DEFAULT_ROUTER_VM_RAMSIZE = 128; // 128M public static final int DEFAULT_ROUTER_CPU_MHZ = 500; // 500 MHz public static final boolean USE_POD_VLAN = false; diff --git a/server/src/com/cloud/network/router/VirtualNetworkApplianceManagerImpl.java b/server/src/com/cloud/network/router/VirtualNetworkApplianceManagerImpl.java index c692491a34..be3e849d43 100755 --- a/server/src/com/cloud/network/router/VirtualNetworkApplianceManagerImpl.java +++ b/server/src/com/cloud/network/router/VirtualNetworkApplianceManagerImpl.java @@ -17,6 +17,8 @@ package com.cloud.network.router; +import java.text.ParseException; +import java.text.SimpleDateFormat; import java.util.ArrayList; import java.util.Arrays; import java.util.Calendar; @@ -41,10 +43,15 @@ import javax.ejb.Local; import javax.inject.Inject; import javax.naming.ConfigurationException; + import org.apache.log4j.Logger; + +import org.apache.cloudstack.alert.AlertService; +import org.apache.cloudstack.alert.AlertService.AlertType; import org.apache.cloudstack.api.command.admin.router.RebootRouterCmd; import org.apache.cloudstack.api.command.admin.router.UpgradeRouterCmd; import org.apache.cloudstack.api.command.admin.router.UpgradeRouterTemplateCmd; +import org.apache.cloudstack.config.ApiServiceConfiguration; import org.apache.cloudstack.context.CallContext; import org.apache.cloudstack.engine.orchestration.service.NetworkOrchestrationService; import org.apache.cloudstack.framework.config.ConfigDepot; @@ -55,7 +62,7 @@ import org.apache.cloudstack.framework.jobs.impl.AsyncJobVO; import org.apache.cloudstack.managed.context.ManagedContextRunnable; import org.apache.cloudstack.utils.identity.ManagementServerNode; -import org.apache.cloudstack.alert.AlertService.AlertType; + import com.cloud.agent.AgentManager; import com.cloud.agent.Listener; import com.cloud.agent.api.AgentControlAnswer; @@ -69,14 +76,12 @@ import com.cloud.agent.api.Command; import com.cloud.agent.api.GetDomRVersionAnswer; import com.cloud.agent.api.GetDomRVersionCmd; +import com.cloud.agent.api.GetRouterAlertsAnswer; import com.cloud.agent.api.ModifySshKeysCommand; import com.cloud.agent.api.NetworkUsageAnswer; import com.cloud.agent.api.NetworkUsageCommand; import com.cloud.agent.api.PvlanSetupCommand; import com.cloud.agent.api.StartupCommand; -import com.cloud.agent.api.routing.GetRouterAlertsCommand; -import com.cloud.agent.api.GetRouterAlertsAnswer; -import com.cloud.agent.api.check.CheckSshAnswer; import com.cloud.agent.api.check.CheckSshCommand; import com.cloud.agent.api.routing.AggregationControlCommand; import com.cloud.agent.api.routing.AggregationControlCommand.Action; @@ -84,6 +89,7 @@ import com.cloud.agent.api.routing.DeleteIpAliasCommand; import com.cloud.agent.api.routing.DhcpEntryCommand; import com.cloud.agent.api.routing.DnsMasqConfigCommand; +import com.cloud.agent.api.routing.GetRouterAlertsCommand; import com.cloud.agent.api.routing.IpAliasTO; import com.cloud.agent.api.routing.IpAssocCommand; import com.cloud.agent.api.routing.LoadBalancerConfigCommand; @@ -183,6 +189,7 @@ import com.cloud.network.dao.NetworkDao; import com.cloud.network.dao.NetworkVO; import com.cloud.network.dao.OpRouterMonitorServiceDao; +import com.cloud.network.dao.OpRouterMonitorServiceVO; import com.cloud.network.dao.PhysicalNetworkServiceProviderDao; import com.cloud.network.dao.RemoteAccessVpnDao; import com.cloud.network.dao.Site2SiteCustomerGatewayDao; @@ -192,7 +199,6 @@ import com.cloud.network.dao.UserIpv6AddressDao; import com.cloud.network.dao.VirtualRouterProviderDao; import com.cloud.network.dao.VpnUserDao; -import com.cloud.network.dao.OpRouterMonitorServiceVO; import com.cloud.network.lb.LoadBalancingRule; import com.cloud.network.lb.LoadBalancingRule.LbDestination; import com.cloud.network.lb.LoadBalancingRule.LbHealthCheckPolicy; @@ -281,7 +287,6 @@ import com.cloud.vm.dao.UserVmDao; import com.cloud.vm.dao.UserVmDetailsDao; import com.cloud.vm.dao.VMInstanceDao; -import org.apache.cloudstack.config.ApiServiceConfiguration; /** * VirtualNetworkApplianceManagerImpl manages the different types of virtual network appliances available in the Cloud Stack. @@ -457,7 +462,7 @@ public VirtualRouter destroyRouter(final long routerId, final Account caller, fi return null; } - _accountMgr.checkAccess(caller, null, true, router); + _accountMgr.checkAccess(caller, null, router); _itMgr.expunge(router.getUuid()); _routerDao.remove(router.getId()); @@ -476,7 +481,7 @@ public VirtualRouter upgradeRouter(final UpgradeRouterCmd cmd) { throw new InvalidParameterValueException("Unable to find router with id " + routerId); } - _accountMgr.checkAccess(caller, null, true, router); + _accountMgr.checkAccess(caller, null, router); if (router.getServiceOfferingId() == serviceOfferingId) { s_logger.debug("Router: " + routerId + "already has service offering: " + serviceOfferingId); @@ -591,7 +596,7 @@ public VirtualRouter stopRouter(final long routerId, final boolean forced) throw throw new InvalidParameterValueException("Unable to find router by id " + routerId + "."); } - _accountMgr.checkAccess(account, null, true, router); + _accountMgr.checkAccess(account, null, router); final UserVO user = _userDao.findById(CallContext.current().getCallingUserId()); @@ -650,7 +655,7 @@ public VirtualRouter rebootRouter(final long routerId, final boolean reprogramNe throw new InvalidParameterValueException("Unable to find domain router with id " + routerId + "."); } - _accountMgr.checkAccess(caller, null, true, router); + _accountMgr.checkAccess(caller, null, router); // Can reboot domain router only in Running state if (router == null || router.getState() != State.Running) { @@ -821,6 +826,13 @@ public boolean start() { s_logger.debug("router.check.interval - " + _routerCheckInterval + " so not scheduling the redundant router checking thread"); } + int _routerAlertsCheckInterval = RouterAlertsCheckInterval.value(); + if (_routerAlertsCheckInterval > 0) { + _checkExecutor.scheduleAtFixedRate(new CheckRouterAlertsTask(), _routerAlertsCheckInterval, _routerAlertsCheckInterval, TimeUnit.SECONDS); + } else { + s_logger.debug("router.alerts.check.interval - " + _routerAlertsCheckInterval + " so not scheduling the router alerts checking thread"); + } + return true; } @@ -1355,8 +1367,6 @@ protected void runInContext() { updateSite2SiteVpnConnectionState(routers); - getRouterAlerts(); - final List networks = _networkDao.listRedundantNetworks(); s_logger.debug("Found " + networks.size() + " networks to update RvR status. "); for (final NetworkVO network : networks) { @@ -1371,20 +1381,33 @@ protected void runInContext() { } } - private void getRouterAlerts() { + protected class CheckRouterAlertsTask extends ManagedContextRunnable { + public CheckRouterAlertsTask() { + } + + @Override + protected void runInContext() { + try { + getRouterAlerts(); + } catch (final Exception ex) { + s_logger.error("Fail to complete the CheckRouterAlertsTask! ", ex); + } + } + } + + protected void getRouterAlerts() { try{ - List routersInIsolatedNetwork = _routerDao.listByStateAndNetworkType(State.Running, GuestType.Isolated, mgmtSrvrId); - List routersInSharedNetwork = _routerDao.listByStateAndNetworkType(State.Running, GuestType.Shared, mgmtSrvrId); + List routers = _routerDao.listByStateAndManagementServer(State.Running, mgmtSrvrId); - List routers = new ArrayList(); - routers.addAll(routersInIsolatedNetwork); - routers.addAll(routersInSharedNetwork); s_logger.debug("Found " + routers.size() + " running routers. "); for (final DomainRouterVO router : routers) { - if (router.getVpcId() != null) { + String serviceMonitoringFlag = SetServiceMonitor.valueIn(router.getDataCenterId()); + // Skip the routers in VPC network or skip the routers where Monitor service is not enabled in the corresponding Zone + if ( !Boolean.parseBoolean(serviceMonitoringFlag) || router.getVpcId() != null) { continue; } + String privateIP = router.getPrivateIpAddress(); if (privateIP != null) { @@ -1392,23 +1415,49 @@ private void getRouterAlerts() { GetRouterAlertsCommand command = null; if (opRouterMonitorServiceVO == null) { - command = new GetRouterAlertsCommand(null); + command = new GetRouterAlertsCommand(new String("1970-01-01 00:00:00")); // To avoid sending null value } else { command = new GetRouterAlertsCommand(opRouterMonitorServiceVO.getLastAlertTimestamp()); } command.setAccessDetail(NetworkElementCommand.ROUTER_IP, router.getPrivateIpAddress()); - command.setAccessDetail(NetworkElementCommand.ROUTER_NAME, router.getInstanceName()); - GetRouterAlertsAnswer answer = null; try { - answer = (GetRouterAlertsAnswer) _agentMgr.easySend(router.getHostId(), command); + final Answer origAnswer = _agentMgr.easySend(router.getHostId(), command); + GetRouterAlertsAnswer answer = null; + + if (origAnswer == null) { + s_logger.warn("Unable to get alerts from router " + router.getHostName()); + continue; + } + if (origAnswer instanceof GetRouterAlertsAnswer) { + answer = (GetRouterAlertsAnswer)origAnswer; + } else { + s_logger.warn("Unable to get alerts from router " + router.getHostName()); + continue; + } + if (!answer.getResult()) { + s_logger.warn("Unable to get alerts from router " + router.getHostName() + " " + answer.getDetails()); + continue; + } + String alerts[] = answer.getAlerts(); - if (alerts != null ) { + if (alerts != null) { + String lastAlertTimeStamp = answer.getTimeStamp(); + SimpleDateFormat sdfrmt = new SimpleDateFormat("yyyy-MM-dd hh:mm:ss"); + sdfrmt.setLenient(false); + try + { + sdfrmt.parse(lastAlertTimeStamp); + } + catch (ParseException e) + { + s_logger.warn("Invalid last alert timestamp received while collecting alerts from router: " + router.getInstanceName()); + continue; + } for (String alert: alerts) { _alertMgr.sendAlert(AlertType.ALERT_TYPE_DOMAIN_ROUTER, router.getDataCenterId(), router.getPodIdToDeployIn(), "Monitoring Service on VR " + router.getInstanceName(), alert); } - String lastAlertTimeStamp = answer.getTimeStamp(); if (opRouterMonitorServiceVO == null) { opRouterMonitorServiceVO = new OpRouterMonitorServiceVO(router.getId(), router.getHostName(), lastAlertTimeStamp); _opRouterMonitorServiceDao.persist(opRouterMonitorServiceVO); @@ -1418,7 +1467,7 @@ private void getRouterAlerts() { } } } catch (Exception e) { - s_logger.warn("Error while collecting alerts from router: " + router.getInstanceName() + " from host: " + router.getHostId(), e); + s_logger.warn("Error while collecting alerts from router: " + router.getInstanceName(), e); continue; } } @@ -1428,7 +1477,6 @@ private void getRouterAlerts() { } } - private final static int DEFAULT_PRIORITY = 100; private final static int DEFAULT_DELTA = 2; @@ -2291,6 +2339,9 @@ protected StringBuilder createGuestBootLoadArgs(final NicProfile guestNic, final buf.append(" guestbrd=").append(brd); buf.append(" guestcidrsize=").append(NetUtils.getCidrSize(guestNic.getNetmask())); buf.append(" router_pr=").append(router.getPriority()); + + int advertInt = NumbersUtil.parseInt(_configDao.getValue(Config.RedundantRouterVrrpInterval.key()), 1); + buf.append(" advert_int=").append(advertInt); } //setup network domain @@ -2299,10 +2350,12 @@ protected StringBuilder createGuestBootLoadArgs(final NicProfile guestNic, final buf.append(" domain=" + domain); } + long cidrSize = 0; + //setup dhcp range if (dc.getNetworkType() == NetworkType.Basic) { if (guestNic.isDefaultNic()) { - final long cidrSize = NetUtils.getCidrSize(guestNic.getNetmask()); + cidrSize = NetUtils.getCidrSize(guestNic.getNetmask()); final String cidr = NetUtils.getCidrSubNet(guestNic.getGateway(), cidrSize); if (cidr != null) { dhcpRange = NetUtils.getIpRangeStartIpFromCidr(cidr, cidrSize); @@ -2311,11 +2364,14 @@ protected StringBuilder createGuestBootLoadArgs(final NicProfile guestNic, final } else if (dc.getNetworkType() == NetworkType.Advanced) { final String cidr = guestNetwork.getCidr(); if (cidr != null) { + cidrSize = NetUtils.getCidrSize(NetUtils.getCidrNetmask(cidr)); dhcpRange = NetUtils.getDhcpRange(cidr); } } if (dhcpRange != null) { + // To limit DNS to the cidr range + buf.append(" cidrsize=" + String.valueOf(cidrSize)); buf.append(" dhcprange=" + dhcpRange); } @@ -2429,6 +2485,19 @@ public boolean finalizeCommandsOnStart(final Commands cmds, final VirtualMachine if (reprogramGuestNtwks) { finalizeIpAssocForNetwork(cmds, router, provider, guestNetworkId, null); finalizeNetworkRulesForNetwork(cmds, router, provider, guestNetworkId); + + NetworkOffering offering = _networkOfferingDao.findById((_networkDao.findById(guestNetworkId)).getNetworkOfferingId()); + //service monitoring is currently not added in RVR + if (!offering.getRedundantRouter()) { + String serviceMonitringSet = _configDao.getValue(Config.EnableServiceMonitoring.key()); + + if (serviceMonitringSet != null && serviceMonitringSet.equalsIgnoreCase("true")) { + finalizeMonitorServiceOnStrat(cmds, profile, router, provider, guestNetworkId, true); + } else { + finalizeMonitorServiceOnStrat(cmds, profile, router, provider, guestNetworkId, false); + } + } + } finalizeUserDataAndDhcpOnStart(cmds, router, provider, guestNetworkId); @@ -2439,15 +2508,6 @@ public boolean finalizeCommandsOnStart(final Commands cmds, final VirtualMachine } - String serviceMonitringSet = SetServiceMonitor.valueIn(router.getDataCenterId()); - //String serviceMonitringSet = _configDao.getValue(Config.EnableServiceMonitoring.key()); - - if (serviceMonitringSet != null && serviceMonitringSet.equalsIgnoreCase("true")) { - finalizeMonitorServiceOnStrat(cmds, profile, router, provider, routerGuestNtwkIds.get(0), true); - } else { - finalizeMonitorServiceOnStrat(cmds, profile, router, provider, routerGuestNtwkIds.get(0), false); - } - return true; } @@ -2751,22 +2811,23 @@ protected ArrayList getPublicIpsToApply(final Virtual public boolean finalizeStart(final VirtualMachineProfile profile, final long hostId, final Commands cmds, final ReservationContext context) { DomainRouterVO router = _routerDao.findById(profile.getId()); - boolean result = true; - - Answer answer = cmds.getAnswer("checkSsh"); - if (answer != null && answer instanceof CheckSshAnswer) { - final CheckSshAnswer sshAnswer = (CheckSshAnswer)answer; - if (sshAnswer == null || !sshAnswer.getResult()) { - s_logger.warn("Unable to ssh to the VM: " + sshAnswer.getDetails()); - result = false; + //process all the answers + for (Answer answer : cmds.getAnswers()) { + // handle any command failures + if (!answer.getResult()) { + String cmdClassName = answer.getClass().getCanonicalName().replace("Answer", "Command"); + String errorMessage = "Command: " + cmdClassName + " failed while starting virtual router"; + String errorDetails = "Details: " + answer.getDetails() + " " + answer.toString(); + //add alerts for the failed commands + _alertMgr.sendAlert(AlertService.AlertType.ALERT_TYPE_DOMAIN_ROUTER, router.getDataCenterId(), router.getPodIdToDeployIn(), errorMessage, errorDetails); + s_logger.warn(errorMessage); + //Stop the router if any of the commands failed + return false; } - } else { - result = false; - } - if (result == false) { - return result; } + // at this point, all the router command are successful. + boolean result = true; //Get guest networks info final List guestNetworks = new ArrayList(); @@ -2781,24 +2842,11 @@ public boolean finalizeStart(final VirtualMachineProfile profile, final long hos } } } - - if (!result) { - return result; - } - - answer = cmds.getAnswer("getDomRVersion"); - if (answer != null && answer instanceof GetDomRVersionAnswer) { - final GetDomRVersionAnswer versionAnswer = (GetDomRVersionAnswer)answer; - if (answer == null || !answer.getResult()) { - s_logger.warn("Unable to get the template/scripts version of router " + router.getInstanceName() + " due to: " + versionAnswer.getDetails()); - result = false; - } else { - router.setTemplateVersion(versionAnswer.getTemplateVersion()); - router.setScriptsVersion(versionAnswer.getScriptsVersion()); - router = _routerDao.persist(router, guestNetworks); - } - } else { - result = false; + if (result) { + GetDomRVersionAnswer versionAnswer = (GetDomRVersionAnswer)cmds.getAnswer("getDomRVersion"); + router.setTemplateVersion(versionAnswer.getTemplateVersion()); + router.setScriptsVersion(versionAnswer.getScriptsVersion()); + router = _routerDao.persist(router, guestNetworks); } return result; @@ -3252,7 +3300,7 @@ public VirtualRouter startRouter(final long routerId, final boolean reprogramNet if (router == null) { throw new InvalidParameterValueException("Unable to find router by id " + routerId + "."); } - _accountMgr.checkAccess(caller, null, true, router); + _accountMgr.checkAccess(caller, null, router); final Account owner = _accountMgr.getAccount(router.getAccountId()); @@ -4330,7 +4378,7 @@ public String getConfigComponentName() { @Override public ConfigKey[] getConfigKeys() { - return new ConfigKey[] {UseExternalDnsServers, routerVersionCheckEnabled, SetServiceMonitor}; + return new ConfigKey[] {UseExternalDnsServers, routerVersionCheckEnabled, SetServiceMonitor, RouterAlertsCheckInterval}; } @Override diff --git a/server/src/com/cloud/network/rules/RulesManagerImpl.java b/server/src/com/cloud/network/rules/RulesManagerImpl.java index 9a76219f00..f6a87bf457 100755 --- a/server/src/com/cloud/network/rules/RulesManagerImpl.java +++ b/server/src/com/cloud/network/rules/RulesManagerImpl.java @@ -25,10 +25,12 @@ import javax.ejb.Local; import javax.inject.Inject; +import org.apache.log4j.Logger; + +import org.apache.cloudstack.acl.SecurityChecker.AccessType; import org.apache.cloudstack.api.command.user.firewall.ListPortForwardingRulesCmd; import org.apache.cloudstack.context.CallContext; import org.apache.cloudstack.engine.orchestration.service.NetworkOrchestrationService; -import org.apache.log4j.Logger; import com.cloud.configuration.ConfigurationManager; import com.cloud.domain.dao.DomainDao; @@ -162,7 +164,7 @@ protected void checkIpAndUserVm(IpAddress ipAddress, UserVm userVm, Account call } } - _accountMgr.checkAccess(caller, null, true, ipAddress, userVm); + _accountMgr.checkAccess(caller, AccessType.OperateEntry, ipAddress, userVm); // validate that IP address and userVM belong to the same account if (ipAddress.getAllocatedToAccountId().longValue() != userVm.getAccountId()) { @@ -187,12 +189,13 @@ public void checkRuleAndUserVm(FirewallRule rule, UserVm userVm, Account caller) return; } - _accountMgr.checkAccess(caller, null, true, rule, userVm); + _accountMgr.checkAccess(caller, AccessType.OperateEntry, rule, userVm); if (userVm.getState() == VirtualMachine.State.Destroyed || userVm.getState() == VirtualMachine.State.Expunging) { throw new InvalidParameterValueException("Invalid user vm: " + userVm.getId()); } + // This same owner check is actually not needed, since multiple entities OperateEntry trick guarantee that if (rule.getAccountId() != userVm.getAccountId()) { throw new InvalidParameterValueException("New rule " + rule + " and vm id=" + userVm.getId() + " belong to different accounts"); } @@ -265,8 +268,8 @@ public PortForwardingRule createPortForwardingRule(final PortForwardingRule rule if (vm == null) { throw new InvalidParameterValueException("Unable to create port forwarding rule on address " + ipAddress + ", invalid virtual machine id specified (" + vmId + ")."); - } else { - checkRuleAndUserVm(rule, vm, caller); + } else if (vm.getState() == VirtualMachine.State.Destroyed || vm.getState() == VirtualMachine.State.Expunging) { + throw new InvalidParameterValueException("Invalid user vm: " + vm.getId()); } // Verify that vm has nic in the network @@ -680,7 +683,7 @@ public boolean revokePortForwardingRule(long ruleId, boolean apply) { throw new InvalidParameterValueException("Unable to find " + ruleId); } - _accountMgr.checkAccess(caller, null, true, rule); + _accountMgr.checkAccess(caller, null, rule); if (!revokePortForwardingRuleInternal(ruleId, caller, ctx.getCallingUserId(), apply)) { throw new CloudRuntimeException("Failed to delete port forwarding rule"); @@ -715,7 +718,7 @@ public boolean revokeStaticNatRule(long ruleId, boolean apply) { throw new InvalidParameterValueException("Unable to find " + ruleId); } - _accountMgr.checkAccess(caller, null, true, rule); + _accountMgr.checkAccess(caller, null, rule); if (!revokeStaticNatRuleInternal(ruleId, caller, ctx.getCallingUserId(), apply)) { throw new CloudRuntimeException("Failed to revoke forwarding rule"); @@ -791,7 +794,7 @@ public Pair, Integer> listPortForwardingRules if (ipAddressVO == null || !ipAddressVO.readyToUse()) { throw new InvalidParameterValueException("Ip address id=" + ipId + " not ready for port forwarding rules yet"); } - _accountMgr.checkAccess(caller, null, true, ipAddressVO); + _accountMgr.checkAccess(caller, null, ipAddressVO); } Ternary domainIdRecursiveListProject = new Ternary(cmd.getDomainId(), cmd.isRecursive(), null); @@ -866,7 +869,7 @@ protected boolean applyPortForwardingRules(long ipId, boolean continueOnError, A } if (caller != null) { - _accountMgr.checkAccess(caller, null, true, rules.toArray(new PortForwardingRuleVO[rules.size()])); + _accountMgr.checkAccess(caller, null, rules.toArray(new PortForwardingRuleVO[rules.size()])); } try { @@ -895,7 +898,7 @@ protected boolean applyStaticNatRulesForIp(long sourceIpId, boolean continueOnEr } if (caller != null) { - _accountMgr.checkAccess(caller, null, true, staticNatRules.toArray(new StaticNatRule[staticNatRules.size()])); + _accountMgr.checkAccess(caller, null, staticNatRules.toArray(new StaticNatRule[staticNatRules.size()])); } try { @@ -919,7 +922,7 @@ public boolean applyPortForwardingRulesForNetwork(long networkId, boolean contin } if (caller != null) { - _accountMgr.checkAccess(caller, null, true, rules.toArray(new PortForwardingRuleVO[rules.size()])); + _accountMgr.checkAccess(caller, null, rules.toArray(new PortForwardingRuleVO[rules.size()])); } try { @@ -945,7 +948,7 @@ public boolean applyStaticNatRulesForNetwork(long networkId, boolean continueOnE } if (caller != null) { - _accountMgr.checkAccess(caller, null, true, rules.toArray(new FirewallRule[rules.size()])); + _accountMgr.checkAccess(caller, null, rules.toArray(new FirewallRule[rules.size()])); } for (FirewallRuleVO rule : rules) { @@ -973,7 +976,7 @@ public boolean applyStaticNatsForNetwork(long networkId, boolean continueOnError } if (caller != null) { - _accountMgr.checkAccess(caller, null, true, ips.toArray(new IPAddressVO[ips.size()])); + _accountMgr.checkAccess(caller, null, ips.toArray(new IPAddressVO[ips.size()])); } List staticNats = new ArrayList(); @@ -1009,7 +1012,7 @@ public Pair, Integer> searchStaticNatRules(Long ipI if (ipAddressVO == null || !ipAddressVO.readyToUse()) { throw new InvalidParameterValueException("Ip address id=" + ipId + " not ready for port forwarding rules yet"); } - _accountMgr.checkAccess(caller, null, true, ipAddressVO); + _accountMgr.checkAccess(caller, null, ipAddressVO); } Ternary domainIdRecursiveListProject = new Ternary(domainId, isRecursive, null); @@ -1386,7 +1389,7 @@ protected List createStaticNatForIp(IpAddress sourceIp, Account calle } if (caller != null) { - _accountMgr.checkAccess(caller, null, true, sourceIp); + _accountMgr.checkAccess(caller, null, sourceIp); } // create new static nat rule @@ -1505,7 +1508,7 @@ public PortForwardingRule updatePortForwardingRule(long id, String customId, Boo if (rule == null) { throw new InvalidParameterValueException("Unable to find " + id); } - _accountMgr.checkAccess(caller, null, true, rule); + _accountMgr.checkAccess(caller, null, rule); if (customId != null) { rule.setUuid(customId); diff --git a/server/src/com/cloud/network/security/SecurityGroupManagerImpl.java b/server/src/com/cloud/network/security/SecurityGroupManagerImpl.java index cf71b25119..a666ecdffc 100755 --- a/server/src/com/cloud/network/security/SecurityGroupManagerImpl.java +++ b/server/src/com/cloud/network/security/SecurityGroupManagerImpl.java @@ -612,7 +612,7 @@ private List authorizeSecurityGroupRule(final Long security } // Verify permissions - _accountMgr.checkAccess(caller, null, true, securityGroup); + _accountMgr.checkAccess(caller, AccessType.OperateEntry, securityGroup); Long domainId = owner.getDomainId(); if (protocol == null) { @@ -716,7 +716,7 @@ private List authorizeSecurityGroupRule(final Long security final Integer startPortOrTypeFinal = startPortOrType; final Integer endPortOrCodeFinal = endPortOrCode; final String protocolFinal = protocol; - return Transaction.execute(new TransactionCallback>() { + List newRules = Transaction.execute(new TransactionCallback>() { @Override public List doInTransaction(TransactionStatus status) { // Prevents other threads/management servers from creating duplicate security rules @@ -761,9 +761,6 @@ public List doInTransaction(TransactionStatus status) { if (s_logger.isDebugEnabled()) { s_logger.debug("Added " + newRules.size() + " rules to security group " + securityGroup.getName()); } - final ArrayList affectedVms = new ArrayList(); - affectedVms.addAll(_securityGroupVMMapDao.listVmIdsBySecurityGroup(securityGroup.getId())); - scheduleRulesetUpdateToHosts(affectedVms, true, null); return newRules; } catch (Exception e) { s_logger.warn("Exception caught when adding security group rules ", e); @@ -776,6 +773,15 @@ public List doInTransaction(TransactionStatus status) { } }); + try { + final ArrayList affectedVms = new ArrayList(); + affectedVms.addAll(_securityGroupVMMapDao.listVmIdsBySecurityGroup(securityGroup.getId())); + scheduleRulesetUpdateToHosts(affectedVms, true, null); + } catch (Exception e) { + s_logger.debug("can't update rules on host, ignore", e); + } + + return newRules; } @Override @@ -813,9 +819,10 @@ private boolean revokeSecurityGroupRule(final Long id, SecurityRuleType type) { // Check permissions SecurityGroup securityGroup = _securityGroupDao.findById(rule.getSecurityGroupId()); - _accountMgr.checkAccess(caller, AccessType.OperateEntry, true, securityGroup); + _accountMgr.checkAccess(caller, AccessType.OperateEntry, securityGroup); - return Transaction.execute(new TransactionCallback() { + long securityGroupId = rule.getSecurityGroupId(); + Boolean result = Transaction.execute(new TransactionCallback() { @Override public Boolean doInTransaction(TransactionStatus status) { SecurityGroupVO groupHandle = null; @@ -831,10 +838,6 @@ public Boolean doInTransaction(TransactionStatus status) { _securityGroupRuleDao.remove(id); s_logger.debug("revokeSecurityGroupRule succeeded for security rule id: " + id); - final ArrayList affectedVms = new ArrayList(); - affectedVms.addAll(_securityGroupVMMapDao.listVmIdsBySecurityGroup(groupHandle.getId())); - scheduleRulesetUpdateToHosts(affectedVms, true, null); - return true; } catch (Exception e) { s_logger.warn("Exception caught when deleting security rules ", e); @@ -846,6 +849,16 @@ public Boolean doInTransaction(TransactionStatus status) { } } }); + + try { + final ArrayList affectedVms = new ArrayList(); + affectedVms.addAll(_securityGroupVMMapDao.listVmIdsBySecurityGroup(securityGroupId)); + scheduleRulesetUpdateToHosts(affectedVms, true, null); + } catch (Exception e) { + s_logger.debug("Can't update rules for host, ignore", e); + } + + return result; } @Override @@ -1107,7 +1120,7 @@ public boolean deleteSecurityGroup(DeleteSecurityGroupCmd cmd) throws ResourceIn } // check permissions - _accountMgr.checkAccess(caller, null, true, group); + _accountMgr.checkAccess(caller, AccessType.OperateEntry, group); return Transaction.execute(new TransactionCallbackWithException() { @Override @@ -1346,20 +1359,21 @@ public boolean securityGroupRulesForVmSecIp(long nicId, String secondaryIp, bool } // Verify permissions - _accountMgr.checkAccess(caller, null, false, vm); + _accountMgr.checkAccess(caller, null, vm); // Validate parameters List vmSgGrps = getSecurityGroupsForVm(vmId); - if (vmSgGrps == null) { + if (vmSgGrps.isEmpty()) { s_logger.debug("Vm is not in any Security group "); return true; } - for (SecurityGroupVO securityGroup : vmSgGrps) { - Account owner = _accountMgr.getAccount(securityGroup.getAccountId()); - if (owner == null) { - throw new InvalidParameterValueException("Unable to find security group owner by id=" + securityGroup.getAccountId()); - } + //If network does not support SG service, no need add SG rules for secondary ip + Network network = _networkModel.getNetwork(nic.getNetworkId()); + if (!_networkModel.isSecurityGroupSupportedInNetwork(network)) { + s_logger.debug("Network " + network + " is not enabled with security group service, "+ + "so not applying SG rules for secondary ip"); + return true; } String vmMac = vm.getPrivateMacAddress(); diff --git a/server/src/com/cloud/network/vpc/NetworkACLManagerImpl.java b/server/src/com/cloud/network/vpc/NetworkACLManagerImpl.java index ad47df14cc..d808c3fbc9 100644 --- a/server/src/com/cloud/network/vpc/NetworkACLManagerImpl.java +++ b/server/src/com/cloud/network/vpc/NetworkACLManagerImpl.java @@ -491,8 +491,12 @@ public boolean applyACLItemsToNetwork(long networkId, List rul foundProvider = true; s_logger.debug("Applying NetworkACL for network: " + network.getId() + " with Network ACL service provider"); handled = element.applyNetworkACLs(network, rules); - if (handled) + if (handled) { + // publish message on message bus, so that network elements implementing distributed routing + // capability can act on the event + _messageBus.publish(_name, "Network_ACL_Replaced", PublishScope.LOCAL, network); break; + } } if (!foundProvider) { s_logger.debug("Unable to find NetworkACL service provider for network: " + network.getId()); diff --git a/server/src/com/cloud/network/vpc/NetworkACLServiceImpl.java b/server/src/com/cloud/network/vpc/NetworkACLServiceImpl.java index e024fbe3d3..72996d160c 100644 --- a/server/src/com/cloud/network/vpc/NetworkACLServiceImpl.java +++ b/server/src/com/cloud/network/vpc/NetworkACLServiceImpl.java @@ -103,7 +103,7 @@ public NetworkACL createNetworkACL(String name, String description, long vpcId, if (vpc == null) { throw new InvalidParameterValueException("Unable to find VPC"); } - _accountMgr.checkAccess(caller, null, true, vpc); + _accountMgr.checkAccess(caller, null, vpc); return _networkAclMgr.createNetworkACL(name, description, vpcId, forDisplay); } @@ -161,7 +161,7 @@ public Pair, Integer> listNetworkACLs(ListNetworkACLL if (vpc == null) { throw new InvalidParameterValueException("Unable to find VPC"); } - _accountMgr.checkAccess(caller, null, true, vpc); + _accountMgr.checkAccess(caller, null, vpc); //Include vpcId 0 to list default ACLs sc.setParameters("vpcId", vpcId, 0); } else { @@ -225,7 +225,7 @@ public boolean deleteNetworkACL(long id) { if (vpc == null) { throw new InvalidParameterValueException("Unable to find specified VPC associated with the ACL"); } - _accountMgr.checkAccess(caller, null, true, vpc); + _accountMgr.checkAccess(caller, null, vpc); return _networkAclMgr.deleteNetworkACL(acl); } @@ -256,14 +256,14 @@ public boolean replaceNetworkACLonPrivateGw(long aclId, long privateGatewayId) t if (vpc == null) { throw new InvalidParameterValueException("Unable to find Vpc associated with the NetworkACL"); } - _accountMgr.checkAccess(caller, null, true, vpc); + _accountMgr.checkAccess(caller, null, vpc); if (!gateway.getVpcId().equals(acl.getVpcId())) { throw new InvalidParameterValueException("private gateway: " + privateGatewayId + " and ACL: " + aclId + " do not belong to the same VPC"); } } PrivateGateway privateGateway = _vpcSvc.getVpcPrivateGateway(gateway.getId()); - _accountMgr.checkAccess(caller, null, true, privateGateway); + _accountMgr.checkAccess(caller, null, privateGateway); return _networkAclMgr.replaceNetworkACLForPrivateGw(acl, privateGateway); @@ -299,7 +299,7 @@ public boolean replaceNetworkACL(long aclId, long networkId) throws ResourceUnav throw new InvalidParameterValueException("Unable to find Vpc associated with the NetworkACL"); } - _accountMgr.checkAccess(caller, null, true, vpc); + _accountMgr.checkAccess(caller, null, vpc); if (!network.getVpcId().equals(acl.getVpcId())) { throw new InvalidParameterValueException("Network: " + networkId + " and ACL: " + aclId + " do not belong to the same VPC"); } @@ -371,7 +371,7 @@ public NetworkACLItem createNetworkACLItem(CreateNetworkACLCmd aclItemCmd) { if (vpc == null) { throw new InvalidParameterValueException("Unable to find Vpc associated with the NetworkACL"); } - _accountMgr.checkAccess(caller, null, true, vpc); + _accountMgr.checkAccess(caller, null, vpc); //Ensure that number is unique within the ACL if (aclItemCmd.getNumber() != null) { @@ -532,6 +532,11 @@ public Pair, Integer> listNetworkACLItems(ListNet if (networkId != null) { Network network = _networkDao.findById(networkId); aclId = network.getNetworkACLId(); + if( aclId == null){ + // No aclId associated with the network. + //Return empty list + return new Pair(new ArrayList(), 0); + } } if (trafficType != null) { @@ -546,7 +551,7 @@ public Pair, Integer> listNetworkACLItems(ListNet if (vpc == null) { throw new InvalidParameterValueException("Unable to find VPC associated with acl"); } - _accountMgr.checkAccess(caller, null, true, vpc); + _accountMgr.checkAccess(caller, null, vpc); } sc.setParameters("aclId", aclId); } else { @@ -615,7 +620,7 @@ public boolean revokeNetworkACLItem(long ruleId) { Account caller = CallContext.current().getCallingAccount(); - _accountMgr.checkAccess(caller, null, true, vpc); + _accountMgr.checkAccess(caller, null, vpc); if((aclItem.getAclId() == NetworkACL.DEFAULT_ALLOW) || (aclItem.getAclId() == NetworkACL.DEFAULT_DENY)){ throw new InvalidParameterValueException("ACL Items in default ACL cannot be deleted"); @@ -642,7 +647,7 @@ public NetworkACLItem updateNetworkACLItem(Long id, String protocol, List getEntityType() { + return VpcGateway.class; } } diff --git a/server/src/com/cloud/network/vpc/VpcManagerImpl.java b/server/src/com/cloud/network/vpc/VpcManagerImpl.java index 2e63639c33..9e02fd797c 100644 --- a/server/src/com/cloud/network/vpc/VpcManagerImpl.java +++ b/server/src/com/cloud/network/vpc/VpcManagerImpl.java @@ -16,6 +16,7 @@ // under the License. package com.cloud.network.vpc; + import java.util.ArrayList; import java.util.Arrays; import java.util.Collection; @@ -35,6 +36,7 @@ import javax.naming.ConfigurationException; import org.apache.cloudstack.acl.ControlledEntity.ACLType; +import org.apache.cloudstack.acl.SecurityChecker.AccessType; import org.apache.cloudstack.api.command.user.vpc.ListPrivateGatewaysCmd; import org.apache.cloudstack.api.command.user.vpc.ListStaticRoutesCmd; import org.apache.cloudstack.context.CallContext; @@ -65,7 +67,6 @@ import com.cloud.exception.ResourceAllocationException; import com.cloud.exception.ResourceUnavailableException; import com.cloud.hypervisor.Hypervisor.HypervisorType; -import com.cloud.network.element.NetworkElement; import com.cloud.network.IpAddress; import com.cloud.network.IpAddressManager; import com.cloud.network.Network; @@ -85,6 +86,7 @@ import com.cloud.network.dao.NetworkVO; import com.cloud.network.dao.PhysicalNetworkDao; import com.cloud.network.dao.Site2SiteVpnGatewayDao; +import com.cloud.network.element.NetworkElement; import com.cloud.network.element.StaticNatServiceProvider; import com.cloud.network.element.VpcProvider; import com.cloud.network.vpc.VpcOffering.State; @@ -127,7 +129,6 @@ import com.cloud.utils.db.TransactionCallback; import com.cloud.utils.db.TransactionCallbackNoReturn; import com.cloud.utils.db.TransactionCallbackWithException; -import com.cloud.utils.db.TransactionCallbackWithExceptionNoReturn; import com.cloud.utils.db.TransactionStatus; import com.cloud.utils.exception.CloudRuntimeException; import com.cloud.utils.exception.ExceptionUtil; @@ -220,44 +221,49 @@ public boolean configure(String name, Map params) throws Configu Transaction.execute(new TransactionCallbackNoReturn() { @Override public void doInTransactionWithoutResult(TransactionStatus status) { - if (_vpcOffDao.findByUniqueName(VpcOffering.defaultVPCOfferingName) == null) { - s_logger.debug("Creating default VPC offering " + VpcOffering.defaultVPCOfferingName); - - Map> svcProviderMap = new HashMap>(); - Set defaultProviders = new HashSet(); - defaultProviders.add(Provider.VPCVirtualRouter); - for (Service svc : getSupportedServices()) { - if (svc == Service.Lb) { - Set lbProviders = new HashSet(); - lbProviders.add(Provider.VPCVirtualRouter); - lbProviders.add(Provider.InternalLbVm); - svcProviderMap.put(svc, lbProviders); - } else { - svcProviderMap.put(svc, defaultProviders); + + if (_vpcOffDao.findByUniqueName(VpcOffering.defaultVPCOfferingName) == null) { + s_logger.debug("Creating default VPC offering " + VpcOffering.defaultVPCOfferingName); + + Map> svcProviderMap = new HashMap>(); + Set defaultProviders = new HashSet(); + defaultProviders.add(Provider.VPCVirtualRouter); + for (Service svc : getSupportedServices()) { + if (svc == Service.Lb) { + Set lbProviders = new HashSet(); + lbProviders.add(Provider.VPCVirtualRouter); + lbProviders.add(Provider.InternalLbVm); + svcProviderMap.put(svc, lbProviders); + } else { + svcProviderMap.put(svc, defaultProviders); + } + } + createVpcOffering(VpcOffering.defaultVPCOfferingName, VpcOffering.defaultVPCOfferingName, + svcProviderMap, true, State.Enabled, null, false, false); } - } - createVpcOffering(VpcOffering.defaultVPCOfferingName, VpcOffering.defaultVPCOfferingName, svcProviderMap, true, State.Enabled, null, false); - } - //configure default vpc offering with Netscaler as LB Provider + //configure default vpc offering with Netscaler as LB Provider if (_vpcOffDao.findByUniqueName(VpcOffering.defaultVPCNSOfferingName) == null) { - s_logger.debug("Creating default VPC offering with Netscaler as LB Provider" + VpcOffering.defaultVPCNSOfferingName); - Map> svcProviderMap = new HashMap>(); - Set defaultProviders = new HashSet(); - defaultProviders.add(Provider.VPCVirtualRouter); - for (Service svc : getSupportedServices()) { - if (svc == Service.Lb) { - Set lbProviders = new HashSet(); - lbProviders.add(Provider.Netscaler); - lbProviders.add(Provider.InternalLbVm); - svcProviderMap.put(svc, lbProviders); - } else { - svcProviderMap.put(svc, defaultProviders); + s_logger.debug("Creating default VPC offering with Netscaler as LB Provider" + VpcOffering.defaultVPCNSOfferingName); + Map> svcProviderMap = new HashMap>(); + Set defaultProviders = new HashSet(); + defaultProviders.add(Provider.VPCVirtualRouter); + for (Service svc : getSupportedServices()) { + if (svc == Service.Lb) { + Set lbProviders = new HashSet(); + lbProviders.add(Provider.Netscaler); + lbProviders.add(Provider.InternalLbVm); + svcProviderMap.put(svc, lbProviders); + } else { + svcProviderMap.put(svc, defaultProviders); + } + } + createVpcOffering(VpcOffering.defaultVPCNSOfferingName, VpcOffering.defaultVPCNSOfferingName, + svcProviderMap, false, State.Enabled, null, false, false); + } } - createVpcOffering(VpcOffering.defaultVPCNSOfferingName, VpcOffering.defaultVPCNSOfferingName, svcProviderMap, false, State.Enabled, null, false); - } - } + }); Map configs = _configDao.getConfiguration(params); @@ -380,10 +386,12 @@ public VpcOffering createVpcOffering(String name, String displayText, List> svcProviderMap, final boolean isDefault, final State state, final Long serviceOfferingId, - final boolean supportsDistributedRouter) { + final boolean supportsDistributedRouter, final boolean offersRegionLevelVPC) { + return Transaction.execute(new TransactionCallback() { @Override public VpcOffering doInTransaction(TransactionStatus status) { // create vpc offering object - VpcOfferingVO offering = new VpcOfferingVO(name, displayText, isDefault, serviceOfferingId, supportsDistributedRouter); + VpcOfferingVO offering = new VpcOfferingVO(name, displayText, isDefault, serviceOfferingId, + supportsDistributedRouter, offersRegionLevelVPC); - if (state != null) { - offering.setState(state); - } - s_logger.debug("Adding vpc offering " + offering); - offering = _vpcOffDao.persist(offering); - // populate services and providers - if (svcProviderMap != null) { - for (Network.Service service : svcProviderMap.keySet()) { - Set providers = svcProviderMap.get(service); - if (providers != null && !providers.isEmpty()) { - for (Network.Provider provider : providers) { - VpcOfferingServiceMapVO offService = new VpcOfferingServiceMapVO(offering.getId(), service, provider); - _vpcOffSvcMapDao.persist(offService); - s_logger.trace("Added service for the vpc offering: " + offService + " with provider " + provider.getName()); + if (state != null) { + offering.setState(state); + } + s_logger.debug("Adding vpc offering " + offering); + offering = _vpcOffDao.persist(offering); + // populate services and providers + if (svcProviderMap != null) { + for (Network.Service service : svcProviderMap.keySet()) { + Set providers = svcProviderMap.get(service); + if (providers != null && !providers.isEmpty()) { + for (Network.Provider provider : providers) { + VpcOfferingServiceMapVO offService = new VpcOfferingServiceMapVO(offering.getId(), service, provider); + _vpcOffSvcMapDao.persist(offService); + s_logger.trace("Added service for the vpc offering: " + offService + " with provider " + provider.getName()); + } + } else { + throw new InvalidParameterValueException("Provider is missing for the VPC offering service " + service.getName()); + } } - } else { - throw new InvalidParameterValueException("Provider is missing for the VPC offering service " + service.getName()); } - } - } - return offering; - } + return offering; + } }); } - private boolean isVpcOfferingSupportsDistributedRouter(Map serviceCapabilitystList) { - boolean supportsDistributedRouter = false; + private void validateConnectivtyServiceCapablitlies(Set providers, Map serviceCapabilitystList) { + if (serviceCapabilitystList != null && !serviceCapabilitystList.isEmpty()) { Collection serviceCapabilityCollection = serviceCapabilitystList.values(); Iterator iter = serviceCapabilityCollection.iterator(); Map capabilityMap = null; + boolean distributedRouterCapabilitySpecified = false; + boolean regionLevelVpcCapabilitySpecified = false; while (iter.hasNext()) { HashMap svcCapabilityMap = (HashMap)iter.next(); @@ -448,24 +460,56 @@ private boolean isVpcOfferingSupportsDistributedRouter(Map serviceCapabilitystLi } if (!svc.equalsIgnoreCase(Service.Connectivity.getName())) { - throw new InvalidParameterValueException("Invalid Service:" + svc + " specified. Only for 'Connectivity' service capabilities can be specified"); + throw new InvalidParameterValueException("Invalid Service:" + svc + " specified. Only 'Connectivity'" + + " service capabilities can be specified"); } - if (!capabilityName.equalsIgnoreCase("DistributedRouter")) { - throw new InvalidParameterValueException("Invalid Capability:" + capabilityName + " specified. Only 'DistributedRouter' capability can be specified."); + if (!capabilityName.equalsIgnoreCase("DistributedRouter") && !capabilityName.equalsIgnoreCase("RegionLevelVpc")) { + throw new InvalidParameterValueException("Invalid Capability:" + capabilityName + " specified." + + " Only 'DistributedRouter'/'RegionLevelVpc' capability can be specified."); + } + + if (capabilityName.equalsIgnoreCase("DistributedRouter")) { + distributedRouterCapabilitySpecified = true; + } + + if (capabilityName.equalsIgnoreCase("RegionLevelVpc")) { + regionLevelVpcCapabilitySpecified = true; } if (!capabilityValue.equalsIgnoreCase("true") && capabilityValue.equalsIgnoreCase("false")) { throw new InvalidParameterValueException("Invalid Capability value:" + capabilityValue + " specified."); } - supportsDistributedRouter = capabilityValue.equalsIgnoreCase("true"); + } + + if (providers != null && !providers.isEmpty()) { + for (Provider provider: providers) { + NetworkElement element = _ntwkModel.getElementImplementingProvider(provider.getName()); + Map> capabilities = element.getCapabilities(); + if (capabilities != null && !capabilities.isEmpty()) { + Map connectivityCapabilities = capabilities.get(Service.Connectivity); + if (regionLevelVpcCapabilitySpecified) { + if (connectivityCapabilities == null || (connectivityCapabilities != null && + !connectivityCapabilities.keySet().contains(Network.Capability.RegionLevelVpc))) { + throw new InvalidParameterValueException("Provider: " + provider.getName() + " does not support " + + Network.Capability.RegionLevelVpc.getName() + " capability."); + } + } + if (distributedRouterCapabilitySpecified) { + if (connectivityCapabilities == null || (connectivityCapabilities != null && + !connectivityCapabilities.keySet().contains(Network.Capability.DistributedRouter))) { + throw new InvalidParameterValueException("Provider: " + provider.getName() + " does not support " + + Network.Capability.DistributedRouter.getName() + " capability."); + } + } + } + } } } - return supportsDistributedRouter; } - private void validateConnectivtyServiceCapablitlies(Set providers, Map serviceCapabilitystList) { - + private boolean isVpcOfferingForRegionLevelVpc(Map serviceCapabilitystList) { + boolean offersRegionLevelVPC = false; if (serviceCapabilitystList != null && !serviceCapabilitystList.isEmpty()) { Collection serviceCapabilityCollection = serviceCapabilitystList.values(); Iterator iter = serviceCapabilityCollection.iterator(); @@ -489,29 +533,55 @@ private void validateConnectivtyServiceCapablitlies(Set providers, Map throw new InvalidParameterValueException("Invalid Service:" + svc + " specified. Only for 'Connectivity' service capabilities can be specified"); } - if (!capabilityName.equalsIgnoreCase("DistributedRouter")) { - throw new InvalidParameterValueException("Invalid Capability:" + capabilityName + " specified. Only 'DistributedRouter' capability can be specified."); + if (!capabilityName.equalsIgnoreCase("RegionLevelVpc")) { + continue; } if (!capabilityValue.equalsIgnoreCase("true") && capabilityValue.equalsIgnoreCase("false")) { throw new InvalidParameterValueException("Invalid Capability value:" + capabilityValue + " specified."); } + offersRegionLevelVPC = capabilityValue.equalsIgnoreCase("true"); } + } + return offersRegionLevelVPC; + } - if (providers != null && !providers.isEmpty()) { - for (Provider provider: providers) { - NetworkElement element = _ntwkModel.getElementImplementingProvider(provider.getName()); - Map> capabilities = element.getCapabilities(); - if (capabilities != null && !capabilities.isEmpty()) { - Map connectivityCapabilities = capabilities.get(Service.Connectivity); - if (connectivityCapabilities == null || (connectivityCapabilities != null && !connectivityCapabilities.keySet().contains(Network.Capability.DistributedRouter))) { - throw new InvalidParameterValueException("Provider: " + provider.getName() + " does not support " - + Network.Capability.DistributedRouter.getName() + " capability."); - } - } + private boolean isVpcOfferingSupportsDistributedRouter(Map serviceCapabilitystList) { + boolean supportsDistributedRouter = false; + if (serviceCapabilitystList != null && !serviceCapabilitystList.isEmpty()) { + Collection serviceCapabilityCollection = serviceCapabilitystList.values(); + Iterator iter = serviceCapabilityCollection.iterator(); + Map capabilityMap = null; + + while (iter.hasNext()) { + HashMap svcCapabilityMap = (HashMap)iter.next(); + Network.Capability capability = null; + String svc = svcCapabilityMap.get("service"); + String capabilityName = svcCapabilityMap.get("capabilitytype"); + String capabilityValue = svcCapabilityMap.get("capabilityvalue"); + if (capabilityName != null) { + capability = Network.Capability.getCapability(capabilityName); + } + + if ((capability == null) || (capabilityName == null) || (capabilityValue == null)) { + throw new InvalidParameterValueException("Invalid capability:" + capabilityName + " capability value:" + capabilityValue); } + + if (!svc.equalsIgnoreCase(Service.Connectivity.getName())) { + throw new InvalidParameterValueException("Invalid Service:" + svc + " specified. Only for 'Connectivity' service capabilities can be specified"); + } + + if (!capabilityName.equalsIgnoreCase("DistributedRouter")) { + continue; + } + + if (!capabilityValue.equalsIgnoreCase("true") && capabilityValue.equalsIgnoreCase("false")) { + throw new InvalidParameterValueException("Invalid Capability value:" + capabilityValue + " specified."); + } + supportsDistributedRouter = capabilityValue.equalsIgnoreCase("true"); } } + return supportsDistributedRouter; } @Override @@ -691,7 +761,7 @@ public Vpc createVpc(long zoneId, long vpcOffId, long vpcOwnerId, String vpcName Account owner = _accountMgr.getAccount(vpcOwnerId); //Verify that caller can perform actions in behalf of vpc owner - _accountMgr.checkAccess(caller, null, false, owner); + _accountMgr.checkAccess(caller, null, owner); //check resource limit _resourceLimitMgr.checkResourceLimit(owner, ResourceType.vpc); @@ -708,6 +778,11 @@ public Vpc createVpc(long zoneId, long vpcOffId, long vpcOwnerId, String vpcName throw ex; } + boolean isRegionLevelVpcOff = vpcOff.offersRegionLevelVPC(); + if (isRegionLevelVpcOff && networkDomain == null) { + throw new InvalidParameterValueException("Network domain must be specified for region level VPC"); + } + //Validate zone DataCenter zone = _entityMgr.findById(DataCenter.class, zoneId); if (zone == null) { @@ -730,13 +805,15 @@ public Vpc createVpc(long zoneId, long vpcOffId, long vpcOwnerId, String vpcName networkDomain = "cs" + Long.toHexString(owner.getId()) + NetworkOrchestrationService.GuestDomainSuffix.valueIn(zoneId); } } + boolean useDistributedRouter = vpcOff.supportsDistributedRouter(); - return createVpc(zoneId, vpcOffId, owner, vpcName, displayText, cidr, networkDomain, displayVpc, useDistributedRouter); + return createVpc(zoneId, vpcOffId, owner, vpcName, displayText, cidr, networkDomain, displayVpc, + useDistributedRouter, isRegionLevelVpcOff); } @DB protected Vpc createVpc(final long zoneId, final long vpcOffId, final Account vpcOwner, final String vpcName, final String displayText, final String cidr, - final String networkDomain, final Boolean displayVpc, final boolean useDistributedRouter) { + final String networkDomain, final Boolean displayVpc, final boolean useDistributedRouter, final boolean regionLevelVpc) { //Validate CIDR if (!NetUtils.isValidCIDR(cidr)) { @@ -759,7 +836,8 @@ protected Vpc createVpc(final long zoneId, final long vpcOffId, final Account vp @Override public VpcVO doInTransaction(TransactionStatus status) { VpcVO vpc = new VpcVO(zoneId, vpcName, displayText, vpcOwner.getId(), vpcOwner.getDomainId(), vpcOffId, - cidr, networkDomain, useDistributedRouter); + cidr, networkDomain, useDistributedRouter, regionLevelVpc); + if (displayVpc != null) { vpc.setDisplay(displayVpc); } @@ -816,7 +894,7 @@ public boolean deleteVpc(long vpcId) throws ConcurrentOperationException, Resour } //verify permissions - _accountMgr.checkAccess(ctx.getCallingAccount(), null, false, vpc); + _accountMgr.checkAccess(ctx.getCallingAccount(), null, vpc); return destroyVpc(vpc, ctx.getCallingAccount(), ctx.getCallingUserId()); } @@ -884,7 +962,7 @@ public Vpc updateVpc(long vpcId, String vpcName, String displayText, String cust throw new InvalidParameterValueException("Unable to find vpc by id " + vpcId); } - _accountMgr.checkAccess(caller, null, false, vpcToUpdate); + _accountMgr.checkAccess(caller, null, vpcToUpdate); VpcVO vpc = _vpcDao.createForUpdate(vpcId); @@ -1076,7 +1154,7 @@ public boolean startVpc(long vpcId, boolean destroyOnFailure) throws ConcurrentO } //permission check - _accountMgr.checkAccess(caller, null, false, vpc); + _accountMgr.checkAccess(caller, null, vpc); DataCenter dc = _entityMgr.findById(DataCenter.class, vpc.getZoneId()); @@ -1136,7 +1214,7 @@ public boolean shutdownVpc(long vpcId) throws ConcurrentOperationException, Reso } //permission check - _accountMgr.checkAccess(caller, null, false, vpc); + _accountMgr.checkAccess(caller, null, vpc); //shutdown provider s_logger.debug("Shutting down vpc " + vpc); @@ -1199,7 +1277,9 @@ public void validateNtwkOffForNtwkInVpc(Long networkId, long newNtwkOffId, Strin continue; } else { NetworkOffering otherOff = _entityMgr.findById(NetworkOffering.class, network.getNetworkOfferingId()); - if (_ntwkModel.areServicesSupportedInNetwork(network.getId(), Service.Lb) && otherOff.getPublicLb()) { + //throw only if networks have different offerings with public lb support + if (_ntwkModel.areServicesSupportedInNetwork(network.getId(), Service.Lb) && otherOff.getPublicLb() && + guestNtwkOff.getId() != otherOff.getId()) { throw new InvalidParameterValueException("Public LB service is already supported " + "by network " + network + " in VPC " + vpc); } } @@ -1400,7 +1480,7 @@ public boolean restartVpc(long vpcId) throws ConcurrentOperationException, Resou throw ex; } - _accountMgr.checkAccess(caller, null, false, vpc); + _accountMgr.checkAccess(caller, null, vpc); s_logger.debug("Restarting VPC " + vpc); boolean restartRequired = false; @@ -1573,10 +1653,14 @@ public PrivateGateway applyVpcPrivateGateway(long gatewayId, boolean destroyOnFa boolean success = true; try { + List providersToImplement = getVpcProviders(vo.getVpcId()); + PrivateGateway gateway = getVpcPrivateGateway(gatewayId); for (VpcProvider provider : getVpcElements()) { - if (!provider.createPrivateGateway(gateway)) { - success = false; + if (providersToImplement.contains(provider.getProvider())) { + if (!provider.createPrivateGateway(gateway)) { + success = false; + } } } if (success) { @@ -1635,17 +1719,20 @@ public void doInTransactionWithoutResult(TransactionStatus status) { }); //1) delete the gateway on the backend + List providersToImplement = getVpcProviders(gatewayVO.getVpcId()); PrivateGateway gateway = getVpcPrivateGateway(gatewayId); for (VpcProvider provider : getVpcElements()) { - if (provider.deletePrivateGateway(gateway)) { - s_logger.debug("Private gateway " + gateway + " was applied succesfully on the backend"); - } else { - s_logger.warn("Private gateway " + gateway + " failed to apply on the backend"); - gatewayVO.setState(VpcGateway.State.Ready); - _vpcGatewayDao.update(gatewayVO.getId(), gatewayVO); - s_logger.debug("Marked gateway " + gatewayVO + " with state " + VpcGateway.State.Ready); + if (providersToImplement.contains(provider.getProvider())) { + if (provider.deletePrivateGateway(gateway)) { + s_logger.debug("Private gateway " + gateway + " was applied succesfully on the backend"); + } else { + s_logger.warn("Private gateway " + gateway + " failed to apply on the backend"); + gatewayVO.setState(VpcGateway.State.Ready); + _vpcGatewayDao.update(gatewayVO.getId(), gatewayVO); + s_logger.debug("Marked gateway " + gatewayVO + " with state " + VpcGateway.State.Ready); - return false; + return false; + } } } @@ -1734,7 +1821,7 @@ public Pair, Integer> listPrivateGateway(ListPrivateGateway } SearchCriteria sc = sb.create(); - _accountMgr.buildACLSearchBuilder(sb, isRecursive, permittedDomains, permittedAccounts, permittedResources, listProjectResourcesCriteria); + _accountMgr.buildACLSearchCriteria(sc, isRecursive, permittedDomains, permittedAccounts, permittedResources, listProjectResourcesCriteria); if (id != null) { sc.addAnd("id", Op.EQ, id); @@ -1847,7 +1934,7 @@ public boolean revokeStaticRoute(long routeId) throws ResourceUnavailableExcepti throw new InvalidParameterValueException("Unable to find static route by id"); } - _accountMgr.checkAccess(caller, null, false, route); + _accountMgr.checkAccess(caller, null, route); markStaticRouteForRevoke(route, caller); @@ -1895,7 +1982,7 @@ public StaticRoute createStaticRoute(long gatewayId, final String cidr) throws N if (vpc == null) { throw new InvalidParameterValueException("Can't add static route to VPC that is being deleted"); } - _accountMgr.checkAccess(caller, null, false, vpc); + _accountMgr.checkAccess(caller, null, vpc); if (!NetUtils.isValidCIDR(cidr)) { throw new InvalidParameterValueException("Invalid format for cidr " + cidr); @@ -2047,7 +2134,7 @@ protected void detectRoutesConflict(StaticRoute newRoute) throws NetworkRuleConf protected void markStaticRouteForRevoke(StaticRouteVO route, Account caller) { s_logger.debug("Revoking static route " + route); if (caller != null) { - _accountMgr.checkAccess(caller, null, false, route); + _accountMgr.checkAccess(caller, null, route); } if (route.getState() == StaticRoute.State.Staged) { @@ -2078,9 +2165,6 @@ protected void runInContext() { } try { - Transaction.execute(new TransactionCallbackWithExceptionNoReturn() { - @Override - public void doInTransactionWithoutResult(TransactionStatus status) throws Exception { // Cleanup inactive VPCs List inactiveVpcs = _vpcDao.listInactiveVpcs(); s_logger.info("Found " + inactiveVpcs.size() + " removed VPCs to cleanup"); @@ -2088,8 +2172,6 @@ public void doInTransactionWithoutResult(TransactionStatus status) throws Except s_logger.debug("Cleaning up " + vpc); destroyVpc(vpc, _accountMgr.getAccount(Account.ACCOUNT_ID_SYSTEM), User.UID_SYSTEM); } - } - }); } catch (Exception e) { s_logger.error("Exception ", e); } finally { @@ -2111,7 +2193,6 @@ public IpAddress associateIPToVpc(final long ipId, final long vpcId) throws Reso IpAddress ipToAssoc = _ntwkModel.getIp(ipId); if (ipToAssoc != null) { - _accountMgr.checkAccess(caller, null, true, ipToAssoc); owner = _accountMgr.getAccount(ipToAssoc.getAllocatedToAccountId()); } else { s_logger.debug("Unable to find ip address by id: " + ipId); @@ -2124,7 +2205,7 @@ public IpAddress associateIPToVpc(final long ipId, final long vpcId) throws Reso } // check permissions - _accountMgr.checkAccess(caller, null, true, owner, vpc); + _accountMgr.checkAccess(caller, AccessType.OperateEntry, ipToAssoc, vpc); boolean isSourceNat = false; if (getExistingSourceNatInVpc(owner.getId(), vpcId) == null) { @@ -2204,13 +2285,13 @@ public Network createVpcGuestNetwork(long ntwkOffId, String name, String display ex.addProxyObject(String.valueOf(vpcId), "VPC"); throw ex; } - _accountMgr.checkAccess(caller, null, false, vpc); + _accountMgr.checkAccess(caller, null, vpc); if (networkDomain == null) { networkDomain = vpc.getNetworkDomain(); } - if (vpc.getZoneId() != zoneId) { + if (!vpc.isRegionLevelVpc() && vpc.getZoneId() != zoneId) { throw new InvalidParameterValueException("New network doesn't belong to vpc zone"); } diff --git a/server/src/com/cloud/network/vpn/RemoteAccessVpnManagerImpl.java b/server/src/com/cloud/network/vpn/RemoteAccessVpnManagerImpl.java index 531adad352..9d9118c021 100755 --- a/server/src/com/cloud/network/vpn/RemoteAccessVpnManagerImpl.java +++ b/server/src/com/cloud/network/vpn/RemoteAccessVpnManagerImpl.java @@ -150,7 +150,7 @@ public RemoteAccessVpn createRemoteAccessVpn(final long publicIpId, String ipRan throw new InvalidParameterValueException("Unable to create remote access vpn, invalid public IP address id" + publicIpId); } - _accountMgr.checkAccess(caller, null, true, ipAddr); + _accountMgr.checkAccess(caller, null, ipAddr); if (!ipAddr.readyToUse()) { throw new InvalidParameterValueException("The Ip address is not ready to be used yet: " + ipAddr.getAddress()); @@ -285,15 +285,16 @@ private void validateRemoteAccessVpnConfiguration() throws ConfigurationExceptio @Override @DB - public void destroyRemoteAccessVpnForIp(long ipId, Account caller) throws ResourceUnavailableException { + public boolean destroyRemoteAccessVpnForIp(long ipId, Account caller) throws ResourceUnavailableException { final RemoteAccessVpnVO vpn = _remoteAccessVpnDao.findByPublicIpAddress(ipId); if (vpn == null) { s_logger.debug("there are no Remote access vpns for public ip address id=" + ipId); - return; + return true; } - _accountMgr.checkAccess(caller, AccessType.OperateEntry, true, vpn); + _accountMgr.checkAccess(caller, AccessType.OperateEntry, vpn); + RemoteAccessVpn.State prevState = vpn.getState(); vpn.setState(RemoteAccessVpn.State.Removed); _remoteAccessVpnDao.update(vpn.getId(), vpn); @@ -305,6 +306,12 @@ public void destroyRemoteAccessVpnForIp(long ipId, Account caller) throws Resour break; } } + }catch (ResourceUnavailableException ex) { + vpn.setState(prevState); + _remoteAccessVpnDao.update(vpn.getId(), vpn); + s_logger.debug("Failed to stop the vpn " + vpn.getId() + " , so reverted state to "+ + RemoteAccessVpn.State.Running); + success = false; } finally { if (success) { //Cleanup corresponding ports @@ -366,6 +373,7 @@ public void doInTransactionWithoutResult(TransactionStatus status) { } } } + return success; } @Override @@ -387,7 +395,7 @@ public VpnUser doInTransaction(TransactionStatus status) { if (owner == null) { throw new InvalidParameterValueException("Unable to add vpn user: Another operation active"); } - _accountMgr.checkAccess(caller, null, true, owner); + _accountMgr.checkAccess(caller, null, owner); //don't allow duplicated user names for the same account VpnUserVO vpnUser = _vpnUsersDao.findByAccountAndUsername(owner.getId(), username); @@ -416,7 +424,7 @@ public boolean removeVpnUser(long vpnOwnerId, String username, Account caller) { if (user == null) { throw new InvalidParameterValueException("Could not find vpn user " + username); } - _accountMgr.checkAccess(caller, null, true, user); + _accountMgr.checkAccess(caller, null, user); Transaction.execute(new TransactionCallbackNoReturn() { @Override @@ -435,7 +443,7 @@ public void doInTransactionWithoutResult(TransactionStatus status) { public List listVpnUsers(long vpnOwnerId, String userName) { Account caller = CallContext.current().getCallingAccount(); Account owner = _accountDao.findById(vpnOwnerId); - _accountMgr.checkAccess(caller, null, true, owner); + _accountMgr.checkAccess(caller, null, owner); return _vpnUsersDao.listByAccount(vpnOwnerId); } @@ -453,7 +461,7 @@ public RemoteAccessVpnVO startRemoteAccessVpn(long ipAddressId, boolean openFire openFirewall = false; } - _accountMgr.checkAccess(caller, null, true, vpn); + _accountMgr.checkAccess(caller, null, vpn); boolean started = false; try { @@ -499,7 +507,7 @@ public void doInTransactionWithoutResult(TransactionStatus status) { public boolean applyVpnUsers(long vpnOwnerId, String userName) { Account caller = CallContext.current().getCallingAccount(); Account owner = _accountDao.findById(vpnOwnerId); - _accountMgr.checkAccess(caller, null, true, owner); + _accountMgr.checkAccess(caller, null, owner); s_logger.debug("Applying vpn users for " + owner); List vpns = _remoteAccessVpnDao.findByAccount(vpnOwnerId); @@ -636,7 +644,7 @@ public Pair, Integer> searchForRemoteAccessVpns( throw new InvalidParameterValueException("Unable to list remote access vpns, IP address " + ipAddressId + " is not associated with an account."); } } - _accountMgr.checkAccess(caller, null, true, publicIp); + _accountMgr.checkAccess(caller, null, publicIp); } Ternary domainIdRecursiveListProject = new Ternary(cmd.getDomainId(), cmd.isRecursive(), null); @@ -747,7 +755,7 @@ public RemoteAccessVpn updateRemoteAccessVpn(long id, String customId, Boolean f throw new InvalidParameterValueException("Can't find remote access vpn by id " + id); } - _accountMgr.checkAccess(CallContext.current().getCallingAccount(), null, true, vpn); + _accountMgr.checkAccess(CallContext.current().getCallingAccount(), null, vpn); if (customId != null) { vpn.setUuid(customId); } diff --git a/server/src/com/cloud/network/vpn/Site2SiteVpnManagerImpl.java b/server/src/com/cloud/network/vpn/Site2SiteVpnManagerImpl.java index fdb5bbf124..a34aa6c7e8 100644 --- a/server/src/com/cloud/network/vpn/Site2SiteVpnManagerImpl.java +++ b/server/src/com/cloud/network/vpn/Site2SiteVpnManagerImpl.java @@ -24,6 +24,9 @@ import javax.inject.Inject; import javax.naming.ConfigurationException; +import org.apache.log4j.Logger; +import org.springframework.stereotype.Component; + import org.apache.cloudstack.api.command.user.vpn.CreateVpnConnectionCmd; import org.apache.cloudstack.api.command.user.vpn.CreateVpnCustomerGatewayCmd; import org.apache.cloudstack.api.command.user.vpn.CreateVpnGatewayCmd; @@ -37,8 +40,6 @@ import org.apache.cloudstack.api.command.user.vpn.UpdateVpnCustomerGatewayCmd; import org.apache.cloudstack.context.CallContext; import org.apache.cloudstack.framework.config.dao.ConfigurationDao; -import org.apache.log4j.Logger; -import org.springframework.stereotype.Component; import com.cloud.configuration.Config; import com.cloud.event.ActionEvent; @@ -124,7 +125,7 @@ public Site2SiteVpnGateway createVpnGateway(CreateVpnGatewayCmd cmd) { Account owner = _accountMgr.getAccount(cmd.getEntityOwnerId()); //Verify that caller can perform actions in behalf of vpc owner - _accountMgr.checkAccess(caller, null, false, owner); + _accountMgr.checkAccess(caller, null, owner); Long vpcId = cmd.getVpcId(); VpcVO vpc = _vpcDao.findById(vpcId); @@ -174,7 +175,7 @@ public Site2SiteCustomerGateway createCustomerGateway(CreateVpnCustomerGatewayCm Account owner = _accountMgr.getAccount(cmd.getEntityOwnerId()); //Verify that caller can perform actions in behalf of vpc owner - _accountMgr.checkAccess(caller, null, false, owner); + _accountMgr.checkAccess(caller, null, owner); String name = cmd.getName(); String gatewayIp = cmd.getGatewayIp(); @@ -242,34 +243,30 @@ public Site2SiteVpnConnection createVpnConnection(CreateVpnConnectionCmd cmd) th Account owner = _accountMgr.getAccount(cmd.getEntityOwnerId()); //Verify that caller can perform actions in behalf of vpc owner - _accountMgr.checkAccess(caller, null, false, owner); + _accountMgr.checkAccess(caller, null, owner); Long customerGatewayId = cmd.getCustomerGatewayId(); Site2SiteCustomerGateway customerGateway = _customerGatewayDao.findById(customerGatewayId); if (customerGateway == null) { throw new InvalidParameterValueException("Unable to found specified Site to Site VPN customer gateway " + customerGatewayId + " !"); } - _accountMgr.checkAccess(caller, null, false, customerGateway); + _accountMgr.checkAccess(caller, null, customerGateway); Long vpnGatewayId = cmd.getVpnGatewayId(); Site2SiteVpnGateway vpnGateway = _vpnGatewayDao.findById(vpnGatewayId); if (vpnGateway == null) { throw new InvalidParameterValueException("Unable to found specified Site to Site VPN gateway " + vpnGatewayId + " !"); } - _accountMgr.checkAccess(caller, null, false, vpnGateway); + _accountMgr.checkAccess(caller, null, vpnGateway); if (customerGateway.getAccountId() != vpnGateway.getAccountId() || customerGateway.getDomainId() != vpnGateway.getDomainId()) { throw new InvalidParameterValueException("VPN connection can only be esitablished between same account's VPN gateway and customer gateway!"); } if (_vpnConnectionDao.findByVpnGatewayIdAndCustomerGatewayId(vpnGatewayId, customerGatewayId) != null) { - throw new InvalidParameterValueException("The vpn connection with customer gateway id " + customerGatewayId + " or vpn gateway id " + vpnGatewayId + + throw new InvalidParameterValueException("The vpn connection with customer gateway id " + customerGatewayId + " and vpn gateway id " + vpnGatewayId + " already existed!"); } - if (_vpnConnectionDao.findByCustomerGatewayId(customerGatewayId) != null) { - throw new InvalidParameterValueException("The vpn connection with specified customer gateway id " + customerGatewayId + " already exists!"); - } - String[] cidrList = customerGateway.getGuestCidrList().split(","); // Remote sub nets cannot overlap VPC's sub net @@ -366,7 +363,7 @@ public boolean deleteCustomerGateway(DeleteVpnCustomerGatewayCmd cmd) { if (customerGateway == null) { throw new InvalidParameterValueException("Fail to find customer gateway with " + id + " !"); } - _accountMgr.checkAccess(caller, null, false, customerGateway); + _accountMgr.checkAccess(caller, null, customerGateway); return doDeleteCustomerGateway(customerGateway); } @@ -401,7 +398,7 @@ public boolean deleteVpnGateway(DeleteVpnGatewayCmd cmd) { throw new InvalidParameterValueException("Fail to find vpn gateway with " + id + " !"); } - _accountMgr.checkAccess(caller, null, false, vpnGateway); + _accountMgr.checkAccess(caller, null, vpnGateway); doDeleteVpnGateway(vpnGateway); return true; @@ -418,7 +415,7 @@ public Site2SiteCustomerGateway updateCustomerGateway(UpdateVpnCustomerGatewayCm if (gw == null) { throw new InvalidParameterValueException("Find to find customer gateway with id " + id); } - _accountMgr.checkAccess(caller, null, false, gw); + _accountMgr.checkAccess(caller, null, gw); List conns = _vpnConnectionDao.listByCustomerGatewayId(id); if (conns != null) { @@ -508,7 +505,7 @@ public boolean deleteVpnConnection(DeleteVpnConnectionCmd cmd) throws ResourceUn throw new InvalidParameterValueException("Fail to find site to site VPN connection " + id + " to delete!"); } - _accountMgr.checkAccess(caller, null, false, conn); + _accountMgr.checkAccess(caller, null, conn); if (conn.getState() == State.Connected) { stopVpnConnection(id); @@ -557,7 +554,7 @@ public Site2SiteVpnConnection resetVpnConnection(ResetVpnConnectionCmd cmd) thro if (conn == null) { throw new InvalidParameterValueException("Fail to find site to site VPN connection " + id + " to reset!"); } - _accountMgr.checkAccess(caller, null, false, conn); + _accountMgr.checkAccess(caller, null, conn); if (conn.getState() == State.Pending) { throw new InvalidParameterValueException("VPN connection " + id + " cannot be reseted when state is Pending!"); @@ -821,7 +818,7 @@ public Site2SiteVpnConnection updateVpnConnection(long id, String customId, Bool throw new InvalidParameterValueException("Fail to find site to site VPN connection " + id); } - _accountMgr.checkAccess(caller, null, false, conn); + _accountMgr.checkAccess(caller, null, conn); if (customId != null) { conn.setUuid(customId); } @@ -844,7 +841,7 @@ public Site2SiteVpnGateway updateVpnGateway(Long id, String customId, Boolean fo throw new InvalidParameterValueException("Fail to find vpn gateway with " + id); } - _accountMgr.checkAccess(caller, null, false, vpnGateway); + _accountMgr.checkAccess(caller, null, vpnGateway); if (customId != null) { vpnGateway.setUuid(customId); } diff --git a/server/src/com/cloud/projects/ProjectManagerImpl.java b/server/src/com/cloud/projects/ProjectManagerImpl.java index d10c059bd5..6aa5abc0e8 100755 --- a/server/src/com/cloud/projects/ProjectManagerImpl.java +++ b/server/src/com/cloud/projects/ProjectManagerImpl.java @@ -244,7 +244,7 @@ public Project enableProject(long projectId) { throw new InvalidParameterValueException("Unable to find project by id " + projectId); } - _accountMgr.checkAccess(caller, AccessType.ModifyProject, true, _accountMgr.getAccount(project.getProjectAccountId())); + _accountMgr.checkAccess(caller, AccessType.ModifyProject, _accountMgr.getAccount(project.getProjectAccountId())); //at this point enabling project doesn't require anything, so just update the state project.setState(State.Active); @@ -264,7 +264,7 @@ public boolean deleteProject(long projectId) { throw new InvalidParameterValueException("Unable to find project by id " + projectId); } - _accountMgr.checkAccess(ctx.getCallingAccount(), AccessType.ModifyProject, true, _accountMgr.getAccount(project.getProjectAccountId())); + _accountMgr.checkAccess(ctx.getCallingAccount(), AccessType.ModifyProject, _accountMgr.getAccount(project.getProjectAccountId())); return deleteProject(ctx.getCallingAccount(), ctx.getCallingUserId(), project); } @@ -463,7 +463,7 @@ public Project updateProject(final long projectId, final String displayText, fin } //verify permissions - _accountMgr.checkAccess(caller, AccessType.ModifyProject, true, _accountMgr.getAccount(project.getProjectAccountId())); + _accountMgr.checkAccess(caller, AccessType.ModifyProject, _accountMgr.getAccount(project.getProjectAccountId())); Transaction.execute(new TransactionCallbackWithExceptionNoReturn() { @Override @@ -550,7 +550,7 @@ public boolean addAccountToProject(long projectId, String accountName, String em } //verify permissions - only project owner can assign - _accountMgr.checkAccess(caller, AccessType.ModifyProject, true, _accountMgr.getAccount(project.getProjectAccountId())); + _accountMgr.checkAccess(caller, AccessType.ModifyProject, _accountMgr.getAccount(project.getProjectAccountId())); //Check if the account already added to the project ProjectAccount projectAccount = _projectAccountDao.findByProjectIdAccountId(projectId, account.getId()); @@ -628,7 +628,7 @@ public boolean deleteAccountFromProject(long projectId, String accountName) { } //verify permissions - _accountMgr.checkAccess(caller, AccessType.ModifyProject, true, _accountMgr.getAccount(project.getProjectAccountId())); + _accountMgr.checkAccess(caller, AccessType.ModifyProject, _accountMgr.getAccount(project.getProjectAccountId())); //Check if the account exists in the project ProjectAccount projectAccount = _projectAccountDao.findByProjectIdAccountId(projectId, account.getId()); @@ -750,7 +750,7 @@ public boolean updateInvitation(final long projectId, String accountName, String } //verify permissions - _accountMgr.checkAccess(caller, null, true, account); + _accountMgr.checkAccess(caller, null, account); accountId = account.getId(); } else { @@ -830,7 +830,7 @@ public Project activateProject(final long projectId) { } //verify permissions - _accountMgr.checkAccess(caller, AccessType.ModifyProject, true, _accountMgr.getAccount(project.getProjectAccountId())); + _accountMgr.checkAccess(caller, AccessType.ModifyProject, _accountMgr.getAccount(project.getProjectAccountId())); //allow project activation only when it's in Suspended state Project.State currentState = project.getState(); @@ -870,7 +870,7 @@ public Project suspendProject(long projectId) throws ConcurrentOperationExceptio throw ex; } - _accountMgr.checkAccess(caller, AccessType.ModifyProject, true, _accountMgr.getAccount(project.getProjectAccountId())); + _accountMgr.checkAccess(caller, AccessType.ModifyProject, _accountMgr.getAccount(project.getProjectAccountId())); if (suspendProject(project)) { s_logger.debug("Successfully suspended project id=" + projectId); @@ -1012,7 +1012,7 @@ public boolean deleteProjectInvitation(long id) { Project project = getProject(invitation.getProjectId()); //check permissions - only project owner can remove the invitations - _accountMgr.checkAccess(caller, AccessType.ModifyProject, true, _accountMgr.getAccount(project.getProjectAccountId())); + _accountMgr.checkAccess(caller, AccessType.ModifyProject, _accountMgr.getAccount(project.getProjectAccountId())); if (_projectInvitationDao.remove(id)) { s_logger.debug("Project Invitation id=" + id + " is removed"); diff --git a/server/src/com/cloud/resource/DiscovererBase.java b/server/src/com/cloud/resource/DiscovererBase.java index ae2a9c9f1e..871dc15cf6 100644 --- a/server/src/com/cloud/resource/DiscovererBase.java +++ b/server/src/com/cloud/resource/DiscovererBase.java @@ -16,18 +16,6 @@ // under the License. package com.cloud.resource; -import java.lang.reflect.Constructor; -import java.lang.reflect.InvocationTargetException; -import java.net.URL; -import java.util.HashMap; -import java.util.Map; - -import javax.inject.Inject; -import javax.naming.ConfigurationException; - -import org.apache.cloudstack.framework.config.dao.ConfigurationDao; -import org.apache.log4j.Logger; - import com.cloud.configuration.Config; import com.cloud.dc.ClusterVO; import com.cloud.dc.dao.ClusterDao; @@ -37,6 +25,16 @@ import com.cloud.network.NetworkModel; import com.cloud.utils.component.AdapterBase; import com.cloud.utils.net.UrlUtil; +import org.apache.cloudstack.framework.config.dao.ConfigurationDao; +import org.apache.log4j.Logger; + +import javax.inject.Inject; +import javax.naming.ConfigurationException; +import java.lang.reflect.Constructor; +import java.lang.reflect.InvocationTargetException; +import java.net.URL; +import java.util.HashMap; +import java.util.Map; public abstract class DiscovererBase extends AdapterBase implements Discoverer { protected Map _params; @@ -139,6 +137,8 @@ protected HashMap buildConfigParams(HostVO host) { 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("router.aggregation.command.each.timeout", _configDao.getValue(Config.RouterAggregationCommandEachTimeout.toString())); + return params; } diff --git a/server/src/com/cloud/resource/ResourceManagerImpl.java b/server/src/com/cloud/resource/ResourceManagerImpl.java index f9a59ba4eb..0f2ffc39b5 100755 --- a/server/src/com/cloud/resource/ResourceManagerImpl.java +++ b/server/src/com/cloud/resource/ResourceManagerImpl.java @@ -63,6 +63,7 @@ import com.cloud.agent.api.StartupRoutingCommand; import com.cloud.agent.api.UnsupportedAnswer; import com.cloud.agent.api.UpdateHostPasswordCommand; +import com.cloud.agent.api.VgpuTypesInfo; import com.cloud.agent.api.to.GPUDeviceTO; import com.cloud.agent.transport.Request; import com.cloud.api.ApiDBUtils; @@ -97,7 +98,6 @@ import com.cloud.exception.InvalidParameterValueException; import com.cloud.exception.PermissionDeniedException; import com.cloud.exception.ResourceInUseException; -import com.cloud.gpu.GPU.vGPUType; import com.cloud.gpu.HostGpuGroupsVO; import com.cloud.gpu.VGPUTypesVO; import com.cloud.gpu.dao.HostGpuGroupsDao; @@ -583,7 +583,7 @@ public List discoverHosts(AddHostCmd cmd) throws IllegalArgument } } - return discoverHostsFull(dcId, podId, clusterId, clusterName, url, username, password, cmd.getHypervisor(), hostTags, cmd.getFullUrlParams(), true); + return discoverHostsFull(dcId, podId, clusterId, clusterName, url, username, password, cmd.getHypervisor(), hostTags, cmd.getFullUrlParams(), false); } @Override @@ -1349,6 +1349,7 @@ public boolean configure(String name, Map params) throws Configu _gpuAvailability = _hostGpuGroupsDao.createSearchBuilder(); _gpuAvailability.and("hostId", _gpuAvailability.entity().getHostId(), Op.EQ); + _gpuAvailability.and("groupName", _gpuAvailability.entity().getGroupName(), Op.EQ); SearchBuilder join1 = _vgpuTypesDao.createSearchBuilder(); join1.and("vgpuType", join1.entity().getVgpuType(), Op.EQ); join1.and("remainingCapacity", join1.entity().getRemainingCapacity(), Op.GT); @@ -2501,21 +2502,26 @@ public List listAllUpAndEnabledHostsInOneZoneByHypervisor(HypervisorType } @Override - public List listAvailableGPUDevice(long hostId, String vgpuType) { - if (vgpuType == null) { - vgpuType = vGPUType.passthrough.getType(); - } + public boolean isHostGpuEnabled(long hostId) { + SearchCriteria sc = _gpuAvailability.create(); + sc.setParameters("hostId", hostId); + return _hostGpuGroupsDao.customSearch(sc, null).size() > 0 ? true : false; + } + + @Override + public List listAvailableGPUDevice(long hostId, String groupName, String vgpuType) { Filter searchFilter = new Filter(VGPUTypesVO.class, "remainingCapacity", false, null, null); SearchCriteria sc = _gpuAvailability.create(); sc.setParameters("hostId", hostId); + sc.setParameters("groupName", groupName); sc.setJoinParameters("groupId", "vgpuType", vgpuType); sc.setJoinParameters("groupId", "remainingCapacity", 0); return _hostGpuGroupsDao.customSearch(sc, searchFilter); } @Override - public boolean isGPUDeviceAvailable(long hostId, String vgpuType) { - if(!listAvailableGPUDevice(hostId, vgpuType).isEmpty()) { + public boolean isGPUDeviceAvailable(long hostId, String groupName, String vgpuType) { + if(!listAvailableGPUDevice(hostId, groupName, vgpuType).isEmpty()) { return true; } else { if (s_logger.isDebugEnabled()) { @@ -2526,13 +2532,13 @@ public boolean isGPUDeviceAvailable(long hostId, String vgpuType) { } @Override - public GPUDeviceTO getGPUDevice(long hostId, String vgpuType) { - HostGpuGroupsVO gpuDevice = listAvailableGPUDevice(hostId, vgpuType).get(0); + public GPUDeviceTO getGPUDevice(long hostId, String groupName, String vgpuType) { + HostGpuGroupsVO gpuDevice = listAvailableGPUDevice(hostId, groupName, vgpuType).get(0); return new GPUDeviceTO(gpuDevice.getGroupName(), vgpuType, null); } @Override - public void updateGPUDetails(long hostId, HashMap> groupDetails) { + public void updateGPUDetails(long hostId, HashMap> groupDetails) { // Update GPU group capacity TransactionLegacy txn = TransactionLegacy.currentTxn(); txn.start(); @@ -2542,7 +2548,7 @@ public void updateGPUDetails(long hostId, HashMap> } @Override - public HashMap> getGPUStatistics(HostVO host) { + public HashMap> getGPUStatistics(HostVO host) { Answer answer = _agentMgr.easySend(host.getId(), new GetGPUStatsCommand(host.getGuid(), host.getName())); if (answer != null && (answer instanceof UnsupportedAnswer)) { return null; diff --git a/server/src/com/cloud/resourcelimit/ResourceLimitManagerImpl.java b/server/src/com/cloud/resourcelimit/ResourceLimitManagerImpl.java index 74cfc31e74..0c0c588d96 100755 --- a/server/src/com/cloud/resourcelimit/ResourceLimitManagerImpl.java +++ b/server/src/com/cloud/resourcelimit/ResourceLimitManagerImpl.java @@ -325,6 +325,9 @@ public long findCorrectResourceLimitForAccount(long accountId, Long limit, Resou } Account account = _accountDao.findById(accountId); + if (account == null) { + return max; + } // Check if limit is configured for account if (limit != null) { @@ -458,7 +461,7 @@ public List searchForLimits(Long id, Long accountId, Long domai List limits = new ArrayList(); boolean isAccount = true; - if (!_accountMgr.isAdmin(caller.getType())) { + if (!_accountMgr.isAdmin(caller.getId())) { accountId = caller.getId(); domainId = null; } else { @@ -480,7 +483,7 @@ public List searchForLimits(Long id, Long accountId, Long domai return limits; } - _accountMgr.checkAccess(caller, null, true, account); + _accountMgr.checkAccess(caller, null, account); domainId = null; } } @@ -500,7 +503,7 @@ public List searchForLimits(Long id, Long accountId, Long domai if (id != null) { ResourceLimitVO vo = _resourceLimitDao.findById(id); if (vo.getAccountId() != null) { - _accountMgr.checkAccess(caller, null, true, _accountDao.findById(vo.getAccountId())); + _accountMgr.checkAccess(caller, null, _accountDao.findById(vo.getAccountId())); limits.add(vo); } else if (vo.getDomainId() != null) { _accountMgr.checkAccess(caller, _domainDao.findById(vo.getDomainId())); @@ -633,6 +636,9 @@ public ResourceLimitVO updateResourceLimit(Long accountId, Long domainId, Intege if (accountId != null) { Account account = _entityMgr.findById(Account.class, accountId); + if (account == null) { + throw new InvalidParameterValueException("Unable to find account " + accountId); + } if (account.getId() == Account.ACCOUNT_ID_SYSTEM) { throw new InvalidParameterValueException("Can't update system account"); } @@ -650,9 +656,9 @@ public ResourceLimitVO updateResourceLimit(Long accountId, Long domainId, Intege } if (account.getType() == Account.ACCOUNT_TYPE_PROJECT) { - _accountMgr.checkAccess(caller, AccessType.ModifyProject, true, account); + _accountMgr.checkAccess(caller, AccessType.ModifyProject, account); } else { - _accountMgr.checkAccess(caller, null, true, account); + _accountMgr.checkAccess(caller, null, account); } ownerType = ResourceOwnerType.Account; diff --git a/server/src/com/cloud/server/ConfigurationServerImpl.java b/server/src/com/cloud/server/ConfigurationServerImpl.java index b8da4c8831..ac0fe5e12c 100755 --- a/server/src/com/cloud/server/ConfigurationServerImpl.java +++ b/server/src/com/cloud/server/ConfigurationServerImpl.java @@ -211,8 +211,8 @@ public void persistDefaultValues() throws InternalErrorException { _configDao.update(Config.UseSecondaryStorageVm.key(), Config.UseSecondaryStorageVm.getCategory(), "true"); s_logger.debug("ConfigurationServer made secondary storage vm required."); - _configDao.update(Config.SecStorageEncryptCopy.key(), Config.SecStorageEncryptCopy.getCategory(), "true"); - s_logger.debug("ConfigurationServer made secondary storage copy encrypted."); + _configDao.update(Config.SecStorageEncryptCopy.key(), Config.SecStorageEncryptCopy.getCategory(), "false"); + s_logger.debug("ConfigurationServer made secondary storage copy encrypt set to false."); _configDao.update("secstorage.secure.copy.cert", "realhostip"); s_logger.debug("ConfigurationServer made secondary storage copy use realhostip."); @@ -1153,9 +1153,9 @@ public void doInTransactionWithoutResult(TransactionStatus status) { // Offering #5 NetworkOfferingVO defaultNetscalerNetworkOffering = - new NetworkOfferingVO(NetworkOffering.DefaultSharedEIPandELBNetworkOffering, - "Offering for Shared networks with Elastic IP and Elastic LB capabilities", TrafficType.Guest, false, true, null, null, true, - Availability.Optional, null, Network.GuestType.Shared, true, false, false, false, true, true, true, false, false, true, true, false, false); + new NetworkOfferingVO(NetworkOffering.DefaultSharedEIPandELBNetworkOffering, + "Offering for Shared networks with Elastic IP and Elastic LB capabilities", TrafficType.Guest, false, true, null, null, true, + Availability.Optional, null, Network.GuestType.Shared, true, false, false, false, true, true, true, false, false, true, true, false, false, false); defaultNetscalerNetworkOffering.setState(NetworkOffering.State.Enabled); defaultNetscalerNetworkOffering = _networkOfferingDao.persistDefaultNetworkOffering(defaultNetscalerNetworkOffering); diff --git a/server/src/com/cloud/server/ManagementServerImpl.java b/server/src/com/cloud/server/ManagementServerImpl.java index 073cf47a90..4a4c74a93c 100755 --- a/server/src/com/cloud/server/ManagementServerImpl.java +++ b/server/src/com/cloud/server/ManagementServerImpl.java @@ -16,9 +16,7 @@ // under the License. package com.cloud.server; -import java.io.UnsupportedEncodingException; import java.lang.reflect.Field; -import java.net.URLDecoder; import java.util.ArrayList; import java.util.Arrays; import java.util.Calendar; @@ -40,9 +38,6 @@ import javax.inject.Inject; import javax.naming.ConfigurationException; -import org.apache.commons.codec.binary.Base64; -import org.apache.log4j.Logger; - import org.apache.cloudstack.acl.ControlledEntity; import org.apache.cloudstack.affinity.AffinityGroupProcessor; import org.apache.cloudstack.affinity.dao.AffinityGroupVMMapDao; @@ -51,8 +46,12 @@ import org.apache.cloudstack.api.command.admin.account.DeleteAccountCmd; import org.apache.cloudstack.api.command.admin.account.DisableAccountCmd; import org.apache.cloudstack.api.command.admin.account.EnableAccountCmd; +import org.apache.cloudstack.api.command.admin.account.ListAccountsCmdByAdmin; import org.apache.cloudstack.api.command.admin.account.LockAccountCmd; import org.apache.cloudstack.api.command.admin.account.UpdateAccountCmd; +import org.apache.cloudstack.api.command.admin.address.AssociateIPAddrCmdByAdmin; +import org.apache.cloudstack.api.command.admin.address.ListPublicIpAddressesCmdByAdmin; +import org.apache.cloudstack.api.command.admin.affinitygroup.UpdateVMAffinityGroupCmdByAdmin; import org.apache.cloudstack.api.command.admin.alert.GenerateAlertCmd; import org.apache.cloudstack.api.command.admin.autoscale.CreateCounterCmd; import org.apache.cloudstack.api.command.admin.autoscale.DeleteCounterCmd; @@ -94,8 +93,16 @@ import org.apache.cloudstack.api.command.admin.internallb.ListInternalLoadBalancerElementsCmd; import org.apache.cloudstack.api.command.admin.internallb.StartInternalLBVMCmd; import org.apache.cloudstack.api.command.admin.internallb.StopInternalLBVMCmd; +import org.apache.cloudstack.api.command.admin.iso.AttachIsoCmdByAdmin; +import org.apache.cloudstack.api.command.admin.iso.CopyIsoCmdByAdmin; +import org.apache.cloudstack.api.command.admin.iso.DetachIsoCmdByAdmin; +import org.apache.cloudstack.api.command.admin.iso.ListIsoPermissionsCmdByAdmin; +import org.apache.cloudstack.api.command.admin.iso.ListIsosCmdByAdmin; +import org.apache.cloudstack.api.command.admin.iso.RegisterIsoCmdByAdmin; +import org.apache.cloudstack.api.command.admin.loadbalancer.ListLoadBalancerRuleInstancesCmdByAdmin; import org.apache.cloudstack.api.command.admin.network.AddNetworkDeviceCmd; import org.apache.cloudstack.api.command.admin.network.AddNetworkServiceProviderCmd; +import org.apache.cloudstack.api.command.admin.network.CreateNetworkCmdByAdmin; import org.apache.cloudstack.api.command.admin.network.CreateNetworkOfferingCmd; import org.apache.cloudstack.api.command.admin.network.CreatePhysicalNetworkCmd; import org.apache.cloudstack.api.command.admin.network.CreateStorageNetworkIpRangeCmd; @@ -109,10 +116,12 @@ import org.apache.cloudstack.api.command.admin.network.ListNetworkDeviceCmd; import org.apache.cloudstack.api.command.admin.network.ListNetworkIsolationMethodsCmd; import org.apache.cloudstack.api.command.admin.network.ListNetworkServiceProvidersCmd; +import org.apache.cloudstack.api.command.admin.network.ListNetworksCmdByAdmin; import org.apache.cloudstack.api.command.admin.network.ListPhysicalNetworksCmd; import org.apache.cloudstack.api.command.admin.network.ListStorageNetworkIpRangeCmd; import org.apache.cloudstack.api.command.admin.network.ListSupportedNetworkServicesCmd; import org.apache.cloudstack.api.command.admin.network.ReleaseDedicatedGuestVlanRangeCmd; +import org.apache.cloudstack.api.command.admin.network.UpdateNetworkCmdByAdmin; import org.apache.cloudstack.api.command.admin.network.UpdateNetworkOfferingCmd; import org.apache.cloudstack.api.command.admin.network.UpdateNetworkServiceProviderCmd; import org.apache.cloudstack.api.command.admin.network.UpdatePhysicalNetworkCmd; @@ -178,7 +187,12 @@ 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.template.CopyTemplateCmdByAdmin; +import org.apache.cloudstack.api.command.admin.template.CreateTemplateCmdByAdmin; +import org.apache.cloudstack.api.command.admin.template.ListTemplatePermissionsCmdByAdmin; +import org.apache.cloudstack.api.command.admin.template.ListTemplatesCmdByAdmin; import org.apache.cloudstack.api.command.admin.template.PrepareTemplateCmd; +import org.apache.cloudstack.api.command.admin.template.RegisterTemplateCmdByAdmin; import org.apache.cloudstack.api.command.admin.usage.AddTrafficMonitorCmd; import org.apache.cloudstack.api.command.admin.usage.AddTrafficTypeCmd; import org.apache.cloudstack.api.command.admin.usage.DeleteTrafficMonitorCmd; @@ -204,20 +218,47 @@ import org.apache.cloudstack.api.command.admin.vlan.DeleteVlanIpRangeCmd; import org.apache.cloudstack.api.command.admin.vlan.ListVlanIpRangesCmd; import org.apache.cloudstack.api.command.admin.vlan.ReleasePublicIpRangeCmd; +import org.apache.cloudstack.api.command.admin.vm.AddNicToVMCmdByAdmin; import org.apache.cloudstack.api.command.admin.vm.AssignVMCmd; +import org.apache.cloudstack.api.command.admin.vm.DeployVMCmdByAdmin; +import org.apache.cloudstack.api.command.admin.vm.DestroyVMCmdByAdmin; import org.apache.cloudstack.api.command.admin.vm.ExpungeVMCmd; import org.apache.cloudstack.api.command.admin.vm.GetVMUserDataCmd; import org.apache.cloudstack.api.command.admin.vm.ListVMsCmdByAdmin; 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.RebootVMCmdByAdmin; import org.apache.cloudstack.api.command.admin.vm.RecoverVMCmd; +import org.apache.cloudstack.api.command.admin.vm.RemoveNicFromVMCmdByAdmin; +import org.apache.cloudstack.api.command.admin.vm.ResetVMPasswordCmdByAdmin; +import org.apache.cloudstack.api.command.admin.vm.ResetVMSSHKeyCmdByAdmin; +import org.apache.cloudstack.api.command.admin.vm.RestoreVMCmdByAdmin; +import org.apache.cloudstack.api.command.admin.vm.ScaleVMCmdByAdmin; +import org.apache.cloudstack.api.command.admin.vm.StartVMCmdByAdmin; +import org.apache.cloudstack.api.command.admin.vm.StopVMCmdByAdmin; +import org.apache.cloudstack.api.command.admin.vm.UpdateDefaultNicForVMCmdByAdmin; +import org.apache.cloudstack.api.command.admin.vm.UpdateVMCmdByAdmin; +import org.apache.cloudstack.api.command.admin.vm.UpgradeVMCmdByAdmin; +import org.apache.cloudstack.api.command.admin.vmsnapshot.RevertToVMSnapshotCmdByAdmin; +import org.apache.cloudstack.api.command.admin.volume.AttachVolumeCmdByAdmin; +import org.apache.cloudstack.api.command.admin.volume.CreateVolumeCmdByAdmin; +import org.apache.cloudstack.api.command.admin.volume.DetachVolumeCmdByAdmin; +import org.apache.cloudstack.api.command.admin.volume.ListVolumesCmdByAdmin; +import org.apache.cloudstack.api.command.admin.volume.MigrateVolumeCmdByAdmin; +import org.apache.cloudstack.api.command.admin.volume.ResizeVolumeCmdByAdmin; +import org.apache.cloudstack.api.command.admin.volume.UpdateVolumeCmdByAdmin; +import org.apache.cloudstack.api.command.admin.volume.UploadVolumeCmdByAdmin; import org.apache.cloudstack.api.command.admin.vpc.CreatePrivateGatewayCmd; +import org.apache.cloudstack.api.command.admin.vpc.CreateVPCCmdByAdmin; import org.apache.cloudstack.api.command.admin.vpc.CreateVPCOfferingCmd; import org.apache.cloudstack.api.command.admin.vpc.DeletePrivateGatewayCmd; import org.apache.cloudstack.api.command.admin.vpc.DeleteVPCOfferingCmd; +import org.apache.cloudstack.api.command.admin.vpc.ListVPCsCmdByAdmin; +import org.apache.cloudstack.api.command.admin.vpc.UpdateVPCCmdByAdmin; import org.apache.cloudstack.api.command.admin.vpc.UpdateVPCOfferingCmd; 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.ListZonesCmdByAdmin; 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; @@ -302,6 +343,8 @@ import org.apache.cloudstack.api.command.user.loadbalancer.RemoveCertFromLoadBalancerCmd; import org.apache.cloudstack.api.command.user.loadbalancer.RemoveFromLoadBalancerRuleCmd; import org.apache.cloudstack.api.command.user.loadbalancer.UpdateApplicationLoadBalancerCmd; +import org.apache.cloudstack.api.command.user.loadbalancer.UpdateLBHealthCheckPolicyCmd; +import org.apache.cloudstack.api.command.user.loadbalancer.UpdateLBStickinessPolicyCmd; import org.apache.cloudstack.api.command.user.loadbalancer.UpdateLoadBalancerRuleCmd; import org.apache.cloudstack.api.command.user.loadbalancer.UploadSslCertCmd; import org.apache.cloudstack.api.command.user.nat.CreateIpForwardingRuleCmd; @@ -464,6 +507,8 @@ import org.apache.cloudstack.storage.datastore.db.PrimaryDataStoreDao; import org.apache.cloudstack.storage.datastore.db.StoragePoolVO; import org.apache.cloudstack.utils.identity.ManagementServerNode; +import org.apache.commons.codec.binary.Base64; +import org.apache.log4j.Logger; import com.cloud.agent.AgentManager; import com.cloud.agent.api.GetVncPortAnswer; @@ -907,7 +952,7 @@ public boolean archiveEvents(ArchiveEventsCmd cmd) { List events = _eventDao.listToArchiveOrDeleteEvents(ids, cmd.getType(), cmd.getStartDate(), cmd.getEndDate(), permittedAccountIds); ControlledEntity[] sameOwnerEvents = events.toArray(new ControlledEntity[events.size()]); - _accountMgr.checkAccess(CallContext.current().getCallingAccount(), null, false, sameOwnerEvents); + _accountMgr.checkAccess(CallContext.current().getCallingAccount(), null, sameOwnerEvents); if (ids != null && events.size() < ids.size()) { result = false; @@ -934,7 +979,7 @@ public boolean deleteEvents(DeleteEventsCmd cmd) { List events = _eventDao.listToArchiveOrDeleteEvents(ids, cmd.getType(), cmd.getStartDate(), cmd.getEndDate(), permittedAccountIds); ControlledEntity[] sameOwnerEvents = events.toArray(new ControlledEntity[events.size()]); - _accountMgr.checkAccess(CallContext.current().getCallingAccount(), null, false, sameOwnerEvents); + _accountMgr.checkAccess(CallContext.current().getCallingAccount(), null, sameOwnerEvents); if (ids != null && events.size() < ids.size()) { result = false; @@ -1984,7 +2029,7 @@ else if (osStdName != null) { throw new InvalidParameterValueException("Unable to find the guest OS by name or UUID"); } //check for duplicates - GuestOSHypervisorVO duplicate = _guestOSHypervisorDao.findByOsIdAndHypervisor(osTypeId.longValue(), hypervisorType.toString(), hypervisorVersion); + GuestOSHypervisorVO duplicate = _guestOSHypervisorDao.findByOsIdAndHypervisorAndUserDefined(guestOs.getId(), hypervisorType.toString(), hypervisorVersion, true); if (duplicate != null) { throw new InvalidParameterValueException("Mapping from hypervisor : " + hypervisorType.toString() + ", version : " + hypervisorVersion + " and guest OS : " @@ -1995,6 +2040,7 @@ else if (osStdName != null) { guestOsMapping.setGuestOsName(osNameForHypervisor); guestOsMapping.setHypervisorType(hypervisorType.toString()); guestOsMapping.setHypervisorVersion(hypervisorVersion); + guestOsMapping.setIsUserDefined(true); return _guestOSHypervisorDao.persist(guestOsMapping); } @@ -2027,6 +2073,7 @@ public GuestOS addGuestOs(AddGuestOsCmd cmd) { guestOsVo.setCategoryId(categoryId.longValue()); guestOsVo.setDisplayName(displayName); guestOsVo.setName(name); + guestOsVo.setIsUserDefined(true); return _guestOSDao.persist(guestOsVo); } @@ -2049,6 +2096,10 @@ public GuestOS updateGuestOs(UpdateGuestOsCmd cmd) { throw new InvalidParameterValueException("Guest OS not found. Please specify a valid ID for the Guest OS"); } + if (!guestOsHandle.getIsUserDefined()) { + throw new InvalidParameterValueException("Unable to modify system defined guest OS"); + } + //Check if update is needed if (displayName.equals(guestOsHandle.getDisplayName())) { return guestOsHandle; @@ -2080,6 +2131,10 @@ public boolean removeGuestOs(RemoveGuestOsCmd cmd) { throw new InvalidParameterValueException("Guest OS not found. Please specify a valid ID for the Guest OS"); } + if (!guestOs.getIsUserDefined()) { + throw new InvalidParameterValueException("Unable to remove system defined guest OS"); + } + return _guestOSDao.remove(id); } @@ -2096,6 +2151,10 @@ public GuestOSHypervisor updateGuestOsMapping(UpdateGuestOsMappingCmd cmd) { throw new InvalidParameterValueException("Guest OS Mapping not found. Please specify a valid ID for the Guest OS Mapping"); } + if (!guestOsHypervisorHandle.getIsUserDefined()) { + throw new InvalidParameterValueException("Unable to modify system defined Guest OS mapping"); + } + GuestOSHypervisorVO guestOsHypervisor = _guestOSHypervisorDao.createForUpdate(id); guestOsHypervisor.setGuestOsName(osNameForHypervisor); if (_guestOSHypervisorDao.update(id, guestOsHypervisor)) { @@ -2117,6 +2176,10 @@ public boolean removeGuestOsMapping(RemoveGuestOsMappingCmd cmd) { throw new InvalidParameterValueException("Guest OS Mapping not found. Please specify a valid ID for the Guest OS Mapping"); } + if (!guestOsHypervisorHandle.getIsUserDefined()) { + throw new InvalidParameterValueException("Unable to remove system defined Guest OS mapping"); + } + return _guestOSHypervisorDao.removeGuestOsMapping(id); } @@ -2710,6 +2773,7 @@ public List> getCommands() { cmdList.add(ListIpForwardingRulesCmd.class); cmdList.add(CreateNetworkACLCmd.class); cmdList.add(CreateNetworkCmd.class); + cmdList.add(CreateNetworkCmdByAdmin.class); cmdList.add(DeleteNetworkACLCmd.class); cmdList.add(DeleteNetworkCmd.class); cmdList.add(ListNetworkACLsCmd.class); @@ -2770,7 +2834,6 @@ public List> getCommands() { cmdList.add(ExpungeVMCmd.class); cmdList.add(GetVMPasswordCmd.class); cmdList.add(ListVMsCmd.class); - cmdList.add(ListVMsCmdByAdmin.class); cmdList.add(ScaleVMCmd.class); cmdList.add(RebootVMCmd.class); cmdList.add(RemoveNicFromVMCmd.class); @@ -2898,6 +2961,57 @@ public List> getCommands() { cmdList.add(UpdateRemoteAccessVpnCmd.class); cmdList.add(UpdateVpnConnectionCmd.class); cmdList.add(UpdateVpnGatewayCmd.class); + // separated admin commands + cmdList.add(ListAccountsCmdByAdmin.class); + cmdList.add(ListZonesCmdByAdmin.class); + cmdList.add(ListTemplatesCmdByAdmin.class); + cmdList.add(CreateTemplateCmdByAdmin.class); + cmdList.add(CopyTemplateCmdByAdmin.class); + cmdList.add(RegisterTemplateCmdByAdmin.class); + cmdList.add(ListTemplatePermissionsCmdByAdmin.class); + cmdList.add(RegisterIsoCmdByAdmin.class); + cmdList.add(CopyIsoCmdByAdmin.class); + cmdList.add(ListIsosCmdByAdmin.class); + cmdList.add(AttachIsoCmdByAdmin.class); + cmdList.add(DetachIsoCmdByAdmin.class); + cmdList.add(ListIsoPermissionsCmdByAdmin.class); + cmdList.add(UpdateVMAffinityGroupCmdByAdmin.class); + cmdList.add(AddNicToVMCmdByAdmin.class); + cmdList.add(RemoveNicFromVMCmdByAdmin.class); + cmdList.add(UpdateDefaultNicForVMCmdByAdmin.class); + cmdList.add(ListLoadBalancerRuleInstancesCmdByAdmin.class); + cmdList.add(DeployVMCmdByAdmin.class); + cmdList.add(DestroyVMCmdByAdmin.class); + cmdList.add(RebootVMCmdByAdmin.class); + cmdList.add(ResetVMPasswordCmdByAdmin.class); + cmdList.add(ResetVMSSHKeyCmdByAdmin.class); + cmdList.add(RestoreVMCmdByAdmin.class); + cmdList.add(ScaleVMCmdByAdmin.class); + cmdList.add(StartVMCmdByAdmin.class); + cmdList.add(StopVMCmdByAdmin.class); + cmdList.add(UpdateVMCmdByAdmin.class); + cmdList.add(UpgradeVMCmdByAdmin.class); + cmdList.add(RevertToVMSnapshotCmdByAdmin.class); + cmdList.add(ListVMsCmdByAdmin.class); + cmdList.add(AttachVolumeCmdByAdmin.class); + cmdList.add(CreateVolumeCmdByAdmin.class); + cmdList.add(DetachVolumeCmdByAdmin.class); + cmdList.add(MigrateVolumeCmdByAdmin.class); + cmdList.add(ResizeVolumeCmdByAdmin.class); + cmdList.add(UpdateVolumeCmdByAdmin.class); + cmdList.add(UploadVolumeCmdByAdmin.class); + cmdList.add(ListVolumesCmdByAdmin.class); + cmdList.add(AssociateIPAddrCmdByAdmin.class); + cmdList.add(ListPublicIpAddressesCmdByAdmin.class); + cmdList.add(CreateNetworkCmdByAdmin.class); + cmdList.add(UpdateNetworkCmdByAdmin.class); + cmdList.add(ListNetworksCmdByAdmin.class); + cmdList.add(CreateVPCCmdByAdmin.class); + cmdList.add(ListVPCsCmdByAdmin.class); + cmdList.add(UpdateVPCCmdByAdmin.class); + cmdList.add(UpdateLBStickinessPolicyCmd.class); + cmdList.add(UpdateLBHealthCheckPolicyCmd.class); + return cmdList; } @@ -3201,7 +3315,7 @@ public ArrayList getCloudIdentifierResponse(long userId) { } // check permissions - _accountMgr.checkAccess(caller, null, true, _accountMgr.getAccount(user.getAccountId())); + _accountMgr.checkAccess(caller, null, _accountMgr.getAccount(user.getAccountId())); String cloudIdentifier = _configDao.getValue("cloud.identifier"); if (cloudIdentifier == null) { @@ -3248,6 +3362,7 @@ public Map listCapabilities(ListCapabilitiesCmd cmd) { } } + long diskOffMinSize = VolumeOrchestrationService.CustomDiskOfferingMinSize.value(); long diskOffMaxSize = VolumeOrchestrationService.CustomDiskOfferingMaxSize.value(); KVMSnapshotEnabled = Boolean.parseBoolean(_configDao.getValue("KVM.snapshot.enabled")); @@ -3271,6 +3386,7 @@ public Map listCapabilities(ListCapabilitiesCmd cmd) { capabilities.put("supportELB", supportELB); capabilities.put("projectInviteRequired", _projectMgr.projectInviteRequired()); capabilities.put("allowusercreateprojects", _projectMgr.allowUserToCreateProject()); + capabilities.put("customDiskOffMinSize", diskOffMinSize); capabilities.put("customDiskOffMaxSize", diskOffMaxSize); capabilities.put("regionSecondaryEnabled", regionSecondaryEnabled); capabilities.put("KVMSnapshotEnabled", KVMSnapshotEnabled); @@ -3306,7 +3422,7 @@ public InstanceGroupVO updateVmGroup(UpdateVMGroupCmd cmd) { throw ex; } - _accountMgr.checkAccess(caller, null, true, group); + _accountMgr.checkAccess(caller, null, group); // Check if name is already in use by this account (exclude this group) boolean isNameInUse = _vmGroupDao.isNameInUse(group.getAccountId(), groupName); @@ -3352,16 +3468,6 @@ public String uploadCertificate(UploadCustomCertificateCmd cmd) { String certificate = cmd.getCertificate(); String key = cmd.getPrivateKey(); - try { - if (certificate != null) { - certificate = URLDecoder.decode(certificate, "UTF-8"); - } - if (key != null) { - key = URLDecoder.decode(key, "UTF-8"); - } - } catch (UnsupportedEncodingException e) { - } finally { - } if (cmd.getPrivateKey() != null && !_ksMgr.validateCertificate(certificate, key, cmd.getDomainSuffix())) { throw new InvalidParameterValueException("Failed to pass certificate validation check"); @@ -3369,16 +3475,20 @@ public String uploadCertificate(UploadCustomCertificateCmd cmd) { if (cmd.getPrivateKey() != null) { _ksMgr.saveCertificate(ConsoleProxyManager.CERTIFICATE_NAME, certificate, key, cmd.getDomainSuffix()); + + // Reboot ssvm here since private key is present - meaning server cert being passed + List alreadyRunning = _secStorageVmDao.getSecStorageVmListInStates(null, State.Running, State.Migrating, State.Starting); + for (SecondaryStorageVmVO ssVmVm : alreadyRunning) { + _secStorageVmMgr.rebootSecStorageVm(ssVmVm.getId()); + } } else { _ksMgr.saveCertificate(cmd.getAlias(), certificate, cmd.getCertIndex(), cmd.getDomainSuffix()); } _consoleProxyMgr.setManagementState(ConsoleProxyManagementState.ResetSuspending); - List alreadyRunning = _secStorageVmDao.getSecStorageVmListInStates(null, State.Running, State.Migrating, State.Starting); - for (SecondaryStorageVmVO ssVmVm : alreadyRunning) { - _secStorageVmMgr.rebootSecStorageVm(ssVmVm.getId()); - } - return "Certificate has been updated, we will stop all running console proxy VMs and secondary storage VMs to propagate the new certificate, please give a few minutes for console access service to be up again"; + return "Certificate has been successfully updated, if its the server certificate we would reboot all " + + "running console proxy VMs and secondary storage VMs to propagate the new certificate, " + + "please give a few minutes for console access and storage services service to be up and working again"; } @Override @@ -3551,7 +3661,7 @@ public String getVMPassword(GetVMPasswordCmd cmd) { } // make permission check - _accountMgr.checkAccess(caller, null, true, vm); + _accountMgr.checkAccess(caller, null, vm); _userVmDao.loadDetails(vm); String password = vm.getDetail("Encrypted.Password"); @@ -3724,7 +3834,7 @@ private VirtualMachine upgradeStoppedSystemVm(Long systemVmId, Long serviceOffer throw new InvalidParameterValueException("Unable to find SystemVm with id " + systemVmId); } - _accountMgr.checkAccess(caller, null, true, systemVm); + _accountMgr.checkAccess(caller, null, systemVm); // Check that the specified service offering ID is valid ServiceOfferingVO newServiceOffering = _offeringDao.findById(serviceOfferingId); diff --git a/server/src/com/cloud/server/StatsCollector.java b/server/src/com/cloud/server/StatsCollector.java index 50aa93cd5e..29ace93202 100755 --- a/server/src/com/cloud/server/StatsCollector.java +++ b/server/src/com/cloud/server/StatsCollector.java @@ -49,6 +49,7 @@ import com.cloud.agent.api.GetStorageStatsCommand; import com.cloud.agent.api.HostStatsEntry; import com.cloud.agent.api.PerformanceMonitorCommand; +import com.cloud.agent.api.VgpuTypesInfo; import com.cloud.agent.api.VmDiskStatsEntry; import com.cloud.agent.api.VmStatsEntry; import com.cloud.cluster.ManagementServerHostVO; @@ -342,7 +343,7 @@ protected void runInContext() { gpuEnabledHosts = hosts; } for (HostVO host : gpuEnabledHosts) { - HashMap> groupDetails = _resourceMgr.getGPUStatistics(host); + HashMap> groupDetails = _resourceMgr.getGPUStatistics(host); if (groupDetails != null) { _resourceMgr.updateGPUDetails(host.getId(), groupDetails); } diff --git a/server/src/com/cloud/servlet/ConsoleProxyServlet.java b/server/src/com/cloud/servlet/ConsoleProxyServlet.java index 60f32cf4bb..16d7a3292f 100644 --- a/server/src/com/cloud/servlet/ConsoleProxyServlet.java +++ b/server/src/com/cloud/servlet/ConsoleProxyServlet.java @@ -522,7 +522,7 @@ private boolean checkSessionPermision(HttpServletRequest req, long vmId, Account switch (vm.getType()) { case User: try { - _accountMgr.checkAccess(accountObj, null, true, vm); + _accountMgr.checkAccess(accountObj, null, vm); } catch (PermissionDeniedException ex) { if (_accountMgr.isNormalUser(accountObj.getId())) { if (s_logger.isDebugEnabled()) { diff --git a/server/src/com/cloud/storage/StorageManagerImpl.java b/server/src/com/cloud/storage/StorageManagerImpl.java index 3b29b33624..c27a457f0e 100755 --- a/server/src/com/cloud/storage/StorageManagerImpl.java +++ b/server/src/com/cloud/storage/StorageManagerImpl.java @@ -618,7 +618,7 @@ public PrimaryDataStoreInfo createPool(CreateStoragePoolCmd cmd) throws Resource } else { throw new InvalidParameterValueException("Missing parameter hypervisor. Hypervisor type is required to create zone wide primary storage."); } - if (hypervisorType != HypervisorType.KVM && hypervisorType != HypervisorType.VMware && hypervisorType != HypervisorType.Any) { + if (hypervisorType != HypervisorType.KVM && hypervisorType != HypervisorType.VMware && hypervisorType != HypervisorType.Hyperv && hypervisorType != HypervisorType.Any) { throw new InvalidParameterValueException("zone wide storage pool is not supported for hypervisor type " + hypervisor); } } diff --git a/server/src/com/cloud/storage/VolumeApiServiceImpl.java b/server/src/com/cloud/storage/VolumeApiServiceImpl.java index 30b5479b63..6db3a2d97b 100644 --- a/server/src/com/cloud/storage/VolumeApiServiceImpl.java +++ b/server/src/com/cloud/storage/VolumeApiServiceImpl.java @@ -28,6 +28,7 @@ import org.apache.log4j.Logger; +import org.apache.cloudstack.acl.SecurityChecker.AccessType; import org.apache.cloudstack.api.command.user.volume.AttachVolumeCmd; import org.apache.cloudstack.api.command.user.volume.CreateVolumeCmd; import org.apache.cloudstack.api.command.user.volume.DetachVolumeCmd; @@ -272,7 +273,7 @@ public VolumeVO uploadVolume(UploadVolumeCmd cmd) throws ResourceAllocationExcep private boolean validateVolume(Account caller, long ownerId, Long zoneId, String volumeName, String url, String format) throws ResourceAllocationException { // permission check - _accountMgr.checkAccess(caller, null, true, _accountMgr.getActiveAccountById(ownerId)); + _accountMgr.checkAccess(caller, null, _accountMgr.getActiveAccountById(ownerId)); // Check that the resource limit for volumes won't be exceeded _resourceLimitMgr.checkResourceLimit(_accountMgr.getAccount(ownerId), ResourceType.volume); @@ -378,13 +379,15 @@ public VolumeVO allocVolume(CreateVolumeCmd cmd) throws ResourceAllocationExcept Account caller = CallContext.current().getCallingAccount(); long ownerId = cmd.getEntityOwnerId(); + Account owner = _accountMgr.getActiveAccountById(ownerId); Boolean displayVolume = cmd.getDisplayVolume(); // permission check - _accountMgr.checkAccess(caller, null, true, _accountMgr.getActiveAccountById(ownerId)); + _accountMgr.checkAccess(caller, null, owner); if (displayVolume == null) { displayVolume = true; + } else { if (!_accountMgr.isRootAdmin(caller.getId())) { throw new PermissionDeniedException("Cannot update parameter displayvolume, only admin permitted "); @@ -392,7 +395,7 @@ public VolumeVO allocVolume(CreateVolumeCmd cmd) throws ResourceAllocationExcept } // Check that the resource limit for volumes won't be exceeded - _resourceLimitMgr.checkResourceLimit(_accountMgr.getAccount(ownerId), ResourceType.volume, displayVolume); + _resourceLimitMgr.checkResourceLimit(owner, ResourceType.volume, displayVolume); Long zoneId = cmd.getZoneId(); Long diskOfferingId = null; @@ -508,9 +511,6 @@ public VolumeVO allocVolume(CreateVolumeCmd cmd) throws ResourceAllocationExcept size = snapshotCheck.getSize(); // ; disk offering is used for tags // purposes - // check snapshot permissions - _accountMgr.checkAccess(caller, null, true, snapshotCheck); - // one step operation - create volume in VM's cluster and attach it // to the VM Long vmId = cmd.getVirtualMachineId(); @@ -525,15 +525,12 @@ public VolumeVO allocVolume(CreateVolumeCmd cmd) throws ResourceAllocationExcept if (vm.getState() != State.Running && vm.getState() != State.Stopped) { throw new InvalidParameterValueException("Please specify a VM that is either running or stopped."); } - - // permission check - _accountMgr.checkAccess(caller, null, false, vm); } } // Check that the resource limit for primary storage won't be exceeded - _resourceLimitMgr.checkResourceLimit(_accountMgr.getAccount(ownerId), ResourceType.primary_storage, displayVolume, new Long(size)); + _resourceLimitMgr.checkResourceLimit(owner, ResourceType.primary_storage, displayVolume, new Long(size)); // Verify that zone exists DataCenterVO zone = _dcDao.findById(zoneId); @@ -557,13 +554,13 @@ public VolumeVO allocVolume(CreateVolumeCmd cmd) throws ResourceAllocationExcept userSpecifiedName = getRandomVolumeName(); } - VolumeVO volume = commitVolume(cmd, caller, ownerId, displayVolume, zoneId, diskOfferingId, size, minIops, maxIops, parentVolume, userSpecifiedName, + VolumeVO volume = commitVolume(cmd, caller, owner, displayVolume, zoneId, diskOfferingId, size, minIops, maxIops, parentVolume, userSpecifiedName, _uuidMgr.generateUuid(Volume.class, cmd.getCustomId())); return volume; } - private VolumeVO commitVolume(final CreateVolumeCmd cmd, final Account caller, final long ownerId, final Boolean displayVolume, final Long zoneId, + private VolumeVO commitVolume(final CreateVolumeCmd cmd, final Account caller, final Account owner, final Boolean displayVolume, final Long zoneId, final Long diskOfferingId, final Long size, final Long minIops, final Long maxIops, final VolumeVO parentVolume, final String userSpecifiedName, final String uuid) { return Transaction.execute(new TransactionCallback() { @Override @@ -573,15 +570,14 @@ public VolumeVO doInTransaction(TransactionStatus status) { volume.setUuid(uuid); volume.setDataCenterId(zoneId); volume.setPodId(null); - volume.setAccountId(ownerId); - volume.setDomainId(((caller == null) ? Domain.ROOT_DOMAIN : caller.getDomainId())); + volume.setAccountId(owner.getId()); + volume.setDomainId(owner.getDomainId()); volume.setDiskOfferingId(diskOfferingId); volume.setSize(size); volume.setMinIops(minIops); volume.setMaxIops(maxIops); volume.setInstanceId(null); volume.setUpdated(new Date()); - volume.setDomainId((caller == null) ? Domain.ROOT_DOMAIN : caller.getDomainId()); volume.setDisplayVolume(displayVolume); if (parentVolume != null) { volume.setTemplateId(parentVolume.getTemplateId()); @@ -591,10 +587,10 @@ public VolumeVO doInTransaction(TransactionStatus status) { } volume = _volsDao.persist(volume); - if (cmd.getSnapshotId() == null) { + if (cmd.getSnapshotId() == null && displayVolume) { // for volume created from snapshot, create usage event after volume creation - UsageEventUtils.publishUsageEvent(EventTypes.EVENT_VOLUME_CREATE, volume.getAccountId(), volume.getDataCenterId(), volume.getId(), volume.getName(), - diskOfferingId, null, size, Volume.class.getName(), volume.getUuid()); + UsageEventUtils.publishUsageEvent(EventTypes.EVENT_VOLUME_CREATE, volume.getAccountId(), volume.getDataCenterId(), volume.getId(), volume.getName(), + diskOfferingId, null, size, Volume.class.getName(), volume.getUuid(), displayVolume); } CallContext.current().setEventDetails("Volume Id: " + volume.getId()); @@ -677,11 +673,11 @@ protected VolumeVO createVolumeFromSnapshot(VolumeVO volume, long snapshotId, Lo // sync old snapshots to region store if necessary createdVolume = _volumeMgr.createVolumeFromSnapshot(volume, snapshot, vm); - + VolumeVO volumeVo = _volsDao.findById(createdVolume.getId()); UsageEventUtils.publishUsageEvent(EventTypes.EVENT_VOLUME_CREATE, createdVolume.getAccountId(), createdVolume.getDataCenterId(), createdVolume.getId(), - createdVolume.getName(), createdVolume.getDiskOfferingId(), null, createdVolume.getSize(), Volume.class.getName(), createdVolume.getUuid()); + createdVolume.getName(), createdVolume.getDiskOfferingId(), null, createdVolume.getSize(), Volume.class.getName(), createdVolume.getUuid(), volumeVo.isDisplayVolume()); - return _volsDao.findById(createdVolume.getId()); + return volumeVo; } @Override @@ -701,27 +697,17 @@ public VolumeVO resizeVolume(ResizeVolumeCmd cmd) throws ResourceAllocationExcep newDiskOffering = _diskOfferingDao.findById(cmd.getNewDiskOfferingId()); - /* - * Volumes with no hypervisor have never been assigned, and can be - * resized by recreating. perhaps in the future we can just update the - * db entry for the volume - */ - if (_volsDao.getHypervisorType(volume.getId()) == HypervisorType.None) { - throw new InvalidParameterValueException("Can't resize a volume that has never been attached, not sure which hypervisor type. Recreate volume to resize."); - } - - /* Only works for KVM/Xen for now */ - if (_volsDao.getHypervisorType(volume.getId()) != HypervisorType.KVM && _volsDao.getHypervisorType(volume.getId()) != HypervisorType.XenServer - && _volsDao.getHypervisorType(volume.getId()) != HypervisorType.VMware) { - throw new InvalidParameterValueException("Cloudstack currently only supports volumes marked as KVM or XenServer hypervisor for resize"); - } - - if (volume.getState() != Volume.State.Ready) { - throw new InvalidParameterValueException("Volume should be in ready state before attempting a resize"); + /* Only works for KVM/Xen/VMware for now, and volumes with 'None' since they're just allocated in db */ + if (_volsDao.getHypervisorType(volume.getId()) != HypervisorType.KVM + && _volsDao.getHypervisorType(volume.getId()) != HypervisorType.XenServer + && _volsDao.getHypervisorType(volume.getId()) != HypervisorType.VMware + && _volsDao.getHypervisorType(volume.getId()) != HypervisorType.None) { + throw new InvalidParameterValueException("Cloudstack currently only supports volumes marked as KVM, VMware, XenServer hypervisor for resize"); } - if (!volume.getVolumeType().equals(Volume.Type.DATADISK)) { - throw new InvalidParameterValueException("Can only resize DATA volumes"); + if (volume.getState() != Volume.State.Ready && volume.getState() != Volume.State.Allocated) { + throw new InvalidParameterValueException("Volume should be in ready or allocated state before attempting a resize. " + + "Volume " + volume.getUuid() + " state is:" + volume.getState()); } /* @@ -729,7 +715,7 @@ public VolumeVO resizeVolume(ResizeVolumeCmd cmd) throws ResourceAllocationExcep * required, get the correct size value */ if (newDiskOffering == null) { - if (diskOffering.isCustomized()) { + if (diskOffering.isCustomized() || volume.getVolumeType().equals(Volume.Type.ROOT)) { newSize = cmd.getSize(); if (newSize == null) { @@ -741,6 +727,9 @@ public VolumeVO resizeVolume(ResizeVolumeCmd cmd) throws ResourceAllocationExcep throw new InvalidParameterValueException("current offering" + volume.getDiskOfferingId() + " cannot be resized, need to specify a disk offering"); } } else { + if (!volume.getVolumeType().equals(Volume.Type.DATADISK)) { + throw new InvalidParameterValueException("Can only resize Data volumes via new disk offering"); + } if (newDiskOffering.getRemoved() != null || !DiskOfferingVO.Type.Disk.equals(newDiskOffering.getType())) { throw new InvalidParameterValueException("Disk offering ID is missing or invalid"); @@ -782,9 +771,7 @@ public VolumeVO resizeVolume(ResizeVolumeCmd cmd) throws ResourceAllocationExcep } /* does the caller have the authority to act on this volume? */ - _accountMgr.checkAccess(CallContext.current().getCallingAccount(), null, true, volume); - - UserVmVO userVm = _userVmDao.findById(volume.getInstanceId()); + _accountMgr.checkAccess(CallContext.current().getCallingAccount(), null, volume); long currentSize = volume.getSize(); @@ -805,6 +792,20 @@ public VolumeVO resizeVolume(ResizeVolumeCmd cmd) throws ResourceAllocationExcep - currentSize)); } + /* If this volume has never been beyond allocated state, short circuit everything and simply update the database */ + if (volume.getState() == Volume.State.Allocated) { + s_logger.debug("Volume is allocated, but never created, simply updating database with new size"); + volume.setSize(newSize); + if (newDiskOffering != null) { + volume.setDiskOfferingId(cmd.getNewDiskOfferingId()); + } + _volsDao.update(volume.getId(), volume); + return volume; + } + + UserVmVO userVm = _userVmDao.findById(volume.getInstanceId()); + + if (userVm != null) { // serialize VM operation AsyncJobExecutionContext jobContext = AsyncJobExecutionContext.getCurrentExecutionContext(); @@ -933,7 +934,7 @@ public boolean deleteVolume(long volumeId, Account caller) throws ConcurrentOper throw new InvalidParameterValueException("There are snapshot creating on it, Unable to delete the volume"); } - _accountMgr.checkAccess(caller, null, true, volume); + _accountMgr.checkAccess(caller, null, volume); if (volume.getInstanceId() != null) { throw new InvalidParameterValueException("Please specify a volume that is not attached to any VM."); @@ -967,7 +968,7 @@ storage count (in case of upload volume). */ // Log usage event for volumes belonging user VM's only UsageEventUtils.publishUsageEvent(EventTypes.EVENT_VOLUME_DELETE, volume.getAccountId(), volume.getDataCenterId(), volume.getId(), volume.getName(), - Volume.class.getName(), volume.getUuid()); + Volume.class.getName(), volume.getUuid(), volume.isDisplayVolume()); } } // Mark volume as removed if volume has not been created on primary or secondary @@ -1126,7 +1127,8 @@ public Volume attachVolumeToVM(Long vmId, Long volumeId, Long deviceId) { } // permission check - _accountMgr.checkAccess(caller, null, true, volume, vm); + // TODO: remove this if we can annotate volume parameter in createVolumeCmd since this routine is used there as well. + _accountMgr.checkAccess(caller, AccessType.OperateEntry, volume, vm); if (!(Volume.State.Allocated.equals(volume.getState()) || Volume.State.Ready.equals(volume.getState()) || Volume.State.Uploaded.equals(volume.getState()))) { throw new InvalidParameterValueException("Volume state must be in Allocated, Ready or in Uploaded state"); @@ -1220,14 +1222,13 @@ public Volume updateVolume(long volumeId, String path, String state, Long storag VolumeVO volume = _volumeDao.findById(volumeId); + if(volume == null) + throw new InvalidParameterValueException("The volume id doesn't exist"); + if (path != null) { volume.setPath(path); } - if (displayVolume != null) { - volume.setDisplayVolume(displayVolume); - } - if(chainInfo != null){ volume.setChainInfo(chainInfo); } @@ -1253,17 +1254,61 @@ public Volume updateVolume(long volumeId, String path, String state, Long storag volume.setUuid(customId); } - if (displayVolume != null && displayVolume != volume.isDisplayVolume()) { // No need to check permissions since only Admin allowed to call this API. - volume.setDisplayVolume(displayVolume); - _resourceLimitMgr.changeResourceCount(entityOwnerId, ResourceType.volume, displayVolume); - _resourceLimitMgr.changeResourceCount(entityOwnerId, ResourceType.primary_storage, displayVolume, new Long(volume.getSize())); - } + updateDisplay(volume, displayVolume); _volumeDao.update(volumeId, volume); return volume; } + + @Override + public void updateDisplay(Volume volume, Boolean displayVolume){ + // 1. Resource limit changes + updateResourceCount(volume, displayVolume); + + // 2. generate usage event if not in destroyed state + saveUsageEvent(volume, displayVolume); + + // 3. Set the flag + if (displayVolume != null && displayVolume != volume.isDisplayVolume()){ + // FIXME - Confused - typecast for now. + ((VolumeVO)volume).setDisplayVolume(displayVolume); + _volumeDao.update(volume.getId(), (VolumeVO)volume); + } + + } + + private void updateResourceCount(Volume volume, Boolean displayVolume){ + // Update only when the flag has changed. + if (displayVolume != null && displayVolume != volume.isDisplayVolume()){ + _resourceLimitMgr.changeResourceCount(volume.getAccountId(), ResourceType.volume, displayVolume); + _resourceLimitMgr.changeResourceCount(volume.getAccountId(), ResourceType.primary_storage, displayVolume, new Long(volume.getSize())); + } + } + + private void saveUsageEvent(Volume volume, Boolean displayVolume){ + + // Update only when the flag has changed && only when volume in a non-destroyed state. + if ((displayVolume != null && displayVolume != volume.isDisplayVolume()) && !isVolumeDestroyed(volume)){ + if (displayVolume){ + // flag turned 1 equivalent to freshly created volume + UsageEventUtils.publishUsageEvent(EventTypes.EVENT_VOLUME_CREATE, volume.getAccountId(), volume.getDataCenterId(), volume.getId(), volume.getName(), + volume.getDiskOfferingId(), volume.getTemplateId(), volume.getSize(), Volume.class.getName(), volume.getUuid()); + }else { + // flag turned 0 equivalent to deleting a volume + UsageEventUtils.publishUsageEvent(EventTypes.EVENT_VOLUME_DELETE, volume.getAccountId(), volume.getDataCenterId(), volume.getId(), volume.getName(), + Volume.class.getName(), volume.getUuid()); + } + } + } + + private boolean isVolumeDestroyed(Volume volume){ + if(volume.getState() == Volume.State.Destroy || volume.getState() == Volume.State.Expunging && volume.getState() == Volume.State.Expunged) + return true; + return false; + } + @Override @ActionEvent(eventType = EventTypes.EVENT_VOLUME_DETACH, eventDescription = "detaching volume", async = true) public Volume detachVolumeFromVM(DetachVolumeCmd cmmd) { @@ -1297,7 +1342,7 @@ public Volume detachVolumeFromVM(DetachVolumeCmd cmmd) { } // Permissions check - _accountMgr.checkAccess(caller, null, true, volume); + _accountMgr.checkAccess(caller, null, volume); // Check that the volume is a data volume if (volume.getVolumeType() != Volume.Type.DATADISK) { @@ -1428,7 +1473,7 @@ private Volume orchestrateDetachVolumeFromVM(long vmId, long volumeId) { // Mark the volume as detached _volsDao.detachVolume(volume.getId()); - // volume.getPoolId() should be null if the VM we are attaching the disk to has never been started before + // volume.getPoolId() should be null if the VM we are detaching the disk from has never been started before DataStore dataStore = volume.getPoolId() != null ? dataStoreMgr.getDataStore(volume.getPoolId(), DataStoreRole.Primary) : null; volService.disconnectVolumeFromHost(volFactory.getVolume(volume.getId()), host, dataStore); @@ -1487,12 +1532,11 @@ public Volume migrateVolume(MigrateVolumeCmd cmd) { liveMigrateVolume = capabilities.isStorageMotionSupported(); } } - } - // If the disk is not attached to any VM then it can be moved. Otherwise, it needs to be attached to a vm - // running on a hypervisor that supports storage motion so that it be be migrated. - if (instanceId != null && !liveMigrateVolume) { - throw new InvalidParameterValueException("Volume needs to be detached from VM"); + // If vm is running, and hypervisor doesn't support live migration, then return error + if (!liveMigrateVolume) { + throw new InvalidParameterValueException("Volume needs to be detached from VM"); + } } if (liveMigrateVolume && !cmd.isLiveMigrate()) { @@ -1743,7 +1787,7 @@ public String extractVolume(ExtractVolumeCmd cmd) { } // perform permission check - _accountMgr.checkAccess(account, null, true, volume); + _accountMgr.checkAccess(account, null, volume); if (_dcDao.findById(zoneId) == null) { throw new InvalidParameterValueException("Please specify a valid zone."); diff --git a/server/src/com/cloud/storage/snapshot/SnapshotManagerImpl.java b/server/src/com/cloud/storage/snapshot/SnapshotManagerImpl.java index 6bf4817571..d19a0ed846 100755 --- a/server/src/com/cloud/storage/snapshot/SnapshotManagerImpl.java +++ b/server/src/com/cloud/storage/snapshot/SnapshotManagerImpl.java @@ -286,7 +286,7 @@ public Snapshot createSnapshot(Long volumeId, Long policyId, Long snapshotId, Ac boolean backedUp = false; // does the caller have the authority to act on this volume - _accountMgr.checkAccess(CallContext.current().getCallingAccount(), null, true, volume); + _accountMgr.checkAccess(CallContext.current().getCallingAccount(), null, volume); SnapshotInfo snapshot = snapshotFactory.getSnapshot(snapshotId, DataStoreRole.Primary); @@ -391,7 +391,7 @@ public boolean deleteSnapshot(long snapshotId) { throw new InvalidParameterValueException("unable to find a snapshot with id " + snapshotId); } - _accountMgr.checkAccess(caller, null, true, snapshotCheck); + _accountMgr.checkAccess(caller, null, snapshotCheck); SnapshotStrategy snapshotStrategy = _storageStrategyFactory.getSnapshotStrategy(snapshotCheck, SnapshotOperation.DELETE); if (snapshotStrategy == null) { s_logger.error("Unable to find snaphot strategy to handle snapshot with id '" + snapshotId + "'"); @@ -450,7 +450,7 @@ public Pair, Integer> listSnapshots(ListSnapshotsCmd cm if (volumeId != null) { VolumeVO volume = _volsDao.findById(volumeId); if (volume != null) { - _accountMgr.checkAccess(CallContext.current().getCallingAccount(), null, true, volume); + _accountMgr.checkAccess(CallContext.current().getCallingAccount(), null, volume); } } @@ -599,7 +599,7 @@ public boolean deleteSnapshotDirsForAccount(long accountId) { SnapshotDataStoreVO snapshotStoreRef = _snapshotStoreDao.findBySnapshot(snapshot.getId(), DataStoreRole.Image); if (snapshotStrategy.deleteSnapshot(snapshot.getId())) { - if (snapshot.getRecurringType() == Type.MANUAL) { + if (Type.MANUAL == snapshot.getRecurringType()) { _resourceLimitMgr.decrementResourceCount(accountId, ResourceType.snapshot); _resourceLimitMgr.decrementResourceCount(accountId, ResourceType.secondary_storage, new Long(snapshotStoreRef.getSize())); } @@ -624,7 +624,7 @@ public SnapshotPolicyVO createPolicy(CreateSnapshotPolicyCmd cmd, Account policy throw new InvalidParameterValueException("Failed to create snapshot policy, unable to find a volume with id " + volumeId); } - _accountMgr.checkAccess(CallContext.current().getCallingAccount(), null, true, volume); + _accountMgr.checkAccess(CallContext.current().getCallingAccount(), null, volume); if (volume.getState() != Volume.State.Ready) { throw new InvalidParameterValueException("VolumeId: " + volumeId + " is not in " + Volume.State.Ready + " state but " + volume.getState() + @@ -723,7 +723,7 @@ public Pair, Integer> listPoliciesforVolume(ListS if (volume == null) { throw new InvalidParameterValueException("Unable to find a volume with id " + volumeId); } - _accountMgr.checkAccess(CallContext.current().getCallingAccount(), null, true, volume); + _accountMgr.checkAccess(CallContext.current().getCallingAccount(), null, volume); Pair, Integer> result = _snapshotPolicyDao.listAndCountByVolumeId(volumeId); return new Pair, Integer>(result.first(), result.second()); } @@ -769,7 +769,7 @@ public List findRecurringSnapshotSchedule(ListRecurringSnaps if (account != null) { long volAcctId = volume.getAccountId(); - if (_accountMgr.isAdmin(account.getType())) { + if (_accountMgr.isAdmin(account.getId())) { Account userAccount = _accountDao.findById(Long.valueOf(volAcctId)); if (!_domainDao.isChildDomain(account.getDomainId(), userAccount.getDomainId())) { throw new PermissionDeniedException("Unable to list snapshot schedule for volume " + volumeId + ", permission denied."); @@ -999,7 +999,7 @@ public boolean deleteSnapshotPolicies(DeleteSnapshotPoliciesCmd cmd) { throw new InvalidParameterValueException("Policy id given: " + policy + " does not belong to a valid volume"); } - _accountMgr.checkAccess(CallContext.current().getCallingAccount(), null, true, volume); + _accountMgr.checkAccess(CallContext.current().getCallingAccount(), null, volume); } boolean success = true; @@ -1030,12 +1030,9 @@ public boolean canOperateOnVolume(Volume volume) { @Override public Snapshot allocSnapshot(Long volumeId, Long policyId) throws ResourceAllocationException { - Account caller = CallContext.current().getCallingAccount(); VolumeInfo volume = volFactory.getVolume(volumeId); supportedByHypervisor(volume); - // Verify permissions - _accountMgr.checkAccess(caller, null, true, volume); Type snapshotType = getSnapshotType(policyId); Account owner = _accountMgr.getAccount(volume.getAccountId()); diff --git a/server/src/com/cloud/tags/TaggedResourceManagerImpl.java b/server/src/com/cloud/tags/TaggedResourceManagerImpl.java index 900c822da8..cac12c628d 100644 --- a/server/src/com/cloud/tags/TaggedResourceManagerImpl.java +++ b/server/src/com/cloud/tags/TaggedResourceManagerImpl.java @@ -39,9 +39,11 @@ import com.cloud.event.EventTypes; import com.cloud.exception.InvalidParameterValueException; import com.cloud.exception.PermissionDeniedException; +import com.cloud.network.LBHealthCheckPolicyVO; import com.cloud.network.as.AutoScaleVmGroupVO; import com.cloud.network.as.AutoScaleVmProfileVO; import com.cloud.network.dao.IPAddressVO; +import com.cloud.network.dao.LBStickinessPolicyVO; import com.cloud.network.dao.LoadBalancerVO; import com.cloud.network.dao.NetworkVO; import com.cloud.network.dao.RemoteAccessVpnVO; @@ -119,6 +121,9 @@ public class TaggedResourceManagerImpl extends ManagerBase implements TaggedReso s_typeMap.put(ResourceObjectType.DiskOffering, DiskOfferingVO.class); s_typeMap.put(ResourceObjectType.AutoScaleVmProfile, AutoScaleVmProfileVO.class); s_typeMap.put(ResourceObjectType.AutoScaleVmGroup, AutoScaleVmGroupVO.class); + s_typeMap.put(ResourceObjectType.LBStickinessPolicy, LBStickinessPolicyVO.class); + s_typeMap.put(ResourceObjectType.LBHealthCheckPolicy, LBHealthCheckPolicyVO.class); + } @Inject @@ -222,7 +227,7 @@ public void doInTransactionWithoutResult(TransactionStatus status) { Long domainId = accountDomainPair.second(); Long accountId = accountDomainPair.first(); if (accountId != null) { - _accountMgr.checkAccess(caller, null, false, _accountMgr.getAccount(accountId)); + _accountMgr.checkAccess(caller, null, _accountMgr.getAccount(accountId)); } else if (domainId != null && !_accountMgr.isNormalUser(caller.getId())) { //check permissions; _accountMgr.checkAccess(caller, _domainMgr.getDomain(domainId)); @@ -284,7 +289,7 @@ public boolean deleteTags(List resourceIds, ResourceObjectType resourceT for (ResourceTag resourceTag : resourceTags) { //1) validate the permissions Account owner = _accountMgr.getAccount(resourceTag.getAccountId()); - _accountMgr.checkAccess(caller, null, false, owner); + _accountMgr.checkAccess(caller, null, owner); //2) Only remove tag if it matches key value pairs if (tags != null && !tags.isEmpty()) { for (String key : tags.keySet()) { diff --git a/server/src/com/cloud/template/HypervisorTemplateAdapter.java b/server/src/com/cloud/template/HypervisorTemplateAdapter.java index 2b6f1ebf3a..51dedf7697 100755 --- a/server/src/com/cloud/template/HypervisorTemplateAdapter.java +++ b/server/src/com/cloud/template/HypervisorTemplateAdapter.java @@ -29,7 +29,6 @@ import org.apache.log4j.Logger; -import org.apache.cloudstack.acl.IAMEntityType; import org.apache.cloudstack.api.command.user.iso.DeleteIsoCmd; import org.apache.cloudstack.api.command.user.iso.RegisterIsoCmd; import org.apache.cloudstack.api.command.user.template.DeleteTemplateCmd; @@ -400,6 +399,11 @@ public boolean delete(TemplateProfile profile) { } } if (success) { + if ((imageStores.size() > 1) && (profile.getZoneId() != null)) { + //if template is stored in more than one image stores, and the zone id is not null, then don't delete other templates. + return success; + } + // delete all cache entries for this template List cacheTmpls = imageFactory.listTemplateOnCache(template.getId()); for (TemplateInfo tmplOnCache : cacheTmpls) { @@ -423,7 +427,7 @@ public boolean delete(TemplateProfile profile) { } // remove its related ACL permission - Pair tmplt = new Pair(IAMEntityType.VirtualMachineTemplate, template.getId()); + Pair, Long> tmplt = new Pair, Long>(VirtualMachineTemplate.class, template.getId()); _messageBus.publish(_name, EntityManager.MESSAGE_REMOVE_ENTITY_EVENT, PublishScope.LOCAL, tmplt); } diff --git a/server/src/com/cloud/template/TemplateAdapterBase.java b/server/src/com/cloud/template/TemplateAdapterBase.java index f3c16cad03..cb38075324 100755 --- a/server/src/com/cloud/template/TemplateAdapterBase.java +++ b/server/src/com/cloud/template/TemplateAdapterBase.java @@ -179,7 +179,7 @@ public TemplateProfile prepare(boolean isIso, long userId, String name, String d if (!isAdmin && zoneId == null && !isRegionStore ) { // domain admin and user should also be able to register template on a region store - throw new InvalidParameterValueException("Please specify a valid zone Id."); + throw new InvalidParameterValueException("Please specify a valid zone Id. Only admins can create templates in all zones."); } if (url.toLowerCase().contains("file://")) { @@ -209,10 +209,6 @@ public TemplateProfile prepare(boolean isIso, long userId, String name, String d _resourceLimitMgr.checkResourceLimit(templateOwner, ResourceType.template); - if (!_accountMgr.isRootAdmin(templateOwner.getId()) && zoneId == null) { - throw new IllegalArgumentException("Only admins can create templates in all zones"); - } - // If a zoneId is specified, make sure it is valid if (zoneId != null) { DataCenterVO zone = _dcDao.findById(zoneId); @@ -258,7 +254,7 @@ public TemplateProfile prepare(RegisterTemplateCmd cmd) throws ResourceAllocatio //check if the caller can operate with the template owner Account caller = CallContext.current().getCallingAccount(); Account owner = _accountMgr.getAccount(cmd.getEntityOwnerId()); - _accountMgr.checkAccess(caller, null, true, owner); + _accountMgr.checkAccess(caller, null, owner); boolean isRouting = (cmd.isRoutingType() == null) ? false : cmd.isRoutingType(); @@ -281,7 +277,7 @@ public TemplateProfile prepare(RegisterIsoCmd cmd) throws ResourceAllocationExce //check if the caller can operate with the template owner Account caller = CallContext.current().getCallingAccount(); Account owner = _accountMgr.getAccount(cmd.getEntityOwnerId()); - _accountMgr.checkAccess(caller, null, true, owner); + _accountMgr.checkAccess(caller, null, owner); Long zoneId = cmd.getZoneId(); // ignore passed zoneId if we are using region wide image store @@ -324,7 +320,7 @@ protected VMTemplateVO persistTemplate(TemplateProfile profile) { private Long accountAndUserValidation(Account account, long userId, UserVmVO vmInstanceCheck, VMTemplateVO template, String msg) throws PermissionDeniedException { if (account != null) { - if (!_accountMgr.isAdmin(account.getType())) { + if (!_accountMgr.isAdmin(account.getId())) { if ((vmInstanceCheck != null) && (account.getId() != vmInstanceCheck.getAccountId())) { throw new PermissionDeniedException(msg + ". Permission denied."); } diff --git a/server/src/com/cloud/template/TemplateManagerImpl.java b/server/src/com/cloud/template/TemplateManagerImpl.java index 34123cdb98..294748ff1a 100755 --- a/server/src/com/cloud/template/TemplateManagerImpl.java +++ b/server/src/com/cloud/template/TemplateManagerImpl.java @@ -33,7 +33,6 @@ import org.apache.log4j.Logger; -import org.apache.cloudstack.acl.IAMEntityType; import org.apache.cloudstack.acl.SecurityChecker.AccessType; import org.apache.cloudstack.api.ApiConstants; import org.apache.cloudstack.api.BaseListTemplateOrIsoPermissionsCmd; @@ -370,7 +369,7 @@ public VirtualMachineTemplate prepareTemplate(long templateId, long zoneId) { throw new InvalidParameterValueException("Unable to find template id=" + templateId); } - _accountMgr.checkAccess(CallContext.current().getCallingAccount(), AccessType.OperateEntry, true, vmTemplate); + _accountMgr.checkAccess(CallContext.current().getCallingAccount(), AccessType.OperateEntry, vmTemplate); prepareTemplateInAllStoragePools(vmTemplate, zoneId); return vmTemplate; @@ -416,7 +415,7 @@ private String extract(Account caller, Long templateId, String url, Long zoneId, throw new InvalidParameterValueException("Unable to extract template id=" + templateId + " as it's not extractable"); } - _accountMgr.checkAccess(caller, AccessType.OperateEntry, true, template); + _accountMgr.checkAccess(caller, AccessType.OperateEntry, template); List ssStores = _dataStoreMgr.getImageStoresByScope(new ZoneScope(zoneId)); @@ -723,7 +722,7 @@ public VirtualMachineTemplate copyTemplate(CopyTemplateCmd cmd) throws StorageUn return template; } - _accountMgr.checkAccess(caller, AccessType.OperateEntry, true, template); + _accountMgr.checkAccess(caller, AccessType.OperateEntry, template); boolean success = copy(userId, template, srcSecStore, dstZone); @@ -912,7 +911,7 @@ public boolean detachIso(long vmId) { throw new InvalidParameterValueException("Please specify a valid VM."); } - _accountMgr.checkAccess(caller, null, true, userVM); + _accountMgr.checkAccess(caller, null, userVM); Long isoId = userVM.getIsoId(); if (isoId == null) { @@ -953,12 +952,11 @@ public boolean attachIso(long isoId, long vmId) { // check permissions // check if caller has access to VM and ISO - // and also check if the VM's owner has access to the ISO. - - _accountMgr.checkAccess(caller, null, false, iso, vm); - + // and also check if the VM's owner has access to the ISO. This is a bit different from sameOwner check for attachVolumeToVM, where both volume and VM need + // OperateEntry access type. Here VM needs OperateEntry access type, ISO needs UseEntry access type. + _accountMgr.checkAccess(caller, null, iso, vm); Account vmOwner = _accountDao.findById(vm.getAccountId()); - _accountMgr.checkAccess(vmOwner, null, false, iso, vm); + _accountMgr.checkAccess(vmOwner, null, iso); State vmState = vm.getState(); if (vmState != State.Running && vmState != State.Stopped) { @@ -1062,7 +1060,7 @@ public boolean deleteTemplate(DeleteTemplateCmd cmd) { throw new InvalidParameterValueException("unable to find template with id " + templateId); } - _accountMgr.checkAccess(caller, AccessType.OperateEntry, true, template); + _accountMgr.checkAccess(caller, AccessType.OperateEntry, template); if (template.getFormat() == ImageFormat.ISO) { throw new InvalidParameterValueException("Please specify a valid template."); @@ -1085,7 +1083,7 @@ public boolean deleteIso(DeleteIsoCmd cmd) { throw new InvalidParameterValueException("unable to find iso with id " + templateId); } - _accountMgr.checkAccess(caller, AccessType.OperateEntry, true, template); + _accountMgr.checkAccess(caller, AccessType.OperateEntry, template); if (template.getFormat() != ImageFormat.ISO) { throw new InvalidParameterValueException("Please specify a valid iso."); @@ -1135,7 +1133,7 @@ public List listTemplatePermissions(BaseListTemplateOrIsoPermissionsCmd } if (!template.isPublicTemplate()) { - _accountMgr.checkAccess(caller, null, true, template); + _accountMgr.checkAccess(caller, AccessType.ListEntry, template); } List accountNames = new ArrayList(); @@ -1208,8 +1206,7 @@ public boolean updateTemplateOrIsoPermissions(BaseUpdateTemplateOrIsoPermissions } } - //_accountMgr.checkAccess(caller, AccessType.ModifyEntry, true, template); - _accountMgr.checkAccess(caller, AccessType.OperateEntry, true, template); //TODO: should we replace all ModifyEntry as OperateEntry? + _accountMgr.checkAccess(caller, AccessType.OperateEntry, template); // If the template is removed throw an error. if (template.getRemoved() != null) { @@ -1221,7 +1218,7 @@ public boolean updateTemplateOrIsoPermissions(BaseUpdateTemplateOrIsoPermissions throw new InvalidParameterValueException("unable to update permissions for " + mediaType + " with id " + id); } - boolean isAdmin = _accountMgr.isAdmin(caller.getType()); + boolean isAdmin = _accountMgr.isAdmin(caller.getId()); // check configuration parameter(allow.public.user.templates) value for // the template owner boolean allowPublicUserTemplates = AllowPublicUserTemplates.valueIn(template.getAccountId()); @@ -1257,8 +1254,8 @@ public boolean updateTemplateOrIsoPermissions(BaseUpdateTemplateOrIsoPermissions if (isExtractable != null) { // Only Root admins allowed to change it for templates - if (!template.getFormat().equals(ImageFormat.ISO) && _accountMgr.isRootAdmin(caller.getId())) { - throw new InvalidParameterValueException("Only ROOT admins are allowed to modify this attribute."); + if (!template.getFormat().equals(ImageFormat.ISO) && !_accountMgr.isRootAdmin(caller.getId())) { + throw new InvalidParameterValueException("Only ROOT admins are allowed to modify isExtractable attribute."); } else { // For Isos normal user can change it, as their are no derivatives. updatedTemplate.setExtractable(isExtractable.booleanValue()); @@ -1304,7 +1301,7 @@ public void doInTransactionWithoutResult(TransactionStatus status) { // add ACL permission in IAM Map permit = new HashMap(); - permit.put(ApiConstants.ENTITY_TYPE, IAMEntityType.VirtualMachineTemplate.toString()); + permit.put(ApiConstants.ENTITY_TYPE, VirtualMachineTemplate.class); permit.put(ApiConstants.ENTITY_ID, id); permit.put(ApiConstants.ACCESS_TYPE, AccessType.UseEntry); permit.put(ApiConstants.IAM_ACTION, "listTemplates"); @@ -1321,7 +1318,7 @@ public void doInTransactionWithoutResult(TransactionStatus status) { _launchPermissionDao.removePermissions(id, accountIds); // remove ACL permission in IAM Map permit = new HashMap(); - permit.put(ApiConstants.ENTITY_TYPE, IAMEntityType.VirtualMachineTemplate.toString()); + permit.put(ApiConstants.ENTITY_TYPE, VirtualMachineTemplate.class); permit.put(ApiConstants.ENTITY_ID, id); permit.put(ApiConstants.ACCESS_TYPE, AccessType.UseEntry); permit.put(ApiConstants.IAM_ACTION, "listTemplates"); @@ -1488,9 +1485,9 @@ public VMTemplateVO createPrivateTemplateRecord(CreateTemplateCmd cmd, Account t Long userId = CallContext.current().getCallingUserId(); Account caller = CallContext.current().getCallingAccount(); - boolean isAdmin = (_accountMgr.isAdmin(caller.getType())); + boolean isAdmin = (_accountMgr.isAdmin(caller.getId())); - _accountMgr.checkAccess(caller, null, true, templateOwner); + _accountMgr.checkAccess(caller, null, templateOwner); String name = cmd.getTemplateName(); if ((name == null) || (name.length() > 32)) { @@ -1542,7 +1539,7 @@ public VMTemplateVO createPrivateTemplateRecord(CreateTemplateCmd cmd, Account t throw new InvalidParameterValueException("Failed to create private template record, unable to find volume " + volumeId); } // check permissions - _accountMgr.checkAccess(caller, null, true, volume); + _accountMgr.checkAccess(caller, null, volume); // If private template is created from Volume, check that the volume // will not be active when the private template is @@ -1565,7 +1562,7 @@ public VMTemplateVO createPrivateTemplateRecord(CreateTemplateCmd cmd, Account t volume = _volumeDao.findById(snapshot.getVolumeId()); // check permissions - _accountMgr.checkAccess(caller, null, true, snapshot); + _accountMgr.checkAccess(caller, null, snapshot); if (snapshot.getState() != Snapshot.State.BackedUp) { throw new InvalidParameterValueException("Snapshot id=" + snapshotId + " is not in " + Snapshot.State.BackedUp + @@ -1781,7 +1778,7 @@ private VMTemplateVO updateTemplateOrIso(BaseUpdateTemplateOrIsoCmd cmd) { verifyTemplateId(id); // do a permission check - _accountMgr.checkAccess(account, AccessType.OperateEntry, true, template); + _accountMgr.checkAccess(account, AccessType.OperateEntry, template); if (cmd.isRoutingType() != null) { if (!_accountService.isRootAdmin(account.getId())) { throw new PermissionDeniedException("Parameter isrouting can only be specified by a Root Admin, permission denied"); diff --git a/server/src/com/cloud/user/AccountManagerImpl.java b/server/src/com/cloud/user/AccountManagerImpl.java index f0d129a3ce..3ff9bd2daa 100755 --- a/server/src/com/cloud/user/AccountManagerImpl.java +++ b/server/src/com/cloud/user/AccountManagerImpl.java @@ -61,7 +61,6 @@ import org.apache.cloudstack.managed.context.ManagedContextRunnable; import org.apache.cloudstack.region.gslb.GlobalLoadBalancerRuleDao; -import com.cloud.api.ApiDBUtils; import com.cloud.configuration.Config; import com.cloud.configuration.ConfigurationManager; import com.cloud.configuration.Resource.ResourceOwnerType; @@ -76,7 +75,6 @@ import com.cloud.dc.dao.DedicatedResourceDao; import com.cloud.domain.Domain; import com.cloud.domain.DomainVO; -import com.cloud.domain.PartOf; import com.cloud.domain.dao.DomainDao; import com.cloud.event.ActionEvent; import com.cloud.event.ActionEventUtils; @@ -103,6 +101,7 @@ import com.cloud.network.dao.RemoteAccessVpnDao; import com.cloud.network.dao.RemoteAccessVpnVO; import com.cloud.network.dao.VpnUserDao; +import com.cloud.network.security.SecurityGroup; import com.cloud.network.security.SecurityGroupManager; import com.cloud.network.security.dao.SecurityGroupDao; import com.cloud.network.vpc.Vpc; @@ -361,15 +360,29 @@ public AccountVO getSystemAccount() { } @Override - public boolean isAdmin(short accountType) { - return ((accountType == Account.ACCOUNT_TYPE_ADMIN) || (accountType == Account.ACCOUNT_TYPE_RESOURCE_DOMAIN_ADMIN) || - (accountType == Account.ACCOUNT_TYPE_DOMAIN_ADMIN) || (accountType == Account.ACCOUNT_TYPE_READ_ONLY_ADMIN)); + public boolean isAdmin(Long accountId) { + if (accountId != null) { + AccountVO acct = _accountDao.findById(accountId); + if (acct == null) { + return false; //account is deleted or does not exist + } + if ((isRootAdmin(accountId)) || (isDomainAdmin(accountId)) || (isResourceDomainAdmin(accountId))) { + return true; + } else if (acct.getType() == Account.ACCOUNT_TYPE_READ_ONLY_ADMIN) { + return true; + } + + } + return false; } @Override public boolean isRootAdmin(Long accountId) { if (accountId != null) { AccountVO acct = _accountDao.findById(accountId); + if (acct == null) { + return false; //account is deleted or does not exist + } for (SecurityChecker checker : _securityCheckers) { try { if (checker.checkAccess(acct, null, null, "SystemCapability")) { @@ -390,11 +403,14 @@ public boolean isRootAdmin(Long accountId) { public boolean isDomainAdmin(Long accountId) { if (accountId != null) { AccountVO acct = _accountDao.findById(accountId); + if (acct == null) { + return false; //account is deleted or does not exist + } for (SecurityChecker checker : _securityCheckers) { try { if (checker.checkAccess(acct, null, null, "DomainCapability")) { if (s_logger.isDebugEnabled()) { - s_logger.debug("Root Access granted to " + acct + " by " + checker.getName()); + s_logger.debug("DomainAdmin Access granted to " + acct + " by " + checker.getName()); } return true; } @@ -415,12 +431,33 @@ public boolean isNormalUser(long accountId) { return false; } - public boolean isResourceDomainAdmin(short accountType) { - return (accountType == Account.ACCOUNT_TYPE_RESOURCE_DOMAIN_ADMIN); + public boolean isResourceDomainAdmin(Long accountId) { + if (accountId != null) { + AccountVO acct = _accountDao.findById(accountId); + if (acct == null) { + return false; //account is deleted or does not exist + } + for (SecurityChecker checker : _securityCheckers) { + try { + if (checker.checkAccess(acct, null, null, "DomainResourceCapability")) { + if (s_logger.isDebugEnabled()) { + s_logger.debug("ResourceDomainAdmin Access granted to " + acct + " by " + checker.getName()); + } + return true; + } + } catch (PermissionDeniedException ex) { + return false; + } + } + } + return false; } public boolean isInternalAccount(long accountId) { Account account = _accountDao.findById(accountId); + if (account == null) { + return false; //account is deleted or does not exist + } if (isRootAdmin(accountId) || (account.getType() == Account.ACCOUNT_ID_SYSTEM)) { return true; } @@ -442,104 +479,119 @@ public void checkAccess(Account caller, Domain domain) throws PermissionDeniedEx throw new PermissionDeniedException("There's no way to confirm " + caller + " has access to " + domain); } - @Override - public void checkAccess(Account account, AccessType accessType, boolean sameOwner, PartOf... entities) throws PermissionDeniedException { - // TODO Auto-generated method stub - - //TO BE IMPLEMENTED - - } @Override - public void checkAccess(Account caller, AccessType accessType, boolean sameOwner, ControlledEntity... entities) { - checkAccess(caller, accessType, sameOwner, null, entities); + public void checkAccess(Account caller, AccessType accessType, ControlledEntity... entities) throws PermissionDeniedException { + checkAccess(caller, accessType, null, entities); } @Override - public void checkAccess(Account caller, AccessType accessType, boolean sameOwner, String apiName, ControlledEntity... entities) { - //check for the same owner - Long ownerId = null; - ControlledEntity prevEntity = null; - if (sameOwner) { - for (ControlledEntity entity : entities) { - if (sameOwner) { - if (ownerId == null) { - ownerId = entity.getAccountId(); - } else if (ownerId.longValue() != entity.getAccountId()) { - throw new PermissionDeniedException("Entity " + entity + " and entity " + prevEntity + " belong to different accounts"); - } - prevEntity = entity; - } - } + public void checkAccess(Account caller, AccessType accessType, String apiName, ControlledEntity... entities) throws PermissionDeniedException { + boolean granted = false; + // construct entities identification string + StringBuffer entityBuf = new StringBuffer("{"); + for (ControlledEntity ent : entities) { + entityBuf.append(ent.toString()); } + entityBuf.append("}"); + String entityStr = entityBuf.toString(); - if (caller.getId() == Account.ACCOUNT_ID_SYSTEM || isRootAdmin(caller.getId())) { - // no need to make permission checks if the system/root admin makes the call - if (s_logger.isTraceEnabled()) { - s_logger.trace("No need to make permission check for System/RootAdmin account, returning true"); - } - return; - } + boolean isRootAdmin = isRootAdmin(caller.getAccountId()); + boolean isDomainAdmin = isDomainAdmin(caller.getAccountId()); + boolean isResourceDomainAdmin = isResourceDomainAdmin(caller.getAccountId()); - HashMap> domains = new HashMap>(); + if ((isRootAdmin || isDomainAdmin || isResourceDomainAdmin || caller.getId() == Account.ACCOUNT_ID_SYSTEM) + && (accessType == null || accessType == AccessType.UseEntry)) { - for (ControlledEntity entity : entities) { - long domainId = entity.getDomainId(); - if (entity.getAccountId() != -1 && domainId == -1) { // If account exists domainId should too so calculate - // it. This condition might be hit for templates or entities which miss domainId in their tables - Account account = ApiDBUtils.findAccountById(entity.getAccountId()); - domainId = account != null ? account.getDomainId() : -1; - } - if (entity.getAccountId() != -1 && domainId != -1 && !(entity instanceof VirtualMachineTemplate) && - !(entity instanceof Network && accessType != null && accessType == AccessType.UseEntry) && !(entity instanceof AffinityGroup)) { - List toBeChecked = domains.get(entity.getDomainId()); - // for templates, we don't have to do cross domains check - if (toBeChecked == null) { - toBeChecked = new ArrayList(); - domains.put(domainId, toBeChecked); + for (ControlledEntity entity : entities) { + if (entity instanceof VirtualMachineTemplate || (entity instanceof Network && accessType != null && (isDomainAdmin || isResourceDomainAdmin)) + || entity instanceof AffinityGroup || entity instanceof SecurityGroup) { + // Go through IAM (SecurityCheckers) + for (SecurityChecker checker : _securityCheckers) { + if (checker.checkAccess(caller, accessType, apiName, entity)) { + if (s_logger.isDebugEnabled()) { + s_logger.debug("Access to " + entityStr + " granted to " + caller + " by " + + checker.getName()); + } + granted = true; + break; + } + } + } else { + if (isRootAdmin || caller.getId() == Account.ACCOUNT_ID_SYSTEM) { + // no need to make permission checks if the system/root + // admin makes the call + if (s_logger.isTraceEnabled()) { + s_logger.trace("No need to make permission check for System/RootAdmin account, returning true"); + } + granted = true; + } else if (isDomainAdmin || isResourceDomainAdmin) { + Domain entityDomain = getEntityDomain(entity); + if (entityDomain != null) { + try { + checkAccess(caller, entityDomain); + granted = true; + } catch (PermissionDeniedException e) { + List entityList = new ArrayList(); + entityList.add(entity); + e.addDetails(caller, entityList); + throw e; + } + } + } + } + + if (!granted) { + assert false : "How can all of the security checkers pass on checking this check: " + entityStr; + throw new PermissionDeniedException("There's no way to confirm " + caller + " has access to " + + entityStr); } - toBeChecked.add(entity); + } - boolean granted = false; + } else { + // Go through IAM (SecurityCheckers) for (SecurityChecker checker : _securityCheckers) { - if (checker.checkAccess(caller, entity, accessType, apiName)) { + if (checker.checkAccess(caller, accessType, apiName, entities)) { if (s_logger.isDebugEnabled()) { - s_logger.debug("Access to " + entity + " granted to " + caller + " by " + checker.getName()); + s_logger.debug("Access to " + entityStr + " granted to " + caller + " by " + checker.getName()); } granted = true; break; } } + } - if (!granted) { - assert false : "How can all of the security checkers pass on checking this check: " + entity; - throw new PermissionDeniedException("There's no way to confirm " + caller + " has access to " + entity); - } + if (!granted) { + assert false : "How can all of the security checkers pass on checking this check: " + entityStr; + throw new PermissionDeniedException("There's no way to confirm " + caller + " has access to " + entityStr); } + } - for (Map.Entry> domain : domains.entrySet()) { - for (SecurityChecker checker : _securityCheckers) { - Domain d = _domainMgr.getDomain(domain.getKey()); - if (d == null || d.getRemoved() != null) { - throw new PermissionDeniedException("Domain is not found.", caller, domain.getValue()); - } - try { - checker.checkAccess(caller, d); - } catch (PermissionDeniedException e) { - e.addDetails(caller, domain.getValue()); - throw e; - } + private Domain getEntityDomain(ControlledEntity entity) { + Domain entityDomain = null; + long domainId = entity.getDomainId(); + + if (domainId != -1) { + entityDomain = _domainMgr.getDomain(domainId); + } else { + if (entity.getAccountId() != -1) { + // If account exists domainId should too so + // calculate + // it. This condition might be hit for templates or + // entities which miss domainId in their tables + Account account = getAccount(entity.getAccountId()); + domainId = account != null ? account.getDomainId() : -1; + entityDomain = _domainMgr.getDomain(domainId); } } - // check that resources belong to the same account - + return entityDomain; } @Override public Long checkAccessAndSpecifyAuthority(Account caller, Long zoneId) { // We just care for resource domain admin for now. He should be permitted to see only his zone. - if (isResourceDomainAdmin(caller.getType())) { + if (isResourceDomainAdmin(caller.getAccountId())) { if (zoneId == null) return getZoneIdForAccount(caller); else if (zoneId.compareTo(getZoneIdForAccount(caller)) != 0) @@ -660,8 +712,10 @@ protected boolean cleanupAccount(AccountVO account, long callerUserId, Account c // delete the account from project accounts _projectAccountDao.removeAccountFromProjects(accountId); - //delete the account from group - _messageBus.publish(_name, MESSAGE_REMOVE_ACCOUNT_EVENT, PublishScope.LOCAL, accountId); + if (account.getType() != Account.ACCOUNT_TYPE_PROJECT) { + // delete the account from group + _messageBus.publish(_name, MESSAGE_REMOVE_ACCOUNT_EVENT, PublishScope.LOCAL, accountId); + } // delete all vm groups belonging to accont List groups = _vmGroupDao.listByAccountId(accountId); @@ -1099,6 +1153,9 @@ public UserAccount updateUser(UpdateUserCmd cmd) { // If the account is an admin type, return an error. We do not allow this Account account = _accountDao.findById(user.getAccountId()); + if (account == null) { + throw new InvalidParameterValueException("unable to find user account " + user.getAccountId()); + } // don't allow updating project account if (account.getType() == Account.ACCOUNT_TYPE_PROJECT) { @@ -1106,11 +1163,11 @@ public UserAccount updateUser(UpdateUserCmd cmd) { } // don't allow updating system account - if (account != null && (account.getId() == Account.ACCOUNT_ID_SYSTEM)) { + if (account.getId() == Account.ACCOUNT_ID_SYSTEM) { throw new PermissionDeniedException("user id : " + id + " is system account, update is not allowed"); } - checkAccess(CallContext.current().getCallingAccount(), AccessType.OperateEntry, true, account); + checkAccess(CallContext.current().getCallingAccount(), AccessType.OperateEntry, account); if (firstName != null) { if (firstName.isEmpty()) { @@ -1213,6 +1270,9 @@ public UserAccount disableUser(long userId) { } Account account = _accountDao.findById(user.getAccountId()); + if (account == null) { + throw new InvalidParameterValueException("unable to find user account " + user.getAccountId()); + } // don't allow disabling user belonging to project's account if (account.getType() == Account.ACCOUNT_TYPE_PROJECT) { @@ -1224,7 +1284,7 @@ public UserAccount disableUser(long userId) { throw new InvalidParameterValueException("User id : " + userId + " is a system user, disabling is not allowed"); } - checkAccess(caller, AccessType.OperateEntry, true, account); + checkAccess(caller, AccessType.OperateEntry, account); boolean success = doSetUserStatus(userId, State.disabled); if (success) { @@ -1252,6 +1312,9 @@ public UserAccount enableUser(final long userId) { } Account account = _accountDao.findById(user.getAccountId()); + if (account == null) { + throw new InvalidParameterValueException("unable to find user account " + user.getAccountId()); + } if (account.getType() == Account.ACCOUNT_TYPE_PROJECT) { throw new InvalidParameterValueException("Unable to find active user by id " + userId); @@ -1262,7 +1325,7 @@ public UserAccount enableUser(final long userId) { throw new InvalidParameterValueException("User id : " + userId + " is a system user, enabling is not allowed"); } - checkAccess(caller, AccessType.OperateEntry, true, account); + checkAccess(caller, AccessType.OperateEntry, account); boolean success = Transaction.execute(new TransactionCallback() { @Override @@ -1300,6 +1363,9 @@ public UserAccount lockUser(long userId) { } Account account = _accountDao.findById(user.getAccountId()); + if (account == null) { + throw new InvalidParameterValueException("unable to find user account " + user.getAccountId()); + } // don't allow to lock user of the account of type Project if (account.getType() == Account.ACCOUNT_TYPE_PROJECT) { @@ -1311,7 +1377,7 @@ public UserAccount lockUser(long userId) { throw new PermissionDeniedException("user id : " + userId + " is a system user, locking is not allowed"); } - checkAccess(caller, AccessType.OperateEntry, true, account); + checkAccess(caller, AccessType.OperateEntry, account); // make sure the account is enabled too // if the user is either locked already or disabled already, don't change state...only lock currently enabled @@ -1365,7 +1431,7 @@ boolean deleteUserAccount(long accountId) { // If the user is a System user, return an error. We do not allow this AccountVO account = _accountDao.findById(accountId); - if (account.getRemoved() != null) { + if (account == null || account.getRemoved() != null) { s_logger.info("The account:" + account.getAccountName() + " is already removed"); return true; } @@ -1375,7 +1441,7 @@ boolean deleteUserAccount(long accountId) { throw new InvalidParameterValueException("The specified account does not exist in the system"); } - checkAccess(caller, null, true, account); + checkAccess(caller, null, account); // don't allow to delete default account (system and admin) if (account.isDefault()) { @@ -1420,7 +1486,7 @@ public AccountVO enableAccount(String accountName, Long domainId, Long accountId // Check if user performing the action is allowed to modify this account Account caller = CallContext.current().getCallingAccount(); - checkAccess(caller, AccessType.OperateEntry, true, account); + checkAccess(caller, AccessType.OperateEntry, account); boolean success = enableAccount(account.getId()); if (success) { @@ -1454,7 +1520,7 @@ public AccountVO lockAccount(String accountName, Long domainId, Long accountId) throw new PermissionDeniedException("Account id : " + accountId + " is a system account, lock is not allowed"); } - checkAccess(caller, AccessType.OperateEntry, true, account); + checkAccess(caller, AccessType.OperateEntry, account); if (lockAccount(account.getId())) { CallContext.current().putContextParameter(Account.class, account.getUuid()); @@ -1484,7 +1550,7 @@ public AccountVO disableAccount(String accountName, Long domainId, Long accountI throw new PermissionDeniedException("Account id : " + accountId + " is a system account, disable is not allowed"); } - checkAccess(caller, AccessType.OperateEntry, true, account); + checkAccess(caller, AccessType.OperateEntry, account); if (disableAccount(account.getId())) { CallContext.current().putContextParameter(Account.class, account.getUuid()); @@ -1603,7 +1669,7 @@ public boolean deleteUser(DeleteUserCmd deleteUserCmd) { throw new InvalidParameterValueException("The user is default and can't be removed"); } - checkAccess(CallContext.current().getCallingAccount(), AccessType.OperateEntry, true, account); + checkAccess(CallContext.current().getCallingAccount(), AccessType.OperateEntry, account); CallContext.current().putContextParameter(User.class, user.getUuid()); return _userDao.remove(id); } @@ -1725,7 +1791,7 @@ public Account finalizeOwner(Account caller, String accountName, Long domainId, return getAccount(project.getProjectAccountId()); } - if (isAdmin(caller.getType()) && accountName != null && domainId != null) { + if (isAdmin(caller.getId()) && accountName != null && domainId != null) { Domain domain = _domainMgr.getDomain(domainId); if (domain == null) { throw new InvalidParameterValueException("Unable to find the domain by id=" + domainId); @@ -1738,7 +1804,7 @@ public Account finalizeOwner(Account caller, String accountName, Long domainId, checkAccess(caller, domain); return owner; - } else if (!isAdmin(caller.getType()) && accountName != null && domainId != null) { + } else if (!isAdmin(caller.getId()) && accountName != null && domainId != null) { if (!accountName.equals(caller.getAccountName()) || domainId.longValue() != caller.getDomainId()) { throw new PermissionDeniedException("Can't create/list resources for account " + accountName + " in domain " + domainId + ", permission denied"); } else { @@ -2099,7 +2165,7 @@ private UserAccount getUserAccount(String username, String password, Long domain UserAccount userAccount = _userAccountDao.getUserAccount(username, domainId); if (userAccount != null) { if (userAccount.getState().equalsIgnoreCase(Account.State.enabled.toString())) { - if (!isInternalAccount(userAccount.getType())) { + if (!isInternalAccount(userAccount.getId())) { // Internal accounts are not disabled int attemptsMade = userAccount.getLoginAttempts() + 1; if (updateIncorrectLoginCount) { @@ -2217,43 +2283,49 @@ public UserAccount getUserByApiKey(String apiKey) { return _userAccountDao.getUserByApiKey(apiKey); } + @Override public void buildACLSearchParameters(Account caller, Long id, String accountName, Long projectId, List permittedDomains, List permittedAccounts, List permittedResources, Ternary domainIdRecursiveListProject, boolean listAll, boolean forProjectInvitation, String action) { - //TODO: need to handle listAll flag + Long domainId = domainIdRecursiveListProject.first(); - if (domainId != null) { - // look for entity in the given domain - Domain domain = _domainDao.findById(domainId); - if (domain == null) { - throw new InvalidParameterValueException("Unable to find domain by id " + domainId); + Long accountId = null; + if (id == null) { + // if id is specified, it will ignore all other parameters + if (domainId != null) { + // look for entity in the given domain + Domain domain = _domainDao.findById(domainId); + if (domain == null) { + throw new InvalidParameterValueException("Unable to find domain by id " + domainId); + } + // check permissions + checkAccess(caller, domain); } - // check permissions - checkAccess(caller, domain); - } - if (accountName != null) { - if (projectId != null) { - throw new InvalidParameterValueException("Account and projectId can't be specified together"); - } + // specific account is specified, we need to filter contents to only show contents owned by that account. + if (accountName != null) { + if (projectId != null) { + throw new InvalidParameterValueException("Account and projectId can't be specified together"); + } - Account userAccount = null; - Domain domain = null; - if (domainId != null) { - userAccount = _accountDao.findActiveAccount(accountName, domainId); - domain = _domainDao.findById(domainId); - } else { - userAccount = _accountDao.findActiveAccount(accountName, caller.getDomainId()); - domain = _domainDao.findById(caller.getDomainId()); - } + Account userAccount = null; + Domain domain = null; + if (domainId != null) { + userAccount = _accountDao.findActiveAccount(accountName, domainId); + domain = _domainDao.findById(domainId); + } else { + userAccount = _accountDao.findActiveAccount(accountName, caller.getDomainId()); + domain = _domainDao.findById(caller.getDomainId()); + } - if (userAccount != null) { - //check permissions - checkAccess(caller, null, false, userAccount); - permittedAccounts.add(userAccount.getId()); - } else { - throw new InvalidParameterValueException("could not find account " + accountName + " in domain " + domain.getUuid()); + if (userAccount != null) { + //check permissions + checkAccess(caller, null, userAccount); + accountId = userAccount.getId(); + } else { + throw new InvalidParameterValueException("could not find account " + accountName + " in domain " + domain.getUuid()); + } } } @@ -2278,6 +2350,11 @@ public void buildACLSearchParameters(Account caller, Long id, String accountName } } } else { + AccessType accessType = AccessType.UseEntry; + if (listAll || id != null) { + // listAll = true or id given should show all resources that owner has ListEntry access type. + accessType = AccessType.ListEntry; + } domainIdRecursiveListProject.third(Project.ListProjectResourcesCriteria.SkipProjectResources); // search for policy permissions associated with caller to get all his authorized domains, accounts, and resources @@ -2288,18 +2365,41 @@ public void buildACLSearchParameters(Account caller, Long id, String accountName return; // no futher filtering QuerySelector qs = _querySelectors.get(0); - boolean grantedAll = qs.isGrantedAll(caller, action); + boolean grantedAll = qs.isGrantedAll(caller, action, accessType); + if ( grantedAll ){ - if ( domainId != null ){ + if (accountId != null) { + permittedAccounts.add(accountId); + domainIdRecursiveListProject.second(false); // isRecursive is only valid if only domainId is passed. + } else if (domainId != null) { permittedDomains.add(domainId); + } else { + domainIdRecursiveListProject.second(false); // isRecursive is only valid if only domainId is passed. } } else { - List grantedDomains = qs.getAuthorizedDomains(caller, action); - List grantedAccounts = qs.getAuthorizedAccounts(caller, action); - List grantedResources = qs.getAuthorizedResources(caller, action); + List grantedDomains = qs.getAuthorizedDomains(caller, action, accessType); + List grantedAccounts = qs.getAuthorizedAccounts(caller, action, accessType); + List grantedResources = qs.getAuthorizedResources(caller, action, accessType); - if (permittedAccounts.isEmpty() && domainId != null) { + if (accountId != null) { + // specific account filter is specified + if (grantedDomains.contains(domainId)) { + // the account domain is granted to the caller + permittedAccounts.add(accountId); + } + else if (grantedAccounts.contains(accountId)) { + permittedAccounts.add(accountId); + } else { + //TODO: we should also filter granted resources based on accountId passed. + // potential bug, if accountId is passed, it may show some granted resources that may not be owned by that account. + // to fix this, we need to change the interface to also pass ControlledEntity class to use EntityManager to find + // ControlledEntity instance to check accountId. But this has some issues for those non controlled entities, + // like NetworkACLItem + permittedResources.addAll(grantedResources); + } + domainIdRecursiveListProject.second(false); // isRecursive is only valid if only domainId is passed. + } else if (domainId != null) { // specific domain and no account is specified if (grantedDomains.contains(domainId)) { permittedDomains.add(domainId); @@ -2310,13 +2410,26 @@ public void buildACLSearchParameters(Account caller, Long id, String accountName permittedAccounts.add(acctId); } } + //TODO: we should also filter granted resources based on domainId passed. + // potential bug, if domainId is passed, it may show some granted resources that may not be in that domain. + // to fix this, we need to change the interface to also pass ControlledEntity class to use EntityManager to find + // ControlledEntity instance to check domainId. But this has some issues for those non controlled entities, + // like NetworkACLItem permittedResources.addAll(grantedResources); } - } else if (permittedAccounts.isEmpty()) { + } else { // neither domain nor account is not specified permittedDomains.addAll(grantedDomains); permittedAccounts.addAll(grantedAccounts); permittedResources.addAll(grantedResources); + domainIdRecursiveListProject.second(false); // isRecursive is only valid if only domainId is passed. + } + + if (permittedDomains.isEmpty() && permittedAccounts.isEmpty() && permittedResources.isEmpty()) { + // if at this point, all permitted arrays are empty, that means that caller cannot see anything, we put -1 in permittedAccounts + // to distinguish this case from the case that caller can see everything + permittedAccounts.add(-1L); + } } } @@ -2530,4 +2643,9 @@ public Long finalyzeAccountId(final String accountName, final Long domainId, fin } return null; } + + @Override + public UserAccount getUserAccountById(Long userId) { + return _userAccountDao.findById(userId); + } } diff --git a/server/src/com/cloud/user/DomainManagerImpl.java b/server/src/com/cloud/user/DomainManagerImpl.java index fbbe0c2870..fe6e530ccb 100644 --- a/server/src/com/cloud/user/DomainManagerImpl.java +++ b/server/src/com/cloud/user/DomainManagerImpl.java @@ -227,7 +227,11 @@ public Set getDomainParentIds(long domainId) { @Override public boolean removeDomain(long domainId) { - return _domainDao.remove(domainId); + boolean removed = _domainDao.remove(domainId); + if (removed) { + _messageBus.publish(_name, MESSAGE_REMOVE_DOMAIN_EVENT, PublishScope.LOCAL, domainId); + } + return removed; } @Override @@ -324,6 +328,9 @@ public boolean deleteDomain(DomainVO domain, Boolean cleanup) { " because it can't be removed due to resources referencing to it"); domain.setState(Domain.State.Active); _domainDao.update(domain.getId(), domain); + } else { + // succeeded in removing the domain + _messageBus.publish(_name, MESSAGE_REMOVE_DOMAIN_EVENT, PublishScope.LOCAL, domain.getId()); } } } diff --git a/server/src/com/cloud/vm/UserVmManager.java b/server/src/com/cloud/vm/UserVmManager.java index afe1002788..61e28d81bd 100755 --- a/server/src/com/cloud/vm/UserVmManager.java +++ b/server/src/com/cloud/vm/UserVmManager.java @@ -109,4 +109,6 @@ UserVm updateVirtualMachine(long id, String displayName, String group, Boolean h public void saveCustomOfferingDetails(long vmId, ServiceOffering serviceOffering); public void removeCustomOfferingDetails(long vmId); + + void generateUsageEvent(VirtualMachine vm, boolean isDisplay, String eventType); } diff --git a/server/src/com/cloud/vm/UserVmManagerImpl.java b/server/src/com/cloud/vm/UserVmManagerImpl.java index 393613a140..e7db877fdd 100755 --- a/server/src/com/cloud/vm/UserVmManagerImpl.java +++ b/server/src/com/cloud/vm/UserVmManagerImpl.java @@ -35,9 +35,6 @@ import javax.inject.Inject; import javax.naming.ConfigurationException; -import org.apache.commons.codec.binary.Base64; -import org.apache.log4j.Logger; - import org.apache.cloudstack.acl.ControlledEntity.ACLType; import org.apache.cloudstack.acl.SecurityChecker.AccessType; import org.apache.cloudstack.affinity.AffinityGroupService; @@ -47,7 +44,6 @@ import org.apache.cloudstack.api.ApiConstants; import org.apache.cloudstack.api.BaseCmd.HTTPMethod; import org.apache.cloudstack.api.command.admin.vm.AssignVMCmd; -import org.apache.cloudstack.api.command.admin.vm.ExpungeVMCmd; import org.apache.cloudstack.api.command.admin.vm.RecoverVMCmd; import org.apache.cloudstack.api.command.user.vm.AddNicToVMCmd; import org.apache.cloudstack.api.command.user.vm.DeployVMCmd; @@ -69,6 +65,9 @@ import org.apache.cloudstack.engine.orchestration.service.NetworkOrchestrationService; import org.apache.cloudstack.engine.orchestration.service.VolumeOrchestrationService; import org.apache.cloudstack.engine.service.api.OrchestrationService; +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.PrimaryDataStore; import org.apache.cloudstack.engine.subsystem.api.storage.TemplateDataFactory; import org.apache.cloudstack.engine.subsystem.api.storage.VolumeDataFactory; import org.apache.cloudstack.engine.subsystem.api.storage.VolumeInfo; @@ -80,11 +79,16 @@ import org.apache.cloudstack.framework.config.dao.ConfigurationDao; import org.apache.cloudstack.framework.jobs.AsyncJobManager; import org.apache.cloudstack.managed.context.ManagedContextRunnable; +import org.apache.cloudstack.storage.command.DeleteCommand; +import org.apache.cloudstack.storage.command.DettachCommand; 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.Answer; +import com.cloud.agent.api.Command; import com.cloud.agent.api.GetVmDiskStatsAnswer; import com.cloud.agent.api.GetVmDiskStatsCommand; import com.cloud.agent.api.GetVmStatsAnswer; @@ -93,6 +97,7 @@ import com.cloud.agent.api.StartAnswer; import com.cloud.agent.api.VmDiskStatsEntry; import com.cloud.agent.api.VmStatsEntry; +import com.cloud.agent.api.to.DiskTO; import com.cloud.agent.api.to.NicTO; import com.cloud.agent.api.to.VirtualMachineTO; import com.cloud.agent.manager.Commands; @@ -191,6 +196,7 @@ import com.cloud.service.ServiceOfferingVO; import com.cloud.service.dao.ServiceOfferingDao; import com.cloud.service.dao.ServiceOfferingDetailsDao; +import com.cloud.storage.DataStoreRole; import com.cloud.storage.DiskOfferingVO; import com.cloud.storage.GuestOSCategoryVO; import com.cloud.storage.GuestOSVO; @@ -204,6 +210,7 @@ import com.cloud.storage.VMTemplateVO; import com.cloud.storage.VMTemplateZoneVO; import com.cloud.storage.Volume; +import com.cloud.storage.VolumeApiService; import com.cloud.storage.VolumeVO; import com.cloud.storage.dao.DiskOfferingDao; import com.cloud.storage.dao.GuestOSCategoryDao; @@ -445,6 +452,10 @@ public enum UserVmCloneType { UUIDManager _uuidMgr; @Inject DeploymentPlanningManager _planningMgr; + @Inject + VolumeApiService _volumeService; + @Inject + DataStoreManager _dataStoreMgr; protected ScheduledExecutorService _executor = null; protected int _expungeInterval; @@ -520,7 +531,7 @@ public UserVm resetVMPassword(ResetVMPasswordCmd cmd, String password) throws Re throw new InvalidParameterValueException("Vm with id " + vmId + " is not in the right state"); } - _accountMgr.checkAccess(caller, null, true, userVm); + _accountMgr.checkAccess(caller, null, userVm); boolean result = resetVMPasswordInternal(vmId, password); @@ -626,7 +637,7 @@ public UserVm resetVMSSHKey(ResetVMSSHKeyCmd cmd) throws ResourceUnavailableExce + " in specified domain id"); } - _accountMgr.checkAccess(caller, null, true, userVm); + _accountMgr.checkAccess(caller, null, userVm); String password = null; String sshPublicKey = s.getPublicKey(); if (template != null && template.getEnablePassword()) { @@ -766,7 +777,7 @@ public UserVm upgradeVirtualMachine(UpgradeVMCmd cmd) throws ResourceAllocationE + "; make sure the virtual machine is stopped"); } - _accountMgr.checkAccess(caller, null, true, vmInstance); + _accountMgr.checkAccess(caller, null, vmInstance); // Check resource limits for CPU and Memory. Map customParameters = cmd.getDetails(); @@ -828,9 +839,10 @@ public UserVm upgradeVirtualMachine(UpgradeVMCmd cmd) throws ResourceAllocationE } // Generate usage event for VM upgrade - generateUsageEvent(newServiceOffering, cmd.getDetails(), _vmDao.findById(vmId), EventTypes.EVENT_VM_UPGRADE); + UserVmVO userVm = _vmDao.findById(vmId); + generateUsageEvent( userVm, userVm.isDisplayVm(), EventTypes.EVENT_VM_UPGRADE); - return _vmDao.findById(vmInstance.getId()); + return userVm; } @Override @@ -879,7 +891,7 @@ private UserVm upgradeStoppedVirtualMachine(Long vmId, Long svcOffId, Map allNics = _nicDao.listByVmId(vmInstance.getId()); for (NicVO nic : allNics) { @@ -977,18 +982,12 @@ public UserVm addNicToVirtualMachine(AddNicToVMCmd cmd) throws InvalidParameterV profile = new NicProfile(ipAddress, null); } - // Perform permission check on VM - _accountMgr.checkAccess(caller, null, true, vmInstance); - // Verify that zone is not Basic DataCenterVO dc = _dcDao.findById(vmInstance.getDataCenterId()); if (dc.getNetworkType() == DataCenter.NetworkType.Basic) { throw new CloudRuntimeException("Zone " + vmInstance.getDataCenterId() + ", has a NetworkType of Basic. Can't add a new NIC to a VM on a Basic Network"); } - // Perform account permission check on network - _accountMgr.checkAccess(caller, AccessType.UseEntry, false, network); - //ensure network belongs in zone if (network.getDataCenterId() != vmInstance.getDataCenterId()) { throw new CloudRuntimeException(vmInstance + " is in zone:" + vmInstance.getDataCenterId() + " but " + network + " is in zone:" + network.getDataCenterId()); @@ -1047,7 +1046,7 @@ public UserVm removeNicFromVirtualMachine(RemoveNicFromVMCmd cmd) throws Invalid } // Perform permission check on VM - _accountMgr.checkAccess(caller, null, true, vmInstance); + _accountMgr.checkAccess(caller, null, vmInstance); // Verify that zone is not Basic DataCenterVO dc = _dcDao.findById(vmInstance.getDataCenterId()); @@ -1061,7 +1060,7 @@ public UserVm removeNicFromVirtualMachine(RemoveNicFromVMCmd cmd) throws Invalid } // Perform account permission check on network - _accountMgr.checkAccess(caller, AccessType.UseEntry, false, network); + _accountMgr.checkAccess(caller, AccessType.UseEntry, network); boolean nicremoved = false; @@ -1103,7 +1102,7 @@ public UserVm updateDefaultNicForVirtualMachine(UpdateDefaultNicForVMCmd cmd) th } // Perform permission check on VM - _accountMgr.checkAccess(caller, null, true, vmInstance); + _accountMgr.checkAccess(caller, null, vmInstance); // Verify that zone is not Basic DataCenterVO dc = _dcDao.findById(vmInstance.getDataCenterId()); @@ -1184,13 +1183,13 @@ public UserVm updateDefaultNicForVirtualMachine(UpdateDefaultNicForVMCmd cmd) th String nicIdString = Long.toString(nic.getId()); long newNetworkOfferingId = network.getNetworkOfferingId(); UsageEventUtils.publishUsageEvent(EventTypes.EVENT_NETWORK_OFFERING_REMOVE, vmInstance.getAccountId(), vmInstance.getDataCenterId(), vmInstance.getId(), - oldNicIdString, oldNetworkOfferingId, null, 1L, VirtualMachine.class.getName(), vmInstance.getUuid()); + oldNicIdString, oldNetworkOfferingId, null, 1L, VirtualMachine.class.getName(), vmInstance.getUuid(), vmInstance.isDisplay()); UsageEventUtils.publishUsageEvent(EventTypes.EVENT_NETWORK_OFFERING_ASSIGN, vmInstance.getAccountId(), vmInstance.getDataCenterId(), vmInstance.getId(), nicIdString, - newNetworkOfferingId, null, 1L, VirtualMachine.class.getName(), vmInstance.getUuid()); + newNetworkOfferingId, null, 1L, VirtualMachine.class.getName(), vmInstance.getUuid(), vmInstance.isDisplay()); UsageEventUtils.publishUsageEvent(EventTypes.EVENT_NETWORK_OFFERING_REMOVE, vmInstance.getAccountId(), vmInstance.getDataCenterId(), vmInstance.getId(), nicIdString, - newNetworkOfferingId, null, 0L, VirtualMachine.class.getName(), vmInstance.getUuid()); + newNetworkOfferingId, null, 0L, VirtualMachine.class.getName(), vmInstance.getUuid(), vmInstance.isDisplay()); UsageEventUtils.publishUsageEvent(EventTypes.EVENT_NETWORK_OFFERING_ASSIGN, vmInstance.getAccountId(), vmInstance.getDataCenterId(), vmInstance.getId(), - oldNicIdString, oldNetworkOfferingId, null, 0L, VirtualMachine.class.getName(), vmInstance.getUuid()); + oldNicIdString, oldNetworkOfferingId, null, 0L, VirtualMachine.class.getName(), vmInstance.getUuid(), vmInstance.isDisplay()); return _vmDao.findById(vmInstance.getId()); } @@ -1212,11 +1211,11 @@ public UserVm upgradeVirtualMachine(ScaleVMCmd cmd) throws ResourceUnavailableEx UserVmVO vmInstance = _vmDao.findById(vmId); if (vmInstance.getState().equals(State.Stopped)) { // Generate usage event for VM upgrade - generateUsageEvent(_offeringDao.findById(newServiceOfferingId), cmd.getDetails(), _vmDao.findById(vmId), EventTypes.EVENT_VM_UPGRADE); + generateUsageEvent(vmInstance, vmInstance.isDisplayVm(), EventTypes.EVENT_VM_UPGRADE); } if (vmInstance.getState().equals(State.Running)) { // Generate usage event for Dynamic scaling of VM - generateUsageEvent(_offeringDao.findById(newServiceOfferingId), cmd.getDetails(), _vmDao.findById(vmId), EventTypes.EVENT_VM_UPGRADE); + generateUsageEvent( vmInstance, vmInstance.isDisplayVm(), EventTypes.EVENT_VM_DYNAMIC_SCALE); } return vmInstance; } else { @@ -1285,7 +1284,7 @@ private boolean upgradeRunningVirtualMachine(Long vmId, Long newServiceOfferingI throw new InvalidParameterValueException("This operation not permitted for this hypervisor of the vm"); } - _accountMgr.checkAccess(caller, null, true, vmInstance); + _accountMgr.checkAccess(caller, null, vmInstance); //Check if its a scale "up" ServiceOfferingVO newServiceOffering = _offeringDao.findById(newServiceOfferingId); @@ -1494,7 +1493,7 @@ public UserVm recoverVirtualMachine(RecoverVMCmd cmd) throws ResourceAllocationE } // check permissions - _accountMgr.checkAccess(caller, null, true, vm); + _accountMgr.checkAccess(caller, null, vm); if (vm.getRemoved() != null) { if (s_logger.isDebugEnabled()) { @@ -1557,8 +1556,8 @@ public void doInTransactionWithoutResult(TransactionStatus status) throws Resour offeringId = offering.getId(); } } - UsageEventUtils.publishUsageEvent(EventTypes.EVENT_VOLUME_CREATE, volume.getAccountId(), volume.getDataCenterId(), volume.getId(), volume.getName(), - offeringId, templateId, volume.getSize(), Volume.class.getName(), volume.getUuid()); + UsageEventUtils.publishUsageEvent(EventTypes.EVENT_VOLUME_CREATE, volume.getAccountId(), volume.getDataCenterId(), volume.getId(), volume.getName(), + offeringId, templateId, volume.getSize(), Volume.class.getName(), volume.getUuid(), volume.isDisplayVolume()); } } @@ -1610,7 +1609,7 @@ public boolean configure(String name, Map params) throws Configu _itMgr.registerGuru(VirtualMachine.Type.User, this); - VirtualMachine.State.getStateMachine().registerListener(new UserVmStateListener(_usageEventDao, _networkDao, _nicDao, _offeringDao)); + VirtualMachine.State.getStateMachine().registerListener(new UserVmStateListener(_usageEventDao, _networkDao, _nicDao, _offeringDao, _vmDao, this)); String value = _configDao.getValue(Config.SetVmInternalNameUsingDisplayName.key()); _instanceNameFlag = (value == null) ? false : Boolean.parseBoolean(value); @@ -1799,7 +1798,7 @@ protected void runInContext() { } for (UserVmVO vm : vms) { try { - expunge(vm, _accountMgr.getSystemUser().getId(), _accountMgr.getSystemAccount()); + expungeVm(vm.getId()); } catch (Exception e) { s_logger.warn("Unable to expunge " + vm, e); } @@ -1829,6 +1828,7 @@ public UserVm updateVirtualMachine(UpdateVMCmd cmd) throws ResourceUnavailableEx String userData = cmd.getUserData(); Boolean isDynamicallyScalable = cmd.isDynamicallyScalable(); String hostName = cmd.getHostName(); + Account caller = CallContext.current().getCallingAccount(); // Input validation and permission checks UserVmVO vmInstance = _vmDao.findById(id.longValue()); @@ -1836,19 +1836,85 @@ public UserVm updateVirtualMachine(UpdateVMCmd cmd) throws ResourceUnavailableEx throw new InvalidParameterValueException("unable to find virtual machine with id " + id); } - _accountMgr.checkAccess(CallContext.current().getCallingAccount(), null, true, vmInstance); + _accountMgr.checkAccess(CallContext.current().getCallingAccount(), null, vmInstance); //If the flag is specified and is changed if (isDisplayVm != null && isDisplayVm != vmInstance.isDisplayVm()) { + + //update vm + vmInstance.setDisplayVm(isDisplayVm); + + // Resource limit changes ServiceOffering offering = _serviceOfferingDao.findByIdIncludingRemoved(vmInstance.getServiceOfferingId()); _resourceLimitMgr.changeResourceCount(vmInstance.getAccountId(), ResourceType.user_vm, isDisplayVm); _resourceLimitMgr.changeResourceCount(vmInstance.getAccountId(), ResourceType.cpu, isDisplayVm, new Long(offering.getCpu())); _resourceLimitMgr.changeResourceCount(vmInstance.getAccountId(), ResourceType.memory, isDisplayVm, new Long(offering.getRamSize())); + + // Usage + saveUsageEvent(vmInstance); + + // take care of the root volume as well. + List rootVols = _volsDao.findByInstanceAndType(id, Volume.Type.ROOT); + if(!rootVols.isEmpty()){ + _volumeService.updateDisplay(rootVols.get(0), isDisplayVm); + } + + // take care of the data volumes as well. + List dataVols = _volsDao.findByInstanceAndType(id, Volume.Type.DATADISK); + for(Volume dataVol : dataVols){ + _volumeService.updateDisplay(dataVol, isDisplayVm); + } + } return updateVirtualMachine(id, displayName, group, ha, isDisplayVm, osTypeId, userData, isDynamicallyScalable, cmd.getHttpMethod(), cmd.getCustomId(), hostName); } + private void saveUsageEvent(UserVmVO vm) { + + // If vm not destroyed + if( vm.getState() != State.Destroyed && vm.getState() != State.Expunging && vm.getState() != State.Error){ + + if(vm.isDisplayVm()){ + //1. Allocated VM Usage Event + generateUsageEvent(vm, true, EventTypes.EVENT_VM_CREATE); + + if(vm.getState() == State.Running || vm.getState() == State.Stopping){ + //2. Running VM Usage Event + generateUsageEvent(vm, true, EventTypes.EVENT_VM_START); + + // 3. Network offering usage + generateNetworkUsageForVm(vm, true, EventTypes.EVENT_NETWORK_OFFERING_ASSIGN); + } + + }else { + //1. Allocated VM Usage Event + generateUsageEvent(vm, true, EventTypes.EVENT_VM_DESTROY); + + if(vm.getState() == State.Running || vm.getState() == State.Stopping){ + //2. Running VM Usage Event + generateUsageEvent(vm, true, EventTypes.EVENT_VM_STOP); + + // 3. Network offering usage + generateNetworkUsageForVm(vm, true, EventTypes.EVENT_NETWORK_OFFERING_REMOVE); + } + } + } + + } + + private void generateNetworkUsageForVm(VirtualMachine vm, boolean isDisplay, String eventType){ + + List nics = _nicDao.listByVmId(vm.getId()); + for (NicVO nic : nics) { + NetworkVO network = _networkDao.findById(nic.getNetworkId()); + long isDefault = (nic.isDefaultNic()) ? 1 : 0; + UsageEventUtils.publishUsageEvent(eventType, vm.getAccountId(), vm.getDataCenterId(), vm.getId(), + Long.toString(nic.getId()), network.getNetworkOfferingId(), null, isDefault, vm.getClass().getName(), vm.getUuid(), isDisplay); + } + + } + @Override public UserVm updateVirtualMachine(long id, String displayName, String group, Boolean ha, Boolean isDisplayVmEnabled, Long osTypeId, String userData, Boolean isDynamicallyScalable, HTTPMethod httpMethod, String customId, String hostName) throws ResourceUnavailableException, InsufficientCapacityException { @@ -1985,7 +2051,7 @@ public UserVm rebootVirtualMachine(RebootVMCmd cmd) throws InsufficientCapacityE throw new InvalidParameterValueException("unable to find a virtual machine with id " + vmId); } - _accountMgr.checkAccess(caller, null, true, vmInstance); + _accountMgr.checkAccess(caller, null, vmInstance); // If the VM is Volatile in nature, on reboot discard the VM's root disk and create a new root disk for it: by calling restoreVM long serviceOfferingId = vmInstance.getServiceOfferingId(); @@ -2008,7 +2074,7 @@ public UserVm destroyVm(DestroyVMCmd cmd) throws ResourceUnavailableException, C long vmId = cmd.getId(); boolean expunge = cmd.getExpunge(); - if (!_accountMgr.isAdmin(ctx.getCallingAccount().getType()) && expunge) { + if (!_accountMgr.isAdmin(ctx.getCallingAccount().getId()) && expunge) { throw new PermissionDeniedException("Parameter " + ApiConstants.EXPUNGE + " can be passed by Admin only"); } @@ -2023,12 +2089,6 @@ public UserVm destroyVm(DestroyVMCmd cmd) throws ResourceUnavailableException, C return destroyedVm; } - @Override - @ActionEvent(eventType = EventTypes.EVENT_VM_EXPUNGE, eventDescription = "expunging Vm", async = true) - public UserVm expungeVm(ExpungeVMCmd cmd) throws ResourceUnavailableException, ConcurrentOperationException { - return expungeVm(cmd.getId()); - } - @Override @DB public InstanceGroupVO createVmGroup(CreateVMGroupCmd cmd) { @@ -2089,7 +2149,7 @@ public boolean deleteVmGroup(DeleteVMGroupCmd cmd) { throw new InvalidParameterValueException("unable to find a vm group with id " + groupId); } - _accountMgr.checkAccess(caller, null, true, group); + _accountMgr.checkAccess(caller, null, group); return deleteVmGroup(groupId); } @@ -2223,7 +2283,7 @@ public UserVm createBasicSecurityGroupVirtualMachine(DataCenter zone, ServiceOff List networkList = new ArrayList(); // Verify that caller can perform actions in behalf of vm owner - _accountMgr.checkAccess(caller, null, true, owner); + _accountMgr.checkAccess(caller, null, owner); // Get default guest network in Basic zone Network defaultNetwork = _networkModel.getExclusiveGuestNetwork(zone.getId()); @@ -2278,7 +2338,7 @@ public UserVm createAdvancedSecurityGroupVirtualMachine(DataCenter zone, Service boolean isVmWare = (template.getHypervisorType() == HypervisorType.VMware || (hypervisor != null && hypervisor == HypervisorType.VMware)); // Verify that caller can perform actions in behalf of vm owner - _accountMgr.checkAccess(caller, null, true, owner); + _accountMgr.checkAccess(caller, null, owner); // If no network is specified, find system security group enabled network if (networkIdList == null || networkIdList.isEmpty()) { @@ -2336,7 +2396,7 @@ public UserVm createAdvancedSecurityGroupVirtualMachine(DataCenter zone, Service // Perform account permission check if (network.getAclType() == ACLType.Account) { - _accountMgr.checkAccess(caller, AccessType.UseEntry, false, network); + _accountMgr.checkAccess(owner, AccessType.UseEntry, network); } networkList.add(network); } @@ -2382,7 +2442,7 @@ public UserVm createAdvancedVirtualMachine(DataCenter zone, ServiceOffering serv List networkList = new ArrayList(); // Verify that caller can perform actions in behalf of vm owner - _accountMgr.checkAccess(caller, null, true, owner); + _accountMgr.checkAccess(caller, null, owner); List vpcSupportedHTypes = _vpcMgr.getSupportedVpcHypervisors(); if (networkIdList == null || networkIdList.isEmpty()) { @@ -2447,7 +2507,7 @@ public UserVm createAdvancedVirtualMachine(DataCenter zone, ServiceOffering serv } } - _networkModel.checkNetworkPermissions(owner, network); + _networkModel.checkNetworkPermissions(owner, network, AccessType.UseEntry); // don't allow to use system networks NetworkOffering networkOffering = _entityMgr.findById(NetworkOffering.class, network.getNetworkOfferingId()); @@ -2476,7 +2536,7 @@ protected UserVm createVirtualMachine(DataCenter zone, ServiceOffering serviceOf List affinityGroupIdList, Map customParameters, String customId) throws InsufficientCapacityException, ResourceUnavailableException, ConcurrentOperationException, StorageUnavailableException, ResourceAllocationException { - _accountMgr.checkAccess(caller, null, true, owner); + _accountMgr.checkAccess(caller, null, owner); if (owner.getState() == Account.State.disabled) { throw new PermissionDeniedException("The owner of vm to deploy is disabled: " + owner); @@ -2552,7 +2612,7 @@ protected UserVm createVirtualMachine(DataCenter zone, ServiceOffering serviceOf throw new InvalidParameterValueException("Unable to find security group by id " + securityGroupId); } else { // verify permissions - _accountMgr.checkAccess(caller, null, true, owner, sg); + _accountMgr.checkAccess(owner, AccessType.UseEntry, sg); } } } @@ -2568,27 +2628,7 @@ protected UserVm createVirtualMachine(DataCenter zone, ServiceOffering serviceOf + " , Please try again after removing the affinity group"); } else { // verify permissions - if (ag.getAclType() == ACLType.Domain) { - _accountMgr.checkAccess(caller, null, false, 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.getId())) { - if (!_affinityGroupService.isAffinityGroupAvailableInDomain(ag.getId(), owner.getDomainId())) { - throw new PermissionDeniedException("Affinity Group " + ag + " does not belong to the VM's domain"); - } - } - } else { - _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.getId())) { - if (ag.getAccountId() != owner.getAccountId()) { - throw new PermissionDeniedException("Affinity Group " + ag + " does not belong to the VM's account"); - } - } - } + _accountMgr.checkAccess(owner, AccessType.UseEntry, ag); } } } @@ -2614,10 +2654,7 @@ protected UserVm createVirtualMachine(DataCenter zone, ServiceOffering serviceOf } // Check templates permissions - if (!template.isPublicTemplate()) { - Account templateOwner = _accountMgr.getAccount(template.getAccountId()); - _accountMgr.checkAccess(owner, null, true, templateOwner); - } + _accountMgr.checkAccess(owner, AccessType.UseEntry, template); // check if the user data is correct validateUserData(userData, httpmethod); @@ -2642,17 +2679,12 @@ protected UserVm createVirtualMachine(DataCenter zone, ServiceOffering serviceOf boolean securityGroupEnabled = false; boolean vpcNetwork = false; for (NetworkVO network : networkList) { - if (network.getDataCenterId() != zone.getId()) { + if ((network.getDataCenterId() != zone.getId()) && !network.isStrechedL2Network()) { throw new InvalidParameterValueException("Network id=" + network.getId() + " doesn't belong to zone " + zone.getId()); } - //relax the check if the caller is admin account - if (caller.getType() != Account.ACCOUNT_TYPE_ADMIN) { - if (!(network.getGuestType() == Network.GuestType.Shared && network.getAclType() == ACLType.Domain) - && !(network.getAclType() == ACLType.Account && network.getAccountId() == accountId)) { - throw new InvalidParameterValueException("only shared network or isolated network with the same account_id can be added to vm"); - } - } + // Perform account permission check on network + _accountMgr.checkAccess(owner, AccessType.UseEntry, network); IpAddresses requestedIpPair = null; if (requestedIps != null && !requestedIps.isEmpty()) { @@ -2835,11 +2867,31 @@ public UserVmVO doInTransaction(TransactionStatus status) throws InsufficientCap vm.setIsoId(template.getId()); } Long rootDiskSize = null; + // custom root disk size, resizes base template to larger size if (customParameters.containsKey("rootdisksize")) { if (NumbersUtil.parseLong(customParameters.get("rootdisksize"), -1) <= 0) { throw new InvalidParameterValueException("rootdisk size should be a non zero number."); } - rootDiskSize = Long.parseLong(customParameters.get("rootDisksize")); + rootDiskSize = Long.parseLong(customParameters.get("rootdisksize")); + + // only KVM supports rootdisksize override + if (hypervisor != HypervisorType.KVM) { + throw new InvalidParameterValueException("Hypervisor " + hypervisor + " does not support rootdisksize override"); + } + + // rotdisksize must be larger than template + VMTemplateVO templateVO = _templateDao.findById(template.getId()); + if (templateVO == null) { + throw new InvalidParameterValueException("Unable to look up template by id " + template.getId()); + } + + if ((rootDiskSize << 30) < templateVO.getSize()) { + throw new InvalidParameterValueException("unsupported: rootdisksize override is smaller than template size " + templateVO.getSize()); + } else { + s_logger.debug("rootdisksize of " + (rootDiskSize << 30) + " was larger than template size of " + templateVO.getSize()); + } + + s_logger.debug("found root disk size of " + rootDiskSize); customParameters.remove("rootdisksize"); } @@ -2915,10 +2967,10 @@ public UserVmVO doInTransaction(TransactionStatus status) throws InsufficientCap if (!offering.isDynamic()) { UsageEventUtils.publishUsageEvent(EventTypes.EVENT_VM_CREATE, accountId, zone.getId(), vm.getId(), vm.getHostName(), offering.getId(), template.getId(), - hypervisorType.toString(), VirtualMachine.class.getName(), vm.getUuid()); + hypervisorType.toString(), VirtualMachine.class.getName(), vm.getUuid(), vm.isDisplayVm()); } else { UsageEventUtils.publishUsageEvent(EventTypes.EVENT_VM_CREATE, accountId, zone.getId(), vm.getId(), vm.getHostName(), offering.getId(), template.getId(), - hypervisorType.toString(), VirtualMachine.class.getName(), vm.getUuid(), customParameters); + hypervisorType.toString(), VirtualMachine.class.getName(), vm.getUuid(), customParameters, vm.isDisplayVm()); } //Update Resource Count for the given account @@ -2928,13 +2980,22 @@ public UserVmVO doInTransaction(TransactionStatus status) throws InsufficientCap }); } - private void generateUsageEvent(ServiceOfferingVO serviceOffering, Map customParameters, UserVmVO vm, String eventType) { + @Override + public void generateUsageEvent(VirtualMachine vm, boolean isDisplay, String eventType){ + ServiceOfferingVO serviceOffering = _offeringDao.findById(vm.getId(), vm.getServiceOfferingId()); if (!serviceOffering.isDynamic()) { - UsageEventUtils.publishUsageEvent(eventType, vm.getAccountId(), vm.getDataCenterId(), vm.getId(), vm.getHostName(), serviceOffering.getId(), vm.getTemplateId(), vm - .getHypervisorType().toString(), VirtualMachine.class.getName(), vm.getUuid()); - } else { - UsageEventUtils.publishUsageEvent(eventType, vm.getAccountId(), vm.getDataCenterId(), vm.getId(), vm.getHostName(), serviceOffering.getId(), vm.getTemplateId(), vm - .getHypervisorType().toString(), VirtualMachine.class.getName(), vm.getUuid(), customParameters); + UsageEventUtils.publishUsageEvent(eventType, vm.getAccountId(), vm.getDataCenterId(), vm.getId(), + vm.getHostName(), serviceOffering.getId(), vm.getTemplateId(), vm.getHypervisorType().toString(), + VirtualMachine.class.getName(), vm.getUuid(), isDisplay); + } + else { + Map customParameters = new HashMap(); + customParameters.put(UsageEventVO.DynamicParameters.cpuNumber.name(), serviceOffering.getCpu().toString()); + customParameters.put(UsageEventVO.DynamicParameters.cpuSpeed.name(), serviceOffering.getSpeed().toString()); + customParameters.put(UsageEventVO.DynamicParameters.memory.name(), serviceOffering.getRamSize().toString()); + UsageEventUtils.publishUsageEvent(eventType, vm.getAccountId(), vm.getDataCenterId(), vm.getId(), + vm.getHostName(), serviceOffering.getId(), vm.getTemplateId(), vm.getHypervisorType().toString(), + VirtualMachine.class.getName(), vm.getUuid(), customParameters, isDisplay); } } @@ -3104,7 +3165,7 @@ public boolean finalizeStart(VirtualMachineProfile profile, long hostId, Command NetworkVO network = _networkDao.findById(nic.getNetworkId()); long isDefault = (nic.isDefaultNic()) ? 1 : 0; UsageEventUtils.publishUsageEvent(EventTypes.EVENT_NETWORK_OFFERING_ASSIGN, vm.getAccountId(), vm.getDataCenterId(), vm.getId(), Long.toString(nic.getId()), - network.getNetworkOfferingId(), null, isDefault, VirtualMachine.class.getName(), vm.getUuid()); + network.getNetworkOfferingId(), null, isDefault, VirtualMachine.class.getName(), vm.getUuid(), vm.isDisplay()); if (network.getTrafficType() == TrafficType.Guest) { originalIp = nic.getIp4Address(); guestNic = nic; @@ -3246,7 +3307,7 @@ public Pair> startVirtualMach throw new InvalidParameterValueException("unable to find a virtual machine with id " + vmId); } - _accountMgr.checkAccess(callerAccount, null, true, vm); + _accountMgr.checkAccess(callerAccount, null, vm); Account owner = _accountDao.findById(vm.getAccountId()); @@ -3389,7 +3450,7 @@ public UserVm destroyVm(long vmId) throws ResourceUnavailableException, Concurre for (VolumeVO volume : volumes) { if (volume.getVolumeType().equals(Volume.Type.ROOT)) { UsageEventUtils.publishUsageEvent(EventTypes.EVENT_VOLUME_DELETE, volume.getAccountId(), volume.getDataCenterId(), volume.getId(), volume.getName(), - Volume.class.getName(), volume.getUuid()); + Volume.class.getName(), volume.getUuid(), volume.isDisplayVolume()); } } @@ -3424,12 +3485,12 @@ public void collectVmDiskStatistics(final UserVmVO userVm) { try { diskStatsAnswer = (GetVmDiskStatsAnswer)_agentMgr.easySend(hostId, new GetVmDiskStatsCommand(vmNames, host.getGuid(), host.getName())); } catch (Exception e) { - s_logger.warn("Error while collecting disk stats for vm: " + userVm.getHostName() + " from host: " + host.getName(), e); + s_logger.warn("Error while collecting disk stats for vm: " + userVm.getInstanceName() + " from host: " + host.getName(), e); return; } if (diskStatsAnswer != null) { if (!diskStatsAnswer.getResult()) { - s_logger.warn("Error while collecting disk stats vm: " + userVm.getHostName() + " from host: " + host.getName() + "; details: " + diskStatsAnswer.getDetails()); + s_logger.warn("Error while collecting disk stats vm: " + userVm.getInstanceName() + " from host: " + host.getName() + "; details: " + diskStatsAnswer.getDetails()); return; } try { @@ -3529,6 +3590,7 @@ public void doInTransactionWithoutResult(TransactionStatus status) { } @Override + @ActionEvent(eventType = EventTypes.EVENT_VM_EXPUNGE, eventDescription = "expunging Vm", async = true) public UserVm expungeVm(long vmId) throws ResourceUnavailableException, ConcurrentOperationException { Account caller = CallContext.current().getCallingAccount(); Long userId = caller.getId(); @@ -3552,7 +3614,7 @@ public UserVm expungeVm(long vmId) throws ResourceUnavailableException, Concurre throw ex; } - _accountMgr.checkAccess(caller, null, true, vm); + _accountMgr.checkAccess(caller, null, vm); boolean status; @@ -3622,7 +3684,12 @@ public VirtualMachine vmStorageMigration(Long vmId, StoragePool destPool) { throw new InvalidParameterValueException("Data disks attached to the vm, can not migrate. Need to dettach data disks at first"); } - HypervisorType destHypervisorType = _clusterDao.findById(destPool.getClusterId()).getHypervisorType(); + HypervisorType destHypervisorType = destPool.getHypervisor(); + if (destHypervisorType == null) { + destHypervisorType = _clusterDao.findById( + destPool.getClusterId()).getHypervisorType(); + } + if (vm.getHypervisorType() != destHypervisorType) { throw new InvalidParameterValueException("hypervisor is not compatible: dest: " + destHypervisorType.toString() + ", vm: " + vm.getHypervisorType().toString()); } @@ -4027,7 +4094,7 @@ public VirtualMachine migrateVirtualMachineWithVolume(Long vmId, Host destinatio } List vmVolumes = _volsDao.findUsableVolumesForInstance(vm.getId()); - Map volToPoolObjectMap = new HashMap(); + Map volToPoolObjectMap = new HashMap(); if (!isVMUsingLocalStorage(vm) && destinationHost.getClusterId().equals(srcHost.getClusterId())) { if (volumeToPool.isEmpty()) { // If the destination host is in the same cluster and volumes do not have to be migrated across pools @@ -4051,7 +4118,7 @@ public VirtualMachine migrateVirtualMachineWithVolume(Long vmId, Host destinatio if (!vmVolumes.contains(volume)) { throw new InvalidParameterValueException("There volume " + volume + " doesn't belong to " + "the virtual machine " + vm + " that has to be migrated"); } - volToPoolObjectMap.put(volume, pool); + volToPoolObjectMap.put(Long.valueOf(volume.getId()), Long.valueOf(pool.getId())); } } } @@ -4128,8 +4195,8 @@ public UserVm moveVMToUser(final AssignVMCmd cmd) throws ResourceAllocationExcep } //check caller has access to both the old and new account - _accountMgr.checkAccess(caller, null, true, oldAccount); - _accountMgr.checkAccess(caller, null, true, newAccount); + _accountMgr.checkAccess(caller, null, oldAccount); + _accountMgr.checkAccess(caller, null, newAccount); // make sure the accounts are not same if (oldAccount.getAccountId() == newAccount.getAccountId()) { @@ -4182,7 +4249,7 @@ public UserVm moveVMToUser(final AssignVMCmd cmd) throws ResourceAllocationExcep VirtualMachineTemplate template = _templateDao.findById(vm.getTemplateId()); if (!template.isPublicTemplate()) { Account templateOwner = _accountMgr.getAccount(template.getAccountId()); - _accountMgr.checkAccess(newAccount, null, true, templateOwner); + _accountMgr.checkAccess(newAccount, null, templateOwner); } // VV 5: check the new account can create vm in the domain @@ -4194,7 +4261,7 @@ public UserVm moveVMToUser(final AssignVMCmd cmd) throws ResourceAllocationExcep public void doInTransactionWithoutResult(TransactionStatus status) { //generate destroy vm event for usage UsageEventUtils.publishUsageEvent(EventTypes.EVENT_VM_DESTROY, vm.getAccountId(), vm.getDataCenterId(), vm.getId(), vm.getHostName(), vm.getServiceOfferingId(), - vm.getTemplateId(), vm.getHypervisorType().toString(), VirtualMachine.class.getName(), vm.getUuid()); + vm.getTemplateId(), vm.getHypervisorType().toString(), VirtualMachine.class.getName(), vm.getUuid(), vm.isDisplayVm()); // update resource counts for old account resourceCountDecrement(oldAccount.getAccountId(), vm.isDisplayVm(), new Long(offering.getCpu()), new Long(offering.getRamSize())); @@ -4206,20 +4273,20 @@ public void doInTransactionWithoutResult(TransactionStatus status) { // OS 2: update volume for (VolumeVO volume : volumes) { - UsageEventUtils.publishUsageEvent(EventTypes.EVENT_VOLUME_DELETE, volume.getAccountId(), volume.getDataCenterId(), volume.getId(), volume.getName(), - Volume.class.getName(), volume.getUuid()); + UsageEventUtils.publishUsageEvent(EventTypes.EVENT_VOLUME_DELETE, volume.getAccountId(), volume.getDataCenterId(), volume.getId(), volume.getName(), + Volume.class.getName(), volume.getUuid(), volume.isDisplayVolume()); _resourceLimitMgr.decrementResourceCount(oldAccount.getAccountId(), ResourceType.volume); - _resourceLimitMgr.decrementResourceCount(oldAccount.getAccountId(), ResourceType.primary_storage, new Long(volume.getSize())); + _resourceLimitMgr.decrementResourceCount(oldAccount.getAccountId(), ResourceType.primary_storage, new Long(volume.getSize())); volume.setAccountId(newAccount.getAccountId()); volume.setDomainId(newAccount.getDomainId()); _volsDao.persist(volume); _resourceLimitMgr.incrementResourceCount(newAccount.getAccountId(), ResourceType.volume); - _resourceLimitMgr.incrementResourceCount(newAccount.getAccountId(), ResourceType.primary_storage, new Long(volume.getSize())); - UsageEventUtils.publishUsageEvent(EventTypes.EVENT_VOLUME_CREATE, volume.getAccountId(), volume.getDataCenterId(), volume.getId(), volume.getName(), - volume.getDiskOfferingId(), volume.getTemplateId(), volume.getSize(), Volume.class.getName(), volume.getUuid()); + _resourceLimitMgr.incrementResourceCount(newAccount.getAccountId(), ResourceType.primary_storage, new Long(volume.getSize())); + UsageEventUtils.publishUsageEvent(EventTypes.EVENT_VOLUME_CREATE, volume.getAccountId(), volume.getDataCenterId(), volume.getId(), volume.getName(), + volume.getDiskOfferingId(), volume.getTemplateId(), volume.getSize(), Volume.class.getName(), volume.getUuid(), volume.isDisplayVolume()); //snapshots: mark these removed in db List snapshots = _snapshotDao.listByVolumeIdIncludingRemoved(volume.getId()); - for (SnapshotVO snapshot : snapshots) { + for (SnapshotVO snapshot : snapshots) { _snapshotDao.remove(snapshot.getId()); } } @@ -4229,7 +4296,7 @@ public void doInTransactionWithoutResult(TransactionStatus status) { //generate usage events to account for this change UsageEventUtils.publishUsageEvent(EventTypes.EVENT_VM_CREATE, vm.getAccountId(), vm.getDataCenterId(), vm.getId(), vm.getHostName(), vm.getServiceOfferingId(), - vm.getTemplateId(), vm.getHypervisorType().toString(), VirtualMachine.class.getName(), vm.getUuid()); + vm.getTemplateId(), vm.getHypervisorType().toString(), VirtualMachine.class.getName(), vm.getUuid(), vm.isDisplayVm()); } }); @@ -4332,7 +4399,7 @@ public void doInTransactionWithoutResult(TransactionStatus status) { throw ex; } - _networkModel.checkNetworkPermissions(newAccount, network); + _networkModel.checkNetworkPermissions(newAccount, network, AccessType.UseEntry); // don't allow to use system networks NetworkOffering networkOffering = _entityMgr.findById(NetworkOffering.class, network.getNetworkOfferingId()); @@ -4439,7 +4506,7 @@ public UserVm restoreVM(RestoreVMCmd cmd) throws InsufficientCapacityException, throw ex; } - _accountMgr.checkAccess(caller, null, true, vm); + _accountMgr.checkAccess(caller, null, vm); return restoreVMInternal(caller, vm, newTemplateId); } @@ -4489,7 +4556,7 @@ public UserVm restoreVMInternal(Account caller, UserVmVO vm, Long newTemplateId) //newTemplateId can be either template or ISO id. In the following snippet based on the vm deployment (from template or ISO) it is handled accordingly if (newTemplateId != null) { template = _templateDao.findById(newTemplateId); - _accountMgr.checkAccess(caller, null, true, template); + _accountMgr.checkAccess(caller, null, template); if (isISO) { if (!template.getFormat().equals(ImageFormat.ISO)) { throw new InvalidParameterValueException("Invalid ISO id provided to restore the VM "); @@ -4546,11 +4613,14 @@ public UserVm restoreVMInternal(Account caller, UserVmVO vm, Long newTemplateId) _resourceLimitMgr.incrementResourceCount(vm.getAccountId(), ResourceType.volume); } + handleManagedStorage(vm, root); + _volsDao.attachVolume(newVol.getId(), vmId, newVol.getDeviceId()); /* Detach and destory the old root volume */ _volsDao.detachVolume(root.getId()); + volumeMgr.destroyVolume(root); // For VMware hypervisor since the old root volume is replaced by the new root volume, force expunge old root volume if it has been created in storage @@ -4598,6 +4668,81 @@ public UserVm restoreVMInternal(Account caller, UserVmVO vm, Long newTemplateId) } + private void handleManagedStorage(UserVmVO vm, VolumeVO root) { + StoragePoolVO storagePool = _storagePoolDao.findById(root.getPoolId()); + + if (storagePool.isManaged()) { + Long hostId = vm.getHostId() != null ? vm.getHostId() : vm.getLastHostId(); + + if (hostId != null) { + VolumeInfo volumeInfo = volFactory.getVolume(root.getId()); + Host host = _hostDao.findById(hostId); + + final Command cmd; + + if (host.getHypervisorType() == HypervisorType.XenServer) { + DiskTO disk = new DiskTO(volumeInfo.getTO(), root.getDeviceId(), root.getPath(), root.getVolumeType()); + + // it's OK in this case to send a detach command to the host for a root volume as this + // will simply lead to the SR that supports the root volume being removed + cmd = new DettachCommand(disk, vm.getInstanceName()); + + DettachCommand detachCommand = (DettachCommand)cmd; + + detachCommand.setManaged(true); + + detachCommand.setStorageHost(storagePool.getHostAddress()); + detachCommand.setStoragePort(storagePool.getPort()); + + detachCommand.set_iScsiName(root.get_iScsiName()); + } + else if (host.getHypervisorType() == HypervisorType.VMware) { + PrimaryDataStore primaryDataStore = (PrimaryDataStore)volumeInfo.getDataStore(); + Map details = primaryDataStore.getDetails(); + + if (details == null) { + details = new HashMap(); + + primaryDataStore.setDetails(details); + } + + details.put(DiskTO.MANAGED, Boolean.TRUE.toString()); + + cmd = new DeleteCommand(volumeInfo.getTO()); + } + else { + throw new CloudRuntimeException("This hypervisor type is not supported on managed storage for this command."); + } + + Commands cmds = new Commands(Command.OnError.Stop); + + cmds.addCommand(cmd); + + try { + _agentMgr.send(hostId, cmds); + } + catch (Exception ex) { + throw new CloudRuntimeException(ex.getMessage()); + } + + if (!cmds.isSuccessful()) { + for (Answer answer : cmds.getAnswers()) { + if (!answer.getResult()) { + s_logger.warn("Failed to reset vm due to: " + answer.getDetails()); + + throw new CloudRuntimeException("Unable to reset " + vm + " due to " + answer.getDetails()); + } + } + } + + // root.getPoolId() should be null if the VM we are detaching the disk from has never been started before + DataStore dataStore = root.getPoolId() != null ? _dataStoreMgr.getDataStore(root.getPoolId(), DataStoreRole.Primary) : null; + + volumeMgr.disconnectVolumeFromHost(volFactory.getVolume(root.getId()), host, dataStore); + } + } + } + @Override public void prepareStop(VirtualMachineProfile profile) { UserVmVO vm = _vmDao.findById(profile.getId()); @@ -4640,7 +4785,7 @@ public String getVmUserData(long vmId) { } //check permissions - _accountMgr.checkAccess(CallContext.current().getCallingAccount(), null, true, vm); + _accountMgr.checkAccess(CallContext.current().getCallingAccount(), null, vm); return vm.getUserData(); } diff --git a/server/src/com/cloud/vm/UserVmStateListener.java b/server/src/com/cloud/vm/UserVmStateListener.java index 2f6be6cbbc..202391f4e4 100644 --- a/server/src/com/cloud/vm/UserVmStateListener.java +++ b/server/src/com/cloud/vm/UserVmStateListener.java @@ -25,6 +25,7 @@ import javax.inject.Inject; import com.cloud.server.ManagementService; +import com.cloud.vm.dao.UserVmDao; import org.apache.log4j.Logger; import org.springframework.beans.factory.NoSuchBeanDefinitionException; @@ -33,11 +34,9 @@ import com.cloud.event.EventCategory; import com.cloud.event.EventTypes; import com.cloud.event.UsageEventUtils; -import com.cloud.event.UsageEventVO; import com.cloud.event.dao.UsageEventDao; import com.cloud.network.dao.NetworkDao; import com.cloud.network.dao.NetworkVO; -import com.cloud.service.ServiceOfferingVO; import com.cloud.service.dao.ServiceOfferingDao; import com.cloud.utils.component.ComponentContext; import com.cloud.utils.fsm.StateListener; @@ -51,15 +50,19 @@ public class UserVmStateListener implements StateListener customParameters = new HashMap(); - customParameters.put(UsageEventVO.DynamicParameters.cpuNumber.name(), serviceOffering.getCpu().toString()); - customParameters.put(UsageEventVO.DynamicParameters.cpuSpeed.name(), serviceOffering.getSpeed().toString()); - customParameters.put(UsageEventVO.DynamicParameters.memory.name(), serviceOffering.getRamSize().toString()); - UsageEventUtils.publishUsageEvent(eventType, vm.getAccountId(), vm.getDataCenterId(), vm.getId(), - vm.getHostName(), serviceOffering.getId(), vm.getTemplateId(), vm.getHypervisorType().toString(), - VirtualMachine.class.getName(), vm.getUuid(), customParameters); + private void generateUsageEvent(Long serviceOfferingId, VirtualMachine vm, String eventType){ + boolean displayVm = true; + if(vm.getType() == VirtualMachine.Type.User){ + UserVmVO uservm = _userVmDao.findById(vm.getId()); + displayVm = uservm.isDisplayVm(); } + + _userVmMgr.generateUsageEvent(vm, displayVm, eventType); } private void pubishOnEventBus(String event, String status, VirtualMachine vo, VirtualMachine.State oldState, VirtualMachine.State newState) { diff --git a/server/src/com/cloud/vm/snapshot/VMSnapshotManagerImpl.java b/server/src/com/cloud/vm/snapshot/VMSnapshotManagerImpl.java index 37cdf86fd4..8dc2c1862c 100644 --- a/server/src/com/cloud/vm/snapshot/VMSnapshotManagerImpl.java +++ b/server/src/com/cloud/vm/snapshot/VMSnapshotManagerImpl.java @@ -297,7 +297,7 @@ public VMSnapshot allocVMSnapshot(Long vmId, String vsDisplayName, String vsDesc } // check access - _accountMgr.checkAccess(caller, null, true, userVmVo); + //_accountMgr.checkAccess(caller, null, userVmVo); // check max snapshot limit for per VM if (_vmSnapshotDao.findByVm(vmId).size() >= _vmSnapshotMax) { @@ -448,7 +448,7 @@ public boolean deleteVMSnapshot(Long vmSnapshotId) { throw new InvalidParameterValueException("unable to find the vm snapshot with id " + vmSnapshotId); } - _accountMgr.checkAccess(caller, null, true, vmSnapshot); + _accountMgr.checkAccess(caller, null, vmSnapshot); // check VM snapshot states, only allow to delete vm snapshots in created and error state if (VMSnapshot.State.Ready != vmSnapshot.getState() && VMSnapshot.State.Expunging != vmSnapshot.getState() && VMSnapshot.State.Error != vmSnapshot.getState()) { @@ -513,7 +513,7 @@ private boolean orchestrateDeleteVMSnapshot(Long vmSnapshotId) { throw new InvalidParameterValueException("unable to find the vm snapshot with id " + vmSnapshotId); } - _accountMgr.checkAccess(caller, null, true, vmSnapshot); + _accountMgr.checkAccess(caller, null, vmSnapshot); // check VM snapshot states, only allow to delete vm snapshots in created and error state if (VMSnapshot.State.Ready != vmSnapshot.getState() && VMSnapshot.State.Expunging != vmSnapshot.getState() && VMSnapshot.State.Error != vmSnapshot.getState()) { @@ -564,7 +564,7 @@ public UserVm revertToSnapshot(Long vmSnapshotId) throws InsufficientCapacityExc } Account caller = getCaller(); - _accountMgr.checkAccess(caller, null, true, vmSnapshotVo); + _accountMgr.checkAccess(caller, null, vmSnapshotVo); // VM should be in running or stopped states if (userVm.getState() != VirtualMachine.State.Running @@ -646,7 +646,7 @@ private UserVm orchestrateRevertToVMSnapshot(Long vmSnapshotId) throws Insuffici } Account caller = getCaller(); - _accountMgr.checkAccess(caller, null, true, vmSnapshotVo); + _accountMgr.checkAccess(caller, null, vmSnapshotVo); // VM should be in running or stopped states if (userVm.getState() != VirtualMachine.State.Running && userVm.getState() != VirtualMachine.State.Stopped) { diff --git a/server/src/org/apache/cloudstack/affinity/AffinityGroupServiceImpl.java b/server/src/org/apache/cloudstack/affinity/AffinityGroupServiceImpl.java index f375fde565..ef636920cd 100644 --- a/server/src/org/apache/cloudstack/affinity/AffinityGroupServiceImpl.java +++ b/server/src/org/apache/cloudstack/affinity/AffinityGroupServiceImpl.java @@ -28,7 +28,6 @@ import org.apache.log4j.Logger; -import org.apache.cloudstack.acl.IAMEntityType; import org.apache.cloudstack.acl.ControlledEntity; import org.apache.cloudstack.acl.ControlledEntity.ACLType; import org.apache.cloudstack.acl.SecurityChecker.AccessType; @@ -218,7 +217,7 @@ public AffinityGroupVO doInTransaction(TransactionStatus status) { _affinityGroupDomainMapDao.persist(domainMap); //send event for storing the domain wide resource access Map params = new HashMap(); - params.put(ApiConstants.ENTITY_TYPE, IAMEntityType.AffinityGroup); + params.put(ApiConstants.ENTITY_TYPE, AffinityGroup.class); params.put(ApiConstants.ENTITY_ID, group.getId()); params.put(ApiConstants.DOMAIN_ID, domainId); params.put(ApiConstants.SUBDOMAIN_ACCESS, subDomainAccess); @@ -263,7 +262,7 @@ public boolean deleteAffinityGroup(Long affinityGroupId, String account, Long do affinityGroupId = group.getId(); } // check permissions - _accountMgr.checkAccess(caller, AccessType.OperateEntry, true, group); + _accountMgr.checkAccess(caller, AccessType.OperateEntry, group); final Long affinityGroupIdFinal = affinityGroupId; Transaction.execute(new TransactionCallbackNoReturn() { @@ -300,7 +299,7 @@ public void doInTransactionWithoutResult(TransactionStatus status) { _affinityGroupDomainMapDao.remove(groupDomain.getId()); } // remove its related ACL permission - Pair params = new Pair(IAMEntityType.AffinityGroup, affinityGroupIdFinal); + Pair, Long> params = new Pair, Long>(AffinityGroup.class, affinityGroupIdFinal); _messageBus.publish(_name, EntityManager.MESSAGE_REMOVE_ENTITY_EVENT, PublishScope.LOCAL, params); } } @@ -354,7 +353,7 @@ public Pair, Integer> listAffinityGroups(Long affi if (userVM == null) { throw new InvalidParameterValueException("Unable to list affinity groups for virtual machine instance " + vmId + "; instance not found."); } - _accountMgr.checkAccess(caller, null, true, userVM); + _accountMgr.checkAccess(caller, null, userVM); // add join to affinity_groups_vm_map groupSearch.join("vmInstanceSearch", vmInstanceSearch, groupSearch.entity().getId(), vmInstanceSearch.entity().getAffinityGroupId(), JoinBuilder.JoinType.INNER); @@ -478,14 +477,7 @@ public UserVm updateVMAffinityGroups(Long vmId, List affinityGroupIds) { throw new InvalidParameterValueException("Unable to find affinity group by id " + affinityGroupId); } 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.getId())) { - if (ag.getAccountId() != owner.getAccountId()) { - throw new PermissionDeniedException("Affinity Group " + ag + " does not belong to the VM's account"); - } - } + _accountMgr.checkAccess(owner, AccessType.UseEntry, ag); } } _affinityGroupVMMapDao.updateMap(vmId, affinityGroupIds); diff --git a/server/src/org/apache/cloudstack/network/lb/ApplicationLoadBalancerManagerImpl.java b/server/src/org/apache/cloudstack/network/lb/ApplicationLoadBalancerManagerImpl.java index 73bf0d2a38..ad1a2c4ec8 100644 --- a/server/src/org/apache/cloudstack/network/lb/ApplicationLoadBalancerManagerImpl.java +++ b/server/src/org/apache/cloudstack/network/lb/ApplicationLoadBalancerManagerImpl.java @@ -24,14 +24,15 @@ import javax.ejb.Local; import javax.inject.Inject; +import org.apache.log4j.Logger; +import org.springframework.stereotype.Component; + import org.apache.cloudstack.acl.SecurityChecker.AccessType; import org.apache.cloudstack.api.command.user.loadbalancer.ListApplicationLoadBalancersCmd; import org.apache.cloudstack.context.CallContext; import org.apache.cloudstack.engine.orchestration.service.NetworkOrchestrationService; import org.apache.cloudstack.lb.ApplicationLoadBalancerRuleVO; import org.apache.cloudstack.lb.dao.ApplicationLoadBalancerRuleDao; -import org.apache.log4j.Logger; -import org.springframework.stereotype.Component; import com.cloud.event.ActionEvent; import com.cloud.event.EventTypes; @@ -114,7 +115,7 @@ public ApplicationLoadBalancerRule createApplicationLoadBalancer(String name, St } Account caller = CallContext.current().getCallingAccount(); - _accountMgr.checkAccess(caller, AccessType.UseEntry, false, guestNtwk); + _accountMgr.checkAccess(caller, AccessType.UseEntry, guestNtwk); Network sourceIpNtwk = _networkModel.getNetwork(sourceIpNetworkId); if (sourceIpNtwk == null) { @@ -546,7 +547,7 @@ public ApplicationLoadBalancerRule updateApplicationLoadBalancer(Long id, String if (rule == null) { throw new InvalidParameterValueException("Unable to find load balancer " + id); } - _accountMgr.checkAccess(caller, null, true, rule); + _accountMgr.checkAccess(caller, null, rule); if (customId != null) { rule.setUuid(customId); diff --git a/server/src/org/apache/cloudstack/network/lb/CertServiceImpl.java b/server/src/org/apache/cloudstack/network/lb/CertServiceImpl.java index ba71d631a9..67f2c02e0c 100644 --- a/server/src/org/apache/cloudstack/network/lb/CertServiceImpl.java +++ b/server/src/org/apache/cloudstack/network/lb/CertServiceImpl.java @@ -147,7 +147,7 @@ public void deleteSslCert(DeleteSslCertCmd deleteSslCertCmd) { if (certVO == null) { throw new InvalidParameterValueException("Invalid certificate id: " + certId); } - _accountMgr.checkAccess(caller, SecurityChecker.AccessType.OperateEntry, true, certVO); + _accountMgr.checkAccess(caller, SecurityChecker.AccessType.OperateEntry, certVO); List lbCertRule = _lbCertDao.listByCertId(certId); @@ -191,7 +191,7 @@ public List listSslCerts(ListSslCertsCmd listSslCertCmd) { throw new InvalidParameterValueException("Invalid certificate id: " + certId); } - _accountMgr.checkAccess(caller, SecurityChecker.AccessType.UseEntry, true, certVO); + _accountMgr.checkAccess(caller, SecurityChecker.AccessType.UseEntry, certVO); certLbMap = _lbCertDao.listByCertId(certId); @@ -206,7 +206,7 @@ public List listSslCerts(ListSslCertsCmd listSslCertCmd) { throw new InvalidParameterValueException("found no loadbalancer wth id: " + lbRuleId); } - _accountMgr.checkAccess(caller, SecurityChecker.AccessType.UseEntry, true, lb); + _accountMgr.checkAccess(caller, SecurityChecker.AccessType.UseEntry, lb); // get the cert id LoadBalancerCertMapVO lbCertMapRule; @@ -229,7 +229,7 @@ public List listSslCerts(ListSslCertsCmd listSslCertCmd) { List certVOList = _sslCertDao.listByAccountId(accountId); if (certVOList == null || certVOList.isEmpty()) return certResponseList; - _accountMgr.checkAccess(caller, SecurityChecker.AccessType.UseEntry, true, certVOList.get(0)); + _accountMgr.checkAccess(caller, SecurityChecker.AccessType.UseEntry, certVOList.get(0)); for (SslCertVO cert : certVOList) { certLbMap = _lbCertDao.listByCertId(cert.getId()); diff --git a/server/src/org/apache/cloudstack/region/gslb/GlobalLoadBalancingRulesServiceImpl.java b/server/src/org/apache/cloudstack/region/gslb/GlobalLoadBalancingRulesServiceImpl.java index c84fea29d5..516b3ab521 100644 --- a/server/src/org/apache/cloudstack/region/gslb/GlobalLoadBalancingRulesServiceImpl.java +++ b/server/src/org/apache/cloudstack/region/gslb/GlobalLoadBalancingRulesServiceImpl.java @@ -183,7 +183,7 @@ public boolean assignToGlobalLoadBalancerRule(AssignToGlobalLoadBalancerRuleCmd throw new InvalidParameterValueException("Invalid global load balancer rule id: " + gslbRuleId); } - _accountMgr.checkAccess(caller, SecurityChecker.AccessType.OperateEntry, true, gslbRule); + _accountMgr.checkAccess(caller, SecurityChecker.AccessType.OperateEntry, gslbRule); if (gslbRule.getState() == GlobalLoadBalancerRule.State.Revoke) { throw new InvalidParameterValueException("global load balancer rule id: " + gslbRule.getUuid() + " is in revoked state"); @@ -224,7 +224,7 @@ public boolean assignToGlobalLoadBalancerRule(AssignToGlobalLoadBalancerRuleCmd throw new InvalidParameterValueException("Specified load balancer rule ID does not exist."); } - _accountMgr.checkAccess(caller, null, true, loadBalancer); + _accountMgr.checkAccess(caller, null, loadBalancer); if (gslbRule.getAccountId() != loadBalancer.getAccountId()) { throw new InvalidParameterValueException("GSLB rule and load balancer rule does not belong to same account"); @@ -319,7 +319,7 @@ public boolean removeFromGlobalLoadBalancerRule(RemoveFromGlobalLoadBalancerRule throw new InvalidParameterValueException("Invalid global load balancer rule id: " + gslbRuleId); } - _accountMgr.checkAccess(caller, SecurityChecker.AccessType.OperateEntry, true, gslbRule); + _accountMgr.checkAccess(caller, SecurityChecker.AccessType.OperateEntry, gslbRule); if (gslbRule.getState() == GlobalLoadBalancerRule.State.Revoke) { throw new InvalidParameterValueException("global load balancer rule id: " + gslbRuleId + " is already in revoked state"); @@ -346,7 +346,7 @@ public boolean removeFromGlobalLoadBalancerRule(RemoveFromGlobalLoadBalancerRule throw new InvalidParameterValueException("Specified load balancer rule ID does not exist."); } - _accountMgr.checkAccess(caller, null, true, loadBalancer); + _accountMgr.checkAccess(caller, null, loadBalancer); } for (GlobalLoadBalancerLbRuleMapVO gslbLbMapVo : gslbLbMapVos) { @@ -445,7 +445,7 @@ private void revokeGslbRule(final long gslbRuleId, Account caller) { throw new InvalidParameterValueException("Invalid global load balancer rule id: " + gslbRuleId); } - _accountMgr.checkAccess(caller, SecurityChecker.AccessType.OperateEntry, true, gslbRule); + _accountMgr.checkAccess(caller, SecurityChecker.AccessType.OperateEntry, gslbRule); if (gslbRule.getState() == com.cloud.region.ha.GlobalLoadBalancerRule.State.Staged) { if (s_logger.isDebugEnabled()) { @@ -523,7 +523,7 @@ public GlobalLoadBalancerRule updateGlobalLoadBalancerRule(UpdateGlobalLoadBalan CallContext ctx = CallContext.current(); Account caller = ctx.getCallingAccount(); - _accountMgr.checkAccess(caller, SecurityChecker.AccessType.OperateEntry, true, gslbRule); + _accountMgr.checkAccess(caller, SecurityChecker.AccessType.OperateEntry, gslbRule); if (algorithm != null && !GlobalLoadBalancerRule.Algorithm.isValidAlgorithm(algorithm)) { throw new InvalidParameterValueException("Invalid Algorithm: " + algorithm); @@ -583,7 +583,7 @@ public List listGlobalLoadBalancerRule(ListGlobalLoadBal if (gslbRule == null) { throw new InvalidParameterValueException("Invalid gslb rule id specified"); } - _accountMgr.checkAccess(caller, org.apache.cloudstack.acl.SecurityChecker.AccessType.UseEntry, false, gslbRule); + _accountMgr.checkAccess(caller, org.apache.cloudstack.acl.SecurityChecker.AccessType.UseEntry, gslbRule); response.add(gslbRule); return response; diff --git a/server/test/com/cloud/api/dispatch/CommandCreationWorkerTest.java b/server/test/com/cloud/api/dispatch/CommandCreationWorkerTest.java index 34d64fc3c1..72dd770d5a 100644 --- a/server/test/com/cloud/api/dispatch/CommandCreationWorkerTest.java +++ b/server/test/com/cloud/api/dispatch/CommandCreationWorkerTest.java @@ -18,7 +18,12 @@ import java.util.HashMap; import java.util.Map; +import java.util.UUID; +import com.cloud.user.Account; +import com.cloud.user.AccountVO; +import com.cloud.user.UserVO; +import org.apache.cloudstack.context.CallContext; import org.junit.Test; import static org.mockito.Mockito.mock; @@ -36,6 +41,9 @@ public void testHandle() throws ResourceAllocationException { // Prepare final BaseAsyncCreateCmd asyncCreateCmd = mock(BaseAsyncCreateCmd.class); final Map params = new HashMap(); + Account account = new AccountVO("testaccount", 1L, "networkdomain", (short) 0, "uuid"); + UserVO user = new UserVO(1, "testuser", "password", "firstname", "lastName", "email", "timezone", UUID.randomUUID().toString()); + CallContext.register(user, account); // Execute final CommandCreationWorker creationWorker = new CommandCreationWorker(); diff --git a/server/test/com/cloud/api/dispatch/ParamGenericValidationWorkerTest.java b/server/test/com/cloud/api/dispatch/ParamGenericValidationWorkerTest.java index 8f9709ca9d..3073c7ffd8 100644 --- a/server/test/com/cloud/api/dispatch/ParamGenericValidationWorkerTest.java +++ b/server/test/com/cloud/api/dispatch/ParamGenericValidationWorkerTest.java @@ -95,6 +95,10 @@ public void testHandle() throws ResourceAllocationException { params.put(ApiConstants.SIGNATURE, ""); params.put(ApiConstants.CTX_ACCOUNT_ID, ""); params.put(ApiConstants.CTX_START_EVENT_ID, ""); + // Make sure it's case insensitive + params.put(ApiConstants.CTX_START_EVENT_ID, ""); + params.put(ApiConstants.CTX_START_EVENT_ID.toLowerCase(), ""); + params.put(ApiConstants.CTX_USER_ID.toUpperCase(), ""); params.put(ApiConstants.CTX_USER_ID, ""); params.put(ApiConstants.UUID, ""); params.put(ApiConstants.ID, ""); diff --git a/server/test/com/cloud/event/EventControlsUnitTest.java b/server/test/com/cloud/event/EventControlsUnitTest.java index 91dc921d26..0dc57427c5 100644 --- a/server/test/com/cloud/event/EventControlsUnitTest.java +++ b/server/test/com/cloud/event/EventControlsUnitTest.java @@ -60,7 +60,7 @@ protected void setUp() { MockitoAnnotations.initMocks(this); _mgmtServer._eventDao = _eventDao; _mgmtServer._accountMgr = _accountMgr; - doNothing().when(_accountMgr).checkAccess(any(Account.class), any(AccessType.class), any(Boolean.class), any(ControlledEntity.class)); + doNothing().when(_accountMgr).checkAccess(any(Account.class), any(AccessType.class), any(ControlledEntity.class)); when(_eventDao.listToArchiveOrDeleteEvents(anyList(), anyString(), any(Date.class), any(Date.class), anyList())).thenReturn(_events); } diff --git a/server/test/com/cloud/network/CreatePrivateNetworkTest.java b/server/test/com/cloud/network/CreatePrivateNetworkTest.java index dc979d05c9..b124b20dad 100644 --- a/server/test/com/cloud/network/CreatePrivateNetworkTest.java +++ b/server/test/com/cloud/network/CreatePrivateNetworkTest.java @@ -103,7 +103,7 @@ public void setup() throws Exception { NetworkOfferingVO ntwkOff = new NetworkOfferingVO("offer", "fakeOffer", TrafficType.Guest, true, true, null, null, false, null, null, GuestType.Isolated, false, false, false, false, - false, false, false, false, false, false, false, false, false); + false, false, false, false, false, false, false, false, false, false); when(networkService._networkOfferingDao.findById(anyLong())).thenReturn(ntwkOff); List netofferlist = new ArrayList(); netofferlist.add(ntwkOff); diff --git a/server/test/com/cloud/network/MockNetworkModelImpl.java b/server/test/com/cloud/network/MockNetworkModelImpl.java index 6c9e597b9f..33387fae64 100644 --- a/server/test/com/cloud/network/MockNetworkModelImpl.java +++ b/server/test/com/cloud/network/MockNetworkModelImpl.java @@ -25,6 +25,8 @@ import javax.ejb.Local; import javax.naming.ConfigurationException; +import org.apache.cloudstack.acl.SecurityChecker.AccessType; + import com.cloud.dc.Vlan; import com.cloud.exception.InsufficientAddressCapacityException; import com.cloud.exception.InvalidParameterValueException; @@ -878,4 +880,10 @@ public boolean isNetworkReadyForGc(long networkId) { public boolean getNetworkEgressDefaultPolicy(Long networkId) { return false; //To change body of implemented methods use File | Settings | File Templates. } + + @Override + public void checkNetworkPermissions(Account owner, Network network, AccessType accessType) { + // TODO Auto-generated method stub + + } } diff --git a/server/test/com/cloud/network/lb/AssignLoadBalancerTest.java b/server/test/com/cloud/network/lb/AssignLoadBalancerTest.java new file mode 100644 index 0000000000..257a21fd67 --- /dev/null +++ b/server/test/com/cloud/network/lb/AssignLoadBalancerTest.java @@ -0,0 +1,271 @@ +// 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.lb; + +import com.cloud.domain.DomainVO; +import com.cloud.domain.dao.DomainDao; +import com.cloud.exception.ResourceAllocationException; +import com.cloud.exception.ResourceUnavailableException; +import com.cloud.exception.InsufficientCapacityException; +import com.cloud.exception.InvalidParameterValueException; +import com.cloud.network.NetworkModelImpl; +import com.cloud.network.dao.LoadBalancerDao; +import com.cloud.network.dao.LoadBalancerVMMapDao; +import com.cloud.network.dao.LoadBalancerVMMapVO; +import com.cloud.network.dao.LoadBalancerVO; +import com.cloud.network.rules.FirewallRule; +import com.cloud.network.rules.RulesManagerImpl; +import com.cloud.user.Account; +import com.cloud.user.AccountManager; +import com.cloud.user.AccountVO; +import com.cloud.user.UserVO; +import com.cloud.user.dao.AccountDao; +import com.cloud.uservm.UserVm; +import com.cloud.vm.Nic; +import com.cloud.vm.NicVO; +import com.cloud.vm.UserVmVO; +import com.cloud.vm.dao.NicSecondaryIpDao; +import com.cloud.vm.dao.UserVmDao; +import org.apache.cloudstack.api.ResponseGenerator; +import org.apache.cloudstack.api.command.user.loadbalancer.AssignToLoadBalancerRuleCmd; +import org.apache.cloudstack.api.response.SuccessResponse; +import org.apache.cloudstack.context.CallContext; +import org.junit.After; +import org.junit.Before; +import org.junit.Rule; +import org.junit.Test; +import org.junit.rules.ExpectedException; +import org.mockito.Mock; +import org.mockito.Mockito; +import org.mockito.Spy; + +import javax.inject.Inject; + +import java.util.UUID; +import java.util.HashMap; +import java.util.Map; +import java.util.List; +import java.util.ArrayList; + +import static org.mockito.Matchers.anyBoolean; +import static org.mockito.Matchers.anyLong; +import static org.mockito.Matchers.anyString; +import static org.mockito.Mockito.when; + +public class AssignLoadBalancerTest { + + @Inject + AccountManager _accountMgr; + + @Inject + AccountManager _acctMgr; + + @Inject + AccountDao _accountDao; + + @Inject + DomainDao _domainDao; + + @Mock + List _lbvmMapList; + + @Mock + List nic; + + @Mock + UserVmDao userDao; + + @Spy + RulesManagerImpl _rulesMgr = new RulesManagerImpl() { + @Override + public void checkRuleAndUserVm (FirewallRule rule, UserVm userVm, Account caller) { + + } + }; + + + @Spy + NicVO nicvo = new NicVO() { + + }; + + @Spy + NetworkModelImpl _networkModel = new NetworkModelImpl() { + @Override + public List getNics(long vmId) { + nic = new ArrayList(); + nicvo.setNetworkId(204L); + nic.add(nicvo); + return nic; + } + }; + + + LoadBalancingRulesManagerImpl _lbMgr = new LoadBalancingRulesManagerImpl(); + + private AssignToLoadBalancerRuleCmd assignToLbRuleCmd; + private ResponseGenerator responseGenerator; + private SuccessResponse successResponseGenerator; + + @Rule + public ExpectedException expectedException = ExpectedException.none(); + + private static long domainId = 5L; + private static long accountId = 5L; + private static String accountName = "admin"; + + @Before + public void setUp() { + assignToLbRuleCmd = new AssignToLoadBalancerRuleCmd() { + }; + + // ComponentContext.initComponentsLifeCycle(); + AccountVO account = new AccountVO(accountName, domainId, "networkDomain", Account.ACCOUNT_TYPE_NORMAL, "uuid"); + DomainVO domain = new DomainVO("rootDomain", 5L, 5L, "networkDomain"); + + UserVO user = new UserVO(1, "testuser", "password", "firstname", "lastName", "email", "timezone", UUID.randomUUID().toString()); + + CallContext.register(user, account); + + } + + @Test(expected = InvalidParameterValueException.class) + public void testBothArgsEmpty() throws ResourceAllocationException, ResourceUnavailableException, InsufficientCapacityException { + + Map> emptyMap = new HashMap>(); + + LoadBalancerDao lbdao = Mockito.mock(LoadBalancerDao.class); + _lbMgr._lbDao = lbdao; + + when(lbdao.findById(anyLong())).thenReturn(Mockito.mock(LoadBalancerVO.class)); + + _lbMgr.assignToLoadBalancer(1L, null, emptyMap); + + } + + @Test(expected = InvalidParameterValueException.class) + public void testNicIsNotInNw() throws ResourceAllocationException, ResourceUnavailableException, InsufficientCapacityException { + + Map> vmIdIpMap = new HashMap>(); + List secIp = new ArrayList(); + secIp.add("10.1.1.175"); + vmIdIpMap.put(1L,secIp); + + List vmIds = new ArrayList(); + vmIds.add(2L); + + LoadBalancerDao lbDao = Mockito.mock(LoadBalancerDao.class); + LoadBalancerVMMapDao lb2VmMapDao = Mockito.mock(LoadBalancerVMMapDao.class); + UserVmDao userVmDao = Mockito.mock(UserVmDao.class); + + _lbMgr._lbDao = lbDao; + _lbMgr._lb2VmMapDao = lb2VmMapDao; + _lbMgr._vmDao = userVmDao; + _lbvmMapList = new ArrayList<>(); + _lbMgr._rulesMgr = _rulesMgr; + _lbMgr._networkModel = _networkModel; + + when(lbDao.findById(anyLong())).thenReturn(Mockito.mock(LoadBalancerVO.class)); + when(userVmDao.findById(anyLong())).thenReturn(Mockito.mock(UserVmVO.class)); + when(lb2VmMapDao.listByLoadBalancerId(anyLong(), anyBoolean())).thenReturn(_lbvmMapList); + + _lbMgr.assignToLoadBalancer(1L, null, vmIdIpMap); + } + + + @Test(expected = InvalidParameterValueException.class) + public void tesSecIpNotSetToVm() throws ResourceAllocationException, ResourceUnavailableException, InsufficientCapacityException { + + AssignToLoadBalancerRuleCmd assignLbRuleCmd = Mockito.mock(AssignToLoadBalancerRuleCmd.class); + + Map> vmIdIpMap = new HashMap>(); + List secIp = new ArrayList(); + secIp.add("10.1.1.175"); + vmIdIpMap.put(1L,secIp); + + List vmIds = new ArrayList(); + vmIds.add(2L); + + LoadBalancerVO lbVO = new LoadBalancerVO("1", "L1", "Lbrule", 1, 22, 22, "rb", 204, 0, 0, "tcp"); + + LoadBalancerDao lbDao = Mockito.mock(LoadBalancerDao.class); + LoadBalancerVMMapDao lb2VmMapDao = Mockito.mock(LoadBalancerVMMapDao.class); + UserVmDao userVmDao = Mockito.mock(UserVmDao.class); + NicSecondaryIpDao nicSecIpDao = Mockito.mock(NicSecondaryIpDao.class); + + _lbMgr._lbDao = lbDao; + _lbMgr._lb2VmMapDao = lb2VmMapDao; + _lbMgr._vmDao = userVmDao; + _lbMgr._nicSecondaryIpDao = nicSecIpDao; + _lbvmMapList = new ArrayList<>(); + _lbMgr._rulesMgr = _rulesMgr; + _lbMgr._networkModel = _networkModel; + + when(lbDao.findById(anyLong())).thenReturn(lbVO); + when(userVmDao.findById(anyLong())).thenReturn(Mockito.mock(UserVmVO.class)); + when(lb2VmMapDao.listByLoadBalancerId(anyLong(), anyBoolean())).thenReturn(_lbvmMapList); + when (nicSecIpDao.findByIp4AddressAndNicId(anyString(), anyLong())).thenReturn(null); + + _lbMgr.assignToLoadBalancer(1L, null, vmIdIpMap); + } + + + + @Test(expected = InvalidParameterValueException.class) + public void testVmIdAlreadyExist() throws ResourceAllocationException, ResourceUnavailableException, InsufficientCapacityException { + + AssignToLoadBalancerRuleCmd assignLbRuleCmd = Mockito.mock(AssignToLoadBalancerRuleCmd.class); + + Map> vmIdIpMap = new HashMap>(); + List secIp = new ArrayList(); + secIp.add("10.1.1.175"); + vmIdIpMap.put(1L,secIp); + + List vmIds = new ArrayList(); + vmIds.add(2L); + + LoadBalancerVO lbVO = new LoadBalancerVO("1", "L1", "Lbrule", 1, 22, 22, "rb", 204, 0, 0, "tcp"); + + LoadBalancerDao lbDao = Mockito.mock(LoadBalancerDao.class); + LoadBalancerVMMapDao lb2VmMapDao = Mockito.mock(LoadBalancerVMMapDao.class); + UserVmDao userVmDao = Mockito.mock(UserVmDao.class); + NicSecondaryIpDao nicSecIpDao = Mockito.mock(NicSecondaryIpDao.class); + LoadBalancerVMMapVO lbVmMapVO = new LoadBalancerVMMapVO(1L, 1L, "10.1.1.175", false); + + _lbMgr._lbDao = lbDao; + _lbMgr._lb2VmMapDao = lb2VmMapDao; + _lbMgr._vmDao = userVmDao; + _lbMgr._nicSecondaryIpDao = nicSecIpDao; + _lbvmMapList = new ArrayList<>(); + _lbvmMapList.add(lbVmMapVO); + _lbMgr._rulesMgr = _rulesMgr; + _lbMgr._networkModel = _networkModel; + + when(lbDao.findById(anyLong())).thenReturn(lbVO); + when(userVmDao.findById(anyLong())).thenReturn(Mockito.mock(UserVmVO.class)); + when(lb2VmMapDao.listByLoadBalancerId(anyLong(), anyBoolean())).thenReturn(_lbvmMapList); + when (nicSecIpDao.findByIp4AddressAndNicId(anyString(), anyLong())).thenReturn(null); + + _lbMgr.assignToLoadBalancer(1L, null, vmIdIpMap); + } + + @After + public void tearDown() { + CallContext.unregister(); + } + +} \ No newline at end of file diff --git a/server/test/com/cloud/resource/MockResourceManagerImpl.java b/server/test/com/cloud/resource/MockResourceManagerImpl.java index e6bf9a26b2..2646af079a 100644 --- a/server/test/com/cloud/resource/MockResourceManagerImpl.java +++ b/server/test/com/cloud/resource/MockResourceManagerImpl.java @@ -36,6 +36,7 @@ import com.cloud.agent.api.StartupCommand; import com.cloud.agent.api.StartupRoutingCommand; +import com.cloud.agent.api.VgpuTypesInfo; import com.cloud.agent.api.to.GPUDeviceTO; import com.cloud.dc.DataCenterVO; import com.cloud.dc.HostPodVO; @@ -558,31 +559,37 @@ public boolean releaseHostReservation(Long hostId) { } @Override - public boolean isGPUDeviceAvailable(long hostId, String vgpuType) { + public boolean isGPUDeviceAvailable(long hostId, String groupName, String vgpuType) { // TODO Auto-generated method stub return false; } @Override - public GPUDeviceTO getGPUDevice(long hostId, String vgpuType) { + public GPUDeviceTO getGPUDevice(long hostId, String groupName, String vgpuType) { // TODO Auto-generated method stub return null; } @Override - public List listAvailableGPUDevice(long hostId, String vgpuType) { + public List listAvailableGPUDevice(long hostId, String groupName, String vgpuType) { // TODO Auto-generated method stub return null; } @Override - public void updateGPUDetails(long hostId, HashMap> deviceDetails) { + public void updateGPUDetails(long hostId, HashMap> deviceDetails) { // TODO Auto-generated method stub } @Override - public HashMap> getGPUStatistics(HostVO host) { + public HashMap> getGPUStatistics(HostVO host) { // TODO Auto-generated method stub return null; } + + @Override + public boolean isHostGpuEnabled(long hostId) { + // TODO Auto-generated method stub + return false; + } } diff --git a/server/test/com/cloud/user/MockAccountManagerImpl.java b/server/test/com/cloud/user/MockAccountManagerImpl.java index f373cba922..a2b8a8559f 100644 --- a/server/test/com/cloud/user/MockAccountManagerImpl.java +++ b/server/test/com/cloud/user/MockAccountManagerImpl.java @@ -33,7 +33,6 @@ import org.apache.cloudstack.api.command.admin.user.UpdateUserCmd; import com.cloud.domain.Domain; -import com.cloud.domain.PartOf; import com.cloud.exception.ConcurrentOperationException; import com.cloud.exception.PermissionDeniedException; import com.cloud.exception.ResourceUnavailableException; @@ -120,7 +119,7 @@ public boolean deleteUser(DeleteUserCmd deleteUserCmd) { } @Override - public boolean isAdmin(short accountType) { + public boolean isAdmin(Long accountId) { // TODO Auto-generated method stub return false; } @@ -219,15 +218,12 @@ public String getName() { return null; } - @Override - public void checkAccess(Account account, AccessType accessType, boolean sameOwner, ControlledEntity... entities) throws PermissionDeniedException { - // TODO Auto-generated method stub - } + @Override - public void checkAccess(Account account, AccessType accessType, boolean sameOwner, PartOf... entities) throws PermissionDeniedException { + public UserAccount getUserAccountById(Long userId) { // TODO Auto-generated method stub - + return null; } @Override @@ -344,17 +340,22 @@ public List listAclGroupsByAccount(Long accountId) { return null; } + @Override - public void checkAccess(Account account, AccessType accessType, boolean sameOwner, String apiName, - ControlledEntity... entities) throws PermissionDeniedException { + public Long finalyzeAccountId(String accountName, Long domainId, Long projectId, boolean enabledOnly) { // TODO Auto-generated method stub + return null; } @Override - public Long finalyzeAccountId(String accountName, Long domainId, Long projectId, boolean enabledOnly) { + public void checkAccess(Account account, AccessType accessType, ControlledEntity... entities) throws PermissionDeniedException { // TODO Auto-generated method stub - return null; } + @Override + public void checkAccess(Account account, AccessType accessType, String apiName, ControlledEntity... entities) throws PermissionDeniedException { + // TODO Auto-generated method stub + + } } diff --git a/server/test/com/cloud/vm/UserVmManagerTest.java b/server/test/com/cloud/vm/UserVmManagerTest.java index 43010a3f64..927d5e33b5 100755 --- a/server/test/com/cloud/vm/UserVmManagerTest.java +++ b/server/test/com/cloud/vm/UserVmManagerTest.java @@ -50,6 +50,8 @@ import org.apache.cloudstack.context.CallContext; import org.apache.cloudstack.engine.orchestration.service.VolumeOrchestrationService; import org.apache.cloudstack.framework.config.dao.ConfigurationDao; +import org.apache.cloudstack.storage.datastore.db.PrimaryDataStoreDao; +import org.apache.cloudstack.storage.datastore.db.StoragePoolVO; import com.cloud.capacity.CapacityManager; import com.cloud.configuration.ConfigurationManager; @@ -141,6 +143,8 @@ public class UserVmManagerTest { EntityManager _entityMgr; @Mock ResourceLimitService _resourceLimitMgr; + @Mock + PrimaryDataStoreDao _storagePoolDao; @Before public void setup() { @@ -162,6 +166,7 @@ public void setup() { _userVmMgr._resourceLimitMgr = _resourceLimitMgr; _userVmMgr._scaleRetry = 2; _userVmMgr._entityMgr = _entityMgr; + _userVmMgr._storagePoolDao = _storagePoolDao; doReturn(3L).when(_account).getId(); doReturn(8L).when(_vmMock).getAccountId(); @@ -214,6 +219,12 @@ public void testRestoreVMF2() throws ResourceUnavailableException, InsufficientC Account account = new AccountVO("testaccount", 1L, "networkdomain", (short)0, "uuid"); UserVO user = new UserVO(1, "testuser", "password", "firstname", "lastName", "email", "timezone", UUID.randomUUID().toString()); + StoragePoolVO storagePool = new StoragePoolVO(); + + storagePool.setManaged(false); + + when(_storagePoolDao.findById(anyLong())).thenReturn(storagePool); + CallContext.register(user, account); try { _userVmMgr.restoreVMInternal(_account, _vmMock, null); @@ -245,6 +256,12 @@ public void testRestoreVMF3() throws ResourceUnavailableException, InsufficientC Account account = new AccountVO("testaccount", 1L, "networkdomain", (short)0, "uuid"); UserVO user = new UserVO(1, "testuser", "password", "firstname", "lastName", "email", "timezone", UUID.randomUUID().toString()); + StoragePoolVO storagePool = new StoragePoolVO(); + + storagePool.setManaged(false); + + when(_storagePoolDao.findById(anyLong())).thenReturn(storagePool); + CallContext.register(user, account); try { _userVmMgr.restoreVMInternal(_account, _vmMock, null); @@ -266,7 +283,7 @@ public void testRestoreVMF4() throws ResourceUnavailableException, InsufficientC doReturn(3L).when(_volumeMock).getTemplateId(); doReturn(ImageFormat.VHD).when(_templateMock).getFormat(); when(_templateDao.findById(anyLong())).thenReturn(_templateMock); - doNothing().when(_accountMgr).checkAccess(_account, null, true, _templateMock); + doNothing().when(_accountMgr).checkAccess(_account, null, _templateMock); when(_storageMgr.allocateDuplicateVolume(_volumeMock, 14L)).thenReturn(_volumeMock); when(_templateMock.getGuestOSId()).thenReturn(5L); doNothing().when(_vmMock).setGuestOSId(anyLong()); @@ -282,6 +299,12 @@ public void testRestoreVMF4() throws ResourceUnavailableException, InsufficientC Account account = new AccountVO("testaccount", 1L, "networkdomain", (short)0, "uuid"); UserVO user = new UserVO(1, "testuser", "password", "firstname", "lastName", "email", "timezone", UUID.randomUUID().toString()); + StoragePoolVO storagePool = new StoragePoolVO(); + + storagePool.setManaged(false); + + when(_storagePoolDao.findById(anyLong())).thenReturn(storagePool); + CallContext.register(user, account); try { _userVmMgr.restoreVMInternal(_account, _vmMock, 14L); @@ -304,7 +327,7 @@ public void testRestoreVMF5() throws ResourceUnavailableException, InsufficientC doReturn(3L).when(_vmMock).getIsoId(); doReturn(ImageFormat.ISO).when(_templateMock).getFormat(); when(_templateDao.findById(anyLong())).thenReturn(_templateMock); - doNothing().when(_accountMgr).checkAccess(_account, null, true, _templateMock); + doNothing().when(_accountMgr).checkAccess(_account, null, _templateMock); when(_storageMgr.allocateDuplicateVolume(_volumeMock, null)).thenReturn(_volumeMock); doNothing().when(_vmMock).setIsoId(14L); when(_templateMock.getGuestOSId()).thenReturn(5L); @@ -321,6 +344,12 @@ public void testRestoreVMF5() throws ResourceUnavailableException, InsufficientC Account account = new AccountVO("testaccount", 1L, "networkdomain", (short)0, "uuid"); UserVO user = new UserVO(1, "testuser", "password", "firstname", "lastName", "email", "timezone", UUID.randomUUID().toString()); + StoragePoolVO storagePool = new StoragePoolVO(); + + storagePool.setManaged(false); + + when(_storagePoolDao.findById(anyLong())).thenReturn(storagePool); + CallContext.register(user, account); try { _userVmMgr.restoreVMInternal(_account, _vmMock, 14L); @@ -384,7 +413,7 @@ public void testScaleVMF2() throws Exception { doReturn(VirtualMachine.State.Running).when(_vmInstance).getState(); - doNothing().when(_accountMgr).checkAccess(_account, null, true, _templateMock); + doNothing().when(_accountMgr).checkAccess(_account, null, _templateMock); doNothing().when(_itMgr).checkIfCanUpgrade(_vmMock, _offeringVo); @@ -577,7 +606,7 @@ public void testMoveVmToUser2() throws Exception { when(_accountService.getActiveAccountByName(anyString(), anyLong())).thenReturn(newAccount); - doThrow(new PermissionDeniedException("Access check failed")).when(_accountMgr).checkAccess(any(Account.class), any(AccessType.class), any(Boolean.class), + doThrow(new PermissionDeniedException("Access check failed")).when(_accountMgr).checkAccess(any(Account.class), any(AccessType.class), any(ControlledEntity.class)); CallContext.register(user, caller); diff --git a/server/test/com/cloud/vm/snapshot/VMSnapshotManagerTest.java b/server/test/com/cloud/vm/snapshot/VMSnapshotManagerTest.java index 9d5c2b42ea..03afdbd580 100644 --- a/server/test/com/cloud/vm/snapshot/VMSnapshotManagerTest.java +++ b/server/test/com/cloud/vm/snapshot/VMSnapshotManagerTest.java @@ -125,7 +125,7 @@ public void setup() { _vmSnapshotMgr._guestOSDao = _guestOSDao; _vmSnapshotMgr._hypervisorCapabilitiesDao = _hypervisorCapabilitiesDao; - doNothing().when(_accountMgr).checkAccess(any(Account.class), any(AccessType.class), any(Boolean.class), any(ControlledEntity.class)); + doNothing().when(_accountMgr).checkAccess(any(Account.class), any(AccessType.class), any(ControlledEntity.class)); _vmSnapshotMgr._vmSnapshotMax = _vmSnapshotMax; diff --git a/server/test/com/cloud/vpc/MockNetworkManagerImpl.java b/server/test/com/cloud/vpc/MockNetworkManagerImpl.java index ac303dddfc..387a710d9d 100644 --- a/server/test/com/cloud/vpc/MockNetworkManagerImpl.java +++ b/server/test/com/cloud/vpc/MockNetworkManagerImpl.java @@ -606,7 +606,7 @@ public boolean destroyNetwork(long networkId, ReservationContext context, boolea @Override public Network createGuestNetwork(long networkOfferingId, String name, String displayText, String gateway, String cidr, String vlanId, String networkDomain, Account owner, Long domainId, PhysicalNetwork physicalNetwork, long zoneId, ACLType aclType, Boolean subdomainAccess, Long vpcId, String gatewayv6, - String cidrv6, Boolean displayNetworkEnabled, String isolatedPvlan) throws ConcurrentOperationException, InsufficientCapacityException, + String cidrv6, Boolean displayNetworkEnabled, String isolatedPvlan ) throws ConcurrentOperationException, InsufficientCapacityException, ResourceAllocationException { // TODO Auto-generated method stub return null; diff --git a/server/test/com/cloud/vpc/MockNetworkModelImpl.java b/server/test/com/cloud/vpc/MockNetworkModelImpl.java index 67ab8e875c..c93584dbe3 100644 --- a/server/test/com/cloud/vpc/MockNetworkModelImpl.java +++ b/server/test/com/cloud/vpc/MockNetworkModelImpl.java @@ -26,6 +26,8 @@ import javax.inject.Inject; import javax.naming.ConfigurationException; +import org.apache.cloudstack.acl.SecurityChecker.AccessType; + import com.cloud.dc.Vlan; import com.cloud.exception.InsufficientAddressCapacityException; import com.cloud.exception.InvalidParameterValueException; @@ -893,4 +895,10 @@ public boolean isNetworkReadyForGc(long networkId) { public boolean getNetworkEgressDefaultPolicy(Long networkId) { return false; //To change body of implemented methods use File | Settings | File Templates. } + + @Override + public void checkNetworkPermissions(Account owner, Network network, AccessType accessType) { + // TODO Auto-generated method stub + + } } diff --git a/server/test/com/cloud/vpc/VpcApiUnitTest.java b/server/test/com/cloud/vpc/VpcApiUnitTest.java index 5e283743b7..dee9afe3b5 100644 --- a/server/test/com/cloud/vpc/VpcApiUnitTest.java +++ b/server/test/com/cloud/vpc/VpcApiUnitTest.java @@ -85,7 +85,7 @@ public void getActiveVpc() { public void validateNtwkOffForVpc() { //validate network offering //1) correct network offering - VpcVO vo = new VpcVO(1, "new vpc", "new vpc", 1, 1, 1, "0.0.0.0/0", "vpc domain", false); + VpcVO vo = new VpcVO(1, "new vpc", "new vpc", 1, 1, 1, "0.0.0.0/0", "vpc domain", false, false); boolean result = false; try { _vpcService.validateNtwkOffForNtwkInVpc(2L, 1, "0.0.0.0", "111-", vo, "10.1.1.1", new AccountVO(), null); diff --git a/server/test/com/cloud/vpc/dao/MockVpcDaoImpl.java b/server/test/com/cloud/vpc/dao/MockVpcDaoImpl.java index e1a6ac2ae4..7492598e90 100644 --- a/server/test/com/cloud/vpc/dao/MockVpcDaoImpl.java +++ b/server/test/com/cloud/vpc/dao/MockVpcDaoImpl.java @@ -98,9 +98,9 @@ public void persistVpcServiceProviders(long vpcId, Map> ser public VpcVO findById(Long id) { VpcVO vo = null; if (id.longValue() == 1) { - vo = new VpcVO(1, "new vpc", "new vpc", 1, 1, 1, "0.0.0.0/0", "vpc domain", false); + vo = new VpcVO(1, "new vpc", "new vpc", 1, 1, 1, "0.0.0.0/0", "vpc domain", false, false); } else if (id.longValue() == 2) { - vo = new VpcVO(1, "new vpc", "new vpc", 1, 1, 1, "0.0.0.0/0", "vpc domain", false); + vo = new VpcVO(1, "new vpc", "new vpc", 1, 1, 1, "0.0.0.0/0", "vpc domain", false, false); vo.setState(State.Inactive); } diff --git a/server/test/org/apache/cloudstack/affinity/AffinityApiUnitTest.java b/server/test/org/apache/cloudstack/affinity/AffinityApiUnitTest.java index f0ee8abd02..e7581d6777 100644 --- a/server/test/org/apache/cloudstack/affinity/AffinityApiUnitTest.java +++ b/server/test/org/apache/cloudstack/affinity/AffinityApiUnitTest.java @@ -32,6 +32,7 @@ import javax.inject.Inject; import javax.naming.ConfigurationException; +import com.cloud.utils.db.EntityManager; import org.junit.After; import org.junit.Before; import org.junit.BeforeClass; @@ -282,6 +283,11 @@ public AffinityGroupDomainMapDao affinityGroupDomainMapDao() { return Mockito.mock(AffinityGroupDomainMapDao.class); } + @Bean + public EntityManager entityManager() { + return Mockito.mock(EntityManager.class); + } + @Bean public DomainDao domainDao() { return Mockito.mock(DomainDao.class); diff --git a/server/test/resources/createNetworkOffering.xml b/server/test/resources/createNetworkOffering.xml index 6ae1978f40..887a8af724 100644 --- a/server/test/resources/createNetworkOffering.xml +++ b/server/test/resources/createNetworkOffering.xml @@ -48,4 +48,6 @@ + + diff --git a/services/iam/plugin/src/org/apache/cloudstack/api/command/iam/AddIAMPermissionToIAMPolicyCmd.java b/services/iam/plugin/src/org/apache/cloudstack/api/command/iam/AddIAMPermissionToIAMPolicyCmd.java index d37cc3cb7b..d69f3d0a0b 100644 --- a/services/iam/plugin/src/org/apache/cloudstack/api/command/iam/AddIAMPermissionToIAMPolicyCmd.java +++ b/services/iam/plugin/src/org/apache/cloudstack/api/command/iam/AddIAMPermissionToIAMPolicyCmd.java @@ -72,6 +72,9 @@ public class AddIAMPermissionToIAMPolicyCmd extends BaseAsyncCmd { @Parameter(name = ApiConstants.IAM_SCOPE_ID, type = CommandType.STRING, required = false, description = "The UUID of the permission scope id") private String scopeId; + @Parameter(name = ApiConstants.READ_ONLY, type = CommandType.BOOLEAN, required = false, description = "Read Only access is added; Only applicable when action = List/Read api name") + private Boolean readOnly; + ///////////////////////////////////////////////////// /////////////////// Accessors /////////////////////// @@ -100,6 +103,10 @@ public Long getScopeId() { return _iamApiSrv.getPermissionScopeId(scope, entityType, scopeId); } + public Boolean isReadOnly() { + return (readOnly != null) ? readOnly : false; + } + ///////////////////////////////////////////////////// /////////////// API Implementation/////////////////// ///////////////////////////////////////////////////// @@ -123,7 +130,7 @@ public void execute() throws ResourceUnavailableException, CallContext.current().setEventDetails("IAM policy Id: " + getId()); // Only explicit ALLOW is supported for this release, no explicit deny IAMPolicy result = _iamApiSrv.addIAMPermissionToIAMPolicy(id, entityType, PermissionScope.valueOf(scope), - getScopeId(), action, Permission.Allow, false); + getScopeId(), action, Permission.Allow, false, isReadOnly()); if (result != null) { IAMPolicyResponse response = _iamApiSrv.createIAMPolicyResponse(result); response.setResponseName(getCommandName()); diff --git a/services/iam/plugin/src/org/apache/cloudstack/api/command/iam/CreateIAMGroupCmd.java b/services/iam/plugin/src/org/apache/cloudstack/api/command/iam/CreateIAMGroupCmd.java index d0b9bc6b1c..93940e810c 100644 --- a/services/iam/plugin/src/org/apache/cloudstack/api/command/iam/CreateIAMGroupCmd.java +++ b/services/iam/plugin/src/org/apache/cloudstack/api/command/iam/CreateIAMGroupCmd.java @@ -97,7 +97,7 @@ public String getCommandName() { @Override public long getEntityOwnerId() { Account account = CallContext.current().getCallingAccount(); - if ((account == null) || _accountService.isAdmin(account.getType())) { + if ((account == null) || _accountService.isAdmin(account.getId())) { if ((domainId != null) && (accountName != null)) { Account userAccount = _responseGenerator.findAccountByNameDomain(accountName, domainId); if (userAccount != null) { diff --git a/services/iam/plugin/src/org/apache/cloudstack/api/command/iam/CreateIAMPolicyCmd.java b/services/iam/plugin/src/org/apache/cloudstack/api/command/iam/CreateIAMPolicyCmd.java index be863de308..7ebab6735a 100644 --- a/services/iam/plugin/src/org/apache/cloudstack/api/command/iam/CreateIAMPolicyCmd.java +++ b/services/iam/plugin/src/org/apache/cloudstack/api/command/iam/CreateIAMPolicyCmd.java @@ -104,7 +104,7 @@ public String getCommandName() { @Override public long getEntityOwnerId() { Account account = CallContext.current().getCallingAccount(); - if ((account == null) || _accountService.isAdmin(account.getType())) { + if ((account == null) || _accountService.isAdmin(account.getId())) { if ((domainId != null) && (accountName != null)) { Account userAccount = _responseGenerator.findAccountByNameDomain(accountName, domainId); if (userAccount != null) { diff --git a/services/iam/plugin/src/org/apache/cloudstack/api/response/iam/IAMPermissionResponse.java b/services/iam/plugin/src/org/apache/cloudstack/api/response/iam/IAMPermissionResponse.java index 5def248d7a..046e1f4d34 100644 --- a/services/iam/plugin/src/org/apache/cloudstack/api/response/iam/IAMPermissionResponse.java +++ b/services/iam/plugin/src/org/apache/cloudstack/api/response/iam/IAMPermissionResponse.java @@ -18,7 +18,6 @@ import com.google.gson.annotations.SerializedName; -import org.apache.cloudstack.acl.IAMEntityType; import org.apache.cloudstack.acl.PermissionScope; import org.apache.cloudstack.api.ApiConstants; import org.apache.cloudstack.api.BaseResponse; @@ -34,7 +33,7 @@ public class IAMPermissionResponse extends BaseResponse { @SerializedName(ApiConstants.ENTITY_TYPE) @Param(description = "the entity type of this permission") - private IAMEntityType entityType; + private String entityType; @SerializedName(ApiConstants.IAM_SCOPE) @Param(description = "scope of this permission") @@ -48,11 +47,11 @@ public class IAMPermissionResponse extends BaseResponse { @Param(description = "allow or deny of this permission") private IAMPolicyPermission.Permission permission; - public IAMEntityType getEntityType() { + public String getEntityType() { return entityType; } - public void setEntityType(IAMEntityType entityType) { + public void setEntityType(String entityType) { this.entityType = entityType; } diff --git a/services/iam/plugin/src/org/apache/cloudstack/iam/IAMApiService.java b/services/iam/plugin/src/org/apache/cloudstack/iam/IAMApiService.java index bb8f03b77f..6735d4804d 100644 --- a/services/iam/plugin/src/org/apache/cloudstack/iam/IAMApiService.java +++ b/services/iam/plugin/src/org/apache/cloudstack/iam/IAMApiService.java @@ -60,7 +60,7 @@ public interface IAMApiService extends PluggableService { void removeIAMPolicyFromAccounts(Long policyId, List accountIds); IAMPolicy addIAMPermissionToIAMPolicy(long iamPolicyId, String entityType, PermissionScope scope, Long scopeId, - String action, Permission perm, Boolean recursive); + String action, Permission perm, Boolean recursive, Boolean readOnly); IAMPolicy removeIAMPermissionFromIAMPolicy(long iamPolicyId, String entityType, PermissionScope scope, Long scopeId, String action); diff --git a/services/iam/plugin/src/org/apache/cloudstack/iam/IAMApiServiceImpl.java b/services/iam/plugin/src/org/apache/cloudstack/iam/IAMApiServiceImpl.java index 69f669c7e1..b4c2d4d0d2 100644 --- a/services/iam/plugin/src/org/apache/cloudstack/iam/IAMApiServiceImpl.java +++ b/services/iam/plugin/src/org/apache/cloudstack/iam/IAMApiServiceImpl.java @@ -27,11 +27,18 @@ import javax.naming.ConfigurationException; import org.apache.log4j.Logger; +import org.bouncycastle.util.IPAddress; + +import com.amazonaws.auth.policy.Condition; +import com.amazonaws.services.ec2.model.SecurityGroup; +import com.amazonaws.services.ec2.model.Snapshot; +import com.amazonaws.services.ec2.model.Volume; +import com.amazonaws.services.ec2.model.Vpc; +import com.amazonaws.services.elasticache.model.Event; -import org.apache.cloudstack.acl.IAMEntityType; import org.apache.cloudstack.acl.PermissionScope; import org.apache.cloudstack.acl.SecurityChecker.AccessType; -import org.apache.cloudstack.affinity.AffinityGroupVO; +import org.apache.cloudstack.affinity.AffinityGroup; import org.apache.cloudstack.api.ApiConstants; import org.apache.cloudstack.api.BaseListCmd; import org.apache.cloudstack.api.InternalIdentity; @@ -54,7 +61,7 @@ import org.apache.cloudstack.api.response.iam.IAMPermissionResponse; import org.apache.cloudstack.api.response.iam.IAMPolicyResponse; import org.apache.cloudstack.context.CallContext; -import org.apache.cloudstack.framework.jobs.impl.AsyncJobVO; +import org.apache.cloudstack.framework.jobs.AsyncJob; import org.apache.cloudstack.framework.messagebus.MessageBus; import org.apache.cloudstack.framework.messagebus.MessageSubscriber; import org.apache.cloudstack.iam.api.IAMGroup; @@ -62,9 +69,6 @@ import org.apache.cloudstack.iam.api.IAMPolicyPermission; import org.apache.cloudstack.iam.api.IAMPolicyPermission.Permission; import org.apache.cloudstack.iam.api.IAMService; -import org.apache.cloudstack.iam.server.IAMGroupVO; -import org.apache.cloudstack.iam.server.IAMPolicyVO; -import org.apache.cloudstack.region.gslb.GlobalLoadBalancerRuleVO; import com.cloud.api.ApiServerService; import com.cloud.domain.Domain; @@ -72,50 +76,45 @@ import com.cloud.domain.dao.DomainDao; import com.cloud.event.ActionEvent; import com.cloud.event.EventTypes; -import com.cloud.event.EventVO; import com.cloud.exception.InvalidParameterValueException; -import com.cloud.network.UserIpv6AddressVO; -import com.cloud.network.VpnUserVO; -import com.cloud.network.as.AutoScalePolicyVO; -import com.cloud.network.as.AutoScaleVmGroupVO; -import com.cloud.network.as.AutoScaleVmProfileVO; -import com.cloud.network.as.ConditionVO; -import com.cloud.network.dao.IPAddressVO; -import com.cloud.network.dao.MonitoringServiceVO; -import com.cloud.network.dao.NetworkVO; -import com.cloud.network.dao.RemoteAccessVpnVO; -import com.cloud.network.dao.Site2SiteCustomerGatewayVO; -import com.cloud.network.dao.Site2SiteVpnConnectionVO; -import com.cloud.network.dao.Site2SiteVpnGatewayVO; -import com.cloud.network.dao.SslCertVO; -import com.cloud.network.rules.FirewallRuleVO; -import com.cloud.network.rules.PortForwardingRuleVO; -import com.cloud.network.security.SecurityGroupVO; -import com.cloud.network.vpc.StaticRouteVO; -import com.cloud.network.vpc.VpcGatewayVO; -import com.cloud.network.vpc.VpcVO; -import com.cloud.projects.ProjectInvitationVO; -import com.cloud.storage.SnapshotVO; -import com.cloud.storage.VMTemplateVO; -import com.cloud.storage.VolumeVO; -import com.cloud.tags.ResourceTagVO; +import com.cloud.network.IpAddress; +import com.cloud.network.MonitoringService; +import com.cloud.network.Network; +import com.cloud.network.RemoteAccessVpn; +import com.cloud.network.Site2SiteCustomerGateway; +import com.cloud.network.Site2SiteVpnConnection; +import com.cloud.network.Site2SiteVpnGateway; +import com.cloud.network.UserIpv6Address; +import com.cloud.network.VpnUser; +import com.cloud.network.as.AutoScalePolicy; +import com.cloud.network.as.AutoScaleVmGroup; +import com.cloud.network.as.AutoScaleVmProfile; +import com.cloud.network.lb.SslCert; +import com.cloud.network.rules.FirewallRule; +import com.cloud.network.rules.PortForwardingRule; +import com.cloud.network.vpc.StaticRoute; +import com.cloud.network.vpc.VpcGateway; +import com.cloud.projects.ProjectInvitation; +import com.cloud.region.ha.GlobalLoadBalancerRule; +import com.cloud.server.ResourceTag; import com.cloud.template.TemplateManager; +import com.cloud.template.VirtualMachineTemplate; import com.cloud.user.Account; import com.cloud.user.AccountManager; import com.cloud.user.AccountVO; import com.cloud.user.DomainManager; -import com.cloud.user.SSHKeyPairVO; +import com.cloud.user.SSHKeyPair; 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.EntityManager; -import com.cloud.vm.InstanceGroupVO; -import com.cloud.vm.VMInstanceVO; -import com.cloud.vm.dao.NicIpAliasVO; -import com.cloud.vm.dao.NicSecondaryIpVO; -import com.cloud.vm.snapshot.VMSnapshotVO; +import com.cloud.vm.InstanceGroup; +import com.cloud.vm.NicIpAlias; +import com.cloud.vm.NicSecondaryIp; +import com.cloud.vm.VirtualMachine; +import com.cloud.vm.snapshot.VMSnapshot; @Local(value = {IAMApiService.class}) public class IAMApiServiceImpl extends ManagerBase implements IAMApiService, Manager { @@ -144,48 +143,46 @@ public class IAMApiServiceImpl extends ManagerBase implements IAMApiService, Man @Inject EntityManager _entityMgr; - private static final Map> s_typeMap = new HashMap>(); + private static final Map> s_typeMap = new HashMap>(); static { - s_typeMap.put(IAMEntityType.VirtualMachine, VMInstanceVO.class); - s_typeMap.put(IAMEntityType.Volume, VolumeVO.class); - s_typeMap.put(IAMEntityType.ResourceTag, ResourceTagVO.class); - s_typeMap.put(IAMEntityType.Account, AccountVO.class); - s_typeMap.put(IAMEntityType.AffinityGroup, AffinityGroupVO.class); - s_typeMap.put(IAMEntityType.AutoScalePolicy, AutoScalePolicyVO.class); - s_typeMap.put(IAMEntityType.AutoScaleVmProfile, AutoScaleVmProfileVO.class); - s_typeMap.put(IAMEntityType.AutoScaleVmGroup, AutoScaleVmGroupVO.class); - s_typeMap.put(IAMEntityType.Condition, ConditionVO.class); - s_typeMap.put(IAMEntityType.Vpc, VpcVO.class); - s_typeMap.put(IAMEntityType.VpcGateway, VpcGatewayVO.class); - s_typeMap.put(IAMEntityType.PrivateGateway, RemoteAccessVpnVO.class); - s_typeMap.put(IAMEntityType.VpnUser, VpnUserVO.class); - s_typeMap.put(IAMEntityType.VMSnapshot, VMSnapshotVO.class); - s_typeMap.put(IAMEntityType.VirtualMachineTemplate, VMTemplateVO.class); - s_typeMap.put(IAMEntityType.UserIpv6Address, UserIpv6AddressVO.class); - s_typeMap.put(IAMEntityType.StaticRoute, StaticRouteVO.class); - s_typeMap.put(IAMEntityType.SSHKeyPair, SSHKeyPairVO.class); - s_typeMap.put(IAMEntityType.Snapshot, SnapshotVO.class); - s_typeMap.put(IAMEntityType.Site2SiteVpnGateway, Site2SiteVpnGatewayVO.class); - s_typeMap.put(IAMEntityType.Site2SiteCustomerGateway, Site2SiteCustomerGatewayVO.class); - s_typeMap.put(IAMEntityType.Site2SiteVpnConnection, Site2SiteVpnConnectionVO.class); - s_typeMap.put(IAMEntityType.SecurityGroup, SecurityGroupVO.class); - s_typeMap.put(IAMEntityType.RemoteAccessVpn, RemoteAccessVpnVO.class); - s_typeMap.put(IAMEntityType.PublicIpAddress, IPAddressVO.class); - s_typeMap.put(IAMEntityType.ProjectInvitation, ProjectInvitationVO.class); - s_typeMap.put(IAMEntityType.NicSecondaryIp, NicSecondaryIpVO.class); - s_typeMap.put(IAMEntityType.NicIpAlias, NicIpAliasVO.class); - s_typeMap.put(IAMEntityType.Network, NetworkVO.class); - s_typeMap.put(IAMEntityType.IpAddress, IPAddressVO.class); - s_typeMap.put(IAMEntityType.InstanceGroup, InstanceGroupVO.class); - s_typeMap.put(IAMEntityType.GlobalLoadBalancerRule, GlobalLoadBalancerRuleVO.class); - s_typeMap.put(IAMEntityType.FirewallRule, FirewallRuleVO.class); - s_typeMap.put(IAMEntityType.PortForwardingRule, PortForwardingRuleVO.class); - s_typeMap.put(IAMEntityType.Event, EventVO.class); - s_typeMap.put(IAMEntityType.AsyncJob, AsyncJobVO.class); - s_typeMap.put(IAMEntityType.IAMGroup, IAMGroupVO.class); - s_typeMap.put(IAMEntityType.IAMPolicy, IAMPolicyVO.class); - s_typeMap.put(IAMEntityType.MonitorService, MonitoringServiceVO.class); - s_typeMap.put(IAMEntityType.SSLCert, SslCertVO.class); + s_typeMap.put(VirtualMachine.class.getSimpleName(), VirtualMachine.class); + s_typeMap.put(Volume.class.getSimpleName(), Volume.class); + s_typeMap.put(ResourceTag.class.getSimpleName(), ResourceTag.class); + s_typeMap.put(Account.class.getSimpleName(), Account.class); + s_typeMap.put(AffinityGroup.class.getSimpleName(), AffinityGroup.class); + s_typeMap.put(AutoScalePolicy.class.getSimpleName(), AutoScalePolicy.class); + s_typeMap.put(AutoScaleVmProfile.class.getSimpleName(), AutoScaleVmProfile.class); + s_typeMap.put(AutoScaleVmGroup.class.getSimpleName(), AutoScaleVmGroup.class); + s_typeMap.put(Condition.class.getSimpleName(), Condition.class); + s_typeMap.put(Vpc.class.getSimpleName(), Vpc.class); + s_typeMap.put(VpcGateway.class.getSimpleName(), VpcGateway.class); + s_typeMap.put(VpnUser.class.getSimpleName(), VpnUser.class); + s_typeMap.put(VMSnapshot.class.getSimpleName(), VMSnapshot.class); + s_typeMap.put(VirtualMachineTemplate.class.getSimpleName(), VirtualMachineTemplate.class); + s_typeMap.put(UserIpv6Address.class.getSimpleName(), UserIpv6Address.class); + s_typeMap.put(StaticRoute.class.getSimpleName(), StaticRoute.class); + s_typeMap.put(SSHKeyPair.class.getSimpleName(), SSHKeyPair.class); + s_typeMap.put(Snapshot.class.getSimpleName(), Snapshot.class); + s_typeMap.put(Site2SiteVpnGateway.class.getSimpleName(), Site2SiteVpnGateway.class); + s_typeMap.put(Site2SiteCustomerGateway.class.getSimpleName(), Site2SiteCustomerGateway.class); + s_typeMap.put(Site2SiteVpnConnection.class.getSimpleName(), Site2SiteVpnConnection.class); + s_typeMap.put(SecurityGroup.class.getSimpleName(), SecurityGroup.class); + s_typeMap.put(RemoteAccessVpn.class.getSimpleName(), RemoteAccessVpn.class); + s_typeMap.put(ProjectInvitation.class.getSimpleName(), ProjectInvitation.class); + s_typeMap.put(NicSecondaryIp.class.getSimpleName(), NicSecondaryIp.class); + s_typeMap.put(NicIpAlias.class.getSimpleName(), NicIpAlias.class); + s_typeMap.put(Network.class.getSimpleName(), Network.class); + s_typeMap.put(IpAddress.class.getSimpleName(), IPAddress.class); + s_typeMap.put(InstanceGroup.class.getSimpleName(), InstanceGroup.class); + s_typeMap.put(GlobalLoadBalancerRule.class.getSimpleName(), GlobalLoadBalancerRule.class); + s_typeMap.put(FirewallRule.class.getSimpleName(), FirewallRule.class); + s_typeMap.put(PortForwardingRule.class.getSimpleName(), PortForwardingRule.class); + s_typeMap.put(Event.class.getSimpleName(), Event.class); + s_typeMap.put(AsyncJob.class.getSimpleName(), AsyncJob.class); + s_typeMap.put(IAMGroup.class.getSimpleName(), IAMGroup.class); + s_typeMap.put(IAMPolicy.class.getSimpleName(), IAMPolicy.class); + s_typeMap.put(MonitoringService.class.getSimpleName(), MonitoringService.class); + s_typeMap.put(SslCert.class.getSimpleName(), SslCert.class); } @Override @@ -246,7 +243,7 @@ public void onPublishMessage(String senderAddress, String subject, Object obj) { Long domainId = ((Long) obj); if (domainId != null) { s_logger.debug("MessageBus message: Domain removed: " + domainId + ", removing the domain group"); - Domain domain = _domainDao.findById(domainId); + Domain domain = _domainDao.findByIdIncludingRemoved(domainId); List groups = listDomainGroup(domain); for (IAMGroup group : groups) { _iamSrv.deleteIAMGroup(group.getId()); @@ -260,10 +257,13 @@ public void onPublishMessage(String senderAddress, String subject, Object obj) { public void onPublishMessage(String senderAddress, String subject, Object obj) { Long templateId = (Long)obj; if (templateId != null) { - s_logger.debug("MessageBus message: new public template registered: " + templateId + ", grant permission to domain admin and normal user policies"); - _iamSrv.addIAMPermissionToIAMPolicy(new Long(Account.ACCOUNT_TYPE_DOMAIN_ADMIN + 1), IAMEntityType.VirtualMachineTemplate.toString(), + s_logger.debug("MessageBus message: new public template registered: " + templateId + + ", grant permission to default root admin, domain admin and normal user policies"); + _iamSrv.addIAMPermissionToIAMPolicy(new Long(Account.ACCOUNT_TYPE_ADMIN + 1), VirtualMachineTemplate.class.getSimpleName(), + PermissionScope.RESOURCE.toString(), templateId, "listTemplates", AccessType.UseEntry.toString(), Permission.Allow, false); + _iamSrv.addIAMPermissionToIAMPolicy(new Long(Account.ACCOUNT_TYPE_DOMAIN_ADMIN + 1), VirtualMachineTemplate.class.getSimpleName(), PermissionScope.RESOURCE.toString(), templateId, "listTemplates", AccessType.UseEntry.toString(), Permission.Allow, false); - _iamSrv.addIAMPermissionToIAMPolicy(new Long(Account.ACCOUNT_TYPE_NORMAL + 1), IAMEntityType.VirtualMachineTemplate.toString(), + _iamSrv.addIAMPermissionToIAMPolicy(new Long(Account.ACCOUNT_TYPE_NORMAL + 1), VirtualMachineTemplate.class.getSimpleName(), PermissionScope.RESOURCE.toString(), templateId, "listTemplates", AccessType.UseEntry.toString(), Permission.Allow, false); } } @@ -283,9 +283,9 @@ public void onPublishMessage(String senderAddress, String subject, Object obj) { _messageBus.subscribe(EntityManager.MESSAGE_REMOVE_ENTITY_EVENT, new MessageSubscriber() { @Override public void onPublishMessage(String senderAddress, String subject, Object obj) { - Pair entity = (Pair)obj; + Pair, Long> entity = (Pair, Long>)obj; if (entity != null) { - String entityType = entity.first().toString(); + String entityType = entity.first().getSimpleName(); Long entityId = entity.second(); s_logger.debug("MessageBus message: delete an entity: (" + entityType + "," + entityId + "), remove its related permission"); _iamSrv.removeIAMPermissionForEntity(entityType, entityId); @@ -299,13 +299,13 @@ public void onPublishMessage(String senderAddress, String subject, Object obj) { public void onPublishMessage(String senderAddress, String subject, Object obj) { Map permit = (Map)obj; if (permit != null) { - String entityType = (String)permit.get(ApiConstants.ENTITY_TYPE); + Class entityType = (Class)permit.get(ApiConstants.ENTITY_TYPE); Long entityId = (Long)permit.get(ApiConstants.ENTITY_ID); AccessType accessType = (AccessType)permit.get(ApiConstants.ACCESS_TYPE); String action = (String)permit.get(ApiConstants.IAM_ACTION); List acctIds = (List)permit.get(ApiConstants.ACCOUNTS); s_logger.debug("MessageBus message: grant accounts permission to an entity: (" + entityType + "," + entityId + ")"); - grantEntityPermissioinToAccounts(entityType, entityId, accessType, action, acctIds); + grantEntityPermissioinToAccounts(entityType.getSimpleName(), entityId, accessType, action, acctIds); } } }); @@ -315,13 +315,13 @@ public void onPublishMessage(String senderAddress, String subject, Object obj) { public void onPublishMessage(String senderAddress, String subject, Object obj) { Map permit = (Map)obj; if (permit != null) { - String entityType = (String)permit.get(ApiConstants.ENTITY_TYPE); + Class entityType = (Class)permit.get(ApiConstants.ENTITY_TYPE); Long entityId = (Long)permit.get(ApiConstants.ENTITY_ID); AccessType accessType = (AccessType)permit.get(ApiConstants.ACCESS_TYPE); String action = (String)permit.get(ApiConstants.IAM_ACTION); List acctIds = (List)permit.get(ApiConstants.ACCOUNTS); s_logger.debug("MessageBus message: revoke from accounts permission to an entity: (" + entityType + "," + entityId + ")"); - revokeEntityPermissioinFromAccounts(entityType, entityId, accessType, action, acctIds); + revokeEntityPermissioinFromAccounts(entityType.getSimpleName(), entityId, accessType, action, acctIds); } } }); @@ -355,20 +355,35 @@ private void populateIAMGroupAdminAccountMap() { sysAccts.add(Account.ACCOUNT_ID_SYSTEM); sysAccts.add(Account.ACCOUNT_ID_SYSTEM + 1); _iamSrv.addAccountsToGroup(sysAccts, new Long(Account.ACCOUNT_TYPE_ADMIN + 1)); + + // add the root domain group + Domain domain = _domainDao.findById(Domain.ROOT_DOMAIN); + if (domain != null) { + List domainGroups = listDomainGroup(domain); + if (domainGroups != null && !domainGroups.isEmpty()) { + return; + } + IAMGroup rootDomainGrp = _iamSrv.createIAMGroup("DomainGrp-" + domain.getUuid(), "Root Domain group", + domain.getPath()); + // add the system accounts to the root domain group + _iamSrv.addAccountsToGroup(sysAccts, rootDomainGrp.getId()); + + } + } private void addDomainWideResourceAccess(Map params) { - IAMEntityType entityType = (IAMEntityType)params.get(ApiConstants.ENTITY_TYPE); + Class entityType = (Class)params.get(ApiConstants.ENTITY_TYPE); Long entityId = (Long) params.get(ApiConstants.ENTITY_ID); Long domainId = (Long) params.get(ApiConstants.DOMAIN_ID); Boolean isRecursive = (Boolean) params.get(ApiConstants.SUBDOMAIN_ACCESS); - if (entityType == IAMEntityType.Network) { - createPolicyAndAddToDomainGroup("DomainWideNetwork-" + entityId, "domain wide network", entityType.toString(), + if (entityType == Network.class) { + createPolicyAndAddToDomainGroup("DomainWideNetwork-" + entityId, "domain wide network", entityType.getSimpleName(), entityId, "listNetworks", AccessType.UseEntry, domainId, isRecursive); - } else if (entityType == IAMEntityType.AffinityGroup) { - createPolicyAndAddToDomainGroup("DomainWideNetwork-" + entityId, "domain wide affinityGroup", entityType.toString(), + } else if (entityType == AffinityGroup.class) { + createPolicyAndAddToDomainGroup("DomainWideNetwork-" + entityId, "domain wide affinityGroup", entityType.getSimpleName(), entityId, "listAffinityGroups", AccessType.UseEntry, domainId, isRecursive); } @@ -509,11 +524,17 @@ public void removeIAMPolicyFromAccounts(final Long policyId, final List ac @Override @ActionEvent(eventType = EventTypes.EVENT_IAM_POLICY_GRANT, eventDescription = "Granting acl permission to IAM Policy") public IAMPolicy addIAMPermissionToIAMPolicy(long iamPolicyId, String entityType, PermissionScope scope, - Long scopeId, String action, Permission perm, Boolean recursive) { + Long scopeId, String action, Permission perm, Boolean recursive, Boolean readOnly) { Class cmdClass = _apiServer.getCmdClass(action); AccessType accessType = null; if (BaseListCmd.class.isAssignableFrom(cmdClass)) { - accessType = AccessType.UseEntry; + if (readOnly) { + accessType = AccessType.ListEntry; + } else { + accessType = AccessType.UseEntry; + } + } else { + accessType = AccessType.OperateEntry; } String accessTypeStr = (accessType != null) ? accessType.toString() : null; return _iamSrv.addIAMPermissionToIAMPolicy(iamPolicyId, entityType, scope.toString(), scopeId, action, @@ -575,7 +596,7 @@ public IAMPolicyResponse createIAMPolicyResponse(IAMPolicy policy) { IAMPermissionResponse perm = new IAMPermissionResponse(); perm.setAction(permission.getAction()); if (permission.getEntityType() != null) { - perm.setEntityType(IAMEntityType.valueOf(permission.getEntityType())); + perm.setEntityType(permission.getEntityType()); } if (permission.getScope() != null) { perm.setScope(PermissionScope.valueOf(permission.getScope())); @@ -717,7 +738,8 @@ public void grantEntityPermissioinToAccounts(String entityType, Long entityId, A String description = "Policy to grant permission to " + entityType + entityId; policy = createIAMPolicy(caller, aclPolicyName, description, null); // add permission to this policy - addIAMPermissionToIAMPolicy(policy.getId(), entityType, PermissionScope.RESOURCE, entityId, action, Permission.Allow, false); + addIAMPermissionToIAMPolicy(policy.getId(), entityType, PermissionScope.RESOURCE, entityId, action, + Permission.Allow, false, false); } // attach this policy to list of accounts if not attached already Long policyId = policy.getId(); @@ -758,12 +780,12 @@ private boolean isPolicyAttachedToAccount(Long policyId, Long accountId) { private void resetTemplatePermission(Long templateId){ // reset template will change template to private, so we need to remove its permission for domain admin and normal user group - _iamSrv.removeIAMPermissionFromIAMPolicy(new Long(Account.ACCOUNT_TYPE_DOMAIN_ADMIN + 1), IAMEntityType.VirtualMachineTemplate.toString(), + _iamSrv.removeIAMPermissionFromIAMPolicy(new Long(Account.ACCOUNT_TYPE_DOMAIN_ADMIN + 1), VirtualMachineTemplate.class.getSimpleName(), PermissionScope.RESOURCE.toString(), templateId, "listTemplates"); - _iamSrv.removeIAMPermissionFromIAMPolicy(new Long(Account.ACCOUNT_TYPE_NORMAL + 1), IAMEntityType.VirtualMachineTemplate.toString(), + _iamSrv.removeIAMPermissionFromIAMPolicy(new Long(Account.ACCOUNT_TYPE_NORMAL + 1), VirtualMachineTemplate.class.getSimpleName(), PermissionScope.RESOURCE.toString(), templateId, "listTemplates"); // check if there is a policy with only UseEntry permission for this template added - IAMPolicy policy = _iamSrv.getResourceGrantPolicy(IAMEntityType.VirtualMachineTemplate.toString(), templateId, AccessType.UseEntry.toString(), "listTemplates"); + IAMPolicy policy = _iamSrv.getResourceGrantPolicy(VirtualMachineTemplate.class.getSimpleName(), templateId, AccessType.UseEntry.toString(), "listTemplates"); if ( policy == null ){ s_logger.info("No policy found for this template grant: " + templateId + ", no detach to be done"); return; @@ -788,7 +810,7 @@ public Long getPermissionScopeId(String scope, String entityType, String scopeId entity = _accountDao.findByUuid(scopeId); break; case RESOURCE: - Class clazz = s_typeMap.get(IAMEntityType.valueOf(entityType)); + Class clazz = s_typeMap.get(entityType); entity = (InternalIdentity)_entityMgr.findByUuid(clazz, scopeId); } diff --git a/services/iam/plugin/src/org/apache/cloudstack/iam/RoleBasedAPIAccessChecker.java b/services/iam/plugin/src/org/apache/cloudstack/iam/RoleBasedAPIAccessChecker.java index fb75db310f..91593f6f23 100644 --- a/services/iam/plugin/src/org/apache/cloudstack/iam/RoleBasedAPIAccessChecker.java +++ b/services/iam/plugin/src/org/apache/cloudstack/iam/RoleBasedAPIAccessChecker.java @@ -29,12 +29,10 @@ import org.apache.log4j.Logger; import org.apache.cloudstack.acl.APIChecker; -import org.apache.cloudstack.acl.IAMEntityType; import org.apache.cloudstack.acl.PermissionScope; import org.apache.cloudstack.acl.RoleType; import org.apache.cloudstack.acl.SecurityChecker.AccessType; import org.apache.cloudstack.api.APICommand; -import org.apache.cloudstack.api.BaseAsyncCreateCmd; import org.apache.cloudstack.api.BaseCmd; import org.apache.cloudstack.api.BaseListCmd; import org.apache.cloudstack.iam.api.IAMPolicy; @@ -46,6 +44,7 @@ import com.cloud.exception.PermissionDeniedException; import com.cloud.storage.VMTemplateVO; import com.cloud.storage.dao.VMTemplateDao; +import com.cloud.template.VirtualMachineTemplate; import com.cloud.user.Account; import com.cloud.user.AccountService; import com.cloud.user.User; @@ -133,9 +132,11 @@ public boolean start() { // add permissions for public templates List pTmplts = _templateDao.listByPublic(); for (VMTemplateVO tmpl : pTmplts){ - _iamSrv.addIAMPermissionToIAMPolicy(new Long(Account.ACCOUNT_TYPE_DOMAIN_ADMIN + 1), IAMEntityType.VirtualMachineTemplate.toString(), + _iamSrv.addIAMPermissionToIAMPolicy(new Long(Account.ACCOUNT_TYPE_ADMIN + 1), VirtualMachineTemplate.class.getSimpleName(), PermissionScope.RESOURCE.toString(), tmpl.getId(), "listTemplates", AccessType.UseEntry.toString(), Permission.Allow, false); - _iamSrv.addIAMPermissionToIAMPolicy(new Long(Account.ACCOUNT_TYPE_NORMAL + 1), IAMEntityType.VirtualMachineTemplate.toString(), + _iamSrv.addIAMPermissionToIAMPolicy(new Long(Account.ACCOUNT_TYPE_DOMAIN_ADMIN + 1), VirtualMachineTemplate.class.getSimpleName(), + PermissionScope.RESOURCE.toString(), tmpl.getId(), "listTemplates", AccessType.UseEntry.toString(), Permission.Allow, false); + _iamSrv.addIAMPermissionToIAMPolicy(new Long(Account.ACCOUNT_TYPE_NORMAL + 1), VirtualMachineTemplate.class.getSimpleName(), PermissionScope.RESOURCE.toString(), tmpl.getId(), "listTemplates", AccessType.UseEntry.toString(), Permission.Allow, false); } @@ -216,26 +217,8 @@ public void setServices(List services) { } private void addDefaultAclPolicyPermission(String apiName, Class cmdClass, RoleType role) { - AccessType accessType = null; - IAMEntityType[] entityTypes = null; - if (cmdClass != null) { - BaseCmd cmdObj; - try { - cmdObj = (BaseCmd) cmdClass.newInstance(); - if (cmdObj instanceof BaseListCmd) { - accessType = AccessType.UseEntry; - } else if (!(cmdObj instanceof BaseAsyncCreateCmd)) { - accessType = AccessType.OperateEntry; - } - } catch (Exception e) { - throw new CloudRuntimeException(String.format( - "%s is claimed as an API command, but it cannot be instantiated", cmdClass.getName())); - } - - APICommand at = cmdClass.getAnnotation(APICommand.class); - entityTypes = at.entityType(); - } + Class[] entityTypes = null; PermissionScope permissionScope = PermissionScope.ACCOUNT; Long policyId = getDefaultPolicyId(role); @@ -257,14 +240,43 @@ private void addDefaultAclPolicyPermission(String apiName, Class cmdClass, Ro break; } + boolean addAccountScopedUseEntry = false; + + if (cmdClass != null) { + BaseCmd cmdObj; + try { + cmdObj = (BaseCmd) cmdClass.newInstance(); + if (cmdObj instanceof BaseListCmd) { + accessType = AccessType.ListEntry; + addAccountScopedUseEntry = true; + } else { + accessType = AccessType.OperateEntry; + } + } catch (Exception e) { + throw new CloudRuntimeException(String.format( + "%s is claimed as an API command, but it cannot be instantiated", cmdClass.getName())); + } + + APICommand at = cmdClass.getAnnotation(APICommand.class); + entityTypes = at.entityType(); + } if (entityTypes == null || entityTypes.length == 0) { _iamSrv.addIAMPermissionToIAMPolicy(policyId, null, permissionScope.toString(), new Long(IAMPolicyPermission.PERMISSION_SCOPE_ID_CURRENT_CALLER), apiName, (accessType == null) ? null : accessType.toString(), Permission.Allow, false); + if (addAccountScopedUseEntry) { + _iamSrv.addIAMPermissionToIAMPolicy(policyId, null, PermissionScope.ACCOUNT.toString(), new Long( + IAMPolicyPermission.PERMISSION_SCOPE_ID_CURRENT_CALLER), apiName, AccessType.UseEntry.toString(), Permission.Allow, false); + } } else { - for (IAMEntityType entityType : entityTypes) { - _iamSrv.addIAMPermissionToIAMPolicy(policyId, entityType.toString(), permissionScope.toString(), new Long(IAMPolicyPermission.PERMISSION_SCOPE_ID_CURRENT_CALLER), + for (Class entityType : entityTypes) { + _iamSrv.addIAMPermissionToIAMPolicy(policyId, entityType.getSimpleName(), permissionScope.toString(), new Long( + IAMPolicyPermission.PERMISSION_SCOPE_ID_CURRENT_CALLER), apiName, (accessType == null) ? null : accessType.toString(), Permission.Allow, false); + if (addAccountScopedUseEntry) { + _iamSrv.addIAMPermissionToIAMPolicy(policyId, entityType.getSimpleName(), PermissionScope.ACCOUNT.toString(), new Long( + IAMPolicyPermission.PERMISSION_SCOPE_ID_CURRENT_CALLER), apiName, AccessType.UseEntry.toString(), Permission.Allow, false); + } } } diff --git a/services/iam/plugin/src/org/apache/cloudstack/iam/RoleBasedEntityAccessChecker.java b/services/iam/plugin/src/org/apache/cloudstack/iam/RoleBasedEntityAccessChecker.java index 3fe854a2a0..7b3d967ffd 100644 --- a/services/iam/plugin/src/org/apache/cloudstack/iam/RoleBasedEntityAccessChecker.java +++ b/services/iam/plugin/src/org/apache/cloudstack/iam/RoleBasedEntityAccessChecker.java @@ -59,6 +59,25 @@ public boolean checkAccess(Account caller, ControlledEntity entity, AccessType a return checkAccess(caller, entity, accessType, null); } + private String buildAccessCacheKey(Account caller, ControlledEntity entity, AccessType accessType, String action) { + StringBuffer key = new StringBuffer(); + key.append(caller.getAccountId()); + key.append("-"); + String entityType = null; + if (entity != null && entity.getEntityType() != null) { + entityType = entity.getEntityType().getSimpleName(); + if (entity instanceof InternalIdentity) { + entityType += ((InternalIdentity)entity).getId(); + } + } + key.append(entityType != null ? entityType : "null"); + key.append("-"); + key.append(accessType != null ? accessType.toString() : "null"); + key.append("-"); + key.append(action != null ? action : "null"); + return key.toString(); + } + @Override public boolean checkAccess(Account caller, ControlledEntity entity, AccessType accessType, String action) throws PermissionDeniedException { @@ -66,32 +85,60 @@ public boolean checkAccess(Account caller, ControlledEntity entity, AccessType a if (caller == null) { throw new InvalidParameterValueException("Caller cannot be passed as NULL to IAM!"); } + + if (entity == null && action == null) { + throw new InvalidParameterValueException("Entity and action cannot be both NULL in checkAccess!"); + } + + // check IAM cache first + String accessKey = buildAccessCacheKey(caller, entity, accessType, action); + CheckAccessResult allowDeny = (CheckAccessResult)_iamSrv.getFromIAMCache(accessKey); + if (allowDeny != null) { + s_logger.debug("IAM access check for " + accessKey + " from cache: " + allowDeny.isAllow()); + if (allowDeny.isAllow()) { + return true; + } else { + if (allowDeny.getDenyMsg() != null) { + throw new PermissionDeniedException(allowDeny.getDenyMsg()); + } else { + return false; + } + } + } + if (entity == null && action != null) { // check if caller can do this action List policies = _iamSrv.listIAMPolicies(caller.getAccountId()); boolean isAllowed = _iamSrv.isActionAllowedForPolicies(action, policies); if (!isAllowed) { - throw new PermissionDeniedException("The action '" + action + "' not allowed for account " + caller); + String msg = "The action '" + action + "' not allowed for account " + caller; + _iamSrv.addToIAMCache(accessKey, new CheckAccessResult(msg)); + throw new PermissionDeniedException(msg); } + _iamSrv.addToIAMCache(accessKey, new CheckAccessResult(true)); return true; } - if (entity == null) { - throw new InvalidParameterValueException("Entity and action cannot be both NULL in checkAccess!"); + + // if a Project entity, skip + Account entityAccount = _accountService.getAccount(entity.getAccountId()); + if (entityAccount != null && entityAccount.getType() == Account.ACCOUNT_TYPE_PROJECT) { + _iamSrv.addToIAMCache(accessKey, new CheckAccessResult(false)); + return false; } String entityType = null; if (entity.getEntityType() != null) { - entityType = entity.getEntityType().toString(); + entityType = entity.getEntityType().getSimpleName(); } if (accessType == null) { accessType = AccessType.UseEntry; } - // get all Policies of this caller w.r.t the entity - List policies = getEffectivePolicies(caller, entity); + // get all Policies of this caller by considering recursive domain group policy + List policies = getEffectivePolicies(caller); HashMap policyPermissionMap = new HashMap(); for (IAMPolicy policy : policies) { @@ -122,22 +169,71 @@ public boolean checkAccess(Account caller, ControlledEntity entity, AccessType a } } if (policyPermissionMap.containsKey(policy) && policyPermissionMap.get(policy)) { + _iamSrv.addToIAMCache(accessKey, new CheckAccessResult(true)); return true; } } if (!policies.isEmpty()) { // Since we reach this point, none of the // roles granted access + + String msg = "Account " + caller + " does not have permission to access resource " + entity + + " for access type: " + accessType; if (s_logger.isDebugEnabled()) { - s_logger.debug("Account " + caller + " does not have permission to access resource " + entity - + " for access type: " + accessType); + s_logger.debug(msg); } - throw new PermissionDeniedException(caller + " does not have permission to access resource " + entity); + _iamSrv.addToIAMCache(accessKey, new CheckAccessResult(msg)); + throw new PermissionDeniedException(msg); } + _iamSrv.addToIAMCache(accessKey, new CheckAccessResult(false)); return false; } + @Override + public boolean checkAccess(Account caller, AccessType accessType, String action, ControlledEntity... entities) + throws PermissionDeniedException { + + // operate access on multiple entities? + if (accessType != null && accessType == AccessType.OperateEntry) { + // In this case caller MUST own n-1 entities. + + for (ControlledEntity entity : entities) { + checkAccess(caller, entity, accessType, action); + + boolean otherEntitiesAccess = true; + + for (ControlledEntity otherEntity : entities) { + if (otherEntity != entity) { + if (otherEntity.getAccountId() == caller.getAccountId() + || (checkAccess(caller, otherEntity, accessType, action) && otherEntity.getAccountId() == entity + .getAccountId())) { + continue; + } else { + otherEntitiesAccess = false; + break; + } + } + } + + if (otherEntitiesAccess) { + return true; + } + } + + throw new PermissionDeniedException(caller + + " does not have permission to perform this operation on these resources"); + + } else { + for (ControlledEntity entity : entities) { + if (!checkAccess(caller, entity, accessType, action)) { + return false; + } + } + return true; + } + } + private boolean checkPermissionScope(Account caller, String scope, Long scopeId, ControlledEntity entity) { if(scopeId != null && !scopeId.equals(new Long(IAMPolicyPermission.PERMISSION_SCOPE_ID_CURRENT_CALLER))){ @@ -167,22 +263,17 @@ private boolean checkPermissionScope(Account caller, String scope, Long scopeId, if (_domainDao.isChildDomain(caller.getDomainId(), entity.getDomainId())) { return true; } + } else if (scope.equals(PermissionScope.ALL.name())) { + return true; } } return false; } - private List getEffectivePolicies(Account caller, ControlledEntity entity) { + private List getEffectivePolicies(Account caller) { - // Get the static Policies of the Caller List policies = _iamSrv.listIAMPolicies(caller.getId()); - // add any dynamic policies w.r.t the entity - if (caller.getId() == entity.getAccountId()) { - // The caller owns the entity - policies.add(_iamSrv.getResourceOwnerPolicy()); - } - List groups = _iamSrv.listIAMGroups(caller.getId()); for (IAMGroup group : groups) { // for each group find the grand parent groups. @@ -194,4 +285,40 @@ private List getEffectivePolicies(Account caller, ControlledEntity en return policies; } + + private class CheckAccessResult { + boolean allow; + String denyMsg; + + public CheckAccessResult(boolean aw) { + this(aw, null); + } + + public CheckAccessResult(String msg) { + this(false, msg); + } + + public CheckAccessResult(boolean aw, String msg) { + allow = aw; + denyMsg = msg; + } + + public boolean isAllow() { + return allow; + } + + public void setAllow(boolean aw) { + allow = aw; + } + + + public String getDenyMsg() { + return denyMsg; + } + + public void setDenyMsg(String denyMsg) { + this.denyMsg = denyMsg; + } + + } } diff --git a/services/iam/plugin/src/org/apache/cloudstack/iam/RoleBasedEntityQuerySelector.java b/services/iam/plugin/src/org/apache/cloudstack/iam/RoleBasedEntityQuerySelector.java index 23c57a1688..5d31433803 100644 --- a/services/iam/plugin/src/org/apache/cloudstack/iam/RoleBasedEntityQuerySelector.java +++ b/services/iam/plugin/src/org/apache/cloudstack/iam/RoleBasedEntityQuerySelector.java @@ -25,11 +25,14 @@ import org.apache.cloudstack.acl.PermissionScope; import org.apache.cloudstack.acl.QuerySelector; +import org.apache.cloudstack.acl.SecurityChecker.AccessType; import org.apache.cloudstack.iam.api.IAMGroup; import org.apache.cloudstack.iam.api.IAMPolicy; import org.apache.cloudstack.iam.api.IAMPolicyPermission; import org.apache.cloudstack.iam.api.IAMService; +import com.cloud.domain.DomainVO; +import com.cloud.domain.dao.DomainDao; import com.cloud.user.Account; import com.cloud.utils.component.AdapterBase; @@ -39,24 +42,44 @@ public class RoleBasedEntityQuerySelector extends AdapterBase implements QuerySe @Inject IAMService _iamService; + @Inject + DomainDao _domainDao; @Override - public List getAuthorizedDomains(Account caller, String action) { + public List getAuthorizedDomains(Account caller, String action, AccessType accessType) { long accountId = caller.getAccountId(); + if (accessType == null) { + accessType = AccessType.UseEntry; // default always show resources authorized to use + } // Get the static Policies of the Caller List policies = _iamService.listIAMPolicies(accountId); // for each policy, find granted permission with Domain scope List domainIds = new ArrayList(); for (IAMPolicy policy : policies) { - List pp = _iamService.listPolicyPermissionsByScope(policy.getId(), action, PermissionScope.DOMAIN.toString()); + List pp = new ArrayList(); + pp.addAll(_iamService.listPolicyPermissionsByScope(policy.getId(), action, + PermissionScope.DOMAIN.toString(), accessType.toString())); + if (pp != null) { for (IAMPolicyPermission p : pp) { if (p.getScopeId() != null) { + Long domainId = null; if (p.getScopeId().longValue() == -1) { - domainIds.add(caller.getDomainId()); + domainId = caller.getDomainId(); + //domainIds.add(caller.getDomainId()); } else { - domainIds.add(p.getScopeId()); + domainId = p.getScopeId(); + //domainIds.add(p.getScopeId()); } + //domainIds.add(domainId); + // add all the domain children from this domain (including this domain itself). Like RoleBasedEntityAccessChecker, we made an assumption, if DOMAIN scope is granted, it means that + // the whole domain tree is granted access. + DomainVO domain = _domainDao.findById(domainId); + List childDomains = _domainDao.getDomainChildrenIds(domain.getPath()); + if (childDomains != null && childDomains.size() > 0) { + domainIds.addAll(childDomains); + } + } } } @@ -65,14 +88,20 @@ public List getAuthorizedDomains(Account caller, String action) { } @Override - public List getAuthorizedAccounts(Account caller, String action) { + public List getAuthorizedAccounts(Account caller, String action, AccessType accessType) { long accountId = caller.getAccountId(); + if (accessType == null) { + accessType = AccessType.UseEntry; // default always show resources authorized to use + } // Get the static Policies of the Caller List policies = _iamService.listIAMPolicies(accountId); // for each policy, find granted permission with Account scope List accountIds = new ArrayList(); for (IAMPolicy policy : policies) { - List pp = _iamService.listPolicyPermissionsByScope(policy.getId(), action, PermissionScope.ACCOUNT.toString()); + List pp = new ArrayList(); + pp.addAll(_iamService.listPolicyPermissionsByScope(policy.getId(), action, + PermissionScope.ACCOUNT.toString(), accessType.toString())); + if (pp != null) { for (IAMPolicyPermission p : pp) { if (p.getScopeId() != null) { @@ -89,8 +118,11 @@ public List getAuthorizedAccounts(Account caller, String action) { } @Override - public List getAuthorizedResources(Account caller, String action) { + public List getAuthorizedResources(Account caller, String action, AccessType accessType) { long accountId = caller.getAccountId(); + if (accessType == null) { + accessType = AccessType.UseEntry; // default always show resources authorized to use + } // Get the static Policies of the Caller List policies = _iamService.listIAMPolicies(accountId); @@ -107,7 +139,10 @@ public List getAuthorizedResources(Account caller, String action) { // for each policy, find granted permission with Resource scope List entityIds = new ArrayList(); for (IAMPolicy policy : policies) { - List pp = _iamService.listPolicyPermissionsByScope(policy.getId(), action, PermissionScope.RESOURCE.toString()); + List pp = new ArrayList(); + pp.addAll(_iamService.listPolicyPermissionsByScope(policy.getId(), action, + PermissionScope.RESOURCE.toString(), accessType.toString())); + if (pp != null) { for (IAMPolicyPermission p : pp) { if (p.getScopeId() != null) { @@ -120,13 +155,18 @@ public List getAuthorizedResources(Account caller, String action) { } @Override - public boolean isGrantedAll(Account caller, String action) { + public boolean isGrantedAll(Account caller, String action, AccessType accessType) { long accountId = caller.getAccountId(); + if (accessType == null) { + accessType = AccessType.UseEntry; // default always show resources authorized to use + } // Get the static Policies of the Caller List policies = _iamService.listIAMPolicies(accountId); // for each policy, find granted permission with ALL scope for (IAMPolicy policy : policies) { - List pp = _iamService.listPolicyPermissionsByScope(policy.getId(), action, PermissionScope.ALL.toString()); + List pp = new ArrayList(); + pp.addAll(_iamService.listPolicyPermissionsByScope(policy.getId(), action, PermissionScope.ALL.toString(), + accessType.toString())); if (pp != null && pp.size() > 0) { return true; } diff --git a/services/iam/plugin/test/org/apache/cloudstack/iam/test/IAMApiServiceTest.java b/services/iam/plugin/test/org/apache/cloudstack/iam/test/IAMApiServiceTest.java index b825ab224f..84e1e56255 100644 --- a/services/iam/plugin/test/org/apache/cloudstack/iam/test/IAMApiServiceTest.java +++ b/services/iam/plugin/test/org/apache/cloudstack/iam/test/IAMApiServiceTest.java @@ -50,7 +50,6 @@ import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; import org.springframework.test.context.support.AnnotationConfigContextLoader; -import org.apache.cloudstack.acl.IAMEntityType; import org.apache.cloudstack.acl.PermissionScope; import org.apache.cloudstack.acl.SecurityChecker.AccessType; import org.apache.cloudstack.api.command.user.vm.ListVMsCmd; @@ -84,6 +83,7 @@ import com.cloud.utils.Pair; import com.cloud.utils.component.ComponentContext; import com.cloud.utils.db.EntityManager; +import com.cloud.vm.VirtualMachine; @RunWith(SpringJUnit4ClassRunner.class) @ContextConfiguration(loader = AnnotationConfigContextLoader.class) @@ -292,15 +292,15 @@ public void addRemovePermissionToPolicyTest() { Class clz = ListVMsCmd.class; when(_apiServer.getCmdClass("listVirtualMachines")).thenReturn(clz); when( - _iamSrv.addIAMPermissionToIAMPolicy(policyId, IAMEntityType.VirtualMachine.toString(), + _iamSrv.addIAMPermissionToIAMPolicy(policyId, VirtualMachine.class.getSimpleName(), PermissionScope.RESOURCE.toString(), resId, "listVirtualMachines", AccessType.UseEntry.toString(), Permission.Allow, false)).thenReturn(policy); - _aclSrv.addIAMPermissionToIAMPolicy(policyId, IAMEntityType.VirtualMachine.toString(), - PermissionScope.RESOURCE, resId, "listVirtualMachines", Permission.Allow, false); + _aclSrv.addIAMPermissionToIAMPolicy(policyId, VirtualMachine.class.getSimpleName(), + PermissionScope.RESOURCE, resId, "listVirtualMachines", Permission.Allow, false, false); Pair, Integer> policyList = new Pair, Integer>(policies, 1); List policyPerms = new ArrayList(); IAMPolicyPermission perm = new IAMPolicyPermissionVO(policyId, "listVirtualMachines", - IAMEntityType.VirtualMachine.toString(), AccessType.UseEntry.toString(), + VirtualMachine.class.getSimpleName(), AccessType.UseEntry.toString(), PermissionScope.RESOURCE.toString(), resId, Permission.Allow, false); policyPerms.add(perm); @@ -316,7 +316,7 @@ public void addRemovePermissionToPolicyTest() { //remove permission from policy policyPerms.remove(perm); - _aclSrv.removeIAMPermissionFromIAMPolicy(policyId, IAMEntityType.VirtualMachine.toString(), + _aclSrv.removeIAMPermissionFromIAMPolicy(policyId, VirtualMachine.class.getSimpleName(), PermissionScope.RESOURCE, resId, "listVirtualMachines"); policyResp = _aclSrv.listIAMPolicies(null, "policy1", callerDomainId, 0L, 20L); assertTrue("No. of response items should be one", policyResp.getCount() == 1); diff --git a/services/iam/server/pom.xml b/services/iam/server/pom.xml index bed8811d16..77b2522843 100644 --- a/services/iam/server/pom.xml +++ b/services/iam/server/pom.xml @@ -31,6 +31,10 @@ commons-io commons-io + + net.sf.ehcache + ehcache-core + org.apache.cloudstack cloud-utils diff --git a/services/iam/server/resources/META-INF/cloudstack/core/spring-iam-server-context.xml b/services/iam/server/resources/META-INF/cloudstack/core/spring-iam-server-context.xml index c9f383f4f5..4994a3400b 100644 --- a/services/iam/server/resources/META-INF/cloudstack/core/spring-iam-server-context.xml +++ b/services/iam/server/resources/META-INF/cloudstack/core/spring-iam-server-context.xml @@ -35,6 +35,13 @@ - + + + + + + + + diff --git a/services/iam/server/src/org/apache/cloudstack/iam/api/IAMService.java b/services/iam/server/src/org/apache/cloudstack/iam/api/IAMService.java index 74a0885150..3a470ee677 100644 --- a/services/iam/server/src/org/apache/cloudstack/iam/api/IAMService.java +++ b/services/iam/server/src/org/apache/cloudstack/iam/api/IAMService.java @@ -72,7 +72,7 @@ IAMPolicy removeIAMPermissionFromIAMPolicy(long iamPolicyId, String entityType, List listPolicyPermissions(long policyId); - List listPolicyPermissionsByScope(long policyId, String action, String scope); + List listPolicyPermissionsByScope(long policyId, String action, String scope, String accessType); List listPolicyPermissionByActionAndEntity(long policyId, String action, String entityType); @@ -89,4 +89,11 @@ List listPolicyPermissionByAccessAndEntity(long policyId, S List listRecursiveIAMPoliciesByGroup(long groupId); + /* Interface used for cache IAM checkAccess result */ + void addToIAMCache(Object accessKey, Object allowDeny); + + Object getFromIAMCache(Object accessKey); + + void invalidateIAMCache(); + } diff --git a/services/iam/server/src/org/apache/cloudstack/iam/server/IAMServiceImpl.java b/services/iam/server/src/org/apache/cloudstack/iam/server/IAMServiceImpl.java index 097d84f958..796ae43624 100644 --- a/services/iam/server/src/org/apache/cloudstack/iam/server/IAMServiceImpl.java +++ b/services/iam/server/src/org/apache/cloudstack/iam/server/IAMServiceImpl.java @@ -18,9 +18,15 @@ 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 net.sf.ehcache.Cache; +import net.sf.ehcache.CacheManager; +import net.sf.ehcache.Element; import org.apache.log4j.Logger; @@ -38,6 +44,7 @@ import org.apache.cloudstack.iam.server.dao.IAMPolicyPermissionDao; import com.cloud.exception.InvalidParameterValueException; +import com.cloud.utils.NumbersUtil; import com.cloud.utils.Pair; import com.cloud.utils.component.Manager; import com.cloud.utils.component.ManagerBase; @@ -82,6 +89,62 @@ public class IAMServiceImpl extends ManagerBase implements IAMService, Manager { @Inject IAMPolicyPermissionDao _policyPermissionDao; + private Cache _iamCache; + + private void createIAMCache(final Map params) { + final String value = (String)params.get("cache.size"); + + if (value != null) { + final CacheManager cm = CacheManager.create(); + final int maxElements = NumbersUtil.parseInt(value, 0); + final int live = NumbersUtil.parseInt((String)params.get("cache.time.to.live"), 300); + final int idle = NumbersUtil.parseInt((String)params.get("cache.time.to.idle"), 300); + _iamCache = new Cache(getName(), maxElements, false, live == -1, live == -1 ? Integer.MAX_VALUE : live, idle); + cm.addCache(_iamCache); + s_logger.info("IAM Cache created: " + _iamCache.toString()); + } else { + _iamCache = null; + } + } + + @Override + public void addToIAMCache(Object accessKey, Object allowDeny) { + if (_iamCache != null) { + try { + s_logger.debug("Put IAM access check for " + accessKey + " in cache"); + _iamCache.put(new Element(accessKey, allowDeny)); + } catch (final Exception e) { + s_logger.debug("Can't put " + accessKey + " to IAM cache", e); + } + } + } + + @Override + public void invalidateIAMCache() { + //This may need to use event bus to publish to other MS, but event bus now is missing this functionality to handle PublishScope.GLOBAL + if (_iamCache != null) { + s_logger.debug("Invalidate IAM cache"); + _iamCache.removeAll(); + } + } + + @Override + public Object getFromIAMCache(Object accessKey) { + if (_iamCache != null) { + final Element element = _iamCache.get(accessKey); + return element == null ? null : element.getObjectValue(); + } + return null; + } + + @Override + public boolean configure(final String name, final Map params) throws ConfigurationException { + boolean result = super.configure(name, params); + // create IAM cache + createIAMCache(params); + return result; + } + @DB @Override public IAMGroup createIAMGroup(String iamGroupName, String description, String path) { @@ -111,7 +174,7 @@ public boolean deleteIAMGroup(final Long iamGroupId) { Transaction.execute(new TransactionCallbackNoReturn() { @Override public void doInTransactionWithoutResult(TransactionStatus status) { - // remove this group related entry in acl_group_role_map + // remove this group related entry in acl_group_policy_map List groupPolicyMap = _aclGroupPolicyMapDao.listByGroupId(grp.getId()); if (groupPolicyMap != null) { for (IAMGroupPolicyMapVO gr : groupPolicyMap) { @@ -132,6 +195,7 @@ public void doInTransactionWithoutResult(TransactionStatus status) { } }); + invalidateIAMCache(); return true; } @@ -147,6 +211,9 @@ public List listIAMGroups(long accountId) { List groupIds = _aclGroupAccountMapDao.customSearch(groupSc, null); + if (groupIds == null || groupIds.isEmpty()) { + return new ArrayList(); + } SearchBuilder sb = _aclGroupDao.createSearchBuilder(); sb.and("ids", sb.entity().getId(), Op.IN); SearchCriteria sc = sb.create(); @@ -181,6 +248,8 @@ public void doInTransactionWithoutResult(TransactionStatus status) { } } }); + + invalidateIAMCache(); return group; } @@ -207,6 +276,8 @@ public void doInTransactionWithoutResult(TransactionStatus status) { } } }); + + invalidateIAMCache(); return group; } @@ -342,7 +413,7 @@ public boolean deleteIAMPolicy(final long iamPolicyId) { Transaction.execute(new TransactionCallbackNoReturn() { @Override public void doInTransactionWithoutResult(TransactionStatus status) { - // remove this role related entry in acl_group_role_map + // remove this policy related entry in acl_group_policy_map List groupPolicyMap = _aclGroupPolicyMapDao.listByPolicyId(policy.getId()); if (groupPolicyMap != null) { for (IAMGroupPolicyMapVO gr : groupPolicyMap) { @@ -371,6 +442,8 @@ public void doInTransactionWithoutResult(TransactionStatus status) { } }); + invalidateIAMCache(); + return true; } @@ -533,6 +606,7 @@ public void doInTransactionWithoutResult(TransactionStatus status) { } }); + invalidateIAMCache(); return group; } @@ -565,6 +639,8 @@ public void doInTransactionWithoutResult(TransactionStatus status) { } } }); + + invalidateIAMCache(); return group; } @@ -591,6 +667,8 @@ public void doInTransactionWithoutResult(TransactionStatus status) { } } }); + + invalidateIAMCache(); } @Override @@ -614,6 +692,8 @@ public void doInTransactionWithoutResult(TransactionStatus status) { } } }); + + invalidateIAMCache(); } @DB @@ -628,13 +708,16 @@ public IAMPolicy addIAMPermissionToIAMPolicy(long iamPolicyId, String entityType } // add entry in acl_policy_permission table - IAMPolicyPermissionVO permit = _policyPermissionDao.findByPolicyAndEntity(iamPolicyId, entityType, scope, scopeId, action, perm); + IAMPolicyPermissionVO permit = _policyPermissionDao.findByPolicyAndEntity(iamPolicyId, entityType, scope, + scopeId, action, perm, accessType); if (permit == null) { // not there already permit = new IAMPolicyPermissionVO(iamPolicyId, action, entityType, accessType, scope, scopeId, perm, recursive); _policyPermissionDao.persist(permit); } + + invalidateIAMCache(); return policy; } @@ -650,11 +733,14 @@ public IAMPolicy removeIAMPermissionFromIAMPolicy(long iamPolicyId, String entit + "; failed to revoke permission from policy."); } // remove entry from acl_entity_permission table - IAMPolicyPermissionVO permit = _policyPermissionDao.findByPolicyAndEntity(iamPolicyId, entityType, scope, scopeId, action, Permission.Allow); + IAMPolicyPermissionVO permit = _policyPermissionDao.findByPolicyAndEntity(iamPolicyId, entityType, scope, + scopeId, action, Permission.Allow, null); if (permit != null) { // not removed yet _policyPermissionDao.remove(permit.getId()); } + + invalidateIAMCache(); return policy; } @@ -677,6 +763,8 @@ public void doInTransactionWithoutResult(TransactionStatus status) { } } }); + + invalidateIAMCache(); } @DB @@ -697,6 +785,7 @@ public IAMPolicy resetIAMPolicy(long iamPolicyId) { permissionSC.setParameters("policyId", iamPolicyId); _policyPermissionDao.expunge(permissionSC); + invalidateIAMCache(); return policy; } @@ -739,8 +828,8 @@ public List getGrantedEntities(long accountId, String action, String scope // for each policy, find granted permission within the given scope List entityIds = new ArrayList(); for (IAMPolicy policy : policies) { - List pp = _policyPermissionDao.listGrantedByActionAndScope(policy.getId(), action, - scope); + List pp = _policyPermissionDao.listByPolicyActionAndScope(policy.getId(), action, + scope, null); if (pp != null) { for (IAMPolicyPermissionVO p : pp) { if (p.getScopeId() != null) { @@ -762,9 +851,10 @@ public List listPolicyPermissions(long policyId) { @SuppressWarnings("unchecked") @Override - public List listPolicyPermissionsByScope(long policyId, String action, String scope) { + public List listPolicyPermissionsByScope(long policyId, String action, String scope, + String accessType) { @SuppressWarnings("rawtypes") - List pp = _policyPermissionDao.listGrantedByActionAndScope(policyId, action, scope); + List pp = _policyPermissionDao.listByPolicyActionAndScope(policyId, action, scope, accessType); return pp; } diff --git a/services/iam/server/src/org/apache/cloudstack/iam/server/dao/IAMPolicyPermissionDao.java b/services/iam/server/src/org/apache/cloudstack/iam/server/dao/IAMPolicyPermissionDao.java index cdcb02b1de..ebb4916470 100644 --- a/services/iam/server/src/org/apache/cloudstack/iam/server/dao/IAMPolicyPermissionDao.java +++ b/services/iam/server/src/org/apache/cloudstack/iam/server/dao/IAMPolicyPermissionDao.java @@ -27,9 +27,9 @@ public interface IAMPolicyPermissionDao extends GenericDao listByPolicy(long policyId); IAMPolicyPermissionVO findByPolicyAndEntity(long policyId, String entityType, String scope, Long scopeId, - String action, Permission perm); + String action, Permission perm, String accessType); - List listGrantedByActionAndScope(long policyId, String action, String scope); + List listByPolicyActionAndScope(long policyId, String action, String scope, String accessType); List listByPolicyActionAndEntity(long policyId, String action, String entityType); diff --git a/services/iam/server/src/org/apache/cloudstack/iam/server/dao/IAMPolicyPermissionDaoImpl.java b/services/iam/server/src/org/apache/cloudstack/iam/server/dao/IAMPolicyPermissionDaoImpl.java index 3f976cfefc..44b77d1163 100644 --- a/services/iam/server/src/org/apache/cloudstack/iam/server/dao/IAMPolicyPermissionDaoImpl.java +++ b/services/iam/server/src/org/apache/cloudstack/iam/server/dao/IAMPolicyPermissionDaoImpl.java @@ -33,7 +33,6 @@ public class IAMPolicyPermissionDaoImpl extends GenericDaoBase policyIdSearch; private SearchBuilder fullSearch; - private SearchBuilder actionScopeSearch; private SearchBuilder entitySearch; @Override @@ -54,13 +53,6 @@ public boolean configure(String name, Map params) throws Configu fullSearch.and("accessType", fullSearch.entity().getAccessType(), SearchCriteria.Op.EQ); fullSearch.done(); - actionScopeSearch = createSearchBuilder(); - actionScopeSearch.and("policyId", actionScopeSearch.entity().getAclPolicyId(), SearchCriteria.Op.EQ); - actionScopeSearch.and("scope", actionScopeSearch.entity().getScope(), SearchCriteria.Op.EQ); - actionScopeSearch.and("action", actionScopeSearch.entity().getAction(), SearchCriteria.Op.EQ); - actionScopeSearch.and("permission", actionScopeSearch.entity().getPermission(), SearchCriteria.Op.EQ); - actionScopeSearch.done(); - entitySearch = createSearchBuilder(); entitySearch.and("entityType", entitySearch.entity().getEntityType(), SearchCriteria.Op.EQ); entitySearch.and("scopeId", entitySearch.entity().getScopeId(), SearchCriteria.Op.EQ); @@ -78,7 +70,7 @@ public List listByPolicy(long policyId) { @Override public IAMPolicyPermissionVO findByPolicyAndEntity(long policyId, String entityType, String scope, Long scopeId, - String action, Permission perm) { + String action, Permission perm, String accessType) { SearchCriteria sc = fullSearch.create(); sc.setParameters("policyId", policyId); sc.setParameters("entityType", entityType); @@ -86,16 +78,25 @@ public IAMPolicyPermissionVO findByPolicyAndEntity(long policyId, String entityT sc.setParameters("scopeId", scopeId); sc.setParameters("action", action); sc.setParameters("permission", perm); + if (accessType != null) { + // accessType can be optional, used mainly in list apis with + // ListEntry and UseEntry distinction + sc.setParameters("accessType", accessType); + } return findOneBy(sc); } @Override - public List listGrantedByActionAndScope(long policyId, String action, String scope) { - SearchCriteria sc = actionScopeSearch.create(); + public List listByPolicyActionAndScope(long policyId, String action, String scope, String accessType) { + SearchCriteria sc = fullSearch.create(); sc.setParameters("policyId", policyId); sc.setParameters("action", action); sc.setParameters("scope", scope); sc.setParameters("permission", Permission.Allow); + if ( accessType != null ){ + // accessType can be optional, used mainly in list apis with ListEntry and UseEntry distinction + sc.setParameters("accessType", accessType); + } return listBy(sc); } @@ -120,7 +121,7 @@ public List listByPolicyAccessAndEntity(long policyId, St @Override public List listByEntity(String entityType, Long entityId) { - SearchCriteria sc = fullSearch.create(); + SearchCriteria sc = entitySearch.create(); sc.setParameters("entityType", entityType); sc.setParameters("scopeId", entityId); return listBy(sc); diff --git a/services/secondary-storage/server/src/org/apache/cloudstack/storage/resource/NfsSecondaryStorageResource.java b/services/secondary-storage/server/src/org/apache/cloudstack/storage/resource/NfsSecondaryStorageResource.java index 9782c2ec7c..6927f028cf 100755 --- a/services/secondary-storage/server/src/org/apache/cloudstack/storage/resource/NfsSecondaryStorageResource.java +++ b/services/secondary-storage/server/src/org/apache/cloudstack/storage/resource/NfsSecondaryStorageResource.java @@ -1188,6 +1188,8 @@ private void configCerts(KeystoreManager.Certificates certs) { } else { String prvKey = certs.getPrivKey(); String pubCert = certs.getPrivCert(); + String certChain = certs.getCertChain(); + String rootCACert = certs.getRootCACert(); try { File prvKeyFile = File.createTempFile("prvkey", null); @@ -1203,10 +1205,34 @@ private void configCerts(KeystoreManager.Certificates certs) { out.write(pubCert); out.close(); - configureSSL(prvkeyPath, pubCertFilePath, null); + String certChainFilePath = null, rootCACertFilePath = null; + File certChainFile = null, rootCACertFile = null; + if(certChain != null){ + certChainFile = File.createTempFile("certchain", null); + certChainFilePath = certChainFile.getAbsolutePath(); + out = new BufferedWriter(new FileWriter(certChainFile)); + out.write(certChain); + out.close(); + } + + if(rootCACert != null){ + rootCACertFile = File.createTempFile("rootcert", null); + rootCACertFilePath = rootCACertFile.getAbsolutePath(); + out = new BufferedWriter(new FileWriter(rootCACertFile)); + out.write(rootCACert); + out.close(); + } + + configureSSL(prvkeyPath, pubCertFilePath, certChainFilePath, rootCACertFilePath); prvKeyFile.delete(); pubCertFile.delete(); + if(certChainFile != null){ + certChainFile.delete(); + } + if(rootCACertFile != null){ + rootCACertFile.delete(); + } } catch (IOException e) { s_logger.debug("Failed to config ssl: " + e.toString()); @@ -1278,7 +1304,7 @@ protected Answer deleteSnapshot(final DeleteCommand cmd) { if (!snapshotDir.exists()) { details = "snapshot directory " + snapshotDir.getName() + " doesn't exist"; s_logger.debug(details); - return new Answer(cmd, false, details); + return new Answer(cmd, true, details); } // delete snapshot in the directory if exists String lPath = absoluteSnapshotPath + "/*" + snapshotName + "*"; @@ -2064,7 +2090,7 @@ private void configureSSL() { } } - private void configureSSL(String prvkeyPath, String prvCertPath, String certChainPath) { + private void configureSSL(String prvkeyPath, String prvCertPath, String certChainPath, String rootCACert) { if (!_inSystemVM) { return; } @@ -2076,6 +2102,9 @@ private void configureSSL(String prvkeyPath, String prvCertPath, String certChai if (certChainPath != null) { command.add("-t", certChainPath); } + if (rootCACert != null) { + command.add("-u", rootCACert); + } String result = command.execute(); if (result != null) { s_logger.warn("Unable to configure httpd to use ssl"); diff --git a/setup/bindir/cloud-setup-baremetal.in b/setup/bindir/cloud-setup-baremetal.in new file mode 100644 index 0000000000..367e38943e --- /dev/null +++ b/setup/bindir/cloud-setup-baremetal.in @@ -0,0 +1,232 @@ +#!/usr/bin/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. + +import sys, os +from subprocess import PIPE, Popen +import logging +import traceback +from os.path import exists, join +from signal import alarm, signal, SIGALRM, SIGKILL + +class CloudRuntimeException(Exception): + def __init__(self, errMsg): + self.errMsg = errMsg + def __str__(self): + return self.errMsg +def formatExceptionInfo(maxTBlevel=5): + cla, exc, trbk = sys.exc_info() + excTb = traceback.format_tb(trbk, maxTBlevel) + msg = str(exc) + "\n" + for tb in excTb: + msg += tb + return msg + +class bash: + def __init__(self, args, timeout=600): + self.args = args + logging.debug("execute:%s"%args) + self.timeout = timeout + self.process = None + self.success = False + self.run() + + def run(self): + class Alarm(Exception): + pass + def alarm_handler(signum, frame): + raise Alarm + + try: + self.process = Popen(self.args, shell=True, stdout=PIPE, stderr=PIPE) + if self.timeout != -1: + signal(SIGALRM, alarm_handler) + alarm(self.timeout) + + try: + self.stdout, self.stderr = self.process.communicate() + if self.timeout != -1: + alarm(0) + except Alarm: + os.kill(self.process.pid, SIGKILL) + raise CloudRuntimeException("Timeout during command execution") + + self.success = self.process.returncode == 0 + except: + raise CloudRuntimeException(formatExceptionInfo()) + +# if not self.success: +# raise CloudRuntimeException(self.getStderr()) + + def isSuccess(self): + return self.success + + def getStdout(self): + return self.stdout.strip("\n") + + def getLines(self): + return self.stdout.split("\n") + + def getStderr(self): + return self.stderr.strip("\n") + + +def initLoging(logFile=None): + try: + if logFile is None: + logging.basicConfig(level=logging.DEBUG) + else: + logging.basicConfig(filename=logFile, level=logging.DEBUG) + except: + logging.basicConfig(level=logging.DEBUG) + +def writeProgressBar(msg, result=None): + if msg is not None: + output = "%-80s"%msg + elif result is True: + output = "[ \033[92m%-2s\033[0m ]\n"%"OK" + elif result is False: + output = "[ \033[91m%-6s\033[0m ]\n"%"FAILED" + sys.stdout.write(output) + sys.stdout.flush() + +def printError(msg): + sys.stderr.write(msg) + sys.stderr.write("\n") + sys.stderr.flush() + +def printMsg(msg): + sys.stdout.write(msg+"\n") + sys.stdout.flush() + +def checkRpm(pkgName): + chkPkg = bash("rpm -q %s"%pkgName) + writeProgressBar("Checking %s"%pkgName, None) + if not chkPkg.isSuccess(): + writeProgressBar(None, False) + printError("%s is not found, please make sure it is installed. You may try 'yum install %s'\n"%(pkgName, pkgName)) + return False + else: + writeProgressBar(None, True) + return True + +def checkEnv(): + writeProgressBar("Checking is root") + ret = bash("whoami") + if ret.getStdout() != "root": + writeProgressBar(None, False) + printError("This script must run as root") + return False + else: + writeProgressBar(None, True) + + pkgList = ['tftp-server', 'syslinux', 'xinetd', 'chkconfig', 'dhcp'] + for pkg in pkgList: + if not checkRpm(pkg): + return False + return True + +def exitIfFail(ret): + if not ret: sys.exit(1) + +def bashWithResult(cmd): + writeProgressBar("Executing '%s'"%cmd) + ret = bash(cmd) + if not ret.isSuccess(): + writeProgressBar(None, False) + writeProgressBar(ret.getStderr() + '\n') + return False + else: + writeProgressBar(None, True) + return True + +def configurePxeStuff(): + stuff = ['tftp', 'xinetd', 'dhcpd'] + cmds = ['chkconfig --level 345 %s on' % i for i in stuff] + cmds.append('/etc/init.d/xinetd restart') + + for cmd in cmds: + if not bashWithResult(cmd): return False + + chkIptable = bash('chkconfig --list iptables') + if 'on' in chkIptable.getStdout(): + printMsg("Detected iptables is running, need to open tftp port 69") + if not bashWithResult('iptables -I INPUT 1 -p udp --dport 69 -j ACCEPT'): return False + if not bashWithResult('/etc/init.d/iptables save'): return False + + return True + +def getTftpRootDir(tftpRootDirList): + tftpRoot = bash("cat /etc/xinetd.d/tftp | grep server_args") + if not tftpRoot.isSuccess(): + printError("Cannot get tftp root directory from /etc/xinetd.d/tftp, here may be something wrong with your tftp-server, try reinstall it\n") + return False + tftpRootDir = tftpRoot.getStdout() + index = tftpRootDir.find("/") + if index == -1: + printError("Wrong server_arg in /etc/xinetd.d/tftp (%s)"%tftpRootDir) + return False + tftpRootDir = tftpRootDir[index:] + tftpRootDirList.append(tftpRootDir) + return True + +def preparePING(tftpRootDir): + pingFiles = ['boot.msg', 'initrd.gz', 'kernel', 'pxelinux.0'] + pingDir = "/usr/share/PING" + + for f in pingFiles: + path = join(pingDir, f) + if not exists(path): + printError("Cannot find %s, please make sure PING-3.01 is installed"%path) + return False + if not bashWithResult("cp -f %s %s"%(path, tftpRootDir)): return False + + if not bashWithResult("mkdir -p %s/pxelinux.cfg"%tftpRootDir): return False + + return True + +def prepareSyslinux(tftpRootDir): + pkg = bash('rpm -ql syslinux | grep "/pxelinux.0$"') + if not pkg.isSuccess(): + printError('cannot find pxelinux.0 on system. is syslinux installed?') + return False + + pkg = pkg.getStdout() + cp = "cp -f %s %s" % (pkg, tftpRootDir) + if not bashWithResult(cp): + return False + + return True + + + +if __name__ == "__main__": + initLoging("/tmp/cloud-setup-baremetal.log") + tftpRootDirList = [] + + exitIfFail(checkEnv()) + exitIfFail(configurePxeStuff()) + exitIfFail(getTftpRootDir(tftpRootDirList)) + + tftpRootDir = tftpRootDirList[0].strip() + #exitIfFail(preparePING(tftpRootDir)) + exitIfFail(prepareSyslinux(tftpRootDir)) + printMsg("") + printMsg("Setup BareMetal PXE server successfully") + printMsg("TFTP root directory is: %s\n"%tftpRootDir) + sys.exit(0) + diff --git a/setup/bindir/cloud-sysvmadm.in b/setup/bindir/cloud-sysvmadm.in index e2a626ef92..4c67c31085 100755 --- a/setup/bindir/cloud-sysvmadm.in +++ b/setup/bindir/cloud-sysvmadm.in @@ -7,9 +7,9 @@ # 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 @@ -75,7 +75,7 @@ do esac done - + stop_start_system() { @@ -86,46 +86,46 @@ length_console=(${#console[@]}) echo -e "\nStopping and starting $length_secondary secondary storage vm(s)$inzone..." -echo -e "Stopping and starting $length_secondary secondary storage vm(s)$inzone..." >>$LOGFILE +echo -e "[$(date "+%Y.%m.%d-%H.%M.%S")] Stopping and starting $length_secondary secondary storage vm(s)$inzone..." >>$LOGFILE for d in "${secondary[@]}"; do - echo "INFO: Stopping secondary storage vm with id $d" >>$LOGFILE + echo "[$(date "+%Y.%m.%d-%H.%M.%S")] INFO: Stopping secondary storage vm with id $d" >>$LOGFILE jobresult=$(send_request stopSystemVm $d) if [ "$jobresult" != "1" ]; then echo -e "ERROR: Failed to stop secondary storage vm with id $d \n" - echo "ERROR: Failed to stop secondary storage vm with id $d" >>$LOGFILE - else - echo "INFO: Starting secondary storage vm with id $d" >>$LOGFILE + echo "[$(date "+%Y.%m.%d-%H.%M.%S")] ERROR: Failed to stop secondary storage vm with id $d" >>$LOGFILE + else + echo "[$(date "+%Y.%m.%d-%H.%M.%S")] INFO: Starting secondary storage vm with id $d" >>$LOGFILE jobresult=$(send_request startSystemVm $d SSVM) if [ "$jobresult" != "1" ]; then - echo "ERROR: Failed to start secondary storage vm with id $d" >>$LOGFILE - echo "ERROR: Failed to start secondary storage vm with id $d" >>$LOGFILE + echo "[$(date "+%Y.%m.%d-%H.%M.%S")] ERROR: Failed to start secondary storage vm with id $d" >>$LOGFILE + echo "[$(date "+%Y.%m.%d-%H.%M.%S")] ERROR: Failed to start secondary storage vm with id $d" >>$LOGFILE fi fi done if [ "$length_secondary" == "0" ];then echo -e "No running secondary storage vms found \n" -else +else echo -e "Done stopping and starting secondary storage vm(s)$inzone" - echo -e "Done stopping and starting secondary storage vm(s)$inzone." >>$LOGFILE + echo -e "[$(date "+%Y.%m.%d-%H.%M.%S")] Done stopping and starting secondary storage vm(s)$inzone." >>$LOGFILE fi echo -e "\nStopping and starting $length_console console proxy vm(s)$inzone..." -echo -e "Stopping and starting $length_console console proxy vm(s)$inzone..." >>$LOGFILE +echo -e "[$(date "+%Y.%m.%d-%H.%M.%S")] Stopping and starting $length_console console proxy vm(s)$inzone..." >>$LOGFILE for d in "${console[@]}"; do - echo "INFO: Stopping console proxy with id $d" >>$LOGFILE + echo "[$(date "+%Y.%m.%d-%H.%M.%S")] INFO: Stopping console proxy with id $d" >>$LOGFILE jobresult=$(send_request stopSystemVm $d) if [ "$jobresult" != "1" ]; then echo -e "ERROR: Failed to stop console proxy vm with id $d \n" - echo "ERROR: Failed to stop console proxy vm with id $d" >>$LOGFILE - else - echo "INFO: Starting console proxy vm with id $d" >>$LOGFILE + echo "[$(date "+%Y.%m.%d-%H.%M.%S")] ERROR: Failed to stop console proxy vm with id $d" >>$LOGFILE + else + echo "[$(date "+%Y.%m.%d-%H.%M.%S")] INFO: Starting console proxy vm with id $d" >>$LOGFILE jobresult=$(send_request startSystemVm $d consoleProxy) if [ "$jobresult" != "1" ]; then echo -e "ERROR: Failed to start console proxy vm with id $d \n" - echo "ERROR: Failed to start console proxy vm with id $d" >>$LOGFILE + echo "[$(date "+%Y.%m.%d-%H.%M.%S")] ERROR: Failed to start console proxy vm with id $d" >>$LOGFILE fi fi done @@ -134,33 +134,33 @@ if [ "$length_console" == "0" ];then echo -e "No running console proxy vms found \n" else echo "Done stopping and starting console proxy vm(s) $inzone." - echo "Done stopping and starting console proxy vm(s) $inzone." >>$LOGFILE + echo "[$(date "+%Y.%m.%d-%H.%M.%S")] Done stopping and starting console proxy vm(s) $inzone." >>$LOGFILE fi } stop_start_router() { router=(`mysql -h $db --user=$user --password=$password --skip-column-names -U cloud -e "select id from vm_instance where state=\"Running\" and type=\"DomainRouter\"$zone"`) length_router=(${#router[@]}) - + echo -e "\nStopping and starting $length_router running routing vm(s)$inzone... " - echo -e "Stopping and starting $length_router running routing vm(s)$inzone... " >>$LOGFILE - + echo -e "[$(date "+%Y.%m.%d-%H.%M.%S")] Stopping and starting $length_router running routing vm(s)$inzone... " >>$LOGFILE + #Spawn reboot router in parallel - run commands in chunks - number of threads is configurable pids=() for d in "${router[@]}"; do - + reboot_router $d & pids=( "${pids[@]}" $! ) - + length_pids=(${#pids[@]}) unfinishedPids=(${#pids[@]}) - + if [ $maxthreads -gt $length_router ]; then maxthreads=$length_router fi - + if [ $length_pids -ge $maxthreads ]; then while [ $unfinishedPids -gt 0 ]; do sleep 10 @@ -170,33 +170,33 @@ stop_start_router() { count=`expr $count + 1` fi done - + if [ $count -eq $unfinishedPids ]; then unfinishedPids=0 fi - + done - + #remove all elements from pids if [ $unfinishedPids -eq 0 ]; then pids=() length_pids=(${#pids[@]}) fi - + fi - + done - + if [ "$length_router" == "0" ];then - echo -e "No running router vms found \n" >>$LOGFILE - else + echo -e "[$(date "+%Y.%m.%d-%H.%M.%S")] No running router vms found \n" >>$LOGFILE + else while [ $unfinishedPids -gt 0 ]; do sleep 10 done - + echo -e "Done restarting router(s)$inzone. \n" - echo -e "Done restarting router(s)$inzone. \n" >>$LOGFILE - + echo -e "[$(date "+%Y.%m.%d-%H.%M.%S")] Done restarting router(s)$inzone. \n" >>$LOGFILE + fi } @@ -212,56 +212,60 @@ send_request(){ return fi jobresult=$(query_async_job_result $jobid) + if [ "$jobresult" != "1" ]; then + echo -e "ERROR: Failed to $1 id=$2; jobId is $jobid \n" + echo "[$(date "+%Y.%m.%d-%H.%M.%S")] ERROR: Failed to $1 id=$2; jobId is $jobid" >>$LOGFILE + fi echo $jobresult } reboot_router(){ - echo "INFO: Restarting router with id $1" >>$LOGFILE + echo "[$(date "+%Y.%m.%d-%H.%M.%S")] INFO: Restarting router with id $1" >>$LOGFILE jobid=`curl -sS "http://$ms:8096/?command=rebootRouter&id=$1&response=json" | sed 's/\"//g' | sed 's/ //g' | sed 's/{//g' | sed 's/}//g' | awk -F: {'print $3'}` if [ "$jobid" == "" ]; then - echo "ERROR: Failed to restart domainRouter with id $1" >>$LOGFILE + echo "[$(date "+%Y.%m.%d-%H.%M.%S")] ERROR: Failed to restart domainRouter with id $1; unable to submit the job" >>$LOGFILE echo 2 return fi - + jobresult=$(query_async_job_result $jobid) - + if [ "$jobresult" != "1" ]; then echo -e "ERROR: Failed to restart domainRouter with id $1 \n" - echo "ERROR: Failed to restart domainRouter with id $1" >>$LOGFILE + echo "[$(date "+%Y.%m.%d-%H.%M.%S")] ERROR: Failed to restart domainRouter with id $1; jobId $jobid" >>$LOGFILE exit 0 else - echo "INFO: Successfully restarted domainRouter with id $1" >>$LOGFILE + echo "[$(date "+%Y.%m.%d-%H.%M.%S")] INFO: Successfully restarted domainRouter with id $1; jobId $jobid" >>$LOGFILE exit 0 fi - + } restart_networks(){ - networks=(`mysql -h $db --user=$user --password=$password --skip-column-names -U cloud -e "select n.id + networks=(`mysql -h $db --user=$user --password=$password --skip-column-names -U cloud -e "select n.id from networks n, network_offerings no where n.network_offering_id = no.id and no.system_only = 0 and n.removed is null$zone"`) length_networks=(${#networks[@]}) - + echo -e "\nRestarting $length_networks networks$inzone... " - echo -e "Restarting $length_networks networks$inzone... " >>$LOGFILE - + echo -e "[$(date "+%Y.%m.%d-%H.%M.%S")] Restarting $length_networks networks$inzone... " >>$LOGFILE + #Spawn restart network in parallel - run commands in chunks - number of threads is configurable pids=() for d in "${networks[@]}"; do - + restart_network $d & pids=( "${pids[@]}" $! ) - + length_pids=(${#pids[@]}) unfinishedPids=(${#pids[@]}) - + if [ $maxthreads -gt $length_networks ]; then maxthreads=$length_networks fi - + if [ $length_pids -ge $maxthreads ]; then while [ $unfinishedPids -gt 0 ]; do sleep 10 @@ -271,74 +275,74 @@ restart_networks(){ count=`expr $count + 1` fi done - + if [ $count -eq $unfinishedPids ]; then unfinishedPids=0 fi - + done - + #remove all elements from pids if [ $unfinishedPids -eq 0 ]; then pids=() length_pids=(${#pids[@]}) fi - + fi - + done - + if [ "$length_networks" == "0" ];then - echo -e "No networks found \n" >>$LOGFILE - else + echo -e "[$(date "+%Y.%m.%d-%H.%M.%S")] No networks found \n" >>$LOGFILE + else while [ $unfinishedPids -gt 0 ]; do sleep 10 done - + echo -e "Done restarting networks$inzone. \n" - echo -e "Done restarting networks$inzone. \n" >>$LOGFILE - + echo -e "[$(date "+%Y.%m.%d-%H.%M.%S")] Done restarting networks$inzone. \n" >>$LOGFILE + fi } restart_network(){ jobid=`curl -sS "http://$ms:8096/?command=restartNetwork&id=$1&response=json" | sed 's/\"//g' | sed 's/ //g' | sed 's/{//g' | sed 's/}//g' | awk -F: {'print $3'}` if [ "$jobid" == "" ]; then - echo "ERROR: Failed to restart network with id $1" >>$LOGFILE + echo "[$(date "+%Y.%m.%d-%H.%M.%S")] ERROR: Failed to restart network with id $1; unable to submit the job" >>$LOGFILE echo 2 return fi - + jobresult=$(query_async_job_result $jobid) - + if [ "$jobresult" != "1" ]; then - echo "ERROR: Failed to restart network with id $1" >>$LOGFILE + echo "[$(date "+%Y.%m.%d-%H.%M.%S")] ERROR: Failed to restart network with id $1; jobId $jobid" >>$LOGFILE else - echo "INFO: Successfully restarted network with id $1" >>$LOGFILE + echo "[$(date "+%Y.%m.%d-%H.%M.%S")] INFO: Successfully restarted network with id $1; jobId $jobid" >>$LOGFILE fi - + } restart_vpc(){ echo -e "INFO: Restarting vpc with id $1" - echo "INFO: Restarting vpc with id $1" >>$LOGFILE + echo "[$(date "+%Y.%m.%d-%H.%M.%S")] INFO: Restarting vpc with id $1" >>$LOGFILE jobid=`curl -sS "http://$ms:8096/?command=restartVPC&id=$1&response=json" | sed 's/\"//g' | sed 's/ //g' | sed 's/{//g' | sed 's/}//g' | awk -F: {'print $3'}` if [ "$jobid" == "" ]; then - echo "ERROR: Failed to restart vpc with id $1" >>$LOGFILE + echo "[$(date "+%Y.%m.%d-%H.%M.%S")] ERROR: Failed to restart vpc with id $1; unable to submit the job" >>$LOGFILE echo 2 return fi - + jobresult=$(query_async_job_result $jobid) - + if [ "$jobresult" != "1" ]; then echo -e "ERROR: Failed to restart vpc with id $1 \n" - echo "ERROR: Failed to restart vpc with id $1" >>$LOGFILE + echo "[$(date "+%Y.%m.%d-%H.%M.%S")] ERROR: Failed to restart vpc with id $1; jobId $jobid" >>$LOGFILE else echo -e "INFO: Successfully restarted vpc with id $1 \n" - echo "INFO: Successfully restarted vpc with id $1" >>$LOGFILE + echo "[$(date "+%Y.%m.%d-%H.%M.%S")] INFO: Successfully restarted vpc with id $1; jobId $jobid" >>$LOGFILE fi } @@ -346,26 +350,26 @@ restart_vpc(){ restart_vpcs(){ vpcs=(`mysql -h $db --user=$user --password=$password --skip-column-names -U cloud -e "select id from vpc WHERE removed is null$zone"`) length_vpcs=(${#vpcs[@]}) - + echo -e "\nRestarting $length_vpcs vpcs... " - echo -e "Restarting $length_vpcs vpcs... " >>$LOGFILE - + echo -e "[$(date "+%Y.%m.%d-%H.%M.%S")] Restarting $length_vpcs vpcs... " >>$LOGFILE + #Spawn restart vpcs in parallel - run commands in chunks - number of threads is configurable pids=() for d in "${vpcs[@]}"; do - + restart_vpc $d & pids=( "${pids[@]}" $! ) - + length_pids=(${#pids[@]}) unfinishedPids=(${#pids[@]}) - + if [ $maxthreads -gt $length_vpcs ]; then maxthreads=$length_vpcs fi - + if [ $length_pids -ge $maxthreads ]; then while [ $unfinishedPids -gt 0 ]; do sleep 10 @@ -375,34 +379,34 @@ restart_vpcs(){ count=`expr $count + 1` fi done - + if [ $count -eq $unfinishedPids ]; then unfinishedPids=0 fi - + done - + #remove all elements from pids if [ $unfinishedPids -eq 0 ]; then pids=() length_pids=(${#pids[@]}) fi - + fi - + done - + if [ "$length_vpcs" == "0" ];then - echo -e "No vpcs found \n" >>$LOGFILE - else + echo -e "[$(date "+%Y.%m.%d-%H.%M.%S")] No vpcs found \n" >>$LOGFILE + else while [ $unfinishedPids -gt 0 ]; do sleep 10 done - + echo -e "Done restarting vpcs$inzone. \n" - echo -e "Done restarting vpcs$inzone. \n" >>$LOGFILE - + echo -e "[$(date "+%Y.%m.%d-%H.%M.%S")] Done restarting vpcs$inzone. \n" >>$LOGFILE + fi } diff --git a/setup/db/create-schema-simulator.sql b/setup/db/create-schema-simulator.sql index facfefc5e7..d33596ebdb 100644 --- a/setup/db/create-schema-simulator.sql +++ b/setup/db/create-schema-simulator.sql @@ -106,7 +106,10 @@ CREATE TABLE `simulator`.`mockconfiguration` ( `cluster_id` bigint unsigned, `host_id` bigint unsigned, `name` varchar(255), - `values` varchar(4095), + `values` varchar(4096), + `count` int, + `json_response` varchar(4096), + `removed` datetime, PRIMARY KEY (`id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8; diff --git a/setup/db/db/schema-420to421.sql b/setup/db/db/schema-420to421.sql index 42e9c1e1ec..78687f22fe 100644 --- a/setup/db/db/schema-420to421.sql +++ b/setup/db/db/schema-420to421.sql @@ -24,7 +24,8 @@ INSERT IGNORE INTO `cloud`.`configuration` VALUES ('Advanced', 'DEFAULT', 'manag 'The maximum size limit for S3 single part upload API(in GB). If it is set to 0, then it means always use multi-part upload to upload object to S3. If it is set to -1, then it means always use single-part upload to upload object to S3.'); INSERT IGNORE INTO `cloud`.`configuration` VALUES ("Storage", 'DEFAULT', 'management-server', "enable.ha.storage.migration", "true", "Enable/disable storage migration across primary storage during HA"); - +UPDATE `cloud`.`configuration` SET description="Specify whether or not to reserve CPU based on CPU overprovisioning factor" where name="vmware.reserve.cpu"; +UPDATE `cloud`.`configuration` SET description="Specify whether or not to reserve memory based on memory overprovisioning factor" where name="vmware.reserve.mem"; -- Remove Windows Server 8 from guest_os_type dropdown to use Windows Server 2012 DELETE FROM `cloud`.`guest_os_hypervisor` where guest_os_id=168; DELETE FROM `cloud`.`guest_os` where id=168; diff --git a/setup/db/db/schema-430to440-cleanup.sql b/setup/db/db/schema-430to440-cleanup.sql index 30df9782f6..8b1eec406c 100644 --- a/setup/db/db/schema-430to440-cleanup.sql +++ b/setup/db/db/schema-430to440-cleanup.sql @@ -19,4 +19,4 @@ -- Schema cleanup from 4.3.0 to 4.4.0; --; - +ALTER TABLE `cloud`.`network_acl_item` DROP COLUMN `cidr`; diff --git a/setup/db/db/schema-430to440.sql b/setup/db/db/schema-430to440.sql index 5c5511ac5f..89db04a2e9 100644 --- a/setup/db/db/schema-430to440.sql +++ b/setup/db/db/schema-430to440.sql @@ -128,9 +128,9 @@ CREATE VIEW `cloud`.`volume_view` AS volumes.attached, volumes.removed, volumes.pod_id, - volumes.display_volume, + volumes.display_volume, volumes.format, - volumes.path, + volumes.path, volumes.chain_info, account.id account_id, account.uuid account_uuid, @@ -146,7 +146,7 @@ CREATE VIEW `cloud`.`volume_view` AS data_center.id data_center_id, data_center.uuid data_center_uuid, data_center.name data_center_name, - data_center.networktype data_center_type, + data_center.networktype data_center_type, vm_instance.id vm_id, vm_instance.uuid vm_uuid, vm_instance.name vm_name, @@ -177,6 +177,12 @@ CREATE VIEW `cloud`.`volume_view` AS vm_template.uuid template_uuid, vm_template.extractable, vm_template.type template_type, + vm_template.name template_name, + vm_template.display_text template_display_text, + iso.id iso_id, + iso.uuid iso_uuid, + iso.name iso_name, + iso.display_text iso_display_text, resource_tags.id tag_id, resource_tags.uuid tag_uuid, resource_tags.key tag_key, @@ -214,7 +220,9 @@ CREATE VIEW `cloud`.`volume_view` AS left join `cloud`.`cluster` ON storage_pool.cluster_id = cluster.id left join - `cloud`.`vm_template` ON volumes.template_id = vm_template.id OR volumes.iso_id = vm_template.id + `cloud`.`vm_template` ON volumes.template_id = vm_template.id + left join + `cloud`.`vm_template` iso ON iso.id = volumes.iso_id left join `cloud`.`resource_tags` ON resource_tags.resource_id = volumes.id and resource_tags.resource_type = 'Volume' @@ -453,20 +461,20 @@ CREATE VIEW `cloud`.`user_vm_view` AS left join `cloud`.`user_vm_details` `custom_ram_size` ON (((`custom_ram_size`.`vm_id` = `cloud`.`vm_instance`.`id`) and (`custom_ram_size`.`name` = 'memory'))); --- ACL DB schema +-- ACL DB schema CREATE TABLE `cloud`.`iam_group` ( `id` bigint unsigned NOT NULL UNIQUE auto_increment, `name` varchar(255) NOT NULL, `description` varchar(255) default NULL, `uuid` varchar(40), - `path` varchar(255) NOT NULL, + `path` varchar(255) NOT NULL, `account_id` bigint unsigned NOT NULL, `view` varchar(40) default 'User' COMMENT 'response review this group account should see for result', `removed` datetime COMMENT 'date the group was removed', `created` datetime COMMENT 'date the group was created', PRIMARY KEY (`id`), INDEX `i_iam_group__removed`(`removed`), - CONSTRAINT `uc_iam_group__uuid` UNIQUE (`uuid`) + CONSTRAINT `uc_iam_group__uuid` UNIQUE (`uuid`) ) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8; CREATE TABLE `cloud`.`iam_group_account_map` ( @@ -474,11 +482,11 @@ CREATE TABLE `cloud`.`iam_group_account_map` ( `group_id` bigint unsigned NOT NULL, `account_id` bigint unsigned NOT NULL, `removed` datetime COMMENT 'date the account was removed from the group', - `created` datetime COMMENT 'date the account was assigned to the group', + `created` datetime COMMENT 'date the account was assigned to the group', PRIMARY KEY (`id`), CONSTRAINT `fk_iam_group_vm_map__group_id` FOREIGN KEY(`group_id`) REFERENCES `iam_group` (`id`) ON DELETE CASCADE, CONSTRAINT `fk_iam_group_vm_map__account_id` FOREIGN KEY(`account_id`) REFERENCES `account` (`id`) ON DELETE CASCADE -) ENGINE=InnoDB DEFAULT CHARSET=utf8; +) ENGINE=InnoDB DEFAULT CHARSET=utf8; CREATE TABLE `cloud`.`iam_policy` ( @@ -487,7 +495,7 @@ CREATE TABLE `cloud`.`iam_policy` ( `description` varchar(255) DEFAULT NULL, `uuid` varchar(40) DEFAULT NULL, `path` varchar(255) NOT NULL, - `account_id` bigint unsigned NOT NULL, + `account_id` bigint unsigned NOT NULL, `removed` datetime DEFAULT NULL COMMENT 'date the role was removed', `created` datetime DEFAULT NULL COMMENT 'date the role was created', `policy_type` varchar(64) DEFAULT 'Static' COMMENT 'Static or Dynamic', @@ -658,13 +666,27 @@ ALTER TABLE `cloud`.`s2s_vpn_gateway` ADD COLUMN `display` tinyint(1) NOT NULL D INSERT IGNORE INTO `cloud`.`guest_os` (id, uuid, category_id, display_name) VALUES (225, UUID(), 9, 'FreeBSD 10 (32-bit)'); INSERT IGNORE INTO `cloud`.`guest_os` (id, uuid, category_id, display_name) VALUES (226, UUID(), 9, 'FreeBSD 10 (64-bit)'); +INSERT IGNORE INTO `cloud`.`guest_os` (id, uuid, category_id, display_name) VALUES (227, UUID(), 1, 'CentOS 6.5 (32-bit)'); +INSERT IGNORE INTO `cloud`.`guest_os` (id, uuid, category_id, display_name) VALUES (228, UUID(), 1, 'CentOS 6.5 (64-bit)'); +INSERT IGNORE INTO `cloud`.`guest_os` (id, uuid, category_id, display_name) VALUES (229, UUID(), 6, 'Windows 8.1 (64-bit)'); +INSERT IGNORE INTO `cloud`.`guest_os` (id, uuid, category_id, display_name) VALUES (230, UUID(), 6, 'Windows 8.1 (32-bit)'); + +INSERT IGNORE INTO `cloud`.`guest_os_hypervisor` (hypervisor_type, guest_os_name, guest_os_id) VALUES ("XenServer", 'Windows 8.1 (64-bit)', 229); +INSERT IGNORE INTO `cloud`.`guest_os_hypervisor` (hypervisor_type, guest_os_name, guest_os_id) VALUES ("VmWare", 'Windows 8.1 (64-bit)', 229); +INSERT IGNORE INTO `cloud`.`guest_os_hypervisor` (hypervisor_type, guest_os_name, guest_os_id) VALUES ("XenServer", 'Windows 8.1 (32-bit)', 230); +INSERT IGNORE INTO `cloud`.`guest_os_hypervisor` (hypervisor_type, guest_os_name, guest_os_id) VALUES ("VmWare", 'Windows 8.1 (32-bit)', 230); +INSERT IGNORE INTO `cloud`.`guest_os_hypervisor` (hypervisor_type, guest_os_name, guest_os_id) VALUES ("XenServer", 'CentOS 6.5 (32-bit)', 227); +INSERT IGNORE INTO `cloud`.`guest_os_hypervisor` (hypervisor_type, guest_os_name, guest_os_id) VALUES ("VmWare", 'CentOS 6.5 (32-bit)', 227); +INSERT IGNORE INTO `cloud`.`guest_os_hypervisor` (hypervisor_type, guest_os_name, guest_os_id) VALUES ("VmWare", 'CentOS 6.5 (64-bit)', 228); +INSERT IGNORE INTO `cloud`.`guest_os_hypervisor` (hypervisor_type, guest_os_name, guest_os_id) VALUES ("XenServer", 'CentOS 6.5 (64-bit)', 228); + CREATE TABLE `cloud`.`op_router_monitoring_services` ( `vm_id` bigint unsigned UNIQUE NOT NULL COMMENT 'Primary Key', `router_name` varchar(255) NOT NULL COMMENT 'Name of the Virtual Router', `last_alert_timestamp` varchar(255) NOT NULL COMMENT 'Timestamp of the last alert received from Virtual Router', PRIMARY KEY (`vm_id`), CONSTRAINT `fk_virtual_router__id` FOREIGN KEY `fk_virtual_router__id` (`vm_id`) REFERENCES `vm_instance`(`id`) ON DELETE CASCADE -) ENGINE = InnoDB DEFAULT CHARSET=utf8 +) ENGINE = InnoDB DEFAULT CHARSET=utf8; ALTER TABLE `cloud`.`event` ADD COLUMN `display` tinyint(1) NOT NULL DEFAULT '1' COMMENT 'True if the detail can be displayed to the end user'; @@ -724,7 +746,13 @@ CREATE TABLE `cloud`.`vgpu_types` ( `id` bigint(20) unsigned NOT NULL AUTO_INCREMENT, `gpu_group_id` bigint(20) unsigned NOT NULL, `vgpu_type` varchar(40) NOT NULL COMMENT 'vgpu type supported by this gpu group', - `remaining_vm_capacity` bigint(20) unsigned DEFAULT NULL COMMENT 'remaining vgpu can be created with this vgpu_type on the given gpu group', + `video_ram` bigint(20) unsigned DEFAULT NULL COMMENT 'video RAM for this vgpu type', + `max_heads` bigint(20) unsigned DEFAULT NULL COMMENT 'maximum displays per user', + `max_resolution_x` bigint(20) unsigned DEFAULT NULL COMMENT 'maximum X resolution per display', + `max_resolution_y` bigint(20) unsigned DEFAULT NULL COMMENT 'maximum Y resolution per display', + `max_vgpu_per_pgpu` bigint(20) unsigned DEFAULT NULL COMMENT 'max number of vgpus per physical gpu (pgpu)', + `remaining_capacity` bigint(20) unsigned DEFAULT NULL COMMENT 'remaining vgpu can be created with this vgpu_type on the given gpu group', + `max_capacity` bigint(20) unsigned DEFAULT NULL COMMENT 'maximum vgpu can be created with this vgpu_type on the given gpu group', PRIMARY KEY (`id`), CONSTRAINT `fk_vgpu_types__gpu_group_id` FOREIGN KEY (`gpu_group_id`) REFERENCES `host_gpu_groups` (`id`) ON DELETE CASCADE ) ENGINE=InnoDB CHARSET=utf8; @@ -734,14 +762,916 @@ ALTER TABLE `cloud`.`guest_os_hypervisor` ADD COLUMN `uuid` varchar(40) COMMENT ALTER TABLE `cloud`.`guest_os_hypervisor` ADD CONSTRAINT `uc_guest_os_hypervisor__uuid` UNIQUE (`uuid`); ALTER TABLE `cloud`.`guest_os_hypervisor` ADD COLUMN `created` datetime COMMENT 'Time when mapping was created'; ALTER TABLE `cloud`.`guest_os_hypervisor` ADD COLUMN `removed` datetime COMMENT 'Time when mapping was removed if deleted, else NULL'; +ALTER TABLE `cloud`.`guest_os_hypervisor` ADD COLUMN `is_user_defined` INT(1) UNSIGNED DEFAULT 0 COMMENT 'True if this guest OS mapping was added by admin'; UPDATE `cloud`.`guest_os_hypervisor` SET `uuid` = UUID(); UPDATE `cloud`.`guest_os_hypervisor` SET `created` = now(); ALTER TABLE `cloud`.`guest_os` ADD COLUMN `created` datetime COMMENT 'Time when Guest OS was created in system'; ALTER TABLE `cloud`.`guest_os` ADD COLUMN `removed` datetime COMMENT 'Time when Guest OS was removed if deleted, else NULL'; UPDATE `cloud`.`guest_os` SET `created` = now(); +ALTER TABLE `cloud`.`guest_os` ADD COLUMN `is_user_defined` INT(1) UNSIGNED DEFAULT 0 COMMENT 'True if this guest OS type was added by admin'; ALTER TABLE `cloud`.`vm_reservation` ADD COLUMN `deployment_planner` varchar(40) DEFAULT NULL COMMENT 'Preferred deployment planner for the vm'; ALTER TABLE `cloud`.`vpc_offerings` ADD COLUMN supports_distributed_router boolean default false; ALTER TABLE `cloud`.`vpc` ADD COLUMN uses_distributed_router boolean default false; - INSERT INTO `cloud`.`storage_pool_details` (pool_id,name,value,display) SELECT storage_pool.id,data_center_details.name,data_center_details.value,data_center_details.display FROM `cloud`.`storage_pool` JOIN `cloud`.`data_center_details` ON data_center_details.dc_id=storage_pool.data_center_id WHERE data_center_details.name = "storage.overprovisioning.factor"; DELETE FROM `cloud`.`data_center_details` WHERE name="storage.overprovisioning.factor"; +ALTER TABLE `cloud`.`vpc_offerings` ADD COLUMN supports_region_level_vpc boolean default false; +ALTER TABLE `cloud`.`network_offerings` ADD COLUMN supports_streched_l2 boolean default false; +ALTER TABLE `cloud`.`networks` ADD COLUMN streched_l2 boolean default false; +ALTER TABLE `cloud`.`vpc` ADD COLUMN region_level_vpc boolean default false; +ALTER TABLE `cloud`.`load_balancer_vm_map` ADD COLUMN instance_ip VARCHAR(40); +ALTER TABLE `cloud`.`load_balancer_vm_map` DROP KEY `load_balancer_id`, ADD UNIQUE KEY load_balancer_id (`load_balancer_id`, `instance_id`, `instance_ip`); +INSERT IGNORE INTO `cloud`.`guest_os_hypervisor` (uuid,hypervisor_type, hypervisor_version, guest_os_name, guest_os_id, created, is_user_defined) VALUES (UUID(),'Xenserver', 'XCP 1.0', 'CentOS 4.5 (32-bit)', 1, now(), 0); +INSERT IGNORE INTO `cloud`.`guest_os_hypervisor` (uuid,hypervisor_type, hypervisor_version, guest_os_name, guest_os_id, created, is_user_defined) VALUES (UUID(),'Xenserver', 'XCP 1.0', 'CentOS 4.6 (32-bit)', 2, now(), 0); +INSERT IGNORE INTO `cloud`.`guest_os_hypervisor` (uuid,hypervisor_type, hypervisor_version, guest_os_name, guest_os_id, created, is_user_defined) VALUES (UUID(),'Xenserver', 'XCP 1.0', 'CentOS 4.7 (32-bit)', 3, now(), 0); +INSERT IGNORE INTO `cloud`.`guest_os_hypervisor` (uuid,hypervisor_type, hypervisor_version, guest_os_name, guest_os_id, created, is_user_defined) VALUES (UUID(),'Xenserver', 'XCP 1.0', 'CentOS 4.8 (32-bit)', 4, now(), 0); +INSERT IGNORE INTO `cloud`.`guest_os_hypervisor` (uuid,hypervisor_type, hypervisor_version, guest_os_name, guest_os_id, created, is_user_defined) VALUES (UUID(),'Xenserver', 'XCP 1.0', 'CentOS 5 (32-bit)', 5, now(), 0); +INSERT IGNORE INTO `cloud`.`guest_os_hypervisor` (uuid,hypervisor_type, hypervisor_version, guest_os_name, guest_os_id, created, is_user_defined) VALUES (UUID(),'Xenserver', 'XCP 1.0', 'CentOS 5 (64-bit)', 6, now(), 0); +INSERT IGNORE INTO `cloud`.`guest_os_hypervisor` (uuid,hypervisor_type, hypervisor_version, guest_os_name, guest_os_id, created, is_user_defined) VALUES (UUID(),'Xenserver', 'XCP 1.0', 'CentOS 5 (32-bit)', 7, now(), 0); +INSERT IGNORE INTO `cloud`.`guest_os_hypervisor` (uuid,hypervisor_type, hypervisor_version, guest_os_name, guest_os_id, created, is_user_defined) VALUES (UUID(),'Xenserver', 'XCP 1.0', 'CentOS 5 (64-bit)', 8, now(), 0); +INSERT IGNORE INTO `cloud`.`guest_os_hypervisor` (uuid,hypervisor_type, hypervisor_version, guest_os_name, guest_os_id, created, is_user_defined) VALUES (UUID(),'Xenserver', 'XCP 1.0', 'CentOS 5 (32-bit)', 9, now(), 0); +INSERT IGNORE INTO `cloud`.`guest_os_hypervisor` (uuid,hypervisor_type, hypervisor_version, guest_os_name, guest_os_id, created, is_user_defined) VALUES (UUID(),'Xenserver', 'XCP 1.0', 'CentOS 5 (64-bit)', 10, now(), 0); +INSERT IGNORE INTO `cloud`.`guest_os_hypervisor` (uuid,hypervisor_type, hypervisor_version, guest_os_name, guest_os_id, created, is_user_defined) VALUES (UUID(),'Xenserver', 'XCP 1.0', 'CentOS 5 (32-bit)', 11, now(), 0); +INSERT IGNORE INTO `cloud`.`guest_os_hypervisor` (uuid,hypervisor_type, hypervisor_version, guest_os_name, guest_os_id, created, is_user_defined) VALUES (UUID(),'Xenserver', 'XCP 1.0', 'CentOS 5 (64-bit)', 12, now(), 0); +INSERT IGNORE INTO `cloud`.`guest_os_hypervisor` (uuid,hypervisor_type, hypervisor_version, guest_os_name, guest_os_id, created, is_user_defined) VALUES (UUID(),'Xenserver', 'XCP 1.0', 'CentOS 5 (32-bit)', 13, now(), 0); +INSERT IGNORE INTO `cloud`.`guest_os_hypervisor` (uuid,hypervisor_type, hypervisor_version, guest_os_name, guest_os_id, created, is_user_defined) VALUES (UUID(),'Xenserver', 'XCP 1.0', 'CentOS 5 (64-bit)', 14, now(), 0); +INSERT IGNORE INTO `cloud`.`guest_os_hypervisor` (uuid,hypervisor_type, hypervisor_version, guest_os_name, guest_os_id, created, is_user_defined) VALUES (UUID(),'Xenserver', 'XCP 1.0', 'CentOS 5 (32-bit)', 111, now(), 0); +INSERT IGNORE INTO `cloud`.`guest_os_hypervisor` (uuid,hypervisor_type, hypervisor_version, guest_os_name, guest_os_id, created, is_user_defined) VALUES (UUID(),'Xenserver', 'XCP 1.0', 'CentOS 5 (64-bit)', 112, now(), 0); +INSERT IGNORE INTO `cloud`.`guest_os_hypervisor` (uuid,hypervisor_type, hypervisor_version, guest_os_name, guest_os_id, created, is_user_defined) VALUES (UUID(),'Xenserver', 'XCP 1.0', 'Debian Lenny 5.0 (32-bit)', 15, now(), 0); +INSERT IGNORE INTO `cloud`.`guest_os_hypervisor` (uuid,hypervisor_type, hypervisor_version, guest_os_name, guest_os_id, created, is_user_defined) VALUES (UUID(),'Xenserver', 'XCP 1.0', 'Debian Squeeze 6.0 (32-bit)', 132, now(), 0); +INSERT IGNORE INTO `cloud`.`guest_os_hypervisor` (uuid,hypervisor_type, hypervisor_version, guest_os_name, guest_os_id, created, is_user_defined) VALUES (UUID(),'Xenserver', 'XCP 1.0', 'Debian Squeeze 6.0 (64-bit) (experimental)', 133, now(), 0); +INSERT IGNORE INTO `cloud`.`guest_os_hypervisor` (uuid,hypervisor_type, hypervisor_version, guest_os_name, guest_os_id, created, is_user_defined) VALUES (UUID(),'Xenserver', 'XCP 1.0', 'Debian Squeeze 6.0 (32-bit)', 183, now(), 0); +INSERT IGNORE INTO `cloud`.`guest_os_hypervisor` (uuid,hypervisor_type, hypervisor_version, guest_os_name, guest_os_id, created, is_user_defined) VALUES (UUID(),'Xenserver', 'XCP 1.0', 'Debian Squeeze 6.0 (64-bit) (experimental)', 184, now(), 0); +INSERT IGNORE INTO `cloud`.`guest_os_hypervisor` (uuid,hypervisor_type, hypervisor_version, guest_os_name, guest_os_id, created, is_user_defined) VALUES (UUID(),'Xenserver', 'XCP 1.0', 'Oracle Enterprise Linux 5 (32-bit)', 16, now(), 0); +INSERT IGNORE INTO `cloud`.`guest_os_hypervisor` (uuid,hypervisor_type, hypervisor_version, guest_os_name, guest_os_id, created, is_user_defined) VALUES (UUID(),'Xenserver', 'XCP 1.0', 'Oracle Enterprise Linux 5 (64-bit)', 17, now(), 0); +INSERT IGNORE INTO `cloud`.`guest_os_hypervisor` (uuid,hypervisor_type, hypervisor_version, guest_os_name, guest_os_id, created, is_user_defined) VALUES (UUID(),'Xenserver', 'XCP 1.0', 'Oracle Enterprise Linux 5 (32-bit)', 18, now(), 0); +INSERT IGNORE INTO `cloud`.`guest_os_hypervisor` (uuid,hypervisor_type, hypervisor_version, guest_os_name, guest_os_id, created, is_user_defined) VALUES (UUID(),'Xenserver', 'XCP 1.0', 'Oracle Enterprise Linux 5 (64-bit)', 19, now(), 0); +INSERT IGNORE INTO `cloud`.`guest_os_hypervisor` (uuid,hypervisor_type, hypervisor_version, guest_os_name, guest_os_id, created, is_user_defined) VALUES (UUID(),'Xenserver', 'XCP 1.0', 'Oracle Enterprise Linux 5 (32-bit)', 20, now(), 0); +INSERT IGNORE INTO `cloud`.`guest_os_hypervisor` (uuid,hypervisor_type, hypervisor_version, guest_os_name, guest_os_id, created, is_user_defined) VALUES (UUID(),'Xenserver', 'XCP 1.0', 'Oracle Enterprise Linux 5 (64-bit)', 21, now(), 0); +INSERT IGNORE INTO `cloud`.`guest_os_hypervisor` (uuid,hypervisor_type, hypervisor_version, guest_os_name, guest_os_id, created, is_user_defined) VALUES (UUID(),'Xenserver', 'XCP 1.0', 'Oracle Enterprise Linux 5 (32-bit)', 22, now(), 0); +INSERT IGNORE INTO `cloud`.`guest_os_hypervisor` (uuid,hypervisor_type, hypervisor_version, guest_os_name, guest_os_id, created, is_user_defined) VALUES (UUID(),'Xenserver', 'XCP 1.0', 'Oracle Enterprise Linux 5 (64-bit)', 23, now(), 0); +INSERT IGNORE INTO `cloud`.`guest_os_hypervisor` (uuid,hypervisor_type, hypervisor_version, guest_os_name, guest_os_id, created, is_user_defined) VALUES (UUID(),'Xenserver', 'XCP 1.0', 'Oracle Enterprise Linux 5 (32-bit)', 24, now(), 0); +INSERT IGNORE INTO `cloud`.`guest_os_hypervisor` (uuid,hypervisor_type, hypervisor_version, guest_os_name, guest_os_id, created, is_user_defined) VALUES (UUID(),'Xenserver', 'XCP 1.0', 'Oracle Enterprise Linux 5 (64-bit)', 25, now(), 0); +INSERT IGNORE INTO `cloud`.`guest_os_hypervisor` (uuid,hypervisor_type, hypervisor_version, guest_os_name, guest_os_id, created, is_user_defined) VALUES (UUID(),'Xenserver', 'XCP 1.0', 'Oracle Enterprise Linux 5 (32-bit)', 134, now(), 0); +INSERT IGNORE INTO `cloud`.`guest_os_hypervisor` (uuid,hypervisor_type, hypervisor_version, guest_os_name, guest_os_id, created, is_user_defined) VALUES (UUID(),'Xenserver', 'XCP 1.0', 'Oracle Enterprise Linux 5 (64-bit)', 135, now(), 0); +INSERT IGNORE INTO `cloud`.`guest_os_hypervisor` (uuid,hypervisor_type, hypervisor_version, guest_os_name, guest_os_id, created, is_user_defined) VALUES (UUID(),'Xenserver', 'XCP 1.0', 'Red Hat Enterprise Linux 4.5 (32-bit)', 26, now(), 0); +INSERT IGNORE INTO `cloud`.`guest_os_hypervisor` (uuid,hypervisor_type, hypervisor_version, guest_os_name, guest_os_id, created, is_user_defined) VALUES (UUID(),'Xenserver', 'XCP 1.0', 'Red Hat Enterprise Linux 4.6 (32-bit)', 27, now(), 0); +INSERT IGNORE INTO `cloud`.`guest_os_hypervisor` (uuid,hypervisor_type, hypervisor_version, guest_os_name, guest_os_id, created, is_user_defined) VALUES (UUID(),'Xenserver', 'XCP 1.0', 'Red Hat Enterprise Linux 4.7 (32-bit)', 28, now(), 0); +INSERT IGNORE INTO `cloud`.`guest_os_hypervisor` (uuid,hypervisor_type, hypervisor_version, guest_os_name, guest_os_id, created, is_user_defined) VALUES (UUID(),'Xenserver', 'XCP 1.0', 'Red Hat Enterprise Linux 4.8 (32-bit)', 29, now(), 0); +INSERT IGNORE INTO `cloud`.`guest_os_hypervisor` (uuid,hypervisor_type, hypervisor_version, guest_os_name, guest_os_id, created, is_user_defined) VALUES (UUID(),'Xenserver', 'XCP 1.0', 'Red Hat Enterprise Linux 5 (32-bit)', 30, now(), 0); +INSERT IGNORE INTO `cloud`.`guest_os_hypervisor` (uuid,hypervisor_type, hypervisor_version, guest_os_name, guest_os_id, created, is_user_defined) VALUES (UUID(),'Xenserver', 'XCP 1.0', 'Red Hat Enterprise Linux 5 (64-bit)', 31, now(), 0); +INSERT IGNORE INTO `cloud`.`guest_os_hypervisor` (uuid,hypervisor_type, hypervisor_version, guest_os_name, guest_os_id, created, is_user_defined) VALUES (UUID(),'Xenserver', 'XCP 1.0', 'Red Hat Enterprise Linux 5 (32-bit)', 32, now(), 0); +INSERT IGNORE INTO `cloud`.`guest_os_hypervisor` (uuid,hypervisor_type, hypervisor_version, guest_os_name, guest_os_id, created, is_user_defined) VALUES (UUID(),'Xenserver', 'XCP 1.0', 'Red Hat Enterprise Linux 5 (64-bit)', 33, now(), 0); +INSERT IGNORE INTO `cloud`.`guest_os_hypervisor` (uuid,hypervisor_type, hypervisor_version, guest_os_name, guest_os_id, created, is_user_defined) VALUES (UUID(),'Xenserver', 'XCP 1.0', 'Red Hat Enterprise Linux 5 (32-bit)', 34, now(), 0); +INSERT IGNORE INTO `cloud`.`guest_os_hypervisor` (uuid,hypervisor_type, hypervisor_version, guest_os_name, guest_os_id, created, is_user_defined) VALUES (UUID(),'Xenserver', 'XCP 1.0', 'Red Hat Enterprise Linux 5 (64-bit)', 35, now(), 0); +INSERT IGNORE INTO `cloud`.`guest_os_hypervisor` (uuid,hypervisor_type, hypervisor_version, guest_os_name, guest_os_id, created, is_user_defined) VALUES (UUID(),'Xenserver', 'XCP 1.0', 'Red Hat Enterprise Linux 5 (32-bit)', 36, now(), 0); +INSERT IGNORE INTO `cloud`.`guest_os_hypervisor` (uuid,hypervisor_type, hypervisor_version, guest_os_name, guest_os_id, created, is_user_defined) VALUES (UUID(),'Xenserver', 'XCP 1.0', 'Red Hat Enterprise Linux 5 (64-bit)', 37, now(), 0); +INSERT IGNORE INTO `cloud`.`guest_os_hypervisor` (uuid,hypervisor_type, hypervisor_version, guest_os_name, guest_os_id, created, is_user_defined) VALUES (UUID(),'Xenserver', 'XCP 1.0', 'Red Hat Enterprise Linux 5 (32-bit)', 38, now(), 0); +INSERT IGNORE INTO `cloud`.`guest_os_hypervisor` (uuid,hypervisor_type, hypervisor_version, guest_os_name, guest_os_id, created, is_user_defined) VALUES (UUID(),'Xenserver', 'XCP 1.0', 'Red Hat Enterprise Linux 5 (64-bit)', 39, now(), 0); +INSERT IGNORE INTO `cloud`.`guest_os_hypervisor` (uuid,hypervisor_type, hypervisor_version, guest_os_name, guest_os_id, created, is_user_defined) VALUES (UUID(),'Xenserver', 'XCP 1.0', 'Red Hat Enterprise Linux 5 (32-bit)', 113, now(), 0); +INSERT IGNORE INTO `cloud`.`guest_os_hypervisor` (uuid,hypervisor_type, hypervisor_version, guest_os_name, guest_os_id, created, is_user_defined) VALUES (UUID(),'Xenserver', 'XCP 1.0', 'Red Hat Enterprise Linux 5 (64-bit)', 114, now(), 0); +INSERT IGNORE INTO `cloud`.`guest_os_hypervisor` (uuid,hypervisor_type, hypervisor_version, guest_os_name, guest_os_id, created, is_user_defined) VALUES (UUID(),'Xenserver', 'XCP 1.0', 'Red Hat Enterprise Linux 6 (32-bit)', 136, now(), 0); +INSERT IGNORE INTO `cloud`.`guest_os_hypervisor` (uuid,hypervisor_type, hypervisor_version, guest_os_name, guest_os_id, created, is_user_defined) VALUES (UUID(),'Xenserver', 'XCP 1.0', 'Red Hat Enterprise Linux 6 (64-bit)', 137, now(), 0); +INSERT IGNORE INTO `cloud`.`guest_os_hypervisor` (uuid,hypervisor_type, hypervisor_version, guest_os_name, guest_os_id, created, is_user_defined) VALUES (UUID(),'Xenserver', 'XCP 1.0', 'SUSE Linux Enterprise Server 9 SP4', 40, now(), 0); +INSERT IGNORE INTO `cloud`.`guest_os_hypervisor` (uuid,hypervisor_type, hypervisor_version, guest_os_name, guest_os_id, created, is_user_defined) VALUES (UUID(),'Xenserver', 'XCP 1.0', 'SUSE Linux Enterprise Server 10 SP1', 41, now(), 0); +INSERT IGNORE INTO `cloud`.`guest_os_hypervisor` (uuid,hypervisor_type, hypervisor_version, guest_os_name, guest_os_id, created, is_user_defined) VALUES (UUID(),'Xenserver', 'XCP 1.0', 'SUSE Linux Enterprise Server 10 SP1 x64', 42, now(), 0); +INSERT IGNORE INTO `cloud`.`guest_os_hypervisor` (uuid,hypervisor_type, hypervisor_version, guest_os_name, guest_os_id, created, is_user_defined) VALUES (UUID(),'Xenserver', 'XCP 1.0', 'SUSE Linux Enterprise Server 10 SP2', 43, now(), 0); +INSERT IGNORE INTO `cloud`.`guest_os_hypervisor` (uuid,hypervisor_type, hypervisor_version, guest_os_name, guest_os_id, created, is_user_defined) VALUES (UUID(),'Xenserver', 'XCP 1.0', 'SUSE Linux Enterprise Server 10 SP2 x64', 44, now(), 0); +INSERT IGNORE INTO `cloud`.`guest_os_hypervisor` (uuid,hypervisor_type, hypervisor_version, guest_os_name, guest_os_id, created, is_user_defined) VALUES (UUID(),'Xenserver', 'XCP 1.0', 'Other install media', 45, now(), 0); +INSERT IGNORE INTO `cloud`.`guest_os_hypervisor` (uuid,hypervisor_type, hypervisor_version, guest_os_name, guest_os_id, created, is_user_defined) VALUES (UUID(),'Xenserver', 'XCP 1.0', 'SUSE Linux Enterprise Server 11', 46, now(), 0); +INSERT IGNORE INTO `cloud`.`guest_os_hypervisor` (uuid,hypervisor_type, hypervisor_version, guest_os_name, guest_os_id, created, is_user_defined) VALUES (UUID(),'Xenserver', 'XCP 1.0', 'SUSE Linux Enterprise Server 11 x64', 47, now(), 0); +INSERT IGNORE INTO `cloud`.`guest_os_hypervisor` (uuid,hypervisor_type, hypervisor_version, guest_os_name, guest_os_id, created, is_user_defined) VALUES (UUID(),'Xenserver', 'XCP 1.0', 'SUSE Linux Enterprise Server 11 SP1 (32-bit)', 155, now(), 0); +INSERT IGNORE INTO `cloud`.`guest_os_hypervisor` (uuid,hypervisor_type, hypervisor_version, guest_os_name, guest_os_id, created, is_user_defined) VALUES (UUID(),'Xenserver', 'XCP 1.0', 'SUSE Linux Enterprise Server 11 SP1 (64-bit)', 154, now(), 0); +INSERT IGNORE INTO `cloud`.`guest_os_hypervisor` (uuid,hypervisor_type, hypervisor_version, guest_os_name, guest_os_id, created, is_user_defined) VALUES (UUID(),'Xenserver', 'XCP 1.0', 'Windows 7 (32-bit)', 48, now(), 0); +INSERT IGNORE INTO `cloud`.`guest_os_hypervisor` (uuid,hypervisor_type, hypervisor_version, guest_os_name, guest_os_id, created, is_user_defined) VALUES (UUID(),'Xenserver', 'XCP 1.0', 'Windows 7 (64-bit)', 49, now(), 0); +INSERT IGNORE INTO `cloud`.`guest_os_hypervisor` (uuid,hypervisor_type, hypervisor_version, guest_os_name, guest_os_id, created, is_user_defined) VALUES (UUID(),'Xenserver', 'XCP 1.0', 'Windows Server 2003 (32-bit)', 50, now(), 0); +INSERT IGNORE INTO `cloud`.`guest_os_hypervisor` (uuid,hypervisor_type, hypervisor_version, guest_os_name, guest_os_id, created, is_user_defined) VALUES (UUID(),'Xenserver', 'XCP 1.0', 'Windows Server 2003 (64-bit)', 51, now(), 0); +INSERT IGNORE INTO `cloud`.`guest_os_hypervisor` (uuid,hypervisor_type, hypervisor_version, guest_os_name, guest_os_id, created, is_user_defined) VALUES (UUID(),'Xenserver', 'XCP 1.0', 'Windows Server 2003 (32-bit)', 87, now(), 0); +INSERT IGNORE INTO `cloud`.`guest_os_hypervisor` (uuid,hypervisor_type, hypervisor_version, guest_os_name, guest_os_id, created, is_user_defined) VALUES (UUID(),'Xenserver', 'XCP 1.0', 'Windows Server 2003 (64-bit)', 88, now(), 0); +INSERT IGNORE INTO `cloud`.`guest_os_hypervisor` (uuid,hypervisor_type, hypervisor_version, guest_os_name, guest_os_id, created, is_user_defined) VALUES (UUID(),'Xenserver', 'XCP 1.0', 'Windows Server 2003 (32-bit)', 89, now(), 0); +INSERT IGNORE INTO `cloud`.`guest_os_hypervisor` (uuid,hypervisor_type, hypervisor_version, guest_os_name, guest_os_id, created, is_user_defined) VALUES (UUID(),'Xenserver', 'XCP 1.0', 'Windows Server 2003 (64-bit)', 90, now(), 0); +INSERT IGNORE INTO `cloud`.`guest_os_hypervisor` (uuid,hypervisor_type, hypervisor_version, guest_os_name, guest_os_id, created, is_user_defined) VALUES (UUID(),'Xenserver', 'XCP 1.0', 'Windows Server 2008 (32-bit)', 52, now(), 0); +INSERT IGNORE INTO `cloud`.`guest_os_hypervisor` (uuid,hypervisor_type, hypervisor_version, guest_os_name, guest_os_id, created, is_user_defined) VALUES (UUID(),'Xenserver', 'XCP 1.0', 'Windows Server 2008 (64-bit)', 53, now(), 0); +INSERT IGNORE INTO `cloud`.`guest_os_hypervisor` (uuid,hypervisor_type, hypervisor_version, guest_os_name, guest_os_id, created, is_user_defined) VALUES (UUID(),'Xenserver', 'XCP 1.0', 'Windows Server 2008 R2 (64-bit)', 54, now(), 0); +INSERT IGNORE INTO `cloud`.`guest_os_hypervisor` (uuid,hypervisor_type, hypervisor_version, guest_os_name, guest_os_id, created, is_user_defined) VALUES (UUID(),'Xenserver', 'XCP 1.0', 'Windows XP SP3 (32-bit)', 58, now(), 0); +INSERT IGNORE INTO `cloud`.`guest_os_hypervisor` (uuid,hypervisor_type, hypervisor_version, guest_os_name, guest_os_id, created, is_user_defined) VALUES (UUID(),'Xenserver', 'XCP 1.0', 'Windows Vista (32-bit)', 56, now(), 0); +INSERT IGNORE INTO `cloud`.`guest_os_hypervisor` (uuid,hypervisor_type, hypervisor_version, guest_os_name, guest_os_id, created, is_user_defined) VALUES (UUID(),'Xenserver', 'XCP 1.0', 'Ubuntu Lucid Lynx 10.04 (32-bit) (experimental)', 121, now(), 0); +INSERT IGNORE INTO `cloud`.`guest_os_hypervisor` (uuid,hypervisor_type, hypervisor_version, guest_os_name, guest_os_id, created, is_user_defined) VALUES (UUID(),'Xenserver', 'XCP 1.0', 'Ubuntu Lucid Lynx 10.04 (64-bit) (experimental)', 126, now(), 0); +INSERT IGNORE INTO `cloud`.`guest_os_hypervisor` (uuid,hypervisor_type, hypervisor_version, guest_os_name, guest_os_id, created, is_user_defined) VALUES (UUID(),'Xenserver', 'XCP 1.0', 'Other install media', 98, now(), 0); +INSERT IGNORE INTO `cloud`.`guest_os_hypervisor` (uuid,hypervisor_type, hypervisor_version, guest_os_name, guest_os_id, created, is_user_defined) VALUES (UUID(),'Xenserver', 'XCP 1.0', 'Other install media', 99, now(), 0); +INSERT IGNORE INTO `cloud`.`guest_os_hypervisor` (uuid,hypervisor_type, hypervisor_version, guest_os_name, guest_os_id, created, is_user_defined) VALUES (UUID(),'Xenserver', 'XCP 1.0', 'CentOS 5 (32-bit)', 139, now(), 0); +INSERT IGNORE INTO `cloud`.`guest_os_hypervisor` (uuid,hypervisor_type, hypervisor_version, guest_os_name, guest_os_id, created, is_user_defined) VALUES (UUID(),'Xenserver', 'XCP 1.0', 'CentOS 5 (64-bit)', 140, now(), 0); +INSERT IGNORE INTO `cloud`.`guest_os_hypervisor` (uuid,hypervisor_type, hypervisor_version, guest_os_name, guest_os_id, created, is_user_defined) VALUES (UUID(),'Xenserver', '5.6 FP1', 'CentOS 4.5 (32-bit)', 1, now(), 0); +INSERT IGNORE INTO `cloud`.`guest_os_hypervisor` (uuid,hypervisor_type, hypervisor_version, guest_os_name, guest_os_id, created, is_user_defined) VALUES (UUID(),'Xenserver', '5.6 FP1', 'CentOS 4.6 (32-bit)', 2, now(), 0); +INSERT IGNORE INTO `cloud`.`guest_os_hypervisor` (uuid,hypervisor_type, hypervisor_version, guest_os_name, guest_os_id, created, is_user_defined) VALUES (UUID(),'Xenserver', '5.6 FP1', 'CentOS 4.7 (32-bit)', 3, now(), 0); +INSERT IGNORE INTO `cloud`.`guest_os_hypervisor` (uuid,hypervisor_type, hypervisor_version, guest_os_name, guest_os_id, created, is_user_defined) VALUES (UUID(),'Xenserver', '5.6 FP1', 'CentOS 4.8 (32-bit)', 4, now(), 0); +INSERT IGNORE INTO `cloud`.`guest_os_hypervisor` (uuid,hypervisor_type, hypervisor_version, guest_os_name, guest_os_id, created, is_user_defined) VALUES (UUID(),'Xenserver', '5.6 FP1', 'CentOS 5 (32-bit)', 5, now(), 0); +INSERT IGNORE INTO `cloud`.`guest_os_hypervisor` (uuid,hypervisor_type, hypervisor_version, guest_os_name, guest_os_id, created, is_user_defined) VALUES (UUID(),'Xenserver', '5.6 FP1', 'CentOS 5 (64-bit)', 6, now(), 0); +INSERT IGNORE INTO `cloud`.`guest_os_hypervisor` (uuid,hypervisor_type, hypervisor_version, guest_os_name, guest_os_id, created, is_user_defined) VALUES (UUID(),'Xenserver', '5.6 FP1', 'CentOS 5 (32-bit)', 7, now(), 0); +INSERT IGNORE INTO `cloud`.`guest_os_hypervisor` (uuid,hypervisor_type, hypervisor_version, guest_os_name, guest_os_id, created, is_user_defined) VALUES (UUID(),'Xenserver', '5.6 FP1', 'CentOS 5 (64-bit)', 8, now(), 0); +INSERT IGNORE INTO `cloud`.`guest_os_hypervisor` (uuid,hypervisor_type, hypervisor_version, guest_os_name, guest_os_id, created, is_user_defined) VALUES (UUID(),'Xenserver', '5.6 FP1', 'CentOS 5 (32-bit)', 9, now(), 0); +INSERT IGNORE INTO `cloud`.`guest_os_hypervisor` (uuid,hypervisor_type, hypervisor_version, guest_os_name, guest_os_id, created, is_user_defined) VALUES (UUID(),'Xenserver', '5.6 FP1', 'CentOS 5 (64-bit)', 10, now(), 0); +INSERT IGNORE INTO `cloud`.`guest_os_hypervisor` (uuid,hypervisor_type, hypervisor_version, guest_os_name, guest_os_id, created, is_user_defined) VALUES (UUID(),'Xenserver', '5.6 FP1', 'CentOS 5 (32-bit)', 11, now(), 0); +INSERT IGNORE INTO `cloud`.`guest_os_hypervisor` (uuid,hypervisor_type, hypervisor_version, guest_os_name, guest_os_id, created, is_user_defined) VALUES (UUID(),'Xenserver', '5.6 FP1', 'CentOS 5 (64-bit)', 12, now(), 0); +INSERT IGNORE INTO `cloud`.`guest_os_hypervisor` (uuid,hypervisor_type, hypervisor_version, guest_os_name, guest_os_id, created, is_user_defined) VALUES (UUID(),'Xenserver', '5.6 FP1', 'CentOS 5 (32-bit)', 13, now(), 0); +INSERT IGNORE INTO `cloud`.`guest_os_hypervisor` (uuid,hypervisor_type, hypervisor_version, guest_os_name, guest_os_id, created, is_user_defined) VALUES (UUID(),'Xenserver', '5.6 FP1', 'CentOS 5 (64-bit)', 14, now(), 0); +INSERT IGNORE INTO `cloud`.`guest_os_hypervisor` (uuid,hypervisor_type, hypervisor_version, guest_os_name, guest_os_id, created, is_user_defined) VALUES (UUID(),'Xenserver', '5.6 FP1', 'CentOS 5 (32-bit)', 111, now(), 0); +INSERT IGNORE INTO `cloud`.`guest_os_hypervisor` (uuid,hypervisor_type, hypervisor_version, guest_os_name, guest_os_id, created, is_user_defined) VALUES (UUID(),'Xenserver', '5.6 FP1', 'CentOS 5 (64-bit)', 112, now(), 0); +INSERT IGNORE INTO `cloud`.`guest_os_hypervisor` (uuid,hypervisor_type, hypervisor_version, guest_os_name, guest_os_id, created, is_user_defined) VALUES (UUID(),'Xenserver', '5.6 FP1', 'Debian Lenny 5.0 (32-bit)', 15, now(), 0); +INSERT IGNORE INTO `cloud`.`guest_os_hypervisor` (uuid,hypervisor_type, hypervisor_version, guest_os_name, guest_os_id, created, is_user_defined) VALUES (UUID(),'Xenserver', '5.6 FP1', 'Debian Squeeze 6.0 (32-bit)', 132, now(), 0); +INSERT IGNORE INTO `cloud`.`guest_os_hypervisor` (uuid,hypervisor_type, hypervisor_version, guest_os_name, guest_os_id, created, is_user_defined) VALUES (UUID(),'Xenserver', '5.6 FP1', 'Debian Squeeze 6.0 (64-bit) (experimental)', 133, now(), 0); +INSERT IGNORE INTO `cloud`.`guest_os_hypervisor` (uuid,hypervisor_type, hypervisor_version, guest_os_name, guest_os_id, created, is_user_defined) VALUES (UUID(),'Xenserver', '5.6 FP1', 'Debian Squeeze 6.0 (32-bit)', 183, now(), 0); +INSERT IGNORE INTO `cloud`.`guest_os_hypervisor` (uuid,hypervisor_type, hypervisor_version, guest_os_name, guest_os_id, created, is_user_defined) VALUES (UUID(),'Xenserver', '5.6 FP1', 'Debian Squeeze 6.0 (64-bit) (experimental)', 184, now(), 0); +INSERT IGNORE INTO `cloud`.`guest_os_hypervisor` (uuid,hypervisor_type, hypervisor_version, guest_os_name, guest_os_id, created, is_user_defined) VALUES (UUID(),'Xenserver', '5.6 FP1', 'Oracle Enterprise Linux 5 (32-bit)', 16, now(), 0); +INSERT IGNORE INTO `cloud`.`guest_os_hypervisor` (uuid,hypervisor_type, hypervisor_version, guest_os_name, guest_os_id, created, is_user_defined) VALUES (UUID(),'Xenserver', '5.6 FP1', 'Oracle Enterprise Linux 5 (64-bit)', 17, now(), 0); +INSERT IGNORE INTO `cloud`.`guest_os_hypervisor` (uuid,hypervisor_type, hypervisor_version, guest_os_name, guest_os_id, created, is_user_defined) VALUES (UUID(),'Xenserver', '5.6 FP1', 'Oracle Enterprise Linux 5 (32-bit)', 18, now(), 0); +INSERT IGNORE INTO `cloud`.`guest_os_hypervisor` (uuid,hypervisor_type, hypervisor_version, guest_os_name, guest_os_id, created, is_user_defined) VALUES (UUID(),'Xenserver', '5.6 FP1', 'Oracle Enterprise Linux 5 (64-bit)', 19, now(), 0); +INSERT IGNORE INTO `cloud`.`guest_os_hypervisor` (uuid,hypervisor_type, hypervisor_version, guest_os_name, guest_os_id, created, is_user_defined) VALUES (UUID(),'Xenserver', '5.6 FP1', 'Oracle Enterprise Linux 5 (32-bit)', 20, now(), 0); +INSERT IGNORE INTO `cloud`.`guest_os_hypervisor` (uuid,hypervisor_type, hypervisor_version, guest_os_name, guest_os_id, created, is_user_defined) VALUES (UUID(),'Xenserver', '5.6 FP1', 'Oracle Enterprise Linux 5 (64-bit)', 21, now(), 0); +INSERT IGNORE INTO `cloud`.`guest_os_hypervisor` (uuid,hypervisor_type, hypervisor_version, guest_os_name, guest_os_id, created, is_user_defined) VALUES (UUID(),'Xenserver', '5.6 FP1', 'Oracle Enterprise Linux 5 (32-bit)', 22, now(), 0); +INSERT IGNORE INTO `cloud`.`guest_os_hypervisor` (uuid,hypervisor_type, hypervisor_version, guest_os_name, guest_os_id, created, is_user_defined) VALUES (UUID(),'Xenserver', '5.6 FP1', 'Oracle Enterprise Linux 5 (64-bit)', 23, now(), 0); +INSERT IGNORE INTO `cloud`.`guest_os_hypervisor` (uuid,hypervisor_type, hypervisor_version, guest_os_name, guest_os_id, created, is_user_defined) VALUES (UUID(),'Xenserver', '5.6 FP1', 'Oracle Enterprise Linux 5 (32-bit)', 24, now(), 0); +INSERT IGNORE INTO `cloud`.`guest_os_hypervisor` (uuid,hypervisor_type, hypervisor_version, guest_os_name, guest_os_id, created, is_user_defined) VALUES (UUID(),'Xenserver', '5.6 FP1', 'Oracle Enterprise Linux 5 (64-bit)', 25, now(), 0); +INSERT IGNORE INTO `cloud`.`guest_os_hypervisor` (uuid,hypervisor_type, hypervisor_version, guest_os_name, guest_os_id, created, is_user_defined) VALUES (UUID(),'Xenserver', '5.6 FP1', 'Oracle Enterprise Linux 5 (32-bit)', 134, now(), 0); +INSERT IGNORE INTO `cloud`.`guest_os_hypervisor` (uuid,hypervisor_type, hypervisor_version, guest_os_name, guest_os_id, created, is_user_defined) VALUES (UUID(),'Xenserver', '5.6 FP1', 'Oracle Enterprise Linux 5 (64-bit)', 135, now(), 0); +INSERT IGNORE INTO `cloud`.`guest_os_hypervisor` (uuid,hypervisor_type, hypervisor_version, guest_os_name, guest_os_id, created, is_user_defined) VALUES (UUID(),'Xenserver', '5.6 FP1', 'Red Hat Enterprise Linux 4.5 (32-bit)', 26, now(), 0); +INSERT IGNORE INTO `cloud`.`guest_os_hypervisor` (uuid,hypervisor_type, hypervisor_version, guest_os_name, guest_os_id, created, is_user_defined) VALUES (UUID(),'Xenserver', '5.6 FP1', 'Red Hat Enterprise Linux 4.6 (32-bit)', 27, now(), 0); +INSERT IGNORE INTO `cloud`.`guest_os_hypervisor` (uuid,hypervisor_type, hypervisor_version, guest_os_name, guest_os_id, created, is_user_defined) VALUES (UUID(),'Xenserver', '5.6 FP1', 'Red Hat Enterprise Linux 4.7 (32-bit)', 28, now(), 0); +INSERT IGNORE INTO `cloud`.`guest_os_hypervisor` (uuid,hypervisor_type, hypervisor_version, guest_os_name, guest_os_id, created, is_user_defined) VALUES (UUID(),'Xenserver', '5.6 FP1', 'Red Hat Enterprise Linux 4.8 (32-bit)', 29, now(), 0); +INSERT IGNORE INTO `cloud`.`guest_os_hypervisor` (uuid,hypervisor_type, hypervisor_version, guest_os_name, guest_os_id, created, is_user_defined) VALUES (UUID(),'Xenserver', '5.6 FP1', 'Red Hat Enterprise Linux 5 (32-bit)', 30, now(), 0); +INSERT IGNORE INTO `cloud`.`guest_os_hypervisor` (uuid,hypervisor_type, hypervisor_version, guest_os_name, guest_os_id, created, is_user_defined) VALUES (UUID(),'Xenserver', '5.6 FP1', 'Red Hat Enterprise Linux 5 (64-bit)', 31, now(), 0); +INSERT IGNORE INTO `cloud`.`guest_os_hypervisor` (uuid,hypervisor_type, hypervisor_version, guest_os_name, guest_os_id, created, is_user_defined) VALUES (UUID(),'Xenserver', '5.6 FP1', 'Red Hat Enterprise Linux 5 (32-bit)', 32, now(), 0); +INSERT IGNORE INTO `cloud`.`guest_os_hypervisor` (uuid,hypervisor_type, hypervisor_version, guest_os_name, guest_os_id, created, is_user_defined) VALUES (UUID(),'Xenserver', '5.6 FP1', 'Red Hat Enterprise Linux 5 (64-bit)', 33, now(), 0); +INSERT IGNORE INTO `cloud`.`guest_os_hypervisor` (uuid,hypervisor_type, hypervisor_version, guest_os_name, guest_os_id, created, is_user_defined) VALUES (UUID(),'Xenserver', '5.6 FP1', 'Red Hat Enterprise Linux 5 (32-bit)', 34, now(), 0); +INSERT IGNORE INTO `cloud`.`guest_os_hypervisor` (uuid,hypervisor_type, hypervisor_version, guest_os_name, guest_os_id, created, is_user_defined) VALUES (UUID(),'Xenserver', '5.6 FP1', 'Red Hat Enterprise Linux 5 (64-bit)', 35, now(), 0); +INSERT IGNORE INTO `cloud`.`guest_os_hypervisor` (uuid,hypervisor_type, hypervisor_version, guest_os_name, guest_os_id, created, is_user_defined) VALUES (UUID(),'Xenserver', '5.6 FP1', 'Red Hat Enterprise Linux 5 (32-bit)', 36, now(), 0); +INSERT IGNORE INTO `cloud`.`guest_os_hypervisor` (uuid,hypervisor_type, hypervisor_version, guest_os_name, guest_os_id, created, is_user_defined) VALUES (UUID(),'Xenserver', '5.6 FP1', 'Red Hat Enterprise Linux 5 (64-bit)', 37, now(), 0); +INSERT IGNORE INTO `cloud`.`guest_os_hypervisor` (uuid,hypervisor_type, hypervisor_version, guest_os_name, guest_os_id, created, is_user_defined) VALUES (UUID(),'Xenserver', '5.6 FP1', 'Red Hat Enterprise Linux 5 (32-bit)', 38, now(), 0); +INSERT IGNORE INTO `cloud`.`guest_os_hypervisor` (uuid,hypervisor_type, hypervisor_version, guest_os_name, guest_os_id, created, is_user_defined) VALUES (UUID(),'Xenserver', '5.6 FP1', 'Red Hat Enterprise Linux 5 (64-bit)', 39, now(), 0); +INSERT IGNORE INTO `cloud`.`guest_os_hypervisor` (uuid,hypervisor_type, hypervisor_version, guest_os_name, guest_os_id, created, is_user_defined) VALUES (UUID(),'Xenserver', '5.6 FP1', 'Red Hat Enterprise Linux 5 (32-bit)', 113, now(), 0); +INSERT IGNORE INTO `cloud`.`guest_os_hypervisor` (uuid,hypervisor_type, hypervisor_version, guest_os_name, guest_os_id, created, is_user_defined) VALUES (UUID(),'Xenserver', '5.6 FP1', 'Red Hat Enterprise Linux 5 (64-bit)', 114, now(), 0); +INSERT IGNORE INTO `cloud`.`guest_os_hypervisor` (uuid,hypervisor_type, hypervisor_version, guest_os_name, guest_os_id, created, is_user_defined) VALUES (UUID(),'Xenserver', '5.6 FP1', 'Red Hat Enterprise Linux 6 (32-bit) (experimental)', 136, now(), 0); +INSERT IGNORE INTO `cloud`.`guest_os_hypervisor` (uuid,hypervisor_type, hypervisor_version, guest_os_name, guest_os_id, created, is_user_defined) VALUES (UUID(),'Xenserver', '5.6 FP1', 'Red Hat Enterprise Linux 6 (64-bit) (experimental)', 137, now(), 0); +INSERT IGNORE INTO `cloud`.`guest_os_hypervisor` (uuid,hypervisor_type, hypervisor_version, guest_os_name, guest_os_id, created, is_user_defined) VALUES (UUID(),'Xenserver', '5.6 FP1', 'SUSE Linux Enterprise Server 9 SP4 (32-bit)', 40, now(), 0); +INSERT IGNORE INTO `cloud`.`guest_os_hypervisor` (uuid,hypervisor_type, hypervisor_version, guest_os_name, guest_os_id, created, is_user_defined) VALUES (UUID(),'Xenserver', '5.6 FP1', 'SUSE Linux Enterprise Server 10 SP1 (32-bit)', 41, now(), 0); +INSERT IGNORE INTO `cloud`.`guest_os_hypervisor` (uuid,hypervisor_type, hypervisor_version, guest_os_name, guest_os_id, created, is_user_defined) VALUES (UUID(),'Xenserver', '5.6 FP1', 'SUSE Linux Enterprise Server 10 SP1 (64-bit)', 42, now(), 0); +INSERT IGNORE INTO `cloud`.`guest_os_hypervisor` (uuid,hypervisor_type, hypervisor_version, guest_os_name, guest_os_id, created, is_user_defined) VALUES (UUID(),'Xenserver', '5.6 FP1', 'SUSE Linux Enterprise Server 10 SP2 (32-bit)', 43, now(), 0); +INSERT IGNORE INTO `cloud`.`guest_os_hypervisor` (uuid,hypervisor_type, hypervisor_version, guest_os_name, guest_os_id, created, is_user_defined) VALUES (UUID(),'Xenserver', '5.6 FP1', 'SUSE Linux Enterprise Server 10 SP2 (64-bit)', 44, now(), 0); +INSERT IGNORE INTO `cloud`.`guest_os_hypervisor` (uuid,hypervisor_type, hypervisor_version, guest_os_name, guest_os_id, created, is_user_defined) VALUES (UUID(),'Xenserver', '5.6 FP1', 'SUSE Linux Enterprise Server 10 SP3 (64-bit)', 45, now(), 0); +INSERT IGNORE INTO `cloud`.`guest_os_hypervisor` (uuid,hypervisor_type, hypervisor_version, guest_os_name, guest_os_id, created, is_user_defined) VALUES (UUID(),'Xenserver', '5.6 FP1', 'SUSE Linux Enterprise Server 11 (32-bit)', 46, now(), 0); +INSERT IGNORE INTO `cloud`.`guest_os_hypervisor` (uuid,hypervisor_type, hypervisor_version, guest_os_name, guest_os_id, created, is_user_defined) VALUES (UUID(),'Xenserver', '5.6 FP1', 'SUSE Linux Enterprise Server 11 (64-bit)', 47, now(), 0); +INSERT IGNORE INTO `cloud`.`guest_os_hypervisor` (uuid,hypervisor_type, hypervisor_version, guest_os_name, guest_os_id, created, is_user_defined) VALUES (UUID(),'Xenserver', '5.6 FP1', 'Windows 7 (32-bit)', 48, now(), 0); +INSERT IGNORE INTO `cloud`.`guest_os_hypervisor` (uuid,hypervisor_type, hypervisor_version, guest_os_name, guest_os_id, created, is_user_defined) VALUES (UUID(),'Xenserver', '5.6 FP1', 'Windows 7 (64-bit)', 49, now(), 0); +INSERT IGNORE INTO `cloud`.`guest_os_hypervisor` (uuid,hypervisor_type, hypervisor_version, guest_os_name, guest_os_id, created, is_user_defined) VALUES (UUID(),'Xenserver', '5.6 FP1', 'Windows Server 2003 (32-bit)', 50, now(), 0); +INSERT IGNORE INTO `cloud`.`guest_os_hypervisor` (uuid,hypervisor_type, hypervisor_version, guest_os_name, guest_os_id, created, is_user_defined) VALUES (UUID(),'Xenserver', '5.6 FP1', 'Windows Server 2003 (64-bit)', 51, now(), 0); +INSERT IGNORE INTO `cloud`.`guest_os_hypervisor` (uuid,hypervisor_type, hypervisor_version, guest_os_name, guest_os_id, created, is_user_defined) VALUES (UUID(),'Xenserver', '5.6 FP1', 'Windows Server 2003 (32-bit)', 87, now(), 0); +INSERT IGNORE INTO `cloud`.`guest_os_hypervisor` (uuid,hypervisor_type, hypervisor_version, guest_os_name, guest_os_id, created, is_user_defined) VALUES (UUID(),'Xenserver', '5.6 FP1', 'Windows Server 2003 (64-bit)', 88, now(), 0); +INSERT IGNORE INTO `cloud`.`guest_os_hypervisor` (uuid,hypervisor_type, hypervisor_version, guest_os_name, guest_os_id, created, is_user_defined) VALUES (UUID(),'Xenserver', '5.6 FP1', 'Windows Server 2008 (32-bit)', 52, now(), 0); +INSERT IGNORE INTO `cloud`.`guest_os_hypervisor` (uuid,hypervisor_type, hypervisor_version, guest_os_name, guest_os_id, created, is_user_defined) VALUES (UUID(),'Xenserver', '5.6 FP1', 'Windows Server 2008 (64-bit)', 53, now(), 0); +INSERT IGNORE INTO `cloud`.`guest_os_hypervisor` (uuid,hypervisor_type, hypervisor_version, guest_os_name, guest_os_id, created, is_user_defined) VALUES (UUID(),'Xenserver', '5.6 FP1', 'Windows Server 2008 R2 (64-bit)', 54, now(), 0); +INSERT IGNORE INTO `cloud`.`guest_os_hypervisor` (uuid,hypervisor_type, hypervisor_version, guest_os_name, guest_os_id, created, is_user_defined) VALUES (UUID(),'Xenserver', '5.6 FP1', 'Windows 2000 SP4 (32-bit)', 55, now(), 0); +INSERT IGNORE INTO `cloud`.`guest_os_hypervisor` (uuid,hypervisor_type, hypervisor_version, guest_os_name, guest_os_id, created, is_user_defined) VALUES (UUID(),'Xenserver', '5.6 FP1', 'Windows Vista (32-bit)', 56, now(), 0); +INSERT IGNORE INTO `cloud`.`guest_os_hypervisor` (uuid,hypervisor_type, hypervisor_version, guest_os_name, guest_os_id, created, is_user_defined) VALUES (UUID(),'Xenserver', '5.6 FP1', 'Windows XP SP3 (32-bit)', 58, now(), 0); +INSERT IGNORE INTO `cloud`.`guest_os_hypervisor` (uuid,hypervisor_type, hypervisor_version, guest_os_name, guest_os_id, created, is_user_defined) VALUES (UUID(),'Xenserver', '5.6 FP1', 'Ubuntu Lucid Lynx 10.04 (32-bit) (experimental)', 121, now(), 0); +INSERT IGNORE INTO `cloud`.`guest_os_hypervisor` (uuid,hypervisor_type, hypervisor_version, guest_os_name, guest_os_id, created, is_user_defined) VALUES (UUID(),'Xenserver', '5.6 FP1', 'Ubuntu Lucid Lynx 10.04 (64-bit) (experimental)', 126, now(), 0); +INSERT IGNORE INTO `cloud`.`guest_os_hypervisor` (uuid,hypervisor_type, hypervisor_version, guest_os_name, guest_os_id, created, is_user_defined) VALUES (UUID(),'Xenserver', '5.6 FP1', 'Other install media', 98, now(), 0); +INSERT IGNORE INTO `cloud`.`guest_os_hypervisor` (uuid,hypervisor_type, hypervisor_version, guest_os_name, guest_os_id, created, is_user_defined) VALUES (UUID(),'Xenserver', '5.6 FP1', 'Other install media', 99, now(), 0); +INSERT IGNORE INTO `cloud`.`guest_os_hypervisor` (uuid,hypervisor_type, hypervisor_version, guest_os_name, guest_os_id, created, is_user_defined) VALUES (UUID(),'Xenserver', '5.6 FP1', 'CentOS 5 (32-bit)', 139, now(), 0); +INSERT IGNORE INTO `cloud`.`guest_os_hypervisor` (uuid,hypervisor_type, hypervisor_version, guest_os_name, guest_os_id, created, is_user_defined) VALUES (UUID(),'Xenserver', '5.6 FP1', 'CentOS 5 (64-bit)', 140, now(), 0); +INSERT IGNORE INTO `cloud`.`guest_os_hypervisor` (uuid,hypervisor_type, hypervisor_version, guest_os_name, guest_os_id, created, is_user_defined) VALUES (UUID(),'Xenserver', '5.6 SP2', 'CentOS 4.5 (32-bit)', 1, now(), 0); +INSERT IGNORE INTO `cloud`.`guest_os_hypervisor` (uuid,hypervisor_type, hypervisor_version, guest_os_name, guest_os_id, created, is_user_defined) VALUES (UUID(),'Xenserver', '5.6 SP2', 'CentOS 4.6 (32-bit)', 2, now(), 0); +INSERT IGNORE INTO `cloud`.`guest_os_hypervisor` (uuid,hypervisor_type, hypervisor_version, guest_os_name, guest_os_id, created, is_user_defined) VALUES (UUID(),'Xenserver', '5.6 SP2', 'CentOS 4.7 (32-bit)', 3, now(), 0); +INSERT IGNORE INTO `cloud`.`guest_os_hypervisor` (uuid,hypervisor_type, hypervisor_version, guest_os_name, guest_os_id, created, is_user_defined) VALUES (UUID(),'Xenserver', '5.6 SP2', 'CentOS 4.8 (32-bit)', 4, now(), 0); +INSERT IGNORE INTO `cloud`.`guest_os_hypervisor` (uuid,hypervisor_type, hypervisor_version, guest_os_name, guest_os_id, created, is_user_defined) VALUES (UUID(),'Xenserver', '5.6 SP2', 'CentOS 5 (32-bit)', 5, now(), 0); +INSERT IGNORE INTO `cloud`.`guest_os_hypervisor` (uuid,hypervisor_type, hypervisor_version, guest_os_name, guest_os_id, created, is_user_defined) VALUES (UUID(),'Xenserver', '5.6 SP2', 'CentOS 5 (64-bit)', 6, now(), 0); +INSERT IGNORE INTO `cloud`.`guest_os_hypervisor` (uuid,hypervisor_type, hypervisor_version, guest_os_name, guest_os_id, created, is_user_defined) VALUES (UUID(),'Xenserver', '5.6 SP2', 'CentOS 5 (32-bit)', 7, now(), 0); +INSERT IGNORE INTO `cloud`.`guest_os_hypervisor` (uuid,hypervisor_type, hypervisor_version, guest_os_name, guest_os_id, created, is_user_defined) VALUES (UUID(),'Xenserver', '5.6 SP2', 'CentOS 5 (64-bit)', 8, now(), 0); +INSERT IGNORE INTO `cloud`.`guest_os_hypervisor` (uuid,hypervisor_type, hypervisor_version, guest_os_name, guest_os_id, created, is_user_defined) VALUES (UUID(),'Xenserver', '5.6 SP2', 'CentOS 5 (32-bit)', 9, now(), 0); +INSERT IGNORE INTO `cloud`.`guest_os_hypervisor` (uuid,hypervisor_type, hypervisor_version, guest_os_name, guest_os_id, created, is_user_defined) VALUES (UUID(),'Xenserver', '5.6 SP2', 'CentOS 5 (64-bit)', 10, now(), 0); +INSERT IGNORE INTO `cloud`.`guest_os_hypervisor` (uuid,hypervisor_type, hypervisor_version, guest_os_name, guest_os_id, created, is_user_defined) VALUES (UUID(),'Xenserver', '5.6 SP2', 'CentOS 5 (32-bit)', 11, now(), 0); +INSERT IGNORE INTO `cloud`.`guest_os_hypervisor` (uuid,hypervisor_type, hypervisor_version, guest_os_name, guest_os_id, created, is_user_defined) VALUES (UUID(),'Xenserver', '5.6 SP2', 'CentOS 5 (64-bit)', 12, now(), 0); +INSERT IGNORE INTO `cloud`.`guest_os_hypervisor` (uuid,hypervisor_type, hypervisor_version, guest_os_name, guest_os_id, created, is_user_defined) VALUES (UUID(),'Xenserver', '5.6 SP2', 'CentOS 5 (32-bit)', 13, now(), 0); +INSERT IGNORE INTO `cloud`.`guest_os_hypervisor` (uuid,hypervisor_type, hypervisor_version, guest_os_name, guest_os_id, created, is_user_defined) VALUES (UUID(),'Xenserver', '5.6 SP2', 'CentOS 5 (64-bit)', 14, now(), 0); +INSERT IGNORE INTO `cloud`.`guest_os_hypervisor` (uuid,hypervisor_type, hypervisor_version, guest_os_name, guest_os_id, created, is_user_defined) VALUES (UUID(),'Xenserver', '5.6 SP2', 'CentOS 5 (32-bit)', 111, now(), 0); +INSERT IGNORE INTO `cloud`.`guest_os_hypervisor` (uuid,hypervisor_type, hypervisor_version, guest_os_name, guest_os_id, created, is_user_defined) VALUES (UUID(),'Xenserver', '5.6 SP2', 'CentOS 5 (64-bit)', 112, now(), 0); +INSERT IGNORE INTO `cloud`.`guest_os_hypervisor` (uuid,hypervisor_type, hypervisor_version, guest_os_name, guest_os_id, created, is_user_defined) VALUES (UUID(),'Xenserver', '5.6 SP2', 'Debian Lenny 5.0 (32-bit)', 15, now(), 0); +INSERT IGNORE INTO `cloud`.`guest_os_hypervisor` (uuid,hypervisor_type, hypervisor_version, guest_os_name, guest_os_id, created, is_user_defined) VALUES (UUID(),'Xenserver', '5.6 SP2', 'Debian Squeeze 6.0 (32-bit)', 132, now(), 0); +INSERT IGNORE INTO `cloud`.`guest_os_hypervisor` (uuid,hypervisor_type, hypervisor_version, guest_os_name, guest_os_id, created, is_user_defined) VALUES (UUID(),'Xenserver', '5.6 SP2', 'Debian Squeeze 6.0 (64-bit) (experimental)', 133, now(), 0); +INSERT IGNORE INTO `cloud`.`guest_os_hypervisor` (uuid,hypervisor_type, hypervisor_version, guest_os_name, guest_os_id, created, is_user_defined) VALUES (UUID(),'Xenserver', '5.6 SP2', 'Debian Squeeze 6.0 (32-bit)', 183, now(), 0); +INSERT IGNORE INTO `cloud`.`guest_os_hypervisor` (uuid,hypervisor_type, hypervisor_version, guest_os_name, guest_os_id, created, is_user_defined) VALUES (UUID(),'Xenserver', '5.6 SP2', 'Debian Squeeze 6.0 (64-bit) (experimental)', 184, now(), 0); +INSERT IGNORE INTO `cloud`.`guest_os_hypervisor` (uuid,hypervisor_type, hypervisor_version, guest_os_name, guest_os_id, created, is_user_defined) VALUES (UUID(),'Xenserver', '5.6 SP2', 'Oracle Enterprise Linux 5 (32-bit)', 16, now(), 0); +INSERT IGNORE INTO `cloud`.`guest_os_hypervisor` (uuid,hypervisor_type, hypervisor_version, guest_os_name, guest_os_id, created, is_user_defined) VALUES (UUID(),'Xenserver', '5.6 SP2', 'Oracle Enterprise Linux 5 (64-bit)', 17, now(), 0); +INSERT IGNORE INTO `cloud`.`guest_os_hypervisor` (uuid,hypervisor_type, hypervisor_version, guest_os_name, guest_os_id, created, is_user_defined) VALUES (UUID(),'Xenserver', '5.6 SP2', 'Oracle Enterprise Linux 5 (32-bit)', 18, now(), 0); +INSERT IGNORE INTO `cloud`.`guest_os_hypervisor` (uuid,hypervisor_type, hypervisor_version, guest_os_name, guest_os_id, created, is_user_defined) VALUES (UUID(),'Xenserver', '5.6 SP2', 'Oracle Enterprise Linux 5 (64-bit)', 19, now(), 0); +INSERT IGNORE INTO `cloud`.`guest_os_hypervisor` (uuid,hypervisor_type, hypervisor_version, guest_os_name, guest_os_id, created, is_user_defined) VALUES (UUID(),'Xenserver', '5.6 SP2', 'Oracle Enterprise Linux 5 (32-bit)', 20, now(), 0); +INSERT IGNORE INTO `cloud`.`guest_os_hypervisor` (uuid,hypervisor_type, hypervisor_version, guest_os_name, guest_os_id, created, is_user_defined) VALUES (UUID(),'Xenserver', '5.6 SP2', 'Oracle Enterprise Linux 5 (64-bit)', 21, now(), 0); +INSERT IGNORE INTO `cloud`.`guest_os_hypervisor` (uuid,hypervisor_type, hypervisor_version, guest_os_name, guest_os_id, created, is_user_defined) VALUES (UUID(),'Xenserver', '5.6 SP2', 'Oracle Enterprise Linux 5 (32-bit)', 22, now(), 0); +INSERT IGNORE INTO `cloud`.`guest_os_hypervisor` (uuid,hypervisor_type, hypervisor_version, guest_os_name, guest_os_id, created, is_user_defined) VALUES (UUID(),'Xenserver', '5.6 SP2', 'Oracle Enterprise Linux 5 (64-bit)', 23, now(), 0); +INSERT IGNORE INTO `cloud`.`guest_os_hypervisor` (uuid,hypervisor_type, hypervisor_version, guest_os_name, guest_os_id, created, is_user_defined) VALUES (UUID(),'Xenserver', '5.6 SP2', 'Oracle Enterprise Linux 5 (32-bit)', 24, now(), 0); +INSERT IGNORE INTO `cloud`.`guest_os_hypervisor` (uuid,hypervisor_type, hypervisor_version, guest_os_name, guest_os_id, created, is_user_defined) VALUES (UUID(),'Xenserver', '5.6 SP2', 'Oracle Enterprise Linux 5 (64-bit)', 25, now(), 0); +INSERT IGNORE INTO `cloud`.`guest_os_hypervisor` (uuid,hypervisor_type, hypervisor_version, guest_os_name, guest_os_id, created, is_user_defined) VALUES (UUID(),'Xenserver', '5.6 SP2', 'Oracle Enterprise Linux 5 (32-bit)', 134, now(), 0); +INSERT IGNORE INTO `cloud`.`guest_os_hypervisor` (uuid,hypervisor_type, hypervisor_version, guest_os_name, guest_os_id, created, is_user_defined) VALUES (UUID(),'Xenserver', '5.6 SP2', 'Oracle Enterprise Linux 5 (64-bit)', 135, now(), 0); +INSERT IGNORE INTO `cloud`.`guest_os_hypervisor` (uuid,hypervisor_type, hypervisor_version, guest_os_name, guest_os_id, created, is_user_defined) VALUES (UUID(),'Xenserver', '5.6 SP2', 'Red Hat Enterprise Linux 4.5 (32-bit)', 26, now(), 0); +INSERT IGNORE INTO `cloud`.`guest_os_hypervisor` (uuid,hypervisor_type, hypervisor_version, guest_os_name, guest_os_id, created, is_user_defined) VALUES (UUID(),'Xenserver', '5.6 SP2', 'Red Hat Enterprise Linux 4.6 (32-bit)', 27, now(), 0); +INSERT IGNORE INTO `cloud`.`guest_os_hypervisor` (uuid,hypervisor_type, hypervisor_version, guest_os_name, guest_os_id, created, is_user_defined) VALUES (UUID(),'Xenserver', '5.6 SP2', 'Red Hat Enterprise Linux 4.7 (32-bit)', 28, now(), 0); +INSERT IGNORE INTO `cloud`.`guest_os_hypervisor` (uuid,hypervisor_type, hypervisor_version, guest_os_name, guest_os_id, created, is_user_defined) VALUES (UUID(),'Xenserver', '5.6 SP2', 'Red Hat Enterprise Linux 4.8 (32-bit)', 29, now(), 0); +INSERT IGNORE INTO `cloud`.`guest_os_hypervisor` (uuid,hypervisor_type, hypervisor_version, guest_os_name, guest_os_id, created, is_user_defined) VALUES (UUID(),'Xenserver', '5.6 SP2', 'Red Hat Enterprise Linux 5 (32-bit)', 30, now(), 0); +INSERT IGNORE INTO `cloud`.`guest_os_hypervisor` (uuid,hypervisor_type, hypervisor_version, guest_os_name, guest_os_id, created, is_user_defined) VALUES (UUID(),'Xenserver', '5.6 SP2', 'Red Hat Enterprise Linux 5 (64-bit)', 31, now(), 0); +INSERT IGNORE INTO `cloud`.`guest_os_hypervisor` (uuid,hypervisor_type, hypervisor_version, guest_os_name, guest_os_id, created, is_user_defined) VALUES (UUID(),'Xenserver', '5.6 SP2', 'Red Hat Enterprise Linux 5 (32-bit)', 32, now(), 0); +INSERT IGNORE INTO `cloud`.`guest_os_hypervisor` (uuid,hypervisor_type, hypervisor_version, guest_os_name, guest_os_id, created, is_user_defined) VALUES (UUID(),'Xenserver', '5.6 SP2', 'Red Hat Enterprise Linux 5 (64-bit)', 33, now(), 0); +INSERT IGNORE INTO `cloud`.`guest_os_hypervisor` (uuid,hypervisor_type, hypervisor_version, guest_os_name, guest_os_id, created, is_user_defined) VALUES (UUID(),'Xenserver', '5.6 SP2', 'Red Hat Enterprise Linux 5 (32-bit)', 34, now(), 0); +INSERT IGNORE INTO `cloud`.`guest_os_hypervisor` (uuid,hypervisor_type, hypervisor_version, guest_os_name, guest_os_id, created, is_user_defined) VALUES (UUID(),'Xenserver', '5.6 SP2', 'Red Hat Enterprise Linux 5 (64-bit)', 35, now(), 0); +INSERT IGNORE INTO `cloud`.`guest_os_hypervisor` (uuid,hypervisor_type, hypervisor_version, guest_os_name, guest_os_id, created, is_user_defined) VALUES (UUID(),'Xenserver', '5.6 SP2', 'Red Hat Enterprise Linux 5 (32-bit)', 36, now(), 0); +INSERT IGNORE INTO `cloud`.`guest_os_hypervisor` (uuid,hypervisor_type, hypervisor_version, guest_os_name, guest_os_id, created, is_user_defined) VALUES (UUID(),'Xenserver', '5.6 SP2', 'Red Hat Enterprise Linux 5 (64-bit)', 37, now(), 0); +INSERT IGNORE INTO `cloud`.`guest_os_hypervisor` (uuid,hypervisor_type, hypervisor_version, guest_os_name, guest_os_id, created, is_user_defined) VALUES (UUID(),'Xenserver', '5.6 SP2', 'Red Hat Enterprise Linux 5 (32-bit)', 38, now(), 0); +INSERT IGNORE INTO `cloud`.`guest_os_hypervisor` (uuid,hypervisor_type, hypervisor_version, guest_os_name, guest_os_id, created, is_user_defined) VALUES (UUID(),'Xenserver', '5.6 SP2', 'Red Hat Enterprise Linux 5 (64-bit)', 39, now(), 0); +INSERT IGNORE INTO `cloud`.`guest_os_hypervisor` (uuid,hypervisor_type, hypervisor_version, guest_os_name, guest_os_id, created, is_user_defined) VALUES (UUID(),'Xenserver', '5.6 SP2', 'Red Hat Enterprise Linux 5 (32-bit)', 113, now(), 0); +INSERT IGNORE INTO `cloud`.`guest_os_hypervisor` (uuid,hypervisor_type, hypervisor_version, guest_os_name, guest_os_id, created, is_user_defined) VALUES (UUID(),'Xenserver', '5.6 SP2', 'Red Hat Enterprise Linux 5 (64-bit)', 114, now(), 0); +INSERT IGNORE INTO `cloud`.`guest_os_hypervisor` (uuid,hypervisor_type, hypervisor_version, guest_os_name, guest_os_id, created, is_user_defined) VALUES (UUID(),'Xenserver', '5.6 SP2', 'Red Hat Enterprise Linux 6 (32-bit)', 136, now(), 0); +INSERT IGNORE INTO `cloud`.`guest_os_hypervisor` (uuid,hypervisor_type, hypervisor_version, guest_os_name, guest_os_id, created, is_user_defined) VALUES (UUID(),'Xenserver', '5.6 SP2', 'Red Hat Enterprise Linux 6 (64-bit)', 137, now(), 0); +INSERT IGNORE INTO `cloud`.`guest_os_hypervisor` (uuid,hypervisor_type, hypervisor_version, guest_os_name, guest_os_id, created, is_user_defined) VALUES (UUID(),'Xenserver', '5.6 SP2', 'SUSE Linux Enterprise Server 9 SP4 (32-bit)', 40, now(), 0); +INSERT IGNORE INTO `cloud`.`guest_os_hypervisor` (uuid,hypervisor_type, hypervisor_version, guest_os_name, guest_os_id, created, is_user_defined) VALUES (UUID(),'Xenserver', '5.6 SP2', 'SUSE Linux Enterprise Server 10 SP1 (32-bit)', 41, now(), 0); +INSERT IGNORE INTO `cloud`.`guest_os_hypervisor` (uuid,hypervisor_type, hypervisor_version, guest_os_name, guest_os_id, created, is_user_defined) VALUES (UUID(),'Xenserver', '5.6 SP2', 'SUSE Linux Enterprise Server 10 SP1 (64-bit)', 42, now(), 0); +INSERT IGNORE INTO `cloud`.`guest_os_hypervisor` (uuid,hypervisor_type, hypervisor_version, guest_os_name, guest_os_id, created, is_user_defined) VALUES (UUID(),'Xenserver', '5.6 SP2', 'SUSE Linux Enterprise Server 10 SP2 (32-bit)', 43, now(), 0); +INSERT IGNORE INTO `cloud`.`guest_os_hypervisor` (uuid,hypervisor_type, hypervisor_version, guest_os_name, guest_os_id, created, is_user_defined) VALUES (UUID(),'Xenserver', '5.6 SP2', 'SUSE Linux Enterprise Server 10 SP2 (64-bit)', 44, now(), 0); +INSERT IGNORE INTO `cloud`.`guest_os_hypervisor` (uuid,hypervisor_type, hypervisor_version, guest_os_name, guest_os_id, created, is_user_defined) VALUES (UUID(),'Xenserver', '5.6 SP2', 'SUSE Linux Enterprise Server 10 SP3 (64-bit)', 45, now(), 0); +INSERT IGNORE INTO `cloud`.`guest_os_hypervisor` (uuid,hypervisor_type, hypervisor_version, guest_os_name, guest_os_id, created, is_user_defined) VALUES (UUID(),'Xenserver', '5.6 SP2', 'SUSE Linux Enterprise Server 11 (32-bit)', 46, now(), 0); +INSERT IGNORE INTO `cloud`.`guest_os_hypervisor` (uuid,hypervisor_type, hypervisor_version, guest_os_name, guest_os_id, created, is_user_defined) VALUES (UUID(),'Xenserver', '5.6 SP2', 'SUSE Linux Enterprise Server 11 (64-bit)', 47, now(), 0); +INSERT IGNORE INTO `cloud`.`guest_os_hypervisor` (uuid,hypervisor_type, hypervisor_version, guest_os_name, guest_os_id, created, is_user_defined) VALUES (UUID(),'Xenserver', '5.6 SP2', 'Windows 7 (32-bit)', 48, now(), 0); +INSERT IGNORE INTO `cloud`.`guest_os_hypervisor` (uuid,hypervisor_type, hypervisor_version, guest_os_name, guest_os_id, created, is_user_defined) VALUES (UUID(),'Xenserver', '5.6 SP2', 'Windows 7 (64-bit)', 49, now(), 0); +INSERT IGNORE INTO `cloud`.`guest_os_hypervisor` (uuid,hypervisor_type, hypervisor_version, guest_os_name, guest_os_id, created, is_user_defined) VALUES (UUID(),'Xenserver', '5.6 SP2', 'Windows Server 2008 (32-bit)', 52, now(), 0); +INSERT IGNORE INTO `cloud`.`guest_os_hypervisor` (uuid,hypervisor_type, hypervisor_version, guest_os_name, guest_os_id, created, is_user_defined) VALUES (UUID(),'Xenserver', '5.6 SP2', 'Windows Server 2008 (64-bit)', 53, now(), 0); +INSERT IGNORE INTO `cloud`.`guest_os_hypervisor` (uuid,hypervisor_type, hypervisor_version, guest_os_name, guest_os_id, created, is_user_defined) VALUES (UUID(),'Xenserver', '5.6 SP2', 'Windows Server 2008 R2 (64-bit)', 54, now(), 0); +INSERT IGNORE INTO `cloud`.`guest_os_hypervisor` (uuid,hypervisor_type, hypervisor_version, guest_os_name, guest_os_id, created, is_user_defined) VALUES (UUID(),'Xenserver', '5.6 SP2', 'Windows Vista (32-bit)', 56, now(), 0); +INSERT IGNORE INTO `cloud`.`guest_os_hypervisor` (uuid,hypervisor_type, hypervisor_version, guest_os_name, guest_os_id, created, is_user_defined) VALUES (UUID(),'Xenserver', '5.6 SP2', 'Windows XP SP3 (32-bit)', 58, now(), 0); +INSERT IGNORE INTO `cloud`.`guest_os_hypervisor` (uuid,hypervisor_type, hypervisor_version, guest_os_name, guest_os_id, created, is_user_defined) VALUES (UUID(),'Xenserver', '5.6 SP2', 'Ubuntu Lucid Lynx 10.04 (32-bit) (experimental)', 121, now(), 0); +INSERT IGNORE INTO `cloud`.`guest_os_hypervisor` (uuid,hypervisor_type, hypervisor_version, guest_os_name, guest_os_id, created, is_user_defined) VALUES (UUID(),'Xenserver', '5.6 SP2', 'Ubuntu Lucid Lynx 10.04 (64-bit) (experimental)', 126, now(), 0); +INSERT IGNORE INTO `cloud`.`guest_os_hypervisor` (uuid,hypervisor_type, hypervisor_version, guest_os_name, guest_os_id, created, is_user_defined) VALUES (UUID(),'Xenserver', '5.6 SP2', 'Other install media', 98, now(), 0); +INSERT IGNORE INTO `cloud`.`guest_os_hypervisor` (uuid,hypervisor_type, hypervisor_version, guest_os_name, guest_os_id, created, is_user_defined) VALUES (UUID(),'Xenserver', '5.6 SP2', 'Other install media', 99, now(), 0); +INSERT IGNORE INTO `cloud`.`guest_os_hypervisor` (uuid,hypervisor_type, hypervisor_version, guest_os_name, guest_os_id, created, is_user_defined) VALUES (UUID(),'Xenserver', '5.6 SP2', 'CentOS 5 (32-bit)', 139, now(), 0); +INSERT IGNORE INTO `cloud`.`guest_os_hypervisor` (uuid,hypervisor_type, hypervisor_version, guest_os_name, guest_os_id, created, is_user_defined) VALUES (UUID(),'Xenserver', '5.6 SP2', 'CentOS 5 (64-bit)', 140, now(), 0); +INSERT IGNORE INTO `cloud`.`guest_os_hypervisor` (uuid,hypervisor_type, hypervisor_version, guest_os_name, guest_os_id, created, is_user_defined) VALUES (UUID(),'Xenserver', '6.0', 'CentOS 4.5 (32-bit)', 1, now(), 0); +INSERT IGNORE INTO `cloud`.`guest_os_hypervisor` (uuid,hypervisor_type, hypervisor_version, guest_os_name, guest_os_id, created, is_user_defined) VALUES (UUID(),'Xenserver', '6.0', 'CentOS 4.6 (32-bit)', 2, now(), 0); +INSERT IGNORE INTO `cloud`.`guest_os_hypervisor` (uuid,hypervisor_type, hypervisor_version, guest_os_name, guest_os_id, created, is_user_defined) VALUES (UUID(),'Xenserver', '6.0', 'CentOS 4.7 (32-bit)', 3, now(), 0); +INSERT IGNORE INTO `cloud`.`guest_os_hypervisor` (uuid,hypervisor_type, hypervisor_version, guest_os_name, guest_os_id, created, is_user_defined) VALUES (UUID(),'Xenserver', '6.0', 'CentOS 4.8 (32-bit)', 4, now(), 0); +INSERT IGNORE INTO `cloud`.`guest_os_hypervisor` (uuid,hypervisor_type, hypervisor_version, guest_os_name, guest_os_id, created, is_user_defined) VALUES (UUID(),'Xenserver', '6.0', 'CentOS 5 (32-bit)', 5, now(), 0); +INSERT IGNORE INTO `cloud`.`guest_os_hypervisor` (uuid,hypervisor_type, hypervisor_version, guest_os_name, guest_os_id, created, is_user_defined) VALUES (UUID(),'Xenserver', '6.0', 'CentOS 5 (64-bit)', 6, now(), 0); +INSERT IGNORE INTO `cloud`.`guest_os_hypervisor` (uuid,hypervisor_type, hypervisor_version, guest_os_name, guest_os_id, created, is_user_defined) VALUES (UUID(),'Xenserver', '6.0', 'CentOS 5 (32-bit)', 7, now(), 0); +INSERT IGNORE INTO `cloud`.`guest_os_hypervisor` (uuid,hypervisor_type, hypervisor_version, guest_os_name, guest_os_id, created, is_user_defined) VALUES (UUID(),'Xenserver', '6.0', 'CentOS 5 (64-bit)', 8, now(), 0); +INSERT IGNORE INTO `cloud`.`guest_os_hypervisor` (uuid,hypervisor_type, hypervisor_version, guest_os_name, guest_os_id, created, is_user_defined) VALUES (UUID(),'Xenserver', '6.0', 'CentOS 5 (32-bit)', 9, now(), 0); +INSERT IGNORE INTO `cloud`.`guest_os_hypervisor` (uuid,hypervisor_type, hypervisor_version, guest_os_name, guest_os_id, created, is_user_defined) VALUES (UUID(),'Xenserver', '6.0', 'CentOS 5 (64-bit)', 10, now(), 0); +INSERT IGNORE INTO `cloud`.`guest_os_hypervisor` (uuid,hypervisor_type, hypervisor_version, guest_os_name, guest_os_id, created, is_user_defined) VALUES (UUID(),'Xenserver', '6.0', 'CentOS 5 (32-bit)', 11, now(), 0); +INSERT IGNORE INTO `cloud`.`guest_os_hypervisor` (uuid,hypervisor_type, hypervisor_version, guest_os_name, guest_os_id, created, is_user_defined) VALUES (UUID(),'Xenserver', '6.0', 'CentOS 5 (64-bit)', 12, now(), 0); +INSERT IGNORE INTO `cloud`.`guest_os_hypervisor` (uuid,hypervisor_type, hypervisor_version, guest_os_name, guest_os_id, created, is_user_defined) VALUES (UUID(),'Xenserver', '6.0', 'CentOS 5 (32-bit)', 13, now(), 0); +INSERT IGNORE INTO `cloud`.`guest_os_hypervisor` (uuid,hypervisor_type, hypervisor_version, guest_os_name, guest_os_id, created, is_user_defined) VALUES (UUID(),'Xenserver', '6.0', 'CentOS 5 (64-bit)', 14, now(), 0); +INSERT IGNORE INTO `cloud`.`guest_os_hypervisor` (uuid,hypervisor_type, hypervisor_version, guest_os_name, guest_os_id, created, is_user_defined) VALUES (UUID(),'Xenserver', '6.0', 'CentOS 5 (32-bit)', 111, now(), 0); +INSERT IGNORE INTO `cloud`.`guest_os_hypervisor` (uuid,hypervisor_type, hypervisor_version, guest_os_name, guest_os_id, created, is_user_defined) VALUES (UUID(),'Xenserver', '6.0', 'CentOS 5 (64-bit)', 112, now(), 0); +INSERT IGNORE INTO `cloud`.`guest_os_hypervisor` (uuid,hypervisor_type, hypervisor_version, guest_os_name, guest_os_id, created, is_user_defined) VALUES (UUID(),'Xenserver', '6.0', 'CentOS 5 (32-bit)', 141, now(), 0); +INSERT IGNORE INTO `cloud`.`guest_os_hypervisor` (uuid,hypervisor_type, hypervisor_version, guest_os_name, guest_os_id, created, is_user_defined) VALUES (UUID(),'Xenserver', '6.0', 'CentOS 5 (64-bit)', 142, now(), 0); +INSERT IGNORE INTO `cloud`.`guest_os_hypervisor` (uuid,hypervisor_type, hypervisor_version, guest_os_name, guest_os_id, created, is_user_defined) VALUES (UUID(),'Xenserver', '6.0', 'CentOS 6.0 (32-bit) (experimental)', 143, now(), 0); +INSERT IGNORE INTO `cloud`.`guest_os_hypervisor` (uuid,hypervisor_type, hypervisor_version, guest_os_name, guest_os_id, created, is_user_defined) VALUES (UUID(),'Xenserver', '6.0', 'CentOS 6.0 (64-bit) (experimental)', 144, now(), 0); +INSERT IGNORE INTO `cloud`.`guest_os_hypervisor` (uuid,hypervisor_type, hypervisor_version, guest_os_name, guest_os_id, created, is_user_defined) VALUES (UUID(),'Xenserver', '6.0', 'Debian Lenny 5.0 (32-bit)', 15, now(), 0); +INSERT IGNORE INTO `cloud`.`guest_os_hypervisor` (uuid,hypervisor_type, hypervisor_version, guest_os_name, guest_os_id, created, is_user_defined) VALUES (UUID(),'Xenserver', '6.0', 'Debian Squeeze 6.0 (32-bit)', 132, now(), 0); +INSERT IGNORE INTO `cloud`.`guest_os_hypervisor` (uuid,hypervisor_type, hypervisor_version, guest_os_name, guest_os_id, created, is_user_defined) VALUES (UUID(),'Xenserver', '6.0', 'Debian Squeeze 6.0 (64-bit)', 133, now(), 0); +INSERT IGNORE INTO `cloud`.`guest_os_hypervisor` (uuid,hypervisor_type, hypervisor_version, guest_os_name, guest_os_id, created, is_user_defined) VALUES (UUID(),'Xenserver', '6.0', 'Debian Squeeze 6.0 (32-bit)', 183, now(), 0); +INSERT IGNORE INTO `cloud`.`guest_os_hypervisor` (uuid,hypervisor_type, hypervisor_version, guest_os_name, guest_os_id, created, is_user_defined) VALUES (UUID(),'Xenserver', '6.0', 'Debian Squeeze 6.0 (64-bit)', 184, now(), 0); +INSERT IGNORE INTO `cloud`.`guest_os_hypervisor` (uuid,hypervisor_type, hypervisor_version, guest_os_name, guest_os_id, created, is_user_defined) VALUES (UUID(),'Xenserver', '6.0', 'Oracle Enterprise Linux 5 (32-bit)', 16, now(), 0); +INSERT IGNORE INTO `cloud`.`guest_os_hypervisor` (uuid,hypervisor_type, hypervisor_version, guest_os_name, guest_os_id, created, is_user_defined) VALUES (UUID(),'Xenserver', '6.0', 'Oracle Enterprise Linux 5 (64-bit)', 17, now(), 0); +INSERT IGNORE INTO `cloud`.`guest_os_hypervisor` (uuid,hypervisor_type, hypervisor_version, guest_os_name, guest_os_id, created, is_user_defined) VALUES (UUID(),'Xenserver', '6.0', 'Oracle Enterprise Linux 5 (32-bit)', 18, now(), 0); +INSERT IGNORE INTO `cloud`.`guest_os_hypervisor` (uuid,hypervisor_type, hypervisor_version, guest_os_name, guest_os_id, created, is_user_defined) VALUES (UUID(),'Xenserver', '6.0', 'Oracle Enterprise Linux 5 (64-bit)', 19, now(), 0); +INSERT IGNORE INTO `cloud`.`guest_os_hypervisor` (uuid,hypervisor_type, hypervisor_version, guest_os_name, guest_os_id, created, is_user_defined) VALUES (UUID(),'Xenserver', '6.0', 'Oracle Enterprise Linux 5 (32-bit)', 20, now(), 0); +INSERT IGNORE INTO `cloud`.`guest_os_hypervisor` (uuid,hypervisor_type, hypervisor_version, guest_os_name, guest_os_id, created, is_user_defined) VALUES (UUID(),'Xenserver', '6.0', 'Oracle Enterprise Linux 5 (64-bit)', 21, now(), 0); +INSERT IGNORE INTO `cloud`.`guest_os_hypervisor` (uuid,hypervisor_type, hypervisor_version, guest_os_name, guest_os_id, created, is_user_defined) VALUES (UUID(),'Xenserver', '6.0', 'Oracle Enterprise Linux 5 (32-bit)', 22, now(), 0); +INSERT IGNORE INTO `cloud`.`guest_os_hypervisor` (uuid,hypervisor_type, hypervisor_version, guest_os_name, guest_os_id, created, is_user_defined) VALUES (UUID(),'Xenserver', '6.0', 'Oracle Enterprise Linux 5 (64-bit)', 23, now(), 0); +INSERT IGNORE INTO `cloud`.`guest_os_hypervisor` (uuid,hypervisor_type, hypervisor_version, guest_os_name, guest_os_id, created, is_user_defined) VALUES (UUID(),'Xenserver', '6.0', 'Oracle Enterprise Linux 5 (32-bit)', 24, now(), 0); +INSERT IGNORE INTO `cloud`.`guest_os_hypervisor` (uuid,hypervisor_type, hypervisor_version, guest_os_name, guest_os_id, created, is_user_defined) VALUES (UUID(),'Xenserver', '6.0', 'Oracle Enterprise Linux 5 (64-bit)', 25, now(), 0); +INSERT IGNORE INTO `cloud`.`guest_os_hypervisor` (uuid,hypervisor_type, hypervisor_version, guest_os_name, guest_os_id, created, is_user_defined) VALUES (UUID(),'Xenserver', '6.0', 'Oracle Enterprise Linux 5 (32-bit)', 134, now(), 0); +INSERT IGNORE INTO `cloud`.`guest_os_hypervisor` (uuid,hypervisor_type, hypervisor_version, guest_os_name, guest_os_id, created, is_user_defined) VALUES (UUID(),'Xenserver', '6.0', 'Oracle Enterprise Linux 5 (64-bit)', 135, now(), 0); +INSERT IGNORE INTO `cloud`.`guest_os_hypervisor` (uuid,hypervisor_type, hypervisor_version, guest_os_name, guest_os_id, created, is_user_defined) VALUES (UUID(),'Xenserver', '6.0', 'Oracle Enterprise Linux 5 (32-bit)', 145, now(), 0); +INSERT IGNORE INTO `cloud`.`guest_os_hypervisor` (uuid,hypervisor_type, hypervisor_version, guest_os_name, guest_os_id, created, is_user_defined) VALUES (UUID(),'Xenserver', '6.0', 'Oracle Enterprise Linux 5 (64-bit)', 146, now(), 0); +INSERT IGNORE INTO `cloud`.`guest_os_hypervisor` (uuid,hypervisor_type, hypervisor_version, guest_os_name, guest_os_id, created, is_user_defined) VALUES (UUID(),'Xenserver', '6.0', 'Oracle Enterprise Linux 6.0 (32-bit)', 147, now(), 0); +INSERT IGNORE INTO `cloud`.`guest_os_hypervisor` (uuid,hypervisor_type, hypervisor_version, guest_os_name, guest_os_id, created, is_user_defined) VALUES (UUID(),'Xenserver', '6.0', 'Oracle Enterprise Linux 6.0 (64-bit)', 148, now(), 0); +INSERT IGNORE INTO `cloud`.`guest_os_hypervisor` (uuid,hypervisor_type, hypervisor_version, guest_os_name, guest_os_id, created, is_user_defined) VALUES (UUID(),'Xenserver', '6.0', 'Red Hat Enterprise Linux 4.5 (32-bit)', 26, now(), 0); +INSERT IGNORE INTO `cloud`.`guest_os_hypervisor` (uuid,hypervisor_type, hypervisor_version, guest_os_name, guest_os_id, created, is_user_defined) VALUES (UUID(),'Xenserver', '6.0', 'Red Hat Enterprise Linux 4.6 (32-bit)', 27, now(), 0); +INSERT IGNORE INTO `cloud`.`guest_os_hypervisor` (uuid,hypervisor_type, hypervisor_version, guest_os_name, guest_os_id, created, is_user_defined) VALUES (UUID(),'Xenserver', '6.0', 'Red Hat Enterprise Linux 4.7 (32-bit)', 28, now(), 0); +INSERT IGNORE INTO `cloud`.`guest_os_hypervisor` (uuid,hypervisor_type, hypervisor_version, guest_os_name, guest_os_id, created, is_user_defined) VALUES (UUID(),'Xenserver', '6.0', 'Red Hat Enterprise Linux 4.8 (32-bit)', 29, now(), 0); +INSERT IGNORE INTO `cloud`.`guest_os_hypervisor` (uuid,hypervisor_type, hypervisor_version, guest_os_name, guest_os_id, created, is_user_defined) VALUES (UUID(),'Xenserver', '6.0', 'Red Hat Enterprise Linux 5 (32-bit)', 30, now(), 0); +INSERT IGNORE INTO `cloud`.`guest_os_hypervisor` (uuid,hypervisor_type, hypervisor_version, guest_os_name, guest_os_id, created, is_user_defined) VALUES (UUID(),'Xenserver', '6.0', 'Red Hat Enterprise Linux 5 (64-bit)', 31, now(), 0); +INSERT IGNORE INTO `cloud`.`guest_os_hypervisor` (uuid,hypervisor_type, hypervisor_version, guest_os_name, guest_os_id, created, is_user_defined) VALUES (UUID(),'Xenserver', '6.0', 'Red Hat Enterprise Linux 5 (32-bit)', 32, now(), 0); +INSERT IGNORE INTO `cloud`.`guest_os_hypervisor` (uuid,hypervisor_type, hypervisor_version, guest_os_name, guest_os_id, created, is_user_defined) VALUES (UUID(),'Xenserver', '6.0', 'Red Hat Enterprise Linux 5 (64-bit)', 33, now(), 0); +INSERT IGNORE INTO `cloud`.`guest_os_hypervisor` (uuid,hypervisor_type, hypervisor_version, guest_os_name, guest_os_id, created, is_user_defined) VALUES (UUID(),'Xenserver', '6.0', 'Red Hat Enterprise Linux 5 (32-bit)', 34, now(), 0); +INSERT IGNORE INTO `cloud`.`guest_os_hypervisor` (uuid,hypervisor_type, hypervisor_version, guest_os_name, guest_os_id, created, is_user_defined) VALUES (UUID(),'Xenserver', '6.0', 'Red Hat Enterprise Linux 5 (64-bit)', 35, now(), 0); +INSERT IGNORE INTO `cloud`.`guest_os_hypervisor` (uuid,hypervisor_type, hypervisor_version, guest_os_name, guest_os_id, created, is_user_defined) VALUES (UUID(),'Xenserver', '6.0', 'Red Hat Enterprise Linux 5 (32-bit)', 36, now(), 0); +INSERT IGNORE INTO `cloud`.`guest_os_hypervisor` (uuid,hypervisor_type, hypervisor_version, guest_os_name, guest_os_id, created, is_user_defined) VALUES (UUID(),'Xenserver', '6.0', 'Red Hat Enterprise Linux 5 (64-bit)', 37, now(), 0); +INSERT IGNORE INTO `cloud`.`guest_os_hypervisor` (uuid,hypervisor_type, hypervisor_version, guest_os_name, guest_os_id, created, is_user_defined) VALUES (UUID(),'Xenserver', '6.0', 'Red Hat Enterprise Linux 5 (32-bit)', 38, now(), 0); +INSERT IGNORE INTO `cloud`.`guest_os_hypervisor` (uuid,hypervisor_type, hypervisor_version, guest_os_name, guest_os_id, created, is_user_defined) VALUES (UUID(),'Xenserver', '6.0', 'Red Hat Enterprise Linux 5 (64-bit)', 39, now(), 0); +INSERT IGNORE INTO `cloud`.`guest_os_hypervisor` (uuid,hypervisor_type, hypervisor_version, guest_os_name, guest_os_id, created, is_user_defined) VALUES (UUID(),'Xenserver', '6.0', 'Red Hat Enterprise Linux 5 (32-bit)', 113, now(), 0); +INSERT IGNORE INTO `cloud`.`guest_os_hypervisor` (uuid,hypervisor_type, hypervisor_version, guest_os_name, guest_os_id, created, is_user_defined) VALUES (UUID(),'Xenserver', '6.0', 'Red Hat Enterprise Linux 5 (64-bit)', 114, now(), 0); +INSERT IGNORE INTO `cloud`.`guest_os_hypervisor` (uuid,hypervisor_type, hypervisor_version, guest_os_name, guest_os_id, created, is_user_defined) VALUES (UUID(),'Xenserver', '6.0', 'Red Hat Enterprise Linux 5 (32-bit)', 149, now(), 0); +INSERT IGNORE INTO `cloud`.`guest_os_hypervisor` (uuid,hypervisor_type, hypervisor_version, guest_os_name, guest_os_id, created, is_user_defined) VALUES (UUID(),'Xenserver', '6.0', 'Red Hat Enterprise Linux 5 (64-bit)', 150, now(), 0); +INSERT IGNORE INTO `cloud`.`guest_os_hypervisor` (uuid,hypervisor_type, hypervisor_version, guest_os_name, guest_os_id, created, is_user_defined) VALUES (UUID(),'Xenserver', '6.0', 'Red Hat Enterprise Linux 6.0 (32-bit)', 136, now(), 0); +INSERT IGNORE INTO `cloud`.`guest_os_hypervisor` (uuid,hypervisor_type, hypervisor_version, guest_os_name, guest_os_id, created, is_user_defined) VALUES (UUID(),'Xenserver', '6.0', 'Red Hat Enterprise Linux 6.0 (64-bit)', 137, now(), 0); +INSERT IGNORE INTO `cloud`.`guest_os_hypervisor` (uuid,hypervisor_type, hypervisor_version, guest_os_name, guest_os_id, created, is_user_defined) VALUES (UUID(),'Xenserver', '6.0', 'SUSE Linux Enterprise Server 9 SP4 (32-bit)', 40, now(), 0); +INSERT IGNORE INTO `cloud`.`guest_os_hypervisor` (uuid,hypervisor_type, hypervisor_version, guest_os_name, guest_os_id, created, is_user_defined) VALUES (UUID(),'Xenserver', '6.0', 'SUSE Linux Enterprise Server 10 SP1 (32-bit)', 41, now(), 0); +INSERT IGNORE INTO `cloud`.`guest_os_hypervisor` (uuid,hypervisor_type, hypervisor_version, guest_os_name, guest_os_id, created, is_user_defined) VALUES (UUID(),'Xenserver', '6.0', 'SUSE Linux Enterprise Server 10 SP1 (64-bit)', 42, now(), 0); +INSERT IGNORE INTO `cloud`.`guest_os_hypervisor` (uuid,hypervisor_type, hypervisor_version, guest_os_name, guest_os_id, created, is_user_defined) VALUES (UUID(),'Xenserver', '6.0', 'SUSE Linux Enterprise Server 10 SP2 (32-bit)', 43, now(), 0); +INSERT IGNORE INTO `cloud`.`guest_os_hypervisor` (uuid,hypervisor_type, hypervisor_version, guest_os_name, guest_os_id, created, is_user_defined) VALUES (UUID(),'Xenserver', '6.0', 'SUSE Linux Enterprise Server 10 SP2 (64-bit)', 44, now(), 0); +INSERT IGNORE INTO `cloud`.`guest_os_hypervisor` (uuid,hypervisor_type, hypervisor_version, guest_os_name, guest_os_id, created, is_user_defined) VALUES (UUID(),'Xenserver', '6.0', 'SUSE Linux Enterprise Server 10 SP3 (32-bit)', 151, now(), 0); +INSERT IGNORE INTO `cloud`.`guest_os_hypervisor` (uuid,hypervisor_type, hypervisor_version, guest_os_name, guest_os_id, created, is_user_defined) VALUES (UUID(),'Xenserver', '6.0', 'SUSE Linux Enterprise Server 10 SP3 (64-bit)', 45, now(), 0); +INSERT IGNORE INTO `cloud`.`guest_os_hypervisor` (uuid,hypervisor_type, hypervisor_version, guest_os_name, guest_os_id, created, is_user_defined) VALUES (UUID(),'Xenserver', '6.0', 'SUSE Linux Enterprise Server 10 SP4 (32-bit)', 153, now(), 0); +INSERT IGNORE INTO `cloud`.`guest_os_hypervisor` (uuid,hypervisor_type, hypervisor_version, guest_os_name, guest_os_id, created, is_user_defined) VALUES (UUID(),'Xenserver', '6.0', 'SUSE Linux Enterprise Server 10 SP4 (64-bit)', 152, now(), 0); +INSERT IGNORE INTO `cloud`.`guest_os_hypervisor` (uuid,hypervisor_type, hypervisor_version, guest_os_name, guest_os_id, created, is_user_defined) VALUES (UUID(),'Xenserver', '6.0', 'SUSE Linux Enterprise Server 11 (32-bit)', 46, now(), 0); +INSERT IGNORE INTO `cloud`.`guest_os_hypervisor` (uuid,hypervisor_type, hypervisor_version, guest_os_name, guest_os_id, created, is_user_defined) VALUES (UUID(),'Xenserver', '6.0', 'SUSE Linux Enterprise Server 11 (64-bit)', 47, now(), 0); +INSERT IGNORE INTO `cloud`.`guest_os_hypervisor` (uuid,hypervisor_type, hypervisor_version, guest_os_name, guest_os_id, created, is_user_defined) VALUES (UUID(),'Xenserver', '6.0', 'SUSE Linux Enterprise Server 11 SP1 (32-bit)', 155, now(), 0); +INSERT IGNORE INTO `cloud`.`guest_os_hypervisor` (uuid,hypervisor_type, hypervisor_version, guest_os_name, guest_os_id, created, is_user_defined) VALUES (UUID(),'Xenserver', '6.0', 'SUSE Linux Enterprise Server 11 SP1 (64-bit)', 154, now(), 0); +INSERT IGNORE INTO `cloud`.`guest_os_hypervisor` (uuid,hypervisor_type, hypervisor_version, guest_os_name, guest_os_id, created, is_user_defined) VALUES (UUID(),'Xenserver', '6.0', 'Windows 7 (32-bit)', 48, now(), 0); +INSERT IGNORE INTO `cloud`.`guest_os_hypervisor` (uuid,hypervisor_type, hypervisor_version, guest_os_name, guest_os_id, created, is_user_defined) VALUES (UUID(),'Xenserver', '6.0', 'Windows 7 (64-bit)', 49, now(), 0); +INSERT IGNORE INTO `cloud`.`guest_os_hypervisor` (uuid,hypervisor_type, hypervisor_version, guest_os_name, guest_os_id, created, is_user_defined) VALUES (UUID(),'Xenserver', '6.0', 'Windows Server 2003 (32-bit)', 50, now(), 0); +INSERT IGNORE INTO `cloud`.`guest_os_hypervisor` (uuid,hypervisor_type, hypervisor_version, guest_os_name, guest_os_id, created, is_user_defined) VALUES (UUID(),'Xenserver', '6.0', 'Windows Server 2003 (64-bit)', 51, now(), 0); +INSERT IGNORE INTO `cloud`.`guest_os_hypervisor` (uuid,hypervisor_type, hypervisor_version, guest_os_name, guest_os_id, created, is_user_defined) VALUES (UUID(),'Xenserver', '6.0', 'Windows Server 2003 (32-bit)', 87, now(), 0); +INSERT IGNORE INTO `cloud`.`guest_os_hypervisor` (uuid,hypervisor_type, hypervisor_version, guest_os_name, guest_os_id, created, is_user_defined) VALUES (UUID(),'Xenserver', '6.0', 'Windows Server 2003 (64-bit)', 88, now(), 0); +INSERT IGNORE INTO `cloud`.`guest_os_hypervisor` (uuid,hypervisor_type, hypervisor_version, guest_os_name, guest_os_id, created, is_user_defined) VALUES (UUID(),'Xenserver', '6.0', 'Windows Server 2003 (32-bit)', 89, now(), 0); +INSERT IGNORE INTO `cloud`.`guest_os_hypervisor` (uuid,hypervisor_type, hypervisor_version, guest_os_name, guest_os_id, created, is_user_defined) VALUES (UUID(),'Xenserver', '6.0', 'Windows Server 2003 (64-bit)', 90, now(), 0); +INSERT IGNORE INTO `cloud`.`guest_os_hypervisor` (uuid,hypervisor_type, hypervisor_version, guest_os_name, guest_os_id, created, is_user_defined) VALUES (UUID(),'Xenserver', '6.0', 'Windows Server 2008 (32-bit)', 52, now(), 0); +INSERT IGNORE INTO `cloud`.`guest_os_hypervisor` (uuid,hypervisor_type, hypervisor_version, guest_os_name, guest_os_id, created, is_user_defined) VALUES (UUID(),'Xenserver', '6.0', 'Windows Server 2008 (64-bit)', 53, now(), 0); +INSERT IGNORE INTO `cloud`.`guest_os_hypervisor` (uuid,hypervisor_type, hypervisor_version, guest_os_name, guest_os_id, created, is_user_defined) VALUES (UUID(),'Xenserver', '6.0', 'Windows Server 2008 R2 (64-bit)', 54, now(), 0); +INSERT IGNORE INTO `cloud`.`guest_os_hypervisor` (uuid,hypervisor_type, hypervisor_version, guest_os_name, guest_os_id, created, is_user_defined) VALUES (UUID(),'Xenserver', '6.0', 'Windows Vista (32-bit)', 56, now(), 0); +INSERT IGNORE INTO `cloud`.`guest_os_hypervisor` (uuid,hypervisor_type, hypervisor_version, guest_os_name, guest_os_id, created, is_user_defined) VALUES (UUID(),'Xenserver', '6.0', 'Windows XP SP3 (32-bit)', 58, now(), 0); +INSERT IGNORE INTO `cloud`.`guest_os_hypervisor` (uuid,hypervisor_type, hypervisor_version, guest_os_name, guest_os_id, created, is_user_defined) VALUES (UUID(),'Xenserver', '6.0', 'Ubuntu Lucid Lynx 10.04 (32-bit)', 121, now(), 0); +INSERT IGNORE INTO `cloud`.`guest_os_hypervisor` (uuid,hypervisor_type, hypervisor_version, guest_os_name, guest_os_id, created, is_user_defined) VALUES (UUID(),'Xenserver', '6.0', 'Ubuntu Lucid Lynx 10.04 (64-bit)', 126, now(), 0); +INSERT IGNORE INTO `cloud`.`guest_os_hypervisor` (uuid,hypervisor_type, hypervisor_version, guest_os_name, guest_os_id, created, is_user_defined) VALUES (UUID(),'Xenserver', '6.0', 'Ubuntu Maverick Meerkat 10.10 (32-bit) (experimental)', 156, now(), 0); +INSERT IGNORE INTO `cloud`.`guest_os_hypervisor` (uuid,hypervisor_type, hypervisor_version, guest_os_name, guest_os_id, created, is_user_defined) VALUES (UUID(),'Xenserver', '6.0', 'Ubuntu Maverick Meerkat 10.10 (64-bit) (experimental)', 157, now(), 0); +INSERT IGNORE INTO `cloud`.`guest_os_hypervisor` (uuid,hypervisor_type, hypervisor_version, guest_os_name, guest_os_id, created, is_user_defined) VALUES (UUID(),'Xenserver', '6.0', 'Other install media', 98, now(), 0); +INSERT IGNORE INTO `cloud`.`guest_os_hypervisor` (uuid,hypervisor_type, hypervisor_version, guest_os_name, guest_os_id, created, is_user_defined) VALUES (UUID(),'Xenserver', '6.0', 'Other install media', 99, now(), 0); +INSERT IGNORE INTO `cloud`.`guest_os_hypervisor` (uuid,hypervisor_type, hypervisor_version, guest_os_name, guest_os_id, created, is_user_defined) VALUES (UUID(),'Xenserver', '6.0', 'Other install media', 60, now(), 0); +INSERT IGNORE INTO `cloud`.`guest_os_hypervisor` (uuid,hypervisor_type, hypervisor_version, guest_os_name, guest_os_id, created, is_user_defined) VALUES (UUID(),'Xenserver', '6.0', 'Other install media', 103, now(), 0); +INSERT IGNORE INTO `cloud`.`guest_os_hypervisor` (uuid,hypervisor_type, hypervisor_version, guest_os_name, guest_os_id, created, is_user_defined) VALUES (UUID(),'Xenserver', '6.0', 'Other install media', 200, now(), 0); +INSERT IGNORE INTO `cloud`.`guest_os_hypervisor` (uuid,hypervisor_type, hypervisor_version, guest_os_name, guest_os_id, created, is_user_defined) VALUES (UUID(),'Xenserver', '6.0', 'Other install media', 201, now(), 0); +INSERT IGNORE INTO `cloud`.`guest_os_hypervisor` (uuid,hypervisor_type, hypervisor_version, guest_os_name, guest_os_id, created, is_user_defined) VALUES (UUID(),'Xenserver', '6.0', 'Other install media', 59, now(), 0); +INSERT IGNORE INTO `cloud`.`guest_os_hypervisor` (uuid,hypervisor_type, hypervisor_version, guest_os_name, guest_os_id, created, is_user_defined) VALUES (UUID(),'Xenserver', '6.0', 'Other install media', 100, now(), 0); +INSERT IGNORE INTO `cloud`.`guest_os_hypervisor` (uuid,hypervisor_type, hypervisor_version, guest_os_name, guest_os_id, created, is_user_defined) VALUES (UUID(),'Xenserver', '6.0', 'Other install media', 202, now(), 0); +INSERT IGNORE INTO `cloud`.`guest_os_hypervisor` (uuid,hypervisor_type, hypervisor_version, guest_os_name, guest_os_id, created, is_user_defined) VALUES (UUID(),'Xenserver', '6.0', 'Other install media', 203, now(), 0); +INSERT IGNORE INTO `cloud`.`guest_os_hypervisor` (uuid,hypervisor_type, hypervisor_version, guest_os_name, guest_os_id, created, is_user_defined) VALUES (UUID(),'Xenserver', '6.0', 'CentOS 5 (32-bit)', 139, now(), 0); +INSERT IGNORE INTO `cloud`.`guest_os_hypervisor` (uuid,hypervisor_type, hypervisor_version, guest_os_name, guest_os_id, created, is_user_defined) VALUES (UUID(),'Xenserver', '6.0', 'CentOS 5 (64-bit)', 140, now(), 0); +INSERT IGNORE INTO `cloud`.`guest_os_hypervisor` (uuid,hypervisor_type, hypervisor_version, guest_os_name, guest_os_id, created, is_user_defined) VALUES (UUID(),'Xenserver', '6.0.2', 'CentOS 4.5 (32-bit)', 1, now(), 0); +INSERT IGNORE INTO `cloud`.`guest_os_hypervisor` (uuid,hypervisor_type, hypervisor_version, guest_os_name, guest_os_id, created, is_user_defined) VALUES (UUID(),'Xenserver', '6.0.2', 'CentOS 4.6 (32-bit)', 2, now(), 0); +INSERT IGNORE INTO `cloud`.`guest_os_hypervisor` (uuid,hypervisor_type, hypervisor_version, guest_os_name, guest_os_id, created, is_user_defined) VALUES (UUID(),'Xenserver', '6.0.2', 'CentOS 4.7 (32-bit)', 3, now(), 0); +INSERT IGNORE INTO `cloud`.`guest_os_hypervisor` (uuid,hypervisor_type, hypervisor_version, guest_os_name, guest_os_id, created, is_user_defined) VALUES (UUID(),'Xenserver', '6.0.2', 'CentOS 4.8 (32-bit)', 4, now(), 0); +INSERT IGNORE INTO `cloud`.`guest_os_hypervisor` (uuid,hypervisor_type, hypervisor_version, guest_os_name, guest_os_id, created, is_user_defined) VALUES (UUID(),'Xenserver', '6.0.2', 'CentOS 5 (32-bit)', 5, now(), 0); +INSERT IGNORE INTO `cloud`.`guest_os_hypervisor` (uuid,hypervisor_type, hypervisor_version, guest_os_name, guest_os_id, created, is_user_defined) VALUES (UUID(),'Xenserver', '6.0.2', 'CentOS 5 (64-bit)', 6, now(), 0); +INSERT IGNORE INTO `cloud`.`guest_os_hypervisor` (uuid,hypervisor_type, hypervisor_version, guest_os_name, guest_os_id, created, is_user_defined) VALUES (UUID(),'Xenserver', '6.0.2', 'CentOS 5 (32-bit)', 7, now(), 0); +INSERT IGNORE INTO `cloud`.`guest_os_hypervisor` (uuid,hypervisor_type, hypervisor_version, guest_os_name, guest_os_id, created, is_user_defined) VALUES (UUID(),'Xenserver', '6.0.2', 'CentOS 5 (64-bit)', 8, now(), 0); +INSERT IGNORE INTO `cloud`.`guest_os_hypervisor` (uuid,hypervisor_type, hypervisor_version, guest_os_name, guest_os_id, created, is_user_defined) VALUES (UUID(),'Xenserver', '6.0.2', 'CentOS 5 (32-bit)', 9, now(), 0); +INSERT IGNORE INTO `cloud`.`guest_os_hypervisor` (uuid,hypervisor_type, hypervisor_version, guest_os_name, guest_os_id, created, is_user_defined) VALUES (UUID(),'Xenserver', '6.0.2', 'CentOS 5 (64-bit)', 10, now(), 0); +INSERT IGNORE INTO `cloud`.`guest_os_hypervisor` (uuid,hypervisor_type, hypervisor_version, guest_os_name, guest_os_id, created, is_user_defined) VALUES (UUID(),'Xenserver', '6.0.2', 'CentOS 5 (32-bit)', 11, now(), 0); +INSERT IGNORE INTO `cloud`.`guest_os_hypervisor` (uuid,hypervisor_type, hypervisor_version, guest_os_name, guest_os_id, created, is_user_defined) VALUES (UUID(),'Xenserver', '6.0.2', 'CentOS 5 (64-bit)', 12, now(), 0); +INSERT IGNORE INTO `cloud`.`guest_os_hypervisor` (uuid,hypervisor_type, hypervisor_version, guest_os_name, guest_os_id, created, is_user_defined) VALUES (UUID(),'Xenserver', '6.0.2', 'CentOS 5 (32-bit)', 13, now(), 0); +INSERT IGNORE INTO `cloud`.`guest_os_hypervisor` (uuid,hypervisor_type, hypervisor_version, guest_os_name, guest_os_id, created, is_user_defined) VALUES (UUID(),'Xenserver', '6.0.2', 'CentOS 5 (64-bit)', 14, now(), 0); +INSERT IGNORE INTO `cloud`.`guest_os_hypervisor` (uuid,hypervisor_type, hypervisor_version, guest_os_name, guest_os_id, created, is_user_defined) VALUES (UUID(),'Xenserver', '6.0.2', 'CentOS 5 (32-bit)', 111, now(), 0); +INSERT IGNORE INTO `cloud`.`guest_os_hypervisor` (uuid,hypervisor_type, hypervisor_version, guest_os_name, guest_os_id, created, is_user_defined) VALUES (UUID(),'Xenserver', '6.0.2', 'CentOS 5 (64-bit)', 112, now(), 0); +INSERT IGNORE INTO `cloud`.`guest_os_hypervisor` (uuid,hypervisor_type, hypervisor_version, guest_os_name, guest_os_id, created, is_user_defined) VALUES (UUID(),'Xenserver', '6.0.2', 'CentOS 5 (32-bit)', 141, now(), 0); +INSERT IGNORE INTO `cloud`.`guest_os_hypervisor` (uuid,hypervisor_type, hypervisor_version, guest_os_name, guest_os_id, created, is_user_defined) VALUES (UUID(),'Xenserver', '6.0.2', 'CentOS 5 (64-bit)', 142, now(), 0); +INSERT IGNORE INTO `cloud`.`guest_os_hypervisor` (uuid,hypervisor_type, hypervisor_version, guest_os_name, guest_os_id, created, is_user_defined) VALUES (UUID(),'Xenserver', '6.0.2', 'CentOS 5 (32-bit)', 161, now(), 0); +INSERT IGNORE INTO `cloud`.`guest_os_hypervisor` (uuid,hypervisor_type, hypervisor_version, guest_os_name, guest_os_id, created, is_user_defined) VALUES (UUID(),'Xenserver', '6.0.2', 'CentOS 5 (64-bit)', 162, now(), 0); +INSERT IGNORE INTO `cloud`.`guest_os_hypervisor` (uuid,hypervisor_type, hypervisor_version, guest_os_name, guest_os_id, created, is_user_defined) VALUES (UUID(),'Xenserver', '6.0.2', 'CentOS 6.0 (32-bit)', 143, now(), 0); +INSERT IGNORE INTO `cloud`.`guest_os_hypervisor` (uuid,hypervisor_type, hypervisor_version, guest_os_name, guest_os_id, created, is_user_defined) VALUES (UUID(),'Xenserver', '6.0.2', 'CentOS 6.0 (64-bit)', 144, now(), 0); +INSERT IGNORE INTO `cloud`.`guest_os_hypervisor` (uuid,hypervisor_type, hypervisor_version, guest_os_name, guest_os_id, created, is_user_defined) VALUES (UUID(),'Xenserver', '6.0.2', 'Debian Lenny 5.0 (32-bit)', 15, now(), 0); +INSERT IGNORE INTO `cloud`.`guest_os_hypervisor` (uuid,hypervisor_type, hypervisor_version, guest_os_name, guest_os_id, created, is_user_defined) VALUES (UUID(),'Xenserver', '6.0.2', 'Debian Squeeze 6.0 (32-bit)', 132, now(), 0); +INSERT IGNORE INTO `cloud`.`guest_os_hypervisor` (uuid,hypervisor_type, hypervisor_version, guest_os_name, guest_os_id, created, is_user_defined) VALUES (UUID(),'Xenserver', '6.0.2', 'Debian Squeeze 6.0 (64-bit)', 133, now(), 0); +INSERT IGNORE INTO `cloud`.`guest_os_hypervisor` (uuid,hypervisor_type, hypervisor_version, guest_os_name, guest_os_id, created, is_user_defined) VALUES (UUID(),'Xenserver', '6.0.2', 'Debian Squeeze 6.0 (32-bit)', 183, now(), 0); +INSERT IGNORE INTO `cloud`.`guest_os_hypervisor` (uuid,hypervisor_type, hypervisor_version, guest_os_name, guest_os_id, created, is_user_defined) VALUES (UUID(),'Xenserver', '6.0.2', 'Debian Squeeze 6.0 (64-bit)', 184, now(), 0); +INSERT IGNORE INTO `cloud`.`guest_os_hypervisor` (uuid,hypervisor_type, hypervisor_version, guest_os_name, guest_os_id, created, is_user_defined) VALUES (UUID(),'Xenserver', '6.0.2', 'Oracle Enterprise Linux 5 (32-bit)', 16, now(), 0); +INSERT IGNORE INTO `cloud`.`guest_os_hypervisor` (uuid,hypervisor_type, hypervisor_version, guest_os_name, guest_os_id, created, is_user_defined) VALUES (UUID(),'Xenserver', '6.0.2', 'Oracle Enterprise Linux 5 (64-bit)', 17, now(), 0); +INSERT IGNORE INTO `cloud`.`guest_os_hypervisor` (uuid,hypervisor_type, hypervisor_version, guest_os_name, guest_os_id, created, is_user_defined) VALUES (UUID(),'Xenserver', '6.0.2', 'Oracle Enterprise Linux 5 (32-bit)', 18, now(), 0); +INSERT IGNORE INTO `cloud`.`guest_os_hypervisor` (uuid,hypervisor_type, hypervisor_version, guest_os_name, guest_os_id, created, is_user_defined) VALUES (UUID(),'Xenserver', '6.0.2', 'Oracle Enterprise Linux 5 (64-bit)', 19, now(), 0); +INSERT IGNORE INTO `cloud`.`guest_os_hypervisor` (uuid,hypervisor_type, hypervisor_version, guest_os_name, guest_os_id, created, is_user_defined) VALUES (UUID(),'Xenserver', '6.0.2', 'Oracle Enterprise Linux 5 (32-bit)', 20, now(), 0); +INSERT IGNORE INTO `cloud`.`guest_os_hypervisor` (uuid,hypervisor_type, hypervisor_version, guest_os_name, guest_os_id, created, is_user_defined) VALUES (UUID(),'Xenserver', '6.0.2', 'Oracle Enterprise Linux 5 (64-bit)', 21, now(), 0); +INSERT IGNORE INTO `cloud`.`guest_os_hypervisor` (uuid,hypervisor_type, hypervisor_version, guest_os_name, guest_os_id, created, is_user_defined) VALUES (UUID(),'Xenserver', '6.0.2', 'Oracle Enterprise Linux 5 (32-bit)', 22, now(), 0); +INSERT IGNORE INTO `cloud`.`guest_os_hypervisor` (uuid,hypervisor_type, hypervisor_version, guest_os_name, guest_os_id, created, is_user_defined) VALUES (UUID(),'Xenserver', '6.0.2', 'Oracle Enterprise Linux 5 (64-bit)', 23, now(), 0); +INSERT IGNORE INTO `cloud`.`guest_os_hypervisor` (uuid,hypervisor_type, hypervisor_version, guest_os_name, guest_os_id, created, is_user_defined) VALUES (UUID(),'Xenserver', '6.0.2', 'Oracle Enterprise Linux 5 (32-bit)', 24, now(), 0); +INSERT IGNORE INTO `cloud`.`guest_os_hypervisor` (uuid,hypervisor_type, hypervisor_version, guest_os_name, guest_os_id, created, is_user_defined) VALUES (UUID(),'Xenserver', '6.0.2', 'Oracle Enterprise Linux 5 (64-bit)', 25, now(), 0); +INSERT IGNORE INTO `cloud`.`guest_os_hypervisor` (uuid,hypervisor_type, hypervisor_version, guest_os_name, guest_os_id, created, is_user_defined) VALUES (UUID(),'Xenserver', '6.0.2', 'Oracle Enterprise Linux 5 (32-bit)', 134, now(), 0); +INSERT IGNORE INTO `cloud`.`guest_os_hypervisor` (uuid,hypervisor_type, hypervisor_version, guest_os_name, guest_os_id, created, is_user_defined) VALUES (UUID(),'Xenserver', '6.0.2', 'Oracle Enterprise Linux 5 (64-bit)', 135, now(), 0); +INSERT IGNORE INTO `cloud`.`guest_os_hypervisor` (uuid,hypervisor_type, hypervisor_version, guest_os_name, guest_os_id, created, is_user_defined) VALUES (UUID(),'Xenserver', '6.0.2', 'Oracle Enterprise Linux 5 (32-bit)', 145, now(), 0); +INSERT IGNORE INTO `cloud`.`guest_os_hypervisor` (uuid,hypervisor_type, hypervisor_version, guest_os_name, guest_os_id, created, is_user_defined) VALUES (UUID(),'Xenserver', '6.0.2', 'Oracle Enterprise Linux 5 (64-bit)', 146, now(), 0); +INSERT IGNORE INTO `cloud`.`guest_os_hypervisor` (uuid,hypervisor_type, hypervisor_version, guest_os_name, guest_os_id, created, is_user_defined) VALUES (UUID(),'Xenserver', '6.0.2', 'Oracle Enterprise Linux 5 (32-bit)', 207, now(), 0); +INSERT IGNORE INTO `cloud`.`guest_os_hypervisor` (uuid,hypervisor_type, hypervisor_version, guest_os_name, guest_os_id, created, is_user_defined) VALUES (UUID(),'Xenserver', '6.0.2', 'Oracle Enterprise Linux 5 (64-bit)', 208, now(), 0); +INSERT IGNORE INTO `cloud`.`guest_os_hypervisor` (uuid,hypervisor_type, hypervisor_version, guest_os_name, guest_os_id, created, is_user_defined) VALUES (UUID(),'Xenserver', '6.0.2', 'Oracle Enterprise Linux 6.0 (32-bit)', 147, now(), 0); +INSERT IGNORE INTO `cloud`.`guest_os_hypervisor` (uuid,hypervisor_type, hypervisor_version, guest_os_name, guest_os_id, created, is_user_defined) VALUES (UUID(),'Xenserver', '6.0.2', 'Oracle Enterprise Linux 6.0 (64-bit)', 148, now(), 0); +INSERT IGNORE INTO `cloud`.`guest_os_hypervisor` (uuid,hypervisor_type, hypervisor_version, guest_os_name, guest_os_id, created, is_user_defined) VALUES (UUID(),'Xenserver', '6.0.2', 'Red Hat Enterprise Linux 4.5 (32-bit)', 26, now(), 0); +INSERT IGNORE INTO `cloud`.`guest_os_hypervisor` (uuid,hypervisor_type, hypervisor_version, guest_os_name, guest_os_id, created, is_user_defined) VALUES (UUID(),'Xenserver', '6.0.2', 'Red Hat Enterprise Linux 4.6 (32-bit)', 27, now(), 0); +INSERT IGNORE INTO `cloud`.`guest_os_hypervisor` (uuid,hypervisor_type, hypervisor_version, guest_os_name, guest_os_id, created, is_user_defined) VALUES (UUID(),'Xenserver', '6.0.2', 'Red Hat Enterprise Linux 4.7 (32-bit)', 28, now(), 0); +INSERT IGNORE INTO `cloud`.`guest_os_hypervisor` (uuid,hypervisor_type, hypervisor_version, guest_os_name, guest_os_id, created, is_user_defined) VALUES (UUID(),'Xenserver', '6.0.2', 'Red Hat Enterprise Linux 4.8 (32-bit)', 29, now(), 0); +INSERT IGNORE INTO `cloud`.`guest_os_hypervisor` (uuid,hypervisor_type, hypervisor_version, guest_os_name, guest_os_id, created, is_user_defined) VALUES (UUID(),'Xenserver', '6.0.2', 'Red Hat Enterprise Linux 5 (32-bit)', 30, now(), 0); +INSERT IGNORE INTO `cloud`.`guest_os_hypervisor` (uuid,hypervisor_type, hypervisor_version, guest_os_name, guest_os_id, created, is_user_defined) VALUES (UUID(),'Xenserver', '6.0.2', 'Red Hat Enterprise Linux 5 (64-bit)', 31, now(), 0); +INSERT IGNORE INTO `cloud`.`guest_os_hypervisor` (uuid,hypervisor_type, hypervisor_version, guest_os_name, guest_os_id, created, is_user_defined) VALUES (UUID(),'Xenserver', '6.0.2', 'Red Hat Enterprise Linux 5 (32-bit)', 32, now(), 0); +INSERT IGNORE INTO `cloud`.`guest_os_hypervisor` (uuid,hypervisor_type, hypervisor_version, guest_os_name, guest_os_id, created, is_user_defined) VALUES (UUID(),'Xenserver', '6.0.2', 'Red Hat Enterprise Linux 5 (64-bit)', 33, now(), 0); +INSERT IGNORE INTO `cloud`.`guest_os_hypervisor` (uuid,hypervisor_type, hypervisor_version, guest_os_name, guest_os_id, created, is_user_defined) VALUES (UUID(),'Xenserver', '6.0.2', 'Red Hat Enterprise Linux 5 (32-bit)', 34, now(), 0); +INSERT IGNORE INTO `cloud`.`guest_os_hypervisor` (uuid,hypervisor_type, hypervisor_version, guest_os_name, guest_os_id, created, is_user_defined) VALUES (UUID(),'Xenserver', '6.0.2', 'Red Hat Enterprise Linux 5 (64-bit)', 35, now(), 0); +INSERT IGNORE INTO `cloud`.`guest_os_hypervisor` (uuid,hypervisor_type, hypervisor_version, guest_os_name, guest_os_id, created, is_user_defined) VALUES (UUID(),'Xenserver', '6.0.2', 'Red Hat Enterprise Linux 5 (32-bit)', 36, now(), 0); +INSERT IGNORE INTO `cloud`.`guest_os_hypervisor` (uuid,hypervisor_type, hypervisor_version, guest_os_name, guest_os_id, created, is_user_defined) VALUES (UUID(),'Xenserver', '6.0.2', 'Red Hat Enterprise Linux 5 (64-bit)', 37, now(), 0); +INSERT IGNORE INTO `cloud`.`guest_os_hypervisor` (uuid,hypervisor_type, hypervisor_version, guest_os_name, guest_os_id, created, is_user_defined) VALUES (UUID(),'Xenserver', '6.0.2', 'Red Hat Enterprise Linux 5 (32-bit)', 38, now(), 0); +INSERT IGNORE INTO `cloud`.`guest_os_hypervisor` (uuid,hypervisor_type, hypervisor_version, guest_os_name, guest_os_id, created, is_user_defined) VALUES (UUID(),'Xenserver', '6.0.2', 'Red Hat Enterprise Linux 5 (64-bit)', 39, now(), 0); +INSERT IGNORE INTO `cloud`.`guest_os_hypervisor` (uuid,hypervisor_type, hypervisor_version, guest_os_name, guest_os_id, created, is_user_defined) VALUES (UUID(),'Xenserver', '6.0.2', 'Red Hat Enterprise Linux 5 (32-bit)', 113, now(), 0); +INSERT IGNORE INTO `cloud`.`guest_os_hypervisor` (uuid,hypervisor_type, hypervisor_version, guest_os_name, guest_os_id, created, is_user_defined) VALUES (UUID(),'Xenserver', '6.0.2', 'Red Hat Enterprise Linux 5 (64-bit)', 114, now(), 0); +INSERT IGNORE INTO `cloud`.`guest_os_hypervisor` (uuid,hypervisor_type, hypervisor_version, guest_os_name, guest_os_id, created, is_user_defined) VALUES (UUID(),'Xenserver', '6.0.2', 'Red Hat Enterprise Linux 5 (32-bit)', 149, now(), 0); +INSERT IGNORE INTO `cloud`.`guest_os_hypervisor` (uuid,hypervisor_type, hypervisor_version, guest_os_name, guest_os_id, created, is_user_defined) VALUES (UUID(),'Xenserver', '6.0.2', 'Red Hat Enterprise Linux 5 (64-bit)', 150, now(), 0); +INSERT IGNORE INTO `cloud`.`guest_os_hypervisor` (uuid,hypervisor_type, hypervisor_version, guest_os_name, guest_os_id, created, is_user_defined) VALUES (UUID(),'Xenserver', '6.0.2', 'Red Hat Enterprise Linux 5 (32-bit)', 189, now(), 0); +INSERT IGNORE INTO `cloud`.`guest_os_hypervisor` (uuid,hypervisor_type, hypervisor_version, guest_os_name, guest_os_id, created, is_user_defined) VALUES (UUID(),'Xenserver', '6.0.2', 'Red Hat Enterprise Linux 5 (64-bit)', 190, now(), 0); +INSERT IGNORE INTO `cloud`.`guest_os_hypervisor` (uuid,hypervisor_type, hypervisor_version, guest_os_name, guest_os_id, created, is_user_defined) VALUES (UUID(),'Xenserver', '6.0.2', 'Red Hat Enterprise Linux 6.0 (32-bit)', 136, now(), 0); +INSERT IGNORE INTO `cloud`.`guest_os_hypervisor` (uuid,hypervisor_type, hypervisor_version, guest_os_name, guest_os_id, created, is_user_defined) VALUES (UUID(),'Xenserver', '6.0.2', 'Red Hat Enterprise Linux 6.0 (64-bit)', 137, now(), 0); +INSERT IGNORE INTO `cloud`.`guest_os_hypervisor` (uuid,hypervisor_type, hypervisor_version, guest_os_name, guest_os_id, created, is_user_defined) VALUES (UUID(),'Xenserver', '6.0.2', 'SUSE Linux Enterprise Server 10 SP1 (32-bit)', 40, now(), 0); +INSERT IGNORE INTO `cloud`.`guest_os_hypervisor` (uuid,hypervisor_type, hypervisor_version, guest_os_name, guest_os_id, created, is_user_defined) VALUES (UUID(),'Xenserver', '6.0.2', 'SUSE Linux Enterprise Server 10 SP1 (32-bit)', 41, now(), 0); +INSERT IGNORE INTO `cloud`.`guest_os_hypervisor` (uuid,hypervisor_type, hypervisor_version, guest_os_name, guest_os_id, created, is_user_defined) VALUES (UUID(),'Xenserver', '6.0.2', 'SUSE Linux Enterprise Server 10 SP1 (64-bit)', 42, now(), 0); +INSERT IGNORE INTO `cloud`.`guest_os_hypervisor` (uuid,hypervisor_type, hypervisor_version, guest_os_name, guest_os_id, created, is_user_defined) VALUES (UUID(),'Xenserver', '6.0.2', 'SUSE Linux Enterprise Server 10 SP2 (32-bit)', 43, now(), 0); +INSERT IGNORE INTO `cloud`.`guest_os_hypervisor` (uuid,hypervisor_type, hypervisor_version, guest_os_name, guest_os_id, created, is_user_defined) VALUES (UUID(),'Xenserver', '6.0.2', 'SUSE Linux Enterprise Server 10 SP2 (64-bit)', 44, now(), 0); +INSERT IGNORE INTO `cloud`.`guest_os_hypervisor` (uuid,hypervisor_type, hypervisor_version, guest_os_name, guest_os_id, created, is_user_defined) VALUES (UUID(),'Xenserver', '6.0.2', 'SUSE Linux Enterprise Server 10 SP3 (32-bit)', 151, now(), 0); +INSERT IGNORE INTO `cloud`.`guest_os_hypervisor` (uuid,hypervisor_type, hypervisor_version, guest_os_name, guest_os_id, created, is_user_defined) VALUES (UUID(),'Xenserver', '6.0.2', 'SUSE Linux Enterprise Server 10 SP3 (64-bit)', 45, now(), 0); +INSERT IGNORE INTO `cloud`.`guest_os_hypervisor` (uuid,hypervisor_type, hypervisor_version, guest_os_name, guest_os_id, created, is_user_defined) VALUES (UUID(),'Xenserver', '6.0.2', 'SUSE Linux Enterprise Server 10 SP4 (32-bit)', 153, now(), 0); +INSERT IGNORE INTO `cloud`.`guest_os_hypervisor` (uuid,hypervisor_type, hypervisor_version, guest_os_name, guest_os_id, created, is_user_defined) VALUES (UUID(),'Xenserver', '6.0.2', 'SUSE Linux Enterprise Server 10 SP4 (64-bit)', 152, now(), 0); +INSERT IGNORE INTO `cloud`.`guest_os_hypervisor` (uuid,hypervisor_type, hypervisor_version, guest_os_name, guest_os_id, created, is_user_defined) VALUES (UUID(),'Xenserver', '6.0.2', 'SUSE Linux Enterprise Server 11 (32-bit)', 46, now(), 0); +INSERT IGNORE INTO `cloud`.`guest_os_hypervisor` (uuid,hypervisor_type, hypervisor_version, guest_os_name, guest_os_id, created, is_user_defined) VALUES (UUID(),'Xenserver', '6.0.2', 'SUSE Linux Enterprise Server 11 (64-bit)', 47, now(), 0); +INSERT IGNORE INTO `cloud`.`guest_os_hypervisor` (uuid,hypervisor_type, hypervisor_version, guest_os_name, guest_os_id, created, is_user_defined) VALUES (UUID(),'Xenserver', '6.0.2', 'SUSE Linux Enterprise Server 11 SP1 (32-bit)', 155, now(), 0); +INSERT IGNORE INTO `cloud`.`guest_os_hypervisor` (uuid,hypervisor_type, hypervisor_version, guest_os_name, guest_os_id, created, is_user_defined) VALUES (UUID(),'Xenserver', '6.0.2', 'SUSE Linux Enterprise Server 11 SP1 (64-bit)', 154, now(), 0); +INSERT IGNORE INTO `cloud`.`guest_os_hypervisor` (uuid,hypervisor_type, hypervisor_version, guest_os_name, guest_os_id, created, is_user_defined) VALUES (UUID(),'Xenserver', '6.0.2', 'Windows 7 (32-bit)', 48, now(), 0); +INSERT IGNORE INTO `cloud`.`guest_os_hypervisor` (uuid,hypervisor_type, hypervisor_version, guest_os_name, guest_os_id, created, is_user_defined) VALUES (UUID(),'Xenserver', '6.0.2', 'Windows 7 (64-bit)', 49, now(), 0); +INSERT IGNORE INTO `cloud`.`guest_os_hypervisor` (uuid,hypervisor_type, hypervisor_version, guest_os_name, guest_os_id, created, is_user_defined) VALUES (UUID(),'Xenserver', '6.0.2', 'Windows 8 (32-bit) (experimental)', 165, now(), 0); +INSERT IGNORE INTO `cloud`.`guest_os_hypervisor` (uuid,hypervisor_type, hypervisor_version, guest_os_name, guest_os_id, created, is_user_defined) VALUES (UUID(),'Xenserver', '6.0.2', 'Windows 8 (64-bit) (experimental)', 166, now(), 0); +INSERT IGNORE INTO `cloud`.`guest_os_hypervisor` (uuid,hypervisor_type, hypervisor_version, guest_os_name, guest_os_id, created, is_user_defined) VALUES (UUID(),'Xenserver', '6.0.2', 'Windows Server 2003 (32-bit)', 50, now(), 0); +INSERT IGNORE INTO `cloud`.`guest_os_hypervisor` (uuid,hypervisor_type, hypervisor_version, guest_os_name, guest_os_id, created, is_user_defined) VALUES (UUID(),'Xenserver', '6.0.2', 'Windows Server 2003 (64-bit)', 51, now(), 0); +INSERT IGNORE INTO `cloud`.`guest_os_hypervisor` (uuid,hypervisor_type, hypervisor_version, guest_os_name, guest_os_id, created, is_user_defined) VALUES (UUID(),'Xenserver', '6.0.2', 'Windows Server 2003 (32-bit)', 87, now(), 0); +INSERT IGNORE INTO `cloud`.`guest_os_hypervisor` (uuid,hypervisor_type, hypervisor_version, guest_os_name, guest_os_id, created, is_user_defined) VALUES (UUID(),'Xenserver', '6.0.2', 'Windows Server 2003 (64-bit)', 88, now(), 0); +INSERT IGNORE INTO `cloud`.`guest_os_hypervisor` (uuid,hypervisor_type, hypervisor_version, guest_os_name, guest_os_id, created, is_user_defined) VALUES (UUID(),'Xenserver', '6.0.2', 'Windows Server 2003 (32-bit)', 89, now(), 0); +INSERT IGNORE INTO `cloud`.`guest_os_hypervisor` (uuid,hypervisor_type, hypervisor_version, guest_os_name, guest_os_id, created, is_user_defined) VALUES (UUID(),'Xenserver', '6.0.2', 'Windows Server 2003 (64-bit)', 90, now(), 0); +INSERT IGNORE INTO `cloud`.`guest_os_hypervisor` (uuid,hypervisor_type, hypervisor_version, guest_os_name, guest_os_id, created, is_user_defined) VALUES (UUID(),'Xenserver', '6.0.2', 'Windows Server 2008 (32-bit)', 52, now(), 0); +INSERT IGNORE INTO `cloud`.`guest_os_hypervisor` (uuid,hypervisor_type, hypervisor_version, guest_os_name, guest_os_id, created, is_user_defined) VALUES (UUID(),'Xenserver', '6.0.2', 'Windows Server 2008 (64-bit)', 53, now(), 0); +INSERT IGNORE INTO `cloud`.`guest_os_hypervisor` (uuid,hypervisor_type, hypervisor_version, guest_os_name, guest_os_id, created, is_user_defined) VALUES (UUID(),'Xenserver', '6.0.2', 'Windows Server 2008 R2 (64-bit)', 54, now(), 0); +INSERT IGNORE INTO `cloud`.`guest_os_hypervisor` (uuid,hypervisor_type, hypervisor_version, guest_os_name, guest_os_id, created, is_user_defined) VALUES (UUID(),'Xenserver', '6.0.2', 'Windows Vista (32-bit)', 56, now(), 0); +INSERT IGNORE INTO `cloud`.`guest_os_hypervisor` (uuid,hypervisor_type, hypervisor_version, guest_os_name, guest_os_id, created, is_user_defined) VALUES (UUID(),'Xenserver', '6.0.2', 'Windows XP SP3 (32-bit)', 58, now(), 0); +INSERT IGNORE INTO `cloud`.`guest_os_hypervisor` (uuid,hypervisor_type, hypervisor_version, guest_os_name, guest_os_id, created, is_user_defined) VALUES (UUID(),'Xenserver', '6.0.2', 'Ubuntu Lucid Lynx 10.04 (32-bit)', 121, now(), 0); +INSERT IGNORE INTO `cloud`.`guest_os_hypervisor` (uuid,hypervisor_type, hypervisor_version, guest_os_name, guest_os_id, created, is_user_defined) VALUES (UUID(),'Xenserver', '6.0.2', 'Ubuntu Lucid Lynx 10.04 (64-bit)', 126, now(), 0); +INSERT IGNORE INTO `cloud`.`guest_os_hypervisor` (uuid,hypervisor_type, hypervisor_version, guest_os_name, guest_os_id, created, is_user_defined) VALUES (UUID(),'Xenserver', '6.0.2', 'Ubuntu Maverick Meerkat 10.10 (32-bit) (experimental)', 156, now(), 0); +INSERT IGNORE INTO `cloud`.`guest_os_hypervisor` (uuid,hypervisor_type, hypervisor_version, guest_os_name, guest_os_id, created, is_user_defined) VALUES (UUID(),'Xenserver', '6.0.2', 'Ubuntu Maverick Meerkat 10.10 (64-bit) (experimental)', 157, now(), 0); +INSERT IGNORE INTO `cloud`.`guest_os_hypervisor` (uuid,hypervisor_type, hypervisor_version, guest_os_name, guest_os_id, created, is_user_defined) VALUES (UUID(),'Xenserver', '6.0.2', 'Other install media', 98, now(), 0); +INSERT IGNORE INTO `cloud`.`guest_os_hypervisor` (uuid,hypervisor_type, hypervisor_version, guest_os_name, guest_os_id, created, is_user_defined) VALUES (UUID(),'Xenserver', '6.0.2', 'Other install media', 99, now(), 0); +INSERT IGNORE INTO `cloud`.`guest_os_hypervisor` (uuid,hypervisor_type, hypervisor_version, guest_os_name, guest_os_id, created, is_user_defined) VALUES (UUID(),'Xenserver', '6.0.2', 'Other install media', 60, now(), 0); +INSERT IGNORE INTO `cloud`.`guest_os_hypervisor` (uuid,hypervisor_type, hypervisor_version, guest_os_name, guest_os_id, created, is_user_defined) VALUES (UUID(),'Xenserver', '6.0.2', 'Other install media', 103, now(), 0); +INSERT IGNORE INTO `cloud`.`guest_os_hypervisor` (uuid,hypervisor_type, hypervisor_version, guest_os_name, guest_os_id, created, is_user_defined) VALUES (UUID(),'Xenserver', '6.0.2', 'Other install media', 200, now(), 0); +INSERT IGNORE INTO `cloud`.`guest_os_hypervisor` (uuid,hypervisor_type, hypervisor_version, guest_os_name, guest_os_id, created, is_user_defined) VALUES (UUID(),'Xenserver', '6.0.2', 'Other install media', 201, now(), 0); +INSERT IGNORE INTO `cloud`.`guest_os_hypervisor` (uuid,hypervisor_type, hypervisor_version, guest_os_name, guest_os_id, created, is_user_defined) VALUES (UUID(),'Xenserver', '6.0.2', 'Other install media', 59, now(), 0); +INSERT IGNORE INTO `cloud`.`guest_os_hypervisor` (uuid,hypervisor_type, hypervisor_version, guest_os_name, guest_os_id, created, is_user_defined) VALUES (UUID(),'Xenserver', '6.0.2', 'Other install media', 100, now(), 0); +INSERT IGNORE INTO `cloud`.`guest_os_hypervisor` (uuid,hypervisor_type, hypervisor_version, guest_os_name, guest_os_id, created, is_user_defined) VALUES (UUID(),'Xenserver', '6.0.2', 'Other install media', 202, now(), 0); +INSERT IGNORE INTO `cloud`.`guest_os_hypervisor` (uuid,hypervisor_type, hypervisor_version, guest_os_name, guest_os_id, created, is_user_defined) VALUES (UUID(),'Xenserver', '6.0.2', 'Other install media', 203, now(), 0); +INSERT IGNORE INTO `cloud`.`guest_os_hypervisor` (uuid,hypervisor_type, hypervisor_version, guest_os_name, guest_os_id, created, is_user_defined) VALUES (UUID(),'Xenserver', '6.0.2', 'CentOS 5 (32-bit)', 139, now(), 0); +INSERT IGNORE INTO `cloud`.`guest_os_hypervisor` (uuid,hypervisor_type, hypervisor_version, guest_os_name, guest_os_id, created, is_user_defined) VALUES (UUID(),'Xenserver', '6.0.2', 'CentOS 5 (64-bit)', 140, now(), 0); +INSERT IGNORE INTO `cloud`.`guest_os_hypervisor` (uuid,hypervisor_type, hypervisor_version, guest_os_name, guest_os_id, created, is_user_defined) VALUES (UUID(),'Xenserver', '6.1.0', 'CentOS 4.5 (32-bit)', 1, now(), 0); +INSERT IGNORE INTO `cloud`.`guest_os_hypervisor` (uuid,hypervisor_type, hypervisor_version, guest_os_name, guest_os_id, created, is_user_defined) VALUES (UUID(),'Xenserver', '6.1.0', 'CentOS 4.6 (32-bit)', 2, now(), 0); +INSERT IGNORE INTO `cloud`.`guest_os_hypervisor` (uuid,hypervisor_type, hypervisor_version, guest_os_name, guest_os_id, created, is_user_defined) VALUES (UUID(),'Xenserver', '6.1.0', 'CentOS 4.7 (32-bit)', 3, now(), 0); +INSERT IGNORE INTO `cloud`.`guest_os_hypervisor` (uuid,hypervisor_type, hypervisor_version, guest_os_name, guest_os_id, created, is_user_defined) VALUES (UUID(),'Xenserver', '6.1.0', 'CentOS 4.8 (32-bit)', 4, now(), 0); +INSERT IGNORE INTO `cloud`.`guest_os_hypervisor` (uuid,hypervisor_type, hypervisor_version, guest_os_name, guest_os_id, created, is_user_defined) VALUES (UUID(),'Xenserver', '6.1.0', 'CentOS 5 (32-bit)', 5, now(), 0); +INSERT IGNORE INTO `cloud`.`guest_os_hypervisor` (uuid,hypervisor_type, hypervisor_version, guest_os_name, guest_os_id, created, is_user_defined) VALUES (UUID(),'Xenserver', '6.1.0', 'CentOS 5 (64-bit)', 6, now(), 0); +INSERT IGNORE INTO `cloud`.`guest_os_hypervisor` (uuid,hypervisor_type, hypervisor_version, guest_os_name, guest_os_id, created, is_user_defined) VALUES (UUID(),'Xenserver', '6.1.0', 'CentOS 5 (32-bit)', 7, now(), 0); +INSERT IGNORE INTO `cloud`.`guest_os_hypervisor` (uuid,hypervisor_type, hypervisor_version, guest_os_name, guest_os_id, created, is_user_defined) VALUES (UUID(),'Xenserver', '6.1.0', 'CentOS 5 (64-bit)', 8, now(), 0); +INSERT IGNORE INTO `cloud`.`guest_os_hypervisor` (uuid,hypervisor_type, hypervisor_version, guest_os_name, guest_os_id, created, is_user_defined) VALUES (UUID(),'Xenserver', '6.1.0', 'CentOS 5 (32-bit)', 9, now(), 0); +INSERT IGNORE INTO `cloud`.`guest_os_hypervisor` (uuid,hypervisor_type, hypervisor_version, guest_os_name, guest_os_id, created, is_user_defined) VALUES (UUID(),'Xenserver', '6.1.0', 'CentOS 5 (64-bit)', 10, now(), 0); +INSERT IGNORE INTO `cloud`.`guest_os_hypervisor` (uuid,hypervisor_type, hypervisor_version, guest_os_name, guest_os_id, created, is_user_defined) VALUES (UUID(),'Xenserver', '6.1.0', 'CentOS 5 (32-bit)', 11, now(), 0); +INSERT IGNORE INTO `cloud`.`guest_os_hypervisor` (uuid,hypervisor_type, hypervisor_version, guest_os_name, guest_os_id, created, is_user_defined) VALUES (UUID(),'Xenserver', '6.1.0', 'CentOS 5 (64-bit)', 12, now(), 0); +INSERT IGNORE INTO `cloud`.`guest_os_hypervisor` (uuid,hypervisor_type, hypervisor_version, guest_os_name, guest_os_id, created, is_user_defined) VALUES (UUID(),'Xenserver', '6.1.0', 'CentOS 5 (32-bit)', 13, now(), 0); +INSERT IGNORE INTO `cloud`.`guest_os_hypervisor` (uuid,hypervisor_type, hypervisor_version, guest_os_name, guest_os_id, created, is_user_defined) VALUES (UUID(),'Xenserver', '6.1.0', 'CentOS 5 (64-bit)', 14, now(), 0); +INSERT IGNORE INTO `cloud`.`guest_os_hypervisor` (uuid,hypervisor_type, hypervisor_version, guest_os_name, guest_os_id, created, is_user_defined) VALUES (UUID(),'Xenserver', '6.1.0', 'CentOS 5 (32-bit)', 111, now(), 0); +INSERT IGNORE INTO `cloud`.`guest_os_hypervisor` (uuid,hypervisor_type, hypervisor_version, guest_os_name, guest_os_id, created, is_user_defined) VALUES (UUID(),'Xenserver', '6.1.0', 'CentOS 5 (64-bit)', 112, now(), 0); +INSERT IGNORE INTO `cloud`.`guest_os_hypervisor` (uuid,hypervisor_type, hypervisor_version, guest_os_name, guest_os_id, created, is_user_defined) VALUES (UUID(),'Xenserver', '6.1.0', 'CentOS 5 (32-bit)', 141, now(), 0); +INSERT IGNORE INTO `cloud`.`guest_os_hypervisor` (uuid,hypervisor_type, hypervisor_version, guest_os_name, guest_os_id, created, is_user_defined) VALUES (UUID(),'Xenserver', '6.1.0', 'CentOS 5 (64-bit)', 142, now(), 0); +INSERT IGNORE INTO `cloud`.`guest_os_hypervisor` (uuid,hypervisor_type, hypervisor_version, guest_os_name, guest_os_id, created, is_user_defined) VALUES (UUID(),'Xenserver', '6.1.0', 'CentOS 5 (32-bit)', 161, now(), 0); +INSERT IGNORE INTO `cloud`.`guest_os_hypervisor` (uuid,hypervisor_type, hypervisor_version, guest_os_name, guest_os_id, created, is_user_defined) VALUES (UUID(),'Xenserver', '6.1.0', 'CentOS 5 (64-bit)', 162, now(), 0); +INSERT IGNORE INTO `cloud`.`guest_os_hypervisor` (uuid,hypervisor_type, hypervisor_version, guest_os_name, guest_os_id, created, is_user_defined) VALUES (UUID(),'Xenserver', '6.1.0', 'CentOS 6 (32-bit)', 143, now(), 0); +INSERT IGNORE INTO `cloud`.`guest_os_hypervisor` (uuid,hypervisor_type, hypervisor_version, guest_os_name, guest_os_id, created, is_user_defined) VALUES (UUID(),'Xenserver', '6.1.0', 'CentOS 6 (64-bit)', 144, now(), 0); +INSERT IGNORE INTO `cloud`.`guest_os_hypervisor` (uuid,hypervisor_type, hypervisor_version, guest_os_name, guest_os_id, created, is_user_defined) VALUES (UUID(),'Xenserver', '6.1.0', 'CentOS 6 (32-bit)', 177, now(), 0); +INSERT IGNORE INTO `cloud`.`guest_os_hypervisor` (uuid,hypervisor_type, hypervisor_version, guest_os_name, guest_os_id, created, is_user_defined) VALUES (UUID(),'Xenserver', '6.1.0', 'CentOS 6 (64-bit)', 178, now(), 0); +INSERT IGNORE INTO `cloud`.`guest_os_hypervisor` (uuid,hypervisor_type, hypervisor_version, guest_os_name, guest_os_id, created, is_user_defined) VALUES (UUID(),'Xenserver', '6.1.0', 'CentOS 6 (32-bit)', 179, now(), 0); +INSERT IGNORE INTO `cloud`.`guest_os_hypervisor` (uuid,hypervisor_type, hypervisor_version, guest_os_name, guest_os_id, created, is_user_defined) VALUES (UUID(),'Xenserver', '6.1.0', 'CentOS 6 (64-bit)', 180, now(), 0); +INSERT IGNORE INTO `cloud`.`guest_os_hypervisor` (uuid,hypervisor_type, hypervisor_version, guest_os_name, guest_os_id, created, is_user_defined) VALUES (UUID(),'Xenserver', '6.1.0', 'CentOS 6 (32-bit)', 171, now(), 0); +INSERT IGNORE INTO `cloud`.`guest_os_hypervisor` (uuid,hypervisor_type, hypervisor_version, guest_os_name, guest_os_id, created, is_user_defined) VALUES (UUID(),'Xenserver', '6.1.0', 'CentOS 6 (64-bit)', 172, now(), 0); +INSERT IGNORE INTO `cloud`.`guest_os_hypervisor` (uuid,hypervisor_type, hypervisor_version, guest_os_name, guest_os_id, created, is_user_defined) VALUES (UUID(),'Xenserver', '6.1.0', 'Debian Squeeze 6.0 (32-bit)', 132, now(), 0); +INSERT IGNORE INTO `cloud`.`guest_os_hypervisor` (uuid,hypervisor_type, hypervisor_version, guest_os_name, guest_os_id, created, is_user_defined) VALUES (UUID(),'Xenserver', '6.1.0', 'Debian Squeeze 6.0 (64-bit)', 133, now(), 0); +INSERT IGNORE INTO `cloud`.`guest_os_hypervisor` (uuid,hypervisor_type, hypervisor_version, guest_os_name, guest_os_id, created, is_user_defined) VALUES (UUID(),'Xenserver', '6.1.0', 'Debian Squeeze 6.0 (32-bit)', 183, now(), 0); +INSERT IGNORE INTO `cloud`.`guest_os_hypervisor` (uuid,hypervisor_type, hypervisor_version, guest_os_name, guest_os_id, created, is_user_defined) VALUES (UUID(),'Xenserver', '6.1.0', 'Debian Squeeze 6.0 (64-bit)', 184, now(), 0); +INSERT IGNORE INTO `cloud`.`guest_os_hypervisor` (uuid,hypervisor_type, hypervisor_version, guest_os_name, guest_os_id, created, is_user_defined) VALUES (UUID(),'Xenserver', '6.1.0', 'Oracle Enterprise Linux 5 (32-bit)', 16, now(), 0); +INSERT IGNORE INTO `cloud`.`guest_os_hypervisor` (uuid,hypervisor_type, hypervisor_version, guest_os_name, guest_os_id, created, is_user_defined) VALUES (UUID(),'Xenserver', '6.1.0', 'Oracle Enterprise Linux 5 (64-bit)', 17, now(), 0); +INSERT IGNORE INTO `cloud`.`guest_os_hypervisor` (uuid,hypervisor_type, hypervisor_version, guest_os_name, guest_os_id, created, is_user_defined) VALUES (UUID(),'Xenserver', '6.1.0', 'Oracle Enterprise Linux 5 (32-bit)', 18, now(), 0); +INSERT IGNORE INTO `cloud`.`guest_os_hypervisor` (uuid,hypervisor_type, hypervisor_version, guest_os_name, guest_os_id, created, is_user_defined) VALUES (UUID(),'Xenserver', '6.1.0', 'Oracle Enterprise Linux 5 (64-bit)', 19, now(), 0); +INSERT IGNORE INTO `cloud`.`guest_os_hypervisor` (uuid,hypervisor_type, hypervisor_version, guest_os_name, guest_os_id, created, is_user_defined) VALUES (UUID(),'Xenserver', '6.1.0', 'Oracle Enterprise Linux 5 (32-bit)', 20, now(), 0); +INSERT IGNORE INTO `cloud`.`guest_os_hypervisor` (uuid,hypervisor_type, hypervisor_version, guest_os_name, guest_os_id, created, is_user_defined) VALUES (UUID(),'Xenserver', '6.1.0', 'Oracle Enterprise Linux 5 (64-bit)', 21, now(), 0); +INSERT IGNORE INTO `cloud`.`guest_os_hypervisor` (uuid,hypervisor_type, hypervisor_version, guest_os_name, guest_os_id, created, is_user_defined) VALUES (UUID(),'Xenserver', '6.1.0', 'Oracle Enterprise Linux 5 (32-bit)', 22, now(), 0); +INSERT IGNORE INTO `cloud`.`guest_os_hypervisor` (uuid,hypervisor_type, hypervisor_version, guest_os_name, guest_os_id, created, is_user_defined) VALUES (UUID(),'Xenserver', '6.1.0', 'Oracle Enterprise Linux 5 (64-bit)', 23, now(), 0); +INSERT IGNORE INTO `cloud`.`guest_os_hypervisor` (uuid,hypervisor_type, hypervisor_version, guest_os_name, guest_os_id, created, is_user_defined) VALUES (UUID(),'Xenserver', '6.1.0', 'Oracle Enterprise Linux 5 (32-bit)', 24, now(), 0); +INSERT IGNORE INTO `cloud`.`guest_os_hypervisor` (uuid,hypervisor_type, hypervisor_version, guest_os_name, guest_os_id, created, is_user_defined) VALUES (UUID(),'Xenserver', '6.1.0', 'Oracle Enterprise Linux 5 (64-bit)', 25, now(), 0); +INSERT IGNORE INTO `cloud`.`guest_os_hypervisor` (uuid,hypervisor_type, hypervisor_version, guest_os_name, guest_os_id, created, is_user_defined) VALUES (UUID(),'Xenserver', '6.1.0', 'Oracle Enterprise Linux 5 (32-bit)', 134, now(), 0); +INSERT IGNORE INTO `cloud`.`guest_os_hypervisor` (uuid,hypervisor_type, hypervisor_version, guest_os_name, guest_os_id, created, is_user_defined) VALUES (UUID(),'Xenserver', '6.1.0', 'Oracle Enterprise Linux 5 (64-bit)', 135, now(), 0); +INSERT IGNORE INTO `cloud`.`guest_os_hypervisor` (uuid,hypervisor_type, hypervisor_version, guest_os_name, guest_os_id, created, is_user_defined) VALUES (UUID(),'Xenserver', '6.1.0', 'Oracle Enterprise Linux 5 (32-bit)', 145, now(), 0); +INSERT IGNORE INTO `cloud`.`guest_os_hypervisor` (uuid,hypervisor_type, hypervisor_version, guest_os_name, guest_os_id, created, is_user_defined) VALUES (UUID(),'Xenserver', '6.1.0', 'Oracle Enterprise Linux 5 (64-bit)', 146, now(), 0); +INSERT IGNORE INTO `cloud`.`guest_os_hypervisor` (uuid,hypervisor_type, hypervisor_version, guest_os_name, guest_os_id, created, is_user_defined) VALUES (UUID(),'Xenserver', '6.1.0', 'Oracle Enterprise Linux 5 (32-bit)', 207, now(), 0); +INSERT IGNORE INTO `cloud`.`guest_os_hypervisor` (uuid,hypervisor_type, hypervisor_version, guest_os_name, guest_os_id, created, is_user_defined) VALUES (UUID(),'Xenserver', '6.1.0', 'Oracle Enterprise Linux 5 (64-bit)', 208, now(), 0); +INSERT IGNORE INTO `cloud`.`guest_os_hypervisor` (uuid,hypervisor_type, hypervisor_version, guest_os_name, guest_os_id, created, is_user_defined) VALUES (UUID(),'Xenserver', '6.1.0', 'Oracle Enterprise Linux 6 (32-bit)', 147, now(), 0); +INSERT IGNORE INTO `cloud`.`guest_os_hypervisor` (uuid,hypervisor_type, hypervisor_version, guest_os_name, guest_os_id, created, is_user_defined) VALUES (UUID(),'Xenserver', '6.1.0', 'Oracle Enterprise Linux 6 (64-bit)', 148, now(), 0); +INSERT IGNORE INTO `cloud`.`guest_os_hypervisor` (uuid,hypervisor_type, hypervisor_version, guest_os_name, guest_os_id, created, is_user_defined) VALUES (UUID(),'Xenserver', '6.1.0', 'Oracle Enterprise Linux 6 (32-bit)', 213, now(), 0); +INSERT IGNORE INTO `cloud`.`guest_os_hypervisor` (uuid,hypervisor_type, hypervisor_version, guest_os_name, guest_os_id, created, is_user_defined) VALUES (UUID(),'Xenserver', '6.1.0', 'Oracle Enterprise Linux 6 (64-bit)', 214, now(), 0); +INSERT IGNORE INTO `cloud`.`guest_os_hypervisor` (uuid,hypervisor_type, hypervisor_version, guest_os_name, guest_os_id, created, is_user_defined) VALUES (UUID(),'Xenserver', '6.1.0', 'Oracle Enterprise Linux 6 (32-bit)', 215, now(), 0); +INSERT IGNORE INTO `cloud`.`guest_os_hypervisor` (uuid,hypervisor_type, hypervisor_version, guest_os_name, guest_os_id, created, is_user_defined) VALUES (UUID(),'Xenserver', '6.1.0', 'Oracle Enterprise Linux 6 (64-bit)', 216, now(), 0); +INSERT IGNORE INTO `cloud`.`guest_os_hypervisor` (uuid,hypervisor_type, hypervisor_version, guest_os_name, guest_os_id, created, is_user_defined) VALUES (UUID(),'Xenserver', '6.1.0', 'Red Hat Enterprise Linux 4.5 (32-bit)', 26, now(), 0); +INSERT IGNORE INTO `cloud`.`guest_os_hypervisor` (uuid,hypervisor_type, hypervisor_version, guest_os_name, guest_os_id, created, is_user_defined) VALUES (UUID(),'Xenserver', '6.1.0', 'Red Hat Enterprise Linux 4.6 (32-bit)', 27, now(), 0); +INSERT IGNORE INTO `cloud`.`guest_os_hypervisor` (uuid,hypervisor_type, hypervisor_version, guest_os_name, guest_os_id, created, is_user_defined) VALUES (UUID(),'Xenserver', '6.1.0', 'Red Hat Enterprise Linux 4.7 (32-bit)', 28, now(), 0); +INSERT IGNORE INTO `cloud`.`guest_os_hypervisor` (uuid,hypervisor_type, hypervisor_version, guest_os_name, guest_os_id, created, is_user_defined) VALUES (UUID(),'Xenserver', '6.1.0', 'Red Hat Enterprise Linux 4.8 (32-bit)', 29, now(), 0); +INSERT IGNORE INTO `cloud`.`guest_os_hypervisor` (uuid,hypervisor_type, hypervisor_version, guest_os_name, guest_os_id, created, is_user_defined) VALUES (UUID(),'Xenserver', '6.1.0', 'Red Hat Enterprise Linux 5 (32-bit)', 30, now(), 0); +INSERT IGNORE INTO `cloud`.`guest_os_hypervisor` (uuid,hypervisor_type, hypervisor_version, guest_os_name, guest_os_id, created, is_user_defined) VALUES (UUID(),'Xenserver', '6.1.0', 'Red Hat Enterprise Linux 5 (64-bit)', 31, now(), 0); +INSERT IGNORE INTO `cloud`.`guest_os_hypervisor` (uuid,hypervisor_type, hypervisor_version, guest_os_name, guest_os_id, created, is_user_defined) VALUES (UUID(),'Xenserver', '6.1.0', 'Red Hat Enterprise Linux 5 (32-bit)', 32, now(), 0); +INSERT IGNORE INTO `cloud`.`guest_os_hypervisor` (uuid,hypervisor_type, hypervisor_version, guest_os_name, guest_os_id, created, is_user_defined) VALUES (UUID(),'Xenserver', '6.1.0', 'Red Hat Enterprise Linux 5 (64-bit)', 33, now(), 0); +INSERT IGNORE INTO `cloud`.`guest_os_hypervisor` (uuid,hypervisor_type, hypervisor_version, guest_os_name, guest_os_id, created, is_user_defined) VALUES (UUID(),'Xenserver', '6.1.0', 'Red Hat Enterprise Linux 5 (32-bit)', 34, now(), 0); +INSERT IGNORE INTO `cloud`.`guest_os_hypervisor` (uuid,hypervisor_type, hypervisor_version, guest_os_name, guest_os_id, created, is_user_defined) VALUES (UUID(),'Xenserver', '6.1.0', 'Red Hat Enterprise Linux 5 (64-bit)', 35, now(), 0); +INSERT IGNORE INTO `cloud`.`guest_os_hypervisor` (uuid,hypervisor_type, hypervisor_version, guest_os_name, guest_os_id, created, is_user_defined) VALUES (UUID(),'Xenserver', '6.1.0', 'Red Hat Enterprise Linux 5 (32-bit)', 36, now(), 0); +INSERT IGNORE INTO `cloud`.`guest_os_hypervisor` (uuid,hypervisor_type, hypervisor_version, guest_os_name, guest_os_id, created, is_user_defined) VALUES (UUID(),'Xenserver', '6.1.0', 'Red Hat Enterprise Linux 5 (64-bit)', 37, now(), 0); +INSERT IGNORE INTO `cloud`.`guest_os_hypervisor` (uuid,hypervisor_type, hypervisor_version, guest_os_name, guest_os_id, created, is_user_defined) VALUES (UUID(),'Xenserver', '6.1.0', 'Red Hat Enterprise Linux 5 (32-bit)', 38, now(), 0); +INSERT IGNORE INTO `cloud`.`guest_os_hypervisor` (uuid,hypervisor_type, hypervisor_version, guest_os_name, guest_os_id, created, is_user_defined) VALUES (UUID(),'Xenserver', '6.1.0', 'Red Hat Enterprise Linux 5 (64-bit)', 39, now(), 0); +INSERT IGNORE INTO `cloud`.`guest_os_hypervisor` (uuid,hypervisor_type, hypervisor_version, guest_os_name, guest_os_id, created, is_user_defined) VALUES (UUID(),'Xenserver', '6.1.0', 'Red Hat Enterprise Linux 5 (32-bit)', 113, now(), 0); +INSERT IGNORE INTO `cloud`.`guest_os_hypervisor` (uuid,hypervisor_type, hypervisor_version, guest_os_name, guest_os_id, created, is_user_defined) VALUES (UUID(),'Xenserver', '6.1.0', 'Red Hat Enterprise Linux 5 (64-bit)', 114, now(), 0); +INSERT IGNORE INTO `cloud`.`guest_os_hypervisor` (uuid,hypervisor_type, hypervisor_version, guest_os_name, guest_os_id, created, is_user_defined) VALUES (UUID(),'Xenserver', '6.1.0', 'Red Hat Enterprise Linux 5 (32-bit)', 149, now(), 0); +INSERT IGNORE INTO `cloud`.`guest_os_hypervisor` (uuid,hypervisor_type, hypervisor_version, guest_os_name, guest_os_id, created, is_user_defined) VALUES (UUID(),'Xenserver', '6.1.0', 'Red Hat Enterprise Linux 5 (64-bit)', 150, now(), 0); +INSERT IGNORE INTO `cloud`.`guest_os_hypervisor` (uuid,hypervisor_type, hypervisor_version, guest_os_name, guest_os_id, created, is_user_defined) VALUES (UUID(),'Xenserver', '6.1.0', 'Red Hat Enterprise Linux 5 (32-bit)', 189, now(), 0); +INSERT IGNORE INTO `cloud`.`guest_os_hypervisor` (uuid,hypervisor_type, hypervisor_version, guest_os_name, guest_os_id, created, is_user_defined) VALUES (UUID(),'Xenserver', '6.1.0', 'Red Hat Enterprise Linux 5 (64-bit)', 190, now(), 0); +INSERT IGNORE INTO `cloud`.`guest_os_hypervisor` (uuid,hypervisor_type, hypervisor_version, guest_os_name, guest_os_id, created, is_user_defined) VALUES (UUID(),'Xenserver', '6.1.0', 'Red Hat Enterprise Linux 6 (32-bit)', 136, now(), 0); +INSERT IGNORE INTO `cloud`.`guest_os_hypervisor` (uuid,hypervisor_type, hypervisor_version, guest_os_name, guest_os_id, created, is_user_defined) VALUES (UUID(),'Xenserver', '6.1.0', 'Red Hat Enterprise Linux 6 (64-bit)', 137, now(), 0); +INSERT IGNORE INTO `cloud`.`guest_os_hypervisor` (uuid,hypervisor_type, hypervisor_version, guest_os_name, guest_os_id, created, is_user_defined) VALUES (UUID(),'Xenserver', '6.1.0', 'Red Hat Enterprise Linux 6 (32-bit)', 195, now(), 0); +INSERT IGNORE INTO `cloud`.`guest_os_hypervisor` (uuid,hypervisor_type, hypervisor_version, guest_os_name, guest_os_id, created, is_user_defined) VALUES (UUID(),'Xenserver', '6.1.0', 'Red Hat Enterprise Linux 6 (64-bit)', 196, now(), 0); +INSERT IGNORE INTO `cloud`.`guest_os_hypervisor` (uuid,hypervisor_type, hypervisor_version, guest_os_name, guest_os_id, created, is_user_defined) VALUES (UUID(),'Xenserver', '6.1.0', 'Red Hat Enterprise Linux 6 (32-bit)', 197, now(), 0); +INSERT IGNORE INTO `cloud`.`guest_os_hypervisor` (uuid,hypervisor_type, hypervisor_version, guest_os_name, guest_os_id, created, is_user_defined) VALUES (UUID(),'Xenserver', '6.1.0', 'Red Hat Enterprise Linux 6 (64-bit)', 198, now(), 0); +INSERT IGNORE INTO `cloud`.`guest_os_hypervisor` (uuid,hypervisor_type, hypervisor_version, guest_os_name, guest_os_id, created, is_user_defined) VALUES (UUID(),'Xenserver', '6.1.0', 'SUSE Linux Enterprise Server 10 SP1 (32-bit)', 40, now(), 0); +INSERT IGNORE INTO `cloud`.`guest_os_hypervisor` (uuid,hypervisor_type, hypervisor_version, guest_os_name, guest_os_id, created, is_user_defined) VALUES (UUID(),'Xenserver', '6.1.0', 'SUSE Linux Enterprise Server 10 SP1 (32-bit)', 41, now(), 0); +INSERT IGNORE INTO `cloud`.`guest_os_hypervisor` (uuid,hypervisor_type, hypervisor_version, guest_os_name, guest_os_id, created, is_user_defined) VALUES (UUID(),'Xenserver', '6.1.0', 'SUSE Linux Enterprise Server 10 SP1 (64-bit)', 42, now(), 0); +INSERT IGNORE INTO `cloud`.`guest_os_hypervisor` (uuid,hypervisor_type, hypervisor_version, guest_os_name, guest_os_id, created, is_user_defined) VALUES (UUID(),'Xenserver', '6.1.0', 'SUSE Linux Enterprise Server 10 SP2 (32-bit)', 43, now(), 0); +INSERT IGNORE INTO `cloud`.`guest_os_hypervisor` (uuid,hypervisor_type, hypervisor_version, guest_os_name, guest_os_id, created, is_user_defined) VALUES (UUID(),'Xenserver', '6.1.0', 'SUSE Linux Enterprise Server 10 SP2 (64-bit)', 44, now(), 0); +INSERT IGNORE INTO `cloud`.`guest_os_hypervisor` (uuid,hypervisor_type, hypervisor_version, guest_os_name, guest_os_id, created, is_user_defined) VALUES (UUID(),'Xenserver', '6.1.0', 'SUSE Linux Enterprise Server 10 SP3 (32-bit)', 151, now(), 0); +INSERT IGNORE INTO `cloud`.`guest_os_hypervisor` (uuid,hypervisor_type, hypervisor_version, guest_os_name, guest_os_id, created, is_user_defined) VALUES (UUID(),'Xenserver', '6.1.0', 'SUSE Linux Enterprise Server 10 SP3 (64-bit)', 45, now(), 0); +INSERT IGNORE INTO `cloud`.`guest_os_hypervisor` (uuid,hypervisor_type, hypervisor_version, guest_os_name, guest_os_id, created, is_user_defined) VALUES (UUID(),'Xenserver', '6.1.0', 'SUSE Linux Enterprise Server 10 SP4 (32-bit)', 153, now(), 0); +INSERT IGNORE INTO `cloud`.`guest_os_hypervisor` (uuid,hypervisor_type, hypervisor_version, guest_os_name, guest_os_id, created, is_user_defined) VALUES (UUID(),'Xenserver', '6.1.0', 'SUSE Linux Enterprise Server 10 SP4 (64-bit)', 152, now(), 0); +INSERT IGNORE INTO `cloud`.`guest_os_hypervisor` (uuid,hypervisor_type, hypervisor_version, guest_os_name, guest_os_id, created, is_user_defined) VALUES (UUID(),'Xenserver', '6.1.0', 'SUSE Linux Enterprise Server 11 (32-bit)', 46, now(), 0); +INSERT IGNORE INTO `cloud`.`guest_os_hypervisor` (uuid,hypervisor_type, hypervisor_version, guest_os_name, guest_os_id, created, is_user_defined) VALUES (UUID(),'Xenserver', '6.1.0', 'SUSE Linux Enterprise Server 11 (64-bit)', 47, now(), 0); +INSERT IGNORE INTO `cloud`.`guest_os_hypervisor` (uuid,hypervisor_type, hypervisor_version, guest_os_name, guest_os_id, created, is_user_defined) VALUES (UUID(),'Xenserver', '6.1.0', 'SUSE Linux Enterprise Server 11 SP1 (32-bit)', 155, now(), 0); +INSERT IGNORE INTO `cloud`.`guest_os_hypervisor` (uuid,hypervisor_type, hypervisor_version, guest_os_name, guest_os_id, created, is_user_defined) VALUES (UUID(),'Xenserver', '6.1.0', 'SUSE Linux Enterprise Server 11 SP1 (64-bit)', 154, now(), 0); +INSERT IGNORE INTO `cloud`.`guest_os_hypervisor` (uuid,hypervisor_type, hypervisor_version, guest_os_name, guest_os_id, created, is_user_defined) VALUES (UUID(),'Xenserver', '6.1.0', 'Windows 7 (32-bit)', 48, now(), 0); +INSERT IGNORE INTO `cloud`.`guest_os_hypervisor` (uuid,hypervisor_type, hypervisor_version, guest_os_name, guest_os_id, created, is_user_defined) VALUES (UUID(),'Xenserver', '6.1.0', 'Windows 7 (64-bit)', 49, now(), 0); +INSERT IGNORE INTO `cloud`.`guest_os_hypervisor` (uuid,hypervisor_type, hypervisor_version, guest_os_name, guest_os_id, created, is_user_defined) VALUES (UUID(),'Xenserver', '6.1.0', 'Windows 8 (32-bit) (experimental)', 165, now(), 0); +INSERT IGNORE INTO `cloud`.`guest_os_hypervisor` (uuid,hypervisor_type, hypervisor_version, guest_os_name, guest_os_id, created, is_user_defined) VALUES (UUID(),'Xenserver', '6.1.0', 'Windows 8 (64-bit) (experimental)', 166, now(), 0); +INSERT IGNORE INTO `cloud`.`guest_os_hypervisor` (uuid,hypervisor_type, hypervisor_version, guest_os_name, guest_os_id, created, is_user_defined) VALUES (UUID(),'Xenserver', '6.1.0', 'Windows Server 2003 (32-bit)', 50, now(), 0); +INSERT IGNORE INTO `cloud`.`guest_os_hypervisor` (uuid,hypervisor_type, hypervisor_version, guest_os_name, guest_os_id, created, is_user_defined) VALUES (UUID(),'Xenserver', '6.1.0', 'Windows Server 2003 (64-bit)', 51, now(), 0); +INSERT IGNORE INTO `cloud`.`guest_os_hypervisor` (uuid,hypervisor_type, hypervisor_version, guest_os_name, guest_os_id, created, is_user_defined) VALUES (UUID(),'Xenserver', '6.1.0', 'Windows Server 2003 (32-bit)', 87, now(), 0); +INSERT IGNORE INTO `cloud`.`guest_os_hypervisor` (uuid,hypervisor_type, hypervisor_version, guest_os_name, guest_os_id, created, is_user_defined) VALUES (UUID(),'Xenserver', '6.1.0', 'Windows Server 2003 (64-bit)', 88, now(), 0); +INSERT IGNORE INTO `cloud`.`guest_os_hypervisor` (uuid,hypervisor_type, hypervisor_version, guest_os_name, guest_os_id, created, is_user_defined) VALUES (UUID(),'Xenserver', '6.1.0', 'Windows Server 2003 (32-bit)', 89, now(), 0); +INSERT IGNORE INTO `cloud`.`guest_os_hypervisor` (uuid,hypervisor_type, hypervisor_version, guest_os_name, guest_os_id, created, is_user_defined) VALUES (UUID(),'Xenserver', '6.1.0', 'Windows Server 2003 (64-bit)', 90, now(), 0); +INSERT IGNORE INTO `cloud`.`guest_os_hypervisor` (uuid,hypervisor_type, hypervisor_version, guest_os_name, guest_os_id, created, is_user_defined) VALUES (UUID(),'Xenserver', '6.1.0', 'Windows Server 2008 (32-bit)', 52, now(), 0); +INSERT IGNORE INTO `cloud`.`guest_os_hypervisor` (uuid,hypervisor_type, hypervisor_version, guest_os_name, guest_os_id, created, is_user_defined) VALUES (UUID(),'Xenserver', '6.1.0', 'Windows Server 2008 (64-bit)', 53, now(), 0); +INSERT IGNORE INTO `cloud`.`guest_os_hypervisor` (uuid,hypervisor_type, hypervisor_version, guest_os_name, guest_os_id, created, is_user_defined) VALUES (UUID(),'Xenserver', '6.1.0', 'Windows Server 2008 R2 (64-bit)', 54, now(), 0); +INSERT IGNORE INTO `cloud`.`guest_os_hypervisor` (uuid,hypervisor_type, hypervisor_version, guest_os_name, guest_os_id, created, is_user_defined) VALUES (UUID(),'Xenserver', '6.1.0', 'Windows Server 2012 (64-bit) (experimental)', 167, now(), 0); +INSERT IGNORE INTO `cloud`.`guest_os_hypervisor` (uuid,hypervisor_type, hypervisor_version, guest_os_name, guest_os_id, created, is_user_defined) VALUES (UUID(),'Xenserver', '6.1.0', 'Windows Vista (32-bit)', 56, now(), 0); +INSERT IGNORE INTO `cloud`.`guest_os_hypervisor` (uuid,hypervisor_type, hypervisor_version, guest_os_name, guest_os_id, created, is_user_defined) VALUES (UUID(),'Xenserver', '6.1.0', 'Windows XP SP3 (32-bit)', 58, now(), 0); +INSERT IGNORE INTO `cloud`.`guest_os_hypervisor` (uuid,hypervisor_type, hypervisor_version, guest_os_name, guest_os_id, created, is_user_defined) VALUES (UUID(),'Xenserver', '6.1.0', 'Ubuntu Lucid Lynx 10.04 (32-bit)', 121, now(), 0); +INSERT IGNORE INTO `cloud`.`guest_os_hypervisor` (uuid,hypervisor_type, hypervisor_version, guest_os_name, guest_os_id, created, is_user_defined) VALUES (UUID(),'Xenserver', '6.1.0', 'Ubuntu Lucid Lynx 10.04 (64-bit)', 126, now(), 0); +INSERT IGNORE INTO `cloud`.`guest_os_hypervisor` (uuid,hypervisor_type, hypervisor_version, guest_os_name, guest_os_id, created, is_user_defined) VALUES (UUID(),'Xenserver', '6.1.0', 'Ubuntu Maverick Meerkat 10.10 (32-bit) (experimental)', 156, now(), 0); +INSERT IGNORE INTO `cloud`.`guest_os_hypervisor` (uuid,hypervisor_type, hypervisor_version, guest_os_name, guest_os_id, created, is_user_defined) VALUES (UUID(),'Xenserver', '6.1.0', 'Ubuntu Maverick Meerkat 10.10 (64-bit) (experimental)', 157, now(), 0); +INSERT IGNORE INTO `cloud`.`guest_os_hypervisor` (uuid,hypervisor_type, hypervisor_version, guest_os_name, guest_os_id, created, is_user_defined) VALUES (UUID(),'Xenserver', '6.1.0', 'Ubuntu Precise Pangolin 12.04 (32-bit)', 163, now(), 0); +INSERT IGNORE INTO `cloud`.`guest_os_hypervisor` (uuid,hypervisor_type, hypervisor_version, guest_os_name, guest_os_id, created, is_user_defined) VALUES (UUID(),'Xenserver', '6.1.0', 'Ubuntu Precise Pangolin 12.04 (64-bit)', 164, now(), 0); +INSERT IGNORE INTO `cloud`.`guest_os_hypervisor` (uuid,hypervisor_type, hypervisor_version, guest_os_name, guest_os_id, created, is_user_defined) VALUES (UUID(),'Xenserver', '6.1.0', 'Other install media', 169, now(), 0); +INSERT IGNORE INTO `cloud`.`guest_os_hypervisor` (uuid,hypervisor_type, hypervisor_version, guest_os_name, guest_os_id, created, is_user_defined) VALUES (UUID(),'Xenserver', '6.1.0', 'Other install media', 170, now(), 0); +INSERT IGNORE INTO `cloud`.`guest_os_hypervisor` (uuid,hypervisor_type, hypervisor_version, guest_os_name, guest_os_id, created, is_user_defined) VALUES (UUID(),'Xenserver', '6.1.0', 'Other install media', 98, now(), 0); +INSERT IGNORE INTO `cloud`.`guest_os_hypervisor` (uuid,hypervisor_type, hypervisor_version, guest_os_name, guest_os_id, created, is_user_defined) VALUES (UUID(),'Xenserver', '6.1.0', 'Other install media', 99, now(), 0); +INSERT IGNORE INTO `cloud`.`guest_os_hypervisor` (uuid,hypervisor_type, hypervisor_version, guest_os_name, guest_os_id, created, is_user_defined) VALUES (UUID(),'Xenserver', '6.1.0', 'Other install media', 60, now(), 0); +INSERT IGNORE INTO `cloud`.`guest_os_hypervisor` (uuid,hypervisor_type, hypervisor_version, guest_os_name, guest_os_id, created, is_user_defined) VALUES (UUID(),'Xenserver', '6.1.0', 'Other install media', 103, now(), 0); +INSERT IGNORE INTO `cloud`.`guest_os_hypervisor` (uuid,hypervisor_type, hypervisor_version, guest_os_name, guest_os_id, created, is_user_defined) VALUES (UUID(),'Xenserver', '6.1.0', 'Other install media', 200, now(), 0); +INSERT IGNORE INTO `cloud`.`guest_os_hypervisor` (uuid,hypervisor_type, hypervisor_version, guest_os_name, guest_os_id, created, is_user_defined) VALUES (UUID(),'Xenserver', '6.1.0', 'Other install media', 201, now(), 0); +INSERT IGNORE INTO `cloud`.`guest_os_hypervisor` (uuid,hypervisor_type, hypervisor_version, guest_os_name, guest_os_id, created, is_user_defined) VALUES (UUID(),'Xenserver', '6.1.0', 'Other install media', 59, now(), 0); +INSERT IGNORE INTO `cloud`.`guest_os_hypervisor` (uuid,hypervisor_type, hypervisor_version, guest_os_name, guest_os_id, created, is_user_defined) VALUES (UUID(),'Xenserver', '6.1.0', 'Other install media', 100, now(), 0); +INSERT IGNORE INTO `cloud`.`guest_os_hypervisor` (uuid,hypervisor_type, hypervisor_version, guest_os_name, guest_os_id, created, is_user_defined) VALUES (UUID(),'Xenserver', '6.1.0', 'Other install media', 202, now(), 0); +INSERT IGNORE INTO `cloud`.`guest_os_hypervisor` (uuid,hypervisor_type, hypervisor_version, guest_os_name, guest_os_id, created, is_user_defined) VALUES (UUID(),'Xenserver', '6.1.0', 'Other install media', 203, now(), 0); +INSERT IGNORE INTO `cloud`.`guest_os_hypervisor` (uuid,hypervisor_type, hypervisor_version, guest_os_name, guest_os_id, created, is_user_defined) VALUES (UUID(),'Xenserver', '6.1.0', 'CentOS 5 (32-bit)', 139, now(), 0); +INSERT IGNORE INTO `cloud`.`guest_os_hypervisor` (uuid,hypervisor_type, hypervisor_version, guest_os_name, guest_os_id, created, is_user_defined) VALUES (UUID(),'Xenserver', '6.1.0', 'CentOS 5 (64-bit)', 140, now(), 0); +INSERT IGNORE INTO `cloud`.`guest_os_hypervisor` (uuid,hypervisor_type, hypervisor_version, guest_os_name, guest_os_id, created, is_user_defined) VALUES (UUID(),'Xenserver', '6.2.0', 'CentOS 4.5 (32-bit)', 1, now(), 0); +INSERT IGNORE INTO `cloud`.`guest_os_hypervisor` (uuid,hypervisor_type, hypervisor_version, guest_os_name, guest_os_id, created, is_user_defined) VALUES (UUID(),'Xenserver', '6.2.0', 'CentOS 4.6 (32-bit)', 2, now(), 0); +INSERT IGNORE INTO `cloud`.`guest_os_hypervisor` (uuid,hypervisor_type, hypervisor_version, guest_os_name, guest_os_id, created, is_user_defined) VALUES (UUID(),'Xenserver', '6.2.0', 'CentOS 4.7 (32-bit)', 3, now(), 0); +INSERT IGNORE INTO `cloud`.`guest_os_hypervisor` (uuid,hypervisor_type, hypervisor_version, guest_os_name, guest_os_id, created, is_user_defined) VALUES (UUID(),'Xenserver', '6.2.0', 'CentOS 4.8 (32-bit)', 4, now(), 0); +INSERT IGNORE INTO `cloud`.`guest_os_hypervisor` (uuid,hypervisor_type, hypervisor_version, guest_os_name, guest_os_id, created, is_user_defined) VALUES (UUID(),'Xenserver', '6.2.0', 'CentOS 5 (32-bit)', 5, now(), 0); +INSERT IGNORE INTO `cloud`.`guest_os_hypervisor` (uuid,hypervisor_type, hypervisor_version, guest_os_name, guest_os_id, created, is_user_defined) VALUES (UUID(),'Xenserver', '6.2.0', 'CentOS 5 (64-bit)', 6, now(), 0); +INSERT IGNORE INTO `cloud`.`guest_os_hypervisor` (uuid,hypervisor_type, hypervisor_version, guest_os_name, guest_os_id, created, is_user_defined) VALUES (UUID(),'Xenserver', '6.2.0', 'CentOS 5 (32-bit)', 7, now(), 0); +INSERT IGNORE INTO `cloud`.`guest_os_hypervisor` (uuid,hypervisor_type, hypervisor_version, guest_os_name, guest_os_id, created, is_user_defined) VALUES (UUID(),'Xenserver', '6.2.0', 'CentOS 5 (64-bit)', 8, now(), 0); +INSERT IGNORE INTO `cloud`.`guest_os_hypervisor` (uuid,hypervisor_type, hypervisor_version, guest_os_name, guest_os_id, created, is_user_defined) VALUES (UUID(),'Xenserver', '6.2.0', 'CentOS 5 (32-bit)', 9, now(), 0); +INSERT IGNORE INTO `cloud`.`guest_os_hypervisor` (uuid,hypervisor_type, hypervisor_version, guest_os_name, guest_os_id, created, is_user_defined) VALUES (UUID(),'Xenserver', '6.2.0', 'CentOS 5 (64-bit)', 10, now(), 0); +INSERT IGNORE INTO `cloud`.`guest_os_hypervisor` (uuid,hypervisor_type, hypervisor_version, guest_os_name, guest_os_id, created, is_user_defined) VALUES (UUID(),'Xenserver', '6.2.0', 'CentOS 5 (32-bit)', 11, now(), 0); +INSERT IGNORE INTO `cloud`.`guest_os_hypervisor` (uuid,hypervisor_type, hypervisor_version, guest_os_name, guest_os_id, created, is_user_defined) VALUES (UUID(),'Xenserver', '6.2.0', 'CentOS 5 (64-bit)', 12, now(), 0); +INSERT IGNORE INTO `cloud`.`guest_os_hypervisor` (uuid,hypervisor_type, hypervisor_version, guest_os_name, guest_os_id, created, is_user_defined) VALUES (UUID(),'Xenserver', '6.2.0', 'CentOS 5 (32-bit)', 13, now(), 0); +INSERT IGNORE INTO `cloud`.`guest_os_hypervisor` (uuid,hypervisor_type, hypervisor_version, guest_os_name, guest_os_id, created, is_user_defined) VALUES (UUID(),'Xenserver', '6.2.0', 'CentOS 5 (64-bit)', 14, now(), 0); +INSERT IGNORE INTO `cloud`.`guest_os_hypervisor` (uuid,hypervisor_type, hypervisor_version, guest_os_name, guest_os_id, created, is_user_defined) VALUES (UUID(),'Xenserver', '6.2.0', 'CentOS 5 (32-bit)', 111, now(), 0); +INSERT IGNORE INTO `cloud`.`guest_os_hypervisor` (uuid,hypervisor_type, hypervisor_version, guest_os_name, guest_os_id, created, is_user_defined) VALUES (UUID(),'Xenserver', '6.2.0', 'CentOS 5 (64-bit)', 112, now(), 0); +INSERT IGNORE INTO `cloud`.`guest_os_hypervisor` (uuid,hypervisor_type, hypervisor_version, guest_os_name, guest_os_id, created, is_user_defined) VALUES (UUID(),'Xenserver', '6.2.0', 'CentOS 5 (32-bit)', 141, now(), 0); +INSERT IGNORE INTO `cloud`.`guest_os_hypervisor` (uuid,hypervisor_type, hypervisor_version, guest_os_name, guest_os_id, created, is_user_defined) VALUES (UUID(),'Xenserver', '6.2.0', 'CentOS 5 (64-bit)', 142, now(), 0); +INSERT IGNORE INTO `cloud`.`guest_os_hypervisor` (uuid,hypervisor_type, hypervisor_version, guest_os_name, guest_os_id, created, is_user_defined) VALUES (UUID(),'Xenserver', '6.2.0', 'CentOS 5 (32-bit)', 161, now(), 0); +INSERT IGNORE INTO `cloud`.`guest_os_hypervisor` (uuid,hypervisor_type, hypervisor_version, guest_os_name, guest_os_id, created, is_user_defined) VALUES (UUID(),'Xenserver', '6.2.0', 'CentOS 5 (64-bit)', 162, now(), 0); +INSERT IGNORE INTO `cloud`.`guest_os_hypervisor` (uuid,hypervisor_type, hypervisor_version, guest_os_name, guest_os_id, created, is_user_defined) VALUES (UUID(),'Xenserver', '6.2.0', 'CentOS 5 (32-bit)', 173, now(), 0); +INSERT IGNORE INTO `cloud`.`guest_os_hypervisor` (uuid,hypervisor_type, hypervisor_version, guest_os_name, guest_os_id, created, is_user_defined) VALUES (UUID(),'Xenserver', '6.2.0', 'CentOS 5 (64-bit)', 174, now(), 0); +INSERT IGNORE INTO `cloud`.`guest_os_hypervisor` (uuid,hypervisor_type, hypervisor_version, guest_os_name, guest_os_id, created, is_user_defined) VALUES (UUID(),'Xenserver', '6.2.0', 'CentOS 5 (32-bit)', 175, now(), 0); +INSERT IGNORE INTO `cloud`.`guest_os_hypervisor` (uuid,hypervisor_type, hypervisor_version, guest_os_name, guest_os_id, created, is_user_defined) VALUES (UUID(),'Xenserver', '6.2.0', 'CentOS 5 (64-bit)', 176, now(), 0); +INSERT IGNORE INTO `cloud`.`guest_os_hypervisor` (uuid,hypervisor_type, hypervisor_version, guest_os_name, guest_os_id, created, is_user_defined) VALUES (UUID(),'Xenserver', '6.2.0', 'CentOS 6 (32-bit)', 143, now(), 0); +INSERT IGNORE INTO `cloud`.`guest_os_hypervisor` (uuid,hypervisor_type, hypervisor_version, guest_os_name, guest_os_id, created, is_user_defined) VALUES (UUID(),'Xenserver', '6.2.0', 'CentOS 6 (64-bit)', 144, now(), 0); +INSERT IGNORE INTO `cloud`.`guest_os_hypervisor` (uuid,hypervisor_type, hypervisor_version, guest_os_name, guest_os_id, created, is_user_defined) VALUES (UUID(),'Xenserver', '6.2.0', 'CentOS 6 (32-bit)', 177, now(), 0); +INSERT IGNORE INTO `cloud`.`guest_os_hypervisor` (uuid,hypervisor_type, hypervisor_version, guest_os_name, guest_os_id, created, is_user_defined) VALUES (UUID(),'Xenserver', '6.2.0', 'CentOS 6 (64-bit)', 178, now(), 0); +INSERT IGNORE INTO `cloud`.`guest_os_hypervisor` (uuid,hypervisor_type, hypervisor_version, guest_os_name, guest_os_id, created, is_user_defined) VALUES (UUID(),'Xenserver', '6.2.0', 'CentOS 6 (32-bit)', 179, now(), 0); +INSERT IGNORE INTO `cloud`.`guest_os_hypervisor` (uuid,hypervisor_type, hypervisor_version, guest_os_name, guest_os_id, created, is_user_defined) VALUES (UUID(),'Xenserver', '6.2.0', 'CentOS 6 (64-bit)', 180, now(), 0); +INSERT IGNORE INTO `cloud`.`guest_os_hypervisor` (uuid,hypervisor_type, hypervisor_version, guest_os_name, guest_os_id, created, is_user_defined) VALUES (UUID(),'Xenserver', '6.2.0', 'CentOS 6 (32-bit)', 171, now(), 0); +INSERT IGNORE INTO `cloud`.`guest_os_hypervisor` (uuid,hypervisor_type, hypervisor_version, guest_os_name, guest_os_id, created, is_user_defined) VALUES (UUID(),'Xenserver', '6.2.0', 'CentOS 6 (64-bit)', 172, now(), 0); +INSERT IGNORE INTO `cloud`.`guest_os_hypervisor` (uuid,hypervisor_type, hypervisor_version, guest_os_name, guest_os_id, created, is_user_defined) VALUES (UUID(),'Xenserver', '6.2.0', 'CentOS 6 (32-bit)', 181, now(), 0); +INSERT IGNORE INTO `cloud`.`guest_os_hypervisor` (uuid,hypervisor_type, hypervisor_version, guest_os_name, guest_os_id, created, is_user_defined) VALUES (UUID(),'Xenserver', '6.2.0', 'CentOS 6 (64-bit)', 182, now(), 0); +INSERT IGNORE INTO `cloud`.`guest_os_hypervisor` (uuid,hypervisor_type, hypervisor_version, guest_os_name, guest_os_id, created, is_user_defined) VALUES (UUID(),'Xenserver', '6.2.0', 'Debian Squeeze 6.0 (32-bit)', 132, now(), 0); +INSERT IGNORE INTO `cloud`.`guest_os_hypervisor` (uuid,hypervisor_type, hypervisor_version, guest_os_name, guest_os_id, created, is_user_defined) VALUES (UUID(),'Xenserver', '6.2.0', 'Debian Squeeze 6.0 (64-bit)', 133, now(), 0); +INSERT IGNORE INTO `cloud`.`guest_os_hypervisor` (uuid,hypervisor_type, hypervisor_version, guest_os_name, guest_os_id, created, is_user_defined) VALUES (UUID(),'Xenserver', '6.2.0', 'Debian Wheezy 7.0 (32-bit)', 183, now(), 0); +INSERT IGNORE INTO `cloud`.`guest_os_hypervisor` (uuid,hypervisor_type, hypervisor_version, guest_os_name, guest_os_id, created, is_user_defined) VALUES (UUID(),'Xenserver', '6.2.0', 'Debian Wheezy 7.0 (64-bit)', 184, now(), 0); +INSERT IGNORE INTO `cloud`.`guest_os_hypervisor` (uuid,hypervisor_type, hypervisor_version, guest_os_name, guest_os_id, created, is_user_defined) VALUES (UUID(),'Xenserver', '6.2.0', 'Oracle Enterprise Linux 5 (32-bit)', 16, now(), 0); +INSERT IGNORE INTO `cloud`.`guest_os_hypervisor` (uuid,hypervisor_type, hypervisor_version, guest_os_name, guest_os_id, created, is_user_defined) VALUES (UUID(),'Xenserver', '6.2.0', 'Oracle Enterprise Linux 5 (64-bit)', 17, now(), 0); +INSERT IGNORE INTO `cloud`.`guest_os_hypervisor` (uuid,hypervisor_type, hypervisor_version, guest_os_name, guest_os_id, created, is_user_defined) VALUES (UUID(),'Xenserver', '6.2.0', 'Oracle Enterprise Linux 5 (32-bit)', 18, now(), 0); +INSERT IGNORE INTO `cloud`.`guest_os_hypervisor` (uuid,hypervisor_type, hypervisor_version, guest_os_name, guest_os_id, created, is_user_defined) VALUES (UUID(),'Xenserver', '6.2.0', 'Oracle Enterprise Linux 5 (64-bit)', 19, now(), 0); +INSERT IGNORE INTO `cloud`.`guest_os_hypervisor` (uuid,hypervisor_type, hypervisor_version, guest_os_name, guest_os_id, created, is_user_defined) VALUES (UUID(),'Xenserver', '6.2.0', 'Oracle Enterprise Linux 5 (32-bit)', 20, now(), 0); +INSERT IGNORE INTO `cloud`.`guest_os_hypervisor` (uuid,hypervisor_type, hypervisor_version, guest_os_name, guest_os_id, created, is_user_defined) VALUES (UUID(),'Xenserver', '6.2.0', 'Oracle Enterprise Linux 5 (64-bit)', 21, now(), 0); +INSERT IGNORE INTO `cloud`.`guest_os_hypervisor` (uuid,hypervisor_type, hypervisor_version, guest_os_name, guest_os_id, created, is_user_defined) VALUES (UUID(),'Xenserver', '6.2.0', 'Oracle Enterprise Linux 5 (32-bit)', 22, now(), 0); +INSERT IGNORE INTO `cloud`.`guest_os_hypervisor` (uuid,hypervisor_type, hypervisor_version, guest_os_name, guest_os_id, created, is_user_defined) VALUES (UUID(),'Xenserver', '6.2.0', 'Oracle Enterprise Linux 5 (64-bit)', 23, now(), 0); +INSERT IGNORE INTO `cloud`.`guest_os_hypervisor` (uuid,hypervisor_type, hypervisor_version, guest_os_name, guest_os_id, created, is_user_defined) VALUES (UUID(),'Xenserver', '6.2.0', 'Oracle Enterprise Linux 5 (32-bit)', 24, now(), 0); +INSERT IGNORE INTO `cloud`.`guest_os_hypervisor` (uuid,hypervisor_type, hypervisor_version, guest_os_name, guest_os_id, created, is_user_defined) VALUES (UUID(),'Xenserver', '6.2.0', 'Oracle Enterprise Linux 5 (64-bit)', 25, now(), 0); +INSERT IGNORE INTO `cloud`.`guest_os_hypervisor` (uuid,hypervisor_type, hypervisor_version, guest_os_name, guest_os_id, created, is_user_defined) VALUES (UUID(),'Xenserver', '6.2.0', 'Oracle Enterprise Linux 5 (32-bit)', 134, now(), 0); +INSERT IGNORE INTO `cloud`.`guest_os_hypervisor` (uuid,hypervisor_type, hypervisor_version, guest_os_name, guest_os_id, created, is_user_defined) VALUES (UUID(),'Xenserver', '6.2.0', 'Oracle Enterprise Linux 5 (64-bit)', 135, now(), 0); +INSERT IGNORE INTO `cloud`.`guest_os_hypervisor` (uuid,hypervisor_type, hypervisor_version, guest_os_name, guest_os_id, created, is_user_defined) VALUES (UUID(),'Xenserver', '6.2.0', 'Oracle Enterprise Linux 5 (32-bit)', 145, now(), 0); +INSERT IGNORE INTO `cloud`.`guest_os_hypervisor` (uuid,hypervisor_type, hypervisor_version, guest_os_name, guest_os_id, created, is_user_defined) VALUES (UUID(),'Xenserver', '6.2.0', 'Oracle Enterprise Linux 5 (64-bit)', 146, now(), 0); +INSERT IGNORE INTO `cloud`.`guest_os_hypervisor` (uuid,hypervisor_type, hypervisor_version, guest_os_name, guest_os_id, created, is_user_defined) VALUES (UUID(),'Xenserver', '6.2.0', 'Oracle Enterprise Linux 5 (32-bit)', 207, now(), 0); +INSERT IGNORE INTO `cloud`.`guest_os_hypervisor` (uuid,hypervisor_type, hypervisor_version, guest_os_name, guest_os_id, created, is_user_defined) VALUES (UUID(),'Xenserver', '6.2.0', 'Oracle Enterprise Linux 5 (64-bit)', 208, now(), 0); +INSERT IGNORE INTO `cloud`.`guest_os_hypervisor` (uuid,hypervisor_type, hypervisor_version, guest_os_name, guest_os_id, created, is_user_defined) VALUES (UUID(),'Xenserver', '6.2.0', 'Oracle Enterprise Linux 5 (32-bit)', 209, now(), 0); +INSERT IGNORE INTO `cloud`.`guest_os_hypervisor` (uuid,hypervisor_type, hypervisor_version, guest_os_name, guest_os_id, created, is_user_defined) VALUES (UUID(),'Xenserver', '6.2.0', 'Oracle Enterprise Linux 5 (64-bit)', 210, now(), 0); +INSERT IGNORE INTO `cloud`.`guest_os_hypervisor` (uuid,hypervisor_type, hypervisor_version, guest_os_name, guest_os_id, created, is_user_defined) VALUES (UUID(),'Xenserver', '6.2.0', 'Oracle Enterprise Linux 5 (32-bit)', 211, now(), 0); +INSERT IGNORE INTO `cloud`.`guest_os_hypervisor` (uuid,hypervisor_type, hypervisor_version, guest_os_name, guest_os_id, created, is_user_defined) VALUES (UUID(),'Xenserver', '6.2.0', 'Oracle Enterprise Linux 5 (64-bit)', 212, now(), 0); +INSERT IGNORE INTO `cloud`.`guest_os_hypervisor` (uuid,hypervisor_type, hypervisor_version, guest_os_name, guest_os_id, created, is_user_defined) VALUES (UUID(),'Xenserver', '6.2.0', 'Oracle Enterprise Linux 6 (32-bit)', 147, now(), 0); +INSERT IGNORE INTO `cloud`.`guest_os_hypervisor` (uuid,hypervisor_type, hypervisor_version, guest_os_name, guest_os_id, created, is_user_defined) VALUES (UUID(),'Xenserver', '6.2.0', 'Oracle Enterprise Linux 6 (64-bit)', 148, now(), 0); +INSERT IGNORE INTO `cloud`.`guest_os_hypervisor` (uuid,hypervisor_type, hypervisor_version, guest_os_name, guest_os_id, created, is_user_defined) VALUES (UUID(),'Xenserver', '6.2.0', 'Oracle Enterprise Linux 6 (32-bit)', 213, now(), 0); +INSERT IGNORE INTO `cloud`.`guest_os_hypervisor` (uuid,hypervisor_type, hypervisor_version, guest_os_name, guest_os_id, created, is_user_defined) VALUES (UUID(),'Xenserver', '6.2.0', 'Oracle Enterprise Linux 6 (64-bit)', 214, now(), 0); +INSERT IGNORE INTO `cloud`.`guest_os_hypervisor` (uuid,hypervisor_type, hypervisor_version, guest_os_name, guest_os_id, created, is_user_defined) VALUES (UUID(),'Xenserver', '6.2.0', 'Oracle Enterprise Linux 6 (32-bit)', 215, now(), 0); +INSERT IGNORE INTO `cloud`.`guest_os_hypervisor` (uuid,hypervisor_type, hypervisor_version, guest_os_name, guest_os_id, created, is_user_defined) VALUES (UUID(),'Xenserver', '6.2.0', 'Oracle Enterprise Linux 6 (64-bit)', 216, now(), 0); +INSERT IGNORE INTO `cloud`.`guest_os_hypervisor` (uuid,hypervisor_type, hypervisor_version, guest_os_name, guest_os_id, created, is_user_defined) VALUES (UUID(),'Xenserver', '6.2.0', 'Oracle Enterprise Linux 6 (32-bit)', 217, now(), 0); +INSERT IGNORE INTO `cloud`.`guest_os_hypervisor` (uuid,hypervisor_type, hypervisor_version, guest_os_name, guest_os_id, created, is_user_defined) VALUES (UUID(),'Xenserver', '6.2.0', 'Oracle Enterprise Linux 6 (64-bit)', 218, now(), 0); +INSERT IGNORE INTO `cloud`.`guest_os_hypervisor` (uuid,hypervisor_type, hypervisor_version, guest_os_name, guest_os_id, created, is_user_defined) VALUES (UUID(),'Xenserver', '6.2.0', 'Oracle Enterprise Linux 6 (32-bit)', 219, now(), 0); +INSERT IGNORE INTO `cloud`.`guest_os_hypervisor` (uuid,hypervisor_type, hypervisor_version, guest_os_name, guest_os_id, created, is_user_defined) VALUES (UUID(),'Xenserver', '6.2.0', 'Oracle Enterprise Linux 6 (64-bit)', 220, now(), 0); +INSERT IGNORE INTO `cloud`.`guest_os_hypervisor` (uuid,hypervisor_type, hypervisor_version, guest_os_name, guest_os_id, created, is_user_defined) VALUES (UUID(),'Xenserver', '6.2.0', 'Red Hat Enterprise Linux 4.5 (32-bit)', 26, now(), 0); +INSERT IGNORE INTO `cloud`.`guest_os_hypervisor` (uuid,hypervisor_type, hypervisor_version, guest_os_name, guest_os_id, created, is_user_defined) VALUES (UUID(),'Xenserver', '6.2.0', 'Red Hat Enterprise Linux 4.6 (32-bit)', 27, now(), 0); +INSERT IGNORE INTO `cloud`.`guest_os_hypervisor` (uuid,hypervisor_type, hypervisor_version, guest_os_name, guest_os_id, created, is_user_defined) VALUES (UUID(),'Xenserver', '6.2.0', 'Red Hat Enterprise Linux 4.7 (32-bit)', 28, now(), 0); +INSERT IGNORE INTO `cloud`.`guest_os_hypervisor` (uuid,hypervisor_type, hypervisor_version, guest_os_name, guest_os_id, created, is_user_defined) VALUES (UUID(),'Xenserver', '6.2.0', 'Red Hat Enterprise Linux 4.8 (32-bit)', 29, now(), 0); +INSERT IGNORE INTO `cloud`.`guest_os_hypervisor` (uuid,hypervisor_type, hypervisor_version, guest_os_name, guest_os_id, created, is_user_defined) VALUES (UUID(),'Xenserver', '6.2.0', 'Red Hat Enterprise Linux 5 (32-bit)', 30, now(), 0); +INSERT IGNORE INTO `cloud`.`guest_os_hypervisor` (uuid,hypervisor_type, hypervisor_version, guest_os_name, guest_os_id, created, is_user_defined) VALUES (UUID(),'Xenserver', '6.2.0', 'Red Hat Enterprise Linux 5 (64-bit)', 31, now(), 0); +INSERT IGNORE INTO `cloud`.`guest_os_hypervisor` (uuid,hypervisor_type, hypervisor_version, guest_os_name, guest_os_id, created, is_user_defined) VALUES (UUID(),'Xenserver', '6.2.0', 'Red Hat Enterprise Linux 5 (32-bit)', 32, now(), 0); +INSERT IGNORE INTO `cloud`.`guest_os_hypervisor` (uuid,hypervisor_type, hypervisor_version, guest_os_name, guest_os_id, created, is_user_defined) VALUES (UUID(),'Xenserver', '6.2.0', 'Red Hat Enterprise Linux 5 (64-bit)', 33, now(), 0); +INSERT IGNORE INTO `cloud`.`guest_os_hypervisor` (uuid,hypervisor_type, hypervisor_version, guest_os_name, guest_os_id, created, is_user_defined) VALUES (UUID(),'Xenserver', '6.2.0', 'Red Hat Enterprise Linux 5 (32-bit)', 34, now(), 0); +INSERT IGNORE INTO `cloud`.`guest_os_hypervisor` (uuid,hypervisor_type, hypervisor_version, guest_os_name, guest_os_id, created, is_user_defined) VALUES (UUID(),'Xenserver', '6.2.0', 'Red Hat Enterprise Linux 5 (64-bit)', 35, now(), 0); +INSERT IGNORE INTO `cloud`.`guest_os_hypervisor` (uuid,hypervisor_type, hypervisor_version, guest_os_name, guest_os_id, created, is_user_defined) VALUES (UUID(),'Xenserver', '6.2.0', 'Red Hat Enterprise Linux 5 (32-bit)', 36, now(), 0); +INSERT IGNORE INTO `cloud`.`guest_os_hypervisor` (uuid,hypervisor_type, hypervisor_version, guest_os_name, guest_os_id, created, is_user_defined) VALUES (UUID(),'Xenserver', '6.2.0', 'Red Hat Enterprise Linux 5 (64-bit)', 37, now(), 0); +INSERT IGNORE INTO `cloud`.`guest_os_hypervisor` (uuid,hypervisor_type, hypervisor_version, guest_os_name, guest_os_id, created, is_user_defined) VALUES (UUID(),'Xenserver', '6.2.0', 'Red Hat Enterprise Linux 5 (32-bit)', 38, now(), 0); +INSERT IGNORE INTO `cloud`.`guest_os_hypervisor` (uuid,hypervisor_type, hypervisor_version, guest_os_name, guest_os_id, created, is_user_defined) VALUES (UUID(),'Xenserver', '6.2.0', 'Red Hat Enterprise Linux 5 (64-bit)', 39, now(), 0); +INSERT IGNORE INTO `cloud`.`guest_os_hypervisor` (uuid,hypervisor_type, hypervisor_version, guest_os_name, guest_os_id, created, is_user_defined) VALUES (UUID(),'Xenserver', '6.2.0', 'Red Hat Enterprise Linux 5 (32-bit)', 113, now(), 0); +INSERT IGNORE INTO `cloud`.`guest_os_hypervisor` (uuid,hypervisor_type, hypervisor_version, guest_os_name, guest_os_id, created, is_user_defined) VALUES (UUID(),'Xenserver', '6.2.0', 'Red Hat Enterprise Linux 5 (64-bit)', 114, now(), 0); +INSERT IGNORE INTO `cloud`.`guest_os_hypervisor` (uuid,hypervisor_type, hypervisor_version, guest_os_name, guest_os_id, created, is_user_defined) VALUES (UUID(),'Xenserver', '6.2.0', 'Red Hat Enterprise Linux 5 (32-bit)', 149, now(), 0); +INSERT IGNORE INTO `cloud`.`guest_os_hypervisor` (uuid,hypervisor_type, hypervisor_version, guest_os_name, guest_os_id, created, is_user_defined) VALUES (UUID(),'Xenserver', '6.2.0', 'Red Hat Enterprise Linux 5 (64-bit)', 150, now(), 0); +INSERT IGNORE INTO `cloud`.`guest_os_hypervisor` (uuid,hypervisor_type, hypervisor_version, guest_os_name, guest_os_id, created, is_user_defined) VALUES (UUID(),'Xenserver', '6.2.0', 'Red Hat Enterprise Linux 5 (32-bit)', 189, now(), 0); +INSERT IGNORE INTO `cloud`.`guest_os_hypervisor` (uuid,hypervisor_type, hypervisor_version, guest_os_name, guest_os_id, created, is_user_defined) VALUES (UUID(),'Xenserver', '6.2.0', 'Red Hat Enterprise Linux 5 (64-bit)', 190, now(), 0); +INSERT IGNORE INTO `cloud`.`guest_os_hypervisor` (uuid,hypervisor_type, hypervisor_version, guest_os_name, guest_os_id, created, is_user_defined) VALUES (UUID(),'Xenserver', '6.2.0', 'Red Hat Enterprise Linux 5 (32-bit)', 191, now(), 0); +INSERT IGNORE INTO `cloud`.`guest_os_hypervisor` (uuid,hypervisor_type, hypervisor_version, guest_os_name, guest_os_id, created, is_user_defined) VALUES (UUID(),'Xenserver', '6.2.0', 'Red Hat Enterprise Linux 5 (64-bit)', 192, now(), 0); +INSERT IGNORE INTO `cloud`.`guest_os_hypervisor` (uuid,hypervisor_type, hypervisor_version, guest_os_name, guest_os_id, created, is_user_defined) VALUES (UUID(),'Xenserver', '6.2.0', 'Red Hat Enterprise Linux 5 (32-bit)', 193, now(), 0); +INSERT IGNORE INTO `cloud`.`guest_os_hypervisor` (uuid,hypervisor_type, hypervisor_version, guest_os_name, guest_os_id, created, is_user_defined) VALUES (UUID(),'Xenserver', '6.2.0', 'Red Hat Enterprise Linux 5 (64-bit)', 194, now(), 0); +INSERT IGNORE INTO `cloud`.`guest_os_hypervisor` (uuid,hypervisor_type, hypervisor_version, guest_os_name, guest_os_id, created, is_user_defined) VALUES (UUID(),'Xenserver', '6.2.0', 'Red Hat Enterprise Linux 6 (32-bit)', 136, now(), 0); +INSERT IGNORE INTO `cloud`.`guest_os_hypervisor` (uuid,hypervisor_type, hypervisor_version, guest_os_name, guest_os_id, created, is_user_defined) VALUES (UUID(),'Xenserver', '6.2.0', 'Red Hat Enterprise Linux 6 (64-bit)', 137, now(), 0); +INSERT IGNORE INTO `cloud`.`guest_os_hypervisor` (uuid,hypervisor_type, hypervisor_version, guest_os_name, guest_os_id, created, is_user_defined) VALUES (UUID(),'Xenserver', '6.2.0', 'Red Hat Enterprise Linux 6 (32-bit)', 195, now(), 0); +INSERT IGNORE INTO `cloud`.`guest_os_hypervisor` (uuid,hypervisor_type, hypervisor_version, guest_os_name, guest_os_id, created, is_user_defined) VALUES (UUID(),'Xenserver', '6.2.0', 'Red Hat Enterprise Linux 6 (64-bit)', 196, now(), 0); +INSERT IGNORE INTO `cloud`.`guest_os_hypervisor` (uuid,hypervisor_type, hypervisor_version, guest_os_name, guest_os_id, created, is_user_defined) VALUES (UUID(),'Xenserver', '6.2.0', 'Red Hat Enterprise Linux 6 (32-bit)', 197, now(), 0); +INSERT IGNORE INTO `cloud`.`guest_os_hypervisor` (uuid,hypervisor_type, hypervisor_version, guest_os_name, guest_os_id, created, is_user_defined) VALUES (UUID(),'Xenserver', '6.2.0', 'Red Hat Enterprise Linux 6 (64-bit)', 198, now(), 0); +INSERT IGNORE INTO `cloud`.`guest_os_hypervisor` (uuid,hypervisor_type, hypervisor_version, guest_os_name, guest_os_id, created, is_user_defined) VALUES (UUID(),'Xenserver', '6.2.0', 'Red Hat Enterprise Linux 6 (32-bit)', 199, now(), 0); +INSERT IGNORE INTO `cloud`.`guest_os_hypervisor` (uuid,hypervisor_type, hypervisor_version, guest_os_name, guest_os_id, created, is_user_defined) VALUES (UUID(),'Xenserver', '6.2.0', 'Red Hat Enterprise Linux 6 (64-bit)', 204, now(), 0); +INSERT IGNORE INTO `cloud`.`guest_os_hypervisor` (uuid,hypervisor_type, hypervisor_version, guest_os_name, guest_os_id, created, is_user_defined) VALUES (UUID(),'Xenserver', '6.2.0', 'Red Hat Enterprise Linux 6 (32-bit)', 205, now(), 0); +INSERT IGNORE INTO `cloud`.`guest_os_hypervisor` (uuid,hypervisor_type, hypervisor_version, guest_os_name, guest_os_id, created, is_user_defined) VALUES (UUID(),'Xenserver', '6.2.0', 'Red Hat Enterprise Linux 6 (64-bit)', 206, now(), 0); +INSERT IGNORE INTO `cloud`.`guest_os_hypervisor` (uuid,hypervisor_type, hypervisor_version, guest_os_name, guest_os_id, created, is_user_defined) VALUES (UUID(),'Xenserver', '6.2.0', 'SUSE Linux Enterprise Server 10 SP1 (32-bit)', 41, now(), 0); +INSERT IGNORE INTO `cloud`.`guest_os_hypervisor` (uuid,hypervisor_type, hypervisor_version, guest_os_name, guest_os_id, created, is_user_defined) VALUES (UUID(),'Xenserver', '6.2.0', 'SUSE Linux Enterprise Server 10 SP1 (64-bit)', 42, now(), 0); +INSERT IGNORE INTO `cloud`.`guest_os_hypervisor` (uuid,hypervisor_type, hypervisor_version, guest_os_name, guest_os_id, created, is_user_defined) VALUES (UUID(),'Xenserver', '6.2.0', 'SUSE Linux Enterprise Server 10 SP2 (32-bit)', 43, now(), 0); +INSERT IGNORE INTO `cloud`.`guest_os_hypervisor` (uuid,hypervisor_type, hypervisor_version, guest_os_name, guest_os_id, created, is_user_defined) VALUES (UUID(),'Xenserver', '6.2.0', 'SUSE Linux Enterprise Server 10 SP2 (64-bit)', 44, now(), 0); +INSERT IGNORE INTO `cloud`.`guest_os_hypervisor` (uuid,hypervisor_type, hypervisor_version, guest_os_name, guest_os_id, created, is_user_defined) VALUES (UUID(),'Xenserver', '6.2.0', 'SUSE Linux Enterprise Server 10 SP3 (32-bit)', 151, now(), 0); +INSERT IGNORE INTO `cloud`.`guest_os_hypervisor` (uuid,hypervisor_type, hypervisor_version, guest_os_name, guest_os_id, created, is_user_defined) VALUES (UUID(),'Xenserver', '6.2.0', 'SUSE Linux Enterprise Server 10 SP3 (64-bit)', 45, now(), 0); +INSERT IGNORE INTO `cloud`.`guest_os_hypervisor` (uuid,hypervisor_type, hypervisor_version, guest_os_name, guest_os_id, created, is_user_defined) VALUES (UUID(),'Xenserver', '6.2.0', 'SUSE Linux Enterprise Server 10 SP4 (32-bit)', 153, now(), 0); +INSERT IGNORE INTO `cloud`.`guest_os_hypervisor` (uuid,hypervisor_type, hypervisor_version, guest_os_name, guest_os_id, created, is_user_defined) VALUES (UUID(),'Xenserver', '6.2.0', 'SUSE Linux Enterprise Server 10 SP4 (64-bit)', 152, now(), 0); +INSERT IGNORE INTO `cloud`.`guest_os_hypervisor` (uuid,hypervisor_type, hypervisor_version, guest_os_name, guest_os_id, created, is_user_defined) VALUES (UUID(),'Xenserver', '6.2.0', 'SUSE Linux Enterprise Server 11 (32-bit)', 46, now(), 0); +INSERT IGNORE INTO `cloud`.`guest_os_hypervisor` (uuid,hypervisor_type, hypervisor_version, guest_os_name, guest_os_id, created, is_user_defined) VALUES (UUID(),'Xenserver', '6.2.0', 'SUSE Linux Enterprise Server 11 (64-bit)', 47, now(), 0); +INSERT IGNORE INTO `cloud`.`guest_os_hypervisor` (uuid,hypervisor_type, hypervisor_version, guest_os_name, guest_os_id, created, is_user_defined) VALUES (UUID(),'Xenserver', '6.2.0', 'SUSE Linux Enterprise Server 11 SP1 (32-bit)', 155, now(), 0); +INSERT IGNORE INTO `cloud`.`guest_os_hypervisor` (uuid,hypervisor_type, hypervisor_version, guest_os_name, guest_os_id, created, is_user_defined) VALUES (UUID(),'Xenserver', '6.2.0', 'SUSE Linux Enterprise Server 11 SP1 (64-bit)', 154, now(), 0); +INSERT IGNORE INTO `cloud`.`guest_os_hypervisor` (uuid,hypervisor_type, hypervisor_version, guest_os_name, guest_os_id, created, is_user_defined) VALUES (UUID(),'Xenserver', '6.2.0', 'SUSE Linux Enterprise Server 11 SP2 (32-bit)', 186, now(), 0); +INSERT IGNORE INTO `cloud`.`guest_os_hypervisor` (uuid,hypervisor_type, hypervisor_version, guest_os_name, guest_os_id, created, is_user_defined) VALUES (UUID(),'Xenserver', '6.2.0', 'SUSE Linux Enterprise Server 11 SP2 (64-bit)', 185, now(), 0); +INSERT IGNORE INTO `cloud`.`guest_os_hypervisor` (uuid,hypervisor_type, hypervisor_version, guest_os_name, guest_os_id, created, is_user_defined) VALUES (UUID(),'Xenserver', '6.2.0', 'Windows 7 (32-bit)', 48, now(), 0); +INSERT IGNORE INTO `cloud`.`guest_os_hypervisor` (uuid,hypervisor_type, hypervisor_version, guest_os_name, guest_os_id, created, is_user_defined) VALUES (UUID(),'Xenserver', '6.2.0', 'Windows 7 (64-bit)', 49, now(), 0); +INSERT IGNORE INTO `cloud`.`guest_os_hypervisor` (uuid,hypervisor_type, hypervisor_version, guest_os_name, guest_os_id, created, is_user_defined) VALUES (UUID(),'Xenserver', '6.2.0', 'Windows 8 (32-bit)', 165, now(), 0); +INSERT IGNORE INTO `cloud`.`guest_os_hypervisor` (uuid,hypervisor_type, hypervisor_version, guest_os_name, guest_os_id, created, is_user_defined) VALUES (UUID(),'Xenserver', '6.2.0', 'Windows 8 (64-bit)', 166, now(), 0); +INSERT IGNORE INTO `cloud`.`guest_os_hypervisor` (uuid,hypervisor_type, hypervisor_version, guest_os_name, guest_os_id, created, is_user_defined) VALUES (UUID(),'Xenserver', '6.2.0', 'Windows Server 2003 (32-bit)', 50, now(), 0); +INSERT IGNORE INTO `cloud`.`guest_os_hypervisor` (uuid,hypervisor_type, hypervisor_version, guest_os_name, guest_os_id, created, is_user_defined) VALUES (UUID(),'Xenserver', '6.2.0', 'Windows Server 2003 (64-bit)', 51, now(), 0); +INSERT IGNORE INTO `cloud`.`guest_os_hypervisor` (uuid,hypervisor_type, hypervisor_version, guest_os_name, guest_os_id, created, is_user_defined) VALUES (UUID(),'Xenserver', '6.2.0', 'Windows Server 2003 (32-bit)', 87, now(), 0); +INSERT IGNORE INTO `cloud`.`guest_os_hypervisor` (uuid,hypervisor_type, hypervisor_version, guest_os_name, guest_os_id, created, is_user_defined) VALUES (UUID(),'Xenserver', '6.2.0', 'Windows Server 2003 (64-bit)', 88, now(), 0); +INSERT IGNORE INTO `cloud`.`guest_os_hypervisor` (uuid,hypervisor_type, hypervisor_version, guest_os_name, guest_os_id, created, is_user_defined) VALUES (UUID(),'Xenserver', '6.2.0', 'Windows Server 2003 (32-bit)', 89, now(), 0); +INSERT IGNORE INTO `cloud`.`guest_os_hypervisor` (uuid,hypervisor_type, hypervisor_version, guest_os_name, guest_os_id, created, is_user_defined) VALUES (UUID(),'Xenserver', '6.2.0', 'Windows Server 2003 (64-bit)', 90, now(), 0); +INSERT IGNORE INTO `cloud`.`guest_os_hypervisor` (uuid,hypervisor_type, hypervisor_version, guest_os_name, guest_os_id, created, is_user_defined) VALUES (UUID(),'Xenserver', '6.2.0', 'Windows Server 2008 R2 (64-bit)', 54, now(), 0); +INSERT IGNORE INTO `cloud`.`guest_os_hypervisor` (uuid,hypervisor_type, hypervisor_version, guest_os_name, guest_os_id, created, is_user_defined) VALUES (UUID(),'Xenserver', '6.2.0', 'Windows Server 2012 (64-bit)', 167, now(), 0); +INSERT IGNORE INTO `cloud`.`guest_os_hypervisor` (uuid,hypervisor_type, hypervisor_version, guest_os_name, guest_os_id, created, is_user_defined) VALUES (UUID(),'Xenserver', '6.2.0', 'Windows XP SP3 (32-bit)', 58, now(), 0); +INSERT IGNORE INTO `cloud`.`guest_os_hypervisor` (uuid,hypervisor_type, hypervisor_version, guest_os_name, guest_os_id, created, is_user_defined) VALUES (UUID(),'Xenserver', '6.2.0', 'Ubuntu Lucid Lynx 10.04 (32-bit)', 121, now(), 0); +INSERT IGNORE INTO `cloud`.`guest_os_hypervisor` (uuid,hypervisor_type, hypervisor_version, guest_os_name, guest_os_id, created, is_user_defined) VALUES (UUID(),'Xenserver', '6.2.0', 'Ubuntu Lucid Lynx 10.04 (64-bit)', 126, now(), 0); +INSERT IGNORE INTO `cloud`.`guest_os_hypervisor` (uuid,hypervisor_type, hypervisor_version, guest_os_name, guest_os_id, created, is_user_defined) VALUES (UUID(),'Xenserver', '6.2.0', 'Ubuntu Maverick Meerkat 10.10 (32-bit) (experimental)', 156, now(), 0); +INSERT IGNORE INTO `cloud`.`guest_os_hypervisor` (uuid,hypervisor_type, hypervisor_version, guest_os_name, guest_os_id, created, is_user_defined) VALUES (UUID(),'Xenserver', '6.2.0', 'Ubuntu Maverick Meerkat 10.10 (64-bit) (experimental)', 157, now(), 0); +INSERT IGNORE INTO `cloud`.`guest_os_hypervisor` (uuid,hypervisor_type, hypervisor_version, guest_os_name, guest_os_id, created, is_user_defined) VALUES (UUID(),'Xenserver', '6.2.0', 'Ubuntu Precise Pangolin 12.04 (32-bit)', 163, now(), 0); +INSERT IGNORE INTO `cloud`.`guest_os_hypervisor` (uuid,hypervisor_type, hypervisor_version, guest_os_name, guest_os_id, created, is_user_defined) VALUES (UUID(),'Xenserver', '6.2.0', 'Ubuntu Precise Pangolin 12.04 (64-bit)', 164, now(), 0); +INSERT IGNORE INTO `cloud`.`guest_os_hypervisor` (uuid,hypervisor_type, hypervisor_version, guest_os_name, guest_os_id, created, is_user_defined) VALUES (UUID(),'Xenserver', '6.2.0', 'Other install media', 169, now(), 0); +INSERT IGNORE INTO `cloud`.`guest_os_hypervisor` (uuid,hypervisor_type, hypervisor_version, guest_os_name, guest_os_id, created, is_user_defined) VALUES (UUID(),'Xenserver', '6.2.0', 'Other install media', 170, now(), 0); +INSERT IGNORE INTO `cloud`.`guest_os_hypervisor` (uuid,hypervisor_type, hypervisor_version, guest_os_name, guest_os_id, created, is_user_defined) VALUES (UUID(),'Xenserver', '6.2.0', 'Other install media', 98, now(), 0); +INSERT IGNORE INTO `cloud`.`guest_os_hypervisor` (uuid,hypervisor_type, hypervisor_version, guest_os_name, guest_os_id, created, is_user_defined) VALUES (UUID(),'Xenserver', '6.2.0', 'Other install media', 99, now(), 0); +INSERT IGNORE INTO `cloud`.`guest_os_hypervisor` (uuid,hypervisor_type, hypervisor_version, guest_os_name, guest_os_id, created, is_user_defined) VALUES (UUID(),'Xenserver', '6.2.0', 'Other install media', 60, now(), 0); +INSERT IGNORE INTO `cloud`.`guest_os_hypervisor` (uuid,hypervisor_type, hypervisor_version, guest_os_name, guest_os_id, created, is_user_defined) VALUES (UUID(),'Xenserver', '6.2.0', 'Other install media', 103, now(), 0); +INSERT IGNORE INTO `cloud`.`guest_os_hypervisor` (uuid,hypervisor_type, hypervisor_version, guest_os_name, guest_os_id, created, is_user_defined) VALUES (UUID(),'Xenserver', '6.2.0', 'Other install media', 200, now(), 0); +INSERT IGNORE INTO `cloud`.`guest_os_hypervisor` (uuid,hypervisor_type, hypervisor_version, guest_os_name, guest_os_id, created, is_user_defined) VALUES (UUID(),'Xenserver', '6.2.0', 'Other install media', 201, now(), 0); +INSERT IGNORE INTO `cloud`.`guest_os_hypervisor` (uuid,hypervisor_type, hypervisor_version, guest_os_name, guest_os_id, created, is_user_defined) VALUES (UUID(),'Xenserver', '6.2.0', 'Other install media', 59, now(), 0); +INSERT IGNORE INTO `cloud`.`guest_os_hypervisor` (uuid,hypervisor_type, hypervisor_version, guest_os_name, guest_os_id, created, is_user_defined) VALUES (UUID(),'Xenserver', '6.2.0', 'Other install media', 100, now(), 0); +INSERT IGNORE INTO `cloud`.`guest_os_hypervisor` (uuid,hypervisor_type, hypervisor_version, guest_os_name, guest_os_id, created, is_user_defined) VALUES (UUID(),'Xenserver', '6.2.0', 'Other install media', 202, now(), 0); +INSERT IGNORE INTO `cloud`.`guest_os_hypervisor` (uuid,hypervisor_type, hypervisor_version, guest_os_name, guest_os_id, created, is_user_defined) VALUES (UUID(),'Xenserver', '6.2.0', 'Other install media', 203, now(), 0); +INSERT IGNORE INTO `cloud`.`guest_os_hypervisor` (uuid,hypervisor_type, hypervisor_version, guest_os_name, guest_os_id, created, is_user_defined) VALUES (UUID(),'Xenserver', '6.2.0', 'CentOS 5 (32-bit)', 139, now(), 0); +INSERT IGNORE INTO `cloud`.`guest_os_hypervisor` (uuid,hypervisor_type, hypervisor_version, guest_os_name, guest_os_id, created, is_user_defined) VALUES (UUID(),'Xenserver', '6.2.0', 'CentOS 5 (64-bit)', 140, now(), 0); +INSERT IGNORE INTO `cloud`.`guest_os_hypervisor` (uuid,hypervisor_type, hypervisor_version, guest_os_name, guest_os_id, created, is_user_defined) VALUES (UUID(),'Xenserver', '6.2.5', 'CentOS 4.5 (32-bit)', 1, now(), 0); +INSERT IGNORE INTO `cloud`.`guest_os_hypervisor` (uuid,hypervisor_type, hypervisor_version, guest_os_name, guest_os_id, created, is_user_defined) VALUES (UUID(),'Xenserver', '6.2.5', 'CentOS 4.6 (32-bit)', 2, now(), 0); +INSERT IGNORE INTO `cloud`.`guest_os_hypervisor` (uuid,hypervisor_type, hypervisor_version, guest_os_name, guest_os_id, created, is_user_defined) VALUES (UUID(),'Xenserver', '6.2.5', 'CentOS 4.7 (32-bit)', 3, now(), 0); +INSERT IGNORE INTO `cloud`.`guest_os_hypervisor` (uuid,hypervisor_type, hypervisor_version, guest_os_name, guest_os_id, created, is_user_defined) VALUES (UUID(),'Xenserver', '6.2.5', 'CentOS 4.8 (32-bit)', 4, now(), 0); +INSERT IGNORE INTO `cloud`.`guest_os_hypervisor` (uuid,hypervisor_type, hypervisor_version, guest_os_name, guest_os_id, created, is_user_defined) VALUES (UUID(),'Xenserver', '6.2.5', 'CentOS 5 (32-bit)', 5, now(), 0); +INSERT IGNORE INTO `cloud`.`guest_os_hypervisor` (uuid,hypervisor_type, hypervisor_version, guest_os_name, guest_os_id, created, is_user_defined) VALUES (UUID(),'Xenserver', '6.2.5', 'CentOS 5 (64-bit)', 6, now(), 0); +INSERT IGNORE INTO `cloud`.`guest_os_hypervisor` (uuid,hypervisor_type, hypervisor_version, guest_os_name, guest_os_id, created, is_user_defined) VALUES (UUID(),'Xenserver', '6.2.5', 'CentOS 5 (32-bit)', 7, now(), 0); +INSERT IGNORE INTO `cloud`.`guest_os_hypervisor` (uuid,hypervisor_type, hypervisor_version, guest_os_name, guest_os_id, created, is_user_defined) VALUES (UUID(),'Xenserver', '6.2.5', 'CentOS 5 (64-bit)', 8, now(), 0); +INSERT IGNORE INTO `cloud`.`guest_os_hypervisor` (uuid,hypervisor_type, hypervisor_version, guest_os_name, guest_os_id, created, is_user_defined) VALUES (UUID(),'Xenserver', '6.2.5', 'CentOS 5 (32-bit)', 9, now(), 0); +INSERT IGNORE INTO `cloud`.`guest_os_hypervisor` (uuid,hypervisor_type, hypervisor_version, guest_os_name, guest_os_id, created, is_user_defined) VALUES (UUID(),'Xenserver', '6.2.5', 'CentOS 5 (64-bit)', 10, now(), 0); +INSERT IGNORE INTO `cloud`.`guest_os_hypervisor` (uuid,hypervisor_type, hypervisor_version, guest_os_name, guest_os_id, created, is_user_defined) VALUES (UUID(),'Xenserver', '6.2.5', 'CentOS 5 (32-bit)', 11, now(), 0); +INSERT IGNORE INTO `cloud`.`guest_os_hypervisor` (uuid,hypervisor_type, hypervisor_version, guest_os_name, guest_os_id, created, is_user_defined) VALUES (UUID(),'Xenserver', '6.2.5', 'CentOS 5 (64-bit)', 12, now(), 0); +INSERT IGNORE INTO `cloud`.`guest_os_hypervisor` (uuid,hypervisor_type, hypervisor_version, guest_os_name, guest_os_id, created, is_user_defined) VALUES (UUID(),'Xenserver', '6.2.5', 'CentOS 5 (32-bit)', 13, now(), 0); +INSERT IGNORE INTO `cloud`.`guest_os_hypervisor` (uuid,hypervisor_type, hypervisor_version, guest_os_name, guest_os_id, created, is_user_defined) VALUES (UUID(),'Xenserver', '6.2.5', 'CentOS 5 (64-bit)', 14, now(), 0); +INSERT IGNORE INTO `cloud`.`guest_os_hypervisor` (uuid,hypervisor_type, hypervisor_version, guest_os_name, guest_os_id, created, is_user_defined) VALUES (UUID(),'Xenserver', '6.2.5', 'CentOS 5 (32-bit)', 111, now(), 0); +INSERT IGNORE INTO `cloud`.`guest_os_hypervisor` (uuid,hypervisor_type, hypervisor_version, guest_os_name, guest_os_id, created, is_user_defined) VALUES (UUID(),'Xenserver', '6.2.5', 'CentOS 5 (64-bit)', 112, now(), 0); +INSERT IGNORE INTO `cloud`.`guest_os_hypervisor` (uuid,hypervisor_type, hypervisor_version, guest_os_name, guest_os_id, created, is_user_defined) VALUES (UUID(),'Xenserver', '6.2.5', 'CentOS 5 (32-bit)', 141, now(), 0); +INSERT IGNORE INTO `cloud`.`guest_os_hypervisor` (uuid,hypervisor_type, hypervisor_version, guest_os_name, guest_os_id, created, is_user_defined) VALUES (UUID(),'Xenserver', '6.2.5', 'CentOS 5 (64-bit)', 142, now(), 0); +INSERT IGNORE INTO `cloud`.`guest_os_hypervisor` (uuid,hypervisor_type, hypervisor_version, guest_os_name, guest_os_id, created, is_user_defined) VALUES (UUID(),'Xenserver', '6.2.5', 'CentOS 5 (32-bit)', 161, now(), 0); +INSERT IGNORE INTO `cloud`.`guest_os_hypervisor` (uuid,hypervisor_type, hypervisor_version, guest_os_name, guest_os_id, created, is_user_defined) VALUES (UUID(),'Xenserver', '6.2.5', 'CentOS 5 (64-bit)', 162, now(), 0); +INSERT IGNORE INTO `cloud`.`guest_os_hypervisor` (uuid,hypervisor_type, hypervisor_version, guest_os_name, guest_os_id, created, is_user_defined) VALUES (UUID(),'Xenserver', '6.2.5', 'CentOS 5 (32-bit)', 173, now(), 0); +INSERT IGNORE INTO `cloud`.`guest_os_hypervisor` (uuid,hypervisor_type, hypervisor_version, guest_os_name, guest_os_id, created, is_user_defined) VALUES (UUID(),'Xenserver', '6.2.5', 'CentOS 5 (64-bit)', 174, now(), 0); +INSERT IGNORE INTO `cloud`.`guest_os_hypervisor` (uuid,hypervisor_type, hypervisor_version, guest_os_name, guest_os_id, created, is_user_defined) VALUES (UUID(),'Xenserver', '6.2.5', 'CentOS 5 (32-bit)', 175, now(), 0); +INSERT IGNORE INTO `cloud`.`guest_os_hypervisor` (uuid,hypervisor_type, hypervisor_version, guest_os_name, guest_os_id, created, is_user_defined) VALUES (UUID(),'Xenserver', '6.2.5', 'CentOS 5 (64-bit)', 176, now(), 0); +INSERT IGNORE INTO `cloud`.`guest_os_hypervisor` (uuid,hypervisor_type, hypervisor_version, guest_os_name, guest_os_id, created, is_user_defined) VALUES (UUID(),'Xenserver', '6.2.5', 'CentOS 6 (32-bit)', 143, now(), 0); +INSERT IGNORE INTO `cloud`.`guest_os_hypervisor` (uuid,hypervisor_type, hypervisor_version, guest_os_name, guest_os_id, created, is_user_defined) VALUES (UUID(),'Xenserver', '6.2.5', 'CentOS 6 (64-bit)', 144, now(), 0); +INSERT IGNORE INTO `cloud`.`guest_os_hypervisor` (uuid,hypervisor_type, hypervisor_version, guest_os_name, guest_os_id, created, is_user_defined) VALUES (UUID(),'Xenserver', '6.2.5', 'CentOS 6 (32-bit)', 177, now(), 0); +INSERT IGNORE INTO `cloud`.`guest_os_hypervisor` (uuid,hypervisor_type, hypervisor_version, guest_os_name, guest_os_id, created, is_user_defined) VALUES (UUID(),'Xenserver', '6.2.5', 'CentOS 6 (64-bit)', 178, now(), 0); +INSERT IGNORE INTO `cloud`.`guest_os_hypervisor` (uuid,hypervisor_type, hypervisor_version, guest_os_name, guest_os_id, created, is_user_defined) VALUES (UUID(),'Xenserver', '6.2.5', 'CentOS 6 (32-bit)', 179, now(), 0); +INSERT IGNORE INTO `cloud`.`guest_os_hypervisor` (uuid,hypervisor_type, hypervisor_version, guest_os_name, guest_os_id, created, is_user_defined) VALUES (UUID(),'Xenserver', '6.2.5', 'CentOS 6 (64-bit)', 180, now(), 0); +INSERT IGNORE INTO `cloud`.`guest_os_hypervisor` (uuid,hypervisor_type, hypervisor_version, guest_os_name, guest_os_id, created, is_user_defined) VALUES (UUID(),'Xenserver', '6.2.5', 'CentOS 6 (32-bit)', 171, now(), 0); +INSERT IGNORE INTO `cloud`.`guest_os_hypervisor` (uuid,hypervisor_type, hypervisor_version, guest_os_name, guest_os_id, created, is_user_defined) VALUES (UUID(),'Xenserver', '6.2.5', 'CentOS 6 (64-bit)', 172, now(), 0); +INSERT IGNORE INTO `cloud`.`guest_os_hypervisor` (uuid,hypervisor_type, hypervisor_version, guest_os_name, guest_os_id, created, is_user_defined) VALUES (UUID(),'Xenserver', '6.2.5', 'CentOS 6 (32-bit)', 181, now(), 0); +INSERT IGNORE INTO `cloud`.`guest_os_hypervisor` (uuid,hypervisor_type, hypervisor_version, guest_os_name, guest_os_id, created, is_user_defined) VALUES (UUID(),'Xenserver', '6.2.5', 'CentOS 6 (64-bit)', 182, now(), 0); +INSERT IGNORE INTO `cloud`.`guest_os_hypervisor` (uuid,hypervisor_type, hypervisor_version, guest_os_name, guest_os_id, created, is_user_defined) VALUES (UUID(),'Xenserver', '6.2.5', 'Debian Squeeze 6.0 (32-bit)', 132, now(), 0); +INSERT IGNORE INTO `cloud`.`guest_os_hypervisor` (uuid,hypervisor_type, hypervisor_version, guest_os_name, guest_os_id, created, is_user_defined) VALUES (UUID(),'Xenserver', '6.2.5', 'Debian Squeeze 6.0 (64-bit)', 133, now(), 0); +INSERT IGNORE INTO `cloud`.`guest_os_hypervisor` (uuid,hypervisor_type, hypervisor_version, guest_os_name, guest_os_id, created, is_user_defined) VALUES (UUID(),'Xenserver', '6.2.5', 'Debian Wheezy 7.0 (32-bit)', 183, now(), 0); +INSERT IGNORE INTO `cloud`.`guest_os_hypervisor` (uuid,hypervisor_type, hypervisor_version, guest_os_name, guest_os_id, created, is_user_defined) VALUES (UUID(),'Xenserver', '6.2.5', 'Debian Wheezy 7.0 (64-bit)', 184, now(), 0); +INSERT IGNORE INTO `cloud`.`guest_os_hypervisor` (uuid,hypervisor_type, hypervisor_version, guest_os_name, guest_os_id, created, is_user_defined) VALUES (UUID(),'Xenserver', '6.2.5', 'Oracle Enterprise Linux 5 (32-bit)', 16, now(), 0); +INSERT IGNORE INTO `cloud`.`guest_os_hypervisor` (uuid,hypervisor_type, hypervisor_version, guest_os_name, guest_os_id, created, is_user_defined) VALUES (UUID(),'Xenserver', '6.2.5', 'Oracle Enterprise Linux 5 (64-bit)', 17, now(), 0); +INSERT IGNORE INTO `cloud`.`guest_os_hypervisor` (uuid,hypervisor_type, hypervisor_version, guest_os_name, guest_os_id, created, is_user_defined) VALUES (UUID(),'Xenserver', '6.2.5', 'Oracle Enterprise Linux 5 (32-bit)', 18, now(), 0); +INSERT IGNORE INTO `cloud`.`guest_os_hypervisor` (uuid,hypervisor_type, hypervisor_version, guest_os_name, guest_os_id, created, is_user_defined) VALUES (UUID(),'Xenserver', '6.2.5', 'Oracle Enterprise Linux 5 (64-bit)', 19, now(), 0); +INSERT IGNORE INTO `cloud`.`guest_os_hypervisor` (uuid,hypervisor_type, hypervisor_version, guest_os_name, guest_os_id, created, is_user_defined) VALUES (UUID(),'Xenserver', '6.2.5', 'Oracle Enterprise Linux 5 (32-bit)', 20, now(), 0); +INSERT IGNORE INTO `cloud`.`guest_os_hypervisor` (uuid,hypervisor_type, hypervisor_version, guest_os_name, guest_os_id, created, is_user_defined) VALUES (UUID(),'Xenserver', '6.2.5', 'Oracle Enterprise Linux 5 (64-bit)', 21, now(), 0); +INSERT IGNORE INTO `cloud`.`guest_os_hypervisor` (uuid,hypervisor_type, hypervisor_version, guest_os_name, guest_os_id, created, is_user_defined) VALUES (UUID(),'Xenserver', '6.2.5', 'Oracle Enterprise Linux 5 (32-bit)', 22, now(), 0); +INSERT IGNORE INTO `cloud`.`guest_os_hypervisor` (uuid,hypervisor_type, hypervisor_version, guest_os_name, guest_os_id, created, is_user_defined) VALUES (UUID(),'Xenserver', '6.2.5', 'Oracle Enterprise Linux 5 (64-bit)', 23, now(), 0); +INSERT IGNORE INTO `cloud`.`guest_os_hypervisor` (uuid,hypervisor_type, hypervisor_version, guest_os_name, guest_os_id, created, is_user_defined) VALUES (UUID(),'Xenserver', '6.2.5', 'Oracle Enterprise Linux 5 (32-bit)', 24, now(), 0); +INSERT IGNORE INTO `cloud`.`guest_os_hypervisor` (uuid,hypervisor_type, hypervisor_version, guest_os_name, guest_os_id, created, is_user_defined) VALUES (UUID(),'Xenserver', '6.2.5', 'Oracle Enterprise Linux 5 (64-bit)', 25, now(), 0); +INSERT IGNORE INTO `cloud`.`guest_os_hypervisor` (uuid,hypervisor_type, hypervisor_version, guest_os_name, guest_os_id, created, is_user_defined) VALUES (UUID(),'Xenserver', '6.2.5', 'Oracle Enterprise Linux 5 (32-bit)', 134, now(), 0); +INSERT IGNORE INTO `cloud`.`guest_os_hypervisor` (uuid,hypervisor_type, hypervisor_version, guest_os_name, guest_os_id, created, is_user_defined) VALUES (UUID(),'Xenserver', '6.2.5', 'Oracle Enterprise Linux 5 (64-bit)', 135, now(), 0); +INSERT IGNORE INTO `cloud`.`guest_os_hypervisor` (uuid,hypervisor_type, hypervisor_version, guest_os_name, guest_os_id, created, is_user_defined) VALUES (UUID(),'Xenserver', '6.2.5', 'Oracle Enterprise Linux 5 (32-bit)', 145, now(), 0); +INSERT IGNORE INTO `cloud`.`guest_os_hypervisor` (uuid,hypervisor_type, hypervisor_version, guest_os_name, guest_os_id, created, is_user_defined) VALUES (UUID(),'Xenserver', '6.2.5', 'Oracle Enterprise Linux 5 (64-bit)', 146, now(), 0); +INSERT IGNORE INTO `cloud`.`guest_os_hypervisor` (uuid,hypervisor_type, hypervisor_version, guest_os_name, guest_os_id, created, is_user_defined) VALUES (UUID(),'Xenserver', '6.2.5', 'Oracle Enterprise Linux 5 (32-bit)', 207, now(), 0); +INSERT IGNORE INTO `cloud`.`guest_os_hypervisor` (uuid,hypervisor_type, hypervisor_version, guest_os_name, guest_os_id, created, is_user_defined) VALUES (UUID(),'Xenserver', '6.2.5', 'Oracle Enterprise Linux 5 (64-bit)', 208, now(), 0); +INSERT IGNORE INTO `cloud`.`guest_os_hypervisor` (uuid,hypervisor_type, hypervisor_version, guest_os_name, guest_os_id, created, is_user_defined) VALUES (UUID(),'Xenserver', '6.2.5', 'Oracle Enterprise Linux 5 (32-bit)', 209, now(), 0); +INSERT IGNORE INTO `cloud`.`guest_os_hypervisor` (uuid,hypervisor_type, hypervisor_version, guest_os_name, guest_os_id, created, is_user_defined) VALUES (UUID(),'Xenserver', '6.2.5', 'Oracle Enterprise Linux 5 (64-bit)', 210, now(), 0); +INSERT IGNORE INTO `cloud`.`guest_os_hypervisor` (uuid,hypervisor_type, hypervisor_version, guest_os_name, guest_os_id, created, is_user_defined) VALUES (UUID(),'Xenserver', '6.2.5', 'Oracle Enterprise Linux 5 (32-bit)', 211, now(), 0); +INSERT IGNORE INTO `cloud`.`guest_os_hypervisor` (uuid,hypervisor_type, hypervisor_version, guest_os_name, guest_os_id, created, is_user_defined) VALUES (UUID(),'Xenserver', '6.2.5', 'Oracle Enterprise Linux 5 (64-bit)', 212, now(), 0); +INSERT IGNORE INTO `cloud`.`guest_os_hypervisor` (uuid,hypervisor_type, hypervisor_version, guest_os_name, guest_os_id, created, is_user_defined) VALUES (UUID(),'Xenserver', '6.2.5', 'Oracle Enterprise Linux 6 (32-bit)', 147, now(), 0); +INSERT IGNORE INTO `cloud`.`guest_os_hypervisor` (uuid,hypervisor_type, hypervisor_version, guest_os_name, guest_os_id, created, is_user_defined) VALUES (UUID(),'Xenserver', '6.2.5', 'Oracle Enterprise Linux 6 (64-bit)', 148, now(), 0); +INSERT IGNORE INTO `cloud`.`guest_os_hypervisor` (uuid,hypervisor_type, hypervisor_version, guest_os_name, guest_os_id, created, is_user_defined) VALUES (UUID(),'Xenserver', '6.2.5', 'Oracle Enterprise Linux 6 (32-bit)', 213, now(), 0); +INSERT IGNORE INTO `cloud`.`guest_os_hypervisor` (uuid,hypervisor_type, hypervisor_version, guest_os_name, guest_os_id, created, is_user_defined) VALUES (UUID(),'Xenserver', '6.2.5', 'Oracle Enterprise Linux 6 (64-bit)', 214, now(), 0); +INSERT IGNORE INTO `cloud`.`guest_os_hypervisor` (uuid,hypervisor_type, hypervisor_version, guest_os_name, guest_os_id, created, is_user_defined) VALUES (UUID(),'Xenserver', '6.2.5', 'Oracle Enterprise Linux 6 (32-bit)', 215, now(), 0); +INSERT IGNORE INTO `cloud`.`guest_os_hypervisor` (uuid,hypervisor_type, hypervisor_version, guest_os_name, guest_os_id, created, is_user_defined) VALUES (UUID(),'Xenserver', '6.2.5', 'Oracle Enterprise Linux 6 (64-bit)', 216, now(), 0); +INSERT IGNORE INTO `cloud`.`guest_os_hypervisor` (uuid,hypervisor_type, hypervisor_version, guest_os_name, guest_os_id, created, is_user_defined) VALUES (UUID(),'Xenserver', '6.2.5', 'Oracle Enterprise Linux 6 (32-bit)', 217, now(), 0); +INSERT IGNORE INTO `cloud`.`guest_os_hypervisor` (uuid,hypervisor_type, hypervisor_version, guest_os_name, guest_os_id, created, is_user_defined) VALUES (UUID(),'Xenserver', '6.2.5', 'Oracle Enterprise Linux 6 (64-bit)', 218, now(), 0); +INSERT IGNORE INTO `cloud`.`guest_os_hypervisor` (uuid,hypervisor_type, hypervisor_version, guest_os_name, guest_os_id, created, is_user_defined) VALUES (UUID(),'Xenserver', '6.2.5', 'Oracle Enterprise Linux 6 (32-bit)', 219, now(), 0); +INSERT IGNORE INTO `cloud`.`guest_os_hypervisor` (uuid,hypervisor_type, hypervisor_version, guest_os_name, guest_os_id, created, is_user_defined) VALUES (UUID(),'Xenserver', '6.2.5', 'Oracle Enterprise Linux 6 (64-bit)', 220, now(), 0); +INSERT IGNORE INTO `cloud`.`guest_os_hypervisor` (uuid,hypervisor_type, hypervisor_version, guest_os_name, guest_os_id, created, is_user_defined) VALUES (UUID(),'Xenserver', '6.2.5', 'Red Hat Enterprise Linux 4.5 (32-bit)', 26, now(), 0); +INSERT IGNORE INTO `cloud`.`guest_os_hypervisor` (uuid,hypervisor_type, hypervisor_version, guest_os_name, guest_os_id, created, is_user_defined) VALUES (UUID(),'Xenserver', '6.2.5', 'Red Hat Enterprise Linux 4.6 (32-bit)', 27, now(), 0); +INSERT IGNORE INTO `cloud`.`guest_os_hypervisor` (uuid,hypervisor_type, hypervisor_version, guest_os_name, guest_os_id, created, is_user_defined) VALUES (UUID(),'Xenserver', '6.2.5', 'Red Hat Enterprise Linux 4.7 (32-bit)', 28, now(), 0); +INSERT IGNORE INTO `cloud`.`guest_os_hypervisor` (uuid,hypervisor_type, hypervisor_version, guest_os_name, guest_os_id, created, is_user_defined) VALUES (UUID(),'Xenserver', '6.2.5', 'Red Hat Enterprise Linux 4.8 (32-bit)', 29, now(), 0); +INSERT IGNORE INTO `cloud`.`guest_os_hypervisor` (uuid,hypervisor_type, hypervisor_version, guest_os_name, guest_os_id, created, is_user_defined) VALUES (UUID(),'Xenserver', '6.2.5', 'Red Hat Enterprise Linux 5 (32-bit)', 30, now(), 0); +INSERT IGNORE INTO `cloud`.`guest_os_hypervisor` (uuid,hypervisor_type, hypervisor_version, guest_os_name, guest_os_id, created, is_user_defined) VALUES (UUID(),'Xenserver', '6.2.5', 'Red Hat Enterprise Linux 5 (64-bit)', 31, now(), 0); +INSERT IGNORE INTO `cloud`.`guest_os_hypervisor` (uuid,hypervisor_type, hypervisor_version, guest_os_name, guest_os_id, created, is_user_defined) VALUES (UUID(),'Xenserver', '6.2.5', 'Red Hat Enterprise Linux 5 (32-bit)', 32, now(), 0); +INSERT IGNORE INTO `cloud`.`guest_os_hypervisor` (uuid,hypervisor_type, hypervisor_version, guest_os_name, guest_os_id, created, is_user_defined) VALUES (UUID(),'Xenserver', '6.2.5', 'Red Hat Enterprise Linux 5 (64-bit)', 33, now(), 0); +INSERT IGNORE INTO `cloud`.`guest_os_hypervisor` (uuid,hypervisor_type, hypervisor_version, guest_os_name, guest_os_id, created, is_user_defined) VALUES (UUID(),'Xenserver', '6.2.5', 'Red Hat Enterprise Linux 5 (32-bit)', 34, now(), 0); +INSERT IGNORE INTO `cloud`.`guest_os_hypervisor` (uuid,hypervisor_type, hypervisor_version, guest_os_name, guest_os_id, created, is_user_defined) VALUES (UUID(),'Xenserver', '6.2.5', 'Red Hat Enterprise Linux 5 (64-bit)', 35, now(), 0); +INSERT IGNORE INTO `cloud`.`guest_os_hypervisor` (uuid,hypervisor_type, hypervisor_version, guest_os_name, guest_os_id, created, is_user_defined) VALUES (UUID(),'Xenserver', '6.2.5', 'Red Hat Enterprise Linux 5 (32-bit)', 36, now(), 0); +INSERT IGNORE INTO `cloud`.`guest_os_hypervisor` (uuid,hypervisor_type, hypervisor_version, guest_os_name, guest_os_id, created, is_user_defined) VALUES (UUID(),'Xenserver', '6.2.5', 'Red Hat Enterprise Linux 5 (64-bit)', 37, now(), 0); +INSERT IGNORE INTO `cloud`.`guest_os_hypervisor` (uuid,hypervisor_type, hypervisor_version, guest_os_name, guest_os_id, created, is_user_defined) VALUES (UUID(),'Xenserver', '6.2.5', 'Red Hat Enterprise Linux 5 (32-bit)', 38, now(), 0); +INSERT IGNORE INTO `cloud`.`guest_os_hypervisor` (uuid,hypervisor_type, hypervisor_version, guest_os_name, guest_os_id, created, is_user_defined) VALUES (UUID(),'Xenserver', '6.2.5', 'Red Hat Enterprise Linux 5 (64-bit)', 39, now(), 0); +INSERT IGNORE INTO `cloud`.`guest_os_hypervisor` (uuid,hypervisor_type, hypervisor_version, guest_os_name, guest_os_id, created, is_user_defined) VALUES (UUID(),'Xenserver', '6.2.5', 'Red Hat Enterprise Linux 5 (32-bit)', 113, now(), 0); +INSERT IGNORE INTO `cloud`.`guest_os_hypervisor` (uuid,hypervisor_type, hypervisor_version, guest_os_name, guest_os_id, created, is_user_defined) VALUES (UUID(),'Xenserver', '6.2.5', 'Red Hat Enterprise Linux 5 (64-bit)', 114, now(), 0); +INSERT IGNORE INTO `cloud`.`guest_os_hypervisor` (uuid,hypervisor_type, hypervisor_version, guest_os_name, guest_os_id, created, is_user_defined) VALUES (UUID(),'Xenserver', '6.2.5', 'Red Hat Enterprise Linux 5 (32-bit)', 149, now(), 0); +INSERT IGNORE INTO `cloud`.`guest_os_hypervisor` (uuid,hypervisor_type, hypervisor_version, guest_os_name, guest_os_id, created, is_user_defined) VALUES (UUID(),'Xenserver', '6.2.5', 'Red Hat Enterprise Linux 5 (64-bit)', 150, now(), 0); +INSERT IGNORE INTO `cloud`.`guest_os_hypervisor` (uuid,hypervisor_type, hypervisor_version, guest_os_name, guest_os_id, created, is_user_defined) VALUES (UUID(),'Xenserver', '6.2.5', 'Red Hat Enterprise Linux 5 (32-bit)', 189, now(), 0); +INSERT IGNORE INTO `cloud`.`guest_os_hypervisor` (uuid,hypervisor_type, hypervisor_version, guest_os_name, guest_os_id, created, is_user_defined) VALUES (UUID(),'Xenserver', '6.2.5', 'Red Hat Enterprise Linux 5 (64-bit)', 190, now(), 0); +INSERT IGNORE INTO `cloud`.`guest_os_hypervisor` (uuid,hypervisor_type, hypervisor_version, guest_os_name, guest_os_id, created, is_user_defined) VALUES (UUID(),'Xenserver', '6.2.5', 'Red Hat Enterprise Linux 5 (32-bit)', 191, now(), 0); +INSERT IGNORE INTO `cloud`.`guest_os_hypervisor` (uuid,hypervisor_type, hypervisor_version, guest_os_name, guest_os_id, created, is_user_defined) VALUES (UUID(),'Xenserver', '6.2.5', 'Red Hat Enterprise Linux 5 (64-bit)', 192, now(), 0); +INSERT IGNORE INTO `cloud`.`guest_os_hypervisor` (uuid,hypervisor_type, hypervisor_version, guest_os_name, guest_os_id, created, is_user_defined) VALUES (UUID(),'Xenserver', '6.2.5', 'Red Hat Enterprise Linux 5 (32-bit)', 193, now(), 0); +INSERT IGNORE INTO `cloud`.`guest_os_hypervisor` (uuid,hypervisor_type, hypervisor_version, guest_os_name, guest_os_id, created, is_user_defined) VALUES (UUID(),'Xenserver', '6.2.5', 'Red Hat Enterprise Linux 5 (64-bit)', 194, now(), 0); +INSERT IGNORE INTO `cloud`.`guest_os_hypervisor` (uuid,hypervisor_type, hypervisor_version, guest_os_name, guest_os_id, created, is_user_defined) VALUES (UUID(),'Xenserver', '6.2.5', 'Red Hat Enterprise Linux 6 (32-bit)', 136, now(), 0); +INSERT IGNORE INTO `cloud`.`guest_os_hypervisor` (uuid,hypervisor_type, hypervisor_version, guest_os_name, guest_os_id, created, is_user_defined) VALUES (UUID(),'Xenserver', '6.2.5', 'Red Hat Enterprise Linux 6 (64-bit)', 137, now(), 0); +INSERT IGNORE INTO `cloud`.`guest_os_hypervisor` (uuid,hypervisor_type, hypervisor_version, guest_os_name, guest_os_id, created, is_user_defined) VALUES (UUID(),'Xenserver', '6.2.5', 'Red Hat Enterprise Linux 6 (32-bit)', 195, now(), 0); +INSERT IGNORE INTO `cloud`.`guest_os_hypervisor` (uuid,hypervisor_type, hypervisor_version, guest_os_name, guest_os_id, created, is_user_defined) VALUES (UUID(),'Xenserver', '6.2.5', 'Red Hat Enterprise Linux 6 (64-bit)', 196, now(), 0); +INSERT IGNORE INTO `cloud`.`guest_os_hypervisor` (uuid,hypervisor_type, hypervisor_version, guest_os_name, guest_os_id, created, is_user_defined) VALUES (UUID(),'Xenserver', '6.2.5', 'Red Hat Enterprise Linux 6 (32-bit)', 197, now(), 0); +INSERT IGNORE INTO `cloud`.`guest_os_hypervisor` (uuid,hypervisor_type, hypervisor_version, guest_os_name, guest_os_id, created, is_user_defined) VALUES (UUID(),'Xenserver', '6.2.5', 'Red Hat Enterprise Linux 6 (64-bit)', 198, now(), 0); +INSERT IGNORE INTO `cloud`.`guest_os_hypervisor` (uuid,hypervisor_type, hypervisor_version, guest_os_name, guest_os_id, created, is_user_defined) VALUES (UUID(),'Xenserver', '6.2.5', 'Red Hat Enterprise Linux 6 (32-bit)', 199, now(), 0); +INSERT IGNORE INTO `cloud`.`guest_os_hypervisor` (uuid,hypervisor_type, hypervisor_version, guest_os_name, guest_os_id, created, is_user_defined) VALUES (UUID(),'Xenserver', '6.2.5', 'Red Hat Enterprise Linux 6 (64-bit)', 204, now(), 0); +INSERT IGNORE INTO `cloud`.`guest_os_hypervisor` (uuid,hypervisor_type, hypervisor_version, guest_os_name, guest_os_id, created, is_user_defined) VALUES (UUID(),'Xenserver', '6.2.5', 'Red Hat Enterprise Linux 6 (32-bit)', 205, now(), 0); +INSERT IGNORE INTO `cloud`.`guest_os_hypervisor` (uuid,hypervisor_type, hypervisor_version, guest_os_name, guest_os_id, created, is_user_defined) VALUES (UUID(),'Xenserver', '6.2.5', 'Red Hat Enterprise Linux 6 (64-bit)', 206, now(), 0); +INSERT IGNORE INTO `cloud`.`guest_os_hypervisor` (uuid,hypervisor_type, hypervisor_version, guest_os_name, guest_os_id, created, is_user_defined) VALUES (UUID(),'Xenserver', '6.2.5', 'SUSE Linux Enterprise Server 10 SP1 (32-bit)', 41, now(), 0); +INSERT IGNORE INTO `cloud`.`guest_os_hypervisor` (uuid,hypervisor_type, hypervisor_version, guest_os_name, guest_os_id, created, is_user_defined) VALUES (UUID(),'Xenserver', '6.2.5', 'SUSE Linux Enterprise Server 10 SP1 (64-bit)', 42, now(), 0); +INSERT IGNORE INTO `cloud`.`guest_os_hypervisor` (uuid,hypervisor_type, hypervisor_version, guest_os_name, guest_os_id, created, is_user_defined) VALUES (UUID(),'Xenserver', '6.2.5', 'SUSE Linux Enterprise Server 10 SP2 (32-bit)', 43, now(), 0); +INSERT IGNORE INTO `cloud`.`guest_os_hypervisor` (uuid,hypervisor_type, hypervisor_version, guest_os_name, guest_os_id, created, is_user_defined) VALUES (UUID(),'Xenserver', '6.2.5', 'SUSE Linux Enterprise Server 10 SP2 (64-bit)', 44, now(), 0); +INSERT IGNORE INTO `cloud`.`guest_os_hypervisor` (uuid,hypervisor_type, hypervisor_version, guest_os_name, guest_os_id, created, is_user_defined) VALUES (UUID(),'Xenserver', '6.2.5', 'SUSE Linux Enterprise Server 10 SP3 (32-bit)', 151, now(), 0); +INSERT IGNORE INTO `cloud`.`guest_os_hypervisor` (uuid,hypervisor_type, hypervisor_version, guest_os_name, guest_os_id, created, is_user_defined) VALUES (UUID(),'Xenserver', '6.2.5', 'SUSE Linux Enterprise Server 10 SP3 (64-bit)', 45, now(), 0); +INSERT IGNORE INTO `cloud`.`guest_os_hypervisor` (uuid,hypervisor_type, hypervisor_version, guest_os_name, guest_os_id, created, is_user_defined) VALUES (UUID(),'Xenserver', '6.2.5', 'SUSE Linux Enterprise Server 10 SP4 (32-bit)', 153, now(), 0); +INSERT IGNORE INTO `cloud`.`guest_os_hypervisor` (uuid,hypervisor_type, hypervisor_version, guest_os_name, guest_os_id, created, is_user_defined) VALUES (UUID(),'Xenserver', '6.2.5', 'SUSE Linux Enterprise Server 10 SP4 (64-bit)', 152, now(), 0); +INSERT IGNORE INTO `cloud`.`guest_os_hypervisor` (uuid,hypervisor_type, hypervisor_version, guest_os_name, guest_os_id, created, is_user_defined) VALUES (UUID(),'Xenserver', '6.2.5', 'SUSE Linux Enterprise Server 11 (32-bit)', 46, now(), 0); +INSERT IGNORE INTO `cloud`.`guest_os_hypervisor` (uuid,hypervisor_type, hypervisor_version, guest_os_name, guest_os_id, created, is_user_defined) VALUES (UUID(),'Xenserver', '6.2.5', 'SUSE Linux Enterprise Server 11 (64-bit)', 47, now(), 0); +INSERT IGNORE INTO `cloud`.`guest_os_hypervisor` (uuid,hypervisor_type, hypervisor_version, guest_os_name, guest_os_id, created, is_user_defined) VALUES (UUID(),'Xenserver', '6.2.5', 'SUSE Linux Enterprise Server 11 SP1 (32-bit)', 155, now(), 0); +INSERT IGNORE INTO `cloud`.`guest_os_hypervisor` (uuid,hypervisor_type, hypervisor_version, guest_os_name, guest_os_id, created, is_user_defined) VALUES (UUID(),'Xenserver', '6.2.5', 'SUSE Linux Enterprise Server 11 SP1 (64-bit)', 154, now(), 0); +INSERT IGNORE INTO `cloud`.`guest_os_hypervisor` (uuid,hypervisor_type, hypervisor_version, guest_os_name, guest_os_id, created, is_user_defined) VALUES (UUID(),'Xenserver', '6.2.5', 'SUSE Linux Enterprise Server 11 SP2 (32-bit)', 186, now(), 0); +INSERT IGNORE INTO `cloud`.`guest_os_hypervisor` (uuid,hypervisor_type, hypervisor_version, guest_os_name, guest_os_id, created, is_user_defined) VALUES (UUID(),'Xenserver', '6.2.5', 'SUSE Linux Enterprise Server 11 SP2 (64-bit)', 185, now(), 0); +INSERT IGNORE INTO `cloud`.`guest_os_hypervisor` (uuid,hypervisor_type, hypervisor_version, guest_os_name, guest_os_id, created, is_user_defined) VALUES (UUID(),'Xenserver', '6.2.5', 'Windows 7 (32-bit)', 48, now(), 0); +INSERT IGNORE INTO `cloud`.`guest_os_hypervisor` (uuid,hypervisor_type, hypervisor_version, guest_os_name, guest_os_id, created, is_user_defined) VALUES (UUID(),'Xenserver', '6.2.5', 'Windows 7 (64-bit)', 49, now(), 0); +INSERT IGNORE INTO `cloud`.`guest_os_hypervisor` (uuid,hypervisor_type, hypervisor_version, guest_os_name, guest_os_id, created, is_user_defined) VALUES (UUID(),'Xenserver', '6.2.5', 'Windows 8 (32-bit)', 165, now(), 0); +INSERT IGNORE INTO `cloud`.`guest_os_hypervisor` (uuid,hypervisor_type, hypervisor_version, guest_os_name, guest_os_id, created, is_user_defined) VALUES (UUID(),'Xenserver', '6.2.5', 'Windows 8 (64-bit)', 166, now(), 0); +INSERT IGNORE INTO `cloud`.`guest_os_hypervisor` (uuid,hypervisor_type, hypervisor_version, guest_os_name, guest_os_id, created, is_user_defined) VALUES (UUID(),'Xenserver', '6.2.5', 'Windows Server 2003 (32-bit)', 50, now(), 0); +INSERT IGNORE INTO `cloud`.`guest_os_hypervisor` (uuid,hypervisor_type, hypervisor_version, guest_os_name, guest_os_id, created, is_user_defined) VALUES (UUID(),'Xenserver', '6.2.5', 'Windows Server 2003 (64-bit)', 51, now(), 0); +INSERT IGNORE INTO `cloud`.`guest_os_hypervisor` (uuid,hypervisor_type, hypervisor_version, guest_os_name, guest_os_id, created, is_user_defined) VALUES (UUID(),'Xenserver', '6.2.5', 'Windows Server 2003 (32-bit)', 87, now(), 0); +INSERT IGNORE INTO `cloud`.`guest_os_hypervisor` (uuid,hypervisor_type, hypervisor_version, guest_os_name, guest_os_id, created, is_user_defined) VALUES (UUID(),'Xenserver', '6.2.5', 'Windows Server 2003 (64-bit)', 88, now(), 0); +INSERT IGNORE INTO `cloud`.`guest_os_hypervisor` (uuid,hypervisor_type, hypervisor_version, guest_os_name, guest_os_id, created, is_user_defined) VALUES (UUID(),'Xenserver', '6.2.5', 'Windows Server 2003 (32-bit)', 89, now(), 0); +INSERT IGNORE INTO `cloud`.`guest_os_hypervisor` (uuid,hypervisor_type, hypervisor_version, guest_os_name, guest_os_id, created, is_user_defined) VALUES (UUID(),'Xenserver', '6.2.5', 'Windows Server 2003 (64-bit)', 90, now(), 0); +INSERT IGNORE INTO `cloud`.`guest_os_hypervisor` (uuid,hypervisor_type, hypervisor_version, guest_os_name, guest_os_id, created, is_user_defined) VALUES (UUID(),'Xenserver', '6.2.5', 'Windows Server 2008 R2 (64-bit)', 54, now(), 0); +INSERT IGNORE INTO `cloud`.`guest_os_hypervisor` (uuid,hypervisor_type, hypervisor_version, guest_os_name, guest_os_id, created, is_user_defined) VALUES (UUID(),'Xenserver', '6.2.5', 'Windows Server 2012 (64-bit)', 167, now(), 0); +INSERT IGNORE INTO `cloud`.`guest_os_hypervisor` (uuid,hypervisor_type, hypervisor_version, guest_os_name, guest_os_id, created, is_user_defined) VALUES (UUID(),'Xenserver', '6.2.5', 'Windows Server 2012 (64-bit)', 168, now(), 0); +INSERT IGNORE INTO `cloud`.`guest_os_hypervisor` (uuid,hypervisor_type, hypervisor_version, guest_os_name, guest_os_id, created, is_user_defined) VALUES (UUID(),'Xenserver', '6.2.5', 'Windows XP SP3 (32-bit)', 58, now(), 0); +INSERT IGNORE INTO `cloud`.`guest_os_hypervisor` (uuid,hypervisor_type, hypervisor_version, guest_os_name, guest_os_id, created, is_user_defined) VALUES (UUID(),'Xenserver', '6.2.5', 'Ubuntu Lucid Lynx 10.04 (32-bit)', 121, now(), 0); +INSERT IGNORE INTO `cloud`.`guest_os_hypervisor` (uuid,hypervisor_type, hypervisor_version, guest_os_name, guest_os_id, created, is_user_defined) VALUES (UUID(),'Xenserver', '6.2.5', 'Ubuntu Lucid Lynx 10.04 (64-bit)', 126, now(), 0); +INSERT IGNORE INTO `cloud`.`guest_os_hypervisor` (uuid,hypervisor_type, hypervisor_version, guest_os_name, guest_os_id, created, is_user_defined) VALUES (UUID(),'Xenserver', '6.2.5', 'Ubuntu Maverick Meerkat 10.10 (32-bit) (experimental)', 156, now(), 0); +INSERT IGNORE INTO `cloud`.`guest_os_hypervisor` (uuid,hypervisor_type, hypervisor_version, guest_os_name, guest_os_id, created, is_user_defined) VALUES (UUID(),'Xenserver', '6.2.5', 'Ubuntu Maverick Meerkat 10.10 (64-bit) (experimental)', 157, now(), 0); +INSERT IGNORE INTO `cloud`.`guest_os_hypervisor` (uuid,hypervisor_type, hypervisor_version, guest_os_name, guest_os_id, created, is_user_defined) VALUES (UUID(),'Xenserver', '6.2.5', 'Ubuntu Precise Pangolin 12.04 (32-bit)', 163, now(), 0); +INSERT IGNORE INTO `cloud`.`guest_os_hypervisor` (uuid,hypervisor_type, hypervisor_version, guest_os_name, guest_os_id, created, is_user_defined) VALUES (UUID(),'Xenserver', '6.2.5', 'Ubuntu Precise Pangolin 12.04 (64-bit)', 164, now(), 0); +INSERT IGNORE INTO `cloud`.`guest_os_hypervisor` (uuid,hypervisor_type, hypervisor_version, guest_os_name, guest_os_id, created, is_user_defined) VALUES (UUID(),'Xenserver', '6.2.5', 'Other install media', 169, now(), 0); +INSERT IGNORE INTO `cloud`.`guest_os_hypervisor` (uuid,hypervisor_type, hypervisor_version, guest_os_name, guest_os_id, created, is_user_defined) VALUES (UUID(),'Xenserver', '6.2.5', 'Other install media', 170, now(), 0); +INSERT IGNORE INTO `cloud`.`guest_os_hypervisor` (uuid,hypervisor_type, hypervisor_version, guest_os_name, guest_os_id, created, is_user_defined) VALUES (UUID(),'Xenserver', '6.2.5', 'Other install media', 98, now(), 0); +INSERT IGNORE INTO `cloud`.`guest_os_hypervisor` (uuid,hypervisor_type, hypervisor_version, guest_os_name, guest_os_id, created, is_user_defined) VALUES (UUID(),'Xenserver', '6.2.5', 'Other install media', 99, now(), 0); +INSERT IGNORE INTO `cloud`.`guest_os_hypervisor` (uuid,hypervisor_type, hypervisor_version, guest_os_name, guest_os_id, created, is_user_defined) VALUES (UUID(),'Xenserver', '6.2.5', 'Other install media', 60, now(), 0); +INSERT IGNORE INTO `cloud`.`guest_os_hypervisor` (uuid,hypervisor_type, hypervisor_version, guest_os_name, guest_os_id, created, is_user_defined) VALUES (UUID(),'Xenserver', '6.2.5', 'Other install media', 103, now(), 0); +INSERT IGNORE INTO `cloud`.`guest_os_hypervisor` (uuid,hypervisor_type, hypervisor_version, guest_os_name, guest_os_id, created, is_user_defined) VALUES (UUID(),'Xenserver', '6.2.5', 'Other install media', 200, now(), 0); +INSERT IGNORE INTO `cloud`.`guest_os_hypervisor` (uuid,hypervisor_type, hypervisor_version, guest_os_name, guest_os_id, created, is_user_defined) VALUES (UUID(),'Xenserver', '6.2.5', 'Other install media', 201, now(), 0); +INSERT IGNORE INTO `cloud`.`guest_os_hypervisor` (uuid,hypervisor_type, hypervisor_version, guest_os_name, guest_os_id, created, is_user_defined) VALUES (UUID(),'Xenserver', '6.2.5', 'Other install media', 59, now(), 0); +INSERT IGNORE INTO `cloud`.`guest_os_hypervisor` (uuid,hypervisor_type, hypervisor_version, guest_os_name, guest_os_id, created, is_user_defined) VALUES (UUID(),'Xenserver', '6.2.5', 'Other install media', 100, now(), 0); +INSERT IGNORE INTO `cloud`.`guest_os_hypervisor` (uuid,hypervisor_type, hypervisor_version, guest_os_name, guest_os_id, created, is_user_defined) VALUES (UUID(),'Xenserver', '6.2.5', 'Other install media', 202, now(), 0); +INSERT IGNORE INTO `cloud`.`guest_os_hypervisor` (uuid,hypervisor_type, hypervisor_version, guest_os_name, guest_os_id, created, is_user_defined) VALUES (UUID(),'Xenserver', '6.2.5', 'Other install media', 203, now(), 0); +INSERT IGNORE INTO `cloud`.`guest_os_hypervisor` (uuid,hypervisor_type, hypervisor_version, guest_os_name, guest_os_id, created, is_user_defined) VALUES (UUID(),'Xenserver', '6.2.5', 'CentOS 5 (32-bit)', 139, now(), 0); +INSERT IGNORE INTO `cloud`.`guest_os_hypervisor` (uuid,hypervisor_type, hypervisor_version, guest_os_name, guest_os_id, created, is_user_defined) VALUES (UUID(),'Xenserver', '6.2.5', 'CentOS 5 (64-bit)', 140, now(), 0); +INSERT INTO `cloud`.`configuration`(category, instance, component, name, value, description, default_value) VALUES ('Advanced', 'DEFAULT', 'NetworkOrchestrationService', 'router.redundant.vrrp.interval', '1', 'seconds between VRRP broadcast. It would 3 times broadcast fail to trigger fail-over mechanism of redundant router', '1') ON DUPLICATE KEY UPDATE category='Advanced'; +CREATE TABLE `cloud`.`op_vpc_distributed_router_sequence_no` ( + `id` bigint unsigned UNIQUE NOT NULL AUTO_INCREMENT COMMENT 'id', + `vpc_id` bigint unsigned NOT NULL COMMENT 'vpc id.', + `topology_update_sequence_no` bigint unsigned COMMENT 'sequence number to be sent to hypervisor, uniquely identifies a VPC topology update', + `routing_policy__update_sequence_no` bigint unsigned COMMENT 'sequence number to be sent to hypervisor, uniquely identifies a routing policy update', + PRIMARY KEY (`id`), + UNIQUE `u_op_vpc_distributed_router_sequence_no_vpc_id`(`vpc_id`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8; + +INSERT INTO `cloud`.`configuration`(category, instance, component, name, value, description, default_value) VALUES ('Advanced', 'DEFAULT', 'NetworkOrchestrationService', 'router.aggregation.command.each.timeout', '3', 'timeout in seconds for each Virtual Router command being aggregated. The final aggregation command timeout would be determined by this timeout * commands counts ', '3') ON DUPLICATE KEY UPDATE category='Advanced'; + +CREATE TABLE `cloud`.`network_acl_item_cidrs` ( + `id` bigint unsigned UNIQUE NOT NULL auto_increment, + `network_acl_item_id` bigint unsigned NOT NULL COMMENT 'Network ACL Item id', + `cidr` varchar(255) NOT NULL, + PRIMARY KEY (`id`), + CONSTRAINT `fk_network_acl_item_id` FOREIGN KEY `fk_network_acl_item_id`(`network_acl_item_id`) REFERENCES `network_acl_item`(`id`) ON DELETE CASCADE +) ENGINE=InnoDB DEFAULT CHARSET=utf8; + + +ALTER TABLE `cloud`.`load_balancer_healthcheck_policies` ADD COLUMN `display` tinyint(1) NOT NULL DEFAULT '1' COMMENT 'True if the policy can be displayed to the end user'; +ALTER TABLE `cloud`.`load_balancer_stickiness_policies` ADD COLUMN `display` tinyint(1) NOT NULL DEFAULT '1' COMMENT 'True if the policy can be displayed to the end user'; + diff --git a/setup/db/templates.sql b/setup/db/templates.sql index 329932060e..6a74633efc 100755 --- a/setup/db/templates.sql +++ b/setup/db/templates.sql @@ -16,13 +16,13 @@ -- under the License. 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 (1, UUID(), 'routing-1', 'SystemVM Template (XenServer)', 0, now(), 'SYSTEM', 0, 32, 1, 'http://download.cloud.com/templates/4.2/systemvmtemplate-2013-07-12-master-xen.vhd.bz2', '74b92f031cc5c2089ee89efb81344dcf', 0, 'SystemVM Template (XenServer)', 'VHD', 183, 0, 1, 'XenServer' ); + VALUES (1, UUID(), 'routing-1', 'SystemVM Template (XenServer)', 0, now(), 'SYSTEM', 0, 64, 1, 'http://download.cloud.com/templates/4.3/systemvm64template-2014-01-14-master-xen.vhd.bz2', '74b92f031cc5c2089ee89efb81344dcf', 0, 'SystemVM Template (XenServer)', 'VHD', 183, 0, 1, 'XenServer' ); INSERT INTO `cloud`.`vm_template` (id, uuid, unique_name, name, public, created, removed, type, hvm, bits, account_id, url, checksum, enable_password, display_text, format, guest_os_id, featured, cross_zones, hypervisor_type, extractable) VALUES (2, UUID(), 'centos53-x86_64', 'CentOS 5.3(64-bit) no GUI (XenServer)', 1, now(), now(), 'BUILTIN', 0, 64, 1, 'http://download.cloud.com/templates/builtin/f59f18fb-ae94-4f97-afd2-f84755767aca.vhd.bz2', 'b63d854a9560c013142567bbae8d98cf', 0, 'CentOS 5.3(64-bit) no GUI (XenServer)', 'VHD', 12, 1, 1, 'XenServer', 1); 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 (3, UUID(), 'routing-3', 'SystemVM Template (KVM)', 0, now(), 'SYSTEM', 0, 64, 1, 'http://download.cloud.com/templates/4.2/systemvmtemplate-2013-06-12-master-kvm.qcow2.bz2', '6cea42b2633841648040becb588bd8f0', 0, 'SystemVM Template (KVM)', 'QCOW2', 15, 0, 1, 'KVM' ); + VALUES (3, UUID(), 'routing-3', 'SystemVM Template (KVM)', 0, now(), 'SYSTEM', 0, 64, 1, 'http://download.cloud.com/templates/4.3/systemvm64template-2014-01-14-master-kvm.qcow2.bz2', '85a1bed07bf43cbf022451cb2ecae4ff', 0, 'SystemVM Template (KVM)', 'QCOW2', 15, 0, 1, 'KVM' ); INSERT INTO `cloud`.`vm_template` (id, uuid, unique_name, name, public, created, type, hvm, bits, account_id, url, checksum, display_text, enable_password, format, guest_os_id, featured, cross_zones, hypervisor_type, extractable) VALUES (4, UUID(), 'centos55-x86_64', 'CentOS 5.5(64-bit) no GUI (KVM)', 1, now(), 'BUILTIN', 0, 64, 1, 'http://download.cloud.com/releases/2.2.0/eec2209b-9875-3c8d-92be-c001bd8a0faf.qcow2.bz2', 'ed0e788280ff2912ea40f7f91ca7a249', 'CentOS 5.5(64-bit) no GUI (KVM)', 0, 'QCOW2', 112, 1, 1, 'KVM', 1); @@ -68,7 +68,7 @@ INSERT INTO `cloud`.`guest_os` (id, uuid, category_id, display_name) VALUES (11, INSERT INTO `cloud`.`guest_os` (id, uuid, category_id, display_name) VALUES (12, UUID(), 1, 'CentOS 5.3 (64-bit)'); INSERT INTO `cloud`.`guest_os` (id, uuid, category_id, display_name) VALUES (13, UUID(), 1, 'CentOS 5.4 (32-bit)'); INSERT INTO `cloud`.`guest_os` (id, uuid, category_id, display_name) VALUES (14, UUID(), 1, 'CentOS 5.4 (64-bit)'); -INSERT INTO `cloud`.`guest_os` (id, uuid, category_id, display_name) VALUES (15, UUID(), 2, 'Debian GNU/Linux 5.0 (32-bit)'); +INSERT INTO `cloud`.`guest_os` (id, uuid, category_id, display_name) VALUES (15, UUID(), 2, 'Debian GNU/Linux 5.0 (64-bit)'); INSERT INTO `cloud`.`guest_os` (id, uuid, category_id, display_name) VALUES (16, UUID(), 3, 'Oracle Enterprise Linux 5.0 (32-bit)'); INSERT INTO `cloud`.`guest_os` (id, uuid, category_id, display_name) VALUES (17, UUID(), 3, 'Oracle Enterprise Linux 5.0 (64-bit)'); INSERT INTO `cloud`.`guest_os` (id, uuid, category_id, display_name) VALUES (18, UUID(), 3, 'Oracle Enterprise Linux 5.1 (32-bit)'); diff --git a/systemvm/js/ajaxkeys.js b/systemvm/js/ajaxkeys.js index 60c9798fca..8f78cc8a45 100644 --- a/systemvm/js/ajaxkeys.js +++ b/systemvm/js/ajaxkeys.js @@ -169,8 +169,7 @@ KEYBOARD_TYPE_UK = "uk"; var keyboardTables = [ {tindex: 0, keyboardType: KEYBOARD_TYPE_COOKED, mappingTable: - {X11: [ {keycode: 220, entry: X11_KEY_YEN_MARK}, - {keycode: 226, entry: X11_KEY_REVERSE_SOLIUS}, + {X11: [ {keycode: 226, entry: X11_KEY_REVERSE_SOLIUS}, {keycode: 240, entry: [ {type: KEY_DOWN, code: X11_KEY_CAPSLOCK, modifiers: 0 }, diff --git a/systemvm/patches/debian/config/etc/init.d/cloud-early-config b/systemvm/patches/debian/config/etc/init.d/cloud-early-config index 5751f09ac3..ffb23ec7cb 100755 --- a/systemvm/patches/debian/config/etc/init.d/cloud-early-config +++ b/systemvm/patches/debian/config/etc/init.d/cloud-early-config @@ -865,6 +865,12 @@ setup_redundant_router() { sed -i "s/\[RROUTER_LOG\]/$rrouter_log_str/g" $rrouter_bin_path/check_heartbeat.sh sed -i "s/\[RROUTER_LOG\]/$rrouter_log_str/g" $rrouter_bin_path/arping_gateways.sh sed -i "s/\[RROUTER_LOG\]/$rrouter_log_str/g" /opt/cloud/bin/checkrouter.sh + + if [ $ADVERT_INT ] + then + sed -i "s/advert_int 1/advert_int $ADVERT_INT/g" /etc/keepalived/keepalived.conf + fi + chmod a+x $rrouter_bin_path/*.sh sed -i "s/--exec\ \$DAEMON;/--exec\ \$DAEMON\ --\ --vrrp;/g" /etc/init.d/keepalived @@ -1073,8 +1079,16 @@ setup_dhcpsrvr() { enable_svc cloud 0 enable_fwding 0 chkconfig nfs-common off + cp /etc/iptables/iptables-router /etc/iptables/rules.v4 cp /etc/iptables/iptables-router /etc/iptables/rules + + #Only allow DNS service for current network + sed -i "s/-A INPUT -i eth0 -p udp -m udp --dport 53 -j ACCEPT/-A INPUT -i eth0 -p udp -m udp --dport 53 -s $DHCP_RANGE\/$CIDR_SIZE -j ACCEPT/g" /etc/iptables/rules.v4 + sed -i "s/-A INPUT -i eth0 -p udp -m udp --dport 53 -j ACCEPT/-A INPUT -i eth0 -p udp -m udp --dport 53 -s $DHCP_RANGE\/$CIDR_SIZE -j ACCEPT/g" /etc/iptables/rules + sed -i "s/-A INPUT -i eth0 -p tcp -m tcp --dport 53 -j ACCEPT/-A INPUT -i eth0 -p tcp -m tcp --dport 53 -s $DHCP_RANGE\/$CIDR_SIZE -j ACCEPT/g" /etc/iptables/rules.v4 + sed -i "s/-A INPUT -i eth0 -p tcp -m tcp --dport 53 -j ACCEPT/-A INPUT -i eth0 -p tcp -m tcp --dport 53 -s $DHCP_RANGE\/$CIDR_SIZE -j ACCEPT/g" /etc/iptables/rules + if [ "$SSHONGUEST" == "true" ] then setup_sshd $ETH0_IP "eth0" @@ -1100,6 +1114,7 @@ setup_storage_network() { setup_secstorage() { log_it "Setting up secondary storage system vm" + sysctl vm.min_free_kbytes=8192 local hyp=$1 setup_common eth0 eth1 eth2 setup_storage_network @@ -1419,6 +1434,12 @@ for i in $CMDLINE vpccidr) VPCCIDR=$VALUE ;; + cidrsize) + CIDR_SIZE=$VALUE + ;; + advert_int) + ADVERT_INT=$VALUE + ;; esac done diff --git a/systemvm/patches/debian/config/etc/logrotate.d/conntrackd b/systemvm/patches/debian/config/etc/logrotate.d/conntrackd new file mode 100644 index 0000000000..d09d752e11 --- /dev/null +++ b/systemvm/patches/debian/config/etc/logrotate.d/conntrackd @@ -0,0 +1,13 @@ +/var/log/conntrackd-stats.log { + daily + rotate 2 + missingok + compress + delaycompress + + postrotate + if [ -e /var/run/conntrackd.sock ]; then + invoke-rc.d conntrackd restart > /dev/null + fi + endscript +} diff --git a/systemvm/patches/debian/config/opt/cloud/bin/edithosts.sh b/systemvm/patches/debian/config/opt/cloud/bin/edithosts.sh index 8e7ddac8fd..c1046c6dda 100755 --- a/systemvm/patches/debian/config/opt/cloud/bin/edithosts.sh +++ b/systemvm/patches/debian/config/opt/cloud/bin/edithosts.sh @@ -99,7 +99,7 @@ if [ $dnsmasq_managed_lease ] then #release previous dhcp lease if present logger -t cloud "edithosts: releasing $ipv4" - dhcp_release eth0 $ipv4 $(grep "$ipv4 " $DHCP_LEASES | awk '{print $2}') > /dev/null 2>&1 + dhcp_release $(ip route get "$ipv4/32" | tr " " "\n" | grep eth) $ipv4 $(grep "$ipv4 " $DHCP_LEASES | awk '{print $2}') > /dev/null 2>&1 logger -t cloud "edithosts: released $ipv4" fi @@ -184,7 +184,7 @@ then echo "$ipv6 $host" >> $HOSTS fi -if [ "$dflt" != "" ] +if [ "$dflt" != "" -a "$ipv4" != "" ] then #make sure dnsmasq looks into options file sed -i /dhcp-optsfile/d /etc/dnsmasq.conf diff --git a/systemvm/patches/debian/config/opt/cloud/bin/getRouterAlerts.sh b/systemvm/patches/debian/config/opt/cloud/bin/getRouterAlerts.sh index e5e8abeffd..3f5f4a3b05 100644 --- a/systemvm/patches/debian/config/opt/cloud/bin/getRouterAlerts.sh +++ b/systemvm/patches/debian/config/opt/cloud/bin/getRouterAlerts.sh @@ -18,53 +18,38 @@ # getRouterAlerts.sh --- Send the alerts from routerServiceMonitor.log to Management Server -source /root/func.sh - -lock="biglock" -locked=$(getLockFile $lock) -if [ "$locked" != "1" ] -then - exit 1 -fi - #set -x filename=/var/log/routerServiceMonitor.log #Monitor service log file if [ -n "$1" -a -n "$2" ] then - reqdateval=$(date -d $1 +"%Y%m%d"); - reqtimeval=$(date -d $2 +"%H%M%S"); + reqDateVal=$(date -d "$1 $2" "+%s"); else - reqdateval=0 - reqtimeval=0 + reqDateVal=0 fi if [ -f $filename ] then while read line do - if [ -n "$line" ]; then - dateval=`echo $line |awk '{print $1}'` - timeval=`echo $line |awk '{print $2}'` - - todate=$(date -d "$dateval" +"%Y%m%d") > /dev/null - totime=$(date -d "$timeval" +"%H%M%S") > /dev/null - if [ "$todate" -gt "$reqdateval" ] > /dev/null + if [ -n "$line" ] then - if [ -n "$alerts" ]; then alerts="$alerts\n$line"; else alerts="$line"; fi #>> $outputfile - elif [ "$todate" -eq "$reqdateval" ] > /dev/null + dateval=`echo $line |awk '{print $1, $2}'` + IFS=',' read -a array <<< "$dateval" + dateval=${array[0]} + + toDateVal=$(date -d "$dateval" "+%s") + + if [ "$toDateVal" -gt "$reqDateVal" ] then - if [ "$totime" -gt "$reqtimeval" ] > /dev/null - then - if [ -n "$alerts" ]; then alerts="$alerts\n$line"; else alerts="$line"; fi #>> $outputfile - fi + alerts="$line\n$alerts" + else + break fi fi - done < $filename + done < <(tac $filename) fi if [ -n "$alerts" ]; then echo $alerts else echo "No Alerts" -fi - -unlock_exit 0 $lock $locked \ No newline at end of file +fi \ No newline at end of file diff --git a/systemvm/patches/debian/config/opt/cloud/bin/savepassword.sh b/systemvm/patches/debian/config/opt/cloud/bin/savepassword.sh index 1ea27e5b70..21fa09d5b7 100755 --- a/systemvm/patches/debian/config/opt/cloud/bin/savepassword.sh +++ b/systemvm/patches/debian/config/opt/cloud/bin/savepassword.sh @@ -52,7 +52,7 @@ done [ -f $PASSWD_FILE ] || touch $PASSWD_FILE -sed -i /$VM_IP/d $PASSWD_FILE +sed -i /$VM_IP=/d $PASSWD_FILE ps aux | grep serve_password.sh |grep -v grep 2>&1 > /dev/null if [ $? -eq 0 ] diff --git a/systemvm/patches/debian/config/opt/cloud/bin/vpc_privategw_acl.sh b/systemvm/patches/debian/config/opt/cloud/bin/vpc_privategw_acl.sh index d4e3eba14a..b585a364bd 100755 --- a/systemvm/patches/debian/config/opt/cloud/bin/vpc_privategw_acl.sh +++ b/systemvm/patches/debian/config/opt/cloud/bin/vpc_privategw_acl.sh @@ -155,10 +155,12 @@ acl_entry_for_guest_network() { dflag=0 gflag=0 aflag=0 +mflag=0 rules="" rules_list="" dev="" -while getopts 'd:a:' OPTION +mac="" +while getopts 'd:a:M:' OPTION do case $OPTION in d) dflag=1 @@ -167,6 +169,9 @@ do a) aflag=1 rules="$OPTARG" ;; + M) mflag=1 + mac="$OPTARG" + ;; ?) usage unlock_exit 2 $lock $locked ;; diff --git a/systemvm/scripts/_run.sh b/systemvm/scripts/_run.sh index 1a37c7d372..3792261c14 100755 --- a/systemvm/scripts/_run.sh +++ b/systemvm/scripts/_run.sh @@ -68,4 +68,4 @@ if [ "$(uname -m | grep '64')" == "" ]; then fi fi -java -Djavax.net.ssl.trustStore=./certs/realhostip.keystore -Dlog.home=$LOGHOME -mx${maxmem}m -cp $CP com.cloud.agent.AgentShell $keyvalues $@ +java -Djavax.net.ssl.trustStore=./certs/realhostip.keystore -Djsse.enableSNIExtension=false -Dlog.home=$LOGHOME -mx${maxmem}m -cp $CP com.cloud.agent.AgentShell $keyvalues $@ diff --git a/systemvm/scripts/config_ssl.sh b/systemvm/scripts/config_ssl.sh index e474787269..69710554f1 100755 --- a/systemvm/scripts/config_ssl.sh +++ b/systemvm/scripts/config_ssl.sh @@ -24,6 +24,7 @@ help() { printf " -k path of private key\n" printf " -p path of certificate of public key\n" printf " -t path of certificate chain\n" + printf " -u path of root ca certificate \n" } @@ -53,6 +54,10 @@ config_apache2_conf() { sed -i -e "s/NameVirtualHost .*:80/NameVirtualHost $ip:80/g" /etc/apache2/ports.conf sed -i 's/ssl-cert-snakeoil.key/cert_apache.key/' /etc/apache2/sites-available/default-ssl sed -i 's/ssl-cert-snakeoil.pem/cert_apache.crt/' /etc/apache2/sites-available/default-ssl + if [ -f /etc/ssl/certs/cert_apache_chain.crt ] + then + sed -i -e "s/#SSLCertificateChainFile.*/SSLCertificateChainFile \/etc\/ssl\/certs\/cert_apache_chain.crt/" /etc/apache2/sites-available/default-ssl + fi } copy_certs() { @@ -88,12 +93,13 @@ cccflag= customPrivKey=$(dirname $0)/certs/realhostip.key customPrivCert=$(dirname $0)/certs/realhostip.crt customCertChain= +customCACert= publicIp= hostName= keyStore=$(dirname $0)/certs/realhostip.keystore aliasName="CPVMCertificate" storepass="vmops.com" -while getopts 'i:h:k:p:t:c' OPTION +while getopts 'i:h:k:p:t:u:c' OPTION do case $OPTION in c) cflag=1 @@ -107,6 +113,9 @@ do t) cccflag=1 customCertChain="$OPTARG" ;; + u) ccacflag=1 + customCACert="$OPTARG" + ;; i) publicIp="$OPTARG" ;; h) hostName="$OPTARG" @@ -165,10 +174,10 @@ then exit 2 fi -if [ -f "$customPrivCert" ] +if [ -f "$customCACert" ] then keytool -delete -alias $aliasName -keystore $keyStore -storepass $storepass -noprompt - keytool -import -alias $aliasName -keystore $keyStore -storepass $storepass -noprompt -file $customPrivCert + keytool -import -alias $aliasName -keystore $keyStore -storepass $storepass -noprompt -file $customCACert fi if [ -d /etc/apache2 ] diff --git a/test/integration/component/maint/test_egress_rules_host_maintenance.py b/test/integration/component/maint/test_egress_rules_host_maintenance.py index 2b817879c4..a27ada3dca 100644 --- a/test/integration/component/maint/test_egress_rules_host_maintenance.py +++ b/test/integration/component/maint/test_egress_rules_host_maintenance.py @@ -23,9 +23,9 @@ from marvin.cloudstackTestCase import * from marvin.cloudstackAPI import * from marvin.sshClient import SshClient -from marvin.integration.lib.utils import * -from marvin.integration.lib.base import * -from marvin.integration.lib.common import * +from marvin.lib.utils import * +from marvin.lib.base import * +from marvin.lib.common import * #Import System modules import time @@ -100,19 +100,17 @@ def tearDown(self): @classmethod def setUpClass(cls): - cls.services = Services().services - cls.api_client = super( - TestEgressAfterHostMaintenance, - cls - ).getClsTestClient().getApiClient() + cls.testClient = super(TestEgressAfterHostMaintenance, cls).getClsTestClient() + cls.api_client = cls.testClient.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) + cls.domain = get_domain(cls.api_client) + cls.zone = get_zone(cls.api_client, cls.testClient.getZoneForTests()) cls.services['mode'] = cls.zone.networktype cls.pod = get_pod( cls.api_client, - zoneid=cls.zone.id + zone_id=cls.zone.id ) template = get_template( diff --git a/test/integration/component/maint/test_high_availability.py b/test/integration/component/maint/test_high_availability.py index 6ada659cd4..cc687f83ea 100644 --- a/test/integration/component/maint/test_high_availability.py +++ b/test/integration/component/maint/test_high_availability.py @@ -23,9 +23,9 @@ 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.lib.utils import * +from marvin.lib.base import * +from marvin.lib.common import * from marvin.sshClient import SshClient import datetime @@ -107,24 +107,16 @@ class TestHighAvailability(cloudstackTestCase): @classmethod def setUpClass(cls): - cls.api_client = super( - TestHighAvailability, - cls - ).getClsTestClient().getApiClient() + cls.testClient = super(TestHighAvailability, cls).getClsTestClient() + cls.api_client = cls.testClient.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 - ) + cls.domain = get_domain(cls.api_client) + cls.zone = get_zone(cls.api_client, cls.testClient.getZoneForTests()) cls.pod = get_pod( cls.api_client, - zoneid=cls.zone.id, - services=cls.services + zone_id=cls.zone.id ) cls.template = get_template( cls.api_client, diff --git a/test/integration/component/maint/test_host_high_availability.py b/test/integration/component/maint/test_host_high_availability.py index b4c50c7114..4cd7fd8fe8 100644 --- a/test/integration/component/maint/test_host_high_availability.py +++ b/test/integration/component/maint/test_host_high_availability.py @@ -21,9 +21,10 @@ 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.lib.utils import * +from marvin.lib.base import * +from marvin.lib.common import * +import time class Services: @@ -76,20 +77,13 @@ class TestHostHighAvailability(cloudstackTestCase): @classmethod def setUpClass(cls): - cls.api_client = super( - TestHostHighAvailability, - cls - ).getClsTestClient().getApiClient() + cls.testClient = super(TestHostHighAvailability, cls).getClsTestClient() + cls.api_client = cls.testClient.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 - ) + cls.domain = get_domain(cls.api_client) + cls.zone = get_zone(cls.api_client, cls.testClient.getZoneForTests()) cls.template = get_template( cls.api_client, @@ -626,11 +620,7 @@ def test_05_no_vm_with_ha_gets_migrated_to_ha_host_in_live_migration(self): #verify the VM live migration happened to another running host self.debug("Waiting for VM to come up") - wait_for_vm( - self.apiclient, - virtualmachineid=vm_with_ha_enabled.id, - interval=timeout - ) + time.sleep(timeout) vms = VirtualMachine.list( self.apiclient, @@ -758,11 +748,7 @@ def test_06_no_vm_without_ha_gets_migrated_to_ha_host_in_live_migration(self): #verify the VM live migration happened to another running host self.debug("Waiting for VM to come up") - wait_for_vm( - self.apiclient, - virtualmachineid=vm_with_ha_disabled.id, - interval=timeout - ) + time.sleep(timeout) vms = VirtualMachine.list( self.apiclient, diff --git a/test/integration/component/maint/test_multiple_ip_ranges.py b/test/integration/component/maint/test_multiple_ip_ranges.py index dc8021bc91..982dd7c85b 100644 --- a/test/integration/component/maint/test_multiple_ip_ranges.py +++ b/test/integration/component/maint/test_multiple_ip_ranges.py @@ -18,10 +18,10 @@ """ from marvin.cloudstackTestCase import * from marvin.cloudstackAPI import * -from marvin.cloudstackException import cloudstackAPIException -from marvin.integration.lib.utils import * -from marvin.integration.lib.base import * -from marvin.integration.lib.common import * +from marvin.cloudstackException import CloudstackAPIException +from marvin.lib.utils import * +from marvin.lib.base import * +from marvin.lib.common import * # from netaddr import * import netaddr from nose.plugins.attrib import attr @@ -87,13 +87,15 @@ class TestMultipleIpRanges(cloudstackTestCase): """ @classmethod def setUpClass(cls): - cls.api_client = super(TestMultipleIpRanges, cls).getClsTestClient().getApiClient() - cls.dbclient = super(TestMultipleIpRanges, cls).getClsTestClient().getDbConnection() + cls.testClient = super(TestEgressAfterHostMaintenance, cls).getClsTestClient() + cls.api_client = cls.testClient.getApiClient() + cls.dbclient = cls.testClient.getDbConnection() + 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) - cls.pod = get_pod(cls.api_client, cls.zone.id, cls.services) + cls.domain = get_domain(cls.api_client) + cls.zone = get_zone(cls.api_client, cls.testClient.getZoneForTests()) + cls.pod = get_pod(cls.api_client, cls.zone.id) cls.services['mode'] = cls.zone.networktype cls.services["domainid"] = cls.domain.id cls.services["zoneid"] = cls.zone.id diff --git a/test/integration/component/maint/test_redundant_router.py b/test/integration/component/maint/test_redundant_router.py index 617a54673b..66bb477e04 100644 --- a/test/integration/component/maint/test_redundant_router.py +++ b/test/integration/component/maint/test_redundant_router.py @@ -16,9 +16,9 @@ # under the License. from nose.plugins.attrib import attr -from marvin.integration.lib.base import * -from marvin.integration.lib.utils import * -from marvin.integration.lib.common import * +from marvin.lib.base import * +from marvin.lib.utils import * +from marvin.lib.common import * #Import Local Modules from marvin.cloudstackTestCase import cloudstackTestCase @@ -137,14 +137,13 @@ class TestCreateRvRNetworkOffering(cloudstackTestCase): @classmethod def setUpClass(cls): - cls.api_client = super( - TestCreateRvRNetworkOffering, - cls - ).getClsTestClient().getApiClient() + cls.testClient = super(TestCreateRvRNetworkOffering, cls).getClsTestClient() + cls.api_client = cls.testClient.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) + cls.domain = get_domain(cls.api_client) + cls.zone = get_zone(cls.api_client, cls.testClient.getZoneForTests()) cls._cleanup = [] return @@ -231,14 +230,13 @@ class TestCreateRvRNetwork(cloudstackTestCase): @classmethod def setUpClass(cls): - cls.api_client = super( - TestCreateRvRNetwork, - cls - ).getClsTestClient().getApiClient() + cls.testClient = super(TestCreateRvRNetwork, cls).getClsTestClient() + cls.api_client = cls.testClient.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) + cls.domain = get_domain(cls.api_client) + cls.zone = get_zone(cls.api_client, cls.testClient.getZoneForTests()) cls.template = get_template( cls.api_client, cls.zone.id, @@ -433,14 +431,13 @@ class TestCreateRvRNetworkNonDefaultGuestCidr(cloudstackTestCase): @classmethod def setUpClass(cls): - cls.api_client = super( - TestCreateRvRNetworkNonDefaultGuestCidr, - cls - ).getClsTestClient().getApiClient() + cls.testClient = super(TestCreateRvRNetworkNonDefaultGuestCidr, cls).getClsTestClient() + cls.api_client = cls.testClient.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) + cls.domain = get_domain(cls.api_client) + cls.zone = get_zone(cls.api_client, cls.testClient.getZoneForTests()) cls.template = get_template( cls.api_client, cls.zone.id, @@ -642,14 +639,13 @@ class TestRVRInternals(cloudstackTestCase): @classmethod def setUpClass(cls): - cls.api_client = super( - TestRVRInternals, - cls - ).getClsTestClient().getApiClient() + cls.testClient = super(TestRVRInternals, cls).getClsTestClient() + cls.api_client = cls.testClient.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) + cls.domain = get_domain(cls.api_client) + cls.zone = get_zone(cls.api_client, cls.testClient.getZoneForTests()) cls.template = get_template( cls.api_client, cls.zone.id, @@ -685,6 +681,7 @@ def tearDownClass(cls): def setUp(self): self.apiclient = self.testClient.getApiClient() + self.hypervisor = self.testClient.getHypervisorInfo() self.dbclient = self.testClient.getDbConnection() self.account = Account.create( self.apiclient, @@ -846,7 +843,7 @@ def test_redundantVR_internals(self): self.debug(master_router.linklocalip) # Check eth2 port for master router - if self.apiclient.hypervisor.lower() == 'vmware': + if self.hypervisor.lower() == 'vmware': result = get_process_status( self.apiclient.connection.mgtSvr, 22, @@ -854,7 +851,7 @@ def test_redundantVR_internals(self): self.apiclient.connection.passwd, master_router.linklocalip, 'ip addr show eth2', - hypervisor=self.apiclient.hypervisor + hypervisor=self.hypervisor ) else: result = get_process_status( @@ -882,7 +879,7 @@ def test_redundantVR_internals(self): ) # Check eth2 port for backup router - if self.apiclient.hypervisor.lower() == 'vmware': + if self.hypervisor.lower() == 'vmware': result = get_process_status( self.apiclient.connection.mgtSvr, 22, @@ -890,7 +887,7 @@ def test_redundantVR_internals(self): self.apiclient.connction.passwd, backup_router.linklocalip, 'ip addr show eth2', - hypervisor=self.apiclient.hypervisor + hypervisor=self.hypervisor ) else: result = get_process_status( @@ -945,14 +942,13 @@ class TestRvRRedundancy(cloudstackTestCase): @classmethod def setUpClass(cls): - cls.api_client = super( - TestRvRRedundancy, - cls - ).getClsTestClient().getApiClient() + cls.testClient = super(TestRvRRedundancy, cls).getClsTestClient() + cls.api_client = cls.testClient.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) + cls.domain = get_domain(cls.api_client) + cls.zone = get_zone(cls.api_client, cls.testClient.getZoneForTests()) cls.template = get_template( cls.api_client, cls.zone.id, diff --git a/test/integration/component/maint/test_redundant_router_deployment_planning.py b/test/integration/component/maint/test_redundant_router_deployment_planning.py index 879a4da774..b63cda94e5 100644 --- a/test/integration/component/maint/test_redundant_router_deployment_planning.py +++ b/test/integration/component/maint/test_redundant_router_deployment_planning.py @@ -16,9 +16,9 @@ # under the License. from nose.plugins.attrib import attr -from marvin.integration.lib.base import * -from marvin.integration.lib.utils import * -from marvin.integration.lib.common import * +from marvin.lib.base import * +from marvin.lib.utils import * +from marvin.lib.common import * #Import Local Modules from marvin.cloudstackTestCase import cloudstackTestCase @@ -136,14 +136,13 @@ class TestRvRDeploymentPlanning(cloudstackTestCase): @classmethod def setUpClass(cls): - cls.api_client = super( - TestRvRDeploymentPlanning, - cls - ).getClsTestClient().getApiClient() + cls.testClient = super(TestRvRDeploymentPlanning, cls).getClsTestClient() + cls.api_client = cls.testClient.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) + cls.domain = get_domain(cls.api_client) + cls.zone = get_zone(cls.api_client, cls.testClient.getZoneForTests()) cls.template = get_template( cls.api_client, cls.zone.id, diff --git a/test/integration/component/maint/test_redundant_router_network_rules.py b/test/integration/component/maint/test_redundant_router_network_rules.py index 010aaaa7b7..12c4d2c116 100644 --- a/test/integration/component/maint/test_redundant_router_network_rules.py +++ b/test/integration/component/maint/test_redundant_router_network_rules.py @@ -16,9 +16,9 @@ # under the License. from nose.plugins.attrib import attr -from marvin.integration.lib.base import * -from marvin.integration.lib.utils import * -from marvin.integration.lib.common import * +from marvin.lib.base import * +from marvin.lib.utils import * +from marvin.lib.common import * #Import Local Modules from marvin.cloudstackTestCase import cloudstackTestCase @@ -137,14 +137,13 @@ class TestRedundantRouterRulesLifeCycle(cloudstackTestCase): @classmethod def setUpClass(cls): - cls.api_client = super( - TestRedundantRouterRulesLifeCycle, - cls - ).getClsTestClient().getApiClient() + cls.testClient = super(TestRedundantRouterRulesLifeCycle, cls).getClsTestClient() + cls.api_client = cls.testClient.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) + cls.domain = get_domain(cls.api_client) + cls.zone = get_zone(cls.api_client, cls.testClient.getZoneForTests()) cls.template = get_template( cls.api_client, cls.zone.id, diff --git a/test/integration/component/maint/test_vpc_host_maintenance.py b/test/integration/component/maint/test_vpc_host_maintenance.py index 57dfb4be8d..83ba2717d9 100644 --- a/test/integration/component/maint/test_vpc_host_maintenance.py +++ b/test/integration/component/maint/test_vpc_host_maintenance.py @@ -22,11 +22,9 @@ 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.sshClient import SshClient -import datetime +from marvin.lib.utils import * +from marvin.lib.base import * +from marvin.lib.common import * class Services: @@ -190,14 +188,13 @@ class TestVMLifeCycleHostmaintenance(cloudstackTestCase): @classmethod def setUpClass(cls): - cls.api_client = super( - TestVMLifeCycleHostmaintenance, - cls - ).getClsTestClient().getApiClient() + cls.testClient = super(TestVMLifeCycleHostmaintenance, cls).getClsTestClient() + cls.api_client = cls.testClient.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) + cls.domain = get_domain(cls.api_client) + cls.zone = get_zone(cls.api_client, cls.testClient.getZoneForTests()) cls.template = get_template( cls.api_client, cls.zone.id, @@ -554,4 +551,4 @@ def test_03_reconnect_host(self): "Router state should be running" ) # TODO: Check for the network connectivity - return \ No newline at end of file + return diff --git a/test/integration/component/maint/test_vpc_on_host_maintenance.py b/test/integration/component/maint/test_vpc_on_host_maintenance.py index 6630ee61e0..eb3360a458 100644 --- a/test/integration/component/maint/test_vpc_on_host_maintenance.py +++ b/test/integration/component/maint/test_vpc_on_host_maintenance.py @@ -18,9 +18,9 @@ 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.lib.utils import * +from marvin.lib.base import * +from marvin.lib.common import * class Services: @@ -77,14 +77,13 @@ class TestVPCHostMaintenance(cloudstackTestCase): @classmethod def setUpClass(cls): - cls.api_client = super( - TestVPCHostMaintenance, - cls - ).getClsTestClient().getApiClient() + cls.testClient = super(TestVPCHostMaintenance, cls).getClsTestClient() + cls.api_client = cls.testClient.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) + cls.domain = get_domain(cls.api_client) + cls.zone = get_zone(cls.api_client, cls.testClient.getZoneForTests()) cls.template = get_template( cls.api_client, cls.zone.id, diff --git a/test/integration/smoke/test_VirtualRouter_alerts.py b/test/integration/component/test_VirtualRouter_alerts.py similarity index 90% rename from test/integration/smoke/test_VirtualRouter_alerts.py rename to test/integration/component/test_VirtualRouter_alerts.py index 2333d846f1..e6f0a823fd 100644 --- a/test/integration/smoke/test_VirtualRouter_alerts.py +++ b/test/integration/component/test_VirtualRouter_alerts.py @@ -20,10 +20,11 @@ import marvin 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.lib.utils import * +from marvin.lib.base import * +from marvin.lib.common import * from nose.plugins.attrib import attr +from marvin.codes import FAILED import time @@ -96,12 +97,13 @@ def __init__(self): class TestVRServiceFailureAlerting(cloudstackTestCase): @classmethod def setUpClass(cls): - cls.api_client = super(TestVRServiceFailureAlerting, cls).getClsTestClient().getApiClient() + cls.testClient = super(TestVRServiceFailureAlerting, cls).getClsTestClient() + cls.api_client = cls.testClient.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.zone = get_zone(cls.api_client, cls.testClient.getZoneForTests()) + domain = get_domain(cls.api_client) cls.services['mode'] = cls.zone.networktype template = get_template( @@ -109,6 +111,9 @@ def setUpClass(cls): cls.zone.id, cls.services["ostype"] ) + + if template == FAILED: + assert False, "get_template() failed to return template with description %s" % cls.services["ostype"] # Set Zones and disk offerings ?? cls.services["small"]["zoneid"] = cls.zone.id cls.services["small"]["template"] = template.id @@ -148,6 +153,7 @@ def tearDownClass(cls): def setUp(self): self.apiclient = self.testClient.getApiClient() self.dbclient = self.testClient.getDbConnection() + self.hypervisor = self.testClient.getHypervisorInfo() self.cleanup = [] def tearDown(self): @@ -202,7 +208,7 @@ def test_01_VRServiceFailureAlerting(self): alertSubject = "Monitoring Service on VR " + router.name - if self.apiclient.hypervisor.lower() == 'vmware': + if self.hypervisor.lower() == 'vmware': result = get_process_status( self.apiclient.connection.mgtSvr, 22, @@ -210,7 +216,7 @@ def test_01_VRServiceFailureAlerting(self): self.apiclient.connection.passwd, router.linklocalip, "service dnsmasq status", - hypervisor=self.apiclient.hypervisor + hypervisor=self.hypervisor ) else: try: @@ -229,7 +235,7 @@ def test_01_VRServiceFailureAlerting(self): res = str(result) self.debug("apache process status: %s" % res) - time.sleep(300) #wait for 5 minutes meanwhile monitor service on VR starts the apache service + time.sleep(2400) #wait for 40 minutes meanwhile monitor service on VR starts the apache service (router.alerts.check.interval default value is 30minutes) qresultset = self.dbclient.execute( "select id from alert where subject = '%s' ORDER BY id DESC LIMIT 1;" \ diff --git a/test/integration/component/test_accounts.py b/test/integration/component/test_accounts.py index 650a595936..cf5f2b6e47 100644 --- a/test/integration/component/test_accounts.py +++ b/test/integration/component/test_accounts.py @@ -17,14 +17,32 @@ """ P1 tests for Account """ #Import Local Modules -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.sshClient import SshClient +from marvin.cloudstackTestCase import cloudstackTestCase +#from marvin.cloudstackAPI import * +from marvin.lib.utils import (random_gen, + cleanup_resources) +from marvin.lib.base import (Domain, + Account, + ServiceOffering, + VirtualMachine, + Network, + User, + NATRule, + Template, + PublicIPAddress) +from marvin.lib.common import (get_domain, + get_zone, + get_template, + list_accounts, + list_virtual_machines, + list_service_offering, + list_templates, + list_users, + get_builtin_template_info, + wait_for_cleanup) from nose.plugins.attrib import attr -from marvin.cloudstackException import cloudstackAPIException +from marvin.cloudstackException import CloudstackAPIException +import time class Services: """Test Account Services @@ -102,13 +120,11 @@ class TestAccounts(cloudstackTestCase): @classmethod def setUpClass(cls): - cls.api_client = super( - TestAccounts, - cls - ).getClsTestClient().getApiClient() + cls.testClient = super(TestAccounts, cls).getClsTestClient() + cls.api_client = cls.testClient.getApiClient() + cls.services = Services().services - # Get Zone, Domain and templates - cls.zone = get_zone(cls.api_client, cls.services) + cls.zone = get_zone(cls.api_client, cls.testClient.getZoneForTests()) cls.services['mode'] = cls.zone.networktype cls.template = get_template( cls.api_client, @@ -148,7 +164,7 @@ def tearDown(self): raise Exception("Warning: Exception during cleanup : %s" % e) return - @attr(tags=["advanced", "basic", "eip", "advancedns", "sg"]) + @attr(tags=["advanced", "basic", "eip", "advancedns", "sg", "selfservice"]) def test_01_create_account(self): """Test Create Account and user for that account """ @@ -232,13 +248,11 @@ class TestRemoveUserFromAccount(cloudstackTestCase): @classmethod def setUpClass(cls): - cls.api_client = super( - TestRemoveUserFromAccount, - cls - ).getClsTestClient().getApiClient() + cls.testClient = super(TestRemoveUserFromAccount, cls).getClsTestClient() + cls.api_client = cls.testClient.getApiClient() + cls.services = Services().services - # Get Zone, Domain and templates - cls.zone = get_zone(cls.api_client, cls.services) + cls.zone = get_zone(cls.api_client, cls.testClient.getZoneForTests()) cls.services['mode'] = cls.zone.networktype cls.template = get_template( cls.api_client, @@ -286,7 +300,7 @@ def tearDown(self): raise Exception("Warning: Exception during cleanup : %s" % e) return - @attr(tags=["advanced", "basic", "eip", "advancedns", "sg"]) + @attr(tags=["advanced", "basic", "eip", "advancedns", "sg", "selfservice"]) def test_01_user_remove_VM_running(self): """Test Remove one user from the account """ @@ -392,13 +406,11 @@ class TestNonRootAdminsPrivileges(cloudstackTestCase): @classmethod def setUpClass(cls): - cls.api_client = super( - TestNonRootAdminsPrivileges, - cls - ).getClsTestClient().getApiClient() + cls.testClient = super(TestNonRootAdminsPrivileges, cls).getClsTestClient() + cls.api_client = cls.testClient.getApiClient() + cls.services = Services().services - # Get Zone settings - cls.zone = get_zone(cls.api_client, cls.services) + cls.zone = get_zone(cls.api_client, cls.testClient.getZoneForTests()) cls.services['mode'] = cls.zone.networktype # Create an account, domain etc cls.domain = Domain.create( @@ -440,7 +452,7 @@ def tearDown(self): raise Exception("Warning: Exception during cleanup : %s" % e) return - @attr(tags=["advanced", "basic", "eip", "advancedns", "sg"]) + @attr(tags=["advanced", "basic", "eip", "advancedns", "sg", "selfservice"]) def test_01_non_root_admin_Privileges(self): """Test to verify Non Root admin previleges""" @@ -561,7 +573,7 @@ def tearDown(self): raise Exception("Warning: Exception during cleanup : %s" % e) return - @attr(tags=["advanced", "basic", "eip", "advancedns", "sg"]) + @attr(tags=["advanced", "basic", "eip", "advancedns", "sg", "selfservice"]) def test_01_service_offering_siblings(self): """Test to verify service offerings at same level in hierarchy""" @@ -679,7 +691,7 @@ def tearDown(self): raise Exception("Warning: Exception during cleanup : %s" % e) return - @attr(tags=["advanced", "basic", "eip", "advancedns", "sg"]) + @attr(tags=["advanced", "basic", "eip", "advancedns", "sg", "selfservice"]) def test_01_service_offering_hierarchy(self): """Test to verify service offerings at same level in hierarchy""" @@ -726,12 +738,12 @@ class TestTemplateHierarchy(cloudstackTestCase): @classmethod def setUpClass(cls): - cls.api_client = super( - TestTemplateHierarchy, - cls).getClsTestClient().getApiClient() + cls.testClient = super(TestTemplateHierarchy, cls).getClsTestClient() + cls.api_client = cls.testClient.getApiClient() + cls.hypervisor = cls.testClient.getHypervisorInfo() + cls.services = Services().services - # Get Zone settings - cls.zone = get_zone(cls.api_client, cls.services) + cls.zone = get_zone(cls.api_client, cls.testClient.getZoneForTests()) cls.services['mode'] = cls.zone.networktype # Create domains, accounts and template @@ -772,7 +784,8 @@ def setUpClass(cls): cls.services["template"], zoneid=cls.zone.id, account=cls.account_1.name, - domainid=cls.domain_1.id + domainid=cls.domain_1.id, + hypervisor=cls.hypervisor ) # Wait for template to download @@ -879,21 +892,12 @@ class TestAddVmToSubDomain(cloudstackTestCase): @classmethod def setUpClass(cls): - cls.api_client = super( - TestAddVmToSubDomain, - cls - ).getClsTestClient().getApiClient() - cls.services = Services().services + cls.testClient = super(TestAddVmToSubDomain, cls).getClsTestClient() + cls.api_client = cls.testClient.getApiClient() - # Setup working Environment- Create domain, zone, pod cluster etc. - cls.domain = get_domain( - cls.api_client, - cls.services - ) - cls.zone = get_zone( - cls.api_client, - cls.services, - ) + cls.services = Services().services + cls.domain = get_domain(cls.api_client) + cls.zone = get_zone(cls.api_client, cls.testClient.getZoneForTests()) cls.services['mode'] = cls.zone.networktype cls.sub_domain = Domain.create( cls.api_client, @@ -976,7 +980,7 @@ def tearDown(self): raise Exception("Warning: Exception during cleanup : %s" % e) return - @attr(tags=["advanced", "basic", "eip", "advancedns", "sg"]) + @attr(tags=["advanced", "basic", "eip", "advancedns", "sg", "selfservice"]) def test_01_add_vm_to_subdomain(self): """ Test Sub domain allowed to launch VM when a Domain level zone is created""" @@ -1031,14 +1035,12 @@ class TestUserDetails(cloudstackTestCase): @classmethod def setUpClass(cls): - cls.api_client = super( - TestUserDetails, - cls - ).getClsTestClient().getApiClient() + cls.testClient = super(TestUserDetails, cls).getClsTestClient() + cls.api_client = cls.testClient.getApiClient() + cls.services = Services().services - # Get Zone, Domain etc - cls.domain = get_domain(cls.api_client, cls.services) - cls.zone = get_zone(cls.api_client, cls.services) + cls.domain = get_domain(cls.api_client) + cls.zone = get_zone(cls.api_client, cls.testClient.getZoneForTests()) cls.services['mode'] = cls.zone.networktype cls._cleanup = [] return @@ -1331,14 +1333,12 @@ class TestUserLogin(cloudstackTestCase): @classmethod def setUpClass(cls): - cls.api_client = super( - TestUserLogin, - cls - ).getClsTestClient().getApiClient() + cls.testClient = super(TestUserLogin, cls).getClsTestClient() + cls.api_client = cls.testClient.getApiClient() + cls.services = Services().services - # Get Zone, Domain etc - cls.domain = get_domain(cls.api_client, cls.services) - cls.zone = get_zone(cls.api_client, cls.services) + cls.domain = get_domain(cls.api_client) + cls.zone = get_zone(cls.api_client, cls.testClient.getZoneForTests()) cls.services['mode'] = cls.zone.networktype cls._cleanup = [] return @@ -1482,21 +1482,12 @@ class TestDomainForceRemove(cloudstackTestCase): @classmethod def setUpClass(cls): - cls.api_client = super( - TestDomainForceRemove, - cls - ).getClsTestClient().getApiClient() - cls.services = Services().services + cls.testClient = super(TestDomainForceRemove, cls).getClsTestClient() + cls.api_client = cls.testClient.getApiClient() - # Setup working Environment- Create domain, zone, pod cluster etc. - cls.domain = get_domain( - cls.api_client, - cls.services - ) - cls.zone = get_zone( - cls.api_client, - cls.services, - ) + cls.services = Services().services + cls.domain = get_domain(cls.api_client) + cls.zone = get_zone(cls.api_client, cls.testClient.getZoneForTests()) cls.services['mode'] = cls.zone.networktype cls.template = get_template( @@ -1533,7 +1524,7 @@ def tearDown(self): raise Exception("Warning: Exception during cleanup : %s" % e) return - @attr(tags=["domains", "advanced", "advancedns", "simulator"]) + @attr(tags=["domains", "advanced", "advancedns", "simulator", "selfservice"]) def test_forceDeleteDomain(self): """ Test delete domain with force option""" @@ -1681,7 +1672,7 @@ def test_forceDeleteDomain(self): " to cleanup any remaining resouces") # Sleep 3*account.gc to ensure that all resources are deleted wait_for_cleanup(self.apiclient, ["account.cleanup.interval"]*3) - with self.assertRaises(cloudstackAPIException): + with self.assertRaises(CloudstackAPIException): Domain.list( self.apiclient, id=domain.id, @@ -1689,7 +1680,7 @@ def test_forceDeleteDomain(self): ) self.debug("Checking if the resources in domain are deleted") - with self.assertRaises(cloudstackAPIException): + with self.assertRaises(CloudstackAPIException): Account.list( self.apiclient, name=self.account_1.name, @@ -1698,7 +1689,7 @@ def test_forceDeleteDomain(self): ) return - @attr(tags=["domains", "advanced", "advancedns", "simulator"]) + @attr(tags=["domains", "advanced", "advancedns", "simulator", "selfservice"]) def test_DeleteDomain(self): """ Test delete domain without force option""" diff --git a/test/integration/component/test_add_remove_network.py b/test/integration/component/test_add_remove_network.py index 4529ec7dfa..c17293d17a 100644 --- a/test/integration/component/test_add_remove_network.py +++ b/test/integration/component/test_add_remove_network.py @@ -29,7 +29,7 @@ from nose.plugins.attrib import attr from marvin.cloudstackTestCase import cloudstackTestCase, unittest from ddt import ddt, data -from marvin.integration.lib.base import ( +from marvin.lib.base import ( Account, Domain, ServiceOffering, @@ -39,7 +39,7 @@ VpcOffering, VPC ) -from marvin.integration.lib.common import (get_domain, +from marvin.lib.common import (get_domain, get_zone, get_template, list_virtual_machines, @@ -49,7 +49,7 @@ update_resource_limit ) -from marvin.integration.lib.utils import (validateList, +from marvin.lib.utils import (validateList, random_gen, get_hypervisor_type, cleanup_resources) @@ -60,6 +60,7 @@ from marvin.codes import PASS import random +import time class Services: """Test Add Remove Network Services @@ -67,7 +68,7 @@ class Services: def __init__(self): self.services = { - + "sleep": 60, "ostype": "CentOS 5.3 (64-bit)", # Cent OS 5.3 (64 bit) @@ -173,7 +174,10 @@ class TestAddNetworkToVirtualMachine(cloudstackTestCase): @classmethod def setUpClass(cls): - cls.api_client = super(TestAddNetworkToVirtualMachine, cls).getClsTestClient().getApiClient() + cls.testClient = super(TestAddNetworkToVirtualMachine, cls).getClsTestClient() + cls.api_client = cls.testClient.getApiClient() + + cls.services = Services().services hypervisor = get_hypervisor_type(cls.api_client) if hypervisor.lower() not in ["xenserver","kvm"]: @@ -181,8 +185,8 @@ def setUpClass(cls): 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) + cls.domain = get_domain(cls.api_client) + cls.zone = get_zone(cls.api_client, cls.testClient.getZoneForTests()) template = get_template(cls.api_client, cls.zone.id, cls.services["ostype"]) # Set Zones and disk offerings @@ -343,14 +347,10 @@ def test_02_add_nw_stopped_vm(self, value): # Validate the following: # 1. New nic is generated for the added network - self.debug("Stopping Virtual Machine: %s" % self.virtual_machine.id) - self.virtual_machine.stop(self.apiclient) - - vm_list = list_virtual_machines(self.apiclient,id=self.virtual_machine.id) - vm_list_validation_result = validateList(vm_list) - self.assertEqual(vm_list_validation_result[0], PASS, "vm list validation failed due to %s" % - vm_list_validation_result[2]) - self.assertTrue(vm_list[0].state == 'Stopped', "Failed to stop VM, the state is %s" % vm_list[0].state) + try: + self.virtual_machine.stop(self.apiclient) + except Exception as e: + self.fail("Failed to stop VM: %s" % e) network = None #The network which we are adding to the vm if value == "isolated": @@ -392,8 +392,7 @@ def test_03_add_nw_multiple_times(self, value): # Trying to add same network to vm for the second time with self.assertRaises(Exception) as e: self.addNetworkToVm(network, self.virtual_machine) - - self.debug("Adding same network again failed with exception: %s" % e.exception) + self.debug("Adding same network again failed with exception: %s" % e.exception) return @@ -448,16 +447,10 @@ def test_05_add_vpc_nw_stopped_vm(self, value): # Validate the following: # 1. Adding VPC to vm should fail - self.debug("Stopping Virtual Machine: %s" % self.virtual_machine.id) - self.virtual_machine.stop(self.apiclient) - - vm_list = list_virtual_machines(self.apiclient,id=self.virtual_machine.id) - #validation vm list - vm_list_validation_result = validateList(vm_list) - self.assertEqual(vm_list_validation_result[0], PASS, "vm list validation failed due to %s" % - vm_list_validation_result[2]) - - self.assertTrue(vm_list[0].state == 'Stopped', "Failed to stop VM, the state is %s" % vm_list[0].state) + try: + self.virtual_machine.stop(self.apiclient) + except Exception as e: + self.fail("Failed to stop virtual machine: %s" % e) self.addNetworkToVm(self.isolated_network, self.virtual_machine) @@ -515,7 +508,7 @@ def test_10_add_nw_invalid_ipaddress_running_vm(self): with self.assertRaises(Exception) as e: self.addNetworkToVm(self.shared_network, self.virtual_machine, ipaddress = ipaddress) - self.debug("API failed with exception: %s" % e.exception) + self.debug("API failed with exception: %s" % e.exception) return @@ -552,9 +545,7 @@ def test_14_add_nw_different_account(self, value): with self.assertRaises(Exception) as e: self.virtual_machine.add_nic(self.apiclient, network.id) - network.delete(self.apiclient) - - self.debug("Operation failed with exception %s" % e.exception) + self.debug("Operation failed with exception %s" % e.exception) return @@ -606,15 +597,13 @@ def test_24_add_nw_different_domain(self): domainid=self.child_do_admin_2.domainid, serviceofferingid=self.service_offering.id, mode=self.zone.networktype) + time.sleep(self.services["sleep"]) self.debug("Trying to %s network in domain %s to a vm in domain %s, This should fail" % (network.type, self.child_domain_1.name, self.child_domain_2.name)) with self.assertRaises(Exception) as e: virtual_machine.add_nic(self.apiclient, network.id) - self.debug("Operation failed with exception %s" % e.exception) - - network.delete(self.apiclient) - + self.debug("Operation failed with exception %s" % e.exception) return @attr(tags = ["advanced"]) @@ -686,7 +675,7 @@ def test_25_add_nw_above_account_limit(self): with self.assertRaises(Exception) as e: virtual_machine.add_nic(self.apiclient, network_2.id) - self.debug("Operation failed with exception %s" % e.exception) + self.debug("Operation failed with exception %s" % e.exception) return @@ -694,16 +683,18 @@ class TestRemoveNetworkFromVirtualMachine(cloudstackTestCase): @classmethod def setUpClass(cls): - cls.api_client = super(TestRemoveNetworkFromVirtualMachine, cls).getClsTestClient().getApiClient() + cls.testClient = super(TestRemoveNetworkFromVirtualMachine, cls).getClsTestClient() + cls.api_client = cls.testClient.getApiClient() + + cls.services = Services().services hypervisor = get_hypervisor_type(cls.api_client) if hypervisor.lower() not in ["xenserver","kvm"]: raise unittest.SkipTest("This feature is supported only on XenServer and KVM") - 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) + cls.domain = get_domain(cls.api_client) + cls.zone = get_zone(cls.api_client, cls.testClient.getZoneForTests()) template = get_template(cls.api_client,cls.zone.id,cls.services["ostype"]) # Set Zones and disk offerings @@ -836,7 +827,7 @@ def test_08_remove_default_nic(self): self.virtual_machine.id) with self.assertRaises(Exception): self.virtual_machine.remove_nic(self.apiclient, vm_list[0].nic[0].id) - self.debug("Removing default nic of vm failed") + self.debug("Removing default nic of vm failed") return @attr(tags = ["advanced"]) @@ -867,23 +858,25 @@ def test_09_remove_foreign_nic(self): operation should fail") with self.assertRaises(Exception) as e: self.virtual_machine.remove_nic(self.apiclient, virtual_machine.nic[0].id) - self.debug("Operation failed with exception: %s" % e.exception) + self.debug("Operation failed with exception: %s" % e.exception) return class TestUpdateVirtualMachineNIC(cloudstackTestCase): @classmethod def setUpClass(cls): - cls.api_client = super(TestUpdateVirtualMachineNIC, cls).getClsTestClient().getApiClient() + cls.testClient = super(TestUpdateVirtualMachineNIC, cls).getClsTestClient() + cls.api_client = cls.testClient.getApiClient() + + cls.services = Services().services hypervisor = get_hypervisor_type(cls.api_client) if hypervisor.lower() not in ["xenserver","kvm"]: raise unittest.SkipTest("This feature is supported only on XenServer and KVM") - 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) + cls.domain = get_domain(cls.api_client) + cls.zone = get_zone(cls.api_client, cls.testClient.getZoneForTests()) template = get_template(cls.api_client,cls.zone.id,cls.services["ostype"]) # Set Zones and disk offerings @@ -1045,7 +1038,7 @@ def test_12_make_default_nic_as_default(self): self.debug("Trying to set default nic again as default nic, This should fail") with self.assertRaises(Exception) as e: self.virtual_machine.update_default_nic(self.apiclient, nicId = defaultNicId) - self.debug("updateDefaultNic operation failed as expected with exception: %s" % + self.debug("updateDefaultNic operation failed as expected with exception: %s" % e.exception) return @@ -1070,15 +1063,16 @@ def test_13_set_foreign_nic_as_default(self): virtual_machine = VirtualMachine.create(self.apiclient,self.services["virtual_machine"], accountid=account.name,domainid=account.domainid, serviceofferingid=self.service_offering.id,mode=self.zone.networktype) + time.sleep(self.services["sleep"]) self.debug("Deployed virtual machine: %s" % virtual_machine.id) - + foreignNicId = virtual_machine.nic[0].id self.debug("Trying to set nic of new virtual machine as default nic of existing virtual machine, This \ operation should fail") with self.assertRaises(Exception) as e: self.virtual_machine.update_default_nic(self.apiclient, nicId = foreignNicId) - self.debug("updateDefaultNic operation failed as expected with exception: %s" % + self.debug("updateDefaultNic operation failed as expected with exception: %s" % e.exception) return @@ -1087,16 +1081,18 @@ class TestFailureScenariosAddNetworkToVM(cloudstackTestCase): @classmethod def setUpClass(cls): - cls.api_client = super(TestFailureScenariosAddNetworkToVM, cls).getClsTestClient().getApiClient() + cls.testClient = super(TestFailureScenariosAddNetworkToVM, cls).getClsTestClient() + cls.api_client = cls.testClient.getApiClient() + + cls.services = Services().services hypervisor = get_hypervisor_type(cls.api_client) if hypervisor.lower() not in ["xenserver","kvm"]: raise unittest.SkipTest("This feature is supported only on XenServer and KVM") - 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) + cls.domain = get_domain(cls.api_client) + cls.zone = get_zone(cls.api_client, cls.testClient.getZoneForTests()) template = get_template(cls.api_client,cls.zone.id,cls.services["ostype"]) # Set Zones and disk offerings cls.services["virtual_machine"]["zoneid"] = cls.zone.id @@ -1224,6 +1220,7 @@ def test_17_add_nic_different_zone(self): cmd.networkid = isolated_network.id with self.assertRaises(Exception) as e: + time.sleep(5) self.apiclient.addNicToVirtualMachine(cmd) self.debug("addNicToVirtualMachine API failed with exception: %s" % e.exception) @@ -1265,6 +1262,7 @@ def test_18_add_nic_basic_zone(self): virtual_machine = VirtualMachine.create(self.apiclient,self.services["virtual_machine"], serviceofferingid=self.service_offering.id, mode=basicZone.networktype) + time.sleep(self.services["sleep"]) self.debug("Deployed virtual machine %s: " % virtual_machine.id) cmd = addNicToVirtualMachine.addNicToVirtualMachineCmd() @@ -1274,6 +1272,7 @@ def test_18_add_nic_basic_zone(self): self.dedbug("Trying to add isolated network to VM (both in basic zone,\ this operation should fail") with self.assertRaises(Exception) as e: + time.sleep(5) self.apiclient.addNicToVirtualMachine(cmd) self.debug("addNicToVirtualMachine API failed with exception: %s" % e.exception) @@ -1300,12 +1299,13 @@ def test_26_add_nic_insufficient_permission(self): self.debug("Created account %s" % account.name) self.debug("creating user api client for account: %s" % account.name) - api_client = self.testClient.createUserApiClient(UserName=account.name, DomainName=self.account.domain) + api_client = self.testClient.getUserApiClient(UserName=account.name, DomainName=self.account.domain) self.debug("Trying to add network to vm with this api client, this should fail due to \ insufficient permission") with self.assertRaises(Exception) as e: + time.sleep(5) api_client.addNicToVirtualMachine(cmd) self.debug("addNicToVirtualMachine API failed with exception: %s" % e.exception) @@ -1315,16 +1315,18 @@ class TestFailureScenariosRemoveNicFromVM(cloudstackTestCase): @classmethod def setUpClass(cls): - cls.api_client = super(TestFailureScenariosRemoveNicFromVM, cls).getClsTestClient().getApiClient() + cls.testClient = super(TestFailureScenariosRemoveNicFromVM, cls).getClsTestClient() + cls.api_client = cls.testClient.getApiClient() + + cls.services = Services().services hypervisor = get_hypervisor_type(cls.api_client) if hypervisor.lower() not in ["xenserver","kvm"]: raise unittest.SkipTest("This feature is supported only on XenServer and KVM") - 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) + cls.domain = get_domain(cls.api_client) + cls.zone = get_zone(cls.api_client, cls.testClient.getZoneForTests()) template = get_template(cls.api_client,cls.zone.id,cls.services["ostype"]) # Set Zones and disk offerings @@ -1372,7 +1374,7 @@ def tearDown(self): def tearDownClass(cls): try: # Disable Network Offerings - #cls.isolated_network_offering.update(cls.api_client, state='Disabled') + cls.isolated_network_offering.update(cls.api_client, state='Disabled') # Cleanup resources used cleanup_resources(cls.api_client, cls._cleanup) @@ -1478,7 +1480,7 @@ def test_27_remove_nic_insufficient_permission(self): self.debug("Created account %s" % account.name) self.debug("creating user api client for account: %s" % account.name) - api_client = self.testClient.createUserApiClient(UserName=account.name, DomainName=self.account.domain) + api_client = self.testClient.getUserApiClient(UserName=account.name, DomainName=self.account.domain) self.debug("Trying to add network to vm with this api client, this should fail due to \ insufficient permission") @@ -1493,16 +1495,18 @@ class TestFailureScenariosUpdateVirtualMachineNIC(cloudstackTestCase): @classmethod def setUpClass(cls): - cls.api_client = super(TestFailureScenariosUpdateVirtualMachineNIC, cls).getClsTestClient().getApiClient() + cls.testClient = super(TestFailureScenariosUpdateVirtualMachineNIC, cls).getClsTestClient() + cls.api_client = cls.testClient.getApiClient() + + cls.services = Services().services hypervisor = get_hypervisor_type(cls.api_client) if hypervisor.lower() not in ["xenserver","kvm"]: raise unittest.SkipTest("This feature is supported only on XenServer and KVM") - 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) + cls.domain = get_domain(cls.api_client) + cls.zone = get_zone(cls.api_client, cls.testClient.getZoneForTests()) template = get_template(cls.api_client, cls.zone.id, cls.services["ostype"]) # Set Zones and disk offerings @@ -1601,7 +1605,7 @@ def test_21_update_nic_wrong_vm_id(self): with self.assertRaises(Exception) as e: self.apiclient.updateDefaultNicForVirtualMachine(cmd) - self.debug("updateDefaultNicForVirtualMachine API failed with exception: %s" % + self.debug("updateDefaultNicForVirtualMachine API failed with exception: %s" % e.exception) return @@ -1647,7 +1651,7 @@ def test_22_update_nic_wrong_nic_id(self): with self.assertRaises(Exception) as e: self.apiclient.updateDefaultNicForVirtualMachine(cmd) - self.debug("updateDefaultNicForVirtualMachine API failed with exception: %s" % + self.debug("updateDefaultNicForVirtualMachine API failed with exception: %s" % e.exception) return @@ -1676,7 +1680,7 @@ def test_23_update_nic_incorrect_vm_state(self): accountid=account.name,domainid=account.domainid, serviceofferingid=self.service_offering.id, mode=self.zone.networktype) - + time.sleep(self.services["sleep"]) self.debug("Created virtual machine %s" % virtual_machine.id) self.debug("Creating isolated network in account %s" % account.name) @@ -1729,7 +1733,7 @@ def test_23_update_nic_incorrect_vm_state(self): with self.assertRaises(Exception) as e: self.apiclient.updateDefaultNicForVirtualMachine(cmd) - self.debug("updateDefaultNicForVirtualMachine API failed with exception: %s" % + self.debug("updateDefaultNicForVirtualMachine API failed with exception: %s" % e.exception) return @@ -1749,7 +1753,7 @@ def test_28_update_nic_insufficient_permission(self): self.debug("Created account %s" % account.name) self.debug("creating user api client for account: %s" % account.name) - api_client = self.testClient.createUserApiClient(UserName=account.name, DomainName=self.account.domain) + api_client = self.testClient.getUserApiClient(UserName=account.name, DomainName=self.account.domain) self.debug("Listing virtual machine so that to retrive the list of non-default and default nic") vm_list = list_virtual_machines(self.apiclient, id=self.virtual_machine.id) @@ -1779,7 +1783,7 @@ def test_28_update_nic_insufficient_permission(self): with self.assertRaises(Exception) as e: api_client.updateDefaultNicForVirtualMachine(cmd) - self.debug("updateDefaultNicForVirtualMachine API failed with exception: %s" % + self.debug("updateDefaultNicForVirtualMachine API failed with exception: %s" % e.exception) return diff --git a/test/integration/component/test_advancedsg_networks.py b/test/integration/component/test_advancedsg_networks.py index 207659f1ef..2794f96951 100644 --- a/test/integration/component/test_advancedsg_networks.py +++ b/test/integration/component/test_advancedsg_networks.py @@ -19,7 +19,7 @@ """ from marvin.cloudstackTestCase import cloudstackTestCase, unittest from ddt import ddt, data -from marvin.integration.lib.base import (Zone, +from marvin.lib.base import (Zone, ServiceOffering, Account, NetworkOffering, @@ -31,14 +31,14 @@ SecurityGroup, Host) -from marvin.integration.lib.common import (get_domain, +from marvin.lib.common import (get_domain, get_zone, get_template, get_free_vlan, list_virtual_machines, wait_for_cleanup) -from marvin.integration.lib.utils import (cleanup_resources, +from marvin.lib.utils import (cleanup_resources, random_gen, validateList) from marvin.cloudstackAPI import (authorizeSecurityGroupIngress, @@ -54,14 +54,12 @@ class TestCreateZoneSG(cloudstackTestCase): @classmethod def setUpClass(cls): - cloudstackTestClient = super(TestCreateZoneSG,cls).getClsTestClient() - cls.api_client = cloudstackTestClient.getApiClient() - - # Fill services from the external config file - cls.services = cloudstackTestClient.getConfigParser().parsedDict + cls.testClient = super(TestCreateZoneSG, cls).getClsTestClient() + cls.api_client = cls.testClient.getApiClient() + cls.services = cls.testClient.getParsedTestDataConfig() # Get Zone, Domain and templates - cls.domain = get_domain(cls.api_client, cls.services) + cls.domain = get_domain(cls.api_client) cls._cleanup = [] return @@ -154,14 +152,13 @@ class TestNetworksInAdvancedSG(cloudstackTestCase): @classmethod def setUpClass(cls): - cloudstackTestClient = super(TestNetworksInAdvancedSG,cls).getClsTestClient() - cls.api_client = cloudstackTestClient.getApiClient() - - cls.services = cloudstackTestClient.getConfigParser().parsedDict + cls.testClient = super(TestNetworksInAdvancedSG, cls).getClsTestClient() + cls.api_client = cls.testClient.getApiClient() + cls.services = cls.testClient.getParsedTestDataConfig() # Get Zone, Domain and templates - cls.domain = get_domain(cls.api_client, cls.services) - cls.zone = get_zone(cls.api_client, cls.services) + cls.domain = get_domain(cls.api_client) + cls.zone = get_zone(cls.api_client, cls.testClient.getZoneForTests()) cls.template = get_template(cls.api_client, cls.zone.id, cls.services["ostype"]) @@ -1102,14 +1099,13 @@ class TestNetworksInAdvancedSG_VmOperations(cloudstackTestCase): @classmethod def setUpClass(cls): - cloudstackTestClient = super(TestNetworksInAdvancedSG_VmOperations,cls).getClsTestClient() - cls.api_client = cloudstackTestClient.getApiClient() - - cls.services = cloudstackTestClient.getConfigParser().parsedDict + cls.testClient = super(TestNetworksInAdvancedSG_VmOperations, cls).getClsTestClient() + cls.api_client = cls.testClient.getApiClient() + cls.services = cls.testClient.getParsedTestDataConfig() # Get Zone, Domain and templates - cls.domain = get_domain(cls.api_client, cls.services) - cls.zone = get_zone(cls.api_client, cls.services) + cls.domain = get_domain(cls.api_client) + cls.zone = get_zone(cls.api_client, cls.testClient.getZoneForTests()) cls.template = get_template(cls.api_client,cls.zone.id,cls.services["ostype"]) cls.services["virtual_machine"]["zoneid"] = cls.zone.id @@ -1311,11 +1307,11 @@ def test__16_AccountSpecificNwAccess(self): zoneid=self.zone.id) # Creaint user API client of account 1 - api_client_account_1 = self.testClient.createUserApiClient(UserName=account_1.name, + api_client_account_1 = self.testClient.getUserApiClient(UserName=account_1.name, DomainName=account_1.domain) # Creaint user API client of account 2 - api_client_account_2 = self.testClient.createUserApiClient(UserName=account_2.name, + api_client_account_2 = self.testClient.getUserApiClient(UserName=account_2.name, DomainName=account_2.domain) self.debug("Creating virtual machine in account %s with account specific shared network %s" % @@ -1423,11 +1419,11 @@ def test__17_DomainSpecificNwAccess(self): self.cleanup_networks.append(shared_network_domain_2) # Creaint user API client of account 1 - api_client_domain_1 = self.testClient.createUserApiClient(UserName=account_1.name, + api_client_domain_1 = self.testClient.getUserApiClient(UserName=account_1.name, DomainName=account_1.domain) # Creaint user API client of account 2 - api_client_domain_2 = self.testClient.createUserApiClient(UserName=account_2.name, + api_client_domain_2 = self.testClient.getUserApiClient(UserName=account_2.name, DomainName=account_2.domain) self.debug("Creating virtual machine in domain %s with domain wide shared network %s" % @@ -2086,14 +2082,13 @@ class TestSecurityGroups_BasicSanity(cloudstackTestCase): @classmethod def setUpClass(cls): - cloudstackTestClient = super(TestSecurityGroups_BasicSanity,cls).getClsTestClient() - cls.api_client = cloudstackTestClient.getApiClient() - - cls.services = cloudstackTestClient.getConfigParser().parsedDict + cls.testClient = super(TestSecurityGroups_BasicSanity, cls).getClsTestClient() + cls.api_client = cls.testClient.getApiClient() + cls.services = cls.testClient.getParsedTestDataConfig() # Get Zone, Domain and templates - cls.domain = get_domain(cls.api_client, cls.services) - cls.zone = get_zone(cls.api_client, cls.services) + cls.domain = get_domain(cls.api_client) + cls.zone = get_zone(cls.api_client, cls.testClient.getZoneForTests()) cls.template = get_template(cls.api_client,cls.zone.id,cls.services["ostype"]) cls.services["virtual_machine"]["zoneid"] = cls.zone.id @@ -2548,14 +2543,13 @@ class TestSharedNetworkOperations(cloudstackTestCase): @classmethod def setUpClass(cls): - cloudstackTestClient = super(TestSharedNetworkOperations,cls).getClsTestClient() - cls.api_client = cloudstackTestClient.getApiClient() - - cls.services = cloudstackTestClient.getConfigParser().parsedDict + cls.testClient = super(TestSharedNetworkOperations, cls).getClsTestClient() + cls.api_client = cls.testClient.getApiClient() + cls.services = cls.testClient.getParsedTestDataConfig() # Get Zone, Domain and templates - cls.domain = get_domain(cls.api_client, cls.services) - cls.zone = get_zone(cls.api_client, cls.services) + cls.domain = get_domain(cls.api_client) + cls.zone = get_zone(cls.api_client, cls.testClient.getZoneForTests()) cls.template = get_template(cls.api_client,cls.zone.id,cls.services["ostype"]) cls.services["virtual_machine"]["zoneid"] = cls.zone.id @@ -2815,14 +2809,13 @@ class TestAccountBasedIngressRules(cloudstackTestCase): @classmethod def setUpClass(cls): - cloudstackTestClient = super(TestAccountBasedIngressRules,cls).getClsTestClient() - cls.api_client = cloudstackTestClient.getApiClient() - - cls.services = cloudstackTestClient.getConfigParser().parsedDict + cls.testClient = super(TestAccountBasedIngressRules, cls).getClsTestClient() + cls.api_client = cls.testClient.getApiClient() + cls.services = cls.testClient.getParsedTestDataConfig() # Get Zone, Domain and templates - cls.domain = get_domain(cls.api_client, cls.services) - cls.zone = get_zone(cls.api_client, cls.services) + cls.domain = get_domain(cls.api_client) + cls.zone = get_zone(cls.api_client, cls.testClient.getZoneForTests()) cls.template = get_template(cls.api_client,cls.zone.id,cls.services["ostype"]) cls.services["virtual_machine"]["zoneid"] = cls.zone.id diff --git a/test/integration/component/test_affinity_groups.py b/test/integration/component/test_affinity_groups.py index 7e4fabe547..d0fa2f7a3d 100644 --- a/test/integration/component/test_affinity_groups.py +++ b/test/integration/component/test_affinity_groups.py @@ -15,12 +15,20 @@ # 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.sshClient import SshClient +from marvin.cloudstackTestCase import cloudstackTestCase, unittest +from marvin.cloudstackAPI import deleteAffinityGroup +from marvin.lib.utils import (cleanup_resources, + random_gen) +from marvin.lib.base import (Account, + ServiceOffering, + VirtualMachine, + AffinityGroup, + Domain) +from marvin.lib.common import (get_zone, + get_domain, + get_template, + list_virtual_machines, + wait_for_cleanup) from nose.plugins.attrib import attr class Services: @@ -89,12 +97,12 @@ class TestCreateAffinityGroup(cloudstackTestCase): @classmethod def setUpClass(cls): - - cls.api_client = super(TestCreateAffinityGroup, cls).getClsTestClient().getApiClient() + cls.testClient = super(TestCreateAffinityGroup, cls).getClsTestClient() + cls.api_client = cls.testClient.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) + cls.domain = get_domain(cls.api_client) + cls.zone = get_zone(cls.api_client, cls.testClient.getZoneForTests()) cls.template = get_template( cls.api_client, cls.zone.id, @@ -169,7 +177,7 @@ def create_aff_grp(self, api_client=None, aff_grp=None, except Exception as e: raise Exception("Error: Creation of Affinity Group failed : %s" %e) - @attr(tags=["simulator", "basic", "advanced"]) + @attr(tags=["simulator", "basic", "advanced", "selfservice"]) def test_01_admin_create_aff_grp(self): """ Test create affinity group as admin @@ -184,7 +192,7 @@ def test_01_admin_create_aff_grp(self): self.assert_(list_aff_grps[0].id == aff_grp.id) self.cleanup.append(aff_grp) - @attr(tags=["simulator", "basic", "advanced"]) + @attr(tags=["simulator", "basic", "advanced", "selfservice"]) def test_02_doadmin_create_aff_grp(self): """ Test create affinity group as domain admin @@ -197,14 +205,14 @@ def test_02_doadmin_create_aff_grp(self): self.cleanup.append(self.do_admin) self.cleanup.append(self.new_domain) - domainapiclient = self.testClient.createUserApiClient(self.do_admin.name, self.new_domain.name, 2) + domainapiclient = self.testClient.getUserApiClient(self.do_admin.name, self.new_domain.name, 2) aff_grp = self.create_aff_grp(api_client=domainapiclient, aff_grp=self.services["host_anti_affinity"], acc=self.do_admin.name, domainid=self.new_domain.id) aff_grp.delete(domainapiclient) #@attr(tags=["simulator", "basic", "advanced"]) - @attr(tags=["vogxn", "simulator", "basic", "advanced"]) + @attr(tags=["vogxn", "simulator", "basic", "advanced", "selfservice"]) def test_03_user_create_aff_grp(self): """ Test create affinity group as user @@ -214,7 +222,7 @@ def test_03_user_create_aff_grp(self): self.user = Account.create(self.api_client, self.services["new_account"], domainid=self.domain.id) - userapiclient = self.testClient.createUserApiClient(self.user.name, self.domain.name) + userapiclient = self.testClient.getUserApiClient(self.user.name, self.domain.name) self.cleanup.append(self.user) aff_grp = self.create_aff_grp(api_client=userapiclient, aff_grp=self.services["host_anti_affinity"], @@ -222,7 +230,7 @@ def test_03_user_create_aff_grp(self): aff_grp.delete(userapiclient) - @attr(tags=["simulator", "basic", "advanced"]) + @attr(tags=["simulator", "basic", "advanced", "selfservice"]) def test_04_user_create_aff_grp_existing_name(self): """ Test create affinity group that exists (same name) @@ -243,7 +251,7 @@ def test_04_user_create_aff_grp_existing_name(self): self.debug("Deleted Affinity Group: %s" %aff_grp.name) aff_grp.delete(self.api_client) - @attr(tags=["simulator", "basic", "advanced"]) + @attr(tags=["simulator", "basic", "advanced", "selfservice"]) def test_05_create_aff_grp_same_name_diff_acc(self): """ Test create affinity group with existing name but within different account @@ -265,7 +273,7 @@ def test_05_create_aff_grp_same_name_diff_acc(self): self.debug("Deleted Affinity Group: %s" %aff_grp.name) aff_grp.delete(self.api_client) - @attr(tags=["simulator", "basic", "advanced"]) + @attr(tags=["simulator", "basic", "advanced", "selfservice"]) def test_06_create_aff_grp_nonexisting_type(self): """ Test create affinity group of non-existing type @@ -283,12 +291,14 @@ class TestListAffinityGroups(cloudstackTestCase): @classmethod def setUpClass(cls): + cls.testClient = super(TestListAffinityGroups, cls).getClsTestClient() + cls.api_client = cls.testClient.getApiClient() - cls.api_client = super(TestListAffinityGroups, 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) + cls.domain = get_domain(cls.api_client) + cls.zone = get_zone(cls.api_client, cls.testClient.getZoneForTests()) + cls.template = get_template( cls.api_client, cls.zone.id, @@ -391,7 +401,7 @@ def create_vm_in_aff_grps(self, ag_list, account_name=None, domain_id=None): msg="VM is not in Running state") return vm, vm_response.hostid - @attr(tags=["simulator", "basic", "advanced"]) + @attr(tags=["simulator", "basic", "advanced", "selfservice"]) def test_01_list_aff_grps_for_vm(self): """ List affinity group for a vm @@ -413,7 +423,7 @@ def test_01_list_aff_grps_for_vm(self): self.aff_grp[0].delete(self.api_client) - @attr(tags=["simulator", "basic", "advanced"]) + @attr(tags=["simulator", "basic", "advanced", "selfservice"]) def test_02_list_multiple_aff_grps_for_vm(self): """ List multiple affinity groups associated with a vm @@ -442,7 +452,7 @@ def test_02_list_multiple_aff_grps_for_vm(self): aff_grp_01.delete(self.api_client) aff_grp_02.delete(self.api_client) - @attr(tags=["simulator", "basic", "advanced"]) + @attr(tags=["simulator", "basic", "advanced", "selfservice"]) def test_03_list_aff_grps_by_id(self): """ List affinity groups by id @@ -457,7 +467,7 @@ def test_03_list_aff_grps_by_id(self): self.aff_grp[0].delete(self.api_client) - @attr(tags=["simulator", "basic", "advanced"]) + @attr(tags=["simulator", "basic", "advanced", "selfservice"]) def test_04_list_aff_grps_by_name(self): """ List Affinity Groups by name @@ -471,7 +481,7 @@ def test_04_list_aff_grps_by_name(self): self.aff_grp[0].delete(self.api_client) - @attr(tags=["simulator", "basic", "advanced"]) + @attr(tags=["simulator", "basic", "advanced", "selfservice"]) def test_05_list_aff_grps_by_non_existing_id(self): """ List Affinity Groups by non-existing id @@ -485,7 +495,7 @@ def test_05_list_aff_grps_by_non_existing_id(self): self.aff_grp[0].delete(self.api_client) - @attr(tags=["simulator", "basic", "advanced"]) + @attr(tags=["simulator", "basic", "advanced", "selfservice"]) def test_06_list_aff_grps_by_non_existing_name(self): """ List Affinity Groups by non-existing name @@ -499,7 +509,7 @@ def test_06_list_aff_grps_by_non_existing_name(self): self.aff_grp[0].delete(self.api_client) - @attr(tags=["simulator", "basic", "advanced"]) + @attr(tags=["simulator", "basic", "advanced", "selfservice"]) def test_07_list_all_vms_in_aff_grp(self): """ List affinity group should list all for a vms associated with that group @@ -530,11 +540,14 @@ class TestDeleteAffinityGroups(cloudstackTestCase): @classmethod def setUpClass(cls): - cls.api_client = super(TestDeleteAffinityGroups, cls).getClsTestClient().getApiClient() + cls.testClient = super(TestDeleteAffinityGroups, cls).getClsTestClient() + cls.api_client = cls.testClient.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) + cls.domain = get_domain(cls.api_client) + cls.zone = get_zone(cls.api_client, cls.testClient.getZoneForTests()) + cls.template = get_template( cls.api_client, cls.zone.id, @@ -642,7 +655,7 @@ def delete_aff_group(self, apiclient, **kwargs): [setattr(cmd, k, v) for k, v in kwargs.items()] return apiclient.deleteAffinityGroup(cmd) - @attr(tags=["simulator", "basic", "advanced", "multihost"]) + @attr(tags=["simulator", "basic", "advanced", "multihost", "selfservice"]) def test_01_delete_aff_grp_by_name(self): """ Delete Affinity Group by name @@ -653,7 +666,7 @@ def test_01_delete_aff_grp_by_name(self): self.delete_aff_group(self.api_client, name=aff_0.name) self.assert_(AffinityGroup.list(self.api_client, name=aff_0.name) is None) - @attr(tags=["simulator", "basic", "advanced", "multihost"]) + @attr(tags=["simulator", "basic", "advanced", "multihost", "selfservice"]) def test_02_delete_aff_grp_for_acc(self): """ Delete Affinity Group as admin for an account @@ -669,7 +682,7 @@ def test_02_delete_aff_grp_for_acc(self): self.create_vm_in_aff_grps([aff_0.name], account_name=self.account.name, domain_id=self.domain.id) aff_1.delete(self.api_client) - @attr(tags=["simulator", "basic", "advanced", "multihost"]) + @attr(tags=["simulator", "basic", "advanced", "multihost", "selfservice"]) def test_03_delete_aff_grp_with_vms(self): """ Delete Affinity Group which has vms in it @@ -687,7 +700,7 @@ def test_03_delete_aff_grp_with_vms(self): wait_for_cleanup(self.apiclient, ["expunge.delay", "expunge.interval"]) aff_1.delete(self.api_client) - @attr(tags=["simulator", "basic", "advanced", "multihost"]) + @attr(tags=["simulator", "basic", "advanced", "multihost", "selfservice"]) def test_05_delete_aff_grp_id(self): """ Delete Affinity Group with id which does not belong to this user @@ -704,10 +717,10 @@ def test_05_delete_aff_grp_id(self): self.user2 = Account.create(self.apiclient, self.services["new_account1"]) self.cleanup.append(self.user2) - userapiclient = self.testClient.createUserApiClient( + userapiclient = self.testClient.getUserApiClient( UserName=self.user2.name, DomainName=self.user2.domain, - acctType=0) + type=0) aff_1 = self.create_aff_grp(api_client=userapiclient, aff_grp=self.services["host_anti_affinity"]) @@ -723,7 +736,7 @@ def test_05_delete_aff_grp_id(self): aff_0.delete(self.api_client) aff_1.delete(userapiclient) - @attr(tags=["simulator", "basic", "advanced", "multihost"]) + @attr(tags=["simulator", "basic", "advanced", "multihost", "selfservice"]) def test_06_delete_aff_grp_name(self): """ Delete Affinity Group by name which does not belong to this user @@ -740,10 +753,10 @@ def test_06_delete_aff_grp_name(self): self.user2 = Account.create(self.apiclient, self.services["new_account1"]) self.cleanup.append(self.user2) - userapiclient = self.testClient.createUserApiClient( + userapiclient = self.testClient.getUserApiClient( UserName=self.user2.name, DomainName=self.user2.domain, - acctType=0) + type=0) aff_1 = self.create_aff_grp(api_client=userapiclient, aff_grp=self.services["host_anti_affinity"]) @@ -759,7 +772,7 @@ def test_06_delete_aff_grp_name(self): aff_0.delete(self.api_client) aff_1.delete(userapiclient) - @attr(tags=["simulator", "basic", "advanced"]) + @attr(tags=["simulator", "basic", "advanced", "selfservice"]) def test_08_delete_aff_grp_by_id(self): """ Delete Affinity Group by id. @@ -771,7 +784,7 @@ def test_08_delete_aff_grp_by_id(self): aff_grp_1.delete(self.api_client) aff_grp_2.delete(self.api_client) - @attr(tags=["simulator", "basic", "advanced"]) + @attr(tags=["simulator", "basic", "advanced", "selfservice"]) def test_09_delete_aff_grp_root_admin(self): """ Root admin should be able to delete affinity group of other users @@ -781,10 +794,10 @@ def test_09_delete_aff_grp_root_admin(self): self.services["new_account"]) self.cleanup.append(self.user1) - user1apiclient = self.testClient.createUserApiClient( + user1apiclient = self.testClient.getUserApiClient( UserName=self.user1.name, DomainName=self.user1.domain, - acctType=0) + type=0) aff_grp = self.create_aff_grp(api_client=user1apiclient, aff_grp=self.services["host_anti_affinity"]) @@ -800,11 +813,14 @@ class TestUpdateVMAffinityGroups(cloudstackTestCase): @classmethod def setUpClass(cls): - cls.api_client = super(TestUpdateVMAffinityGroups, cls).getClsTestClient().getApiClient() + cls.testClient = super(TestUpdateVMAffinityGroups, cls).getClsTestClient() + cls.api_client = cls.testClient.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) + cls.domain = get_domain(cls.api_client) + cls.zone = get_zone(cls.api_client, cls.testClient.getZoneForTests()) + cls.template = get_template( cls.api_client, cls.zone.id, @@ -909,7 +925,7 @@ def create_vm_in_aff_grps(self, ag_list, account_name=None, domain_id=None): return vm, vm_response.hostid - @attr(tags=["simulator", "basic", "advanced", "multihost"]) + @attr(tags=["simulator", "basic", "advanced", "multihost", "selfservice"]) def test_01_update_aff_grp_by_ids(self): """ Update the list of affinityGroups by using affinity groupids @@ -957,7 +973,7 @@ def test_01_update_aff_grp_by_ids(self): for aff_grp in self.aff_grp: aff_grp.delete(self.api_client) - @attr(tags=["simulator", "basic", "advanced", "multihost"]) + @attr(tags=["simulator", "basic", "advanced", "multihost", "selfservice"]) def test_02_update_aff_grp_by_names(self): """ Update the list of affinityGroups by using affinity groupnames @@ -1000,7 +1016,7 @@ def test_02_update_aff_grp_by_names(self): for aff_grp in self.aff_grp: aff_grp.delete(self.api_client) - @attr(tags=["simulator", "basic", "advanced", "multihost"]) + @attr(tags=["simulator", "basic", "advanced", "multihost", "selfservice"]) def test_03_update_aff_grp_for_vm_with_no_aff_grp(self): """ Update the list of affinityGroups for vm which is not associated @@ -1033,7 +1049,7 @@ def test_03_update_aff_grp_for_vm_with_no_aff_grp(self): aff_grp.delete(self.api_client) @unittest.skip("Skip - Failing - work in progress") - @attr(tags=["simulator", "basic", "advanced", "multihost"]) + @attr(tags=["simulator", "basic", "advanced", "multihost", "NotRun"]) def test_04_update_aff_grp_remove_all(self): """ Update the list of Affinity Groups to empty list @@ -1059,7 +1075,7 @@ def test_04_update_aff_grp_remove_all(self): for aff_grp in aff_grps: aff_grp.delete(self.api_client) - @attr(tags=["simulator", "basic", "advanced", "multihost"]) + @attr(tags=["simulator", "basic", "advanced", "multihost", "selfservice"]) def test_05_update_aff_grp_on_running_vm(self): """ Update the list of Affinity Groups on running vm @@ -1084,11 +1100,14 @@ class TestDeployVMAffinityGroups(cloudstackTestCase): @classmethod def setUpClass(cls): - cls.api_client = super(TestDeployVMAffinityGroups, cls).getClsTestClient().getApiClient() + cls.testClient = super(TestDeployVMAffinityGroups, cls).getClsTestClient() + cls.api_client = cls.testClient.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) + cls.domain = get_domain(cls.api_client) + cls.zone = get_zone(cls.api_client, cls.testClient.getZoneForTests()) + cls.template = get_template( cls.api_client, cls.zone.id, @@ -1195,7 +1214,7 @@ def create_vm_in_aff_grps(self, api_client=None, ag_list=None, ag_ids=None, acco return vm, vm_response.hostid - @attr(tags=["simulator", "basic", "advanced", "multihost"]) + @attr(tags=["simulator", "basic", "advanced", "multihost", "selfservice"]) def test_01_deploy_vm_without_aff_grp(self): """ Deploy VM without affinity group @@ -1206,7 +1225,7 @@ def test_01_deploy_vm_without_aff_grp(self): #Wait for expunge interval to cleanup VM wait_for_cleanup(self.apiclient, ["expunge.delay", "expunge.interval"]) - @attr(tags=["simulator", "basic", "advanced", "multihost"]) + @attr(tags=["simulator", "basic", "advanced", "multihost", "selfservice"]) def test_02_deploy_vm_by_aff_grp_name(self): """ Deploy VM by aff grp name @@ -1218,7 +1237,7 @@ def test_02_deploy_vm_by_aff_grp_name(self): wait_for_cleanup(self.apiclient, ["expunge.delay", "expunge.interval"]) self.aff_grp[0].delete(self.api_client) - @attr(tags=["simulator", "basic", "advanced", "multihost"]) + @attr(tags=["simulator", "basic", "advanced", "multihost", "selfservice"]) def test_03_deploy_vm_by_aff_grp_id(self): """ Deploy VM by aff grp id @@ -1234,7 +1253,7 @@ def test_03_deploy_vm_by_aff_grp_id(self): wait_for_cleanup(self.apiclient, ["expunge.delay", "expunge.interval"]) self.aff_grp[0].delete(self.api_client) - @attr(tags=["simulator", "basic", "advanced", "multihost"]) + @attr(tags=["simulator", "basic", "advanced", "multihost", "selfservice"]) def test_04_deploy_vm_anti_affinity_group(self): """ test DeployVM in anti-affinity groups @@ -1255,7 +1274,7 @@ def test_04_deploy_vm_anti_affinity_group(self): wait_for_cleanup(self.apiclient, ["expunge.delay", "expunge.interval"]) self.aff_grp[0].delete(self.api_client) - @attr(tags=["simulator", "basic", "advanced", "multihost"]) + @attr(tags=["simulator", "basic", "advanced", "multihost", "selfservice"]) def test_05_deploy_vm_by_id(self): """ Deploy vms by affinity group id @@ -1277,7 +1296,7 @@ def test_05_deploy_vm_by_id(self): wait_for_cleanup(self.apiclient, ["expunge.delay", "expunge.interval"]) self.aff_grp[0].delete(self.api_client) - @attr(tags=["simulator", "basic", "advanced", "multihost"]) + @attr(tags=["simulator", "basic", "advanced", "multihost", "selfservice"]) def test_06_deploy_vm_aff_grp_of_other_user_by_name(self): """ Deploy vm in affinity group of another user by name @@ -1294,10 +1313,10 @@ def test_06_deploy_vm_aff_grp_of_other_user_by_name(self): self.user2 = Account.create(self.apiclient, self.services["new_account1"]) self.cleanup.append(self.user2) - userapiclient = self.testClient.createUserApiClient( + userapiclient = self.testClient.getUserApiClient( UserName=self.user2.name, DomainName=self.user2.domain, - acctType=0) + type=0) self.create_aff_grp(api_client=userapiclient, aff_grp=self.services["host_anti_affinity"]) @@ -1310,7 +1329,7 @@ def test_06_deploy_vm_aff_grp_of_other_user_by_name(self): self.aff_grp[0].delete(self.api_client) self.aff_grp[1].delete(userapiclient) - @attr(tags=["simulator", "basic", "advanced", "multihost"]) + @attr(tags=["simulator", "basic", "advanced", "multihost", "selfservice"]) def test_07_deploy_vm_aff_grp_of_other_user_by_id(self): """ Deploy vm in affinity group of another user by id @@ -1327,10 +1346,10 @@ def test_07_deploy_vm_aff_grp_of_other_user_by_id(self): self.user2 = Account.create(self.apiclient, self.services["new_account1"]) self.cleanup.append(self.user2) - userapiclient = self.testClient.createUserApiClient( + userapiclient = self.testClient.getUserApiClient( UserName=self.user2.name, DomainName=self.user2.domain, - acctType=0) + type=0) self.create_aff_grp(api_client=userapiclient, aff_grp=self.services["host_anti_affinity"]) @@ -1346,7 +1365,7 @@ def test_07_deploy_vm_aff_grp_of_other_user_by_id(self): self.aff_grp[0].delete(self.api_client) self.aff_grp[1].delete(userapiclient) - @attr(tags=["simulator", "basic", "advanced", "multihost"]) + @attr(tags=["simulator", "basic", "advanced", "multihost", "selfservice"]) def test_08_deploy_vm_multiple_aff_grps(self): """ Deploy vm in multiple affinity groups @@ -1375,7 +1394,7 @@ def test_08_deploy_vm_multiple_aff_grps(self): self.aff_grp[0].delete(self.api_client) self.aff_grp[1].delete(self.api_client) - @attr(tags=["simulator", "basic", "advanced", "multihost"]) + @attr(tags=["simulator", "basic", "advanced", "multihost", "selfservice"]) def test_09_deploy_vm_multiple_aff_grps(self): """ Deploy multiple vms in multiple affinity groups @@ -1410,7 +1429,7 @@ def test_09_deploy_vm_multiple_aff_grps(self): self.aff_grp[0].delete(self.api_client) self.aff_grp[1].delete(self.api_client) - @attr(tags=["simulator", "basic", "advanced", "multihost"]) + @attr(tags=["simulator", "basic", "advanced", "multihost", "selfservice"]) def test_10_deploy_vm_by_aff_grp_name_and_id(self): """ Deploy VM by aff grp name and id @@ -1432,11 +1451,13 @@ class TestAffinityGroupsAdminUser(cloudstackTestCase): @classmethod def setUpClass(cls): - cls.api_client = super(TestAffinityGroupsAdminUser, cls).getClsTestClient().getApiClient() + cls.testClient = super(TestAffinityGroupsAdminUser, cls).getClsTestClient() + cls.api_client = cls.testClient.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) + cls.domain = get_domain(cls.api_client) + cls.zone = get_zone(cls.api_client, cls.testClient.getZoneForTests()) cls.template = get_template( cls.api_client, cls.zone.id, @@ -1540,7 +1561,7 @@ def create_vm_in_aff_grps(self, api_client=None, ag_list=None, ag_ids=None, acco return vm, vm_response.hostid - @attr(tags=["simulator", "basic", "advanced", "multihost"]) + @attr(tags=["simulator", "basic", "advanced", "multihost", "selfservice"]) def test_01_deploy_vm_another_user(self): """ Deploy vm as Admin in Affinity Group belonging to regular user (should fail) @@ -1549,10 +1570,10 @@ def test_01_deploy_vm_another_user(self): self.services["new_account"]) self.cleanup.append(self.user1) - userapiclient = self.testClient.createUserApiClient( + userapiclient = self.testClient.getUserApiClient( UserName=self.user1.name, DomainName=self.user1.domain, - acctType=0) + type=0) aff_grp = self.create_aff_grp(api_client=userapiclient, aff_grp=self.services["host_anti_affinity"]) @@ -1578,7 +1599,7 @@ def test_02_create_aff_grp_user(self): aff_grp.delete(self.apiclient) - @attr(tags=["simulator", "basic", "advanced", "multihost"]) + @attr(tags=["simulator", "basic", "advanced", "multihost", "selfservice"]) def test_03_list_aff_grp_all_users(self): """ List Affinity Groups as admin for all the users @@ -1588,10 +1609,10 @@ def test_03_list_aff_grp_all_users(self): self.services["new_account"]) self.cleanup.append(self.user1) - userapiclient = self.testClient.createUserApiClient( + userapiclient = self.testClient.getUserApiClient( UserName=self.user1.name, DomainName=self.user1.domain, - acctType=0) + type=0) aff_grp = self.create_aff_grp(api_client=userapiclient, aff_grp=self.services["host_anti_affinity"]) @@ -1601,7 +1622,7 @@ def test_03_list_aff_grp_all_users(self): "Groups of users") aff_grp.delete(userapiclient) - @attr(tags=["simulator", "basic", "advanced"]) + @attr(tags=["simulator", "basic", "advanced", "selfservice"]) def test_04_list_all_admin_aff_grp(self): """ List Affinity Groups belonging to admin user @@ -1628,7 +1649,7 @@ def test_04_list_all_admin_aff_grp(self): aff_grp1.delete(self.api_client) aff_grp2.delete(self.api_client) - @attr(tags=["simulator", "basic", "advanced"]) + @attr(tags=["simulator", "basic", "advanced", "selfservice"]) def test_05_list_all_users_aff_grp(self): """ List Affinity Groups belonging to regular user passing account id and domain id @@ -1638,10 +1659,10 @@ def test_05_list_all_users_aff_grp(self): self.services["new_account"]) self.cleanup.append(self.user1) - userapiclient = self.testClient.createUserApiClient( + userapiclient = self.testClient.getUserApiClient( UserName=self.user1.name, DomainName=self.user1.domain, - acctType=0) + type=0) aff_grp1 = self.create_aff_grp(api_client=userapiclient, aff_grp=self.services["host_anti_affinity"]) @@ -1664,7 +1685,7 @@ def test_05_list_all_users_aff_grp(self): aff_grp1.delete(self.api_client) aff_grp2.delete(self.api_client) - @attr(tags=["simulator", "basic", "advanced"]) + @attr(tags=["simulator", "basic", "advanced", "selfservice"]) def test_06_list_all_users_aff_grp_by_id(self): """ List Affinity Groups belonging to regular user passing group id @@ -1674,10 +1695,10 @@ def test_06_list_all_users_aff_grp_by_id(self): self.services["new_account"]) self.cleanup.append(self.user1) - userapiclient = self.testClient.createUserApiClient( + userapiclient = self.testClient.getUserApiClient( UserName=self.user1.name, DomainName=self.user1.domain, - acctType=0) + type=0) aff_grp = self.create_aff_grp(api_client=userapiclient, aff_grp=self.services["host_anti_affinity"]) @@ -1696,7 +1717,7 @@ def test_06_list_all_users_aff_grp_by_id(self): aff_grp.delete(self.api_client) - @attr(tags=["simulator", "basic", "advanced"]) + @attr(tags=["simulator", "basic", "advanced", "selfservice"]) def test_07_delete_aff_grp_of_other_user(self): """ Delete Affinity Group belonging to regular user @@ -1706,10 +1727,10 @@ def test_07_delete_aff_grp_of_other_user(self): self.services["new_account"]) self.cleanup.append(self.user1) - userapiclient = self.testClient.createUserApiClient( + userapiclient = self.testClient.getUserApiClient( UserName=self.user1.name, DomainName=self.user1.domain, - acctType=0) + type=0) aff_grp = self.create_aff_grp(api_client=userapiclient, aff_grp=self.services["host_anti_affinity"]) diff --git a/test/integration/component/test_allocation_states.py b/test/integration/component/test_allocation_states.py index 5ce0b21124..9ba246ffd8 100644 --- a/test/integration/component/test_allocation_states.py +++ b/test/integration/component/test_allocation_states.py @@ -15,17 +15,16 @@ # specific language governing permissions and limitations # under the License. -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 nose.plugins.attrib import attr -import datetime - - +from marvin.cloudstackTestCase import cloudstackTestCase +from marvin.lib.utils import cleanup_resources +from marvin.lib.base import (Host, + Pod, + Zone, + Cluster, + StoragePool) +from marvin.lib.common import get_zone, get_template +from marvin.codes import FAILED class Services: """Test Resource Limits Services """ @@ -86,13 +85,23 @@ class TestAllocationState(cloudstackTestCase): @classmethod def setUpClass(cls): - cls.api_client = super( - TestAllocationState, - cls - ).getClsTestClient().getApiClient() + cls.testClient = super(TestAllocationState, cls).getClsTestClient() + cls.api_client = cls.testClient.getApiClient() + cls.services = Services().services + # Get Zone, Domain and templates - cls.zone = get_zone(cls.api_client, cls.services) + + cls.zone = get_zone(cls.api_client, cls.testClient.getZoneForTests()) + cls.template = get_template( + cls.api_client, + cls.zone.id, + cls.services["ostype"] + ) + if cls.template == FAILED: + assert False, "get_template() failed to return template with description %s" % cls.services["ostype"] + + cls.services['mode'] = cls.zone.networktype cls._cleanup = [] return @@ -120,7 +129,7 @@ def tearDown(self): raise Exception("Warning: Exception during cleanup : %s" % e) return - @attr(tags = ["advanced", "advancedns", "simulator"]) + @attr(tags=["advanced", "advancedns", "simulator", "selfservice"]) def test_01_zones(self): """Check the status of zones""" @@ -146,7 +155,7 @@ def test_01_zones(self): ) return - @attr(tags = ["advanced", "advancedns", "simulator"]) + @attr(tags=["advanced", "advancedns", "simulator", "selfservice"]) def test_02_pods(self): """Check the status of pods""" @@ -172,7 +181,7 @@ def test_02_pods(self): ) return - @attr(tags = ["advanced", "advancedns", "simulator"]) + @attr(tags=["advanced", "advancedns", "simulator", "selfservice"]) def test_03_clusters(self): """Check the status of clusters""" @@ -198,7 +207,7 @@ def test_03_clusters(self): ) return - @attr(tags = ["advanced", "advancedns", "simulator"]) + @attr(tags=["advanced", "advancedns", "simulator", "selfservice"]) def test_04_hosts(self): """Check the status of hosts""" @@ -225,7 +234,7 @@ def test_04_hosts(self): ) return - @attr(tags = ["advanced", "advancedns", "simulator"]) + @attr(tags=["advanced", "advancedns", "simulator", "selfservice"]) def test_05_storage_pools(self): """Check the status of Storage pools""" @@ -251,7 +260,7 @@ def test_05_storage_pools(self): ) return - @attr(tags = ["advanced", "advancedns", "simulator"]) + @attr(tags=["advanced", "advancedns", "simulator", "selfservice"]) def test_06_secondary_storage(self): """Check the status of secondary storage""" diff --git a/test/integration/component/test_asa1000v_fw.py b/test/integration/component/test_asa1000v_fw.py index c8a11ab170..43d06d1864 100644 --- a/test/integration/component/test_asa1000v_fw.py +++ b/test/integration/component/test_asa1000v_fw.py @@ -18,15 +18,15 @@ """ Cisco ASA1000v external firewall """ #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.sshClient import SshClient -import datetime +from marvin.cloudstackTestCase import cloudstackTestCase +from marvin.lib.utils import cleanup_resources +from marvin.lib.base import (NetworkOffering, + PhysicalNetwork, + VNMC, + ASA1000V, + Cluster) +from marvin.lib.common import get_zone class Services: @@ -101,7 +101,7 @@ def setUp(self): self.apiclient = self.testClient.getApiClient() self.dbclient = self.testClient.getDbConnection() - self.zone = get_zone(self.apiclient, self.services) + self.zone = get_zone(self.apiclient, self.testClient.getZoneForTests()) self.physicalnetworks = PhysicalNetwork.list(self.apiclient, zoneid=self.zone.id) self.assertNotEqual(len(self.physicalnetworks), 0, "Check if the list physical network API returns a non-empty response") self.clusters = Cluster.list(self.apiclient, hypervisor='VMware') diff --git a/test/integration/component/test_assign_vm.py b/test/integration/component/test_assign_vm.py index 400d5f2e72..24b63a62f1 100644 --- a/test/integration/component/test_assign_vm.py +++ b/test/integration/component/test_assign_vm.py @@ -20,7 +20,7 @@ #Import Local Modules from nose.plugins.attrib import attr from marvin.cloudstackTestCase import cloudstackTestCase -from marvin.integration.lib.base import (Account, +from marvin.lib.base import (Account, Domain, User, Project, @@ -29,7 +29,7 @@ DiskOffering, ServiceOffering, VirtualMachine) -from marvin.integration.lib.common import (get_domain, +from marvin.lib.common import (get_domain, get_zone, get_template, list_volumes, @@ -37,7 +37,7 @@ list_networks, list_snapshots, list_virtual_machines) -from marvin.integration.lib.utils import cleanup_resources +from marvin.lib.utils import cleanup_resources def log_test_exceptions(func): def test_wrap_exception_log(self, *args, **kwargs): @@ -98,12 +98,13 @@ class TestVMOwnership(cloudstackTestCase): @classmethod def setUpClass(cls): cls._cleanup = [] - cls.api_client = super(TestVMOwnership, - cls).getClsTestClient().getApiClient() - cls.services = Services().services - # Get Zone Domain and create Domains and sub Domains. - cls.domain = get_domain(cls.api_client, cls.services) - cls.zone = get_zone(cls.api_client, cls.services) + cls.testClient = super(TestVMOwnership, cls).getClsTestClient() + cls.api_client = cls.testClient.getApiClient() + + cls.services = Services().services + # Get Zone, Domain and templates + cls.domain = get_domain(cls.api_client) + cls.zone = get_zone(cls.api_client, cls.testClient.getZoneForTests()) cls.services['mode'] = cls.zone.networktype # Get and set template id for VM creation. cls.template = get_template(cls.api_client, @@ -353,8 +354,8 @@ def test_09_move_across_subdomain(self): # 1. deploy VM in sub subdomain1 # 2. stop VM in sub subdomain1 # 3. assignVirtualMachine to subdomain2 - userapiclient = self.testClient.getUserApiClient(account=self.sdomain_account_user1['account'].name, - domain=self.sdomain_account_user1['domain'].name, + userapiclient = self.testClient.getUserApiClient(UserName=self.sdomain_account_user1['account'].name, + DomainName=self.sdomain_account_user1['domain'].name, type=2) self.create_vm(self.sdomain_account_user1['account'], self.sdomain_account_user1['domain']) self.assertRaises(Exception, self.virtual_machine.assign_virtual_machine, userapiclient, self.sdomain_account_user2['account'].name ,self.sdomain_account_user2['domain'].id) @@ -389,8 +390,8 @@ def test_12_move_across_subdomain_vm_volumes(self): # Validate the following: # 1. deploy VM in sub subdomain1 with volumes. # 3. assignVirtualMachine to subdomain2 - userapiclient = self.testClient.getUserApiClient(account=self.sdomain_account_user1['account'].name, - domain=self.sdomain_account_user1['domain'].name, + userapiclient = self.testClient.getUserApiClient(UserName=self.sdomain_account_user1['account'].name, + DomainName=self.sdomain_account_user1['domain'].name, type=2) self.create_vm(self.sdomain_account_user1['account'], self.sdomain_account_user1['domain'],volume=self.sdomain_account_user1['volume']) self.assertRaises(Exception, self.virtual_machine.assign_virtual_machine, userapiclient, self.sdomain_account_user2['account'].name ,self.sdomain_account_user2['domain'].id) @@ -431,8 +432,8 @@ def test_14_move_across_subdomain_vm_project(self): # Validate the following: # 1. deploy VM in sub subdomain1 with snapshot. # 3. assignVirtualMachine to subdomain2 - userapiclient = self.testClient.getUserApiClient(account=self.sdomain_account_user1['account'].name, - domain=self.sdomain_account_user1['domain'].name, + userapiclient = self.testClient.getUserApiClient(UserName=self.sdomain_account_user1['account'].name, + DomainName=self.sdomain_account_user1['domain'].name, type=2) self.create_vm(self.sdomain_account_user1['account'], self.sdomain_account_user1['domain'], project=self.sdomain_account_user1['project']) self.assertRaises(Exception, self.virtual_machine.assign_virtual_machine, userapiclient, self.sdomain_account_user2['account'].name ,self.sdomain_account_user2['domain'].id) @@ -450,8 +451,8 @@ def test_15_move_across_subdomain_account_limit(self): account=self.sdomain_account_user2['account'].name, domainid=self.sdomain_account_user2['domain'].id, max=0) - userapiclient = self.testClient.getUserApiClient(account=self.sdomain_account_user1['account'].name, - domain=self.sdomain_account_user1['domain'].name, + userapiclient = self.testClient.getUserApiClient(UserName=self.sdomain_account_user1['account'].name, + DomainName=self.sdomain_account_user1['domain'].name, type=2) self.create_vm(self.sdomain_account_user1['account'], self.sdomain_account_user1['domain'], snapshot=True) self.assertRaises(Exception, self.virtual_machine.assign_virtual_machine, userapiclient, self.sdomain_account_user2['account'].name ,self.sdomain_account_user2['domain'].id) @@ -470,8 +471,8 @@ def test_16_move_across_subdomain_volume_and_account_limit(self): account=self.sdomain_account_user2['account'].name, domainid=self.sdomain_account_user2['domain'].id, max=0) - userapiclient = self.testClient.getUserApiClient(account=self.sdomain_account_user1['account'].name, - domain=self.sdomain_account_user1['domain'].name, + userapiclient = self.testClient.getUserApiClient(UserName=self.sdomain_account_user1['account'].name, + DomainName=self.sdomain_account_user1['domain'].name, type=2) self.create_vm(self.sdomain_account_user1['account'], self.sdomain_account_user1['domain'], snapshot=True, volume=self.sdomain_account_user1['volume']) self.assertRaises(Exception, self.virtual_machine.assign_virtual_machine, userapiclient, self.sdomain_account_user2['account'].name ,self.sdomain_account_user2['domain'].id) diff --git a/test/integration/component/test_baremetal.py b/test/integration/component/test_baremetal.py index 2439d0d213..6ab91466bd 100644 --- a/test/integration/component/test_baremetal.py +++ b/test/integration/component/test_baremetal.py @@ -17,18 +17,18 @@ """ Test for baremetal """ #Import Local Modules -import marvin -from marvin.cloudstackTestCase import * -from marvin.cloudstackAPI import * -from marvin.sshClient import SshClient -from marvin.integration.lib.utils import * -from marvin.integration.lib.base import * -from marvin.integration.lib.common import * +from marvin.cloudstackTestCase import cloudstackTestCase +from marvin.cloudstackAPI import createVlanIpRange +from marvin.lib.utils import cleanup_resources +from marvin.lib.base import (NetworkOffering, + NetworkServiceProvider, + PhysicalNetwork, + Network, + Pod) +#from marvin.lib.common import * from nose.plugins.attrib import attr -import telnetlib #Import System modules -import time _multiprocess_shared_ = True class Services: @@ -89,19 +89,19 @@ def test_baremetal(self): physical_network = PhysicalNetwork.list(self.apiclient, zoneid=self.zoneid)[0]; dhcp_provider = NetworkServiceProvider.list(self.apiclient, name="BaremetalDhcpProvider", physical_network_id=physical_network.id)[0] - response = NetworkServiceProvider.update( + NetworkServiceProvider.update( self.apiclient, id=dhcp_provider.id, state='Enabled' ) pxe_provider = NetworkServiceProvider.list(self.apiclient, name="BaremetalPxeProvider", physical_network_id=physical_network.id)[0] - response = NetworkServiceProvider.update( + NetworkServiceProvider.update( self.apiclient, id=pxe_provider.id, state='Enabled' ) userdata_provider = NetworkServiceProvider.list(self.apiclient, name="BaremetalUserdataProvider", physical_network_id=physical_network.id)[0] - response = NetworkServiceProvider.update( + NetworkServiceProvider.update( self.apiclient, id=userdata_provider.id, state='Enabled' @@ -119,5 +119,5 @@ def test_baremetal(self): cmd.startip = "10.1.1.20" cmd.endip = "10.1.1.40" cmd.forVirtualNetwork="false" - response = self.apiclient.createVlanIpRange(cmd) - \ No newline at end of file + self.apiclient.createVlanIpRange(cmd) + diff --git a/test/integration/component/test_base_image_updation.py b/test/integration/component/test_base_image_updation.py index e31aacfa7e..081d855fca 100644 --- a/test/integration/component/test_base_image_updation.py +++ b/test/integration/component/test_base_image_updation.py @@ -26,11 +26,12 @@ #Import Local Modules from marvin.codes import (PASS, + FAIL, RECURRING) from nose.plugins.attrib import attr from marvin.cloudstackTestCase import cloudstackTestCase -from marvin.integration.lib.base import (ServiceOffering, +from marvin.lib.base import (ServiceOffering, Account, VirtualMachine, Volume, @@ -40,13 +41,13 @@ Template ) -from marvin.integration.lib.common import (get_domain, +from marvin.lib.common import (get_domain, get_zone, get_template, list_templates ) -from marvin.integration.lib.utils import (validateList, +from marvin.lib.utils import (validateList, cleanup_resources) import time @@ -160,14 +161,14 @@ class TestBaseImageUpdate(cloudstackTestCase): @classmethod def setUpClass(cls): - cls.api_client = super( - TestBaseImageUpdate, - cls - ).getClsTestClient().getApiClient() + cls.testClient = super(TestBaseImageUpdate, cls).getClsTestClient() + cls.api_client = cls.testClient.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) + cls.domain = get_domain(cls.api_client) + cls.zone = get_zone(cls.api_client, cls.testClient.getZoneForTests()) + cls.template = get_template( cls.api_client, cls.zone.id, @@ -237,6 +238,7 @@ def get_root_device_uuid_for_vm(cls, vm_id, root_device_id): def setUp(self): self.apiclient = self.testClient.getApiClient() + self.hypervisor = self.testClient.getHypervisorInfo() self.dbclient = self.testClient.getDbConnection() self.cleanup = [] @@ -291,7 +293,7 @@ def verify_template_listing(self, template): return - @attr(tags=["advanced", "basic"]) + @attr(tags=["advanced", "basic", "selfservice"]) def test_01_deploy_instance_with_is_volatile_offering(self): """ Test deploy an instance with service offerings with IsVolatile set. """ @@ -322,7 +324,7 @@ def test_01_deploy_instance_with_is_volatile_offering(self): ) return - @attr(tags=["advanced", "basic"]) + @attr(tags=["advanced", "basic", "selfservice"]) def test_02_reboot_instance_with_is_volatile_offering(self): """ Test rebooting instances created with isVolatile service offerings """ @@ -400,7 +402,7 @@ def test_02_reboot_instance_with_is_volatile_offering(self): return - @attr(tags=["advanced", "basic"]) + @attr(tags=["advanced", "basic", "selfservice"]) def test_03_restore_vm_with_new_template(self): """ Test restoring a vm with different template than the one it was created with """ @@ -426,7 +428,8 @@ def test_03_restore_vm_with_new_template(self): v, zoneid=self.zone.id, account=self.account.name, - domainid=self.account.domainid + domainid=self.account.domainid, + hypervisor=self.hypervisor ) self.debug( "Registered a template of format: %s with ID: %s" % ( @@ -515,7 +518,7 @@ def test_03_restore_vm_with_new_template(self): ) return - @attr(tags=["advanced", "basic"]) + @attr(tags=["advanced", "basic", "selfservice"]) def test_04_reoccuring_snapshot_rules(self): """ 1) Create a VM using the Service offering IsVolatile enabled @@ -647,9 +650,13 @@ def test_04_reoccuring_snapshot_rules(self): Here we are passing root disk id of vm before reboot which does not exist hence\ listing should fail") - with self.assertRaises(Exception): - list_snapshots_policy = SnapshotPolicy.list( - self.apiclient, - volumeid=vm_with_reset_root_disk_id - ) + try: + listSnapshotPolicies = SnapshotPolicy.list( + self.apiclient, + volumeid=vm_with_reset_root_disk_id) + except Exception as e: + self.fail("Failed to list snapshot policies: %s" % e) + + self.assertEqual(validateList(listSnapshotPolicies)[0], FAIL,\ + "Snapshot policies list should be empty") return diff --git a/test/integration/component/test_blocker_bugs.py b/test/integration/component/test_blocker_bugs.py index 04a26562d0..ba15b186c1 100644 --- a/test/integration/component/test_blocker_bugs.py +++ b/test/integration/component/test_blocker_bugs.py @@ -16,15 +16,30 @@ # under the License. """ Tests for Blocker bugs """ -import marvin from nose.plugins.attrib import attr -from marvin.integration.lib.base import * -from marvin.integration.lib.utils import * -from marvin.integration.lib.common import * +from marvin.lib.base import (Snapshot, + Template, + Domain, + Account, + ServiceOffering, + Network, + VirtualMachine, + PublicIPAddress, + StaticNATRule, + FireWallRule, + Volume) +from marvin.lib.utils import cleanup_resources, validateList +from marvin.lib.common import (get_zone, + get_domain, + get_template, + list_routers, + get_builtin_template_info) #Import Local Modules -from marvin.cloudstackTestCase import * -from marvin.cloudstackAPI import * +from marvin.cloudstackTestCase import cloudstackTestCase, unittest +from marvin.cloudstackAPI import restartNetwork +from marvin.codes import PASS +import time class Services: @@ -95,8 +110,8 @@ def __init__(self): class TestTemplate(cloudstackTestCase): def setUp(self): - self.apiclient = self.testClient.getApiClient() + self.hypervisor = self.testClient.getHypervisorInfo() self.dbclient = self.testClient.getDbConnection() self.cleanup = [] return @@ -110,12 +125,13 @@ def tearDown(self): @classmethod def setUpClass(cls): - cls.services = Services().services - cls.api_client = super(TestTemplate, cls).getClsTestClient().getApiClient() + cls.testClient = super(TestTemplate, cls).getClsTestClient() + cls.api_client = cls.testClient.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) + cls.domain = get_domain(cls.api_client) + cls.zone = get_zone(cls.api_client, cls.testClient.getZoneForTests()) cls.services['mode'] = cls.zone.networktype cls.services["virtual_machine"]["zoneid"] = cls.zone.id cls.services["template"]["zoneid"] = cls.zone.id @@ -149,7 +165,7 @@ def tearDownClass(cls): return - @attr(tags = ["advanced", "advancedns", "basic", "sg"]) + @attr(tags=["advanced", "advancedns", "basic", "sg", "provisioning"]) def test_01_create_template(self): """TS_BUG_002-Test to create and deploy VM using password enabled template """ @@ -173,7 +189,8 @@ def test_01_create_template(self): self.services["template"], zoneid=self.zone.id, account=self.account.name, - domainid=self.account.domainid + domainid=self.account.domainid, + hypervisor=self.hypervisor ) self.debug( "Registered a template of format: %s with ID: %s" % ( @@ -242,12 +259,14 @@ class TestNATRules(cloudstackTestCase): @classmethod def setUpClass(cls): - cls.api_client = super(TestNATRules, cls).getClsTestClient().getApiClient() - cls.services = Services().services + cls.testClient = super(TestNATRules, cls).getClsTestClient() + cls.api_client = cls.testClient.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) + cls.domain = get_domain(cls.api_client) + cls.zone = get_zone(cls.api_client, cls.testClient.getZoneForTests()) + cls.services['mode'] = cls.zone.networktype template = get_template( cls.api_client, @@ -308,7 +327,7 @@ def tearDownClass(cls): except Exception as e: raise Exception("Warning: Exception during cleanup : %s" % e) - @attr(tags = ["advanced"]) + @attr(tags=["advanced", "selfservice"]) def test_01_firewall_rules_port_fw(self): """"Checking firewall rules deletion after static NAT disable""" @@ -448,10 +467,12 @@ class TestRouters(cloudstackTestCase): @classmethod def setUpClass(cls): - cls.api_client = super(TestRouters, cls).getClsTestClient().getApiClient() + cls.testClient = super(TestRouters, cls).getClsTestClient() + cls.api_client = cls.testClient.getApiClient() + cls.services = Services().services # Get Zone, Domain and templates - cls.zone = get_zone(cls.api_client, cls.services) + cls.zone = get_zone(cls.api_client, cls.testClient.getZoneForTests()) cls.services['mode'] = cls.zone.networktype cls.template = get_template( cls.api_client, @@ -515,7 +536,7 @@ def tearDown(self): raise Exception("Warning: Exception during cleanup : %s" % e) return - @attr(tags = ["advanced", "advancedns"]) + @attr(tags=["advanced", "advancedns", "selfservice"]) def test_01_list_routers_admin(self): """TS_BUG_007-Check listRouters() using Admin User """ @@ -573,11 +594,13 @@ class TestRouterRestart(cloudstackTestCase): @classmethod def setUpClass(cls): - cls.api_client = super(TestRouterRestart, cls).getClsTestClient().getApiClient() + cls.testClient = super(TestRouterRestart, cls).getClsTestClient() + cls.api_client = cls.testClient.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) + cls.zone = get_zone(cls.api_client, cls.testClient.getZoneForTests()) + cls.domain = get_domain(cls.api_client) cls.services['mode'] = cls.zone.networktype template = get_template( cls.api_client, @@ -630,7 +653,7 @@ def tearDown(self): # No need return - @attr(tags = ["advanced", "advancedns", "eip"]) + @attr(tags=["advanced", "advancedns", "eip", "selfservice"]) def test_01_restart_network_cleanup(self): """TS_BUG_008-Test restart network """ @@ -706,12 +729,14 @@ class TestTemplates(cloudstackTestCase): @classmethod def setUpClass(cls): + cls.testClient = super(TestTemplates, cls).getClsTestClient() + cls.api_client = cls.testClient.getApiClient() + cls.services = Services().services - cls.api_client = super(TestTemplates, cls).getClsTestClient().getApiClient() + # Get Zone, Domain and templates + cls.zone = get_zone(cls.api_client, cls.testClient.getZoneForTests()) + cls.domain = get_domain(cls.api_client) - # Get Zone, templates etc - cls.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( @@ -720,20 +745,24 @@ def setUpClass(cls): cls.services["ostype"] ) cls.services["virtual_machine"]["zoneid"] = cls.zone.id - cls.account = Account.create( + cls._cleanup = [] + try: + cls.account = Account.create( cls.api_client, cls.services["account"], domainid=cls.domain.id ) + cls._cleanup.append(cls.account) - cls.services["account"] = cls.account.name - cls.service_offering = ServiceOffering.create( + cls.services["account"] = cls.account.name + cls.service_offering = ServiceOffering.create( cls.api_client, cls.services["service_offering"], ) + cls._cleanup.append(cls.service_offering) - # create virtual machine - cls.virtual_machine = VirtualMachine.create( + # create virtual machine + cls.virtual_machine = VirtualMachine.create( cls.api_client, cls.services["virtual_machine"], templateid=template.id, @@ -741,27 +770,20 @@ def setUpClass(cls): domainid=cls.account.domainid, serviceofferingid=cls.service_offering.id, ) - #Stop virtual machine - cls.virtual_machine.stop(cls.api_client) + #Stop virtual machine + cls.virtual_machine.stop(cls.api_client) - #Wait before server has be successfully stopped - time.sleep(30) - list_volume = Volume.list( + listvolumes = Volume.list( cls.api_client, virtualmachineid=cls.virtual_machine.id, type='ROOT', listall=True ) - try: - if isinstance(list_volume, list): - cls.volume = list_volume[0] + assert validateList(listvolumes)[0] == PASS, "volumes list is empty" + cls.volume = listvolumes[0] except Exception as e: - raise Exception("Warning: Exception during setup : %s" % e) - - cls._cleanup = [ - cls.service_offering, - cls.account, - ] + cls.tearDownClass() + raise unittest.SkipTest("Exception in setUpClass: %s" % e) @classmethod def tearDownClass(cls): @@ -793,7 +815,7 @@ def tearDown(self): return @attr(speed = "slow") - @attr(tags = ["advanced", "advancedns", "basic", "sg", "eip"]) + @attr(tags=["advanced", "advancedns", "basic", "sg", "eip", "provisioning"]) def test_01_check_template_size(self): """TS_BUG_009-Test the size of template created from root disk """ @@ -821,7 +843,7 @@ def test_01_check_template_size(self): return @attr(speed = "slow") - @attr(tags = ["advanced", "advancedns", "basic", "sg", "eip"]) + @attr(tags=["advanced", "advancedns", "basic", "sg", "eip", "provisioning"]) def test_02_check_size_snapshotTemplate(self): """TS_BUG_010-Test check size of snapshot and template """ @@ -902,7 +924,7 @@ def test_02_check_size_snapshotTemplate(self): return @attr(speed = "slow") - @attr(tags = ["advanced", "advancedns", "basic", "sg", "eip"]) + @attr(tags=["advanced", "advancedns", "basic", "sg", "eip", "provisioning"]) def test_03_reuse_template_name(self): """TS_BUG_011-Test Reusing deleted template name """ diff --git a/test/integration/component/test_cpu_domain_limits.py b/test/integration/component/test_cpu_domain_limits.py index 1247a799c8..6cca7c82c6 100644 --- a/test/integration/component/test_cpu_domain_limits.py +++ b/test/integration/component/test_cpu_domain_limits.py @@ -19,21 +19,21 @@ """ # Import Local Modules from nose.plugins.attrib import attr -from marvin.cloudstackTestCase import cloudstackTestCase, unittest -from marvin.integration.lib.base import ( +from marvin.cloudstackTestCase import cloudstackTestCase +from marvin.lib.base import ( Account, ServiceOffering, VirtualMachine, Resources, Domain ) -from marvin.integration.lib.common import (get_domain, +from marvin.lib.common import (get_domain, get_zone, get_template, findSuitableHostForMigration, get_resource_type ) -from marvin.integration.lib.utils import cleanup_resources +from marvin.lib.utils import cleanup_resources from marvin.codes import ERROR_NO_HOST_FOR_MIGRATION class Services: @@ -91,12 +91,13 @@ class TestDomainCPULimitsUpdateResources(cloudstackTestCase): @classmethod def setUpClass(cls): - cls.api_client = super(TestDomainCPULimitsUpdateResources, - cls).getClsTestClient().getApiClient() + cls.testClient = super(TestDomainCPULimitsUpdateResources, cls).getClsTestClient() + cls.api_client = cls.testClient.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) + cls.domain = get_domain(cls.api_client) + cls.zone = get_zone(cls.api_client, cls.testClient.getZoneForTests()) cls.services["mode"] = cls.zone.networktype cls.template = get_template( cls.api_client, @@ -217,7 +218,7 @@ def setupAccounts(self): ) return - @attr(tags=["advanced", "advancedns","simulator"]) + @attr(tags=["advanced", "advancedns","simulator", "selfservice"]) def test_01_multiple_core_vm_start_stop_instance(self): """Test Deploy VM with 4 core CPU & verify the usage""" @@ -237,7 +238,7 @@ def test_01_multiple_core_vm_start_stop_instance(self): self.account = admin self.domain = domain - api_client = self.testClient.createUserApiClient( + api_client = self.testClient.getUserApiClient( UserName=self.account.name, DomainName=self.account.domain) @@ -290,7 +291,7 @@ def test_01_multiple_core_vm_start_stop_instance(self): "Resource count should be same as before, after starting the instance") return - @attr(tags=["advanced", "advancedns","simulator"]) + @attr(tags=["advanced", "advancedns","simulator", "provisioning"]) def test_02_multiple_core_vm_migrate_instance(self): """Test Deploy VM with 4 core CPU & verify the usage""" @@ -310,7 +311,7 @@ def test_02_multiple_core_vm_migrate_instance(self): self.account = admin self.domain = domain - api_client = self.testClient.createUserApiClient( + api_client = self.testClient.getUserApiClient( UserName=self.account.name, DomainName=self.account.domain) @@ -351,7 +352,7 @@ def test_02_multiple_core_vm_migrate_instance(self): "Resource count should be same as before, after migrating the instance") return - @attr(tags=["advanced", "advancedns","simulator"]) + @attr(tags=["advanced", "advancedns","simulator", "selfservice"]) def test_03_multiple_core_vm_delete_instance(self): """Test Deploy VM with 4 core CPU & verify the usage""" @@ -371,7 +372,7 @@ def test_03_multiple_core_vm_delete_instance(self): self.account = admin self.domain = domain - api_client = self.testClient.createUserApiClient( + api_client = self.testClient.getUserApiClient( UserName=self.account.name, DomainName=self.account.domain) @@ -408,7 +409,7 @@ def test_03_multiple_core_vm_delete_instance(self): "Resource count for %s should be 0" % get_resource_type(resource_id=8))#CPU return - @attr(tags=["advanced", "advancedns","simulator"]) + @attr(tags=["advanced", "advancedns","simulator", "selfservice"]) def test_04_deploy_multiple_vm_with_multiple_core(self): """Test Deploy multiple VM with 4 core CPU & verify the usage""" @@ -435,7 +436,7 @@ def test_04_deploy_multiple_vm_with_multiple_core(self): self.account = admin self.domain = domain - api_client = self.testClient.createUserApiClient( + api_client = self.testClient.getUserApiClient( UserName=self.account.name, DomainName=self.account.domain) @@ -505,12 +506,13 @@ class TestMultipleChildDomains(cloudstackTestCase): @classmethod def setUpClass(cls): - cls.api_client = super(TestMultipleChildDomains, - cls).getClsTestClient().getApiClient() + cls.testClient = super(TestMultipleChildDomains, cls).getClsTestClient() + cls.api_client = cls.testClient.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) + cls.domain = get_domain(cls.api_client) + cls.zone = get_zone(cls.api_client, cls.testClient.getZoneForTests()) cls.services["mode"] = cls.zone.networktype cls.template = get_template( cls.api_client, @@ -662,7 +664,7 @@ def setupAccounts(self): } return users - @attr(tags=["advanced", "advancedns","simulator"]) + @attr(tags=["advanced", "advancedns","simulator", "selfservice"]) def test_01_multiple_child_domains(self): """Test CPU limits with multiple child domains""" @@ -689,11 +691,11 @@ def test_01_multiple_child_domains(self): self.debug("Setting up account and domain hierarchy") self.setupAccounts() - api_client_cadmin_1 = self.testClient.createUserApiClient( + api_client_cadmin_1 = self.testClient.getUserApiClient( UserName=self.cadmin_1.name, DomainName=self.cadmin_1.domain) - api_client_cadmin_2 = self.testClient.createUserApiClient( + api_client_cadmin_2 = self.testClient.getUserApiClient( UserName=self.cadmin_2.name, DomainName=self.cadmin_2.domain) diff --git a/test/integration/component/test_cpu_limits.py b/test/integration/component/test_cpu_limits.py index f043773e7b..2cf92f8c2a 100644 --- a/test/integration/component/test_cpu_limits.py +++ b/test/integration/component/test_cpu_limits.py @@ -19,21 +19,21 @@ """ # Import Local Modules from nose.plugins.attrib import attr -from marvin.cloudstackTestCase import cloudstackTestCase, unittest -from marvin.integration.lib.base import ( +from marvin.cloudstackTestCase import cloudstackTestCase +from marvin.lib.base import ( Account, ServiceOffering, VirtualMachine, Domain, Resources ) -from marvin.integration.lib.common import (get_domain, +from marvin.lib.common import (get_domain, get_zone, get_template, findSuitableHostForMigration, get_resource_type ) -from marvin.integration.lib.utils import cleanup_resources +from marvin.lib.utils import cleanup_resources from marvin.codes import ERROR_NO_HOST_FOR_MIGRATION @@ -92,12 +92,13 @@ class TestCPULimits(cloudstackTestCase): @classmethod def setUpClass(cls): - cls.api_client = super(TestCPULimits, - cls).getClsTestClient().getApiClient() + cls.testClient = super(TestCPULimits, cls).getClsTestClient() + cls.api_client = cls.testClient.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) + cls.domain = get_domain(cls.api_client) + cls.zone = get_zone(cls.api_client, cls.testClient.getZoneForTests()) cls.services["mode"] = cls.zone.networktype cls.template = get_template( @@ -176,7 +177,7 @@ def createInstance(self, service_off, networks=None, api_client=None): except Exception as e: self.fail("Failed to deploy an instance: %s" % e) - @attr(tags=["advanced", "advancedns","simulator"]) + @attr(tags=["advanced", "advancedns","simulator", "selfservice"]) def test_01_multiplecore_start_stop_instance(self): """Test Deploy VM with multiple core CPU & verify the usage""" @@ -231,7 +232,7 @@ def test_01_multiplecore_start_stop_instance(self): "Resource count should be same after stopping the instance") return - @attr(tags=["advanced", "advancedns","simulator"]) + @attr(tags=["advanced", "advancedns","simulator", "provisioning"]) def test_02_multiplecore_migrate_instance(self): """Test Deploy VM with multiple core CPU & verify the usage""" @@ -272,7 +273,7 @@ def test_02_multiplecore_migrate_instance(self): "Resource count should be same after migrating the instance") return - @attr(tags=["advanced", "advancedns","simulator"]) + @attr(tags=["advanced", "advancedns","simulator", "selfservice"]) def test_03_multiplecore_delete_instance(self): """Test Deploy VM with multiple core CPU & verify the usage""" @@ -308,7 +309,7 @@ def test_03_multiplecore_delete_instance(self): self.assertEqual(resource_count, 0 , "Resource count for %s should be 0" % get_resource_type(resource_id=8))#CPU return - @attr(tags=["advanced", "advancedns","simulator"]) + @attr(tags=["advanced", "advancedns","simulator", "provisioning"]) def test_04_deploy_multiple_vm_with_multiple_cpus(self): """Test Deploy multiple VM with 4 core CPU & verify the usage""" @@ -352,12 +353,14 @@ class TestDomainCPULimitsConfiguration(cloudstackTestCase): @classmethod def setUpClass(cls): - cls.api_client = super(TestDomainCPULimitsConfiguration, - cls).getClsTestClient().getApiClient() + cls.testClient = super(TestDomainCPULimitsConfiguration, cls).getClsTestClient() + cls.api_client = cls.testClient.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) + cls.domain = get_domain(cls.api_client) + cls.zone = get_zone(cls.api_client, cls.testClient.getZoneForTests()) + cls.services["mode"] = cls.zone.networktype cls.template = get_template( cls.api_client, @@ -462,7 +465,7 @@ def setupAccounts(self): return - @attr(tags=["advanced", "advancedns","simulator"]) + @attr(tags=["advanced", "advancedns","simulator", "selfservice"]) def test_01_stop_start_instance(self): """Test Deploy VM with 4 core CPU & verify the usage""" @@ -481,7 +484,7 @@ def test_01_stop_start_instance(self): self.account = admin self.domain = domain - api_client = self.testClient.createUserApiClient( + api_client = self.testClient.getUserApiClient( UserName=self.account.name, DomainName=self.account.domain) @@ -534,7 +537,7 @@ def test_01_stop_start_instance(self): "Resource count should be same after starting the instance") return - @attr(tags=["advanced", "advancedns","simulator"]) + @attr(tags=["advanced", "advancedns","simulator", "provisioning"]) def test_02_migrate_instance(self): """Test Deploy VM with 4 core CPU & verify the usage""" @@ -553,7 +556,7 @@ def test_02_migrate_instance(self): self.account = admin self.domain = domain - api_client = self.testClient.createUserApiClient( + api_client = self.testClient.getUserApiClient( UserName=self.account.name, DomainName=self.account.domain) @@ -594,7 +597,7 @@ def test_02_migrate_instance(self): "Resource count should be same after starting the instance") return - @attr(tags=["advanced", "advancedns","simulator"]) + @attr(tags=["advanced", "advancedns","simulator", "selfservice"]) def test_03_delete_instance(self): """Test Deploy VM with 4 core CPU & verify the usage""" @@ -613,7 +616,7 @@ def test_03_delete_instance(self): self.account = admin self.domain = domain - api_client = self.testClient.createUserApiClient( + api_client = self.testClient.getUserApiClient( UserName=self.account.name, DomainName=self.account.domain) @@ -685,7 +688,7 @@ def test_04_deploy_multiple_vm_with_multiple_cpus(self): if cpu_account_gc[0].max != 16: self.skipTest("This test case requires configuration value max.account.cpus to be 16") - api_client = self.testClient.createUserApiClient( + api_client = self.testClient.getUserApiClient( UserName=self.account.name, DomainName=self.account.domain) diff --git a/test/integration/component/test_cpu_max_limits.py b/test/integration/component/test_cpu_max_limits.py index 317df166a5..a08ff6d4b4 100644 --- a/test/integration/component/test_cpu_max_limits.py +++ b/test/integration/component/test_cpu_max_limits.py @@ -19,8 +19,8 @@ """ # Import Local Modules from nose.plugins.attrib import attr -from marvin.cloudstackTestCase import cloudstackTestCase, unittest -from marvin.integration.lib.base import ( +from marvin.cloudstackTestCase import cloudstackTestCase +from marvin.lib.base import ( Account, ServiceOffering, VirtualMachine, @@ -28,11 +28,11 @@ Domain, Project ) -from marvin.integration.lib.common import (get_domain, +from marvin.lib.common import (get_domain, get_zone, get_template ) -from marvin.integration.lib.utils import cleanup_resources +from marvin.lib.utils import cleanup_resources class Services: """Test resource limit services @@ -89,12 +89,13 @@ class TestMaxCPULimits(cloudstackTestCase): @classmethod def setUpClass(cls): - cls.api_client = super(TestMaxCPULimits, - cls).getClsTestClient().getApiClient() + cls.testClient = super(TestMaxCPULimits, cls).getClsTestClient() + cls.api_client = cls.testClient.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) + cls.domain = get_domain(cls.api_client) + cls.zone = get_zone(cls.api_client, cls.testClient.getZoneForTests()) cls.services["mode"] = cls.zone.networktype cls.template = get_template( cls.api_client, @@ -227,7 +228,7 @@ def setupAccounts(self, account_limit=2, domain_limit=2, project_limit=2): return - @attr(tags=["advanced", "advancedns","simulator"]) + @attr(tags=["advanced", "advancedns","simulator", "selfservice"]) def test_01_deploy_vm_domain_limit_reached(self): """Test Try to deploy VM with admin account where account has not used the resources but @ domain they are not available""" @@ -251,7 +252,7 @@ def test_01_deploy_vm_domain_limit_reached(self): self.debug("Setting up account and domain hierarchy") self.setupAccounts(account_limit=4, domain_limit=2) - api_client_admin = self.testClient.createUserApiClient( + api_client_admin = self.testClient.getUserApiClient( UserName=self.child_do_admin.name, DomainName=self.child_do_admin.domain) @@ -260,7 +261,7 @@ def test_01_deploy_vm_domain_limit_reached(self): service_off=self.service_offering, api_client=api_client_admin) return - @attr(tags=["advanced", "advancedns","simulator"]) + @attr(tags=["advanced", "advancedns","simulator", "selfservice"]) def test_02_deploy_vm_account_limit_reached(self): """Test Try to deploy VM with admin account where account has used the resources but @ domain they are available""" @@ -284,7 +285,7 @@ def test_02_deploy_vm_account_limit_reached(self): self.debug("Setting up account and domain hierarchy") self.setupAccounts(account_limit=6, domain_limit=8) - api_client_admin = self.testClient.createUserApiClient( + api_client_admin = self.testClient.getUserApiClient( UserName=self.child_do_admin.name, DomainName=self.child_do_admin.domain) @@ -301,7 +302,7 @@ def test_02_deploy_vm_account_limit_reached(self): service_off=self.service_offering, api_client=api_client_admin) return - @attr(tags=["advanced", "advancedns","simulator"]) + @attr(tags=["advanced", "advancedns","simulator", "selfservice"]) def test_03_deploy_vm_project_limit_reached(self): """Test TTry to deploy VM with admin account where account has not used the resources but @ project they are not available""" @@ -325,7 +326,7 @@ def test_03_deploy_vm_project_limit_reached(self): self.debug("Setting up account and domain hierarchy") self.setupAccounts(account_limit=4, domain_limit=4, project_limit=2) - api_client_admin = self.testClient.createUserApiClient( + api_client_admin = self.testClient.getUserApiClient( UserName=self.child_do_admin.name, DomainName=self.child_do_admin.domain) @@ -336,7 +337,7 @@ def test_03_deploy_vm_project_limit_reached(self): service_off=self.service_offering, api_client=api_client_admin) return - @attr(tags=["advanced", "advancedns","simulator"]) + @attr(tags=["advanced", "advancedns","simulator", "selfservice"]) def test_04_deployVm__account_limit_reached(self): """Test Try to deploy VM with admin account where account has used the resources but @ project they are available""" @@ -360,7 +361,7 @@ def test_04_deployVm__account_limit_reached(self): self.debug("Setting up account and domain hierarchy") self.setupAccounts(account_limit=6, domain_limit=6, project_limit=6) - api_client_admin = self.testClient.createUserApiClient( + api_client_admin = self.testClient.getUserApiClient( UserName=self.child_do_admin.name, DomainName=self.child_do_admin.domain) diff --git a/test/integration/component/test_cpu_project_limits.py b/test/integration/component/test_cpu_project_limits.py index ed7cd88248..b33b9f120c 100644 --- a/test/integration/component/test_cpu_project_limits.py +++ b/test/integration/component/test_cpu_project_limits.py @@ -20,20 +20,20 @@ # Import Local Modules from nose.plugins.attrib import attr from marvin.cloudstackTestCase import cloudstackTestCase, unittest -from marvin.integration.lib.base import ( +from marvin.lib.base import ( Account, ServiceOffering, VirtualMachine, Domain, Project ) -from marvin.integration.lib.common import (get_domain, +from marvin.lib.common import (get_domain, get_zone, get_template, findSuitableHostForMigration, get_resource_type ) -from marvin.integration.lib.utils import cleanup_resources +from marvin.lib.utils import cleanup_resources from marvin.codes import ERROR_NO_HOST_FOR_MIGRATION class Services: @@ -91,12 +91,13 @@ class TestProjectsCPULimits(cloudstackTestCase): @classmethod def setUpClass(cls): - cls.api_client = super(TestProjectsCPULimits, - cls).getClsTestClient().getApiClient() + cls.testClient = super(TestProjectsCPULimits, cls).getClsTestClient() + cls.api_client = cls.testClient.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) + cls.domain = get_domain(cls.api_client) + cls.zone = get_zone(cls.api_client, cls.testClient.getZoneForTests()) cls.services["mode"] = cls.zone.networktype cls.template = get_template( cls.api_client, @@ -137,7 +138,7 @@ def setUp(self): self.debug("Setting up account and domain hierarchy") self.setupProjectAccounts() - api_client = self.testClient.createUserApiClient( + api_client = self.testClient.getUserApiClient( UserName=self.admin.name, DomainName=self.admin.domain) @@ -216,7 +217,7 @@ def setupProjectAccounts(self): "Check project name from list response") return - @attr(tags=["advanced", "advancedns","simulator"]) + @attr(tags=["advanced", "advancedns","simulator", "selfservice"]) def test_01_project_counts_start_stop_instance(self): # Validate the following @@ -271,7 +272,7 @@ def test_01_project_counts_start_stop_instance(self): "Resource count should be same after starting the instance") return - @attr(tags=["advanced", "advancedns","simulator"]) + @attr(tags=["advanced", "advancedns","simulator", "provisioning"]) def test_02_project_counts_migrate_instance(self): # Validate the following @@ -313,7 +314,7 @@ def test_02_project_counts_migrate_instance(self): "Resource count should be same after migrating the instance") return - @attr(tags=["advanced", "advancedns","simulator"]) + @attr(tags=["advanced", "advancedns","simulator", "selfservice"]) def test_03_project_counts_delete_instance(self): # Validate the following diff --git a/test/integration/component/test_custom_hostname.py b/test/integration/component/test_custom_hostname.py index 1549a20657..637be86d6b 100644 --- a/test/integration/component/test_custom_hostname.py +++ b/test/integration/component/test_custom_hostname.py @@ -17,12 +17,19 @@ """ P1 tests for user provide hostname cases """ #Import Local Modules -import marvin + from nose.plugins.attrib import attr -from marvin.cloudstackTestCase import * -from marvin.integration.lib.utils import * -from marvin.integration.lib.base import * -from marvin.integration.lib.common import * +from marvin.cloudstackTestCase import cloudstackTestCase +from marvin.lib.utils import (cleanup_resources, + random_gen) +from marvin.lib.base import (ServiceOffering, + Configurations, + VirtualMachine, + Account) +from marvin.lib.common import (get_domain, + get_zone, + get_template, + is_config_suitable) class Services: @@ -94,13 +101,13 @@ class TestInstanceNameFlagTrue(cloudstackTestCase): @classmethod def setUpClass(cls): - cls.api_client = super( - TestInstanceNameFlagTrue, - cls - ).getClsTestClient().getApiClient() + cls.testClient = super(TestInstanceNameFlagTrue, cls).getClsTestClient() + cls.api_client = cls.testClient.getApiClient() + cls.services = Services().services - # Get Zone, default template - cls.zone = get_zone(cls.api_client, cls.services) + # Get Zone, Domain and templates + cls.domain = get_domain(cls.api_client) + cls.zone = get_zone(cls.api_client, cls.testClient.getZoneForTests()) cls.services["mode"] = cls.zone.networktype cls.template = get_template( cls.api_client, @@ -108,12 +115,7 @@ def setUpClass(cls): cls.services["ostype"] ) - # Create domains, account etc. - cls.domain = get_domain( - cls.api_client, - cls.services - ) - + # Create account cls.account = Account.create( cls.api_client, cls.services["account"], @@ -157,7 +159,7 @@ def tearDown(self): @attr(configuration='vm.instancename.flag') - @attr(tags=["advanced", "basic", "sg", "eip", "advancedns", "simulator"]) + @attr(tags=["advanced", "basic", "sg", "eip", "advancedns", "simulator", "selfservice"]) def test_01_user_provided_hostname(self): """ Verify user provided hostname to an instance """ @@ -261,7 +263,7 @@ def test_01_user_provided_hostname(self): return @attr(configuration='vm.instancename.flag') - @attr(tags=["advanced", "basic", "sg", "eip", "advancedns", "simulator"]) + @attr(tags=["advanced", "basic", "sg", "eip", "advancedns", "simulator", "selfservice"]) def test_02_instancename_from_default_configuration(self): """ Verify for globally set instancename """ @@ -372,7 +374,7 @@ def test_02_instancename_from_default_configuration(self): return @attr(configuration='vm.instancename.flag') - @attr(tags=["advanced", "basic", "sg", "eip", "advancedns", "simulator"]) + @attr(tags=["advanced", "basic", "sg", "eip", "advancedns", "simulator", "selfservice"]) def test_03_duplicate_name(self): """ Test the duplicate name when old VM is in non-expunged state """ @@ -432,7 +434,7 @@ def test_03_duplicate_name(self): return @attr(configuration='vm.instancename.flag') - @attr(tags=["advanced", "basic", "sg", "eip", "advancedns", "simulator"]) + @attr(tags=["advanced", "basic", "sg", "eip", "advancedns", "simulator", "selfservice"]) def test_04_edit_display_name(self): """ Test Edit the Display name Through the UI. """ @@ -525,7 +527,7 @@ def test_04_edit_display_name(self): return @attr(configuration='vm.instancename.flag') - @attr(tags=["advanced", "basic", "sg", "eip", "advancedns", "simulator"]) + @attr(tags=["advanced", "basic", "sg", "eip", "advancedns", "simulator", "selfservice"]) def test_05_unsupported_chars_in_display_name(self): """ Test Unsupported chars in the display name (eg: Spaces,Exclamation,yet to get unsupported chars from the dev) @@ -561,13 +563,13 @@ class TestInstanceNameFlagFalse(cloudstackTestCase): @classmethod def setUpClass(cls): - cls.api_client = super( - TestInstanceNameFlagFalse, - cls - ).getClsTestClient().getApiClient() + cls.testClient = super(TestInstanceNameFlagFalse, cls).getClsTestClient() + cls.api_client = cls.testClient.getApiClient() + cls.services = Services().services - # Get Zone, default template - cls.zone = get_zone(cls.api_client, cls.services) + # Get Zone, Domain and templates + cls.domain = get_domain(cls.api_client) + cls.zone = get_zone(cls.api_client, cls.testClient.getZoneForTests()) cls.template = get_template( cls.api_client, @@ -575,12 +577,7 @@ def setUpClass(cls): cls.services["ostype"] ) - # Create domains, account etc. - cls.domain = get_domain( - cls.api_client, - cls.services - ) - + # Create account cls.account = Account.create( cls.api_client, cls.services["account"], @@ -622,7 +619,7 @@ def tearDown(self): return @attr(configuration='vm.instancename.flag') - @attr(tags=["advanced", "basic", "sg", "eip", "advancedns", "simulator"]) + @attr(tags=["advanced", "basic", "sg", "eip", "advancedns", "simulator", "selfservice"]) def test_01_custom_hostname_instancename_false(self): """ Verify custom hostname for the instance when vm.instancename.flag=false diff --git a/test/integration/component/test_deploy_vm_userdata_reg.py b/test/integration/component/test_deploy_vm_userdata_reg.py index b282a86081..1c9f35c579 100755 --- a/test/integration/component/test_deploy_vm_userdata_reg.py +++ b/test/integration/component/test_deploy_vm_userdata_reg.py @@ -19,9 +19,9 @@ # this script will cover VMdeployment with Userdata tests from marvin.cloudstackTestCase import cloudstackTestCase -from marvin.integration.lib.base import * -from marvin.integration.lib.utils import * -from marvin.integration.lib.common import * +from marvin.lib.base import * +from marvin.lib.utils import * +from marvin.lib.common import * from nose.plugins.attrib import attr from marvin.sshClient import SshClient import unittest @@ -71,9 +71,10 @@ class TestDeployVmWithUserData(cloudstackTestCase): @classmethod def setUpClass(cls): - cls.apiClient = super(TestDeployVmWithUserData, cls).getClsTestClient().getApiClient() + cls.testClient = super(TestDeployVmWithUserData, cls).getClsTestClient() + cls.apiClient = cls.testClient.getApiClient() cls.services = Services().services - cls.zone = get_zone(cls.apiClient, cls.services) + cls.zone = get_zone(cls.apiClient, cls.testClient.getZoneForTests()) if cls.zone.localstorageenabled: #For devcloud since localstroage is enabled cls.services["service_offering"]["storagetype"] = "local" @@ -99,8 +100,12 @@ def setUpClass(cls): cls.user_data_2kl = ''.join(random.choice(string.ascii_uppercase + string.digits) for x in range(1900)) + def setUp(self): + self.apiClient = self.testClient.getApiClient() + self.hypervisor = self.testClient.getHypervisorInfo() - @attr(tags=["simulator", "devcloud", "basic", "advanced"]) + + @attr(tags=["simulator", "devcloud", "basic", "advanced", "provisioning"]) def test_deployvm_userdata_post(self): """Test userdata as POST, size > 2k """ @@ -174,7 +179,7 @@ def test_deployvm_userdata_post(self): host.passwd="password" cmd="cat /var/www/html/userdata/"+deployVmResponse.ipaddress+"/user-data" - if self.apiClient.hypervisor.lower() == 'vmware': + if self.hypervisor.lower() == 'vmware': try: result = get_process_status( @@ -184,7 +189,7 @@ def test_deployvm_userdata_post(self): self.apiClient.connection.passwd, router.linklocalip, cmd, - hypervisor=self.apiClient.hypervisor + hypervisor=self.hypervisor ) res = str(result) self.assertEqual(res.__contains__(self.userdata),True,"Userdata Not applied Check the failures") diff --git a/test/integration/component/test_dynamic_compute_offering.py b/test/integration/component/test_dynamic_compute_offering.py index 75cf0d658f..0a07e6cdf7 100644 --- a/test/integration/component/test_dynamic_compute_offering.py +++ b/test/integration/component/test_dynamic_compute_offering.py @@ -24,18 +24,21 @@ Feature Specifications: https://cwiki.apache.org/confluence/display/CLOUDSTACK/Dynamic+Compute+Offering+FS """ from marvin.cloudstackTestCase import cloudstackTestCase -from marvin.integration.lib.utils import (cleanup_resources, - validateList) -from marvin.integration.lib.base import (ServiceOffering, - VirtualMachine, - Account) -from marvin.integration.lib.common import (get_domain, - get_zone, - get_template, - verifyComputeOfferingCreation) - +from marvin.lib.utils import (cleanup_resources, + validateList, + random_gen) +from marvin.lib.base import (Account, + VirtualMachine, + ServiceOffering, + Resources, + AffinityGroup, + Host) +from marvin.lib.common import (get_zone, + get_domain, + get_template, + verifyComputeOfferingCreation) from nose.plugins.attrib import attr -from marvin.codes import PASS, ADMIN_ACCOUNT, USER_ACCOUNT +from marvin.codes import PASS, ADMIN_ACCOUNT, USER_ACCOUNT, FAILED from ddt import ddt, data @ddt @@ -45,21 +48,22 @@ class TestDynamicServiceOffering(cloudstackTestCase): @classmethod def setUpClass(cls): - cloudstackTestClient = super(TestDynamicServiceOffering,cls).getClsTestClient() - cls.api_client = cloudstackTestClient.getApiClient() - - # Fill services from the external config file - cls.services = cloudstackTestClient.getConfigParser().parsedDict + testClient = super(TestDynamicServiceOffering, cls).getClsTestClient() + cls.api_client = cls.apiclient = testClient.getApiClient() + cls.services = testClient.getParsedTestDataConfig() # Get Zone, Domain and templates - cls.domain = get_domain(cls.api_client, cls.services) - cls.zone = get_zone(cls.api_client, cls.services) - cls.mode = str(cls.zone.networktype).lower() + cls.domain = get_domain(cls.apiclient) + cls.zone = get_zone(cls.apiclient, testClient.getZoneForTests()) + cls.services['mode'] = cls.zone.networktype + cls.template = get_template( - cls.api_client, - cls.zone.id, - cls.services["ostype"] - ) + cls.apiclient, + cls.zone.id, + cls.services["ostype"] + ) + if cls.template == FAILED: + assert False, "get_template() failed to return template with description %s" % cls.services["ostype"] cls.services["virtual_machine"]["zoneid"] = cls.zone.id cls.services["virtual_machine"]["template"] = cls.template.id cls._cleanup = [] @@ -230,7 +234,7 @@ def test_deploy_virtual_machines_static_offering(self, value): # Create Account self.account = Account.create(self.apiclient,self.services["account"],domainid=self.domain.id, admin=isadmin) - apiclient = self.testClient.createUserApiClient( + apiclient = self.testClient.getUserApiClient( UserName=self.account.name, DomainName=self.account.domain) self.cleanup.append(self.account) @@ -292,7 +296,7 @@ def test_deploy_virtual_machines_dynamic_offering(self, value): # Create Account and its api client self.account = Account.create(self.apiclient,self.services["account"],domainid=self.domain.id, admin=isadmin) - apiclient = self.testClient.createUserApiClient( + apiclient = self.testClient.getUserApiClient( UserName=self.account.name, DomainName=self.account.domain) self.cleanup.append(self.account) @@ -359,7 +363,7 @@ def test_check_vm_stats(self, value): # Create Account and api client self.account = Account.create(self.apiclient,self.services["account"],domainid=self.domain.id, admin=isadmin) - apiclient = self.testClient.createUserApiClient( + apiclient = self.testClient.getUserApiClient( UserName=self.account.name, DomainName=self.account.domain) self.cleanup.append(self.account) @@ -407,3 +411,1004 @@ def test_check_vm_stats(self, value): not matching with provided custom memory %s" % \ (vm.memory, custommemory)) return + +@ddt +class TestScaleVmDynamicServiceOffering(cloudstackTestCase): + """Test scaling VMs with dynamic Service Offerings + """ + + @classmethod + def setUpClass(cls): + cloudstackTestClient = super(TestScaleVmDynamicServiceOffering,cls).getClsTestClient() + cls.api_client = cloudstackTestClient.getApiClient() + + # Fill services from the external config file + cls.services = cloudstackTestClient.getParsedTestDataConfig() + + # Get Zone, Domain and templates + cls.domain = get_domain(cls.api_client) + cls.zone = get_zone(cls.api_client, cloudstackTestClient.getZoneForTests()) + cls.mode = str(cls.zone.networktype).lower() + cls.template = get_template( + cls.api_client, + cls.zone.id, + cls.services["ostype"] + ) + cls.services["virtual_machine"]["zoneid"] = cls.zone.id + cls.services["virtual_machine"]["template"] = cls.template.id + cls._cleanup = [] + 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_co = [] + self.cleanup = [] + return + + def tearDown(self): + try: + # Clean up compute offerings + cleanup_resources(self.apiclient, self.cleanup) + + # Clean up compute offerings + cleanup_resources(self.apiclient, self.cleanup_co) + + self.cleanup_co[:] = [] + self.cleanup[:] = [] + except Exception as e: + raise Exception("Warning: Exception during cleanup : %s" % e) + return + + @data(ADMIN_ACCOUNT, USER_ACCOUNT) + @attr(tags=["basic","advanced"]) + def test_change_so_stopped_vm_static_to_static(self, value): + """Test scale stopped VM from static offering to static offering""" + + # Steps: + # 1. Create Account (admin/user) and its api client + # 2. Make two static service offerings + # 3. Deploy VM with one static offering + # 4. Stop the VM + # 5. Scale VM with 2nd static service offering + + # Validations: + # 1. Scaling operation should be successful + + isadmin=True + if value == USER_ACCOUNT: + isadmin=False + + try: + # Create Account + self.account = Account.create(self.apiclient,self.services["account"],domainid=self.domain.id, admin=isadmin) + self.cleanup.append(self.account) + apiclient = self.testClient.getUserApiClient( + UserName=self.account.name, + DomainName=self.account.domain) + + # Create static service offerings (Second offering should have + # one of the custom values greater than 1st one, scaling down is not allowed + self.services["service_offering"]["cpunumber"] = "2" + self.services["service_offering"]["cpuspeed"] = "256" + self.services["service_offering"]["memory"] = "128" + + serviceOffering_static_1 = ServiceOffering.create(self.apiclient, + self.services["service_offering"]) + + self.services["service_offering"]["cpunumber"] = "4" + + serviceOffering_static_2 = ServiceOffering.create(self.apiclient, + self.services["service_offering"]) + + self.cleanup_co.append(serviceOffering_static_1) + self.cleanup_co.append(serviceOffering_static_2) + + # Deploy VM + virtualMachine = VirtualMachine.create(apiclient,self.services["virtual_machine"], + serviceofferingid=serviceOffering_static_1.id, + accountid=self.account.name,domainid=self.account.domainid) + + # Stop VM + virtualMachine.stop(apiclient) + + # Scale VM to new static service offering + virtualMachine.scale(apiclient, serviceOfferingId=serviceOffering_static_2.id) + except Exception as e: + self.fail("Exception occured: %s" % e) + return + + @data(ADMIN_ACCOUNT, USER_ACCOUNT) + @attr(tags=["basic","advanced"]) + def test_change_so_stopped_vm_static_to_dynamic(self, value): + """Test scale stopped VM from static offering to dynamic offering""" + + # Steps: + # 1. Create Account (admin/user) and its api client + # 2. Make static and dynamic service offerings + # 3. Deploy VM with static offering + # 4. Stop the VM + # 5. Scale VM with dynamic service offering providing all required + # custom values + # 6. Deploy another VM with static offring and stop the VM + # 7. Scale VM with dynamic service offering providing only custom cpu number + + # Validations: + # 1. Scale operation in step 5 should be successful + # 2. Scale operation in step 7 should fail + + isadmin=True + if value == USER_ACCOUNT: + isadmin=False + + try: + # Create Account and api client + self.account = Account.create(self.apiclient,self.services["account"],domainid=self.domain.id, admin=isadmin) + apiclient = self.testClient.getUserApiClient( + UserName=self.account.name, + DomainName=self.account.domain) + self.cleanup.append(self.account) + + # Create static and dynamic service offerings + self.services["service_offering"]["cpunumber"] = "2" + self.services["service_offering"]["cpuspeed"] = "256" + self.services["service_offering"]["memory"] = "128" + + serviceOffering_static = ServiceOffering.create(self.apiclient, + self.services["service_offering"]) + + + self.services["service_offering"]["cpunumber"] = "" + self.services["service_offering"]["cpuspeed"] = "" + self.services["service_offering"]["memory"] = "" + + serviceOffering_dynamic = ServiceOffering.create(self.apiclient, + self.services["service_offering"]) + + self.cleanup_co.append(serviceOffering_static) + self.cleanup_co.append(serviceOffering_dynamic) + + # Deploy VM with static service offering + virtualMachine_1 = VirtualMachine.create(apiclient,self.services["virtual_machine"], + serviceofferingid=serviceOffering_static.id, + accountid=self.account.name,domainid=self.account.domainid) + + # Stop VM + virtualMachine_1.stop(apiclient) + + # Scale VM to dynamic service offering proving all custom values + virtualMachine_1.scale(apiclient, serviceOfferingId=serviceOffering_dynamic.id, + customcpunumber=4, customcpuspeed=256, custommemory=128) + + # Deploy VM with static service offering + virtualMachine_2 = VirtualMachine.create(apiclient,self.services["virtual_machine"], + serviceofferingid=serviceOffering_static.id, + accountid=self.account.name,domainid=self.account.domainid) + + # Stop VM + virtualMachine_2.stop(apiclient) + except Exception as e: + self.fail("Exception occuered: %s" % e) + + # Scale VM to dynamic service offering proving only custom cpu number + with self.assertRaises(Exception): + virtualMachine_2.scale(apiclient, serviceOfferingId=serviceOffering_dynamic.id, + customcpunumber=4) + return + + @data(ADMIN_ACCOUNT, USER_ACCOUNT) + @attr(tags=["basic","advanced"]) + def test_change_so_stopped_vm_dynamic_to_static(self, value): + """Test scale stopped VM from dynamic offering to static offering""" + + # Steps: + # 1. Create Account (admin/user) and its api client + # 2. Make static and dynamic service offerings + # 3. Deploy VM with dynamic service offering + # 4. Stop the VM + # 5. Scale VM with static service offering + + # Validations: + # 1. Scale operation in step 5 should be successful + + isadmin=True + if value == USER_ACCOUNT: + isadmin=False + + try: + # Create account and api client + self.account = Account.create(self.apiclient,self.services["account"],domainid=self.domain.id, admin=isadmin) + apiclient = self.testClient.getUserApiClient( + UserName=self.account.name, + DomainName=self.account.domain) + self.cleanup.append(self.account) + + # Create dynamic and static service offering + self.services["service_offering"]["cpunumber"] = "" + self.services["service_offering"]["cpuspeed"] = "" + self.services["service_offering"]["memory"] = "" + + serviceOffering_dynamic = ServiceOffering.create(self.apiclient, + self.services["service_offering"]) + + self.services["service_offering"]["cpunumber"] = "4" + self.services["service_offering"]["cpuspeed"] = "256" + self.services["service_offering"]["memory"] = "128" + + serviceOffering_static = ServiceOffering.create(self.apiclient, + self.services["service_offering"]) + + self.cleanup_co.append(serviceOffering_static) + self.cleanup_co.append(serviceOffering_dynamic) + + # Deploy VM with dynamic service offering + virtualMachine = VirtualMachine.create(apiclient,self.services["virtual_machine"], + serviceofferingid=serviceOffering_dynamic.id, + accountid=self.account.name,domainid=self.account.domainid, + customcpunumber=2, customcpuspeed=256, custommemory=128) + + # Stop VM and verify that it is in stopped state + virtualMachine.stop(apiclient) + + # Scale VM to static service offering + virtualMachine.scale(apiclient, serviceOfferingId=serviceOffering_static.id) + except Exception as e: + self.fail("Exception occured: %s" % e) + return + + @data(ADMIN_ACCOUNT, USER_ACCOUNT) + @attr(tags=["basic","advanced"]) + def test_change_so_stopped_vm_dynamic_to_dynamic(self, value): + """Test scale stopped VM from dynamic offering to dynamic offering""" + + # Steps: + # 1. Create Account (admin/user) and its api client + # 2. Make 2 dynamic service offerings + # 3. Deploy VM with dynamic service offering + # 4. Stop the VM + # 5. Scale VM with same dynamic service offering + # 6. Scale VM with other dynamic service offering + # 7. Scale VM with same/other dynamic offering but providing custom + # value for only cpu number + + # Validations: + # 1. Scale operation in step 5 should be successful + # 2. Scale operation in step 6 should be successful + # 3. Scale operation in step 7 should fail + + isadmin=True + if value == USER_ACCOUNT: + isadmin=False + + try: + # Create Account + self.account = Account.create(self.apiclient,self.services["account"],domainid=self.domain.id, admin=isadmin) + apiclient = self.testClient.getUserApiClient( + UserName=self.account.name, + DomainName=self.account.domain) + self.cleanup.append(self.account) + + # Create dynamic service offerings + self.services["service_offering"]["cpunumber"] = "" + self.services["service_offering"]["cpuspeed"] = "" + self.services["service_offering"]["memory"] = "" + + serviceOffering_dynamic_1 = ServiceOffering.create(self.apiclient, + self.services["service_offering"]) + + serviceOffering_dynamic_2 = ServiceOffering.create(self.apiclient, + self.services["service_offering"]) + + self.cleanup_co.append(serviceOffering_dynamic_1) + self.cleanup_co.append(serviceOffering_dynamic_2) + + # Deploy VM with dynamic service offering + virtualMachine = VirtualMachine.create(apiclient,self.services["virtual_machine"], + serviceofferingid=serviceOffering_dynamic_1.id, + accountid=self.account.name,domainid=self.account.domainid, + customcpunumber=2, customcpuspeed=256, custommemory=128) + + # Stop VM + virtualMachine.stop(apiclient) + + # Scale VM with same dynamic service offering + virtualMachine.scale(apiclient, serviceOfferingId=serviceOffering_dynamic_1.id, + customcpunumber=4, customcpuspeed=512, custommemory=256) + + # Scale VM with other dynamic service offering + virtualMachine.scale(apiclient, serviceOfferingId=serviceOffering_dynamic_2.id, + customcpunumber=4, customcpuspeed=512, custommemory=256) + except Exception as e: + self.fail("Exception occured: %s" % e) + + # Scale VM with dynamic service offering proving custom value + # only for cpu number + with self.assertRaises(Exception): + virtualMachine.scale(apiclient, serviceOfferingId=serviceOffering_dynamic_1.id, + customcpunumber=4) + return + + @data(ADMIN_ACCOUNT, USER_ACCOUNT) + @attr(tags=["basic","advanced"]) + def test_change_so_running_vm_static_to_static(self, value): + """Test scale running VM from static offering to static offering""" + + # Steps: + # 1. Create Account (admin/user) and its api client + # 2. Make two static service offerings + # 3. Deploy VM with one static offering + # 4. Scale VM with 2nd static service offering + + # Validations: + # 1. Scaling operation should be successful + + isadmin=True + if value == USER_ACCOUNT: + isadmin=False + + # Create Account and api client + self.account = Account.create(self.apiclient,self.services["account"],domainid=self.domain.id, admin=isadmin) + apiclient = self.testClient.getUserApiClient( + UserName=self.account.name, + DomainName=self.account.domain) + self.cleanup.append(self.account) + + # Create static service offerings + self.services["service_offering"]["cpunumber"] = "2" + self.services["service_offering"]["cpuspeed"] = "256" + self.services["service_offering"]["memory"] = "128" + + serviceOffering_static_1 = ServiceOffering.create(self.apiclient, + self.services["service_offering"]) + + self.services["service_offering"]["cpunumber"] = "4" + + serviceOffering_static_2 = ServiceOffering.create(self.apiclient, + self.services["service_offering"]) + + self.cleanup_co.append(serviceOffering_static_1) + self.cleanup_co.append(serviceOffering_static_2) + + # Deploy VM with static service offering + try: + virtualMachine = VirtualMachine.create(apiclient,self.services["virtual_machine"], + serviceofferingid=serviceOffering_static_1.id, + accountid=self.account.name,domainid=self.account.domainid) + except Exception as e: + self.fail("vm creation failed: %s" % e) + + # Scale VM to other static service offering + try: + virtualMachine.scale(apiclient, serviceOfferingId=serviceOffering_static_2.id) + except Exception as e: + self.fail("Failure while changing service offering: %s" % e) + return + + @data(ADMIN_ACCOUNT, USER_ACCOUNT) + @attr(tags=["basic","advanced"]) + def test_change_so_running_vm_static_to_dynamic(self, value): + """Test scale running VM from static offering to dynamic offering""" + + # Steps: + # 1. Create Account (admin/user) and its api client + # 2. Make static and dynamic service offerings + # 3. Deploy VM with static offering + # 4. Scale VM with dynamic service offering providing all required + # custom values + # 5. Deploy another VM with static offring + # 6. Scale VM with dynamic service offering providing only custom cpu number + + # Validations: + # 1. Scale operation in step 4 should be successful + # 2. Scale operation in step 6 should fail + + isadmin=True + if value == USER_ACCOUNT: + isadmin=False + + # Crate account and api client + self.account = Account.create(self.apiclient,self.services["account"],domainid=self.domain.id, admin=isadmin) + apiclient = self.testClient.getUserApiClient( + UserName=self.account.name, + DomainName=self.account.domain) + self.cleanup.append(self.account) + + # Create static and dynamic service offerings + self.services["service_offering"]["cpunumber"] = "2" + self.services["service_offering"]["cpuspeed"] = "256" + self.services["service_offering"]["memory"] = "128" + + serviceOffering_static = ServiceOffering.create(self.apiclient, + self.services["service_offering"]) + + + self.services["service_offering"]["cpunumber"] = "" + self.services["service_offering"]["cpuspeed"] = "" + self.services["service_offering"]["memory"] = "" + + serviceOffering_dynamic = ServiceOffering.create(self.apiclient, + self.services["service_offering"]) + + self.cleanup_co.append(serviceOffering_static) + self.cleanup_co.append(serviceOffering_dynamic) + + # Deploy VM with static service offering + try: + virtualMachine_1 = VirtualMachine.create(apiclient,self.services["virtual_machine"], + serviceofferingid=serviceOffering_static.id, + accountid=self.account.name,domainid=self.account.domainid) + except Exception as e: + self.fail("vm creation failed: %s" % e) + + # Scale VM to dynamic service offering + try: + virtualMachine_1.scale(apiclient, serviceOfferingId=serviceOffering_dynamic.id, + customcpunumber=4, customcpuspeed=256, custommemory=128) + except Exception as e: + self.fail("Failure while changing service offering: %s" % e) + + try: + virtualMachine_2 = VirtualMachine.create(apiclient,self.services["virtual_machine"], + serviceofferingid=serviceOffering_static.id, + accountid=self.account.name,domainid=self.account.domainid) + except Exception as e: + self.fail("vm creation failed: %s" % e) + + try: + virtualMachine_2.scale(apiclient, serviceOfferingId=serviceOffering_dynamic.id, + customcpunumber=4) + self.fail("Changing service offering with incomplete data should have failed, it succeded") + except Exception as e: + self.debug("Failure while changing service offering as expected: %s" % e) + + return + + @data(ADMIN_ACCOUNT, USER_ACCOUNT) + @attr(tags=["basic","advanced"]) + def test_change_so_running_vm_dynamic_to_static(self, value): + """Test scale running VM from dynamic offering to static offering""" + + # Steps: + # 1. Create Account (admin/user) and its api client + # 2. Make static and dynamic service offerings + # 3. Deploy VM with dynamic service offering + # 4. Scale VM with static service offering + + # Validations: + # 1. Scale operation in step 4 should be successful + + isadmin=True + if value == USER_ACCOUNT: + isadmin=False + + # Create account and api client + self.account = Account.create(self.apiclient,self.services["account"],domainid=self.domain.id, admin=isadmin) + apiclient = self.testClient.getUserApiClient( + UserName=self.account.name, + DomainName=self.account.domain) + self.cleanup.append(self.account) + + # Create dynamic and static service offerings + self.services["service_offering"]["cpunumber"] = "" + self.services["service_offering"]["cpuspeed"] = "" + self.services["service_offering"]["memory"] = "" + + serviceOffering_dynamic = ServiceOffering.create(self.apiclient, + self.services["service_offering"]) + + self.services["service_offering"]["cpunumber"] = "4" + self.services["service_offering"]["cpuspeed"] = "256" + self.services["service_offering"]["memory"] = "128" + + serviceOffering_static = ServiceOffering.create(self.apiclient, + self.services["service_offering"]) + + self.cleanup_co.append(serviceOffering_static) + self.cleanup_co.append(serviceOffering_dynamic) + + # deploy VM with dynamic service offering + try: + virtualMachine = VirtualMachine.create(apiclient,self.services["virtual_machine"], + serviceofferingid=serviceOffering_dynamic.id, + accountid=self.account.name,domainid=self.account.domainid, + customcpunumber=2, customcpuspeed=256, custommemory=128) + except Exception as e: + self.fail("vm creation failed: %s" % e) + + # Scale VM to static service offering + try: + virtualMachine.scale(apiclient, serviceOfferingId=serviceOffering_static.id) + except Exception as e: + self.fail("Failure while changing service offering: %s" % e) + + return + + @data(ADMIN_ACCOUNT, USER_ACCOUNT) + @attr(tags=["basic","advanced"]) + def test_change_so_running_vm_dynamic_to_dynamic(self, value): + """Test scale running VM from dynamic offering to dynamic offering""" + + # Steps: + # 1. Create Account (admin/user) and its api client + # 2. Make 2 dynamic service offerings + # 3. Deploy VM with dynamic service offering + # 4. Scale VM with same dynamic service offering + # 5. Scale VM with other dynamic service offering + # 6. Scale VM with same/other dynamic offering but providing custom + # value for only cpu number + + # Validations: + # 1. Scale operation in step 4 should be successful + # 2. Scale operation in step 5 should be successful + # 3. Scale operation in step 6 should fail + + isadmin=True + if value == USER_ACCOUNT: + isadmin=False + + # Create account and api client + self.account = Account.create(self.apiclient,self.services["account"],domainid=self.domain.id, admin=isadmin) + apiclient = self.testClient.getUserApiClient( + UserName=self.account.name, + DomainName=self.account.domain) + self.cleanup.append(self.account) + + # Create dynamic service offerings + self.services["service_offering"]["cpunumber"] = "" + self.services["service_offering"]["cpuspeed"] = "" + self.services["service_offering"]["memory"] = "" + + serviceOffering_dynamic_1 = ServiceOffering.create(self.apiclient, + self.services["service_offering"]) + + serviceOffering_dynamic_2 = ServiceOffering.create(self.apiclient, + self.services["service_offering"]) + + self.cleanup_co.append(serviceOffering_dynamic_1) + self.cleanup_co.append(serviceOffering_dynamic_2) + + # Deploy VM with dynamic service offering + try: + virtualMachine = VirtualMachine.create(apiclient,self.services["virtual_machine"], + serviceofferingid=serviceOffering_dynamic_1.id, + accountid=self.account.name,domainid=self.account.domainid, + customcpunumber=2, customcpuspeed=256, custommemory=128) + except Exception as e: + self.fail("vm creation failed: %s" % e) + + # Scale VM with same dynamic offering + try: + virtualMachine.scale(apiclient, serviceOfferingId=serviceOffering_dynamic_1.id, + customcpunumber=4, customcpuspeed=512, custommemory=256) + except Exception as e: + self.fail("Failure while changing service offering: %s" % e) + + # Scale VM with other dynamic service offering + try: + virtualMachine.scale(apiclient, serviceOfferingId=serviceOffering_dynamic_2.id, + customcpunumber=4, customcpuspeed=512, custommemory=512) + except Exception as e: + self.fail("Failure while changing service offering: %s" % e) + + # Scale VM with dynamic offering proving custom value only for cpu number + try: + virtualMachine.scale(apiclient, serviceOfferingId=serviceOffering_dynamic_1.id, + customcpunumber=4) + self.fail("Changing service offering should have failed, it succeded") + except Exception as e: + self.debug("Failure while changing service offering: %s" % e) + + return + +@ddt +class TestAccountLimits(cloudstackTestCase): + """Test max limit of account (cpunumber and memory) with dynamic compute offering + """ + + @classmethod + def setUpClass(cls): + cloudstackTestClient = super(TestAccountLimits,cls).getClsTestClient() + cls.api_client = cloudstackTestClient.getApiClient() + + # Fill services from the external config file + cls.services = cloudstackTestClient.getParsedTestDataConfig() + + # Get Zone, Domain and templates + cls.domain = get_domain(cls.api_client) + cls.zone = get_zone(cls.api_client, cloudstackTestClient.getZoneForTests()) + cls.mode = str(cls.zone.networktype).lower() + cls.template = get_template( + cls.api_client, + cls.zone.id, + cls.services["ostype"] + ) + cls.services["virtual_machine"]["zoneid"] = cls.zone.id + cls.services["virtual_machine"]["template"] = cls.template.id + cls._cleanup = [] + 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_co = [] + self.cleanup = [] + return + + def tearDown(self): + try: + # Clean up compute offerings + cleanup_resources(self.apiclient, self.cleanup) + + # Clean up compute offerings + cleanup_resources(self.apiclient, self.cleanup_co) + + self.cleanup_co[:] = [] + self.cleanup[:] = [] + except Exception as e: + raise Exception("Warning: Exception during cleanup : %s" % e) + return + + @data(ADMIN_ACCOUNT, USER_ACCOUNT) + @attr(tags=["basic","advanced"]) + def test_max_account_cpus_deploy_VM(self, value): + """Test cpu limits of account while deploying VM with dynamic compute offering""" + + # Steps: + # 1. Create Account (admin/user) + # 2. Update max cpu limit of account to 2 + # 3. Create dynamic service offering + # 4. Deploy VM with dynamic service offering and cpu number 3 + + # Validations: + # 1. VM creation should fail + + isadmin=True + if value == USER_ACCOUNT: + isadmin=False + + # Create account and api client + self.account = Account.create(self.apiclient,self.services["account"],domainid=self.domain.id, admin=isadmin) + self.cleanup.append(self.account) + + Resources.updateLimit(self.apiclient, + resourcetype=8, + max=2, + account=self.account.name, + domainid=self.account.domainid) + + # Create dynamic service offerings + self.services["service_offering"]["cpunumber"] = "" + self.services["service_offering"]["cpuspeed"] = "" + self.services["service_offering"]["memory"] = "" + + serviceOffering_dynamic = ServiceOffering.create(self.apiclient, + self.services["service_offering"]) + + self.cleanup_co.append(serviceOffering_dynamic) + + # Deploy VM with dynamic service offering + try: + VirtualMachine.create(self.apiclient,self.services["virtual_machine"], + serviceofferingid=serviceOffering_dynamic.id, + accountid=self.account.name,domainid=self.account.domainid, + customcpunumber=3, customcpuspeed=256, custommemory=128) + self.fail("vm creation should have failed, it succeeded") + except Exception as e: + self.debug("vm creation failed as expected with error: %s" % e) + + return + + @data(ADMIN_ACCOUNT, USER_ACCOUNT) + @attr(tags=["basic","advanced"]) + def test_max_account_cpus_scale_VM(self, value): + """Test cpu limits of account while scaling VM with dynamic compute offering""" + + # Steps: + # 1. Create Account (admin/user) + # 2. Update max cpu limit of account to 2 + # 3. Create dynamic service offering + # 4. Deploy VM with dynamic service offering and cpu number 2 + # 5. Try to Scale VM with dynamic service offering and cpu number 3 + + # Validations: + # 1. VM creation should succeed + # 2. VM scaling operation should fail + + isadmin=True + if value == USER_ACCOUNT: + isadmin=False + + # Create account and api client + self.account = Account.create(self.apiclient,self.services["account"],domainid=self.domain.id, admin=isadmin) + self.cleanup.append(self.account) + + Resources.updateLimit(self.apiclient, + resourcetype=8, + max=2, + account=self.account.name, + domainid=self.account.domainid) + + # Create dynamic service offerings + self.services["service_offering"]["cpunumber"] = "" + self.services["service_offering"]["cpuspeed"] = "" + self.services["service_offering"]["memory"] = "" + + serviceOffering_dynamic = ServiceOffering.create(self.apiclient, + self.services["service_offering"]) + + self.cleanup_co.append(serviceOffering_dynamic) + + # Deploy VM with dynamic service offering + try: + virtualMachine = VirtualMachine.create(self.apiclient,self.services["virtual_machine"], + serviceofferingid=serviceOffering_dynamic.id, + accountid=self.account.name,domainid=self.account.domainid, + customcpunumber=2, customcpuspeed=256, custommemory=128) + except Exception as e: + self.fail("vm creation failed: %s" % e) + + # Scale VM with same dynamic offering + try: + virtualMachine.scale(self.apiclient, serviceOfferingId=serviceOffering_dynamic.id, + customcpunumber=4, customcpuspeed=512, custommemory=256) + self.fail("Scaling virtual machine with cpu number more than \ + allowed limit (of account) succeded, should have failed") + except Exception as e: + self.debug("Failure while changing service offering as expected: %s" % e) + + return + + @data(ADMIN_ACCOUNT, USER_ACCOUNT) + @attr(tags=["basic","advanced"]) + def test_max_account_memory_deploy_VM(self, value): + """Test memory limits of account while deploying VM with dynamic compute offering""" + + # Steps: + # 1. Create Account (admin/user) + # 2. Update max memory limit of account to 256 + # 3. Create dynamic service offering + # 4. Deploy VM with dynamic service offering and memory 512 + + # Validations: + # 1. VM creation should fail + + isadmin=True + if value == USER_ACCOUNT: + isadmin=False + + # Create account and api client + self.account = Account.create(self.apiclient,self.services["account"],domainid=self.domain.id, admin=isadmin) + self.cleanup.append(self.account) + + Resources.updateLimit(self.apiclient, + resourcetype=9, + max=256, + account=self.account.name, + domainid=self.account.domainid) + + # Create dynamic service offerings + self.services["service_offering"]["cpunumber"] = "" + self.services["service_offering"]["cpuspeed"] = "" + self.services["service_offering"]["memory"] = "" + + serviceOffering_dynamic = ServiceOffering.create(self.apiclient, + self.services["service_offering"]) + + self.cleanup_co.append(serviceOffering_dynamic) + + # Deploy VM with dynamic service offering + try: + VirtualMachine.create(self.apiclient,self.services["virtual_machine"], + serviceofferingid=serviceOffering_dynamic.id, + accountid=self.account.name,domainid=self.account.domainid, + customcpunumber=3, customcpuspeed=256, custommemory=512) + self.fail("vm creation should have failed, it succeeded") + except Exception as e: + self.debug("vm creation failed as expected with error: %s" % e) + + return + + @data(ADMIN_ACCOUNT, USER_ACCOUNT) + @attr(tags=["basic","advanced"]) + def test_max_account_memory_scale_VM(self, value): + """Test memory limits of account while scaling VM with dynamic compute offering""" + + # Steps: + # 1. Create Account (admin/user) + # 2. Update max memory limit of account to 256 + # 3. Create dynamic service offering + # 4. Deploy VM with dynamic service offering and memory 256 + # 5. Try to Scale VM with dynamic service offering and memory 512 + + # Validations: + # 1. VM creation should succeed + # 2. VM scaling operation should fail + + isadmin=True + if value == USER_ACCOUNT: + isadmin=False + + # Create account and api client + self.account = Account.create(self.apiclient,self.services["account"],domainid=self.domain.id, admin=isadmin) + self.cleanup.append(self.account) + + Resources.updateLimit(self.apiclient, + resourcetype=9, + max=256, + account=self.account.name, + domainid=self.account.domainid) + + # Create dynamic service offerings + self.services["service_offering"]["cpunumber"] = "" + self.services["service_offering"]["cpuspeed"] = "" + self.services["service_offering"]["memory"] = "" + + serviceOffering_dynamic = ServiceOffering.create(self.apiclient, + self.services["service_offering"]) + + self.cleanup_co.append(serviceOffering_dynamic) + + # Deploy VM with dynamic service offering + try: + virtualMachine = VirtualMachine.create(self.apiclient,self.services["virtual_machine"], + serviceofferingid=serviceOffering_dynamic.id, + accountid=self.account.name,domainid=self.account.domainid, + customcpunumber=2, customcpuspeed=256, custommemory=256) + except Exception as e: + self.fail("vm creation failed: %s" % e) + + # Scale VM with same dynamic offering + try: + virtualMachine.scale(self.apiclient, serviceOfferingId=serviceOffering_dynamic.id, + customcpunumber=4, customcpuspeed=512, custommemory=512) + self.fail("Scaling virtual machine with cpu number more than \ + allowed limit (of account) succeded, should have failed") + except Exception as e: + self.debug("Failure while changing service offering as expected: %s" % e) + + return + +@ddt +class TestAffinityGroup(cloudstackTestCase): + """Test affinity group working with VMs created with dynamic offering + """ + + @classmethod + def setUpClass(cls): + cloudstackTestClient = super(TestAffinityGroup,cls).getClsTestClient() + cls.api_client = cloudstackTestClient.getApiClient() + + # Fill services from the external config file + cls.services = cloudstackTestClient.getParsedTestDataConfig() + + # Get Zone, Domain and templates + cls.domain = get_domain(cls.api_client) + cls.zone = get_zone(cls.api_client, cloudstackTestClient.getZoneForTests()) + cls.mode = str(cls.zone.networktype).lower() + cls.template = get_template( + cls.api_client, + cls.zone.id, + cls.services["ostype"] + ) + cls.services["virtual_machine"]["zoneid"] = cls.zone.id + cls.services["virtual_machine"]["template"] = cls.template.id + cls._cleanup = [] + 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_co = [] + self.cleanup = [] + return + + def tearDown(self): + try: + # Clean up compute offerings + cleanup_resources(self.apiclient, self.cleanup) + + # Clean up compute offerings + cleanup_resources(self.apiclient, self.cleanup_co) + + self.cleanup_co[:] = [] + self.cleanup[:] = [] + except Exception as e: + raise Exception("Warning: Exception during cleanup : %s" % e) + return + + @data(ADMIN_ACCOUNT, USER_ACCOUNT) + @attr(tags=["basic","advanced"]) + def test_deploy_VM_with_affinity_group(self, value): + """Test deploy VMs with affinity group and dynamic compute offering""" + + # Steps: + # 1. Create Account (admin/user) + # 2. Update max cpu limit of account to 2 + # 3. Create dynamic service offering + # 4. Deploy VM with dynamic service offering and cpu number 3 + + # Validations: + # 1. VM creation should fail + + isadmin=True + if value == USER_ACCOUNT: + isadmin=False + + # Create account and api client + self.account = Account.create(self.apiclient,self.services["account"],domainid=self.domain.id, admin=isadmin) + self.cleanup.append(self.account) + + # Create dynamic service offerings + self.services["service_offering"]["cpunumber"] = "" + self.services["service_offering"]["cpuspeed"] = "" + self.services["service_offering"]["memory"] = "" + + serviceOffering_dynamic = ServiceOffering.create(self.apiclient, + self.services["service_offering"]) + + self.cleanup_co.append(serviceOffering_dynamic) + + self.services["host_anti_affinity"]["name"] = "aff_grp_" + random_gen(size=6) + affinityGroup = AffinityGroup.create(self.apiclient, self.services["host_anti_affinity"], + self.account.name, self.domain.id) + + # Deploy VM with dynamic service offering + try: + virtualMachine = VirtualMachine.create(self.apiclient,self.services["virtual_machine"], + serviceofferingid=serviceOffering_dynamic.id, + accountid=self.account.name,domainid=self.account.domainid, + customcpunumber=2, customcpuspeed=256, custommemory=128, + affinitygroupnames=[affinityGroup.name]) + except Exception as e: + self.fail("vm creation failed with error: %s" % e) + + otherHostsInCluster = Host.list(self.apiclient, virtualmachineid=virtualMachine.id) + if validateList(otherHostsInCluster)[0] == PASS: + try: + VirtualMachine.create(self.apiclient,self.services["virtual_machine"], + serviceofferingid=serviceOffering_dynamic.id, + accountid=self.account.name,domainid=self.account.domainid, + customcpunumber=2, customcpuspeed=256, custommemory=128, + affinitygroupnames=[affinityGroup.name]) + except Exception as e: + self.fail("vm creation failed with error: %s" % e) + + else: + try: + VirtualMachine.create(self.apiclient,self.services["virtual_machine"], + serviceofferingid=serviceOffering_dynamic.id, + accountid=self.account.name,domainid=self.account.domainid, + customcpunumber=2, customcpuspeed=256, custommemory=128, + affinitygroupnames=[affinityGroup.name]) + self.fail("vm creation should have failed, it succeded") + except Exception as e: + self.debug("vm creation failed as expected with error: %s" % e) + + return diff --git a/test/integration/component/test_egress_fw_rules.py b/test/integration/component/test_egress_fw_rules.py index 8fa8a5ed26..a42caa9bb8 100644 --- a/test/integration/component/test_egress_fw_rules.py +++ b/test/integration/component/test_egress_fw_rules.py @@ -21,7 +21,7 @@ import unittest from nose.plugins.attrib import attr from marvin.cloudstackTestCase import cloudstackTestCase -from marvin.integration.lib.base import (Account, +from marvin.lib.base import (Account, Domain, Router, Network, @@ -31,14 +31,14 @@ FireWallRule, NATRule, PublicIPAddress) -from marvin.integration.lib.common import (get_domain, +from marvin.lib.common import (get_domain, get_zone, get_template, list_routers, wait_for_cleanup, list_virtual_machines ) -from marvin.integration.lib.utils import cleanup_resources, validateList +from marvin.lib.utils import cleanup_resources, validateList from marvin.cloudstackAPI import rebootRouter from marvin.cloudstackAPI.createEgressFirewallRule import createEgressFirewallRuleCmd from marvin.cloudstackAPI.deleteEgressFirewallRule import deleteEgressFirewallRuleCmd @@ -132,12 +132,13 @@ class TestEgressFWRules(cloudstackTestCase): @classmethod def setUpClass(cls): cls._cleanup = [] - cls.api_client = super(TestEgressFWRules, - cls).getClsTestClient().getApiClient() - cls.services = Services().services - # Get Zone Domain and create Domains and sub Domains. - cls.domain = get_domain(cls.api_client, cls.services) - cls.zone = get_zone(cls.api_client, cls.services) + cls.testClient = super(TestEgressFWRules, cls).getClsTestClient() + cls.api_client = cls.testClient.getApiClient() + + cls.services = Services().services + # Get Zone, Domain and templates + cls.domain = get_domain(cls.api_client) + cls.zone = get_zone(cls.api_client, cls.testClient.getZoneForTests()) cls.services['mode'] = cls.zone.networktype # Get and set template id for VM creation. cls.template = get_template(cls.api_client, @@ -274,17 +275,19 @@ def exec_script_on_user_vm(self, script, exec_cmd_params, expected_result, negat self.debug("script: %s" % script+exec_cmd_params) self.debug("result: %s" % result) - if str(result).strip() == expected_result: + str_result = str(str(result).strip()) + str_expected_result = str(expected_result).strip() + if str_result == str_expected_result: exec_success = True if negative_test: self.assertEqual(exec_success, True, - "Script result is %s matching with %s" % (result, expected_result)) + "Script result is %s matching with %s" % (str_result, str_expected_result)) else: self.assertEqual(exec_success, True, - "Script result is %s is not matching with %s" % (result, expected_result)) + "Script result is %s is not matching with %s" % (str_result, str_expected_result)) except Exception as e: self.debug('Error=%s' % e) @@ -382,7 +385,7 @@ def tearDown(self): except Exception as e: self.fail("Warning! Cleanup failed: %s" % e) - @attr(tags = ["advanced"]) + @attr(tags=["advanced", "provisioning"]) def test_01_egress_fr1(self): """Test By-default the communication from guest n/w to public n/w is allowed. """ @@ -397,7 +400,7 @@ def test_01_egress_fr1(self): "['0']", negative_test=False) - @attr(tags = ["advanced"]) + @attr(tags=["advanced", "provisioning"]) def test_01_1_egress_fr1(self): """Test By-default the communication from guest n/w to public n/w is NOT allowed. """ @@ -413,7 +416,7 @@ def test_01_1_egress_fr1(self): negative_test=False) - @attr(tags = ["advanced"]) + @attr(tags=["advanced", "provisioning"]) def test_02_egress_fr2(self): """Test Allow Communication using Egress rule with CIDR + Port Range + Protocol. """ @@ -430,7 +433,7 @@ def test_02_egress_fr2(self): "['100']", negative_test=False) - @attr(tags = ["advanced"]) + @attr(tags=["advanced", "provisioning"]) def test_02_1_egress_fr2(self): """Test Allow Communication using Egress rule with CIDR + Port Range + Protocol. """ @@ -447,7 +450,7 @@ def test_02_1_egress_fr2(self): "['0']", negative_test=False) - @attr(tags = ["advanced"]) + @attr(tags=["advanced", "provisioning"]) def test_03_egress_fr3(self): """Test Communication blocked with network that is other than specified """ @@ -468,7 +471,7 @@ def test_03_egress_fr3(self): "[]", negative_test=False) - @attr(tags = ["advanced"]) + @attr(tags=["advanced", "provisioning"]) def test_03_1_egress_fr3(self): """Test Communication blocked with network that is other than specified """ @@ -489,7 +492,7 @@ def test_03_1_egress_fr3(self): "['failed:']", negative_test=False) - @attr(tags = ["advanced"]) + @attr(tags=["advanced", "selfservice"]) def test_04_egress_fr4(self): """Test Create Egress rule and check the Firewall_Rules DB table """ @@ -526,7 +529,7 @@ def test_04_egress_fr4(self): "DB results not matching, expected: 1, found: %s" % qresultset[0][0]) - @attr(tags = ["advanced"]) + @attr(tags=["advanced", "selfservice"]) def test_04_1_egress_fr4(self): """Test Create Egress rule and check the Firewall_Rules DB table """ @@ -563,7 +566,7 @@ def test_04_1_egress_fr4(self): "DB results not matching, expected: 0, found: %s" % qresultset[0][0]) @unittest.skip("Skip") - @attr(tags = ["advanced"]) + @attr(tags=["advanced", "NotRun"]) def test_05_egress_fr5(self): """Test Create Egress rule and check the IP tables """ @@ -582,7 +585,7 @@ def test_05_egress_fr5(self): @unittest.skip("Skip") - @attr(tags = ["advanced"]) + @attr(tags=["advanced", "NotRun"]) def test_05_1_egress_fr5(self): """Test Create Egress rule and check the IP tables """ @@ -600,7 +603,7 @@ def test_05_1_egress_fr5(self): #TODO: Query VR for expected route rules. - @attr(tags = ["advanced"]) + @attr(tags=["advanced", "provisioning"]) def test_06_egress_fr6(self): """Test Create Egress rule without CIDR """ @@ -616,7 +619,7 @@ def test_06_egress_fr6(self): "['100']", negative_test=False) - @attr(tags = ["advanced"]) + @attr(tags=["advanced", "provisioning"]) def test_06_1_egress_fr6(self): """Test Create Egress rule without CIDR """ @@ -632,7 +635,7 @@ def test_06_1_egress_fr6(self): "['0']", negative_test=False) - @attr(tags = ["advanced"]) + @attr(tags=["advanced", "provisioning"]) def test_07_egress_fr7(self): """Test Create Egress rule without End Port """ @@ -648,7 +651,7 @@ def test_07_egress_fr7(self): "['failed:']", negative_test=False) - @attr(tags = ["advanced"]) + @attr(tags=["advanced", "provisioning"]) def test_07_1_egress_fr7(self): """Test Create Egress rule without End Port """ @@ -665,7 +668,7 @@ def test_07_1_egress_fr7(self): negative_test=False) @unittest.skip("Skip") - @attr(tags = ["advanced"]) + @attr(tags=["advanced", "NotRun"]) def test_08_egress_fr8(self): """Test Port Forwarding and Egress Conflict """ @@ -677,7 +680,7 @@ def test_08_egress_fr8(self): self.createEgressRule() @unittest.skip("Skip") - @attr(tags = ["advanced"]) + @attr(tags=["advanced", "NotRun"]) def test_08_1_egress_fr8(self): """Test Port Forwarding and Egress Conflict """ @@ -689,7 +692,7 @@ def test_08_1_egress_fr8(self): self.createEgressRule() - @attr(tags = ["advanced"]) + @attr(tags=["advanced", "provisioning"]) def test_09_egress_fr9(self): """Test Delete Egress rule """ @@ -713,7 +716,7 @@ def test_09_egress_fr9(self): "['0']", negative_test=False) - @attr(tags = ["advanced"]) + @attr(tags=["advanced", "provisioning"]) def test_09_1_egress_fr9(self): """Test Delete Egress rule """ @@ -738,7 +741,7 @@ def test_09_1_egress_fr9(self): negative_test=False) - @attr(tags = ["advanced"]) + @attr(tags=["advanced", "selfservice"]) def test_10_egress_fr10(self): """Test Invalid CIDR and Invalid Port ranges """ @@ -749,7 +752,7 @@ def test_10_egress_fr10(self): self.create_vm() self.assertRaises(Exception, self.createEgressRule, '10.2.2.0/24') - @attr(tags = ["advanced"]) + @attr(tags=["advanced", "selfservice"]) def test_10_1_egress_fr10(self): """Test Invalid CIDR and Invalid Port ranges """ @@ -761,7 +764,7 @@ def test_10_1_egress_fr10(self): self.assertRaises(Exception, self.createEgressRule, '10.2.2.0/24') - @attr(tags = ["advanced"]) + @attr(tags=["advanced", "selfservice"]) def test_11_egress_fr11(self): """Test Regression on Firewall + PF + LB + SNAT """ @@ -771,7 +774,7 @@ def test_11_egress_fr11(self): # 3. All should work fine. self.create_vm(pfrule=True) - @attr(tags = ["advanced"]) + @attr(tags=["advanced", "selfservice"]) def test_11_1_egress_fr11(self): """Test Regression on Firewall + PF + LB + SNAT """ @@ -781,7 +784,7 @@ def test_11_1_egress_fr11(self): # 3. All should work fine. self.create_vm(pfrule=True, egress_policy=False) - @attr(tags = ["advanced"]) + @attr(tags=["advanced", "provisioning"]) def test_12_egress_fr12(self): """Test Reboot Router """ @@ -798,7 +801,7 @@ def test_12_egress_fr12(self): "['100']", negative_test=False) - @attr(tags = ["advanced"]) + @attr(tags=["advanced", "provisioning"]) def test_12_1_egress_fr12(self): """Test Reboot Router """ @@ -815,7 +818,7 @@ def test_12_1_egress_fr12(self): "['0']", negative_test=False) - @attr(tags = ["advanced"]) + @attr(tags=["advanced", "provisioning"]) def test_13_egress_fr13(self): """Test Redundant Router : Master failover """ @@ -870,7 +873,7 @@ def test_13_egress_fr13(self): "['100']", negative_test=False) - @attr(tags = ["advanced"]) + @attr(tags=["advanced", "provisioning"]) def test_13_1_egress_fr13(self): """Test Redundant Router : Master failover """ diff --git a/test/integration/component/test_egress_rules.py b/test/integration/component/test_egress_rules.py index a2443d4940..0f05c07a22 100644 --- a/test/integration/component/test_egress_rules.py +++ b/test/integration/component/test_egress_rules.py @@ -5,9 +5,9 @@ # 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 @@ -20,13 +20,13 @@ #Import Local Modules from nose.plugins.attrib import attr from marvin.cloudstackTestCase import cloudstackTestCase -from marvin.integration.lib.utils import (random_gen, +from marvin.lib.utils import (random_gen, cleanup_resources) -from marvin.integration.lib.base import (SecurityGroup, +from marvin.lib.base import (SecurityGroup, VirtualMachine, Account, ServiceOffering) -from marvin.integration.lib.common import (get_domain, +from marvin.lib.common import (get_domain, get_zone, get_template, list_virtual_machines) @@ -149,15 +149,13 @@ def tearDown(self): @classmethod def setUpClass(cls): - cls.services = Services().services - cls.api_client = super( - TestDefaultSecurityGroupEgress, - cls - ).getClsTestClient().getApiClient() + cls.testClient = super(TestDefaultSecurityGroupEgress, cls).getClsTestClient() + cls.api_client = cls.testClient.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) + cls.domain = get_domain(cls.api_client) + cls.zone = get_zone(cls.api_client, cls.testClient.getZoneForTests()) cls.services['mode'] = cls.zone.networktype template = get_template( @@ -307,15 +305,13 @@ def tearDown(self): @classmethod def setUpClass(cls): - cls.services = Services().services - cls.api_client = super( - TestAuthorizeIngressRule, - cls - ).getClsTestClient().getApiClient() + cls.testClient = super(TestAuthorizeIngressRule, cls).getClsTestClient() + cls.api_client = cls.testClient.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) + cls.domain = get_domain(cls.api_client) + cls.zone = get_zone(cls.api_client, cls.testClient.getZoneForTests()) cls.services['mode'] = cls.zone.networktype template = get_template( @@ -465,15 +461,13 @@ def tearDown(self): @classmethod def setUpClass(cls): - cls.services = Services().services - cls.api_client = super( - TestDefaultGroupEgress, - cls - ).getClsTestClient().getApiClient() + cls.testClient = super(TestDefaultGroupEgress, cls).getClsTestClient() + cls.api_client = cls.testClient.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) + cls.domain = get_domain(cls.api_client) + cls.zone = get_zone(cls.api_client, cls.testClient.getZoneForTests()) cls.services['mode'] = cls.zone.networktype template = get_template( @@ -663,15 +657,13 @@ def tearDown(self): @classmethod def setUpClass(cls): - cls.services = Services().services - cls.api_client = super( - TestDefaultGroupEgressAfterDeploy, - cls - ).getClsTestClient().getApiClient() + cls.testClient = super(TestDefaultGroupEgressAfterDeploy, cls).getClsTestClient() + cls.api_client = cls.testClient.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) + cls.domain = get_domain(cls.api_client) + cls.zone = get_zone(cls.api_client, cls.testClient.getZoneForTests()) cls.services['mode'] = cls.zone.networktype template = get_template( @@ -842,15 +834,13 @@ def tearDown(self): @classmethod def setUpClass(cls): - cls.services = Services().services - cls.api_client = super( - TestRevokeEgressRule, - cls - ).getClsTestClient().getApiClient() + cls.testClient = super(TestRevokeEgressRule, cls).getClsTestClient() + cls.api_client = cls.testClient.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) + cls.domain = get_domain(cls.api_client) + cls.zone = get_zone(cls.api_client, cls.testClient.getZoneForTests()) cls.services['mode'] = cls.zone.networktype template = get_template( @@ -1125,15 +1115,13 @@ def tearDown(self): @classmethod def setUpClass(cls): - cls.services = Services().services - cls.api_client = super( - TestInvalidAccountAuthroize, - cls - ).getClsTestClient().getApiClient() + cls.testClient = super(TestInvalidAccountAuthroize, cls).getClsTestClient() + cls.api_client = cls.testClient.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) + cls.domain = get_domain(cls.api_client) + cls.zone = get_zone(cls.api_client, cls.testClient.getZoneForTests()) cls.services['mode'] = cls.zone.networktype template = get_template( @@ -1246,15 +1234,13 @@ def tearDown(self): @classmethod def setUpClass(cls): - cls.services = Services().services - cls.api_client = super( - TestMultipleAccountsEgressRuleNeg, - cls - ).getClsTestClient().getApiClient() + cls.testClient = super(TestMultipleAccountsEgressRuleNeg, cls).getClsTestClient() + cls.api_client = cls.testClient.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) + cls.domain = get_domain(cls.api_client) + cls.zone = get_zone(cls.api_client, cls.testClient.getZoneForTests()) cls.services['mode'] = cls.zone.networktype template = get_template( @@ -1495,15 +1481,13 @@ def tearDown(self): @classmethod def setUpClass(cls): - cls.services = Services().services - cls.api_client = super( - TestMultipleAccountsEgressRule, - cls - ).getClsTestClient().getApiClient() + cls.testClient = super(TestMultipleAccountsEgressRule, cls).getClsTestClient() + cls.api_client = cls.testClient.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) + cls.domain = get_domain(cls.api_client) + cls.zone = get_zone(cls.api_client, cls.testClient.getZoneForTests()) cls.services['mode'] = cls.zone.networktype template = get_template( @@ -1786,15 +1770,13 @@ def tearDown(self): @classmethod def setUpClass(cls): - cls.services = Services().services - cls.api_client = super( - TestStartStopVMWithEgressRule, - cls - ).getClsTestClient().getApiClient() + cls.testClient = super(TestStartStopVMWithEgressRule, cls).getClsTestClient() + cls.api_client = cls.testClient.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) + cls.domain = get_domain(cls.api_client) + cls.zone = get_zone(cls.api_client, cls.testClient.getZoneForTests()) cls.services['mode'] = cls.zone.networktype template = get_template( @@ -1919,27 +1901,11 @@ def test_start_stop_vm_egress(self): "Check egress rule created properly" ) - # Stop virtual machine - self.debug("Stopping virtual machine: %s" % self.virtual_machine.id) - self.virtual_machine.stop(self.apiclient) - - vms = VirtualMachine.list( - self.apiclient, - id=self.virtual_machine.id, - listall=True - ) - self.assertEqual( - isinstance(vms, list), - True, - "List VM should return a valid list" - ) - vm = vms[0] - self.assertEqual( - vm.state, - "Stopped", - "VM state should be stopped" - ) - self.debug("VM: %s state: %s" % (vm.id, vm.state)) + try: + # Stop virtual machine + self.virtual_machine.stop(self.apiclient) + except Exception as e: + self.fail("Failed to stop instance: %s" % e) # Start virtual machine self.debug("Starting virtual machine: %s" % self.virtual_machine.id) @@ -1993,15 +1959,13 @@ def tearDown(self): @classmethod def setUpClass(cls): - cls.services = Services().services - cls.api_client = super( - TestInvalidParametersForEgress, - cls - ).getClsTestClient().getApiClient() + cls.testClient = super(TestInvalidParametersForEgress, cls).getClsTestClient() + cls.api_client = cls.testClient.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) + cls.domain = get_domain(cls.api_client) + cls.zone = get_zone(cls.api_client, cls.testClient.getZoneForTests()) cls.services['mode'] = cls.zone.networktype template = get_template( diff --git a/test/integration/component/test_eip_elb.py b/test/integration/component/test_eip_elb.py index d639d82d9f..0613c4d053 100644 --- a/test/integration/component/test_eip_elb.py +++ b/test/integration/component/test_eip_elb.py @@ -22,9 +22,9 @@ 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.lib.utils import * +from marvin.lib.base import * +from marvin.lib.common import * from marvin.sshClient import SshClient import datetime @@ -91,11 +91,13 @@ class TestEIP(cloudstackTestCase): @classmethod def setUpClass(cls): - cls.api_client = super(TestEIP, cls).getClsTestClient().getApiClient() + cls.testClient = super(TestEIP, cls).getClsTestClient() + cls.api_client = cls.testClient.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) + cls.domain = get_domain(cls.api_client) + cls.zone = get_zone(cls.api_client, cls.testClient.getZoneForTests()) cls.services['mode'] = cls.zone.networktype cls.template = get_template( cls.api_client, @@ -909,11 +911,13 @@ class TestELB(cloudstackTestCase): @classmethod def setUpClass(cls): - cls.api_client = super(TestELB, cls).getClsTestClient().getApiClient() + cls.testClient = super(TestELB, cls).getClsTestClient() + cls.api_client = cls.testClient.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) + cls.domain = get_domain(cls.api_client) + cls.zone = get_zone(cls.api_client, cls.testClient.getZoneForTests()) cls.services['mode'] = cls.zone.networktype cls.template = get_template( cls.api_client, diff --git a/test/integration/component/test_escalations.py b/test/integration/component/test_escalations.py new file mode 100644 index 0000000000..1b596a72b6 --- /dev/null +++ b/test/integration/component/test_escalations.py @@ -0,0 +1,8202 @@ +# 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 +from marvin.cloudstackTestCase import cloudstackTestCase +from marvin.cloudstackAPI import (createVolume, + createTemplate) +from marvin.lib.base import (Volume, + Iso, + VirtualMachine, + Template, + Snapshot, + SecurityGroup, + Account, + Zone, + Network, + NetworkOffering, + DiskOffering, + ServiceOffering, + VmSnapshot, + SnapshotPolicy, + SSHKeyPair, + Resources, + Configurations, + VpnCustomerGateway, + Hypervisor) +from marvin.lib.common import (get_zone, + get_domain, + get_template, + list_os_types) +from marvin.lib.utils import (validateList, + cleanup_resources, + random_gen) +from marvin.codes import (PASS, EMPTY_LIST) +from nose.plugins.attrib import attr +import time + +class TestVolumes(cloudstackTestCase): + + @classmethod + def setUpClass(cls): + + cls.testClient = super(TestVolumes, cls).getClsTestClient() + cls.api_client = cls.testClient.getApiClient() + cls.services = cls.testClient.getParsedTestDataConfig() + # Get Domain, Zone, Template + cls.domain = get_domain(cls.api_client) + cls.zone = get_zone(cls.api_client) + cls.template = get_template( + cls.api_client, + cls.zone.id, + cls.services["ostype"] + ) + if cls.zone.localstorageenabled: + cls.storagetype = 'local' + cls.services["service_offerings"]["tiny"]["storagetype"] = 'local' + cls.services["disk_offering"]["storagetype"] = 'local' + else: + cls.storagetype = 'shared' + cls.services["service_offerings"]["tiny"]["storagetype"] = 'shared' + cls.services["disk_offering"]["storagetype"] = 'shared' + + cls.services['mode'] = cls.zone.networktype + cls.services["virtual_machine"]["hypervisor"] = 'XenServer' + cls.services["virtual_machine"]["zoneid"] = cls.zone.id + cls.services["virtual_machine"]["template"] = cls.template.id + cls.services["custom_volume"]["zoneid"] = cls.zone.id + + # Creating Disk offering, Service Offering and Account + cls.disk_offering = DiskOffering.create( + cls.api_client, + cls.services["disk_offering"] + ) + cls.service_offering = ServiceOffering.create( + cls.api_client, + cls.services["service_offerings"]["tiny"] + ) + cls.account = Account.create( + cls.api_client, + cls.services["account"], + domainid=cls.domain.id + ) + + # Getting authentication for user in newly created Account + cls.user = cls.account.user[0] + + cls.userapiclient = cls.testClient.getUserApiClient(cls.user.username, cls.domain.name) + + # Creating Virtual Machine + cls.virtual_machine = VirtualMachine.create( + cls.userapiclient, + cls.services["virtual_machine"], + accountid=cls.account.name, + domainid=cls.account.domainid, + serviceofferingid=cls.service_offering.id, + ) + cls._cleanup = [ + cls.virtual_machine, + cls.disk_offering, + cls.service_offering, + cls.account + ] + + def setUp(self): + + self.apiClient = self.testClient.getApiClient() + self.cleanup = [] + + def tearDown(self): + #Clean up, terminate the created volumes + cleanup_resources(self.apiClient, self.cleanup) + return + + @classmethod + def tearDownClass(cls): + try: + cls.apiclient = super(TestVolumes, cls).getClsTestClient().getApiClient() + cleanup_resources(cls.apiclient, cls._cleanup) + except Exception as e: + raise Exception("Warning: Exception during cleanup : %s" % e) + + + def __verify_values(self, expected_vals, actual_vals): + """ + @summary: Function to verify expected and actual values + Step1: Initializing return flag to True + Step1: Verifying length of expected and actual dictionaries is matching. + If not matching returning false + Step2: Listing all the keys from expected dictionary + Step3: Looping through each key from step2 and verifying expected and actual dictionaries have same value + If not making return flag to False + Step4: returning the return flag after all the values are verified + """ + return_flag = True + + if len(expected_vals) != len(actual_vals): + return False + + keys = expected_vals.keys() + for i in range(0, len(expected_vals)): + exp_val = expected_vals[keys[i]] + act_val = actual_vals[keys[i]] + if exp_val == act_val: + return_flag = return_flag and True + else: + return_flag = return_flag and False + self.debug("expected Value: %s, is not matching with actual value: %s" % ( + exp_val, + act_val + )) + return return_flag + + @attr(tags=["advanced", "basic", "provisioning"]) + def test_01_list_volumes_pagination(self): + """ + @summary: Test List Volumes pagination + + Step1: Listing all the volumes for a user + Step2: Verifying listed volumes for account created at class level + Step3: If number of volumes is less than (page size + 1), then creating them + Step4: Listing all the volumes again after creation of volumes + Step5: Verifying the length of the volumes is (page size + 1) + Step6: Listing all the volumes in page1 + Step7: Verifying that the length of the volumes in page 1 is (page size) + Step8: Listing all the volumes in page2 + Step9: Verifying that the length of the volumes in page 2 is 1 + Step10: Deleting the volume present in page 2 + Step11: Listing for the volumes on page 2 + Step12: Verifying that there are no volumes present in page 2 + """ + # Listing all the volumes for a user + list_volumes_before = Volume.list(self.userapiclient, listall=self.services["listall"]) + + # Verifying listed volumes for account created at class level + self.assertIsNotNone( + list_volumes_before, + "create volume from VM failed at class setup method" + ) + self.assertEqual( + len(list_volumes_before), + 1, + "more than 1 volume created from VM at class level" + ) + + # If number of volumes is less than (pagesize + 1), then creating them + for i in range(0, (self.services["pagesize"])): + volume_created = Volume.create( + self.userapiclient, + self.services["volume"], + zoneid=self.zone.id, + diskofferingid=self.disk_offering.id + ) + self.assertIsNotNone( + volume_created, + "Volume is not created" + ) + if(i < (self.services["pagesize"] - 1)): + self.cleanup.append(volume_created) + + self.assertEqual( + self.services["volume"]["diskname"], + volume_created.name, + "Newly created volume name and the test data volume name are not matching" + ) + + # Listing all the volumes again after creation of volumes + list_volumes_after = Volume.list(self.userapiclient, listall=self.services["listall"]) + + # Verifying the length of the volumes is (page size + 1) + self.assertEqual( + len(list_volumes_after), + (self.services["pagesize"] + 1), + "Number of volumes created is not matching expected" + ) + + # Listing all the volumes in page1 + list_volumes_page1 = Volume.list( + self.userapiclient, + listall=self.services["listall"], + page=1, + pagesize=self.services["pagesize"] + ) + self.assertIsNotNone( + list_volumes_page1, + "No volumes found in Page 1" + ) + # Verifying that the length of the volumes in page 1 is (page size) + self.assertEqual( + len(list_volumes_page1), + self.services["pagesize"], + "List Volume response is not matching with the page size length for page 1" + ) + + # Listing all the volumes in page2 + list_volumes_page2 = Volume.list( + self.userapiclient, + listall=self.services["listall"], + page=2, + pagesize=self.services["pagesize"] + ) + self.assertIsNotNone( + list_volumes_page2, + "No volumes found in Page 2" + ) + # Verifying that the length of the volumes in page 2 is 1 + self.assertEqual( + len(list_volumes_page2), + 1, + "List Volume response is not matching with the page size length for page 2" + ) + volume_page2 = list_volumes_page2[0] + + # Verifying that the volume on page 2 is not present in page1 + for i in range(0, len(list_volumes_page1)): + volume_page1 = list_volumes_page1[i] + self.assertNotEquals( + volume_page2.id, + volume_page1.id, + "Volume listed in page 2 is also listed in page 1" + ) + + # Deleting a single volume + Volume.delete(volume_created, self.userapiclient) + + # Listing the volumes in page 2 + list_volume_response = Volume.list( + self.userapiclient, + listall=self.services["listall"], + page=2, + pagesize=self.services["pagesize"] + ) + # verifying that volume does not exists on page 2 + self.assertEqual( + list_volume_response, + None, + "Volume was not deleted" + ) + return + + @attr(tags=["advanced", "basic", "provisioning"]) + def test_02_list_volume_byid(self): + """ + @summary: Test List Volumes with Id + + Step1: Listing all the volumes for a user before creating a data volume + Step2: Verifying the length of the list as 1 + Step3: Creating a data volume + Step4: Listing all the volumes for a user after creating a data volume + Step5: Verifying the list volume size is increased by 1 + Step6: List the volumes by specifying root volume Id + Step7: Verifying the details of the root volume + Step8: List the volumes by specifying data volume Id + Step9: Verifying the details of the data volume + """ + # Listing all the volumes for a user before creating a data volume + list_volumes_before = Volume.list( + self.userapiclient, + listall=self.services["listall"] + ) + self.assertIsNotNone( + list_volumes_before, + "create volume from VM failed at class setup method") + # Verifying the length of the list as 1 + self.assertEqual( + len(list_volumes_before), + 1, + "more than 1 volume created at class level" + ) + root_volume = list_volumes_before[0] + + # Creating a data volume + volume_created = Volume.create( + self.userapiclient, + self.services["volume"], + zoneid=self.zone.id, + diskofferingid=self.disk_offering.id + ) + self.assertIsNotNone( + volume_created, + "Volume is not created" + ) + self.cleanup.append(volume_created) + + self.assertEqual( + self.services["volume"]["diskname"], + volume_created.name, + "Newly created volume name and the test data volume name are not matching" + ) + # Listing all the volumes for a user after creating a data volume + list_volumes_after = Volume.list( + self.userapiclient, + listall=self.services["listall"] + ) + self.assertIsNotNone( + list_volumes_after, + "Volume creation failed" + ) + # Verifying the list volume size is increased by 1 + self.assertEqual( + len(list_volumes_before) + 1, + len(list_volumes_after), + "list volume is not matching with Number of volumes created" + ) + + # Listing a Root Volume by Id and verifying the volume details + list_volumes_by_id = Volume.list( + self.userapiclient, + listall=self.services["listall"], + id=root_volume.id + ) + self.assertIsNotNone( + list_volumes_by_id, + "Root volume is not listed" + ) + self.assertEqual( + 1, + len(list_volumes_by_id), + "list volume is not matching with Number of volumes created" + ) + obtained_volume = list_volumes_by_id[0] + + #Creating expected and actual values dictionaries + expected_dict = { + "id":root_volume.id, + "name":root_volume.name, + "vmname":self.virtual_machine.name, + "state":"Ready", + "type":"ROOT", + "zoneid":self.zone.id, + "account":self.account.name, + "storagetype":self.storagetype, + "size":self.template.size + } + actual_dict = { + "id":obtained_volume.id, + "name":obtained_volume.name, + "vmname":obtained_volume.vmname, + "state":obtained_volume.state, + "type":obtained_volume.type, + "zoneid":obtained_volume.zoneid, + "account":obtained_volume.account, + "storagetype":obtained_volume.storagetype, + "size":obtained_volume.size, + } + root_volume_status = self.__verify_values( + expected_dict, + actual_dict + ) + self.assertEqual( + True, + root_volume_status, + "Listed Root Volume details are not as expected" + ) + # Listing a Data Volume by Id and verifying the volume details + list_volumes_by_id = Volume.list( + self.userapiclient, + listall=self.services["listall"], + id=volume_created.id + ) + self.assertIsNotNone( + list_volumes_by_id, + "Data volume is not listed" + ) + self.assertEqual( + len(list_volumes_by_id), + 1, + "list volume is not matching with Number of volumes created" + ) + obtained_volume = list_volumes_by_id[0] + + #Creating expected and actual values dictionaries + expected_dict = { + "id":volume_created.id, + "name":volume_created.name, + "state":"Allocated", + "type":"DATADISK", + "zoneid":self.zone.id, + "account":self.account.name, + "storagetype":self.storagetype, + "size":self.disk_offering.disksize + } + actual_dict = { + "id":obtained_volume.id, + "name":obtained_volume.name, + "state":obtained_volume.state, + "type":obtained_volume.type, + "zoneid":obtained_volume.zoneid, + "account":obtained_volume.account, + "storagetype":obtained_volume.storagetype, + "size":obtained_volume.size/(1024*1024*1024), + } + root_volume_status = self.__verify_values( + expected_dict, + actual_dict + ) + self.assertEqual( + True, + root_volume_status, + "Listed Data Volume details are not as expected" + ) + return + + @attr(tags=["advanced", "basic", "provisioning"]) + def test_03_data_volume_resize(self): + """ + @summary: Test to verify creation and resize of data volume + + Step1: Listing the volumes for a user before creating data volume + Step2: Creating a data volume + Step3: Listing the volumes for a user after creating data volume + Step4: Attaching and Detaching data volume created to Virtual Machine + Step5: Verifying if there exists a disk offering with higher size + If not present creating it + Step6: Resizing data volume + """ + # Listing volumes for a user before creating a volume + list_volumes_before = Volume.list(self.userapiclient, listall=self.services["listall"]) + + # Creating a data volume + volume_created = Volume.create( + self.userapiclient, + self.services["volume"], + zoneid=self.zone.id, + diskofferingid=self.disk_offering.id + ) + self.assertIsNotNone(volume_created, "Data volume creation failed") + + self.cleanup.append(volume_created) + + # Listing volumes for a user after creating data volume + list_volumes_after = Volume.list(self.userapiclient, listall=self.services["listall"]) + self.assertEquals( + len(list_volumes_before) + 1, + len(list_volumes_after), + "Data volume creation failed" + ) + + # Attaching data volume created to Virtual Machine + self.virtual_machine.attach_volume( + self.userapiclient, + volume_created + ) + + list_volumes = Volume.list( + self.userapiclient, + listall=self.services["listall"], + id=volume_created.id + ) + attached_volume = list_volumes[0] + + self.assertIsNotNone( + attached_volume.vmname, + "VM is not attached to Volume" + ) + self.assertEquals( + self.virtual_machine.name, + attached_volume.vmname, + "VM Name is not matching with attached vm" + ) + + # Detaching data volume from Virtual Machine + self.virtual_machine.detach_volume( + self.userapiclient, + volume_created + ) + list_volumes = Volume.list( + self.userapiclient, + listall=self.services["listall"], + id=volume_created.id + ) + detached_volume = list_volumes[0] + self.assertIsNone( + detached_volume.vmname, + "VM is not detached from volume" + ) + + # Verifying if there exists a disk offering with higher size. If not present creating it + list_disk_offerings = DiskOffering.list(self.apiClient) + + large_disk_offering_exists = False + # Converting disk_size in bytes to GB + current_disk_size = volume_created.size/(1024*1024*1024) + + for disk_offering in list_disk_offerings: + if ((disk_offering.disksize > current_disk_size) and (not disk_offering.iscustomized) and disk_offering.storagetype == self.storagetype): + new_disk_offering = disk_offering + large_disk_offering_exists = True + break + + if large_disk_offering_exists == False: + new_size = (volume_created.size/(1024*1024*1024)) + 1 + self.services["disk_offering"]["disksize"] = new_size + new_disk_offering = DiskOffering.create( + self.apiClient, + self.services["disk_offering"] + ) + if new_disk_offering is not None: + self.cleanup.append(new_disk_offering) + else: + new_size = new_disk_offering.disksize + + # Resizing data volume + resized_volume = volume_created.resize( + self.userapiclient, + diskofferingid=new_disk_offering.id, + shrinkok='false', + ) + self.assertIsNotNone(resized_volume, "Resize Volume failed") + # Verifying data volume size is increased + self.assertEquals( + new_size, + (resized_volume.size/(1024*1024*1024)), + "volume not resized to expected value" + ) + return + + @attr(tags=["advanced", "basic", "provisioning"]) + def test_04_custom_volume_resize(self): + """ + @summary: Test to verify creation and resize of custom volume + + Step1: Checking if Custom disk offering already exists. + If not present then creating custom Disk Offering + Step2: Listing the volumes for a user before creating custom volume + Step3: Creating a custom volume + Step4: Listing the volumes for a user after creating custom volume + Step5: Attaching and Detaching custom volume created to Virtual Machine + Step6: Resizing custom volume + """ + # Listing all the disk offerings + list_disk_offerings = DiskOffering.list(self.apiClient) + + custom_disk_offering_exists = False + + # Verifying if a custom disk offering already exists + if list_disk_offerings is not None: + for disk_offering in list_disk_offerings: + if (disk_offering.iscustomized and disk_offering.storagetype == self.storagetype): + custom_disk_offering = disk_offering + custom_disk_offering_exists = True + break + + # If a custom disk offering does not exists, then creating a custom disk offering + if custom_disk_offering_exists == False: + custom_disk_offering = DiskOffering.create( + self.apiClient, + self.services["disk_offering"], + custom=True + ) + if custom_disk_offering is not None: + self.cleanup.append(custom_disk_offering) + + # Listing the volumes for a user before creating custom volume + list_volumes_before = Volume.list(self.userapiclient, listall=self.services["listall"]) + + # Creating a custom volume + volume_created = Volume.create_custom_disk( + self.userapiclient, + self.services["custom_volume"], + account=self.account.name, + domainid=self.account.domainid, + diskofferingid=custom_disk_offering.id + ) + self.assertIsNotNone( + volume_created, + "Custom volume did not get created" + ) + + self.cleanup.append(volume_created) + + # Listing the volumes for a user after creating custom volume + list_volumes_after = Volume.list(self.userapiclient, listall=self.services["listall"]) + + # Verifyign that volume list is increased by 1 after creation of custion volume + self.assertEquals( + len(list_volumes_before) + 1, + len(list_volumes_after), + "Custom volume did not get created" + ) + + # Attaching custom volume created to Virtual Machine + self.virtual_machine.attach_volume( + self.userapiclient, + volume_created + ) + list_volumes = Volume.list( + self.userapiclient, + listall=self.services["listall"], + id=volume_created.id + ) + attached_volume = list_volumes[0] + + self.assertIsNotNone( + attached_volume.vmname, + "VM is not attached to Volume" + ) + self.assertEquals( + self.virtual_machine.name, + attached_volume.vmname, + "VM Name is not matching with attached vm" + ) + + # Detaching custom volume from Virtual Machine + self.virtual_machine.detach_volume( + self.userapiclient, + volume_created + ) + list_volumes = Volume.list( + self.userapiclient, + listall=self.services["listall"], + id=volume_created.id + ) + detached_volume = list_volumes[0] + self.assertIsNone( + detached_volume.vmname, + "VM is not detached from volume" + ) + + # Resizing custom volume + # Increasing custom disk size by 1 + new_size = self.services["custom_volume"]["customdisksize"] + 1 + resized_volume = volume_created.resize( + self.userapiclient, + diskofferingid=custom_disk_offering.id, + shrinkok='false', + size=new_size) + self.assertIsNotNone(resized_volume, "Resize Volume failed") + # Verifying that custom disk size is increased + self.assertEquals( + new_size, + (resized_volume.size/(1024*1024*1024)), + "volume not resized to expected value" + ) + return + + @attr(tags=["advanced", "basic", "provisioning"]) + def test_05_volume_snapshot(self): + """ + @summary: Test to verify creation of snapshot from volume and creation of template, volume from snapshot + + Step1: Creating a volume + Step2: Attaching and Detaching custom volume created to Virtual Machine + Step3: Creating Snapshot from volume + Step4: Creating Volume from snapshot + Step5: Creating Template from Snapshot + """ + list_volumes_before = Volume.list(self.userapiclient, listall=self.services["listall"]) + + volume_created = Volume.create( + self.userapiclient, + self.services["volume"], + zoneid=self.zone.id, + diskofferingid=self.disk_offering.id + ) + + self.assertIsNotNone(volume_created, "Volume not created") + + if volume_created is not None: + self.cleanup.append(volume_created) + + list_volumes_after = Volume.list(self.userapiclient, listall=self.services["listall"]) + + self.assertEquals( + len(list_volumes_before) + 1, + len(list_volumes_after), + "Volume not created" + ) + # Attaching and Detaching custom volume created to Virtual Machine + self.virtual_machine.attach_volume( + self.userapiclient, + volume_created + ) + + list_volumes = Volume.list( + self.userapiclient, + listall=self.services["listall"], + id=volume_created.id + ) + attached_volume = list_volumes[0] + + self.assertIsNotNone( + attached_volume.vmname, + "VM is not attached to Volume" + ) + self.assertEquals( + self.virtual_machine.name, + attached_volume.vmname, + "VM Name is not matching with attached vm" + ) + self.virtual_machine.detach_volume( + self.userapiclient, + volume_created + ) + list_volumes = Volume.list( + self.userapiclient, + listall=self.services["listall"], + id=volume_created.id + ) + detached_volume = list_volumes[0] + self.assertIsNone( + detached_volume.vmname, + "VM is not detached from volume" + ) + # Creating Snapshot from volume + snapshot_created = Snapshot.create( + self.userapiclient, + volume_created.id, + ) + + self.assertIsNotNone(snapshot_created, "Snapshot not created") + + self.cleanup.append(snapshot_created) + + #Creating expected and actual values dictionaries + expected_dict = { + "id":volume_created.id, + "intervaltype":"MANUAL", + "snapshottype":"MANUAL", + "volumetype":volume_created.type, + "domain":self.domain.id + } + actual_dict = { + "id":snapshot_created.volumeid, + "intervaltype":snapshot_created.intervaltype, + "snapshottype":snapshot_created.snapshottype, + "volumetype":snapshot_created.volumetype, + "domain":snapshot_created.domainid, + } + status = self.__verify_values( + expected_dict, + actual_dict + ) + self.assertEqual( + True, + status, + "Snapshot created from Volume details are not as expected" + ) + # Creating Volume from snapshot + cmd = createVolume.createVolumeCmd() + cmd.name = "-".join([self.services["volume"]["diskname"], random_gen()]) + cmd.snapshotid = snapshot_created.id + + volume_from_snapshot = Volume(self.userapiclient.createVolume(cmd).__dict__) + + self.assertIsNotNone( + volume_from_snapshot, + "Volume creation failed from snapshot" + ) + self.cleanup.append(volume_from_snapshot) + + #Creating expected and actual values dictionaries + expected_dict = { + "snapshotid":snapshot_created.id, + "volumetype":snapshot_created.volumetype, + "size":self.disk_offering.disksize, + "accounr":self.account.name, + "domain":self.domain.id, + "storagetype":self.storagetype, + "zone":self.zone.id + } + actual_dict = { + "snapshotid":volume_from_snapshot.snapshotid, + "volumetype":volume_from_snapshot.type, + "size":volume_from_snapshot.size/(1024*1024*1024), + "accounr":volume_from_snapshot.account, + "domain":volume_from_snapshot.domainid, + "storagetype":volume_from_snapshot.storagetype, + "zone":volume_from_snapshot.zoneid, + } + status = self.__verify_values( + expected_dict, + actual_dict + ) + self.assertEqual( + True, + status, + "Volume created from Snapshot details are not as expected" + ) + # Creating Template from Snapshot + list_templates_before = Template.list(self.userapiclient, templatefilter='self') + + if list_templates_before is None: + templates_before_size = 0 + else: + templates_before_size = len(list_templates_before) + + cmd = createTemplate.createTemplateCmd() + cmd.name = self.services["ostype"] + cmd.displaytext = self.services["ostype"] + cmd.ostypeid = self.template.ostypeid + cmd.snapshotid = snapshot_created.id + cmd.ispublic = False + cmd.passwordenabled = False + + template_from_snapshot = Template(self.userapiclient.createTemplate(cmd).__dict__) + + self.assertIsNotNone( + template_from_snapshot, + "Template creation failed from snapshot" + ) + + self.cleanup.append(template_from_snapshot) + + #Creating expected and actual values dictionaries + expected_dict = { + "name":self.services["ostype"], + "ostypeid":self.template.ostypeid, + "type":"USER", + "zone":self.zone.id, + "domain":self.domain.id, + "account":self.account.name, + "passwordenabled":False, + "ispublic":False, + "size":self.disk_offering.disksize + } + actual_dict = { + "name":template_from_snapshot.name, + "ostypeid":template_from_snapshot.ostypeid, + "type":template_from_snapshot.templatetype, + "zone":template_from_snapshot.zoneid, + "domain":template_from_snapshot.domainid, + "account":template_from_snapshot.account, + "passwordenabled":template_from_snapshot.passwordenabled, + "ispublic":template_from_snapshot.ispublic, + "size":template_from_snapshot.size/(1024*1024*1024) + } + status = self.__verify_values( + expected_dict, + actual_dict + ) + self.assertEqual( + True, + status, + "Template created from Snapshot details are not as expected" + ) + + list_templates_after = Template.list(self.userapiclient, templatefilter='self') + + self.assertEquals( + templates_before_size + 1, + len(list_templates_after), + "Template creation failed from snapshot" + ) + return + + @attr(tags=["advanced", "basic", "provisioning"]) + def test_06_volume_snapshot_policy_hourly(self): + """ + @summary: Test to verify creation of Hourly Snapshot policies from volume + + Step1: Creating a Volume. + Step2: Attaching volume created in Step2 to virtual machine + Step3: Detaching the volume created in step2 from virtual machine + Step4: Listing snapshot policies for a volume created in step1 + Step5: Creating Hourly snapshot policy + Step6: Listing snapshot policies for a volume created in step1 again + Step7: Verifyign that the list snapshot policy length is increased by 1 + """ + list_volumes_before = Volume.list(self.userapiclient, listall=self.services["listall"]) + + volume_created = Volume.create( + self.userapiclient, + self.services["volume"], + zoneid=self.zone.id, + diskofferingid=self.disk_offering.id + ) + + self.assertIsNotNone(volume_created, "Volume not created") + self.cleanup.append(volume_created) + + list_volumes_after = Volume.list(self.userapiclient, listall=self.services["listall"]) + + self.assertEquals( + len(list_volumes_before) + 1, + len(list_volumes_after), + "Volume not created" + ) + + # Attaching volume created to Virtual Machine + self.virtual_machine.attach_volume( + self.userapiclient, + volume_created + ) + + list_volumes = Volume.list( + self.userapiclient, + listall=self.services["listall"], + id=volume_created.id + ) + attached_volume = list_volumes[0] + + self.assertIsNotNone( + attached_volume.vmname, + "VM is not attached to Volume" + ) + self.assertEquals( + self.virtual_machine.name, + attached_volume.vmname, + "VM Name is not matching with attached vm" + ) + # Detaching volume created from Virtual Machine + self.virtual_machine.detach_volume( + self.userapiclient, + volume_created + ) + list_volumes = Volume.list( + self.userapiclient, + listall=self.services["listall"], + id=volume_created.id + ) + detached_volume = list_volumes[0] + self.assertIsNone( + detached_volume.vmname, + "VM is not detached from volume" + ) + # Creating Hourly Snapshot Policy from volume + self.services["recurring_snapshot"]["intervaltype"] = 'hourly' + self.services["recurring_snapshot"]["schedule"] = '1' + + list_snapshot_policy_before = SnapshotPolicy.list(self.userapiclient, volumeid=volume_created.id) + + snapshot_policy_before_size = 0 + + if list_snapshot_policy_before is not None: + snapshot_policy_before_size = len(list_snapshot_policy_before) + + snapshot_policy_hourly = SnapshotPolicy.create( + self.userapiclient, + volume_created.id, + self.services["recurring_snapshot"] + ) + self.assertIsNotNone( + snapshot_policy_hourly, + "Hourly Snapshot policy creation failed" + ) + #Creating expected and actual values dictionaries + expected_dict = { + "schedule":self.services["recurring_snapshot"]["schedule"], + "intervaltype":0, + "volumeid":volume_created.id + } + actual_dict = { + "schedule":snapshot_policy_hourly.schedule, + "intervaltype":snapshot_policy_hourly.intervaltype, + "volumeid":snapshot_policy_hourly.volumeid + } + status = self.__verify_values( + expected_dict, + actual_dict + ) + self.assertEqual( + True, + status, + "Hourly Snapshot Policy details are not as expected" + ) + + list_snapshot_policy_after = SnapshotPolicy.list(self.userapiclient, volumeid=volume_created.id) + + self.assertIsNotNone( + list_snapshot_policy_after, + "Hourly Snapshot policy creation failed" + ) + self.assertEquals( + snapshot_policy_before_size + 1, + len(list_snapshot_policy_after), + "Hourly Snapshot policy creation failed" + ) + return + + @attr(tags=["advanced", "basic", "provisioning"]) + def test_07_volume_snapshot_policy_daily(self): + """ + @summary: Test to verify creation of Daily Snapshot policies from volume + + Step1: Creating a Volume. + Step2: Attaching volume created in Step2 to virtual machine + Step3: Detaching the volume created in step2 from virtual machine + Step4: Listing snapshot policies for a volume created in step1 + Step5: Creating Daily snapshot policy + Step6: Listing snapshot policies for a volume created in step1 again + Step7: Verifyign that the list snapshot policy length is increased by 1 + """ + list_volumes_before = Volume.list(self.userapiclient, listall=self.services["listall"]) + + volume_created = Volume.create( + self.userapiclient, + self.services["volume"], + zoneid=self.zone.id, + diskofferingid=self.disk_offering.id + ) + + self.assertIsNotNone(volume_created, "Volume not created") + self.cleanup.append(volume_created) + + list_volumes_after = Volume.list(self.userapiclient, listall=self.services["listall"]) + + self.assertEquals( + len(list_volumes_before) + 1, + len(list_volumes_after), + "Volume not created" + ) + # Attaching volume created to Virtual Machine + self.virtual_machine.attach_volume( + self.userapiclient, + volume_created + ) + + list_volumes = Volume.list( + self.userapiclient, + listall=self.services["listall"], + id=volume_created.id + ) + attached_volume = list_volumes[0] + + self.assertIsNotNone( + attached_volume.vmname, + "VM is not attached to Volume" + ) + self.assertEquals( + self.virtual_machine.name, + attached_volume.vmname, + "VM Name is not matching with attached vm" + ) + # Detaching volume created from Virtual Machine + self.virtual_machine.detach_volume( + self.userapiclient, + volume_created + ) + list_volumes = Volume.list( + self.userapiclient, + listall=self.services["listall"], + id=volume_created.id + ) + detached_volume = list_volumes[0] + self.assertIsNone( + detached_volume.vmname, + "VM is not detached from volume" + ) + # Creating Daily Snapshot Policy from volume + self.services["recurring_snapshot"]["intervaltype"] = 'daily' + self.services["recurring_snapshot"]["schedule"] = '00:00' + + list_snapshot_policy_before = SnapshotPolicy.list(self.userapiclient, volumeid=volume_created.id) + + snapshot_policy_before_size = 0 + + if list_snapshot_policy_before is not None: + snapshot_policy_before_size = len(list_snapshot_policy_before) + + snapshot_policy_daily = SnapshotPolicy.create( + self.userapiclient, + volume_created.id, + self.services["recurring_snapshot"] + ) + self.assertIsNotNone( + snapshot_policy_daily, + "Daily Snapshot policy creation failed" + ) + #Creating expected and actual values dictionaries + expected_dict = { + "schedule":self.services["recurring_snapshot"]["schedule"], + "intervaltype":1, + "volumeid":volume_created.id + } + actual_dict = { + "schedule":snapshot_policy_daily.schedule, + "intervaltype":snapshot_policy_daily.intervaltype, + "volumeid":snapshot_policy_daily.volumeid + } + status = self.__verify_values( + expected_dict, + actual_dict + ) + self.assertEqual( + True, + status, + "Daily Snapshot Policy details are not as expected" + ) + + list_snapshot_policy_after = SnapshotPolicy.list(self.userapiclient, volumeid=volume_created.id) + + self.assertIsNotNone( + list_snapshot_policy_after, + "Daily Snapshot policy creation failed" + ) + self.assertEquals( + snapshot_policy_before_size + 1, + len(list_snapshot_policy_after), + "Daily Snapshot policy creation failed" + ) + return + + @attr(tags=["advanced", "basic", "provisioning"]) + def test_08_volume_snapshot_policy_weekly(self): + """ + @summary: Test to verify creation of Weekly Snapshot policies from volume + + Step1: Creating a Volume. + Step2: Attaching volume created in Step2 to virtual machine + Step3: Detaching the volume created in step2 from virtual machine + Step4: Listing snapshot policies for a volume created in step1 + Step5: Creating Weekly snapshot policy + Step6: Listing snapshot policies for a volume created in step1 again + Step7: Verifyign that the list snapshot policy length is increased by 1 + """ + list_volumes_before = Volume.list(self.userapiclient, listall=self.services["listall"]) + + volume_created = Volume.create( + self.userapiclient, + self.services["volume"], + zoneid=self.zone.id, + diskofferingid=self.disk_offering.id + ) + + self.assertIsNotNone(volume_created, "Volume not created") + self.cleanup.append(volume_created) + + list_volumes_after = Volume.list(self.userapiclient, listall=self.services["listall"]) + + self.assertEquals( + len(list_volumes_before) + 1, + len(list_volumes_after), + "Volume not created" + ) + + # Attaching volume created to Virtual Machine + self.virtual_machine.attach_volume( + self.userapiclient, + volume_created + ) + list_volumes = Volume.list( + self.userapiclient, + listall=self.services["listall"], + id=volume_created.id + ) + attached_volume = list_volumes[0] + + self.assertIsNotNone( + attached_volume.vmname, + "VM is not attached to Volume" + ) + self.assertEquals( + self.virtual_machine.name, + attached_volume.vmname, + "VM Name is not matching with attached vm" + ) + # Detaching volume created to Virtual Machine + self.virtual_machine.detach_volume( + self.userapiclient, + volume_created + ) + list_volumes = Volume.list( + self.userapiclient, + listall=self.services["listall"], + id=volume_created.id + ) + detached_volume = list_volumes[0] + self.assertIsNone( + detached_volume.vmname, + "VM is not detached from volume" + ) + # Creating Weekly Snapshot Policy from volume + self.services["recurring_snapshot"]["intervaltype"] = 'weekly' + self.services["recurring_snapshot"]["schedule"] = '00:00:1' + + list_snapshot_policy_before = SnapshotPolicy.list(self.userapiclient, volumeid=volume_created.id) + + snapshot_policy_before_size = 0 + + if list_snapshot_policy_before is not None: + snapshot_policy_before_size = len(list_snapshot_policy_before) + + snapshot_policy_weekly = SnapshotPolicy.create( + self.userapiclient, + volume_created.id, + self.services["recurring_snapshot"] + ) + self.assertIsNotNone( + snapshot_policy_weekly, + "Weekly Snapshot policy creation failed" + ) + #Creating expected and actual values dictionaries + expected_dict = { + "schedule":self.services["recurring_snapshot"]["schedule"], + "intervaltype":2, + "volumeid":volume_created.id + } + actual_dict = { + "schedule":snapshot_policy_weekly.schedule, + "intervaltype":snapshot_policy_weekly.intervaltype, + "volumeid":snapshot_policy_weekly.volumeid + } + status = self.__verify_values( + expected_dict, + actual_dict + ) + self.assertEqual( + True, + status, + "Weekly Snapshot Policy details are not as expected" + ) + + list_snapshot_policy_after = SnapshotPolicy.list(self.userapiclient, volumeid=volume_created.id) + + self.assertIsNotNone( + list_snapshot_policy_after, + "Weekly Snapshot policy creation failed" + ) + self.assertEquals( + snapshot_policy_before_size + 1, + len(list_snapshot_policy_after), + "Weekly Snapshot policy creation failed" + ) + return + + @attr(tags=["advanced", "basic", "provisioning"]) + def test_09_volume_snapshot_policy_monthly(self): + """ + @summary: Test to verify creation of Monthly Snapshot policies from volume + + Step1: Creating a Volume. + Step2: Attaching volume created in Step2 to virtual machine + Step3: Detaching the volume created in step2 from virtual machine + Step4: Listing snapshot policies for a volume created in step1 + Step5: Creating Monthly snapshot policy + Step6: Listing snapshot policies for a volume created in step1 again + Step7: Verifyign that the list snapshot policy length is increased by 1 + Step8: Deleting monthly snapshot policy created in step5 + Step9: List snapshot policies for a volume again + Step10: Verifying that the list snapshot policy length is decreased by 1 + """ + list_volumes_before = Volume.list(self.userapiclient, listall=self.services["listall"]) + + volume_created = Volume.create( + self.userapiclient, + self.services["volume"], + zoneid=self.zone.id, + diskofferingid=self.disk_offering.id + ) + self.assertIsNotNone(volume_created, "Volume not created") + self.cleanup.append(volume_created) + + list_volumes_after = Volume.list(self.userapiclient, listall=self.services["listall"]) + + self.assertEquals( + len(list_volumes_before) + 1, + len(list_volumes_after), + "Volume not created" + ) + # Attaching and Detaching custom volume created to Virtual Machine + self.virtual_machine.attach_volume( + self.userapiclient, + volume_created + ) + list_volumes = Volume.list( + self.userapiclient, + listall=self.services["listall"], + id=volume_created.id + ) + attached_volume = list_volumes[0] + + self.assertIsNotNone( + attached_volume.vmname, + "VM is not attached to Volume" + ) + self.assertEquals( + self.virtual_machine.name, + attached_volume.vmname, + "VM Name is not matching with attached vm" + ) + self.virtual_machine.detach_volume( + self.userapiclient, + volume_created + ) + list_volumes = Volume.list( + self.userapiclient, + listall=self.services["listall"], + id=volume_created.id + ) + detached_volume = list_volumes[0] + self.assertIsNone( + detached_volume.vmname, + "VM is not detached from volume" + ) + # Creating Monthly Snapshot Policy from volume + self.services["recurring_snapshot"]["intervaltype"] = 'monthly' + self.services["recurring_snapshot"]["schedule"] = '00:00:1' + + list_snapshot_policy_before = SnapshotPolicy.list(self.userapiclient, volumeid=volume_created.id) + + snapshot_policy_before_size = 0 + + if list_snapshot_policy_before is not None: + snapshot_policy_before_size = len(list_snapshot_policy_before) + + snapshot_policy_monthly = SnapshotPolicy.create( + self.userapiclient, + volume_created.id, + self.services["recurring_snapshot"]) + self.assertIsNotNone( + snapshot_policy_monthly, + "Monthly Snapshot policy creation failed" + ) + #Creating expected and actual values dictionaries + expected_dict = { + "schedule":self.services["recurring_snapshot"]["schedule"], + "intervaltype":3, + "volumeid":volume_created.id + } + actual_dict = { + "schedule":snapshot_policy_monthly.schedule, + "intervaltype":snapshot_policy_monthly.intervaltype, + "volumeid":snapshot_policy_monthly.volumeid + } + status = self.__verify_values( + expected_dict, + actual_dict + ) + self.assertEqual( + True, + status, + "Monthly Snapshot Policy details are not as expected" + ) + + list_snapshot_policy_after = SnapshotPolicy.list(self.userapiclient, volumeid=volume_created.id) + + self.assertIsNotNone( + list_snapshot_policy_after, + "Monthly Snapshot policy creation failed" + ) + self.assertEquals( + snapshot_policy_before_size + 1, + len(list_snapshot_policy_after), + "Monthly Snapshot policy creation failed" + ) + # Deleting monthly snapshot policy + SnapshotPolicy.delete(snapshot_policy_monthly, self.userapiclient) + + list_snapshot_policies = SnapshotPolicy.list(self.userapiclient, volumeid=volume_created.id) + + self.assertIsNone( + list_snapshot_policies, + "Deletion of Monthly Snapshot policy failed" + ) + return + + @attr(tags=["advanced", "basic", "provisioning"]) + def test_10_volume_snapshots_pagination(self): + """ + @summary: Test to verify pagination of snapshots for Volume + + Step1: Creating a Volume. + Step2: Attaching volume created in Step2 to virtual machine + Step3: Detaching the volume created in step2 from virtual machine + Step4: Listing all the snapshots for a volume + Step5: Creating Pagesize + 1 number of snapshots for a volume + Step6: Listing all the snapshots for a volume + Step7: Verifying that there are pagesize + 1 number of snapshots listsed + Step8: Listing all the snapshots in page 1 + Step9: Listing all the snapshots in page 2 + Step10: Deleting the snapshot present in page 2 + Step11: Listign the snapshots from page 2 again and verifyign that list returns none + """ + list_volumes_before = Volume.list(self.userapiclient, listall=self.services["listall"]) + + # Creating a Volume + volume_created = Volume.create( + self.userapiclient, + self.services["volume"], + zoneid=self.zone.id, + diskofferingid=self.disk_offering.id + ) + self.assertIsNotNone(volume_created, "Volume not created") + self.cleanup.append(volume_created) + + list_volumes_after = Volume.list(self.userapiclient, listall=self.services["listall"]) + + self.assertEquals( + len(list_volumes_before) + 1, + len(list_volumes_after), + "Volume not created" + ) + #Attaching volume to virtual machine + self.virtual_machine.attach_volume( + self.userapiclient, + volume_created + ) + list_volumes = Volume.list( + self.userapiclient, + listall=self.services["listall"], + id=volume_created.id + ) + attached_volume = list_volumes[0] + + self.assertIsNotNone( + attached_volume.vmname, + "VM is not attached to Volume" + ) + self.assertEquals( + self.virtual_machine.name, + attached_volume.vmname, + "VM Name is not matching with attached vm" + ) + #Detaching volume from virtual machine + self.virtual_machine.detach_volume( + self.userapiclient, + volume_created + ) + list_volumes = Volume.list( + self.userapiclient, + listall=self.services["listall"], + id=volume_created.id + ) + detached_volume = list_volumes[0] + self.assertIsNone( + detached_volume.vmname, + "VM is not detached from volume" + ) + + #Creating 3 Snapshots from volume + list_snapshot_before = Snapshot.list( + self.userapiclient, + volumeid=volume_created.id, + listall=self.services["listall"] + ) + self.assertIsNone( + list_snapshot_before, + "Newly created volume is already having snapshots" + ) + + list_snapshot_before_size = 0 + for i in range(0, 3): + snapshot_created = Snapshot.create( + self.userapiclient, + volume_created.id, + ) + self.assertIsNotNone(snapshot_created, "Snapshot not created") + self.cleanup.append(snapshot_created) + + self.assertEquals( + volume_created.id, + snapshot_created.volumeid, + "Snapshot not created for given volume" + ) + + list_snapshot_after = Snapshot.list( + self.userapiclient, + volumeid=volume_created.id, + listall=self.services["listall"] + ) + self.assertEqual( + list_snapshot_before_size+3, + len(list_snapshot_after), + "Number of snapshots created is not matching expected" + ) + #Listing all the snapshots in page1 + list_snapshots_page1 = Snapshot.list( + self.userapiclient, + volumeid=volume_created.id, + listall=self.services["listall"], + page=1, + pagesize=2 + ) + self.assertEqual( + 2, + len(list_snapshots_page1), + "List snapshots response is not matching with the page size length for page 1" + ) + + #Listing all the snapshots in page2 and ensuring only 1 snapshot is present + list_snapshots_page2 = Snapshot.list( + self.userapiclient, + volumeid=volume_created.id, + listall=self.services["listall"], + page=2, + pagesize=2 + ) + self.assertEqual( + len(list_snapshots_page2), + 1, + "List snapshots response is not matching with the page size length for page 2" + ) + snapshot_page2 = list_snapshots_page2[0] + + # Verifying that the snapshot on page 2 is not present in page1 + for i in range(0, len(list_snapshots_page1)): + snapshot_page1 = list_snapshots_page1[i] + self.assertNotEquals( + snapshot_page2.id, + snapshot_page1.id, + "Snapshot listed in page 2 is also listed in page 1" + ) + # Deleting a single snapshot and verifying that snapshot does not exists on page 2 + Snapshot.delete(snapshot_created, self.userapiclient) + + list_snapshot_page2 = Snapshot.list( + self.userapiclient, + volumeid=volume_created.id, + listall=self.services["listall"], + page=2, + pagesize=2 + ) + self.assertEqual( + None, + list_snapshot_page2, + "Snapshot was not deleted" + ) + list_snapshot_page1 = Snapshot.list( + self.userapiclient, + volumeid=volume_created.id, + listall=self.services["listall"], + page=1, + pagesize=2 + ) + self.assertEqual( + 2, + len(list_snapshot_page1), + "Snapshots on page 1 are not matching" + ) + return + + @attr(tags=["advanced", "basic", "provisioning"]) + def test_11_volume_extract(self): + """ + @summary: Test to verify extract/download a Volume + + Step1: Listing Volumes before creating a Volume + Step2: Creating a Volume. + Step3: Verifying that created volume is not none and adding to clean up + Step4: Listing the volumes after creation + Step5: Verifying that the list volume size is increased by 1 + Step6: Attaching volume created in Step2 to virtual machine + Step7: Detaching the volume created in step2 from virtual machine + Step8: Extracting/Downloadign the volume + Step9: Verifyign that a download URL is created for volume download + """ + list_volumes_before = Volume.list(self.userapiclient, listall=self.services["listall"]) + + self.assertIsNotNone( + list_volumes_before, + "volume not created for the vm launched at class level" + ) + volume_created = Volume.create( + self.userapiclient, + self.services["volume"], + zoneid=self.zone.id, + diskofferingid=self.disk_offering.id + ) + + self.assertIsNotNone(volume_created, "Volume not created") + self.cleanup.append(volume_created) + + list_volumes_after = Volume.list(self.userapiclient, listall=self.services["listall"]) + + self.assertIsNotNone( + list_volumes_after, + "volume creation failed" + ) + self.assertEquals( + len(list_volumes_before) + 1, + len(list_volumes_after), + "Volume not created" + ) + #Attaching and Detaching volume created to Virtual Machine + self.virtual_machine.attach_volume( + self.userapiclient, + volume_created + ) + list_volumes = Volume.list( + self.userapiclient, + listall=self.services["listall"], + id=volume_created.id + ) + attached_volume = list_volumes[0] + + self.assertIsNotNone( + attached_volume.vmname, + "VM is not attached to Volume" + ) + self.assertEquals( + self.virtual_machine.name, + attached_volume.vmname, + "VM Name is not matching with attached vm" + ) + self.virtual_machine.detach_volume( + self.userapiclient, + volume_created + ) + list_volumes = Volume.list( + self.userapiclient, + listall=self.services["listall"], + id=volume_created.id + ) + detached_volume = list_volumes[0] + self.assertIsNone( + detached_volume.vmname, + "VM is not detached from volume" + ) + #Extract/Download the volume + self.services["mode"] = "HTTP_DOWNLOAD" + + extract_volume_response = Volume.extract( + self.userapiclient, + volume_created.id, + self.zone.id, + self.services["mode"] + ) + self.assertIsNotNone(extract_volume_response, "Extract/Download volume failed") + + self.assertEquals( + "DOWNLOAD_URL_CREATED", + extract_volume_response.state, + "Failed to create Download URL" + ) + self.assertIsNotNone( + extract_volume_response.url, + "Extract/Download volume URL is NULL" + ) + self.assertTrue( + (extract_volume_response.url.find("https://")!=-1), + "Extract/Download volume URL doesnot contain https://" + ) + self.assertEquals( + volume_created.id, + extract_volume_response.id, + "Extracted/Downloaded volume is not matching with original volume" + ) + return + + @attr(tags=["advanced", "basic", "provisioning"]) + def test_12_volume_upload(self): + """ + @summary: Test to verify upload volume + + Step1: Listing the volumes for a user before uploading volume + Step2: Uploading a volume + Step3: Listing the volumes for a user after uploading data volume + Step4: Verifying that the list volume length after upload is increased by 1 + """ + list_volumes_before = Volume.list(self.userapiclient, listall=self.services["listall"]) + + self.assertIsNotNone( + list_volumes_before, + "volume not created for the vm launched at class level" + ) + #Uploading a Volume + volume_uploaded = Volume.upload( + self.userapiclient, + self.services["upload_volume"], + self.zone.id + ) + self.assertIsNotNone(volume_uploaded, "volume uploading failed") + + self.assertEquals( + self.services["upload_volume"]["diskname"], + volume_uploaded.name, + "Uploaded volume name is not matching with name provided while uploading") + + #Listing the volumes for a user after uploading data volume + list_volumes_after = Volume.list(self.userapiclient, listall=self.services["listall"]) + + self.assertIsNotNone( + list_volumes_after, + "volume not created for the vm launched at class level" + ) + #Asserting that the list volume length after upload is increased by 1 + self.assertEquals( + len(list_volumes_before) + 1, + len(list_volumes_after), + "upload volume failed" + ) + return + +class TestListInstances(cloudstackTestCase): + + @classmethod + def setUpClass(cls): + try: + cls._cleanup = [] + cls.testClient = super(TestListInstances, cls).getClsTestClient() + cls.api_client = cls.testClient.getApiClient() + cls.services = cls.testClient.getParsedTestDataConfig() + + # Get Domain, Zone, Template + cls.domain = get_domain(cls.api_client) + cls.zone = get_zone(cls.api_client) + cls.template = get_template( + cls.api_client, + cls.zone.id, + cls.services["ostype"] + ) + if cls.zone.localstorageenabled: + cls.storagetype = 'local' + cls.services["service_offerings"]["tiny"]["storagetype"] = 'local' + cls.services["disk_offering"]["storagetype"] = 'local' + else: + cls.storagetype = 'shared' + cls.services["service_offerings"]["tiny"]["storagetype"] = 'shared' + cls.services["disk_offering"]["storagetype"] = 'shared' + + cls.services['mode'] = cls.zone.networktype + cls.services["virtual_machine"]["hypervisor"] = cls.testClient.getHypervisorInfo() + cls.services["virtual_machine"]["zoneid"] = cls.zone.id + cls.services["virtual_machine"]["template"] = cls.template.id + cls.services["custom_volume"]["zoneid"] = cls.zone.id + + # Creating Disk offering, Service Offering and Account + cls.disk_offering = DiskOffering.create( + cls.api_client, + cls.services["disk_offering"] + ) + cls._cleanup.append(cls.disk_offering) + cls.service_offering = ServiceOffering.create( + cls.api_client, + cls.services["service_offerings"]["tiny"] + ) + cls._cleanup.append(cls.service_offering) + cls.account = Account.create( + cls.api_client, + cls.services["account"], + domainid=cls.domain.id + ) + # Getting authentication for user in newly created Account + cls.user = cls.account.user[0] + cls.userapiclient = cls.testClient.getUserApiClient(cls.user.username, cls.domain.name) + # Updating resource Limits + for i in range(0,12): + Resources.updateLimit( + cls.api_client, + account=cls.account.name, + domainid=cls.domain.id, + max=-1, + resourcetype=i + ) + + cls._cleanup.append(cls.account) + except Exception as e: + cls.tearDownClass() + raise Exception("Warning: Exception in setup : %s" % e) + return + + def setUp(self): + + self.apiClient = self.testClient.getApiClient() + self.cleanup = [] + + def tearDown(self): + #Clean up, terminate the created resources + cleanup_resources(self.apiClient, self.cleanup) + return + + @classmethod + def tearDownClass(cls): + try: + cleanup_resources(cls.api_client, cls._cleanup) + except Exception as e: + raise Exception("Warning: Exception during cleanup : %s" % e) + + return + + def __verify_values(self, expected_vals, actual_vals): + """ + @Desc: Function to verify expected and actual values + @Steps: + Step1: Initializing return flag to True + Step1: Verifying length of expected and actual dictionaries is matching. + If not matching returning false + Step2: Listing all the keys from expected dictionary + Step3: Looping through each key from step2 and verifying expected and actual dictionaries have same value + If not making return flag to False + Step4: returning the return flag after all the values are verified + """ + return_flag = True + + if len(expected_vals) != len(actual_vals): + return False + + keys = expected_vals.keys() + for i in range(0, len(expected_vals)): + exp_val = expected_vals[keys[i]] + act_val = actual_vals[keys[i]] + if exp_val == act_val: + return_flag = return_flag and True + else: + return_flag = return_flag and False + self.debug("expected Value: %s, is not matching with actual value: %s" % ( + exp_val, + act_val + )) + return return_flag + + @attr(tags=["advanced", "basic", "selfservice"]) + def test_01_list_instances_pagination(self): + """ + @Desc: Test List Instances pagination + @Steps: + Step1: Listing all the Instances for a user + Step2: Verifying listed Instances for account created at class level + Step3: If number of volumes is less than (page size + 1), then creating them + Step4: Listing all the volumes again after creation of volumes + Step5: Verifying the length of the volumes is (page size + 1) + Step6: Listing all the volumes in page1 + Step7: Verifying that the length of the volumes in page 1 is (page size) + Step8: Listing all the volumes in page2 + Step9: Verifying that the length of the volumes in page 2 is 1 + Step10: Deleting the volume present in page 2 + Step11: Listing for the volumes on page 2 + Step12: Verifying that there are no volumes present in page 2 + """ + # Listing all the instances for a user + list_instances_before = VirtualMachine.list(self.userapiclient, listall=self.services["listall"]) + + # Verifying listed instances for account created at class level + self.assertIsNone( + list_instances_before, + "Virtual Machine already exists for newly created user" + ) + # If number of instances are less than (pagesize + 1), then creating them + for i in range(0, (self.services["pagesize"] + 1)): + vm_created = VirtualMachine.create( + self.userapiclient, + self.services["virtual_machine"], + accountid=self.account.name, + domainid=self.account.domainid, + serviceofferingid=self.service_offering.id, + ) + self.assertIsNotNone( + vm_created, + "VM creation failed" + ) + if(i < (self.services["pagesize"])): + self.cleanup.append(vm_created) + + self.assertEqual( + self.services["virtual_machine"]["displayname"], + vm_created.displayname, + "Newly created VM name and the test data VM name are not matching" + ) + + # Listing all the instances again after creating VM's + list_instances_after = VirtualMachine.list(self.userapiclient, listall=self.services["listall"]) + status = validateList(list_instances_after) + self.assertEquals( + PASS, + status[0], + "Listing of instances after creation failed" + ) + # Verifying the length of the instances is (page size + 1) + self.assertEqual( + len(list_instances_after), + (self.services["pagesize"] + 1), + "Number of instances created is not matching as expected" + ) + + # Listing all the volumes in page1 + list_instances_page1 = VirtualMachine.list( + self.userapiclient, + listall=self.services["listall"], + page=1, + pagesize=self.services["pagesize"], + domainid=self.account.domainid + ) + status = validateList(list_instances_page1) + self.assertEquals( + PASS, + status[0], + "Listing of instances in page1 failed" + ) + # Verifying that the length of the instances in page 1 is (page size) + self.assertEqual( + self.services["pagesize"], + len(list_instances_page1), + "List VM response is not matching with the page size length for page 1" + ) + + # Listing all the VM's in page2 + list_instances_page2 = VirtualMachine.list( + self.userapiclient, + listall=self.services["listall"], + page=2, + pagesize=self.services["pagesize"], + domainid=self.account.domainid + ) + status = validateList(list_instances_page2) + self.assertEquals( + PASS, + status[0], + "Listing of instances in page2 failed" + ) + # Verifying that the length of the VM's in page 2 is 1 + self.assertEqual( + 1, + len(list_instances_page2), + "List VM response is not matching with the page size length for page 2" + ) + instance_page2 = list_instances_page2[0] + + # Verifying that the VM on page 2 is not present in page1 + for i in range(0, len(list_instances_page1)): + instance_page1 = list_instances_page1[i] + self.assertNotEquals( + instance_page2.id, + instance_page1.id, + "VM listed in page 2 is also listed in page 1" + ) + + # Deleting a single VM + VirtualMachine.delete(vm_created, self.userapiclient) + + # Listing the VM's in page 2 + list_instance_response = VirtualMachine.list( + self.userapiclient, + listall=self.services["listall"], + page=2, + pagesize=self.services["pagesize"], + domainid=self.account.domainid + ) + # verifying that VM does not exists on page 2 + self.assertEqual( + list_instance_response, + None, + "VM was not deleted" + ) + return + + @attr(tags=["advanced", "basic", "selfservice"]) + def test_02_list_Running_vm(self): + """ + @Desc: Test List Running VM's + @Steps: + Step1: Listing all the Running VMs for a user + Step2: Verifying that the size of the list is 0 + Step3: Deploying a VM + Step4: Listing all the Running VMs for a user again + Step5: Verifying that the size of the list is increased by 1 + Step6: Verifying that the details of the Running VM listed are same as the VM deployed in Step3 + """ + # Listing all the Running VM's for a User + list_running_vms_before = VirtualMachine.list( + self.userapiclient, + listall=self.services["listall"], + page=1, + pagesize=self.services["pagesize"], + domainid=self.account.domainid, + state="Running" + ) + self.assertIsNone( + list_running_vms_before, + "Virtual Machine already exists for newly created user" + ) + # Deploying a VM + vm_created = VirtualMachine.create( + self.userapiclient, + self.services["virtual_machine"], + accountid=self.account.name, + domainid=self.account.domainid, + serviceofferingid=self.service_offering.id, + ) + self.assertIsNotNone( + vm_created, + "VM creation failed" + ) + self.cleanup.append(vm_created) + # Listing all the Running VM's for a User + list_running_vms_after = VirtualMachine.list( + self.userapiclient, + listall=self.services["listall"], + page=1, + pagesize=self.services["pagesize"], + domainid=self.account.domainid, + state="Running" + ) + status = validateList(list_running_vms_after) + self.assertEquals( + PASS, + status[0], + "Newly created VM is not in Running state" + ) + # Verifying list size is 1 + self.assertEquals( + 1, + len(list_running_vms_after), + "Running VM list count is not matching" + ) + running_vm = list_running_vms_after[0] + + #Creating expected and actual values dictionaries + expected_dict = { + "id":vm_created.id, + "name":vm_created.name, + "displayname":vm_created.displayname, + "state":"Running", + "zoneid":vm_created.zoneid, + "account":vm_created.account, + "template":vm_created.templateid + } + actual_dict = { + "id":running_vm.id, + "name":running_vm.name, + "displayname":running_vm.displayname, + "state":running_vm.state, + "zoneid":running_vm.zoneid, + "account":running_vm.account, + "template":running_vm.templateid + } + running_vm_status = self.__verify_values( + expected_dict, + actual_dict + ) + self.assertEqual( + True, + running_vm_status, + "Listed Running VM details are not as expected" + ) + return + + @attr(tags=["advanced", "basic", "selfservice"]) + def test_03_list_Stopped_vm(self): + """ + @Desc: Test List Stopped VM's + @Steps: + Step1: Listing all the Stopped VMs for a user + Step2: Verifying that the size of the list is 0 + Step3: Deploying a VM + Step4: Stopping the VM deployed in step3 + Step5: Listing all the Stopped VMs for a user again + Step6: Verifying that the size of the list is increased by 1 + Step7: Verifying that the details of the Stopped VM listed are same as the VM stopped in Step4 + """ + # Listing all the Stopped VM's for a User + list_stopped_vms_before = VirtualMachine.list( + self.userapiclient, + listall=self.services["listall"], + page=1, + pagesize=self.services["pagesize"], + domainid=self.account.domainid, + state="Stopped" + ) + self.assertIsNone( + list_stopped_vms_before, + "Virtual Machine already exists for newly created user" + ) + # Deploying a VM + vm_created = VirtualMachine.create( + self.userapiclient, + self.services["virtual_machine"], + accountid=self.account.name, + domainid=self.account.domainid, + serviceofferingid=self.service_offering.id, + ) + self.assertIsNotNone( + vm_created, + "VM creation failed" + ) + self.cleanup.append(vm_created) + # Stopping the VM + VirtualMachine.stop(vm_created, self.userapiclient) + # Listing all the Stopped VM's for a User + list_stopped_vms_after = VirtualMachine.list( + self.userapiclient, + listall=self.services["listall"], + page=1, + pagesize=self.services["pagesize"], + domainid=self.account.domainid, + state="Stopped" + ) + status = validateList(list_stopped_vms_after) + self.assertEquals( + PASS, + status[0], + "Stopped VM is not in Stopped state" + ) + # Verifying list size is 1 + self.assertEquals( + 1, + len(list_stopped_vms_after), + "Stopped VM list count is not matching" + ) + stopped_vm = list_stopped_vms_after[0] + #Creating expected and actual values dictionaries + expected_dict = { + "id":vm_created.id, + "name":vm_created.name, + "displayname":vm_created.displayname, + "state":"Stopped", + "zoneid":vm_created.zoneid, + "account":vm_created.account, + "template":vm_created.templateid + } + actual_dict = { + "id":stopped_vm.id, + "name":stopped_vm.name, + "displayname":stopped_vm.displayname, + "state":stopped_vm.state, + "zoneid":stopped_vm.zoneid, + "account":stopped_vm.account, + "template":stopped_vm.templateid + } + stopped_vm_status = self.__verify_values( + expected_dict, + actual_dict + ) + self.assertEqual( + True, + stopped_vm_status, + "Listed Stopped VM details are not as expected" + ) + return + + @attr(tags=["advanced", "basic", "selfservice"]) + def test_04_list_Destroyed_vm(self): + """ + @Desc: Test List Destroyed VM's + @Steps: + Step1: Listing all the Destroyed VMs for a user + Step2: Verifying that the size of the list is 0 + Step3: Deploying a VM + Step4: Destroyed the VM deployed in step3 + Step5: Listing all the Destroyed VMs for a user again + Step6: Verifying that destroyed VM is not listed for User + Step7: Listing all the destroyed VMs as admin + Step8: Verifying that the size of the list is 1 + Step9: Verifying that the details of the Destroyed VM listed are same as the VM destroyed in Step4 + """ + # Listing all the Destroyed VM's for a User + list_destroyed_vms_before = VirtualMachine.list( + self.userapiclient, + listall=self.services["listall"], + page=1, + pagesize=self.services["pagesize"], + domainid=self.account.domainid, + state="Destroyed" + ) + self.assertIsNone( + list_destroyed_vms_before, + "Virtual Machine in Destroyed state already exists for newly created user" + ) + # Deploying a VM + vm_created = VirtualMachine.create( + self.userapiclient, + self.services["virtual_machine"], + accountid=self.account.name, + domainid=self.account.domainid, + serviceofferingid=self.service_offering.id, + ) + self.assertIsNotNone( + vm_created, + "VM creation failed" + ) + # Destroying the VM + VirtualMachine.delete(vm_created, self.userapiclient) + # Listing all the Destroyed VM's for a User + list_destroyed_vms_after = VirtualMachine.list( + self.userapiclient, + listall=self.services["listall"], + page=1, + pagesize=self.services["pagesize"], + domainid=self.account.domainid, + state="Destroyed" + ) + self.assertIsNone( + list_destroyed_vms_after, + "Destroyed VM is not in destroyed state" + ) + # Listing destroyed VMs as admin user + list_destroyed_vms_admin = VirtualMachine.list( + self.apiClient, + listall=self.services["listall"], + page=1, + pagesize=self.services["pagesize"], + domainid=self.account.domainid, + state="Destroyed", + id=vm_created.id + ) + status = validateList(list_destroyed_vms_admin) + self.assertEquals( + PASS, + status[0], + "Destroyed VM is not in Destroyed state" + ) + # Verifying that the length of the destroyed VMs list should be 1 + self.assertEquals( + 1, + len(list_destroyed_vms_admin), + "Destroyed VM list count is not matching" + ) + destroyed_vm = list_destroyed_vms_admin[0] + #Creating expected and actual values dictionaries + expected_dict = { + "id":vm_created.id, + "name":vm_created.name, + "displayname":vm_created.displayname, + "state":"Destroyed", + "zoneid":vm_created.zoneid, + "account":vm_created.account, + "template":vm_created.templateid + } + actual_dict = { + "id":destroyed_vm.id, + "name":destroyed_vm.name, + "displayname":destroyed_vm.displayname, + "state":destroyed_vm.state, + "zoneid":destroyed_vm.zoneid, + "account":destroyed_vm.account, + "template":destroyed_vm.templateid + } + destroyed_vm_status = self.__verify_values( + expected_dict, + actual_dict + ) + self.assertEqual( + True, + destroyed_vm_status, + "Listed Destroyed VM details are not as expected" + ) + return + + @attr(tags=["advanced", "basic", "selfservice"]) + def test_05_list_vm_by_id(self): + """ + @Desc: Test List VM by Id + @Steps: + Step1: Listing all the VMs for a user + Step2: Verifying that the size of the list is 0 + Step3: Deploying a VM + Step4: Listing all the VMs for a user again + Step5: Verifying that the size of the list is increased by 1 + Step6: List a VM by specifying the Id if the VM deployed in Step3 + Step7: Verifying that the details of the Listed VM are same as the VM deployed in Step3 + """ + # Listing all the VM's for a User + list_vms_before = VirtualMachine.list( + self.userapiclient, + listall=self.services["listall"], + page=1, + pagesize=self.services["pagesize"], + domainid=self.account.domainid, + account=self.account.name + ) + self.assertIsNone( + list_vms_before, + "Virtual Machine already exists for newly created user" + ) + # Deploying a VM + vm_created = VirtualMachine.create( + self.userapiclient, + self.services["virtual_machine"], + accountid=self.account.name, + domainid=self.account.domainid, + serviceofferingid=self.service_offering.id, + ) + self.assertIsNotNone( + vm_created, + "VM creation failed" + ) + self.cleanup.append(vm_created) + # Listing all the VM's for a User + list_vms_after = VirtualMachine.list( + self.userapiclient, + listall=self.services["listall"], + page=1, + pagesize=self.services["pagesize"], + domainid=self.account.domainid, + account=self.account.name + ) + status = validateList(list_vms_after) + self.assertEquals( + PASS, + status[0], + "Listing of VM after creation failed" + ) + self.assertEquals( + 1, + len(list_vms_after), + "VM list count is not matching" + ) + # Listing a VM by Id + list_vm_byid = VirtualMachine.list( + self.userapiclient, + listall=self.services["listall"], + id=vm_created.id + ) + status = validateList(list_vm_byid) + self.assertEquals( + PASS, + status[0], + "Listing of VM by Id failed" + ) + listed_vm = list_vm_byid[0] + #Creating expected and actual values dictionaries + expected_dict = { + "id":vm_created.id, + "name":vm_created.name, + "displayname":vm_created.displayname, + "state":vm_created.state, + "zoneid":vm_created.zoneid, + "account":vm_created.account, + "template":vm_created.templateid + } + actual_dict = { + "id":listed_vm.id, + "name":listed_vm.name, + "displayname":listed_vm.displayname, + "state":listed_vm.state, + "zoneid":listed_vm.zoneid, + "account":listed_vm.account, + "template":listed_vm.templateid + } + list_vm_status = self.__verify_values( + expected_dict, + actual_dict + ) + self.assertEqual( + True, + list_vm_status, + "Listed VM by Id details are not as expected" + ) + return + + @attr(tags=["advanced", "basic", "selfservice"]) + def test_06_list_vm_by_name(self): + """ + @Desc: Test List VM's by Name + @Steps: + Step1: Listing all the VMs for a user + Step2: Verifying that the size of the list is 0 + Step3: Deploying a 2 VM's + Step4: Listing all the VMs for a user again + Step5: Verifying that list size is increased by 2 + Step6: Listing the VM by specifying complete name of VM-1 created in step3 + Step7: Verifying that the size of the list is 1 + Step8: Verifying that the details of the listed VM are same as the VM-1 created in step3 + Step9: Listing the VM by specifying the partial name of VM + Step10: Verifying that the size of the list is 2 + """ + # Listing all the VM's for a User + list_vms_before = VirtualMachine.list( + self.userapiclient, + listall=self.services["listall"], + page=1, + pagesize=self.services["pagesize"], + domainid=self.account.domainid, + ) + self.assertIsNone( + list_vms_before, + "Virtual Machine already exists for newly created user" + ) + vms = {} + for i in range(0, 2): + # Deploying a VM + vm_created = VirtualMachine.create( + self.userapiclient, + self.services["virtual_machine"], + accountid=self.account.name, + domainid=self.account.domainid, + serviceofferingid=self.service_offering.id, + ) + self.assertIsNotNone( + vm_created, + "VM creation failed" + ) + self.cleanup.append(vm_created) + vms.update({i: vm_created}) + + # Listing all the VM's for a User + list_vms_after = VirtualMachine.list( + self.userapiclient, + listall=self.services["listall"], + page=1, + pagesize=self.services["pagesize"], + domainid=self.account.domainid, + ) + status = validateList(list_vms_after) + self.assertEquals( + PASS, + status[0], + "VM's creation failed" + ) + self.assertEquals( + 2, + len(list_vms_after), + "VM's list count is not matching" + ) + # Listing the VM by complete name + list_vm_byfullname = VirtualMachine.list( + self.userapiclient, + listall=self.services["listall"], + page=1, + pagesize=self.services["pagesize"], + domainid=self.account.domainid, + name=vms[0].name + ) + status = validateList(list_vm_byfullname) + self.assertEquals( + PASS, + status[0], + "Failed to list VM by Name" + ) + # Verifying that the size of the list is 1 + self.assertEquals( + 1, + len(list_vm_byfullname), + "VM list by full name count is not matching" + ) + # Verifying that the details of the listed VM are same as the VM created above + #Creating expected and actual values dictionaries + expected_dict = { + "id":vms[0].id, + "name":vms[0].name, + "displayname":vms[0].displayname, + "state":vms[0].state, + "zoneid":vms[0].zoneid, + "account":vms[0].account, + "template":vms[0].templateid + } + actual_dict = { + "id":list_vm_byfullname[0].id, + "name":list_vm_byfullname[0].name, + "displayname":list_vm_byfullname[0].displayname, + "state":list_vm_byfullname[0].state, + "zoneid":list_vm_byfullname[0].zoneid, + "account":list_vm_byfullname[0].account, + "template":list_vm_byfullname[0].templateid + } + list_vm_status = self.__verify_values( + expected_dict, + actual_dict + ) + self.assertEqual( + True, + list_vm_status, + "Listed VM details are not as expected" + ) + # Listing the VM by partial name + list_vm_bypartialname = VirtualMachine.list( + self.userapiclient, + listall=self.services["listall"], + domainid=self.account.domainid, + name=vms[0].name[:1] + ) + status = validateList(list_vm_bypartialname) + self.assertEquals( + PASS, + status[0], + "Failed to list VM by Name" + ) + # Verifying that the size of the list is 2 + self.assertEquals( + 2, + len(list_vm_bypartialname), + "VM list by full name count is not matching" + ) + return + + @attr(tags=["advanced", "basic", "selfservice"]) + def test_07_list_vm_by_name_state(self): + """ + @Desc: Test List VM's by Name and State + @Steps: + Step1: Listing all the VMs for a user + Step2: Verifying that the size of the list is 0 + Step3: Deploying a VM + Step4: Listing all the VMs for a user again + Step5: Verifying that list size is increased by 1 + Step6: Listing the VM by specifying name of VM created in step3 and state as Running (matching name and state) + Step7: Verifying that the size of the list is 1 + Step8: Verifying that the details of the listed VM are same as the VM created in step3 + Step9: Listing the VM by specifying name of VM created in step3 and state as Stopped (non matching state) + Step10: Verifying that the size of the list is 0 + Step11: Listing the VM by specifying non matching name and state as Running (non matching name) + Step12: Verifying that the size of the list is 0 + """ + # Listing all the VM's for a User + list_vms_before = VirtualMachine.list( + self.userapiclient, + listall=self.services["listall"], + page=1, + pagesize=self.services["pagesize"], + domainid=self.account.domainid, + ) + self.assertIsNone( + list_vms_before, + "Virtual Machine already exists for newly created user" + ) + # Deploying a VM + vm_created = VirtualMachine.create( + self.userapiclient, + self.services["virtual_machine"], + accountid=self.account.name, + domainid=self.account.domainid, + serviceofferingid=self.service_offering.id, + ) + self.assertIsNotNone( + vm_created, + "VM creation failed" + ) + self.cleanup.append(vm_created) + # Listing all the VM's for a User + list_vms_after = VirtualMachine.list( + self.userapiclient, + listall=self.services["listall"], + page=1, + pagesize=self.services["pagesize"], + domainid=self.account.domainid, + ) + status = validateList(list_vms_after) + self.assertEquals( + PASS, + status[0], + "VM's creation failed" + ) + self.assertEquals( + 1, + len(list_vms_after), + "VM's list count is not matching" + ) + # Listing the VM by matching Name and State + list_running_vm = VirtualMachine.list( + self.userapiclient, + listall=self.services["listall"], + page=1, + pagesize=self.services["pagesize"], + domainid=self.account.domainid, + name=vm_created.name, + state="Running" + ) + status = validateList(list_running_vm) + self.assertEquals( + PASS, + status[0], + "List VM by name and state failed" + ) + # Verifying that the size of the list is 1 + self.assertEquals( + 1, + len(list_running_vm), + "Count of VM list by name and state is not matching" + ) + # Verifying that the details of the listed VM are same as the VM created above + #Creating expected and actual values dictionaries + expected_dict = { + "id":vm_created.id, + "name":vm_created.name, + "displayname":vm_created.displayname, + "state":"Running", + "zoneid":vm_created.zoneid, + "account":vm_created.account, + "template":vm_created.templateid + } + actual_dict = { + "id":list_running_vm[0].id, + "name":list_running_vm[0].name, + "displayname":list_running_vm[0].displayname, + "state":list_running_vm[0].state, + "zoneid":list_running_vm[0].zoneid, + "account":list_running_vm[0].account, + "template":list_running_vm[0].templateid + } + list_vm_status = self.__verify_values( + expected_dict, + actual_dict + ) + self.assertEqual( + True, + list_vm_status, + "Listed VM details are not as expected" + ) + # Listing the VM by matching name and non matching state + list_running_vm = VirtualMachine.list( + self.userapiclient, + listall=self.services["listall"], + page=1, + pagesize=self.services["pagesize"], + domainid=self.account.domainid, + name=vm_created.name, + state="Stopped" + ) + self.assertIsNone( + list_running_vm, + "Listed VM with non matching state" + ) + # Listing the VM by non matching name and matching state + list_running_vm = VirtualMachine.list( + self.userapiclient, + listall=self.services["listall"], + page=1, + pagesize=self.services["pagesize"], + domainid=self.account.domainid, + name="name", + state="Running" + ) + self.assertIsNone( + list_running_vm, + "Listed VM with non matching name" + ) + return + + @attr(tags=["advanced", "basic", "selfservice"]) + def test_08_list_vm_by_zone(self): + """ + @Desc: Test List VM by Zone. + This test case is applicable for a setup having multiple zones. + @Steps: + Step1: Listing all the zones + Step2: Checking if there are multiple zones in the setup. + Continuing below steps only if there are multiple zones + Step3: Listing template for zone + Step4: Listing all the VMs for a user + Step5: Verifying that the size of the list is 0 + Step6: Deploying a VM + Step7: Listing all the VMs for a user again for matching zone + Step8: Verifying that the size of the list is 1 + Step9: Verifying that the details of the Listed VM are same as the VM deployed in Step6 + Step10: Listing all the VMs for a user again for non-matching zone + Step11: Verifying that the size of the list is 0 + """ + # Listing all the zones available + zones_list = Zone.list(self.apiClient) + status = validateList(zones_list) + self.assertEquals( + PASS, + status[0], + "zones not available in the given setup" + ) + current_zone = self.services["virtual_machine"]["zoneid"] + current_template = self.services["virtual_machine"]["template"] + # Checking if there are multiple zones in the setup. + if not len(zones_list) > 1: + self.debug("Setup is not having multiple zones") + else: + # Getting the template available under the zone + template = get_template( + self.apiClient, + zones_list[0].id, + self.services["ostype"] + ) + self.assertIsNotNone( + template, + "Template not found for zone" + ) + self.services["virtual_machine"]["zoneid"] = zones_list[0].id + self.services["virtual_machine"]["template"] = template.id + # Listing all the VM's for a User + list_vms_before = VirtualMachine.list( + self.userapiclient, + listall=self.services["listall"], + page=1, + pagesize=self.services["pagesize"], + domainid=self.account.domainid, + zoneid=zones_list[0].id + ) + self.assertIsNone( + list_vms_before, + "Virtual Machine already exists for newly created user" + ) + # Deploying a VM + vm_created = VirtualMachine.create( + self.userapiclient, + self.services["virtual_machine"], + accountid=self.account.name, + domainid=self.account.domainid, + serviceofferingid=self.service_offering.id, + ) + self.assertIsNotNone( + vm_created, + "VM creation failed" + ) + self.cleanup.append(vm_created) + # Listing all the VMs for a user again for matching zone + list_vms_after = VirtualMachine.list( + self.userapiclient, + listall=self.services["listall"], + page=1, + pagesize=self.services["pagesize"], + domainid=self.account.domainid, + zoneid=zones_list[0].id + ) + status = validateList(list_vms_after) + self.assertEquals( + PASS, + status[0], + "VM creation failed" + ) + # Verifying that the size of the list is 1 + self.assertEquals( + 1, + len(list_vms_after), + "VM list count is not matching" + ) + listed_vm = list_vms_after[0] + # Verifying that the details of the Listed VM are same as the VM deployed above + #Creating expected and actual values dictionaries + expected_dict = { + "id":vm_created.id, + "name":vm_created.name, + "displayname":vm_created.displayname, + "state":vm_created.state, + "zoneid":vm_created.zoneid, + "account":vm_created.account, + "template":vm_created.templateid + } + actual_dict = { + "id":listed_vm.id, + "name":listed_vm.name, + "displayname":listed_vm.displayname, + "state":listed_vm.state, + "zoneid":listed_vm.zoneid, + "account":listed_vm.account, + "template":listed_vm.templateid + } + list_vm_status = self.__verify_values( + expected_dict, + actual_dict + ) + self.assertEqual( + True, + list_vm_status, + "Listed VM by Id details are not as expected" + ) + # Listing all the VMs for a user again for non-matching zone + list_vms = VirtualMachine.list( + self.userapiclient, + listall=self.services["listall"], + page=1, + pagesize=self.services["pagesize"], + domainid=self.account.domainid, + zoneid=zones_list[1].id + ) + self.assertIsNone( + list_vms, + "VM's listed for non matching zone" + ) + self.services["virtual_machine"]["zoneid"] = current_zone + self.services["virtual_machine"]["template"] = current_template + return + + @attr(tags=["advanced", "basic", "selfservice"]) + def test_09_list_vm_by_zone_name(self): + """ + @Desc: Test List VM by Zone. + This test case is applicable for a setup having multiple zones. + @Steps: + Step1: Listing all the zones + Step2: Checking if there are multiple zones in the setup. + Continuing below steps only if there are multiple zones + Step3: Listing template for zone + Step4: Listing all the VMs for a user + Step5: Verifying that the size of the list is 0 + Step6: Deploying a VM + Step7: Listing all the VMs for a user again + Step8: Verifying that list size is increased by 1 + Step9: Listing the VM by specifying name of VM created in step6 and matching zone (matching name and zone) + Step10: Verifying that the size of the list is 1 + Step11: Verifying that the details of the listed VM are same as the VM created in step3 + Step12: Listing the VM by specifying name of VM created in step6 and non matching zone (non matching zone) + Step13: Verifying that the size of the list is 0 + Step14: Listing the VM by specifying non matching name and matching zone (non matching name) + Step15: Verifying that the size of the list is 0 + """ + # Listing all the zones available + zones_list = Zone.list(self.apiClient) + status = validateList(zones_list) + self.assertEquals( + PASS, + status[0], + "zones not available in the given setup" + ) + current_zone = self.services["virtual_machine"]["zoneid"] + current_template = self.services["virtual_machine"]["template"] + # Checking if there are multiple zones in the setup. + if not len(zones_list) > 1: + self.debug("Setup is not having multiple Zones") + else: + # Getting the template available under the zone + template = get_template( + self.apiClient, + zones_list[0].id, + self.services["ostype"] + ) + self.assertIsNotNone( + template, + "Template not found for zone" + ) + self.services["virtual_machine"]["zoneid"] = zones_list[0].id + self.services["virtual_machine"]["template"] = template.id + # Listing all the VM's for a User + list_vms_before = VirtualMachine.list( + self.userapiclient, + listall=self.services["listall"], + page=1, + pagesize=self.services["pagesize"], + domainid=self.account.domainid, + zoneid=zones_list[0].id, + account=self.account.name + ) + self.assertIsNone( + list_vms_before, + "Virtual Machine already exists for newly created user" + ) + # Deploying a VM + vm_created = VirtualMachine.create( + self.userapiclient, + self.services["virtual_machine"], + accountid=self.account.name, + domainid=self.account.domainid, + serviceofferingid=self.service_offering.id, + ) + self.assertIsNotNone( + vm_created, + "VM creation failed" + ) + self.cleanup.append(vm_created) + # Listing all the VMs for a user again for matching zone + list_vms_after = VirtualMachine.list( + self.userapiclient, + listall=self.services["listall"], + page=1, + pagesize=self.services["pagesize"], + domainid=self.account.domainid, + zoneid=zones_list[0].id, + account=self.account.name + ) + status = validateList(list_vms_after) + self.assertEquals( + PASS, + status[0], + "VM creation failed" + ) + # Verifying that the size of the list is 1 + self.assertEquals( + 1, + len(list_vms_after), + "VM list count is not matching" + ) + # Listing the VM by specifying name of VM created in above and matching zone + list_vms = VirtualMachine.list( + self.userapiclient, + listall=self.services["listall"], + page=1, + pagesize=self.services["pagesize"], + domainid=self.account.domainid, + zoneid=zones_list[0].id, + name=vm_created.name + ) + status = validateList(list_vms) + self.assertEquals( + PASS, + status[0], + "Listing VM's by name and zone failed" + ) + # Verifying Verifying that the size of the list is 1 + self.assertEquals( + 1, + len(list_vms), + "Count of listed VM's by name and zone is not as expected" + ) + listed_vm = list_vms[0] + # Verifying that the details of the Listed VM are same as the VM deployed above + #Creating expected and actual values dictionaries + expected_dict = { + "id":vm_created.id, + "name":vm_created.name, + "displayname":vm_created.displayname, + "state":vm_created.state, + "zoneid":vm_created.zoneid, + "account":vm_created.account, + "template":vm_created.templateid + } + actual_dict = { + "id":listed_vm.id, + "name":listed_vm.name, + "displayname":listed_vm.displayname, + "state":listed_vm.state, + "zoneid":listed_vm.zoneid, + "account":listed_vm.account, + "template":listed_vm.templateid + } + list_vm_status = self.__verify_values( + expected_dict, + actual_dict + ) + self.assertEqual( + True, + list_vm_status, + "Listed VM by Id details are not as expected" + ) + # Listing the VM by specifying name of VM created in step3 and non matching zone + list_vms = VirtualMachine.list( + self.userapiclient, + listall=self.services["listall"], + page=1, + pagesize=self.services["pagesize"], + domainid=self.account.domainid, + zoneid=zones_list[1].id, + name=vm_created.name + ) + self.assertIsNone( + list_vms, + "VM's listed for non matching zone" + ) + # Listing the VM by specifying non matching name of VM and matching zone + list_vms = VirtualMachine.list( + self.userapiclient, + listall=self.services["listall"], + page=1, + pagesize=self.services["pagesize"], + domainid=self.account.domainid, + zoneid=zones_list[0].id, + name="name" + ) + self.assertIsNone( + list_vms, + "VM's listed for non matching zone" + ) + self.services["virtual_machine"]["zoneid"] = current_zone + self.services["virtual_machine"]["template"] = current_template + return + + @attr(tags=["advanced", "basic", "selfservice"]) + def test_10_list_vm_by_zone_name_state(self): + """ + @Desc: Test List VM by Zone. + @Steps: + Step1: Listing all the VMs for a user + Step2: Verifying that the size of the list is 0 + Step3: Deploying a VM + Step4: Listing all the VMs for a user again + Step5: Verifying that list size is increased by 1 + Step6: Listing the VM by specifying name of VM created in step3 and matching zone and state as Running + Step7: Verifying that the size of the list is 1 + Step8: Verifying that the details of the listed VM are same as the VM created in step3 + Step9: Listing the VM by specifying name of VM created in step3 and matching zone and state as Stopped + Step10: Verifying that the size of the list is 0 + Step11: Listing the VM by name, Zone and account + Step12: Verifying that the size of the list is 1 + Step13: Verifying that the details of the listed VM are same as the VM created in step3 + """ + # Listing all the VM's for a User + list_vms_before = VirtualMachine.list( + self.userapiclient, + listall=self.services["listall"], + page=1, + pagesize=self.services["pagesize"], + domainid=self.account.domainid, + zoneid=self.zone.id, + account=self.account.name + ) + self.assertIsNone( + list_vms_before, + "Virtual Machine already exists for newly created user" + ) + # Deploying a VM + vm_created = VirtualMachine.create( + self.userapiclient, + self.services["virtual_machine"], + accountid=self.account.name, + domainid=self.account.domainid, + serviceofferingid=self.service_offering.id, + ) + self.assertIsNotNone( + vm_created, + "VM creation failed" + ) + self.cleanup.append(vm_created) + # Listing all the VMs for a user again for matching zone + list_vms_after = VirtualMachine.list( + self.userapiclient, + listall=self.services["listall"], + page=1, + pagesize=self.services["pagesize"], + domainid=self.account.domainid, + zoneid=self.zone.id, + account=self.account.name + ) + status = validateList(list_vms_after) + self.assertEquals( + PASS, + status[0], + "VM creation failed" + ) + # Verifying that the size of the list is 1 + self.assertEquals( + 1, + len(list_vms_after), + "VM list count is not matching" + ) + # Listing the VM by specifying name of VM created in step3 and matching zone and state as Running + list_vms = VirtualMachine.list( + self.userapiclient, + listall=self.services["listall"], + page=1, + pagesize=self.services["pagesize"], + domainid=self.account.domainid, + zoneid=self.zone.id, + name=vm_created.name, + state="Running" + ) + status = validateList(list_vms) + self.assertEquals( + PASS, + status[0], + "Listing VM's by name and zone failed" + ) + # Verifying Verifying that the size of the list is 1 + self.assertEquals( + 1, + len(list_vms), + "Count of listed VM's by name, zone and state is not as expected" + ) + listed_vm = list_vms[0] + # Verifying that the details of the Listed VM are same as the VM deployed above + #Creating expected and actual values dictionaries + expected_dict = { + "id":vm_created.id, + "name":vm_created.name, + "displayname":vm_created.displayname, + "state":vm_created.state, + "zoneid":vm_created.zoneid, + "account":vm_created.account, + "template":vm_created.templateid + } + actual_dict = { + "id":listed_vm.id, + "name":listed_vm.name, + "displayname":listed_vm.displayname, + "state":listed_vm.state, + "zoneid":listed_vm.zoneid, + "account":listed_vm.account, + "template":listed_vm.templateid + } + list_vm_status = self.__verify_values( + expected_dict, + actual_dict + ) + self.assertEqual( + True, + list_vm_status, + "Listed VM by Id details are not as expected" + ) + # Listing the VM by specifying name of VM created in step3, zone and State as Stopped + list_vms = VirtualMachine.list( + self.userapiclient, + listall=self.services["listall"], + page=1, + pagesize=self.services["pagesize"], + domainid=self.account.domainid, + zoneid=self.zone.id, + name=vm_created.name, + state="Stopped" + ) + self.assertIsNone( + list_vms, + "VM's listed for non matching zone" + ) + # Listing the VM by name, zone and account + list_vms = VirtualMachine.list( + self.userapiclient, + listall=self.services["listall"], + page=1, + pagesize=self.services["pagesize"], + domainid=self.account.domainid, + zoneid=self.zone.id, + name=vm_created.name, + account=self.account.name + ) + status = validateList(list_vms) + self.assertEquals( + PASS, + status[0], + "Listing VM's by name, account and zone failed" + ) + # Verifying Verifying that the size of the list is 1 + self.assertEquals( + 1, + len(list_vms), + "Count of listed VM's by name, zone and account is not as expected" + ) + listed_vm = list_vms[0] + # Verifying that the details of the Listed VM are same as the VM deployed above + #Creating expected and actual values dictionaries + expected_dict = { + "id":vm_created.id, + "name":vm_created.name, + "displayname":vm_created.displayname, + "state":vm_created.state, + "zoneid":vm_created.zoneid, + "account":vm_created.account, + "template":vm_created.templateid + } + actual_dict = { + "id":listed_vm.id, + "name":listed_vm.name, + "displayname":listed_vm.displayname, + "state":listed_vm.state, + "zoneid":listed_vm.zoneid, + "account":listed_vm.account, + "template":listed_vm.templateid + } + list_vm_status = self.__verify_values( + expected_dict, + actual_dict + ) + self.assertEqual( + True, + list_vm_status, + "Listed VM by Id details are not as expected" + ) + return + + @attr(tags=["advanced", "basic", "provisioning"]) + def test_11_register_reset_vm_sshkey(self): + """ + @Desc: Test to verify registering and reset of SSH Key for VM + @Steps: + Step1: Deploying a VM + Step2: Stopping the VM deployed in step1 + Step3: Listing all the SSH Key pairs + Step4: Registering a SSH Key pair + Step5: Listing all the SSh Key pairs again + Step6: Verifying that the key pairs list is increased by 1 + Step7: Resetting the VM SSH Key to the key pair registered in step4 + Step8: Verifying that the registered SSH Key pair is set to the VM + """ + # Listing all the VM's for a User + list_vms_before = VirtualMachine.list( + self.userapiclient, + listall=self.services["listall"], + ) + self.assertIsNone( + list_vms_before, + "Virtual Machine already exists for newly created user" + ) + # Deploying a VM + vm_created = VirtualMachine.create( + self.userapiclient, + self.services["virtual_machine"], + accountid=self.account.name, + domainid=self.account.domainid, + serviceofferingid=self.service_offering.id, + ) + self.assertIsNotNone( + vm_created, + "VM creation failed" + ) + self.cleanup.append(vm_created) + # Listing all the VMs for a user again + list_vms_after = VirtualMachine.list( + self.userapiclient, + listall=self.services["listall"], + ) + status = validateList(list_vms_after) + self.assertEquals( + PASS, + status[0], + "VM creation failed" + ) + # Verifying that the size of the list is 1 + self.assertEquals( + 1, + len(list_vms_after), + "VM list count is not matching" + ) + # Stopping the VM deployed above + vm_created.stop( + self.userapiclient, + forced=True + ) + # Listing all the SSH Key pairs + list_keypairs_before = SSHKeyPair.list( + self.userapiclient + ) + list_keypairs_before_size = 0 + if list_keypairs_before is not None: + list_keypairs_before_size = len(list_keypairs_before) + + # Registering new Key pair + new_keypair = SSHKeyPair.register( + self.userapiclient, + name="keypair1", + publickey="ssh-rsa: e6:9a:1e:b5:98:75:88:5d:56:bc:92:7b:43:48:05:b2" + ) + self.assertIsNotNone( + new_keypair, + "New Key pair generation failed" + ) + self.assertEquals( + "keypair1", + new_keypair.name, + "Key Pair not created with given name" + ) + # Listing all the SSH Key pairs again + list_keypairs_after = SSHKeyPair.list( + self.userapiclient + ) + status = validateList(list_keypairs_after) + self.assertEquals( + PASS, + status[0], + "Listing of Key pairs failed" + ) + # Verifying that list size is increased by 1 + self.assertEquals( + list_keypairs_before_size + 1, + len(list_keypairs_after), + "List count is not matching" + ) + # Resetting the VM SSH key to the Key pair created above + vm_created.resetSshKey( + self.userapiclient, + keypair=new_keypair.name + ) + # Listing VM details again + list_vm = VirtualMachine.list( + self.userapiclient, + id=vm_created.id + ) + status = validateList(list_vm) + self.assertEquals( + PASS, + status[0], + "Listing of VM failed" + ) + self.assertEquals( + 1, + len(list_vm), + "VMs list is not as expected" + ) + # Verifying that VM's SSH keypair is set to newly created keypair + self.assertEquals( + new_keypair.name, + list_vm[0].keypair, + "VM is not set to newly created SSH Key pair" + ) + return + + @attr(tags=["advanced", "provisioning"]) + def test_12_vm_nics(self): + """ + @Desc: Test to verify Nics for a VM + @Steps: + Step1: Deploying a VM + Step2: Listing all the Networks + Step3: Verifying that the list size is 1 + Step4: Creating 1 network + Step5: Listing all the networks again + Step6: Verifying that the list size is 2 + Step7: Verifying that VM deployed in step1 has only 1 nic + and it is same as network listed in step3 + Step8: Adding the networks created in step4 to VM deployed in step1 + Step9: Verifying that VM deployed in step1 has 2 nics + Step10: Verifying that isdefault is set to true for only 1 nic + Step11: Verifying that isdefault is set to true for the Network created when deployed a VM + Step12: Making the nic created in step4 as default nic + Step13: Verifying that isdefault is set to true for only 1 nic + Step14: Verifying that the isdefault is set to true for the nic created in step4 + Step15: Removing the non-default nic from VM + Step16: Verifying that VM deployed in step1 has only 1 nic + """ + # Listing all the VM's for a User + list_vms_before = VirtualMachine.list( + self.userapiclient, + listall=self.services["listall"], + ) + self.assertIsNone( + list_vms_before, + "Virtual Machine already exists for newly created user" + ) + # Deploying a VM + vm_created = VirtualMachine.create( + self.userapiclient, + self.services["virtual_machine"], + accountid=self.account.name, + domainid=self.account.domainid, + serviceofferingid=self.service_offering.id, + ) + self.assertIsNotNone( + vm_created, + "VM creation failed" + ) + self.cleanup.append(vm_created) + # Listing all the VMs for a user again + list_vms_after = VirtualMachine.list( + self.userapiclient, + listall=self.services["listall"], + ) + status = validateList(list_vms_after) + self.assertEquals( + PASS, + status[0], + "VM creation failed" + ) + # Verifying that the size of the list is 1 + self.assertEquals( + 1, + len(list_vms_after), + "VM list count is not matching" + ) + # Listing all the networks before + list_network_before = Network.list( + self.userapiclient, + isdefault="true", + zoneid=self.zone.id, + account=self.account.name, + domainid=self.domain.id + ) + status = validateList(list_network_before) + self.assertEquals( + PASS, + status[0], + "Default Network not created when deploying a VM" + ) + # Verifying that only 1 network is created while deploying a VM + self.assertEquals( + 1, + len(list_network_before), + "More than 1 default network exists" + ) + network1 = list_network_before[0] + # Listing Network Offerings + network_offerings_list = NetworkOffering.list( + self.apiClient, + forvpc="false", + guestiptype="Isolated", + state="Enabled", + supportedservices="SourceNat", + zoneid=self.zone.id + ) + self.assertIsNotNone( + network_offerings_list, + "Isolated Network Offerings with sourceNat enabled are not found" + ) + # Creating one more network + network2 = Network.create( + self.userapiclient, + self.services["network"], + accountid=self.account.name, + domainid=self.domain.id, + networkofferingid=network_offerings_list[0].id, + zoneid=self.zone.id + ) + self.assertIsNotNone( + network2, + "Network creation failed" + ) + self.cleanup.append(network2) + # Listing all the networks again + list_network_after = Network.list( + self.userapiclient, + zoneid=self.zone.id, + account=self.account.name, + domainid=self.domain.id + ) + status = validateList(list_network_after) + self.assertEquals( + PASS, + status[0], + "List of Networks failed" + ) + # Verifying that list size is 2 + self.assertEquals( + 2, + len(list_network_after), + "More than 1 default network exists" + ) + # Verifying that VM created is having only 1 nic + vm_nics_before = vm_created.nic + self.assertIsNotNone( + vm_nics_before, + "Nic not found for the VM deployed" + ) + self.assertEquals( + 1, + len(vm_nics_before), + "VM Nic count is not matching" + ) + # Verifying that the nic is same as the default network listed above + self.assertEquals( + network1.id, + vm_nics_before[0].networkid, + "Default NIC for VM is not as expected" + ) + # Adding network2 created above to VM + VirtualMachine.add_nic( + vm_created, + self.userapiclient, + network2.id + ) + # Listing the Vm details again + list_vms_after = VirtualMachine.list( + self.userapiclient, + id=vm_created.id + ) + status = validateList(list_vms_after) + self.assertEquals( + PASS, + status[0], + "Listing of VM failed" + ) + vm = list_vms_after[0] + # Verifying that VM nics size is 2 now + vm_nics_after = vm.nic + self.assertIsNotNone( + vm_nics_after, + "Nic not found for the deployed VM" + ) + self.assertEquals( + 2, + len(vm_nics_after), + "VM NIC's count is not matching" + ) + # Verifying that isdefault is set to true for only 1 nic + default_count = 0 + for i in range(0, len(vm_nics_after)): + if vm_nics_after[i].isdefault is True: + default_count = default_count + 1 + default_nic = vm_nics_after[i] + else: + non_default_nic = vm_nics_after[i] + self.assertEquals( + 1, + default_count, + "Default NIC count is not matching" + ) + # Verifying that default NIC is same the network created when VM is deployed + self.assertEquals( + network1.id, + default_nic.networkid, + "Default NIC is not matching for VM" + ) + # Updating network 2 as default NIC + vm_created.update_default_nic( + self.userapiclient, + non_default_nic.id + ) + # Listing the Vm details again + list_vms_after = VirtualMachine.list( + self.userapiclient, + id=vm_created.id + ) + status = validateList(list_vms_after) + self.assertEquals( + PASS, + status[0], + "Listing of VM failed" + ) + vm = list_vms_after[0] + # Verifying that VM nics size is 2 now + vm_nics_after = vm.nic + self.assertIsNotNone( + vm_nics_after, + "Nic not found for the deployed VM" + ) + self.assertEquals( + 2, + len(vm_nics_after), + "VM NIC's count is not matching" + ) + # Verifying that isdefault is set to true for only 1 nic + default_count = 0 + for i in range(0, len(vm_nics_after)): + if vm_nics_after[i].isdefault is True: + default_count = default_count + 1 + default_nic = vm_nics_after[i] + else: + non_default_nic = vm_nics_after[i] + + self.assertEquals( + 1, + default_count, + "Default NIC count is not matching" + ) + # Verifying that default NIC is same the newly updated network (network 2) + self.assertEquals( + network2.id, + default_nic.networkid, + "Default NIC is not matching for VM" + ) + # Deleting non default NIC + vm_created.remove_nic( + self.userapiclient, + non_default_nic.id + ) + # Listing the Vm details again + list_vms_after = VirtualMachine.list( + self.userapiclient, + id=vm_created.id + ) + status = validateList(list_vms_after) + self.assertEquals( + PASS, + status[0], + "Listing of VM failed" + ) + vm = list_vms_after[0] + # Verifying that VM nics size is 1 now + vm_nics_after = vm.nic + self.assertIsNotNone( + vm_nics_after, + "Nic not found for the deployed VM" + ) + self.assertEquals( + 1, + len(vm_nics_after), + "VM NIC's count is not matching" + ) + # Verifying the nic network is same as the default nic network + self.assertEquals( + network2.id, + vm_nics_after[0].networkid, + "VM NIC is not same as expected" + ) + return + +class TestInstances(cloudstackTestCase): + + @classmethod + def setUpClass(cls): + try: + cls._cleanup = [] + cls.testClient = super(TestInstances, cls).getClsTestClient() + cls.api_client = cls.testClient.getApiClient() + cls.services = cls.testClient.getParsedTestDataConfig() + + # Get Domain, Zone, Template + cls.domain = get_domain(cls.api_client) + cls.zone = get_zone(cls.api_client) + cls.template = get_template( + cls.api_client, + cls.zone.id, + cls.services["ostype"] + ) + if cls.zone.localstorageenabled: + cls.storagetype = 'local' + cls.services["service_offerings"]["tiny"]["storagetype"] = 'local' + cls.services["disk_offering"]["storagetype"] = 'local' + else: + cls.storagetype = 'shared' + cls.services["service_offerings"]["tiny"]["storagetype"] = 'shared' + cls.services["disk_offering"]["storagetype"] = 'shared' + + cls.services['mode'] = cls.zone.networktype + cls.services["virtual_machine"]["hypervisor"] = cls.testClient.getHypervisorInfo() + cls.services["virtual_machine"]["zoneid"] = cls.zone.id + cls.services["virtual_machine"]["template"] = cls.template.id + cls.services["custom_volume"]["zoneid"] = cls.zone.id + + # Creating Disk offering, Service Offering and Account + cls.disk_offering = DiskOffering.create( + cls.api_client, + cls.services["disk_offering"] + ) + cls._cleanup.append(cls.disk_offering) + cls.service_offering = ServiceOffering.create( + cls.api_client, + cls.services["service_offerings"]["tiny"] + ) + cls._cleanup.append(cls.service_offering) + cls.account = Account.create( + cls.api_client, + cls.services["account"], + domainid=cls.domain.id + ) + # Getting authentication for user in newly created Account + cls.user = cls.account.user[0] + cls.userapiclient = cls.testClient.getUserApiClient(cls.user.username, cls.domain.name) + # Updating resource Limits + for i in range(0,12): + Resources.updateLimit( + cls.api_client, + account=cls.account.name, + domainid=cls.domain.id, + max=-1, + resourcetype=i + ) + cls._cleanup.append(cls.account) + except Exception as e: + cls.tearDownClass() + raise Exception("Warning: Exception in setup : %s" % e) + return + + def setUp(self): + + self.apiClient = self.testClient.getApiClient() + self.cleanup = [] + + def tearDown(self): + #Clean up, terminate the created resources + cleanup_resources(self.apiClient, self.cleanup) + return + + @classmethod + def tearDownClass(cls): + try: + cleanup_resources(cls.api_client, cls._cleanup) + except Exception as e: + raise Exception("Warning: Exception during cleanup : %s" % e) + + return + + def __verify_values(self, expected_vals, actual_vals): + """ + @Desc: Function to verify expected and actual values + @Steps: + Step1: Initializing return flag to True + Step1: Verifying length of expected and actual dictionaries is matching. + If not matching returning false + Step2: Listing all the keys from expected dictionary + Step3: Looping through each key from step2 and verifying expected and actual dictionaries have same value + If not making return flag to False + Step4: returning the return flag after all the values are verified + """ + return_flag = True + + if len(expected_vals) != len(actual_vals): + return False + + keys = expected_vals.keys() + for i in range(0, len(expected_vals)): + exp_val = expected_vals[keys[i]] + act_val = actual_vals[keys[i]] + if exp_val == act_val: + return_flag = return_flag and True + else: + return_flag = return_flag and False + self.debug("expected Value: %s, is not matching with actual value: %s" % ( + exp_val, + act_val + )) + return return_flag + + @attr(tags=["advanced", "basic", "provisioning"]) + def test_13_attach_detach_iso(self): + """ + @Desc: Test Attach ISO to VM and Detach ISO from VM. + @Steps: + Step1: Listing all the VMs for a user + Step2: Verifying that the size of the list is 0 + Step3: Deploying a VM + Step4: Listing all the VMs for a user again + Step5: Verifying that list size is increased by 1 + Step6: Listing all the ready ISO's + Step7: If size of the list is >= 1 continuing to next steps + Step8: Attaching the ISO listed to VM deployed in Step3 + Step9: Verifying that the attached ISO details are associated with VM + Step10: Detaching the ISO attached in step8 + Step11: Verifying that detached ISO details are not associated with VM + """ + # Listing all the VM's for a User + list_vms_before = VirtualMachine.list( + self.userapiclient, + listall=self.services["listall"], + page=1, + pagesize=self.services["pagesize"], + domainid=self.account.domainid, + zoneid=self.zone.id, + account=self.account.name + ) + self.assertIsNone( + list_vms_before, + "Virtual Machine already exists for newly created user" + ) + # Deploying a VM + vm_created = VirtualMachine.create( + self.userapiclient, + self.services["virtual_machine"], + accountid=self.account.name, + domainid=self.account.domainid, + serviceofferingid=self.service_offering.id, + ) + self.assertIsNotNone( + vm_created, + "VM creation failed" + ) + self.cleanup.append(vm_created) + # Listing all the VMs for a user again for matching zone + list_vms_after = VirtualMachine.list( + self.userapiclient, + listall=self.services["listall"], + page=1, + pagesize=self.services["pagesize"], + domainid=self.account.domainid, + zoneid=self.zone.id, + account=self.account.name + ) + status = validateList(list_vms_after) + self.assertEquals( + PASS, + status[0], + "VM creation failed" + ) + # Verifying that the size of the list is 1 + self.assertEquals( + 1, + len(list_vms_after), + "VM list count is not matching" + ) + # Listing the ISO's in ready state + isos_list = Iso.list( + self.userapiclient, + isready="true", + isofilter="executable", + zoneid=self.zone.id + ) + # Verifying if size of the list is >= 1 + if isos_list is not None: + iso_toattach = isos_list[0] + # Attaching ISO listed to VM deployed + VirtualMachine.attach_iso( + vm_created, + self.userapiclient, + iso_toattach + ) + list_vm = VirtualMachine.list( + self.userapiclient, + id=vm_created.id + ) + status = validateList(list_vm) + self.assertEquals( + PASS, + status[0], + "VM listing by Id failed" + ) + # Verifying that attached ISO details are present in VM + self.assertEquals( + iso_toattach.name, + list_vm[0].isoname, + "Attached ISO name is not matching" + ) + self.assertEquals( + iso_toattach.displaytext, + list_vm[0].isodisplaytext, + "Attached ISO display is not matching" + ) + # Detaching ISO from VM + VirtualMachine.detach_iso( + vm_created, + self.userapiclient + ) + list_vm = VirtualMachine.list( + self.userapiclient, + id=vm_created.id + ) + status = validateList(list_vm) + self.assertEquals( + PASS, + status[0], + "VM listing by Id failed" + ) + # Verifying that ISO details are NOT present in VM + self.assertIsNone( + list_vm[0].isoname, + "ISO not detached from VM" + ) + else: + self.fail("Executable ISO in Ready is not found in the given setup") + + return + + @attr(tags=["advanced", "basic", "provisioning"]) + def test_14_vm_snapshot_pagination(self): + """ + @Desc: Test VM Snapshots pagination. + @Steps: + Step1: Deploying a VM + Step2: Listing all the Snapshots of the VM deployed in Step 1 + Step3: Verifying that the list size is 0 + Step4: Creating (pagesize + 1) number of Snapshots for the VM + Step5: Listing all the Snapshots of the VM deployed in Step 1 + Step6: Verifying that the list size is (pagesize + 1) + Step7: Listing all the VM snapshots in Page 1 with page size + Step8: Verifying that size of the list is same as page size + Step9: Listing all the VM snapshots in Page 2 with page size + Step10: Verifying that size of the list is 1 + Step11: Deleting VM snapshot in page 2 + Step12: Listing all the VM snapshots in Page 2 with page size + Step13: Verifying that size of the list is 0 + """ + # Listing all the VM's for a User + list_vms_before = VirtualMachine.list( + self.userapiclient, + listall=self.services["listall"], + ) + self.assertIsNone( + list_vms_before, + "Virtual Machine already exists for newly created user" + ) + # Deploying a VM + vm_created = VirtualMachine.create( + self.userapiclient, + self.services["virtual_machine"], + accountid=self.account.name, + domainid=self.account.domainid, + serviceofferingid=self.service_offering.id, + ) + self.assertIsNotNone( + vm_created, + "VM creation failed" + ) + self.cleanup.append(vm_created) + # Listing all the VMs for a user again + list_vms_after = VirtualMachine.list( + self.userapiclient, + listall=self.services["listall"], + ) + status = validateList(list_vms_after) + self.assertEquals( + PASS, + status[0], + "VM creation failed" + ) + # Verifying that the size of the list is 1 + self.assertEquals( + 1, + len(list_vms_after), + "VM list count is not matching" + ) + # Listing all the VM snapshots for VM deployed above + list_snapshots_before = VmSnapshot.list( + self.userapiclient, + listall=self.services["listall"], + virtualmachineid=vm_created.id + ) + # Verifying that the VM snapshot list is None + self.assertIsNone( + list_snapshots_before, + "Snapshots already exists for newly created VM" + ) + # Creating pagesize + 1 number of VM snapshots + for i in range(0, (self.services["pagesize"] + 1)): + snapshot_created = VmSnapshot.create( + self.userapiclient, + vm_created.id, + ) + self.assertIsNotNone( + snapshot_created, + "Snapshot creation failed" + ) + + # Listing all the VM snapshots for VM again + list_snapshots_after = VmSnapshot.list( + self.userapiclient, + listall=self.services["listall"], + virtualmachineid=vm_created.id + ) + status = validateList(list_snapshots_after) + self.assertEquals( + PASS, + status[0], + "VM Snapshots creation failed" + ) + self.assertEquals( + self.services["pagesize"] + 1, + len(list_snapshots_after), + "Count of VM Snapshots is not matching" + ) + # Listing all the VM snapshots in Page 1 with page size + list_snapshots_page1 = VmSnapshot.list( + self.userapiclient, + listall=self.services["listall"], + virtualmachineid=vm_created.id, + page=1, + pagesize=self.services["pagesize"], + ) + status = validateList(list_snapshots_page1) + self.assertEquals( + PASS, + status[0], + "Listing of VM Snapshots failed in page 1" + ) + # Verifying the list size is equal to pagesize + self.assertEquals( + self.services["pagesize"], + len(list_snapshots_page1), + "List VM Snapshot count is not matching in page 1" + ) + # Listing all the VM Snapshots in page 2 + list_snapshots_page2 = VmSnapshot.list( + self.userapiclient, + listall=self.services["listall"], + virtualmachineid=vm_created.id, + page=2, + pagesize=self.services["pagesize"], + ) + status = validateList(list_snapshots_page2) + self.assertEquals( + PASS, + status[0], + "Listing of VM Snapshots failed in page 2" + ) + # Verifying the list size is equal to 1 + self.assertEquals( + 1, + len(list_snapshots_page2), + "List VM Snapshot count is not matching in page 2" + ) + # Deleting VM Snapshot in page 2 + VmSnapshot.deleteVMSnapshot( + self.userapiclient, + snapshot_created.id + ) + # Listing all the VM Snapshots in page 2 again + list_snapshots_page2 = VmSnapshot.list( + self.userapiclient, + listall=self.services["listall"], + virtualmachineid=vm_created.id, + page=2, + pagesize=self.services["pagesize"], + ) + # Verifying the list size is equal to 0 + self.assertIsNone( + list_snapshots_page2, + "VM Snapshots exists in page 2" + ) + return + + @attr(tags=["advanced", "basic", "provisioning"]) + def test_15_revert_vm_to_snapshot(self): + """ + @Desc: Test Revert VM to Snapshot functionality. + @Steps: + Step1: Deploying a VM + Step2: Listing all the Snapshots of the VM deployed in Step 1 + Step3: Verifying that the list size is 0 + Step4: Creating 2 Snapshots for the VM + Step5: Listing all the Snapshots of the VM deployed in Step 1 + Step6: Verifying that the list size is 2 + Step7: Verifying that only 1 snapshot is have current flag set to True + Step8: Verifying that the VM snapshot with current flag set as true is the latest snapshot created + Step9: Reverting VM to snapshot having current flag as false (non current snapshot) + Step10: Verifying that only 1 VM snapshot is having current flag set as true. + Step11: Verifying that the VM Snapshot with current flag set to true is the reverted snapshot in Step 8 + """ + # Listing all the VM's for a User + list_vms_before = VirtualMachine.list( + self.userapiclient, + listall=self.services["listall"], + ) + self.assertIsNone( + list_vms_before, + "Virtual Machine already exists for newly created user" + ) + # Deploying a VM + vm_created = VirtualMachine.create( + self.userapiclient, + self.services["virtual_machine"], + accountid=self.account.name, + domainid=self.account.domainid, + serviceofferingid=self.service_offering.id, + ) + self.assertIsNotNone( + vm_created, + "VM creation failed" + ) + self.cleanup.append(vm_created) + # Listing all the VMs for a user again + list_vms_after = VirtualMachine.list( + self.userapiclient, + listall=self.services["listall"], + ) + status = validateList(list_vms_after) + self.assertEquals( + PASS, + status[0], + "VM creation failed" + ) + # Verifying that the size of the list is 1 + self.assertEquals( + 1, + len(list_vms_after), + "VM list count is not matching" + ) + # Listing all the VM snapshots for VM deployed above + list_snapshots_before = VmSnapshot.list( + self.userapiclient, + listall=self.services["listall"], + virtualmachineid=vm_created.id + ) + # Verifying that the VM snapshot list is None + self.assertIsNone( + list_snapshots_before, + "Snapshots already exists for newly created VM" + ) + # Creating 2 of VM snapshots + snapshot1 = VmSnapshot.create( + self.userapiclient, + vm_created.id, + ) + self.assertIsNotNone( + snapshot1, + "Snapshot creation failed" + ) + snapshot2 = VmSnapshot.create( + self.userapiclient, + vm_created.id, + ) + self.assertIsNotNone( + snapshot2, + "Snapshot creation failed" + ) + # Listing all the VM snapshots for VM again + list_snapshots_after = VmSnapshot.list( + self.userapiclient, + listall=self.services["listall"], + virtualmachineid=vm_created.id + ) + status = validateList(list_snapshots_after) + self.assertEquals( + PASS, + status[0], + "VM Snapshots creation failed" + ) + self.assertEquals( + 2, + len(list_snapshots_after), + "Count of VM Snapshots is not matching" + ) + # Verifying that only 1 snapshot is having current flag set to true + # and that snapshot is the latest snapshot created (snapshot2) + current_count = 0 + for i in range(0, len(list_snapshots_after)): + if(list_snapshots_after[i].current is True): + current_count = current_count + 1 + current_snapshot = list_snapshots_after[i] + + self.assertEquals( + 1, + current_count, + "count of VM Snapshot with current flag as true is not matching" + ) + self.assertEquals( + snapshot2.id, + current_snapshot.id, + "Latest snapshot taken is not marked as current" + ) + # Reverting the VM to Snapshot 1 + VmSnapshot.revertToSnapshot( + self.userapiclient, + snapshot1.id + ) + # Listing the VM snapshots again + list_snapshots_after = VmSnapshot.list( + self.userapiclient, + listall=self.services["listall"], + virtualmachineid=vm_created.id + ) + status = validateList(list_snapshots_after) + self.assertEquals( + PASS, + status[0], + "VM Snapshots creation failed" + ) + self.assertEquals( + 2, + len(list_snapshots_after), + "Count of VM Snapshots is not matching" + ) + # Verifying that only 1 snapshot is having current flag set to true + # and that snapshot is snapshot1 + current_count = 0 + for i in range(0, len(list_snapshots_after)): + if(list_snapshots_after[i].current is True): + current_count = current_count + 1 + current_snapshot = list_snapshots_after[i] + self.assertEquals( + 1, + current_count, + "count of VM Snapshot with current flag as true is not matching" + ) + self.assertEquals( + snapshot1.id, + current_snapshot.id, + "Current flag was set properly after reverting the VM to snapshot" + ) + return + + @attr(tags=["advanced", "basic", "selfservice"]) + def test_16_list_vm_volumes_pagination(self): + """ + @Desc: Test to verify pagination of Volumes for a VM + @Steps: + Step1: Deploying a VM + Step2: Listing all the Volumes of the VM deployed in Step 1 + Step3: Verifying that the list size is 1 + Step4: Creating page size number of volumes + Step5: Attaching all the volumes created in step4 to VM deployed in Step1 + Step6: Listing all the Volumes for the VM in step1 + Step7: Verifying that the list size is equal to page size + 1 + Step8: Listing all the volumes of VM in page 1 + Step9: Verifying that the list size is equal to page size + Step10: Listing all the Volumes in Page 2 + Step11: Verifying that the list size is 1 + Step12: Detaching the volume from the VM + Step13: Listing all the Volumes in Page 2 + Step14: Verifying that list size is 0 + """ + # Listing all the VM's for a User + list_vms_before = VirtualMachine.list( + self.userapiclient, + listall=self.services["listall"], + ) + self.assertIsNone( + list_vms_before, + "Virtual Machine already exists for newly created user" + ) + # Deploying a VM + vm_created = VirtualMachine.create( + self.userapiclient, + self.services["virtual_machine"], + accountid=self.account.name, + domainid=self.account.domainid, + serviceofferingid=self.service_offering.id, + ) + self.assertIsNotNone( + vm_created, + "VM creation failed" + ) + self.cleanup.append(vm_created) + # Listing all the VMs for a user again + list_vms_after = VirtualMachine.list( + self.userapiclient, + listall=self.services["listall"], + ) + status = validateList(list_vms_after) + self.assertEquals( + PASS, + status[0], + "VM creation failed" + ) + # Verifying that the size of the list is 1 + self.assertEquals( + 1, + len(list_vms_after), + "VM list count is not matching" + ) + # Listing all the Volumes for the VM deployed + list_volumes_before = Volume.list( + self.userapiclient, + listall=self.services["listall"], + virtualmachineid=vm_created.id + ) + status = validateList(list_volumes_before) + self.assertEquals( + PASS, + status[0], + "Root volume is not created for VM deployed" + ) + # Verifying the size of the list is 1 + self.assertEquals( + 1, + len(list_volumes_before), + "Volumes count is not matching" + ) + # Creating Page size number of volumes + for i in range(0, self.services["pagesize"]): + volume_created = Volume.create( + self.userapiclient, + self.services["volume"], + zoneid=self.zone.id, + diskofferingid=self.disk_offering.id + ) + self.assertIsNotNone( + volume_created, + "Volume is not created" + ) + self.cleanup.append(volume_created) + # Attaching all the volumes created to VM + vm_created.attach_volume( + self.userapiclient, + volume_created + ) + + # List all the volumes for the VM again + list_volumes_after = Volume.list( + self.userapiclient, + listall=self.services["listall"], + virtualmachineid=vm_created.id + ) + status = validateList(list_volumes_after) + self.assertEquals( + PASS, + status[0], + "Volumes are not listed" + ) + # Verifying that size of the list is equal to page size + 1 + self.assertEquals( + self.services["pagesize"] + 1, + len(list_volumes_after), + "VM's volume count is not matching" + ) + # Listing all the volumes for a VM in page 1 + list_volumes_page1 = Volume.list( + self.userapiclient, + listall=self.services["listall"], + virtualmachineid=vm_created.id, + page=1, + pagesize=self.services["pagesize"] + ) + status = validateList(list_volumes_page1) + self.assertEquals( + PASS, + status[0], + "Volumes not listed in page1" + ) + # Verifying that list size is equal to page size + self.assertEquals( + self.services["pagesize"], + len(list_volumes_page1), + "VM's volume count is not matching in page 1" + ) + # Listing all the volumes for a VM in page 2 + list_volumes_page2 = Volume.list( + self.userapiclient, + listall=self.services["listall"], + virtualmachineid=vm_created.id, + page=2, + pagesize=self.services["pagesize"] + ) + status = validateList(list_volumes_page2) + self.assertEquals( + PASS, + status[0], + "Volumes not listed in page2" + ) + # Verifying that list size is equal to 1 + self.assertEquals( + 1, + len(list_volumes_page2), + "VM's volume count is not matching in page 1" + ) + # Detaching 1 volume from VM + vm_created.detach_volume( + self.userapiclient, + volume_created + ) + # Listing all the volumes for a VM in page 2 again + list_volumes_page2 = Volume.list( + self.userapiclient, + listall=self.services["listall"], + virtualmachineid=vm_created.id, + page=2, + pagesize=self.services["pagesize"] + ) + # Verifying that there are no volumes present in page 2 + self.assertIsNone( + list_volumes_page2, + "Volumes listed in page 2" + ) + return + + @attr(tags=["advanced", "basic", "provisioning"]) + def test_17_running_vm_scaleup(self): + """ + @Desc: Test to verify change service for Running VM + @Steps: + Step1: Checking if dynamic scaling of virtual machines is enabled in zone and template. + If yes then continuing. + If not then printing message that scale up is not possible for Running VM + Step2: Deploying a VM + Step3: Listing all the existing service offerings + Step4: If there is a matching Service Offering for scale-up of running VM + use that service offering. If not create one service offering for scale up. + Step5: Perform change service (scale up) the Running VM deployed in step1 + Step6: Verifying that VM's service offerings is changed + """ + # Checking if Dynamic scaling of VM is supported or not + list_config = Configurations.list( + self.apiClient, + zoneid=self.zone.id, + name="enable.dynamic.scale.vm" + ) + status = validateList(list_config) + self.assertEquals( + PASS, + status[0], + "Listing of configuration failed" + ) + # Checking if dynamic scaling is allowed in Zone and Template + if not ((list_config[0].value is True) and (self.template.isdynamicallyscalable)): + self.debug("Scale up of Running VM is not possible as Zone/Template does not support") + else: + # Listing all the VM's for a User + list_vms_before = VirtualMachine.list( + self.userapiclient, + listall=self.services["listall"], + ) + self.assertIsNone( + list_vms_before, + "Virtual Machine already exists for newly created user" + ) + # Deploying a VM + vm_created = VirtualMachine.create( + self.userapiclient, + self.services["virtual_machine"], + accountid=self.account.name, + domainid=self.account.domainid, + serviceofferingid=self.service_offering.id, + ) + self.assertIsNotNone( + vm_created, + "VM creation failed" + ) + self.cleanup.append(vm_created) + # Listing details of current Service Offering + vm_so_list = ServiceOffering.list( + self.userapiclient, + id=vm_created.serviceofferingid + ) + status = validateList(vm_so_list) + self.assertEquals( + PASS, + status[0], + "Listing of VM Service offering failed" + ) + current_so = vm_so_list[0] + # Listing all the VMs for a user again + list_vms_after = VirtualMachine.list( + self.userapiclient, + listall=self.services["listall"], + ) + status = validateList(list_vms_after) + self.assertEquals( + PASS, + status[0], + "VM creation failed" + ) + # Verifying that the size of the list is 1 + self.assertEquals( + 1, + len(list_vms_after), + "VM list count is not matching" + ) + # Listing all the existing service offerings + service_offerings_list = ServiceOffering.list( + self.userapiclient, + virtualmachineid=vm_created.id + ) + # Verifying if any Service offering available for scale up of VM + so_exists = False + if service_offerings_list is not None: + for i in range(0, len(service_offerings_list)): + if not ((current_so.cpunumber > service_offerings_list[i].cpunumber or\ + current_so.cpuspeed > service_offerings_list[i].cpuspeed or\ + current_so.memory > service_offerings_list[i].memory) or\ + (current_so.cpunumber == service_offerings_list[i].cpunumber and\ + current_so.cpuspeed == service_offerings_list[i].cpuspeed and\ + current_so.memory == service_offerings_list[i].memory)): + if(current_so.storagetype == service_offerings_list[i].storagetype): + so_exists = True + new_so = service_offerings_list[i] + break + # If service offering does not exists, then creating one service offering for scale up + if not so_exists: + self.services["service_offerings"]["small"]["storagetype"] = current_so.storagetype + new_so = ServiceOffering.create( + self.apiClient, + self.services["service_offerings"]["small"] + ) + self.cleanup.append(new_so) + # Scaling up the VM + vm_created.scale_virtualmachine( + self.userapiclient, + new_so.id + ) + # Listing VM details again + list_vms_after = VirtualMachine.list( + self.userapiclient, + id=vm_created.id + ) + status = validateList(list_vms_after) + self.assertEquals( + PASS, + status[0], + "Listing of VM failed" + ) + self.assertEquals( + 1, + len(list_vms_after), + "VMs list is not as expected" + ) + # Verifying that VM's service offerings is changed + self.assertEquals( + new_so.id, + list_vms_after[0].serviceofferingid, + "VM is not containing New Service Offering" + ) + return + + @attr(tags=["advanced", "basic", "provisioning"]) + def test_18_stopped_vm_change_service(self): + """ + @Desc: Test to verify change service for Stopped VM + @Steps: + Step1: Deploying a VM + Step2: Stopping the VM deployed in step1 + Step3: Listing all the existing service offerings + Step4: If there is a matching Service Offering for change service of stopped VM + use that service offering. If not create one service offering for change service. + Step5: Perform change service for the Stopped VM + Step6: Verifying that VM's service offerings is changed + """ + # Listing all the VM's for a User + list_vms_before = VirtualMachine.list( + self.userapiclient, + listall=self.services["listall"], + ) + self.assertIsNone( + list_vms_before, + "Virtual Machine already exists for newly created user" + ) + # Deploying a VM + vm_created = VirtualMachine.create( + self.userapiclient, + self.services["virtual_machine"], + accountid=self.account.name, + domainid=self.account.domainid, + serviceofferingid=self.service_offering.id, + ) + self.assertIsNotNone( + vm_created, + "VM creation failed" + ) + self.cleanup.append(vm_created) + # Listing details of current Service Offering + vm_so_list = ServiceOffering.list( + self.userapiclient, + id=vm_created.serviceofferingid + ) + status = validateList(vm_so_list) + self.assertEquals( + PASS, + status[0], + "Listing of VM Service offering failed" + ) + current_so = vm_so_list[0] + # Listing all the VMs for a user again + list_vms_after = VirtualMachine.list( + self.userapiclient, + listall=self.services["listall"], + ) + status = validateList(list_vms_after) + self.assertEquals( + PASS, + status[0], + "VM creation failed" + ) + # Verifying that the size of the list is 1 + self.assertEquals( + 1, + len(list_vms_after), + "VM list count is not matching" + ) + # Stopping the VM deployed above + vm_created.stop( + self.userapiclient, + forced=True + ) + # Listing all the service offerings + service_offerings_list = ServiceOffering.list( + self.userapiclient, + virtualmachineid=vm_created.id + ) + # Verifying if any Service offering available for change service of VM + so_exists = False + if service_offerings_list is not None: + for i in range(0, len(service_offerings_list)): + if ((current_so.id != service_offerings_list[i].id) and\ + (current_so.storagetype == service_offerings_list[i].storagetype)): + so_exists = True + new_so = service_offerings_list[i] + break + # If service offering does not exists, then creating one service offering for scale up + if not so_exists: + self.services["service_offerings"]["small"]["storagetype"] = current_so.storagetype + new_so = ServiceOffering.create( + self.apiClient, + self.services["service_offerings"]["small"] + ) + self.cleanup.append(new_so) + # Changing service for the VM + vm_created.scale_virtualmachine( + self.userapiclient, + new_so.id + ) + # Listing VM details again + list_vm = VirtualMachine.list( + self.userapiclient, + id=vm_created.id + ) + status = validateList(list_vm) + self.assertEquals( + PASS, + status[0], + "Listing of VM failed" + ) + self.assertEquals( + 1, + len(list_vm), + "VMs list is not as expected" + ) + # Verifying that VM's service offerings is changed + self.assertEquals( + new_so.id, + list_vm[0].serviceofferingid, + "VM is not containing New Service Offering" + ) + return + + @attr(tags=["advanced", "basic", "provisioning"]) + def test_19_create_reset_vm_sshkey(self): + """ + @Desc: Test to verify creation and reset of SSH Key for VM + @Steps: + Step1: Deploying a VM + Step2: Stopping the VM deployed in step1 + Step3: Listing all the SSH Key pairs + Step4: Creating a new SSH Key pair + Step5: Listing all the SSh Key pairs again + Step6: Verifying that the key pairs list is increased by 1 + Step7: Resetting the VM SSH Key to the key pair created in step4 + Step8: Verifying that the new SSH Key pair is set to the VM + """ + # Listing all the VM's for a User + list_vms_before = VirtualMachine.list( + self.userapiclient, + listall=self.services["listall"], + ) + self.assertIsNone( + list_vms_before, + "Virtual Machine already exists for newly created user" + ) + # Deploying a VM + vm_created = VirtualMachine.create( + self.userapiclient, + self.services["virtual_machine"], + accountid=self.account.name, + domainid=self.account.domainid, + serviceofferingid=self.service_offering.id, + ) + self.assertIsNotNone( + vm_created, + "VM creation failed" + ) + self.cleanup.append(vm_created) + # Listing all the VMs for a user again + list_vms_after = VirtualMachine.list( + self.userapiclient, + listall=self.services["listall"], + ) + status = validateList(list_vms_after) + self.assertEquals( + PASS, + status[0], + "VM creation failed" + ) + # Verifying that the size of the list is 1 + self.assertEquals( + 1, + len(list_vms_after), + "VM list count is not matching" + ) + # Stopping the VM deployed above + vm_created.stop( + self.userapiclient, + forced=True + ) + # Listing all the SSH Key pairs + list_keypairs_before = SSHKeyPair.list( + self.userapiclient + ) + list_keypairs_before_size = 0 + if list_keypairs_before is not None: + list_keypairs_before_size = len(list_keypairs_before) + + # Creating a new Key pair + new_keypair = SSHKeyPair.create( + self.userapiclient, + name="keypair1", + account=self.account.name, + domainid=self.domain.id + ) + self.assertIsNotNone( + new_keypair, + "New Key pair generation failed" + ) + self.assertEquals( + "keypair1", + new_keypair.name, + "Key Pair not created with given name" + ) + # Listing all the SSH Key pairs again + list_keypairs_after = SSHKeyPair.list( + self.userapiclient + ) + status = validateList(list_keypairs_after) + self.assertEquals( + PASS, + status[0], + "Listing of Key pairs failed" + ) + # Verifying that list size is increased by 1 + self.assertEquals( + list_keypairs_before_size + 1, + len(list_keypairs_after), + "List count is not matching" + ) + # Resetting the VM SSH key to the Key pair created above + vm_created.resetSshKey( + self.userapiclient, + keypair=new_keypair.name + ) + # Listing VM details again + list_vm = VirtualMachine.list( + self.userapiclient, + id=vm_created.id + ) + status = validateList(list_vm) + self.assertEquals( + PASS, + status[0], + "Listing of VM failed" + ) + self.assertEquals( + 1, + len(list_vm), + "VMs list is not as expected" + ) + # Verifying that VM's SSH keypair is set to newly created keypair + self.assertEquals( + new_keypair.name, + list_vm[0].keypair, + "VM is not set to newly created SSH Key pair" + ) + return + + @attr(tags=["advanced", "basic", "selfservice"]) + def test_20_update_vm_displayname_group(self): + """ + @Desc: Test to verify Update VM details + @Steps: + Step1: List all the VM's for a user + Step2: Deploy a VM with all parameters + Step3: Listing all the VM's again for the user + Step4: Verifying that list size is increased by 1 + Step5: Updating VM details - displayname, group + Step6: Listing the VM deployed in step 2 by ID + Step7: Verifying that displayname, group details of the VM are updated + """ + # Listing all the VM's for a User + list_vms_before = VirtualMachine.list( + self.userapiclient, + listall=self.services["listall"], + ) + self.assertIsNone( + list_vms_before, + "Virtual Machine already exists for newly created user" + ) + self.services["virtual_machine"]["keyboard"] = "us" + # Deploying a VM + vm_created = VirtualMachine.create( + self.userapiclient, + self.services["virtual_machine"], + accountid=self.account.name, + domainid=self.account.domainid, + serviceofferingid=self.service_offering.id, + group="groupName" + ) + self.assertIsNotNone( + vm_created, + "VM creation failed" + ) + self.cleanup.append(vm_created) + # Verifying the displayname and group details for deployed VM + self.assertEquals( + self.services["virtual_machine"]["displayname"], + vm_created.displayname, + "Display name of VM is not as expected" + ) + self.assertEquals( + "groupName", + vm_created.group, + "Group of VM is not as expected" + ) + # Listing all the VMs for a user again + list_vms_after = VirtualMachine.list( + self.userapiclient, + listall=self.services["listall"], + ) + status = validateList(list_vms_after) + self.assertEquals( + PASS, + status[0], + "VM creation failed" + ) + # Verifying that the size of the list is 1 + self.assertEquals( + 1, + len(list_vms_after), + "VM list count is not matching" + ) + # Updating the VM details - displayname and group + vm_created.update( + self.userapiclient, + displayname="DisplayName", + group="Group", + haenable=False + ) + # Listing VM details again + list_vm = VirtualMachine.list( + self.userapiclient, + id=vm_created.id, + ) + status = validateList(list_vm) + self.assertEquals( + PASS, + status[0], + "Listing of VM by Id failed" + ) + self.assertEquals( + 1, + len(list_vm), + "Count of List VM by Id is not matching" + ) + # Verifying that displayname and group details are updated + self.assertEquals( + "DisplayName", + list_vm[0].displayname, + "Displayname of VM is not updated" + ) + self.assertEquals( + "Group", + list_vm[0].group, + "Group of VM is not updated" + ) + return + + @attr(tags=["advanced", "basic", "provisioning"]) + def test_21_restore_vm(self): + """ + @Desc: Test to verify Restore VM + @Steps: + Step1: List all the VM's for a user + Step2: Deploy a VM with all parameters + Step3: Listing all the VM's again for the user + Step4: Verifying that list size is increased by 1 + Step5: Restoring the VM deployed in step2 + Step6: Verifying that restored VM details are same as the VM deployed in step2 + """ + # Listing all the VM's for a User + list_vms_before = VirtualMachine.list( + self.userapiclient, + listall=self.services["listall"], + ) + self.assertIsNone( + list_vms_before, + "Virtual Machine already exists for newly created user" + ) + # Deploying a VM + vm_created = VirtualMachine.create( + self.userapiclient, + self.services["virtual_machine"], + accountid=self.account.name, + domainid=self.account.domainid, + serviceofferingid=self.service_offering.id, + ) + self.assertIsNotNone( + vm_created, + "VM creation failed" + ) + self.cleanup.append(vm_created) + # Listing all the VMs for a user again + list_vms_after = VirtualMachine.list( + self.userapiclient, + listall=self.services["listall"], + ) + status = validateList(list_vms_after) + self.assertEquals( + PASS, + status[0], + "VM creation failed" + ) + # Verifying that the size of the list is 1 + self.assertEquals( + 1, + len(list_vms_after), + "VM list count is not matching" + ) + # Restoring the VM + restored_vm = vm_created.restore(self.userapiclient) + self.assertIsNotNone( + restored_vm, + "VM restore failed" + ) + # Verifying the restored VM details + expected_dict = { + "id":vm_created.id, + "name":vm_created.name, + "displayname":vm_created.displayname, + "state":vm_created.state, + "zoneid":vm_created.zoneid, + "account":vm_created.account, + "template":vm_created.templateid + } + actual_dict = { + "id":restored_vm.id, + "name":restored_vm.name, + "displayname":restored_vm.displayname, + "state":restored_vm.state, + "zoneid":restored_vm.zoneid, + "account":restored_vm.account, + "template":restored_vm.templateid + } + restored_vm_status = self.__verify_values( + expected_dict, + actual_dict + ) + self.assertEqual( + True, + restored_vm_status, + "Restored VM details are not as expected" + ) + return + + @attr(tags=["advanced", "selfservice"]) + def test_22_deploy_vm_multiple_networks(self): + """ + @Desc: Test to verify deploy VM with multiple networks + @Steps: + Step1: List all the networks for user + Step2: If size of list networks is greater than 2 then get all the networks id's + Else create 2 networks and get network id's + Step3: List all the VM's for a user + Step4: Deploy a VM with multiple network id's + Step5: Listing all the VM's again for the user + Step6: Verifying that list size is increased by 1 + Step7: Verify that VM is associated with multiple networks + """ + # Listing all the networks available + networks_list_before = Network.list( + self.userapiclient, + listall=self.services["listall"] + ) + networks_list_size = 0 + if networks_list_before is not None: + networks_list_size = len(networks_list_before) + + # Listing Network Offerings + network_offerings_list = NetworkOffering.list( + self.apiClient, + forvpc="false", + guestiptype="Isolated", + state="Enabled", + supportedservices="SourceNat", + zoneid=self.zone.id + ) + status = validateList(network_offerings_list) + self.assertEquals( + PASS, + status[0], + "Isolated Network Offerings with sourceNat enabled are not found" + ) + while networks_list_size < 2: + # Creating a network + network = Network.create( + self.userapiclient, + self.services["network"], + accountid=self.account.name, + domainid=self.domain.id, + networkofferingid=network_offerings_list[0].id, + zoneid=self.zone.id + ) + self.assertIsNotNone( + network, + "Network creation failed" + ) + self.cleanup.append(network) + networks_list_size = networks_list_size + 1 + + # Listing the networks again + networks_list_after = Network.list( + self.userapiclient, + listall=self.services["listall"] + ) + status = validateList(network_offerings_list) + self.assertEquals( + PASS, + status[0], + "Listing networks failed" + ) + # populating network id's + networkids = networks_list_after[0].id + "," + networks_list_after[1].id + # Listing all the VM's for a User + list_vms_before = VirtualMachine.list( + self.userapiclient, + listall=self.services["listall"], + ) + self.assertIsNone( + list_vms_before, + "Virtual Machine already exists for newly created user" + ) + # Deploying a VM + vm_created = VirtualMachine.create( + self.userapiclient, + self.services["virtual_machine"], + accountid=self.account.name, + domainid=self.account.domainid, + networkids=networkids, + serviceofferingid=self.service_offering.id, + ) + self.assertIsNotNone( + vm_created, + "VM creation failed" + ) + self.cleanup.append(vm_created) + # Listing all the VMs for a user again + list_vms_after = VirtualMachine.list( + self.userapiclient, + listall=self.services["listall"], + ) + status = validateList(list_vms_after) + self.assertEquals( + PASS, + status[0], + "VM creation failed" + ) + # Verifying that the size of the list is 1 + self.assertEquals( + 1, + len(list_vms_after), + "VM list count is not matching" + ) + # Verifying that the NIC's in VM created are same as provided + vm_nics = vm_created.nic + # Verifying that the size of nics is 2 + self.assertEquals( + 2, + len(vm_nics), + "NIC's count in VM created is not matching" + ) + # Verifying that NIC network ID's are as expected + for i in range(0, len(vm_nics)): + if vm_nics[i].isdefault is True: + self.assertEquals( + networks_list_after[0].id, + vm_nics[i].networkid, + "Default NIC is not as expected" + ) + else: + self.assertEquals( + networks_list_after[1].id, + vm_nics[i].networkid, + "Non Default NIC is not as expected" + ) + return + + @attr(tags=["basic", "provisioning"]) + def test_23_deploy_vm_multiple_securitygroups(self): + """ + @Desc: Test to verify deploy VM with multiple Security Groups + @Steps: + Step1: List all the security groups for user + Step2: If size of list security groups is greater than 2 then get all the security groups id's + Else creating 2 security groups and get security groups id's + Step3: List all the VM's for a user + Step4: Deploy a VM with multiple security groups id's + Step5: Listing all the VM's again for the user + Step6: Verifying that list size is increased by 1 + Step7: Verify that VM is associated with multiple security groups + """ + # Listing all the security groups available + security_groups_list = SecurityGroup.list( + self.userapiclient, + listall=self.services["listall"], + domainid=self.domain.id + ) + security_groups_list_size = 0 + if security_groups_list is not None: + security_groups_list_size = len(security_groups_list) + + while security_groups_list_size < 2: + # Creating a security group + security_group = SecurityGroup.create( + self.userapiclient, + self.services["security_group"], + account=self.account.name, + domainid=self.domain.id + ) + self.assertIsNotNone( + security_group, + "Security Group creation failed" + ) + self.cleanup.append(security_group) + security_groups_list_size = security_groups_list_size + 1 + + # Listing the networks again + security_groups_list = SecurityGroup.list( + self.userapiclient, + listall=self.services["listall"], + domainid=self.domain.id + ) + status = validateList(security_groups_list) + self.assertEquals( + PASS, + status[0], + "Listing Security Groups failed" + ) + # populating Security Groups id's + securitygroupids = {security_groups_list[0].id , security_groups_list[1].id} + # Listing all the VM's for a User + list_vms_before = VirtualMachine.list( + self.userapiclient, + listall=self.services["listall"], + ) + self.assertIsNone( + list_vms_before, + "Virtual Machine already exists for newly created user" + ) + # Deploying a VM + vm_created = VirtualMachine.create( + self.userapiclient, + self.services["virtual_machine"], + accountid=self.account.name, + domainid=self.account.domainid, + serviceofferingid=self.service_offering.id, + securitygroupids=securitygroupids, + ) + self.assertIsNotNone( + vm_created, + "VM creation failed" + ) + self.cleanup.append(vm_created) + # Listing all the VMs for a user again + list_vms_after = VirtualMachine.list( + self.userapiclient, + listall=self.services["listall"], + ) + status = validateList(list_vms_after) + self.assertEquals( + PASS, + status[0], + "VM creation failed" + ) + # Verifying that the size of the list is 1 + self.assertEquals( + 1, + len(list_vms_after), + "VM list count is not matching" + ) + # Verifying that the Security Groups's in VM created are same as provided + vm_securitygroups = vm_created.securitygroup + # Verifying that the size of security groups is 2 + self.assertEquals( + 2, + len(vm_securitygroups), + "Security Groups count in VM created is not matching" + ) + # Verifying that Security Group network ID's are as expected + vm_securitygroups_flag = True + for i in range(0, len(vm_securitygroups)): + if ((vm_securitygroups[i].id != security_groups_list[0].id) and\ + (vm_securitygroups[i].id != security_groups_list[1].id)): + vm_securitygroups_flag = False + break + + self.assertEquals( + True, + vm_securitygroups_flag, + "Security Groups in VM are not same as created" + ) + return + +class TestSnapshots(cloudstackTestCase): + + @classmethod + def setUpClass(cls): + try: + cls._cleanup = [] + cls.testClient = super(TestSnapshots, cls).getClsTestClient() + cls.api_client = cls.testClient.getApiClient() + cls.services = cls.testClient.getParsedTestDataConfig() + # Get Domain, Zone, Template + cls.domain = get_domain(cls.api_client) + cls.zone = get_zone(cls.api_client) + cls.template = get_template( + cls.api_client, + cls.zone.id, + cls.services["ostype"] + ) + if cls.zone.localstorageenabled: + cls.storagetype = 'local' + cls.services["service_offerings"]["tiny"]["storagetype"] = 'local' + cls.services["disk_offering"]["storagetype"] = 'local' + else: + cls.storagetype = 'shared' + cls.services["service_offerings"]["tiny"]["storagetype"] = 'shared' + cls.services["disk_offering"]["storagetype"] = 'shared' + + cls.services['mode'] = cls.zone.networktype + cls.services["virtual_machine"]["hypervisor"] = cls.testClient.getHypervisorInfo() + cls.services["virtual_machine"]["zoneid"] = cls.zone.id + cls.services["virtual_machine"]["template"] = cls.template.id + cls.services["custom_volume"]["zoneid"] = cls.zone.id + # Creating Disk offering, Service Offering and Account + cls.disk_offering = DiskOffering.create( + cls.api_client, + cls.services["disk_offering"] + ) + cls._cleanup.append(cls.disk_offering) + cls.service_offering = ServiceOffering.create( + cls.api_client, + cls.services["service_offerings"]["tiny"] + ) + cls._cleanup.append(cls.service_offering) + cls.account = Account.create( + cls.api_client, + cls.services["account"], + domainid=cls.domain.id + ) + # Getting authentication for user in newly created Account + cls.user = cls.account.user[0] + cls.userapiclient = cls.testClient.getUserApiClient(cls.user.username, cls.domain.name) + cls._cleanup.append(cls.account) + # Creating Virtual Machine + cls.virtual_machine = VirtualMachine.create( + cls.userapiclient, + cls.services["virtual_machine"], + accountid=cls.account.name, + domainid=cls.account.domainid, + serviceofferingid=cls.service_offering.id, + ) + cls._cleanup.append(cls.virtual_machine) + except Exception as e: + cls.tearDownClass() + raise Exception("Warning: Exception in setup : %s" % e) + return + + def setUp(self): + + self.apiClient = self.testClient.getApiClient() + self.cleanup = [] + + def tearDown(self): + #Clean up, terminate the created resources + cleanup_resources(self.apiClient, self.cleanup) + return + + @classmethod + def tearDownClass(cls): + try: + cleanup_resources(cls.api_client, cls._cleanup) + except Exception as e: + raise Exception("Warning: Exception during cleanup : %s" % e) + + return + + def __verify_values(self, expected_vals, actual_vals): + """ + @Desc: Function to verify expected and actual values + @Steps: + Step1: Initializing return flag to True + Step1: Verifying length of expected and actual dictionaries is matching. + If not matching returning false + Step2: Listing all the keys from expected dictionary + Step3: Looping through each key from step2 and verifying expected and actual dictionaries have same value + If not making return flag to False + Step4: returning the return flag after all the values are verified + """ + return_flag = True + + if len(expected_vals) != len(actual_vals): + return False + + keys = expected_vals.keys() + for i in range(0, len(expected_vals)): + exp_val = expected_vals[keys[i]] + act_val = actual_vals[keys[i]] + if exp_val == act_val: + return_flag = return_flag and True + else: + return_flag = return_flag and False + self.debug("expected Value: %s, is not matching with actual value: %s" % ( + exp_val, + act_val + )) + return return_flag + + @attr(tags=["advanced", "basic", "provisioning"]) + def test_01_list_volume_snapshots_pagination(self): + """ + @Desc: Test to List Volume Snapshots pagination + @steps: + Step1: Listing all the volume snapshots for a user + Step2: Verifying that list size is 0 + Step3: Creating (page size + 1) number of volume snapshots + Step4: Listing all the volume snapshots again for a user + Step5: Verifying that list size is (page size + 1) + Step6: Listing all the volume snapshots in page1 + Step7: Verifying that list size is (page size) + Step8: Listing all the volume snapshots in page2 + Step9: Verifying that list size is 1 + Step10: Deleting the volume snapshot present in page 2 + Step11: Listing all the volume snapshots in page2 + Step12: Verifying that list size is 0 + """ + # Listing all the volume snapshots for a User + list_vol_snaps_before = Snapshot.list( + self.userapiclient, + listall=self.services["listall"] + ) + # Verifying list size is 0 + self.assertIsNone( + list_vol_snaps_before, + "Volume snapshots exists for newly created user" + ) + # Listing the root volumes available for the user + volumes_list = Volume.list( + self.userapiclient, + listall=self.services["listall"] + ) + status = validateList(volumes_list) + self.assertEquals( + PASS, + status[0], + "Root volume did not get created while deploying a VM" + ) + # Verifying list size to be 1 + self.assertEquals( + 1, + len(volumes_list), + "More than 1 root volume created for deployed VM" + ) + root_volume = volumes_list[0] + # Creating pagesize + 1 number of volume snapshots + for i in range(0, (self.services["pagesize"] + 1)): + snapshot_created = Snapshot.create( + self.userapiclient, + root_volume.id, + ) + self.assertIsNotNone( + snapshot_created, + "Snapshot creation failed" + ) + self.cleanup.append(snapshot_created) + + # Listing all the volume snapshots for user again + list_vol_snaps_after = Snapshot.list( + self.userapiclient, + listall=self.services["listall"] + ) + status = validateList(list_vol_snaps_after) + self.assertEquals( + PASS, + status[0], + "Volume snapshot creation failed" + ) + # Verifying that list size is pagesize + 1 + self.assertEquals( + self.services["pagesize"] + 1, + len(list_vol_snaps_after), + "Failed to create pagesize + 1 number of Volume snapshots" + ) + # Listing all the volume snapshots in page 1 + list_vol_snaps_page1 = Snapshot.list( + self.userapiclient, + listall=self.services["listall"], + page=1, + pagesize=self.services["pagesize"] + ) + status = validateList(list_vol_snaps_page1) + self.assertEquals( + PASS, + status[0], + "Failed to list volume snapshots in page 1" + ) + # Verifying the list size to be equal to pagesize + self.assertEquals( + self.services["pagesize"], + len(list_vol_snaps_page1), + "Size of volume snapshots in page 1 is not matching" + ) + # Listing all the volume snapshots in page 2 + list_vol_snaps_page2 = Snapshot.list( + self.userapiclient, + listall=self.services["listall"], + page=2, + pagesize=self.services["pagesize"] + ) + status = validateList(list_vol_snaps_page2) + self.assertEquals( + PASS, + status[0], + "Failed to list volume snapshots in page 2" + ) + # Verifying the list size to be equal to pagesize + self.assertEquals( + 1, + len(list_vol_snaps_page2), + "Size of volume snapshots in page 2 is not matching" + ) + # Deleting the volume snapshot present in page 2 + Snapshot.delete( + snapshot_created, + self.userapiclient + ) + # Listing all the snapshots in page 2 again + list_vol_snaps_page2 = Snapshot.list( + self.userapiclient, + listall=self.services["listall"], + page=2, + pagesize=self.services["pagesize"] + ) + # Verifying that list size is 0 + self.assertIsNone( + list_vol_snaps_page2, + "Volume snapshot not deleted from page 2" + ) + return + + @attr(tags=["advanced", "basic", "provisioning"]) + def test_02_list_volume_snapshots_byid(self): + """ + @Desc: Test to List Volume Snapshots by Id + @Steps: + Step1: Listing all the volume snapshots for a user + Step2: Verifying that list size is 0 + Step3: Creating a volume snapshot + Step4: Listing all the volume snapshots again for a user + Step5: Verifying that list size is 1 + Step6: Listing all the volume snapshots by specifying snapshot id + Step7: Verifying that list size is 1 + Step8: Verifying details of the listed volume snapshot + """ + # Listing all the volume snapshots for a User + list_vol_snaps_before = Snapshot.list( + self.userapiclient, + listall=self.services["listall"] + ) + # Verifying list size is 0 + self.assertIsNone( + list_vol_snaps_before, + "Volume snapshots exists for newly created user" + ) + # Listing the root volumes available for the user + volumes_list = Volume.list( + self.userapiclient, + listall=self.services["listall"] + ) + status = validateList(volumes_list) + self.assertEquals( + PASS, + status[0], + "Root volume did not get created while deploying a VM" + ) + # Verifying list size to be 1 + self.assertEquals( + 1, + len(volumes_list), + "More than 1 root volume created for deployed VM" + ) + root_volume = volumes_list[0] + # Creating a volume snapshot + snapshot_created = Snapshot.create( + self.userapiclient, + root_volume.id, + ) + self.assertIsNotNone( + snapshot_created, + "Snapshot creation failed" + ) + self.cleanup.append(snapshot_created) + # Listing all the volume snapshots for user again + list_vol_snaps_after = Snapshot.list( + self.userapiclient, + listall=self.services["listall"] + ) + status = validateList(list_vol_snaps_after) + self.assertEquals( + PASS, + status[0], + "Volume snapshot creation failed" + ) + # Verifying that list size is 1 + self.assertEquals( + 1, + len(list_vol_snaps_after), + "Failed to create Volume snapshot" + ) + # Listing volume snapshot by id + list_vol_snapshot = Snapshot.list( + self.userapiclient, + listall=self.services["listall"], + id=snapshot_created.id + ) + status = validateList(list_vol_snapshot) + self.assertEquals( + PASS, + status[0], + "Failed to list Volume snapshot by Id" + ) + # Verifying that list size is 1 + self.assertEquals( + 1, + len(list_vol_snapshot), + "Size of the list volume snapshot by Id is not matching" + ) + # Verifying details of the listed snapshot to be same as snapshot created above + #Creating expected and actual values dictionaries + expected_dict = { + "id":snapshot_created.id, + "name":snapshot_created.name, + "state":snapshot_created.state, + "intervaltype":snapshot_created.intervaltype, + "account":snapshot_created.account, + "domain":snapshot_created.domainid, + "volume":snapshot_created.volumeid + } + actual_dict = { + "id":list_vol_snapshot[0].id, + "name":list_vol_snapshot[0].name, + "state":list_vol_snapshot[0].state, + "intervaltype":list_vol_snapshot[0].intervaltype, + "account":list_vol_snapshot[0].account, + "domain":list_vol_snapshot[0].domainid, + "volume":list_vol_snapshot[0].volumeid + } + vol_snapshot_status = self.__verify_values( + expected_dict, + actual_dict + ) + self.assertEqual( + True, + vol_snapshot_status, + "Listed Volume Snapshot details are not as expected" + ) + return + + @attr(tags=["advanced", "basic", "provisioning"]) + def test_03_list_vm_snapshots_pagination(self): + """ + @Desc: Test to List VM Snapshots pagination + @Steps: + Step1: Listing all the VM snapshots for a user + Step2: Verifying that list size is 0 + Step3: Creating (page size + 1) number of VM snapshots + Step4: Listing all the VM snapshots again for a user + Step5: Verifying that list size is (page size + 1) + Step6: Listing all the VM snapshots in page1 + Step7: Verifying that list size is (page size) + Step8: Listing all the VM snapshots in page2 + Step9: Verifying that list size is 1 + Step10: Deleting the VM snapshot present in page 2 + Step11: Listing all the volume snapshots in page2 + Step12: Verifying that list size is 0 + """ + # Listing all the VM snapshots for a User + list_vm_snaps_before = VmSnapshot.list( + self.userapiclient, + listall=self.services["listall"] + ) + # Verifying list size is 0 + self.assertIsNone( + list_vm_snaps_before, + "VM snapshots exists for newly created user" + ) + # Creating pagesize + 1 number of VM snapshots + for i in range(0, (self.services["pagesize"] + 1)): + snapshot_created = VmSnapshot.create( + self.userapiclient, + self.virtual_machine.id, + ) + self.assertIsNotNone( + snapshot_created, + "Snapshot creation failed" + ) + + # Listing all the VM snapshots for user again + list_vm_snaps_after = VmSnapshot.list( + self.userapiclient, + listall=self.services["listall"] + ) + status = validateList(list_vm_snaps_after) + self.assertEquals( + PASS, + status[0], + "VM snapshot creation failed" + ) + # Verifying that list size is pagesize + 1 + self.assertEquals( + self.services["pagesize"] + 1, + len(list_vm_snaps_after), + "Failed to create pagesize + 1 number of VM snapshots" + ) + # Listing all the VM snapshots in page 1 + list_vm_snaps_page1 = VmSnapshot.list( + self.userapiclient, + listall=self.services["listall"], + page=1, + pagesize=self.services["pagesize"] + ) + status = validateList(list_vm_snaps_page1) + self.assertEquals( + PASS, + status[0], + "Failed to list vm snapshots in page 1" + ) + # Verifying the list size to be equal to pagesize + self.assertEquals( + self.services["pagesize"], + len(list_vm_snaps_page1), + "Size of vm snapshots in page 1 is not matching" + ) + # Listing all the vm snapshots in page 2 + list_vm_snaps_page2 = VmSnapshot.list( + self.userapiclient, + listall=self.services["listall"], + page=2, + pagesize=self.services["pagesize"] + ) + status = validateList(list_vm_snaps_page2) + self.assertEquals( + PASS, + status[0], + "Failed to list vm snapshots in page 2" + ) + # Verifying the list size to be equal to pagesize + self.assertEquals( + 1, + len(list_vm_snaps_page2), + "Size of vm snapshots in page 2 is not matching" + ) + # Deleting the vm snapshot present in page 2 + VmSnapshot.deleteVMSnapshot( + self.userapiclient, + snapshot_created.id + ) + # Listing all the snapshots in page 2 again + list_vm_snaps_page2 = VmSnapshot.list( + self.userapiclient, + listall=self.services["listall"], + page=2, + pagesize=self.services["pagesize"] + ) + # Verifying that list size is 0 + self.assertIsNone( + list_vm_snaps_page2, + "VM snapshot not deleted from page 2" + ) + # Deleting all the existing VM snapshots + list_vm_snaps = VmSnapshot.list( + self.userapiclient, + listall=self.services["listall"], + ) + status = validateList(list_vm_snaps) + self.assertEquals( + PASS, + status[0], + "All VM snapshots deleted" + ) + # Verifying that list size is equal to page size + self.assertEquals( + self.services["pagesize"], + len(list_vm_snaps), + "VM Snapshots count is not matching" + ) + # Deleting all the existing VM snapshots + for i in range(0, len(list_vm_snaps)): + VmSnapshot.deleteVMSnapshot( + self.userapiclient, + list_vm_snaps[i].id + ) + return + + @attr(tags=["advanced", "basic", "provisioning"]) + def test_04_list_vm_snapshots_byid(self): + """ + @summary: Test to List VM Snapshots by Id + + Step1: Listing all the VM snapshots for a user + Step2: Verifying that list size is 0 + Step3: Creating a VM snapshot + Step4: Listing all the VM snapshots again for a user + Step5: Verifying that list size is 1 + Step6: Listing all the VM snapshots by specifying snapshot id + Step7: Verifying that list size is 1 + Step8: Verifying details of the listed VM snapshot + """ + # Listing all the VM snapshots for a User + list_vm_snaps_before = VmSnapshot.list( + self.userapiclient, + listall=self.services["listall"] + ) + # Verifying list size is 0 + self.assertIsNone( + list_vm_snaps_before, + "VM snapshots exists for newly created user" + ) + # Creating a VM snapshot + snapshot_created = VmSnapshot.create( + self.userapiclient, + self.virtual_machine.id, + ) + self.assertIsNotNone( + snapshot_created, + "Snapshot creation failed" + ) + # Listing all the VM snapshots for user again + list_vm_snaps_after = VmSnapshot.list( + self.userapiclient, + listall=self.services["listall"] + ) + status = validateList(list_vm_snaps_after) + self.assertEquals( + PASS, + status[0], + "VM snapshot creation failed" + ) + # Verifying that list size is 1 + self.assertEquals( + 1, + len(list_vm_snaps_after), + "Failed to create VM snapshot" + ) + # Listing vm snapshot by id + list_vm_snapshot = VmSnapshot.list( + self.userapiclient, + listall=self.services["listall"], + vmsnapshotid=snapshot_created.id + ) + status = validateList(list_vm_snapshot) + self.assertEquals( + PASS, + status[0], + "Failed to list VM snapshot by Id" + ) + # Verifying that list size is 1 + self.assertEquals( + 1, + len(list_vm_snapshot), + "Size of the list vm snapshot by Id is not matching" + ) + # Verifying details of the listed snapshot to be same as snapshot created above + #Creating expected and actual values dictionaries + expected_dict = { + "id":snapshot_created.id, + "name":snapshot_created.name, + "state":snapshot_created.state, + "vmid":snapshot_created.virtualmachineid, + } + actual_dict = { + "id":list_vm_snapshot[0].id, + "name":list_vm_snapshot[0].name, + "state":list_vm_snapshot[0].state, + "vmid":list_vm_snapshot[0].virtualmachineid, + } + vm_snapshot_status = self.__verify_values( + expected_dict, + actual_dict + ) + self.assertEqual( + True, + vm_snapshot_status, + "Listed VM Snapshot details are not as expected" + ) + return + +class TestSecurityGroups(cloudstackTestCase): + + @classmethod + def setUpClass(cls): + try: + cls._cleanup = [] + cls.testClient = super(TestSecurityGroups, cls).getClsTestClient() + cls.api_client = cls.testClient.getApiClient() + cls.services = cls.testClient.getParsedTestDataConfig() + # Get Domain, Zone, Template + cls.domain = get_domain(cls.api_client) + cls.zone = get_zone(cls.api_client) + cls.template = get_template( + cls.api_client, + cls.zone.id, + cls.services["ostype"] + ) + cls.services['mode'] = cls.zone.networktype + cls.account = Account.create( + cls.api_client, + cls.services["account"], + domainid=cls.domain.id + ) + # Getting authentication for user in newly created Account + cls.user = cls.account.user[0] + cls.userapiclient = cls.testClient.getUserApiClient(cls.user.username, cls.domain.name) + cls._cleanup.append(cls.account) + except Exception as e: + cls.tearDownClass() + raise Exception("Warning: Exception in setup : %s" % e) + return + + def setUp(self): + + self.apiClient = self.testClient.getApiClient() + self.cleanup = [] + + def tearDown(self): + #Clean up, terminate the created resources + cleanup_resources(self.apiClient, self.cleanup) + return + + @classmethod + def tearDownClass(cls): + try: + cleanup_resources(cls.api_client, cls._cleanup) + except Exception as e: + raise Exception("Warning: Exception during cleanup : %s" % e) + + return + + def __verify_values(self, expected_vals, actual_vals): + """ + @Desc: Function to verify expected and actual values + @Steps: + Step1: Initializing return flag to True + Step1: Verifying length of expected and actual dictionaries is matching. + If not matching returning false + Step2: Listing all the keys from expected dictionary + Step3: Looping through each key from step2 and verifying expected and actual dictionaries have same value + If not making return flag to False + Step4: returning the return flag after all the values are verified + """ + return_flag = True + + if len(expected_vals) != len(actual_vals): + return False + + keys = expected_vals.keys() + for i in range(0, len(expected_vals)): + exp_val = expected_vals[keys[i]] + act_val = actual_vals[keys[i]] + if exp_val == act_val: + return_flag = return_flag and True + else: + return_flag = return_flag and False + self.debug("expected Value: %s, is not matching with actual value: %s" % ( + exp_val, + act_val + )) + return return_flag + + @attr(tags=["basic", "provisioning"]) + def test_01_list_securitygroups_pagination(self): + """ + @Desc: Test to List Security Groups pagination + @steps: + Step1: Listing all the Security Groups for a user + Step2: Verifying that list size is 1 + Step3: Creating (page size) number of Security Groups + Step4: Listing all the Security Groups again for a user + Step5: Verifying that list size is (page size + 1) + Step6: Listing all the Security Groups in page1 + Step7: Verifying that list size is (page size) + Step8: Listing all the Security Groups in page2 + Step9: Verifying that list size is 1 + Step10: Deleting the Security Group present in page 2 + Step11: Listing all the Security Groups in page2 + Step12: Verifying that no security groups are listed + """ + # Listing all the Security Groups for a User + list_securitygroups_before = SecurityGroup.list( + self.userapiclient, + listall=self.services["listall"] + ) + # Verifying that default security group is created + status = validateList(list_securitygroups_before) + self.assertEquals( + PASS, + status[0], + "Default Security Groups creation failed" + ) + # Verifying the size of the list is 1 + self.assertEquals( + 1, + len(list_securitygroups_before), + "Count of Security Groups list is not matching" + ) + # Creating pagesize number of security groups + for i in range(0, (self.services["pagesize"])): + securitygroup_created = SecurityGroup.create( + self.userapiclient, + self.services["security_group"], + account=self.account.name, + domainid=self.domain.id, + description=self.services["security_group"]["name"] + ) + self.assertIsNotNone( + securitygroup_created, + "Security Group creation failed" + ) + if (i < self.services["pagesize"]): + self.cleanup.append(securitygroup_created) + + # Listing all the security groups for user again + list_securitygroups_after = SecurityGroup.list( + self.userapiclient, + listall=self.services["listall"] + ) + status = validateList(list_securitygroups_after) + self.assertEquals( + PASS, + status[0], + "Security Groups creation failed" + ) + # Verifying that list size is pagesize + 1 + self.assertEquals( + self.services["pagesize"] + 1, + len(list_securitygroups_after), + "Failed to create pagesize + 1 number of Security Groups" + ) + # Listing all the security groups in page 1 + list_securitygroups_page1 = SecurityGroup.list( + self.userapiclient, + listall=self.services["listall"], + page=1, + pagesize=self.services["pagesize"] + ) + status = validateList(list_securitygroups_page1) + self.assertEquals( + PASS, + status[0], + "Failed to list security groups in page 1" + ) + # Verifying the list size to be equal to pagesize + self.assertEquals( + self.services["pagesize"], + len(list_securitygroups_page1), + "Size of security groups in page 1 is not matching" + ) + # Listing all the security groups in page 2 + list_securitygroups_page2 = SecurityGroup.list( + self.userapiclient, + listall=self.services["listall"], + page=2, + pagesize=self.services["pagesize"] + ) + status = validateList(list_securitygroups_page2) + self.assertEquals( + PASS, + status[0], + "Failed to list security groups in page 2" + ) + # Verifying the list size to be equal to pagesize + self.assertEquals( + 1, + len(list_securitygroups_page2), + "Size of security groups in page 2 is not matching" + ) + # Deleting the security group present in page 2 + SecurityGroup.delete( + securitygroup_created, + self.userapiclient) + # Listing all the security groups in page 2 again + list_securitygroups_page2 = SecurityGroup.list( + self.userapiclient, + listall=self.services["listall"], + page=2, + pagesize=self.services["pagesize"] + ) + # Verifying that there are no security groups listed + self.assertIsNone( + list_securitygroups_page2, + "Security Groups not deleted from page 2" + ) + return + + @attr(tags=["basic", "provisioning"]) + def test_02_securitygroups_authorize_revoke_ingress(self): + """ + @Desc: Test to Authorize and Revoke Ingress for Security Group + @steps: + Step1: Listing all the Security Groups for a user + Step2: Verifying that list size is 1 + Step3: Creating a Security Groups + Step4: Listing all the Security Groups again for a user + Step5: Verifying that list size is 2 + Step6: Authorizing Ingress for the security group created in step3 + Step7: Listing the security groups by passing id of security group created in step3 + Step8: Verifying that list size is 1 + Step9: Verifying that Ingress is authorized to the security group + Step10: Verifying the details of the Ingress rule are as expected + Step11: Revoking Ingress for the security group created in step3 + Step12: Listing the security groups by passing id of security group created in step3 + Step13: Verifying that list size is 1 + Step14: Verifying that Ingress is revoked from the security group + """ + # Listing all the Security Groups for a User + list_securitygroups_before = SecurityGroup.list( + self.userapiclient, + listall=self.services["listall"] + ) + # Verifying that default security group is created + status = validateList(list_securitygroups_before) + self.assertEquals( + PASS, + status[0], + "Default Security Groups creation failed" + ) + # Verifying the size of the list is 1 + self.assertEquals( + 1, + len(list_securitygroups_before), + "Count of Security Groups list is not matching" + ) + # Creating a security group + securitygroup_created = SecurityGroup.create( + self.userapiclient, + self.services["security_group"], + account=self.account.name, + domainid=self.domain.id, + description=self.services["security_group"]["name"] + ) + self.assertIsNotNone( + securitygroup_created, + "Security Group creation failed" + ) + self.cleanup.append(securitygroup_created) + + # Listing all the security groups for user again + list_securitygroups_after = SecurityGroup.list( + self.userapiclient, + listall=self.services["listall"] + ) + status = validateList(list_securitygroups_after) + self.assertEquals( + PASS, + status[0], + "Security Groups creation failed" + ) + # Verifying that list size is 2 + self.assertEquals( + 2, + len(list_securitygroups_after), + "Failed to create Security Group" + ) + # Authorizing Ingress for the security group created in step3 + securitygroup_created.authorize( + self.userapiclient, + self.services["ingress_rule"], + self.account.name, + self.domain.id, + ) + # Listing the security group by Id + list_securitygroups_byid = SecurityGroup.list( + self.userapiclient, + listall=self.services["listall"], + id=securitygroup_created.id, + domainid=self.domain.id + ) + # Verifying that security group is listed + status = validateList(list_securitygroups_byid) + self.assertEquals( + PASS, + status[0], + "Listing of Security Groups by id failed" + ) + # Verifying size of the list is 1 + self.assertEquals( + 1, + len(list_securitygroups_byid), + "Count of the listing security group by id is not matching" + ) + securitygroup_ingress = list_securitygroups_byid[0].ingressrule + # Validating the Ingress rule + status = validateList(securitygroup_ingress) + self.assertEquals( + PASS, + status[0], + "Security Groups Ingress rule authorization failed" + ) + self.assertEquals( + 1, + len(securitygroup_ingress), + "Security Group Ingress rules count is not matching" + ) + # Verifying the details of the Ingress rule are as expected + #Creating expected and actual values dictionaries + expected_dict = { + "cidr":self.services["ingress_rule"]["cidrlist"], + "protocol":self.services["ingress_rule"]["protocol"], + "startport":self.services["ingress_rule"]["startport"], + "endport":self.services["ingress_rule"]["endport"], + } + actual_dict = { + "cidr":str(securitygroup_ingress[0].cidr), + "protocol":str(securitygroup_ingress[0].protocol.upper()), + "startport":str(securitygroup_ingress[0].startport), + "endport":str(securitygroup_ingress[0].endport), + } + ingress_status = self.__verify_values( + expected_dict, + actual_dict + ) + self.assertEqual( + True, + ingress_status, + "Listed Security group Ingress rule details are not as expected" + ) + # Revoking the Ingress rule from Security Group + securitygroup_created.revoke(self.userapiclient, securitygroup_ingress[0].ruleid) + # Listing the security group by Id + list_securitygroups_byid = SecurityGroup.list( + self.userapiclient, + listall=self.services["listall"], + id=securitygroup_created.id, + domainid=self.domain.id + ) + # Verifying that security group is listed + status = validateList(list_securitygroups_byid) + self.assertEquals( + PASS, + status[0], + "Listing of Security Groups by id failed" + ) + # Verifying size of the list is 1 + self.assertEquals( + 1, + len(list_securitygroups_byid), + "Count of the listing security group by id is not matching" + ) + securitygroup_ingress = list_securitygroups_byid[0].ingressrule + # Verifying that Ingress rule is empty(revoked) + status = validateList(securitygroup_ingress) + self.assertEquals( + EMPTY_LIST, + status[2], + "Security Groups Ingress rule is not revoked" + ) + return + + @attr(tags=["basic", "provisioning"]) + def test_03_securitygroups_authorize_revoke_egress(self): + """ + @Desc: Test to Authorize and Revoke Egress for Security Group + @steps: + Step1: Listing all the Security Groups for a user + Step2: Verifying that list size is 1 + Step3: Creating a Security Groups + Step4: Listing all the Security Groups again for a user + Step5: Verifying that list size is 2 + Step6: Authorizing Egress for the security group created in step3 + Step7: Listing the security groups by passing id of security group created in step3 + Step8: Verifying that list size is 1 + Step9: Verifying that Egress is authorized to the security group + Step10: Verifying the details of the Egress rule are as expected + Step11: Revoking Egress for the security group created in step3 + Step12: Listing the security groups by passing id of security group created in step3 + Step13: Verifying that list size is 1 + Step14: Verifying that Egress is revoked from the security group + """ + # Listing all the Security Groups for a User + list_securitygroups_before = SecurityGroup.list( + self.userapiclient, + listall=self.services["listall"] + ) + # Verifying that default security group is created + status = validateList(list_securitygroups_before) + self.assertEquals( + PASS, + status[0], + "Default Security Groups creation failed" + ) + # Verifying the size of the list is 1 + self.assertEquals( + 1, + len(list_securitygroups_before), + "Count of Security Groups list is not matching" + ) + # Creating a security group + securitygroup_created = SecurityGroup.create( + self.userapiclient, + self.services["security_group"], + account=self.account.name, + domainid=self.domain.id, + description=self.services["security_group"]["name"] + ) + self.assertIsNotNone( + securitygroup_created, + "Security Group creation failed" + ) + self.cleanup.append(securitygroup_created) + + # Listing all the security groups for user again + list_securitygroups_after = SecurityGroup.list( + self.userapiclient, + listall=self.services["listall"] + ) + status = validateList(list_securitygroups_after) + self.assertEquals( + PASS, + status[0], + "Security Groups creation failed" + ) + # Verifying that list size is 2 + self.assertEquals( + 2, + len(list_securitygroups_after), + "Failed to create Security Group" + ) + # Authorizing Egress for the security group created in step3 + securitygroup_created.authorizeEgress( + self.userapiclient, + self.services["ingress_rule"], + self.account.name, + self.domain.id, + ) + # Listing the security group by Id + list_securitygroups_byid = SecurityGroup.list( + self.userapiclient, + listall=self.services["listall"], + id=securitygroup_created.id, + domainid=self.domain.id + ) + # Verifying that security group is listed + status = validateList(list_securitygroups_byid) + self.assertEquals( + PASS, + status[0], + "Listing of Security Groups by id failed" + ) + # Verifying size of the list is 1 + self.assertEquals( + 1, + len(list_securitygroups_byid), + "Count of the listing security group by id is not matching" + ) + securitygroup_egress = list_securitygroups_byid[0].egressrule + # Validating the Ingress rule + status = validateList(securitygroup_egress) + self.assertEquals( + PASS, + status[0], + "Security Groups Egress rule authorization failed" + ) + self.assertEquals( + 1, + len(securitygroup_egress), + "Security Group Egress rules count is not matching" + ) + # Verifying the details of the Egress rule are as expected + #Creating expected and actual values dictionaries + expected_dict = { + "cidr":self.services["ingress_rule"]["cidrlist"], + "protocol":self.services["ingress_rule"]["protocol"], + "startport":self.services["ingress_rule"]["startport"], + "endport":self.services["ingress_rule"]["endport"], + } + actual_dict = { + "cidr":str(securitygroup_egress[0].cidr), + "protocol":str(securitygroup_egress[0].protocol.upper()), + "startport":str(securitygroup_egress[0].startport), + "endport":str(securitygroup_egress[0].endport), + } + ingress_status = self.__verify_values( + expected_dict, + actual_dict + ) + self.assertEqual( + True, + ingress_status, + "Listed Security group Egress rule details are not as expected" + ) + # Revoking the Egress rule from Security Group + securitygroup_created.revokeEgress(self.userapiclient, securitygroup_egress[0].ruleid) + # Listing the security group by Id + list_securitygroups_byid = SecurityGroup.list( + self.userapiclient, + listall=self.services["listall"], + id=securitygroup_created.id, + domainid=self.domain.id + ) + # Verifying that security group is listed + status = validateList(list_securitygroups_byid) + self.assertEquals( + PASS, + status[0], + "Listing of Security Groups by id failed" + ) + # Verifying size of the list is 1 + self.assertEquals( + 1, + len(list_securitygroups_byid), + "Count of the listing security group by id is not matching" + ) + securitygroup_egress = list_securitygroups_byid[0].egressrule + # Verifying that Ingress rule is empty(revoked) + status = validateList(securitygroup_egress) + self.assertEquals( + EMPTY_LIST, + status[2], + "Security Groups Egress rule is not revoked" + ) + return + +class TestVpnCustomerGateways(cloudstackTestCase): + + @classmethod + def setUpClass(cls): + try: + cls._cleanup = [] + cls.testClient = super(TestVpnCustomerGateways, cls).getClsTestClient() + cls.api_client = cls.testClient.getApiClient() + cls.services = cls.testClient.getParsedTestDataConfig() + # Get Domain, Zone, Template + cls.domain = get_domain(cls.api_client) + cls.zone = get_zone(cls.api_client) + cls.template = get_template( + cls.api_client, + cls.zone.id, + cls.services["ostype"] + ) + cls.services['mode'] = cls.zone.networktype + cls.account = Account.create( + cls.api_client, + cls.services["account"], + domainid=cls.domain.id + ) + # Getting authentication for user in newly created Account + cls.user = cls.account.user[0] + cls.userapiclient = cls.testClient.getUserApiClient(cls.user.username, cls.domain.name) + cls._cleanup.append(cls.account) + except Exception as e: + cls.tearDownClass() + raise Exception("Warning: Exception in setup : %s" % e) + return + + def setUp(self): + + self.apiClient = self.testClient.getApiClient() + self.cleanup = [] + + def tearDown(self): + #Clean up, terminate the created resources + cleanup_resources(self.apiClient, self.cleanup) + return + + @classmethod + def tearDownClass(cls): + try: + cleanup_resources(cls.api_client, cls._cleanup) + except Exception as e: + raise Exception("Warning: Exception during cleanup : %s" % e) + + return + + def __verify_values(self, expected_vals, actual_vals): + """ + @Desc: Function to verify expected and actual values + @Steps: + Step1: Initializing return flag to True + Step1: Verifying length of expected and actual dictionaries is matching. + If not matching returning false + Step2: Listing all the keys from expected dictionary + Step3: Looping through each key from step2 and verifying expected and actual dictionaries have same value + If not making return flag to False + Step4: returning the return flag after all the values are verified + """ + return_flag = True + + if len(expected_vals) != len(actual_vals): + return False + + keys = expected_vals.keys() + for i in range(0, len(expected_vals)): + exp_val = expected_vals[keys[i]] + act_val = actual_vals[keys[i]] + if exp_val == act_val: + return_flag = return_flag and True + else: + return_flag = return_flag and False + self.debug("expected Value: %s, is not matching with actual value: %s" % ( + exp_val, + act_val + )) + return return_flag + + @attr(tags=["advanced", "basic", "provisioning"]) + def test_01_list_vpncustomergateways_pagination(self): + """ + @Desc: Test to List VPN Customer Gateways pagination + @steps: + Step1: Listing all the VPN Customer Gateways for a user + Step2: Verifying that no VPN Customer Gateways are listed + Step3: Creating (page size + 1) number of VPN Customer Gateways + Step4: Listing all the VPN Customer Gateways again for a user + Step5: Verifying that list size is (page size + 1) + Step6: Listing all the VPN Customer Gateways in page1 + Step7: Verifying that list size is (page size) + Step8: Listing all the VPN Customer Gateways in page2 + Step9: Verifying that list size is 1 + Step10: Deleting the VPN Customer Gateways present in page 2 + Step11: Listing all the VPN Customer Gateways in page2 + Step12: Verifying that no VPN Customer Gateways are listed + """ + # Listing all the VPN Customer Gateways for a User + list_vpncustomergateways_before = VpnCustomerGateway.list( + self.userapiclient, + listall=self.services["listall"] + ) + # Verifying that no VPN Customer Gateways are listed + self.assertIsNone( + list_vpncustomergateways_before, + "VPN Customer Gateways listed for newly created User" + ) + # Creating pagesize + 1 number of VPN Customer Gateways + for i in range(0, (self.services["pagesize"] + 1)): + vpncustomergateway_created = VpnCustomerGateway.create( + self.userapiclient, + self.services["vpncustomergateway"], + name="VPNCustGateway"+str(i+1), + gateway="10.102.153." + str(i+1), + cidrlist="10.0.0.0/24", + account=self.account.name, + domainid=self.domain.id + ) + self.assertIsNotNone( + vpncustomergateway_created, + "VPN Customer Gateway creation failed" + ) + if (i < self.services["pagesize"] + 1): + self.cleanup.append(vpncustomergateway_created) + + # Listing all the VPN Customer Gateways for a User + list_vpncustomergateways_after = VpnCustomerGateway.list( + self.userapiclient, + listall=self.services["listall"] + ) + status = validateList(list_vpncustomergateways_after) + self.assertEquals( + PASS, + status[0], + "VPN Customer Gateway creation failed" + ) + # Verifying that list size is pagesize + 1 + self.assertEquals( + self.services["pagesize"] + 1, + len(list_vpncustomergateways_after), + "Failed to create pagesize + 1 number of VPN Customer Gateways" + ) + # Listing all the VPN Customer Gateways in page 1 + list_vpncustomergateways_page1 = VpnCustomerGateway.list( + self.userapiclient, + listall=self.services["listall"], + page=1, + pagesize=self.services["pagesize"] + ) + status = validateList(list_vpncustomergateways_page1) + self.assertEquals( + PASS, + status[0], + "Failed to list VPN Customer Gateways in page 1" + ) + # Verifying the list size to be equal to pagesize + self.assertEquals( + self.services["pagesize"], + len(list_vpncustomergateways_page1), + "Size of VPN Customer Gateways in page 1 is not matching" + ) + # Listing all the VPN Customer Gateways in page 2 + list_vpncustomergateways_page2 = VpnCustomerGateway.list( + self.userapiclient, + listall=self.services["listall"], + page=2, + pagesize=self.services["pagesize"] + ) + status = validateList(list_vpncustomergateways_page2) + self.assertEquals( + PASS, + status[0], + "Failed to list VPN Customer Gateways in page 2" + ) + # Verifying the list size to be equal to 1 + self.assertEquals( + 1, + len(list_vpncustomergateways_page2), + "Size of VPN Customer Gateways in page 2 is not matching" + ) + # Deleting the VPM Customer Gateway present in page 2 + VpnCustomerGateway.delete( + vpncustomergateway_created, + self.userapiclient + ) + # Listing all the VPN Customer Gateways in page 2 again + list_vpncustomergateways_page2 = VpnCustomerGateway.list( + self.userapiclient, + listall=self.services["listall"], + page=2, + pagesize=self.services["pagesize"] + ) + # Verifying that there are no VPN Customer Gateways listed + self.assertIsNone( + list_vpncustomergateways_page2, + "VPN Customer Gateways not deleted from page 2" + ) + return + + @attr(tags=["advanced", "basic", "provisioning"]) + def test_02_update_vpncustomergateways(self): + """ + @Desc: Test to update VPN Customer Gateways pagination + @steps: + Step1: Listing all the VPN Customer Gateways for a user + Step2: Verifying that no VPN Customer Gateways are listed + Step3: Creating a VPN Customer Gateways + Step4: Listing all the VPN Customer Gateways again for a user + Step5: Verifying that list size is 1 + Step6: Updating the VPN Customer Gateways created in step3 + Step7: Listing the VPN customer gateway by id + Step8: Verifying that list size is 1 + Step9: Verifying the details of the listed VPN customer gateway are same as updated in step6 + """ + # Listing all the VPN Customer Gateways for a User + list_vpncustomergateways_before = VpnCustomerGateway.list( + self.userapiclient, + listall=self.services["listall"] + ) + # Verifying that no VPN Customer Gateways are listed + self.assertIsNone( + list_vpncustomergateways_before, + "VPN Customer Gateways listed for newly created User" + ) + # Creating A VPN Customer Gateways + vpncustomergateway_created = VpnCustomerGateway.create( + self.userapiclient, + self.services["vpncustomergateway"], + name="VPNCustGateway", + gateway="10.102.153.90", + cidrlist="10.0.0.0/24", + account=self.account.name, + domainid=self.domain.id + ) + self.assertIsNotNone( + vpncustomergateway_created, + "VPN Customer Gateway creation failed" + ) + self.cleanup.append(vpncustomergateway_created) + # Listing all the VPN Customer Gateways for a User + list_vpncustomergateways_after = VpnCustomerGateway.list( + self.userapiclient, + listall=self.services["listall"] + ) + status = validateList(list_vpncustomergateways_after) + self.assertEquals( + PASS, + status[0], + "VPN Customer Gateway creation failed" + ) + # Verifying that list size is 1 + self.assertEquals( + 1, + len(list_vpncustomergateways_after), + "Failed to create VPN Customer Gateways" + ) + # Updating the VPN Customer gateway + vpncustomergateway_updated = VpnCustomerGateway.update( + vpncustomergateway_created, + self.userapiclient, + self.services["vpncustomergateway"], + name="NewVPNCustGateway", + gateway="10.102.153.90", + cidrlist="10.0.0.0/24", + ) + self.assertIsNotNone( + vpncustomergateway_updated, + "Updation of VPN Customer Gateway failed" + ) + # Listing the VPN Customer Gateways by Id + list_vpncustomergateway = VpnCustomerGateway.list( + self.userapiclient, + listall=self.services["listall"], + id=vpncustomergateway_created.id + ) + status = validateList(list_vpncustomergateway) + self.assertEquals( + PASS, + status[0], + "Failed to list VPN Customer Gateways by Id" + ) + # Verifying the list size to be equal to 1 + self.assertEquals( + 1, + len(list_vpncustomergateway), + "Size of VPN Customer Gateways by id is not matching" + ) + # Verifying the details of the listed VPN Customer Gateway are same as updated + #Creating expected and actual values dictionaries + expected_dict = { + "name":vpncustomergateway_updated.name, + "id":vpncustomergateway_updated.id, + "account":vpncustomergateway_updated.account, + "domainid":vpncustomergateway_updated.domainid, + "gateway":vpncustomergateway_updated.gateway, + "cidrlist":vpncustomergateway_updated.cidrlist, + "seckey":vpncustomergateway_updated.ipsecpsk, + "ikepolicy":vpncustomergateway_updated.ikepolicy, + "ikelifetime":vpncustomergateway_updated.ikelifetime, + "esppolicy":vpncustomergateway_updated.esppolicy, + "esplifetime":vpncustomergateway_updated.esplifetime, + } + actual_dict = { + "name":list_vpncustomergateway[0].name, + "id":list_vpncustomergateway[0].id, + "account":list_vpncustomergateway[0].account, + "domainid":list_vpncustomergateway[0].domainid, + "gateway":list_vpncustomergateway[0].gateway, + "cidrlist":list_vpncustomergateway[0].cidrlist, + "seckey":list_vpncustomergateway[0].ipsecpsk, + "ikepolicy":list_vpncustomergateway[0].ikepolicy, + "ikelifetime":list_vpncustomergateway[0].ikelifetime, + "esppolicy":list_vpncustomergateway[0].esppolicy, + "esplifetime":list_vpncustomergateway[0].esplifetime, + } + vpncustomergateway_status = self.__verify_values( + expected_dict, + actual_dict + ) + self.assertEqual( + True, + vpncustomergateway_status, + "Listed VPN Customer Gateway details are not as Updated" + ) + return + +class TestTemplates(cloudstackTestCase): + + @classmethod + def setUpClass(cls): + try: + cls._cleanup = [] + cls.testClient = super(TestTemplates, cls).getClsTestClient() + cls.api_client = cls.testClient.getApiClient() + cls.services = cls.testClient.getParsedTestDataConfig() + # Get Domain, Zone, Template + cls.domain = get_domain(cls.api_client) + cls.zone = get_zone(cls.api_client) + cls.template = get_template( + cls.api_client, + cls.zone.id, + cls.services["ostype"] + ) + cls.hypervisor = cls.testClient.getHypervisorInfo() + cls.services['mode'] = cls.zone.networktype + cls.account = Account.create( + cls.api_client, + cls.services["account"], + domainid=cls.domain.id + ) + # Getting authentication for user in newly created Account + cls.user = cls.account.user[0] + cls.userapiclient = cls.testClient.getUserApiClient(cls.user.username, cls.domain.name) + cls._cleanup.append(cls.account) + except Exception as e: + cls.tearDownClass() + raise Exception("Warning: Exception in setup : %s" % e) + return + + def setUp(self): + + self.apiClient = self.testClient.getApiClient() + self.cleanup = [] + + def tearDown(self): + #Clean up, terminate the created resources + cleanup_resources(self.apiClient, self.cleanup) + return + + @classmethod + def tearDownClass(cls): + try: + cleanup_resources(cls.api_client, cls._cleanup) + except Exception as e: + raise Exception("Warning: Exception during cleanup : %s" % e) + + return + + def __verify_values(self, expected_vals, actual_vals): + """ + @Desc: Function to verify expected and actual values + @Steps: + Step1: Initializing return flag to True + Step1: Verifying length of expected and actual dictionaries is matching. + If not matching returning false + Step2: Listing all the keys from expected dictionary + Step3: Looping through each key from step2 and verifying expected and actual dictionaries have same value + If not making return flag to False + Step4: returning the return flag after all the values are verified + """ + return_flag = True + + if len(expected_vals) != len(actual_vals): + return False + + keys = expected_vals.keys() + for i in range(0, len(expected_vals)): + exp_val = expected_vals[keys[i]] + act_val = actual_vals[keys[i]] + if exp_val == act_val: + return_flag = return_flag and True + else: + return_flag = return_flag and False + self.debug("expected Value: %s, is not matching with actual value: %s" % ( + exp_val, + act_val + )) + return return_flag + + @attr(tags=["advanced", "basic", "provisioning"]) + def test_01_list_templates_pagination(self): + """ + @Desc: Test to List Templates pagination + @steps: + Step1: Listing all the Templates for a user + Step2: Verifying that no Templates are listed + Step3: Creating (page size + 1) number of Templates + Step4: Listing all the Templates again for a user + Step5: Verifying that list size is (page size + 1) + Step6: Listing all the Templates in page1 + Step7: Verifying that list size is (page size) + Step8: Listing all the Templates in page2 + Step9: Verifying that list size is 1 + Step10: Listing the template by Id + Step11: Verifying if the template is downloaded and ready. + If yes the continuing + If not waiting and checking for template to be ready till timeout + Step12: Deleting the Template present in page 2 + Step13: Listing all the Templates in page2 + Step14: Verifying that no Templates are listed + """ + # Listing all the Templates for a User + list_templates_before = Template.list( + self.userapiclient, + listall=self.services["listall"], + templatefilter=self.services["templatefilter"] + ) + # Verifying that no Templates are listed + self.assertIsNone( + list_templates_before, + "Templates listed for newly created User" + ) + self.services["template"]["url"] = "http://10.147.28.7/templates/ttylinux_pv.vhd" + self.services["template"]["format"] = "VHD" + self.services["template"]["ostype"] = self.services["ostype"] + # Creating pagesize + 1 number of Templates + for i in range(0, (self.services["pagesize"] + 1)): + template_created = Template.register( + self.userapiclient, + self.services["template"], + self.zone.id, + hypervisor=self.hypervisor + ) + self.assertIsNotNone( + template_created, + "Template creation failed" + ) + if(i < self.services["pagesize"]): + self.cleanup.append(template_created) + + # Listing all the Templates for a User + list_templates_after = Template.list( + self.userapiclient, + listall=self.services["listall"], + templatefilter=self.services["templatefilter"] + ) + status = validateList(list_templates_after) + self.assertEquals( + PASS, + status[0], + "Templates creation failed" + ) + # Verifying that list size is pagesize + 1 + self.assertEquals( + self.services["pagesize"] + 1, + len(list_templates_after), + "Failed to create pagesize + 1 number of Templates" + ) + # Listing all the Templates in page 1 + list_templates_page1 = Template.list( + self.userapiclient, + listall=self.services["listall"], + templatefilter=self.services["templatefilter"], + page=1, + pagesize=self.services["pagesize"] + ) + status = validateList(list_templates_page1) + self.assertEquals( + PASS, + status[0], + "Failed to list Templates in page 1" + ) + # Verifying the list size to be equal to pagesize + self.assertEquals( + self.services["pagesize"], + len(list_templates_page1), + "Size of Templates in page 1 is not matching" + ) + # Listing all the Templates in page 2 + list_templates_page2 = Template.list( + self.userapiclient, + listall=self.services["listall"], + templatefilter=self.services["templatefilter"], + page=2, + pagesize=self.services["pagesize"] + ) + status = validateList(list_templates_page2) + self.assertEquals( + PASS, + status[0], + "Failed to list Templates in page 2" + ) + # Verifying the list size to be equal to 1 + self.assertEquals( + 1, + len(list_templates_page2), + "Size of Templates in page 2 is not matching" + ) + # Verifying the state of the template to be ready. If not waiting for state to become ready + template_ready = False + count = 0 + while template_ready is False: + list_template = Template.list( + self.userapiclient, + id=template_created.id, + listall=self.services["listall"], + templatefilter=self.services["templatefilter"], + ) + status = validateList(list_template) + self.assertEquals( + PASS, + status[0], + "Failed to list Templates by Id" + ) + if list_template[0].isready is True: + template_ready = True + elif (str(list_template[0].status) == "Error"): + self.fail("Created Template is in Errored state") + break + elif count > 10: + self.fail("Timed out before Template came into ready state") + break + else: + time.sleep(self.services["sleep"]) + count = count + 1 + + # Deleting the Template present in page 2 + Template.delete( + template_created, + self.userapiclient + ) + # Listing all the Templates in page 2 again + list_templates_page2 = Template.list( + self.userapiclient, + listall=self.services["listall"], + templatefilter=self.services["templatefilter"], + page=2, + pagesize=self.services["pagesize"] + ) + # Verifying that there are no Templates listed + self.assertIsNone( + list_templates_page2, + "Templates not deleted from page 2" + ) + del self.services["template"]["url"] + del self.services["template"]["format"] + del self.services["template"]["ostype"] + return + + @attr(tags=["advanced", "basic", "provisioning"]) + def test_02_download_template(self): + """ + @Desc: Test to Download Template + @steps: + Step1: Listing all the Templates for a user + Step2: Verifying that no Templates are listed + Step3: Creating a Templates + Step4: Listing all the Templates again for a user + Step5: Verifying that list size is 1 + Step6: Verifying if the template is in ready state. + If yes the continuing + If not waiting and checking for template to be ready till timeout + Step7: Downloading the template (Extract) + Step8: Verifying that Template is downloaded + """ + # Listing all the Templates for a User + list_templates_before = Template.list( + self.userapiclient, + listall=self.services["listall"], + templatefilter=self.services["templatefilter"] + ) + # Verifying that no Templates are listed + self.assertIsNone( + list_templates_before, + "Templates listed for newly created User" + ) + self.services["template"]["url"] = "http://10.147.28.7/templates/ttylinux_pv.vhd" + self.services["template"]["format"] = "VHD" + self.services["template"]["ostype"] = self.services["ostype"] + self.services["template"]["isextractable"] = True + # Creating aTemplate + template_created = Template.register( + self.userapiclient, + self.services["template"], + self.zone.id, + hypervisor=self.hypervisor + ) + self.assertIsNotNone( + template_created, + "Template creation failed" + ) + self.cleanup.append(template_created) + # Listing all the Templates for a User + list_templates_after = Template.list( + self.userapiclient, + listall=self.services["listall"], + templatefilter=self.services["templatefilter"] + ) + status = validateList(list_templates_after) + self.assertEquals( + PASS, + status[0], + "Templates creation failed" + ) + # Verifying that list size is 1 + self.assertEquals( + 1, + len(list_templates_after), + "Failed to create a Template" + ) + # Verifying the state of the template to be ready. If not waiting for state to become ready till time out + template_ready = False + count = 0 + while template_ready is False: + list_template = Template.list( + self.userapiclient, + id=template_created.id, + listall=self.services["listall"], + templatefilter=self.services["templatefilter"], + ) + status = validateList(list_template) + self.assertEquals( + PASS, + status[0], + "Failed to list Templates by Id" + ) + if list_template[0].isready is True: + template_ready = True + elif (str(list_template[0].status) == "Error"): + self.fail("Created Template is in Errored state") + break + elif count > 10: + self.fail("Timed out before Template came into ready state") + break + else: + time.sleep(self.services["sleep"]) + count = count + 1 + + # Downloading the Template name + download_template = Template.extract( + self.userapiclient, + template_created.id, + mode="HTTP_DOWNLOAD", + zoneid=self.zone.id + ) + self.assertIsNotNone( + download_template, + "Download Template failed" + ) + # Verifying the details of downloaded template + self.assertEquals( + "DOWNLOAD_URL_CREATED", + download_template.state, + "Download URL not created for Template" + ) + self.assertIsNotNone( + download_template.url, + "Download URL not created for Template" + ) + self.assertEquals( + template_created.id, + download_template.id, + "Download Template details are not same as Template created" + ) + del self.services["template"]["url"] + del self.services["template"]["format"] + del self.services["template"]["ostype"] + del self.services["template"]["isextractable"] + return + + @attr(tags=["advanced", "basic", "provisioning"]) + def test_03_edit_template_details(self): + """ + @Desc: Test to Edit Template name, displaytext, OSType + @steps: + Step1: Listing all the Templates for a user + Step2: Verifying that no Templates are listed + Step3: Creating a Templates + Step4: Listing all the Templates again for a user + Step5: Verifying that list size is 1 + Step6: Verifying if the template is in ready state. + If yes the continuing + If not waiting and checking for template to be ready till timeout + Step7: Editing the template name + Step8: Verifying that Template name is edited + Step9: Editing the template displaytext + Step10: Verifying that Template displaytext is edited + Step11: Editing the template ostypeid + Step12: Verifying that Template ostypeid is edited + Step13: Editing the template name, displaytext + Step14: Verifying that Template name, displaytext are edited + Step15: Editing the template name, displaytext, ostypeid + Step16: Verifying that Template name, displaytext and ostypeid are edited + """ + # Listing all the Templates for a User + list_templates_before = Template.list( + self.userapiclient, + listall=self.services["listall"], + templatefilter=self.services["templatefilter"] + ) + # Verifying that no Templates are listed + self.assertIsNone( + list_templates_before, + "Templates listed for newly created User" + ) + self.services["template"]["url"] = "http://10.147.28.7/templates/ttylinux_pv.vhd" + self.services["template"]["format"] = "VHD" + self.services["template"]["ostype"] = self.services["ostype"] + # Creating aTemplate + template_created = Template.register( + self.userapiclient, + self.services["template"], + self.zone.id, + hypervisor=self.hypervisor + ) + self.assertIsNotNone( + template_created, + "Template creation failed" + ) + self.cleanup.append(template_created) + # Listing all the Templates for a User + list_templates_after = Template.list( + self.userapiclient, + listall=self.services["listall"], + templatefilter=self.services["templatefilter"] + ) + status = validateList(list_templates_after) + self.assertEquals( + PASS, + status[0], + "Templates creation failed" + ) + # Verifying that list size is 1 + self.assertEquals( + 1, + len(list_templates_after), + "Failed to create a Template" + ) + # Verifying the state of the template to be ready. If not waiting for state to become ready till time out + template_ready = False + count = 0 + while template_ready is False: + list_template = Template.list( + self.userapiclient, + id=template_created.id, + listall=self.services["listall"], + templatefilter=self.services["templatefilter"], + ) + status = validateList(list_template) + self.assertEquals( + PASS, + status[0], + "Failed to list Templates by Id" + ) + if list_template[0].isready is True: + template_ready = True + elif (str(list_template[0].status) == "Error"): + self.fail("Created Template is in Errored state") + break + elif count > 10: + self.fail("Timed out before Template came into ready state") + break + else: + time.sleep(self.services["sleep"]) + count = count + 1 + + # Editing the Template name + edited_template = Template.update( + template_created, + self.userapiclient, + name="NewTemplateName" + ) + self.assertIsNotNone( + edited_template, + "Editing Template failed" + ) + # Verifying the details of edited template + expected_dict = { + "id":template_created.id, + "name":"NewTemplateName", + "displaytest":template_created.displaytext, + "account":template_created.account, + "domainid":template_created.domainid, + "format":template_created.format, + "ostypeid":template_created.ostypeid, + "templatetype":template_created.templatetype, + } + actual_dict = { + "id":edited_template.id, + "name":edited_template.name, + "displaytest":edited_template.displaytext, + "account":edited_template.account, + "domainid":edited_template.domainid, + "format":edited_template.format, + "ostypeid":edited_template.ostypeid, + "templatetype":edited_template.templatetype, + } + edit_template_status = self.__verify_values( + expected_dict, + actual_dict + ) + self.assertEqual( + True, + edit_template_status, + "Edited Template details are not as expected" + ) + # Editing the Template displaytext + edited_template = Template.update( + template_created, + self.userapiclient, + displaytext="TemplateDisplaytext" + ) + self.assertIsNotNone( + edited_template, + "Editing Template failed" + ) + # Verifying the details of edited template + expected_dict = { + "id":template_created.id, + "name":"NewTemplateName", + "displaytest":"TemplateDisplaytext", + "account":template_created.account, + "domainid":template_created.domainid, + "format":template_created.format, + "ostypeid":template_created.ostypeid, + "templatetype":template_created.templatetype, + } + actual_dict = { + "id":edited_template.id, + "name":edited_template.name, + "displaytest":edited_template.displaytext, + "account":edited_template.account, + "domainid":edited_template.domainid, + "format":edited_template.format, + "ostypeid":edited_template.ostypeid, + "templatetype":edited_template.templatetype, + } + edit_template_status = self.__verify_values( + expected_dict, + actual_dict + ) + self.assertEqual( + True, + edit_template_status, + "Edited Template details are not as expected" + ) + # Editing the Template ostypeid + ostype_list = list_os_types(self.userapiclient) + status = validateList(ostype_list) + self.assertEquals( + PASS, + status[0], + "Failed to list OS Types" + ) + for i in range(0, len(ostype_list)): + if ostype_list[i].id != template_created.ostypeid: + newostypeid = ostype_list[i].id + break + + edited_template = Template.update( + template_created, + self.userapiclient, + ostypeid=newostypeid + ) + self.assertIsNotNone( + edited_template, + "Editing Template failed" + ) + # Verifying the details of edited template + expected_dict = { + "id":template_created.id, + "name":"NewTemplateName", + "displaytest":"TemplateDisplaytext", + "account":template_created.account, + "domainid":template_created.domainid, + "format":template_created.format, + "ostypeid":newostypeid, + "templatetype":template_created.templatetype, + } + actual_dict = { + "id":edited_template.id, + "name":edited_template.name, + "displaytest":edited_template.displaytext, + "account":edited_template.account, + "domainid":edited_template.domainid, + "format":edited_template.format, + "ostypeid":edited_template.ostypeid, + "templatetype":edited_template.templatetype, + } + edit_template_status = self.__verify_values( + expected_dict, + actual_dict + ) + self.assertEqual( + True, + edit_template_status, + "Edited Template details are not as expected" + ) + # Editing the Template name, displaytext + edited_template = Template.update( + template_created, + self.userapiclient, + name=template_created.name, + displaytext=template_created.displaytext + ) + self.assertIsNotNone( + edited_template, + "Editing Template failed" + ) + # Verifying the details of edited template + expected_dict = { + "id":template_created.id, + "name":template_created.name, + "displaytest":template_created.displaytext, + "account":template_created.account, + "domainid":template_created.domainid, + "format":template_created.format, + "ostypeid":newostypeid, + "templatetype":template_created.templatetype, + } + actual_dict = { + "id":edited_template.id, + "name":edited_template.name, + "displaytest":edited_template.displaytext, + "account":edited_template.account, + "domainid":edited_template.domainid, + "format":edited_template.format, + "ostypeid":edited_template.ostypeid, + "templatetype":edited_template.templatetype, + } + edit_template_status = self.__verify_values( + expected_dict, + actual_dict + ) + self.assertEqual( + True, + edit_template_status, + "Edited Template details are not as expected" + ) + # Editing the Template name, displaytext, ostypeid + edited_template = Template.update( + template_created, + self.userapiclient, + name="NewTemplateName", + displaytext="TemplateDisplaytext", + ostypeid=template_created.ostypeid + ) + self.assertIsNotNone( + edited_template, + "Editing Template failed" + ) + # Verifying the details of edited template + expected_dict = { + "id":template_created.id, + "name":"NewTemplateName", + "displaytest":"TemplateDisplaytext", + "account":template_created.account, + "domainid":template_created.domainid, + "format":template_created.format, + "ostypeid":template_created.ostypeid, + "templatetype":template_created.templatetype, + } + actual_dict = { + "id":edited_template.id, + "name":edited_template.name, + "displaytest":edited_template.displaytext, + "account":edited_template.account, + "domainid":edited_template.domainid, + "format":edited_template.format, + "ostypeid":edited_template.ostypeid, + "templatetype":edited_template.templatetype, + } + edit_template_status = self.__verify_values( + expected_dict, + actual_dict + ) + self.assertEqual( + True, + edit_template_status, + "Edited Template details are not as expected" + ) + del self.services["template"]["url"] + del self.services["template"]["format"] + del self.services["template"]["ostype"] + return + + @attr(tags=["advanced", "basic", "provisioning"]) + def test_04_copy_template(self): + """ + @Desc: Test to copy Template from one zone to another + @steps: + Step1: Listing Zones available for a user + Step2: Verifying if the zones listed are greater than 1. + If Yes continuing. + If not halting the test. + Step3: Listing all the templates for a user in zone1 + Step4: Verifying that no templates are listed + Step5: Listing all the templates for a user in zone2 + Step6: Verifying that no templates are listed + Step7: Creating a Template in zone 1 + Step8: Listing all the Templates again for a user in zone1 + Step9: Verifying that list size is 1 + Step10: Listing all the templates for a user in zone2 + Step11: Verifying that no templates are listed + Step12: Copying the template created in step7 from zone1 to zone2 + Step13: Listing all the templates for a user in zone2 + Step14: Verifying that list size is 1 + Step15: Listing all the Templates for a user in zone1 + Step16: Verifying that list size is 1 + """ + # Listing Zones available for a user + zones_list = Zone.list( + self.userapiclient, + available=True + ) + status = validateList(zones_list) + self.assertEquals( + PASS, + status[0], + "Failed to list Zones" + ) + if not len(zones_list) > 1: + self.fail("Enough zones doesnot exists to copy template") + else: + # Listing all the Templates for a User in Zone 1 + list_templates_zone1 = Template.list( + self.userapiclient, + listall=self.services["listall"], + templatefilter=self.services["templatefilter"], + zoneid=zones_list[0].id + ) + # Verifying that no Templates are listed + self.assertIsNone( + list_templates_zone1, + "Templates listed for newly created User in Zone1" + ) + # Listing all the Templates for a User in Zone 2 + list_templates_zone2 = Template.list( + self.userapiclient, + listall=self.services["listall"], + templatefilter=self.services["templatefilter"], + zoneid=zones_list[1].id + ) + # Verifying that no Templates are listed + self.assertIsNone( + list_templates_zone2, + "Templates listed for newly created User in Zone2" + ) + self.services["template"]["url"] = "http://10.147.28.7/templates/ttylinux_pv.vhd" + self.services["template"]["format"] = "VHD" + self.services["template"]["ostype"] = self.services["ostype"] + #Listing Hypervisors in Zone 1 + hypervisor_list = Hypervisor.list( + self.apiClient, + zoneid=zones_list[0].id + ) + status = validateList(zones_list) + self.assertEquals( + PASS, + status[0], + "Failed to list Hypervisors in Zone 1" + ) + # Creating aTemplate in Zone 1 + template_created = Template.register( + self.userapiclient, + self.services["template"], + zones_list[0].id, + hypervisor=hypervisor_list[0].name + ) + self.assertIsNotNone( + template_created, + "Template creation failed" + ) + self.cleanup.append(template_created) + # Listing all the Templates for a User in Zone 1 + list_templates_zone1 = Template.list( + self.userapiclient, + listall=self.services["listall"], + templatefilter=self.services["templatefilter"], + zoneid=zones_list[0].id + ) + status = validateList(list_templates_zone1) + self.assertEquals( + PASS, + status[0], + "Templates creation failed in Zone1" + ) + # Verifying that list size is 1 + self.assertEquals( + 1, + len(list_templates_zone1), + "Failed to create a Template" + ) + # Listing all the Templates for a User in Zone 2 + list_templates_zone2 = Template.list( + self.userapiclient, + listall=self.services["listall"], + templatefilter=self.services["templatefilter"], + zoneid=zones_list[1].id + ) + # Verifying that no Templates are listed + self.assertIsNone( + list_templates_zone2, + "Templates listed for newly created User in Zone2" + ) + # Verifying the state of the template to be ready. If not waiting for state to become ready till time out + template_ready = False + count = 0 + while template_ready is False: + list_template = Template.list( + self.userapiclient, + id=template_created.id, + listall=self.services["listall"], + templatefilter=self.services["templatefilter"], + ) + status = validateList(list_template) + self.assertEquals( + PASS, + status[0], + "Failed to list Templates by Id" + ) + if list_template[0].isready is True: + template_ready = True + elif (str(list_template[0].status) == "Error"): + self.fail("Created Template is in Errored state") + break + elif count > 10: + self.fail("Timed out before Template came into ready state") + break + else: + time.sleep(self.services["sleep"]) + count = count + 1 + + # Copying the Template from Zone1 to Zone2 + copied_template = Template.copy( + self.userapiclient, + template_created.id, + sourcezoneid=template_created.zoneid, + destzoneid=zones_list[1].id + ) + self.assertIsNotNone( + copied_template, + "Copying Template from Zone1 to Zone2 failed" + ) + # Listing all the Templates for a User in Zone 1 + list_templates_zone1 = Template.list( + self.userapiclient, + listall=self.services["listall"], + templatefilter=self.services["templatefilter"], + zoneid=zones_list[0].id + ) + status = validateList(list_templates_zone1) + self.assertEquals( + PASS, + status[0], + "Templates creation failed in Zone1" + ) + # Verifying that list size is 1 + self.assertEquals( + 1, + len(list_templates_zone1), + "Failed to create a Template" + ) + # Listing all the Templates for a User in Zone 2 + list_templates_zone2 = Template.list( + self.userapiclient, + listall=self.services["listall"], + templatefilter=self.services["templatefilter"], + zoneid=zones_list[1].id + ) + status = validateList(list_templates_zone2) + self.assertEquals( + PASS, + status[0], + "Template failed to copy into Zone2" + ) + # Verifying that list size is 1 + self.assertEquals( + 1, + len(list_templates_zone2), + "Template failed to copy into Zone2" + ) + self.assertNotEquals( + "Connection refused", + list_templates_zone2[0].status, + "Failed to copy Template" + ) + self.assertEquals( + True, + list_templates_zone2[0].isready, + "Failed to copy Template" + ) + del self.services["template"]["url"] + del self.services["template"]["format"] + del self.services["template"]["ostype"] + return + +class TestIsos(cloudstackTestCase): + + @classmethod + def setUpClass(cls): + try: + cls._cleanup = [] + cls.testClient = super(TestIsos, cls).getClsTestClient() + cls.api_client = cls.testClient.getApiClient() + cls.services = cls.testClient.getParsedTestDataConfig() + # Get Domain, Zone, Template + cls.domain = get_domain(cls.api_client) + cls.zone = get_zone(cls.api_client) + cls.template = get_template( + cls.api_client, + cls.zone.id, + cls.services["ostype"] + ) + cls.hypervisor = cls.testClient.getHypervisorInfo() + cls.services['mode'] = cls.zone.networktype + cls.account = Account.create( + cls.api_client, + cls.services["account"], + domainid=cls.domain.id + ) + # Getting authentication for user in newly created Account + cls.user = cls.account.user[0] + cls.userapiclient = cls.testClient.getUserApiClient(cls.user.username, cls.domain.name) + cls._cleanup.append(cls.account) + except Exception as e: + cls.tearDownClass() + raise Exception("Warning: Exception in setup : %s" % e) + return + + def setUp(self): + + self.apiClient = self.testClient.getApiClient() + self.cleanup = [] + + def tearDown(self): + #Clean up, terminate the created resources + cleanup_resources(self.apiClient, self.cleanup) + return + + @classmethod + def tearDownClass(cls): + try: + cleanup_resources(cls.api_client, cls._cleanup) + except Exception as e: + raise Exception("Warning: Exception during cleanup : %s" % e) + + return + + def __verify_values(self, expected_vals, actual_vals): + """ + @Desc: Function to verify expected and actual values + @Steps: + Step1: Initializing return flag to True + Step1: Verifying length of expected and actual dictionaries is matching. + If not matching returning false + Step2: Listing all the keys from expected dictionary + Step3: Looping through each key from step2 and verifying expected and actual dictionaries have same value + If not making return flag to False + Step4: returning the return flag after all the values are verified + """ + return_flag = True + + if len(expected_vals) != len(actual_vals): + return False + + keys = expected_vals.keys() + for i in range(0, len(expected_vals)): + exp_val = expected_vals[keys[i]] + act_val = actual_vals[keys[i]] + if exp_val == act_val: + return_flag = return_flag and True + else: + return_flag = return_flag and False + self.debug("expected Value: %s, is not matching with actual value: %s" % ( + exp_val, + act_val + )) + return return_flag + + @attr(tags=["advanced", "basic", "provisioning"]) + def test_01_list_isos_pagination(self): + """ + @Desc: Test to List ISO's pagination + @steps: + Step1: Listing all the ISO's for a user + Step2: Verifying that no ISO's are listed + Step3: Creating (page size + 1) number of ISO's + Step4: Listing all the ISO's again for a user + Step5: Verifying that list size is (page size + 1) + Step6: Listing all the ISO's in page1 + Step7: Verifying that list size is (page size) + Step8: Listing all the ISO's in page2 + Step9: Verifying that list size is 1 + Step10: Listing the ISO's by Id + Step11: Verifying if the ISO is downloaded and ready. + If yes the continuing + If not waiting and checking for iso to be ready till timeout + Step12: Deleting the ISO present in page 2 + Step13: Listing all the ISO's in page2 + Step14: Verifying that no ISO's are listed + """ + # Listing all the ISO's for a User + list_iso_before = Iso.list( + self.userapiclient, + listall=self.services["listall"], + isofilter=self.services["templatefilter"] + ) + # Verifying that no ISOs are listed + self.assertIsNone( + list_iso_before, + "ISOs listed for newly created User" + ) + self.services["iso"]["zoneid"] = self.zone.id + # Creating pagesize + 1 number of ISO's + for i in range(0, (self.services["pagesize"] + 1)): + iso_created = Iso.create( + self.userapiclient, + self.services["iso"] + ) + self.assertIsNotNone( + iso_created, + "ISO creation failed" + ) + if(i < self.services["pagesize"]): + self.cleanup.append(iso_created) + + # Listing all the ISO's for a User + list_iso_after = Iso.list( + self.userapiclient, + listall=self.services["listall"], + isofilter=self.services["templatefilter"] + ) + status = validateList(list_iso_after) + self.assertEquals( + PASS, + status[0], + "ISO's creation failed" + ) + # Verifying that list size is pagesize + 1 + self.assertEquals( + self.services["pagesize"] + 1, + len(list_iso_after), + "Failed to create pagesize + 1 number of ISO's" + ) + # Listing all the ISO's in page 1 + list_iso_page1 = Iso.list( + self.userapiclient, + listall=self.services["listall"], + isofilter=self.services["templatefilter"], + page=1, + pagesize=self.services["pagesize"] + ) + status = validateList(list_iso_page1) + self.assertEquals( + PASS, + status[0], + "Failed to list ISO's in page 1" + ) + # Verifying the list size to be equal to pagesize + self.assertEquals( + self.services["pagesize"], + len(list_iso_page1), + "Size of ISO's in page 1 is not matching" + ) + # Listing all the Templates in page 2 + list_iso_page2 = Iso.list( + self.userapiclient, + listall=self.services["listall"], + isofilter=self.services["templatefilter"], + page=2, + pagesize=self.services["pagesize"] + ) + status = validateList(list_iso_page2) + self.assertEquals( + PASS, + status[0], + "Failed to list ISo's in page 2" + ) + # Verifying the list size to be equal to 1 + self.assertEquals( + 1, + len(list_iso_page2), + "Size of ISO's in page 2 is not matching" + ) + # Verifying the state of the ISO to be ready. If not waiting for state to become ready + iso_ready = False + count = 0 + while iso_ready is False: + list_iso = Iso.list( + self.userapiclient, + listall=self.services["listall"], + isofilter=self.services["templatefilter"], + id=iso_created.id + ) + status = validateList(list_iso) + self.assertEquals( + PASS, + status[0], + "Failed to list ISO by Id" + ) + if list_iso[0].isready is True: + iso_ready = True + elif (str(list_iso[0].status) == "Error"): + self.fail("Created ISO is in Errored state") + break + elif count > 10: + self.fail("Timed out before ISO came into ready state") + break + else: + time.sleep(self.services["sleep"]) + count = count + 1 + + # Deleting the ISO present in page 2 + Iso.delete( + iso_created, + self.userapiclient + ) + # Listing all the ISO's in page 2 again + list_iso_page2 = Iso.list( + self.userapiclient, + listall=self.services["listall"], + isofilter=self.services["templatefilter"], + page=2, + pagesize=self.services["pagesize"] + ) + # Verifying that there are no ISO's listed + self.assertIsNone( + list_iso_page2, + "ISO's not deleted from page 2" + ) + del self.services["iso"]["zoneid"] + return + + @attr(tags=["advanced", "basic", "provisioning"]) + def test_02_download_iso(self): + """ + @Desc: Test to Download ISO + @steps: + Step1: Listing all the ISO's for a user + Step2: Verifying that no ISO's are listed + Step3: Creating an ISO + Step4: Listing all the ISO's again for a user + Step5: Verifying that list size is 1 + Step6: Verifying if the ISO is in ready state. + If yes the continuing + If not waiting and checking for template to be ready till timeout + Step7: Downloading the ISO (Extract) + Step8: Verifying the details of downloaded ISO + """ + # Listing all the ISO's for a User + list_iso_before = Iso.list( + self.userapiclient, + listall=self.services["listall"], + isofilter=self.services["templatefilter"] + ) + # Verifying that no ISOs are listed + self.assertIsNone( + list_iso_before, + "ISOs listed for newly created User" + ) + self.services["iso"]["zoneid"] = self.zone.id + self.services["iso"]["isextractable"] = True + # Creating an ISO's + iso_created = Iso.create( + self.userapiclient, + self.services["iso"] + ) + self.assertIsNotNone( + iso_created, + "ISO creation failed" + ) + self.cleanup.append(iso_created) + # Listing all the ISO's for a User + list_iso_after = Iso.list( + self.userapiclient, + listall=self.services["listall"], + isofilter=self.services["templatefilter"] + ) + status = validateList(list_iso_after) + self.assertEquals( + PASS, + status[0], + "ISO's creation failed" + ) + # Verifying that list size is 1 + self.assertEquals( + 1, + len(list_iso_after), + "Failed to create an ISO's" + ) + # Verifying the state of the ISO to be ready. If not waiting for state to become ready + iso_ready = False + count = 0 + while iso_ready is False: + list_iso = Iso.list( + self.userapiclient, + listall=self.services["listall"], + isofilter=self.services["templatefilter"], + id=iso_created.id + ) + status = validateList(list_iso) + self.assertEquals( + PASS, + status[0], + "Failed to list ISO by Id" + ) + if list_iso[0].isready is True: + iso_ready = True + elif (str(list_iso[0].status) == "Error"): + self.fail("Created ISO is in Errored state") + break + elif count > 10: + self.fail("Timed out before ISO came into ready state") + break + else: + time.sleep(self.services["sleep"]) + count = count + 1 + + # Downloading the ISO + download_iso = Iso.extract( + self.userapiclient, + iso_created.id, + mode="HTTP_DOWNLOAD", + zoneid=self.zone.id + ) + self.assertIsNotNone( + download_iso, + "Download ISO failed" + ) + # Verifying the details of downloaded ISO + self.assertEquals( + "DOWNLOAD_URL_CREATED", + download_iso.state, + "Download URL not created for ISO" + ) + self.assertIsNotNone( + download_iso.url, + "Download URL not created for ISO" + ) + self.assertEquals( + iso_created.id, + download_iso.id, + "Download ISO details are not same as ISO created" + ) + del self.services["iso"]["zoneid"] + del self.services["iso"]["isextractable"] + return + + @attr(tags=["advanced", "basic", "provisioning"]) + def test_03_edit_iso_details(self): + """ + @Desc: Test to Edit ISO name, displaytext, OSType + @steps: + Step1: Listing all the ISO's for a user + Step2: Verifying that no ISO's are listed + Step3: Creating an ISO + Step4: Listing all the ISO's again for a user + Step5: Verifying that list size is 1 + Step6: Verifying if the ISO is in ready state. + If yes the continuing + If not waiting and checking for template to be ready till timeout + Step7: Editing the ISO's name, displaytext + Step8: Verifying that ISO name and displaytext are edited + Step9: Editing the ISO name, displaytext, ostypeid + Step10: Verifying that ISO name, displaytext and ostypeid are edited + """ + # Listing all the ISO's for a User + list_iso_before = Iso.list( + self.userapiclient, + listall=self.services["listall"], + isofilter=self.services["templatefilter"] + ) + # Verifying that no ISOs are listed + self.assertIsNone( + list_iso_before, + "ISOs listed for newly created User" + ) + self.services["iso"]["zoneid"] = self.zone.id + # Creating an ISO's + iso_created = Iso.create( + self.userapiclient, + self.services["iso"] + ) + self.assertIsNotNone( + iso_created, + "ISO creation failed" + ) + self.cleanup.append(iso_created) + # Listing all the ISO's for a User + list_iso_after = Iso.list( + self.userapiclient, + listall=self.services["listall"], + isofilter=self.services["templatefilter"] + ) + status = validateList(list_iso_after) + self.assertEquals( + PASS, + status[0], + "ISO's creation failed" + ) + # Verifying that list size is 1 + self.assertEquals( + 1, + len(list_iso_after), + "Failed to create an ISO's" + ) + # Verifying the state of the ISO to be ready. If not waiting for state to become ready + iso_ready = False + count = 0 + while iso_ready is False: + list_iso = Iso.list( + self.userapiclient, + listall=self.services["listall"], + isofilter=self.services["templatefilter"], + id=iso_created.id + ) + status = validateList(list_iso) + self.assertEquals( + PASS, + status[0], + "Failed to list ISO by Id" + ) + if list_iso[0].isready is True: + iso_ready = True + elif (str(list_iso[0].status) == "Error"): + self.fail("Created ISO is in Errored state") + break + elif count > 10: + self.fail("Timed out before ISO came into ready state") + break + else: + time.sleep(self.services["sleep"]) + count = count + 1 + + # Editing the ISO name, displaytext + edited_iso = Iso.update( + iso_created, + self.userapiclient, + name="NewISOName", + displaytext="NewISODisplayText" + ) + self.assertIsNotNone( + edited_iso, + "Editing ISO failed" + ) + # Verifying the details of edited template + expected_dict = { + "id":iso_created.id, + "name":"NewISOName", + "displaytest":"NewISODisplayText", + "account":iso_created.account, + "domainid":iso_created.domainid, + "isfeatured":iso_created.isfeatured, + "ostypeid":iso_created.ostypeid, + "ispublic":iso_created.ispublic, + } + actual_dict = { + "id":edited_iso.id, + "name":edited_iso.name, + "displaytest":edited_iso.displaytext, + "account":edited_iso.account, + "domainid":edited_iso.domainid, + "isfeatured":edited_iso.isfeatured, + "ostypeid":edited_iso.ostypeid, + "ispublic":edited_iso.ispublic, + } + edit_iso_status = self.__verify_values( + expected_dict, + actual_dict + ) + self.assertEqual( + True, + edit_iso_status, + "Edited ISO details are not as expected" + ) + # Editing the ISO name, displaytext, ostypeid + ostype_list = list_os_types(self.userapiclient) + status = validateList(ostype_list) + self.assertEquals( + PASS, + status[0], + "Failed to list OS Types" + ) + for i in range(0, len(ostype_list)): + if ostype_list[i].id != iso_created.ostypeid: + newostypeid = ostype_list[i].id + break + + edited_iso = Iso.update( + iso_created, + self.userapiclient, + name=iso_created.name, + displaytext=iso_created.displaytext, + ostypeid=newostypeid + ) + self.assertIsNotNone( + edited_iso, + "Editing ISO failed" + ) + # Verifying the details of edited template + expected_dict = { + "id":iso_created.id, + "name":iso_created.name, + "displaytest":iso_created.displaytext, + "account":iso_created.account, + "domainid":iso_created.domainid, + "isfeatured":iso_created.isfeatured, + "ostypeid":newostypeid, + "ispublic":iso_created.ispublic, + } + actual_dict = { + "id":edited_iso.id, + "name":edited_iso.name, + "displaytest":edited_iso.displaytext, + "account":edited_iso.account, + "domainid":edited_iso.domainid, + "isfeatured":edited_iso.isfeatured, + "ostypeid":edited_iso.ostypeid, + "ispublic":edited_iso.ispublic, + } + edit_iso_status = self.__verify_values( + expected_dict, + actual_dict + ) + self.assertEqual( + True, + edit_iso_status, + "Edited ISO details are not as expected" + ) + del self.services["iso"]["zoneid"] + return + + @attr(tags=["advanced", "basic", "provisioning"]) + def test_04_copy_iso(self): + """ + @Desc: Test to copy ISO from one zone to another + @steps: + Step1: Listing Zones available for a user + Step2: Verifying if the zones listed are greater than 1. + If Yes continuing. + If not halting the test. + Step3: Listing all the ISO's for a user in zone1 + Step4: Verifying that no ISO's are listed + Step5: Listing all the ISO's for a user in zone2 + Step6: Verifying that no ISO's are listed + Step7: Creating an ISO in zone 1 + Step8: Listing all the ISO's again for a user in zone1 + Step9: Verifying that list size is 1 + Step10: Listing all the ISO's for a user in zone2 + Step11: Verifying that no ISO's are listed + Step12: Copying the ISO created in step7 from zone1 to zone2 + Step13: Listing all the ISO's for a user in zone2 + Step14: Verifying that list size is 1 + Step15: Listing all the ISO's for a user in zone1 + Step16: Verifying that list size is 1 + """ + # Listing Zones available for a user + zones_list = Zone.list( + self.userapiclient, + available=True + ) + status = validateList(zones_list) + self.assertEquals( + PASS, + status[0], + "Failed to list Zones" + ) + if not len(zones_list) > 1: + self.fail("Enough zones doesnot exists to copy iso") + else: + # Listing all the ISO's for a User in Zone 1 + list_isos_zone1 = Iso.list( + self.userapiclient, + listall=self.services["listall"], + isofilter=self.services["templatefilter"], + zoneid=zones_list[0].id + ) + # Verifying that no ISO's are listed + self.assertIsNone( + list_isos_zone1, + "ISO's listed for newly created User in Zone1" + ) + # Listing all the ISO's for a User in Zone 2 + list_isos_zone2 = Iso.list( + self.userapiclient, + listall=self.services["listall"], + isofilter=self.services["templatefilter"], + zoneid=zones_list[1].id + ) + # Verifying that no ISO's are listed + self.assertIsNone( + list_isos_zone2, + "ISO's listed for newly created User in Zone2" + ) + self.services["iso"]["zoneid"] = zones_list[0].id + # Creating an ISO in Zone 1 + iso_created = Iso.create( + self.userapiclient, + self.services["iso"] + ) + self.assertIsNotNone( + iso_created, + "ISO creation failed" + ) + self.cleanup.append(iso_created) + # Listing all the ISO's for a User in Zone 1 + list_isos_zone1 = Iso.list( + self.userapiclient, + listall=self.services["listall"], + isofilter=self.services["templatefilter"], + zoneid=zones_list[0].id + ) + status = validateList(list_isos_zone1) + self.assertEquals( + PASS, + status[0], + "ISO creation failed in Zone1" + ) + # Verifying that list size is 1 + self.assertEquals( + 1, + len(list_isos_zone1), + "Failed to create a Template" + ) + # Listing all the ISO's for a User in Zone 2 + list_isos_zone2 = Iso.list( + self.userapiclient, + listall=self.services["listall"], + isofilter=self.services["templatefilter"], + zoneid=zones_list[1].id + ) + # Verifying that no ISO's are listed + self.assertIsNone( + list_isos_zone2, + "ISO's listed for newly created User in Zone2" + ) + # Verifying the state of the ISO to be ready. If not waiting for state to become ready + iso_ready = False + count = 0 + while iso_ready is False: + list_iso = Iso.list( + self.userapiclient, + listall=self.services["listall"], + isofilter=self.services["templatefilter"], + id=iso_created.id + ) + status = validateList(list_iso) + self.assertEquals( + PASS, + status[0], + "Failed to list ISO by Id" + ) + if list_iso[0].isready is True: + iso_ready = True + elif (str(list_iso[0].status) == "Error"): + self.fail("Created ISO is in Errored state") + break + elif count > 10: + self.fail("Timed out before ISO came into ready state") + break + else: + time.sleep(self.services["sleep"]) + count = count + 1 + + # Copying the ISO from Zone1 to Zone2 + copied_iso = Iso.copy( + self.userapiclient, + iso_created.id, + sourcezoneid=iso_created.zoneid, + destzoneid=zones_list[1].id + ) + self.assertIsNotNone( + copied_iso, + "Copying ISO from Zone1 to Zone2 failed" + ) + # Listing all the ISO's for a User in Zone 1 + list_isos_zone1 = Iso.list( + self.userapiclient, + listall=self.services["listall"], + isofilter=self.services["templatefilter"], + zoneid=zones_list[0].id + ) + status = validateList(list_isos_zone1) + self.assertEquals( + PASS, + status[0], + "ISO creation failed in Zone1" + ) + # Verifying that list size is 1 + self.assertEquals( + 1, + len(list_isos_zone1), + "Failed to create a Template" + ) + # Listing all the ISO's for a User in Zone 2 + list_isos_zone2 = Iso.list( + self.userapiclient, + listall=self.services["listall"], + isofilter=self.services["templatefilter"], + zoneid=zones_list[1].id + ) + status = validateList(list_isos_zone2) + self.assertEquals( + PASS, + status[0], + "ISO failed to copy into Zone2" + ) + # Verifying that list size is 1 + self.assertEquals( + 1, + len(list_isos_zone2), + "ISO failed to copy into Zone2" + ) + self.assertNotEquals( + "Connection refused", + list_isos_zone2[0].status, + "Failed to copy ISO" + ) + self.assertEquals( + True, + list_isos_zone2[0].isready, + "Failed to copy ISO" + ) + del self.services["iso"]["zoneid"] + return diff --git a/test/integration/component/test_explicit_dedication.py b/test/integration/component/test_explicit_dedication.py index 7aefc21a1f..4ce5c15fa9 100644 --- a/test/integration/component/test_explicit_dedication.py +++ b/test/integration/component/test_explicit_dedication.py @@ -21,9 +21,9 @@ from marvin.cloudstackTestCase import * from marvin.cloudstackAPI import * from marvin.sshClient import SshClient -from marvin.integration.lib.utils import * -from marvin.integration.lib.base import * -from marvin.integration.lib.common import * +from marvin.lib.utils import * +from marvin.lib.base import * +from marvin.lib.common import * from nose.plugins.attrib import attr #Import System modules import time @@ -96,12 +96,13 @@ class TestExplicitDedication(cloudstackTestCase): @classmethod def setUpClass(cls): - cls.api_client = super(TestExplicitDedication, cls).getClsTestClient().getApiClient() - cls.services = Services().services + cls.testClient = super(TestExplicitDedication, cls).getClsTestClient() + cls.api_client = cls.testClient.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) + cls.domain = get_domain(cls.api_client) + cls.zone = get_zone(cls.api_client, cls.testClient.getZoneForTests()) cls.services['mode'] = cls.zone.networktype cls.template = get_template( @@ -152,7 +153,7 @@ def tearDown(self): # This test requires multi host and at least one host which is empty (no vms should # be running on that host). It explicitly dedicates empty host to an account, deploys # a vm for that account and verifies that the vm gets deployed to the dedicated host. - @attr(tags = ["advanced", "basic", "multihosts", "explicitdedication"]) + @attr(tags=["advanced", "basic", "multihosts", "explicitdedication", "selfservice"]) def test_01_deploy_vm_with_explicit_dedication(self): """Test explicit dedication is placing vms of an account on dedicated hosts. """ diff --git a/test/integration/component/test_haproxy.py b/test/integration/component/test_haproxy.py index f77e4ec61c..e3b45b5ab3 100644 --- a/test/integration/component/test_haproxy.py +++ b/test/integration/component/test_haproxy.py @@ -19,7 +19,7 @@ # Import Local Modules from nose.plugins.attrib import attr from marvin.cloudstackTestCase import cloudstackTestCase -from marvin.integration.lib.base import ( +from marvin.lib.base import ( Account, ServiceOffering, VirtualMachine, @@ -31,11 +31,11 @@ Vpn, NATRule ) -from marvin.integration.lib.common import (get_domain, +from marvin.lib.common import (get_domain, get_zone, get_template ) -from marvin.integration.lib.utils import (cleanup_resources, +from marvin.lib.utils import (cleanup_resources, random_gen) from marvin.cloudstackAPI import createLBStickinessPolicy from marvin.sshClient import SshClient @@ -118,12 +118,13 @@ class TestHAProxyStickyness(cloudstackTestCase): @classmethod def setUpClass(cls): - cls.api_client = super(TestHAProxyStickyness, - cls).getClsTestClient().getApiClient() + cls.testClient = super(TestHAProxyStickyness, cls).getClsTestClient() + cls.api_client = cls.testClient.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) + cls.domain = get_domain(cls.api_client) + cls.zone = get_zone(cls.api_client, cls.testClient.getZoneForTests()) cls.template = get_template( cls.api_client, @@ -694,7 +695,7 @@ def test_06_release_ip(self): listall=True) return - @attr(tags=["advanced", "advancedns"]) + @attr(tags=["advanced", "advancedns", "provisioning"]) def test_07_delete_account(self): """Test Delete account and check the router and its rules""" @@ -735,7 +736,7 @@ def test_07_delete_account(self): listall=True) return - @attr(tags=["advanced", "advancedns"]) + @attr(tags=["advanced", "advancedns", "provisioning"]) def test_08_create_policy_router_stopped(self): """Test verify create stickiness policy when router is stopped state""" @@ -768,7 +769,7 @@ def test_08_create_policy_router_stopped(self): self.validate_Stickiness_Policy(lb_rule, "LbCookie", self.public_ip.ipaddress.ipaddress) return - @attr(tags=["advanced", "advancedns"]) + @attr(tags=["advanced", "advancedns", "provisioning"]) def test_09_create_policy_router_destroy(self): """Test check the stickiness policy rules after destroying router""" @@ -799,7 +800,7 @@ def test_09_create_policy_router_destroy(self): return - @attr(tags=["advanced", "advancedns"]) + @attr(tags=["advanced", "advancedns", "provisioning"]) def test_10_create_policy_enable_disable_vpn(self): """Test enable/disable the VPN after applying sticky policy rules""" @@ -830,7 +831,7 @@ def test_10_create_policy_enable_disable_vpn(self): self.validate_Stickiness_Policy(lb_rule, "LbCookie", self.public_ip.ipaddress.ipaddress) return - @attr(tags=["advanced", "advancedns"]) + @attr(tags=["advanced", "advancedns", "selfservice"]) def test_11_invalid_params(self): """Test verfify functionality syncronous and asyncronous validations""" diff --git a/test/integration/component/test_implicit_planner.py b/test/integration/component/test_implicit_planner.py index 2b656d9f2c..9cbd73c6f8 100644 --- a/test/integration/component/test_implicit_planner.py +++ b/test/integration/component/test_implicit_planner.py @@ -21,9 +21,9 @@ from marvin.cloudstackTestCase import * from marvin.cloudstackAPI import * from marvin.sshClient import SshClient -from marvin.integration.lib.utils import * -from marvin.integration.lib.base import * -from marvin.integration.lib.common import * +from marvin.lib.utils import * +from marvin.lib.base import * +from marvin.lib.common import * from nose.plugins.attrib import attr #Import System modules import time @@ -91,12 +91,13 @@ class TestImplicitPlanner(cloudstackTestCase): @classmethod def setUpClass(cls): - cls.api_client = super(TestImplicitPlanner, cls).getClsTestClient().getApiClient() - cls.services = Services().services + cls.testClient = super(TestImplicitPlanner, cls).getClsTestClient() + cls.api_client = cls.testClient.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) + domain = get_domain(cls.api_client) + cls.zone = get_zone(cls.api_client, cls.testClient.getZoneForTests()) cls.services['mode'] = cls.zone.networktype template = get_template( @@ -144,7 +145,7 @@ def tearDown(self): # 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"]) + @attr(tags=["advanced", "basic", "multihosts", "implicitplanner", "selfservice"]) def test_01_deploy_vm_with_implicit_planner(self): """Test implicit planner is placing vms of an account on implicitly dedicated hosts. """ diff --git a/test/integration/component/test_ip_reservation.py b/test/integration/component/test_ip_reservation.py old mode 100755 new mode 100644 index 224212f21d..c84f63c87a --- a/test/integration/component/test_ip_reservation.py +++ b/test/integration/component/test_ip_reservation.py @@ -15,134 +15,567 @@ # specific language governing permissions and limitations # under the License. """ Tests for IP reservation feature + + Test Plan: https://cwiki.apache.org/confluence/display/CLOUDSTACK/IP+Range+Reservation+within+a+Network+Test+Cases + + Issue Link: https://issues.apache.org/jira/browse/CLOUDSTACK-2266 + + Feature Specifications: https://cwiki.apache.org/confluence/display/CLOUDSTACK/FS+-+IP+Range+Reservation+within+a+Network """ -import marvin -from marvin.cloudstackTestCase import * -from marvin.cloudstackAPI import * -from marvin.cloudstackException import cloudstackAPIException -from marvin.integration.lib.utils import * -from marvin.integration.lib.base import * -from marvin.integration.lib.common import * +from marvin.cloudstackTestCase import cloudstackTestCase, unittest +from marvin.lib.utils import validateList, cleanup_resources, verifyRouterState +from marvin.lib.base import (Account, + Network, + VirtualMachine, + Router, + ServiceOffering, + NetworkOffering) +from marvin.lib.common import (get_zone, + get_template, + get_domain, + wait_for_cleanup, + createEnabledNetworkOffering, + createNetworkRulesForVM, + verifyNetworkState) +from marvin.codes import (PASS, FAIL, FAILED, UNKNOWN, FAULT, MASTER, + NAT_RULE, STATIC_NAT_RULE, ERROR_CODE_530) import netaddr +import random from nose.plugins.attrib import attr +from ddt import ddt, data -class Services(object): - """Test IP Reservation - """ - 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 - }, - "isolated_network_offering": { - "name": 'Network offering for Isolated Network', - "displaytext": 'Network offering-DA services', - "guestiptype": 'Isolated', - "supportedservices": 'Dhcp,Dns,SourceNat,PortForwarding,Vpn,Firewall,Lb,UserData,StaticNat', - "traffictype": 'GUEST', - "availability": 'Optional', - "serviceProviderList": { - "Dhcp": 'VirtualRouter', - "Dns": 'VirtualRouter', - "SourceNat": 'VirtualRouter', - "PortForwarding": 'VirtualRouter', - "Vpn": 'VirtualRouter', - "Firewall": 'VirtualRouter', - "Lb": 'VirtualRouter', - "UserData": 'VirtualRouter', - "StaticNat": 'VirtualRouter', - }, - }, - "isolated_persistent_network_offering": { - "name": 'Network offering for Isolated Network', - "displaytext": 'Network offering-DA services', - "guestiptype": 'Isolated', - "supportedservices": 'Dhcp,Dns,SourceNat,PortForwarding,Vpn,Firewall,Lb,UserData,StaticNat', - "traffictype": 'GUEST', - "availability": 'Optional', - "ispersistent": 'True', - "serviceProviderList": { - "Dhcp": 'VirtualRouter', - "Dns": 'VirtualRouter', - "SourceNat": 'VirtualRouter', - "PortForwarding": 'VirtualRouter', - "Vpn": 'VirtualRouter', - "Firewall": 'VirtualRouter', - "Lb": 'VirtualRouter', - "UserData": 'VirtualRouter', - "StaticNat": 'VirtualRouter', - }, - }, - "isolated_network": { - "name": "Isolated Network", - "displaytext": "Isolated Network", - "netmask": "255.255.255.0", - "gateway": "10.1.1.1" - }, - # update CIDR according to netmask and gateway in isolated_network - "isolated_network_cidr": "10.1.1.0/24", - "virtual_machine": { - "displayname": "Test VM", - }, - "ostype": 'CentOS 5.3 (64-bit)', - # Cent OS 5.3 (64 bit) - "sleep": 90, - "timeout": 10, - "mode": 'advanced' - } +def createIsolatedNetwork(self, network_offering_id, gateway=None): + """Create isolated network with given network offering and gateway if provided + and return""" + try: + isolated_network = Network.create(self.apiclient, self.testData["isolated_network"], + networkofferingid=network_offering_id,accountid=self.account.name, + domainid=self.domain.id,zoneid=self.zone.id, + gateway=gateway, netmask='255.255.255.0' if gateway else None) + except Exception as e: + return [FAIL, e] + return [PASS, isolated_network] + +def matchNetworkGuestVmCIDR(self, networkid, guestvmcidr): + """List networks with given network id and check if the guestvmcidr matches + with the given cidr""" + + networks = Network.list(self.apiclient, id=networkid, listall=True) + self.assertEqual(validateList(networks)[0], PASS, "network list validation failed") + self.assertEqual(str(networks[0].cidr), guestvmcidr, "guestvmcidr of network %s \ + does not match with the given value %s" % (networks[0].cidr, guestvmcidr)) + + return +def createVirtualMachine(self, network_id=None, ip_address=None): + """Create and return virtual machine within network and ipaddress""" + virtual_machine = VirtualMachine.create(self.apiclient, + self.testData["virtual_machine"], + networkids=network_id, + serviceofferingid=self.service_offering.id, + accountid=self.account.name, + domainid=self.domain.id, + ipaddress=ip_address) + return virtual_machine +def CreateEnabledNetworkOffering(apiclient, networkServices): + """Create network offering of given test data and enable it""" + + result = createEnabledNetworkOffering(apiclient, networkServices) + assert result[0] == PASS, "Network offering creation/enabling failed due to %s" % result[2] + return result[1] + +@ddt class TestIpReservation(cloudstackTestCase): """Test IP Range Reservation with a Network """ @classmethod def setUpClass(cls): - cls.api_client = super(TestIpReservation, cls).getClsTestClient().getApiClient() - cls.services = Services().services + cls.testClient = super(TestIpReservation, cls).getClsTestClient() + cls.api_client = cls.testClient.getApiClient() + + # Fill services from the external config file + cls.testData = cls.testClient.getParsedTestDataConfig() + # Get Zone, Domain and templates - cls.domain = get_domain(cls.api_client, cls.services) - cls.zone = get_zone(cls.api_client, cls.services) + cls.domain = get_domain(cls.api_client) + cls.zone = get_zone(cls.api_client, cls.testClient.getZoneForTests()) cls.template = get_template( cls.api_client, cls.zone.id, - cls.services["ostype"] + cls.testData["ostype"] ) - cls.services["domainid"] = cls.domain.id - cls.services["zoneid"] = cls.zone.id - cls.account = Account.create( + if cls.template == FAILED: + assert False, "get_template() failed to return template with description %s" % cls.testData["ostype"] + cls.testData["domainid"] = cls.domain.id + cls.testData["zoneid"] = cls.zone.id + cls.testData["virtual_machine"]["zoneid"] = cls.zone.id + cls.testData["virtual_machine"]["template"] = cls.template.id + cls._cleanup = [] + try: + cls.service_offering = ServiceOffering.create( + cls.api_client, + cls.testData["service_offering"] + ) + cls._cleanup.append(cls.service_offering) + cls.isolated_network_offering = CreateEnabledNetworkOffering(cls.api_client, + cls.testData["isolated_network_offering"]) + cls._cleanup.append(cls.isolated_network_offering) + cls.isolated_persistent_network_offering = CreateEnabledNetworkOffering(cls.api_client, + cls.testData["nw_off_isolated_persistent"]) + cls._cleanup.append(cls.isolated_persistent_network_offering) + cls.isolated_network_offering_RVR = CreateEnabledNetworkOffering(cls.api_client, + cls.testData["nw_off_isolated_RVR"]) + cls._cleanup.append(cls.isolated_network_offering_RVR) + except Exception as e: + cls.tearDownClass() + raise unittest.SkipTest("Failure in setUpClass: %s" % e) + 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 = [] + try: + self.account = Account.create(self.apiclient, self.testData["account"], + domainid=self.domain.id) + self.cleanup.append(self.account) + except Exception as e: + self.skipTest("Failed to create account: %s" % e) + return + + def tearDown(self): + try: + # Clean up, terminate the resources created + cleanup_resources(self.apiclient, self.cleanup) + except Exception as e: + raise Exception("Warning: Exception during cleanup : %s" % e) + return + + @attr(tags=["advanced"]) + def test_vm_create_after_reservation(self): + """ Test creating VM in network after IP reservation + # steps + # 1. Create vm in isolated network (LB through VR or Netscaler) with ip in guestvmcidr + # 2. Update guestvmcidr + # 3. Create another VM + # validation + # 1. Guest vm cidr should be successfully updated with correct value + # 2. Existing guest vm ip should not be changed after reservation + # 3. Newly created VM should get ip in guestvmcidr""" + + networkOffering = self.isolated_network_offering + subnet = "10.1."+str(random.randrange(1,254)) + gateway = subnet +".1" + resultSet = createIsolatedNetwork(self, networkOffering.id, gateway=gateway) + if resultSet[0] == FAIL: + self.fail("Failed to create isolated network") + else: + isolated_network = resultSet[1] + guest_vm_cidr = subnet +".0/29" + + try: + virtual_machine_1 = createVirtualMachine(self, network_id=isolated_network.id, + ip_address = subnet+".3") + except Exception as e: + self.fail("VM creation failed: %s" % e) + + isolated_network.update(self.apiclient, guestvmcidr=guest_vm_cidr) + matchNetworkGuestVmCIDR(self, isolated_network.id, guest_vm_cidr) + vms = VirtualMachine.list(self.apiclient, + id=virtual_machine_1.id) + self.assertEqual(validateList(vms)[0], PASS, "vm list validation failed") + self.assertEqual(vms[0].nic[0].ipaddress, + virtual_machine_1.ipaddress, + "VM IP should not change after reservation") + try: + virtual_machine_2 = createVirtualMachine(self, network_id=isolated_network.id) + if netaddr.IPAddress(virtual_machine_2.ipaddress) not in netaddr.IPNetwork(guest_vm_cidr): + self.fail("Newly created VM doesn't get IP from reserverd CIDR") + except Exception as e: + self.fail("VM creation failed, cannot validate the condition: %s" % e) + return + + @attr(tags=["advanced"]) + def test_vm_create_outside_cidr_after_reservation(self): + """ Test create VM outside the range of reserved IPs + # steps + # 1. update guestvmcidr of persistent isolated network (LB through VR or + # Netscaler + # 2. create another VM with ip outside guestvmcidr + """ + # validation + # 1. guest vm cidr should be successfully updated with correct value + # 2 newly created VM should not be created and result in exception + + networkOffering = self.isolated_persistent_network_offering + subnet = "10.1."+str(random.randrange(1,254)) + gateway = subnet +".1" + resultSet = createIsolatedNetwork(self, networkOffering.id, gateway=gateway) + if resultSet[0] == FAIL: + self.fail("Failed to create isolated network") + else: + isolated_network = resultSet[1] + guest_vm_cidr = subnet+".0/29" + + isolated_network.update(self.apiclient, guestvmcidr=guest_vm_cidr) + matchNetworkGuestVmCIDR(self, isolated_network.id, guest_vm_cidr) + try: + createVirtualMachine(self, network_id=self.isolated_network.id, + ip_address=subnet+".9") + self.fail("vm should not be created ") + except Exception as e: + self.debug("exception as IP is outside of guestvmcidr %s" % e) + return + + @attr(tags=["advanced"]) + def test_update_cidr_multiple_vms_not_all_inclusive(self): + """ Test reserve IP range such that one of the VM is not included + # steps + # 1. Create two vms in isolated network + # 2. Update guestvmcidr of network such that only one of the ipaddress of vms + # is in the given range + # validation + # 1. Network updation with this new range should fail""" + + subnet = "10.1."+str(random.randrange(1,254)) + gateway = subnet +".1" + resultSet = createIsolatedNetwork(self, self.isolated_network_offering.id, + gateway=gateway) + if resultSet[0] == FAIL: + self.fail("Failed to create isolated network") + else: + isolated_network = resultSet[1] + guest_vm_cidr = subnet+".0/29" + + try: + createVirtualMachine(self, network_id=isolated_network.id, + ip_address=subnet+".3") + except Exception as e: + self.fail("VM creation failed: %s" % e) + + try: + createVirtualMachine(self, network_id=isolated_network.id, + ip_address=subnet+".9") + except Exception as e: + self.fail("VM creation failed: %s" % e) + + with self.assertRaises(Exception): + isolated_network.update(self.apiclient, guestvmcidr=guest_vm_cidr) + return + + @attr(tags=["advanced"]) + def test_update_cidr_single_vm_not_inclusive(self): + """ Test reserving IP range in network such that existing VM is outside the range + # steps + # 1. Create vm in isolated network + # 2. Update guestvmcidr of network such that ip address of vm + # is outside the given range + # + # validation + # 1. Network updation with this new range should fail""" + subnet = "10.1."+str(random.randrange(1,254)) + gateway = subnet +".1" + resultSet = createIsolatedNetwork(self, self.isolated_network_offering.id, + gateway=gateway) + if resultSet[0] == FAIL: + self.fail("Failed to create isolated network") + else: + isolated_network = resultSet[1] + guest_vm_cidr = subnet+".0/29" + + try: + createVirtualMachine(self, network_id=isolated_network.id, + ip_address=subnet+".9") + except Exception as e: + self.fail("VM creation failed: %s" % e) + + with self.assertRaises(Exception): + isolated_network.update(self.apiclient, guestvmcidr=guest_vm_cidr) + return + + @data(NAT_RULE, STATIC_NAT_RULE) + @attr(tags=["advanced"]) + def test_nat_rules(self, value): + """ Test NAT rules working with IP reservation + # steps + # 1. Create vm in persistent isolated network with ip in guestvmcidr + # 2. Create NAT/static NAT rule for this VM + # 3. Update guestvmcidr + # 4. Create another VM and create network rules for this vm too + # + # validation + # 1. Guest vm cidr should be successfully updated with correct value + # 2. Existing guest vm ip should not be changed after reservation + # 3. Newly created VM should get ip in guestvmcidr + # 4. The network rules should be working""" + + subnet = "10.1."+str(random.randrange(1,254)) + gateway = subnet +".1" + resultSet = createIsolatedNetwork(self, self.isolated_network_offering.id, + gateway=gateway) + if resultSet[0] == FAIL: + self.fail("Failed to create isolated network") + else: + isolated_network = resultSet[1] + guest_vm_cidr = subnet+".0/29" + + try: + virtual_machine_1 = createVirtualMachine(self, network_id=isolated_network.id, + ip_address=subnet+".3") + except Exception as e: + self.fail("VM creation failed: %s" % e) + + result = createNetworkRulesForVM(self.apiclient, virtual_machine_1,value, + self.account, self.testData) + if result[0] == FAIL: + self.fail("Failed to create network rules for VM: %s" % result[1]) + else: + ipaddress_1 = result[1] + virtual_machine_1.get_ssh_client(ipaddress=ipaddress_1.ipaddress.ipaddress) + + isolated_network.update(self.apiclient, guestvmcidr=guest_vm_cidr) + matchNetworkGuestVmCIDR(self, isolated_network.id, guest_vm_cidr) + vms = VirtualMachine.list(self.apiclient, id=virtual_machine_1.id) + self.assertEqual(validateList(vms)[0], PASS, "vm list validation failed") + self.assertEqual(vms[0].nic[0].ipaddress, + virtual_machine_1.ipaddress, + "VM IP should not change after reservation") + try: + virtual_machine_2 = createVirtualMachine(self, network_id=isolated_network.id) + if netaddr.IPAddress(virtual_machine_2.ipaddress) not in netaddr.IPNetwork(guest_vm_cidr): + self.fail("Newly created VM doesn't get IP from reserverd CIDR") + except Exception as e: + self.fail("VM creation failed, cannot validate the condition: %s" % e) + + result = createNetworkRulesForVM(self.apiclient, virtual_machine_2, value, + self.account, self.testData) + if result[0] == FAIL: + self.fail("Failed to create network rules for VM: %s" % result[1]) + else: + ipaddress_2 = result[1] + virtual_machine_2.get_ssh_client(ipaddress=ipaddress_2.ipaddress.ipaddress) + return + + @unittest.skip("Skip - WIP") + @attr(tags=["advanced"]) + def test_RVR_network(self): + """ Test IP reservation in network with RVR + # steps + # 1. create vm in isolated network with RVR and ip in guestvmcidr + # 2. update guestvmcidr + # 3. List routers and stop the master router, wait till backup router comes up + # 4. create another VM + # + # validation + # 1. Guest vm cidr should be successfully updated with correct value + # 2. Existing guest vm ip should not be changed after reservation + # 3. Newly created VM should get ip in guestvmcidr + # 4. Verify that the network has two routers associated with it + # 5. Backup router should come up when master router is stopped""" + + subnet = "10.1."+str(random.randrange(1,254)) + gateway = subnet +".1" + resultSet = createIsolatedNetwork(self, self.isolated_network_offering_RVR.id, + gateway=gateway) + if resultSet[0] == FAIL: + self.fail("Failed to create isolated network") + else: + isolated_network_RVR= resultSet[1] + guest_vm_cidr = subnet+".0/29" + + try: + virtual_machine_1 = createVirtualMachine(self, network_id=isolated_network_RVR.id, + ip_address=subnet+".3") + except Exception as e: + self.fail("VM creation failed: %s" % e) + + isolated_network_RVR.update(self.apiclient, guestvmcidr=guest_vm_cidr) + matchNetworkGuestVmCIDR(self, isolated_network_RVR.id, guest_vm_cidr) + vms = VirtualMachine.list(self.apiclient, + id=virtual_machine_1.id) + self.assertEqual(validateList(vms)[0], PASS, "vm list validation failed") + self.assertEqual(vms[0].nic[0].ipaddress, + virtual_machine_1.ipaddress, + "VM IP should not change after reservation") + + self.debug("Listing routers for network: %s" % isolated_network_RVR.name) + routers = Router.list(self.apiclient, networkid=isolated_network_RVR.id, listall=True) + self.assertEqual(validateList(routers)[0], PASS, "Routers list validation failed") + self.assertEqual(len(routers), 2, "Length of the list router should be 2 (Backup & master)") + + if routers[0].redundantstate == MASTER: + master_router = routers[0] + backup_router = routers[1] + else: + master_router = routers[1] + backup_router = routers[0] + + self.debug("Stopping router ID: %s" % master_router.id) + + try: + Router.stop(self.apiclient, id=master_router.id) + except Exception as e: + self.fail("Failed to stop master router due to error %s" % e) + + # wait for VR to update state + wait_for_cleanup(self.apiclient, ["router.check.interval"]) + + result = verifyRouterState(master_router.id, [UNKNOWN,FAULT]) + if result[0] == FAIL: + self.fail(result[1]) + result = verifyRouterState(backup_router.id, [MASTER]) + if result[0] == FAIL: + self.fail(result[1]) + + try: + virtual_machine_2 = createVirtualMachine(self, network_id=isolated_network_RVR.id) + if netaddr.IPAddress(virtual_machine_2.ipaddress) not in netaddr.IPNetwork(guest_vm_cidr): + self.fail("Newly created VM doesn't get IP from reserverd CIDR") + except Exception as e: + self.fail("VM creation failed, cannot validate the condition: %s" % e) + return + + @attr(tags=["advanced"]) + def test_ip_reservation_in_multiple_networks_same_account(self): + """ Test IP reservation in multiple networks created in same account + # steps + # 1. Create two isolated networks with user defined cidr in same account + # Test below conditions for both the networks in the account + # 2. Create vm in persistent isolated network with ip in guestvmcidr + # 3. Update guestvmcidr + # 4. Create another VM + # + # validation + # 1. Guest vm cidr should be successfully updated with correct value + # 2. Existing guest vm ip should not be changed after reservation + # 3. Newly created VM should get ip in guestvmcidr""" + + account_1 = Account.create(self.apiclient, self.testData["account"], + domainid=self.domain.id) + self.cleanup.append(account_1) + + random_subnet = str(random.randrange(1,254)) + gateway = "10.1." + random_subnet +".1" + isolated_network_1 = Network.create(self.apiclient, self.testData["isolated_network"], + networkofferingid=self.isolated_network_offering.id,accountid=account_1.name, + domainid=self.domain.id,zoneid=self.zone.id, + gateway=gateway, netmask='255.255.255.0') + guest_vm_cidr = "10.1."+random_subnet+".0/29" + + try: + virtual_machine_1 = VirtualMachine.create(self.apiclient, self.testData["virtual_machine"], + networkids=isolated_network_1.id, serviceofferingid=self.service_offering.id, + accountid=account_1.name, domainid=self.domain.id, + ipaddress="10.1."+random_subnet+".3") + except Exception as e: + self.fail("VM creation failed: %s" % e) + + isolated_network_1.update(self.apiclient, guestvmcidr=guest_vm_cidr) + matchNetworkGuestVmCIDR(self, isolated_network_1.id, guest_vm_cidr) + vms = VirtualMachine.list(self.apiclient, + id=virtual_machine_1.id) + self.assertEqual(validateList(vms)[0], PASS, "vm list validation failed") + self.assertEqual(vms[0].nic[0].ipaddress, + virtual_machine_1.ipaddress, + "VM IP should not change after reservation") + + try: + virtual_machine_2 = VirtualMachine.create(self.apiclient, self.testData["virtual_machine"], + networkids=isolated_network_1.id, serviceofferingid=self.service_offering.id, + accountid=account_1.name, domainid=self.domain.id) + if netaddr.IPAddress(virtual_machine_2.ipaddress) not in netaddr.IPNetwork(guest_vm_cidr): + self.fail("Newly created VM doesn't get IP from reserverd CIDR") + except Exception as e: + self.fail("VM creation failed, cannot validate the condition: %s" % e) + + random_subnet = str(random.randrange(1,254)) + gateway = "10.1." + random_subnet +".1" + isolated_network_2 = Network.create(self.apiclient, self.testData["isolated_network"], + networkofferingid=self.isolated_network_offering.id,accountid=account_1.name, + domainid=self.domain.id,zoneid=self.zone.id, + gateway=gateway, netmask='255.255.255.0') + guest_vm_cidr = "10.1."+random_subnet+".0/29" + + try: + virtual_machine_3 = VirtualMachine.create(self.apiclient, self.testData["virtual_machine"], + networkids=isolated_network_2.id, serviceofferingid=self.service_offering.id, + accountid=account_1.name, domainid=self.domain.id, + ipaddress="10.1."+random_subnet+".3") + except Exception as e: + self.fail("VM creation failed: %s" % e) + + isolated_network_2.update(self.apiclient, guestvmcidr=guest_vm_cidr) + matchNetworkGuestVmCIDR(self, isolated_network_2.id, guest_vm_cidr) + vms = VirtualMachine.list(self.apiclient, + id=virtual_machine_3.id) + self.assertEqual(validateList(vms)[0], PASS, "vm list validation failed") + self.assertEqual(vms[0].nic[0].ipaddress, + virtual_machine_3.ipaddress, + "VM IP should not change after reservation") + + try: + virtual_machine_4 = VirtualMachine.create(self.apiclient, self.testData["virtual_machine"], + networkids=isolated_network_2.id, serviceofferingid=self.service_offering.id, + accountid=account_1.name, domainid=self.domain.id) + if netaddr.IPAddress(virtual_machine_4.ipaddress) not in netaddr.IPNetwork(guest_vm_cidr): + self.fail("Newly created VM doesn't get IP from reserverd CIDR") + except Exception as e: + self.fail("VM creation failed, cannot validate the condition: %s" % e) + return + +@ddt +class TestRestartNetwork(cloudstackTestCase): + """Test Restart Network + """ + @classmethod + def setUpClass(cls): + cls.testClient = super(TestRestartNetwork, cls).getClsTestClient() + cls.api_client = cls.testClient.getApiClient() + + # Fill services from the external config file + cls.testData = cls.testClient.getParsedTestDataConfig() + + # Get Zone, Domain and templates + cls.domain = get_domain(cls.api_client) + cls.zone = get_zone(cls.api_client, cls.testClient.getZoneForTests()) + cls.template = get_template( cls.api_client, - cls.services["account"], - domainid=cls.domain.id + cls.zone.id, + cls.testData["ostype"] ) - cls.services["account"] = cls.account.name - cls.services["virtual_machine"]["zoneid"] = cls.zone.id - cls.services["virtual_machine"]["template"] = cls.template.id - cls.service_offering = ServiceOffering.create( + if cls.template == FAILED: + assert False, "get_template() failed to return template with description %s" % cls.testData["ostype"] + cls.testData["domainid"] = cls.domain.id + cls.testData["zoneid"] = cls.zone.id + cls.testData["virtual_machine"]["zoneid"] = cls.zone.id + cls.testData["virtual_machine"]["template"] = cls.template.id + cls._cleanup = [] + try: + cls.service_offering = ServiceOffering.create( cls.api_client, - cls.services["service_offering"] + cls.testData["service_offering"] ) - cls.isolated_network_offering = cls.create_isolated_network_offering("isolated_network_offering") - cls.isolated_persistent_network_offering = cls.create_isolated_network_offering("isolated_persistent_network_offering") - cls.isolated_network = cls.create_isolated_network(cls.isolated_network_offering.id) - cls.isolated_persistent_network = cls.create_isolated_network(cls.isolated_persistent_network_offering.id) - # network will be deleted as part of account cleanup - cls._cleanup = [ - cls.account, cls.service_offering, cls.isolated_network_offering, cls.isolated_persistent_network_offering, - ] + cls._cleanup.append(cls.service_offering) + cls.isolated_network_offering = CreateEnabledNetworkOffering(cls.api_client, + cls.testData["isolated_network_offering"]) + cls._cleanup.append(cls.isolated_network_offering) + cls.isolated_persistent_network_offering = CreateEnabledNetworkOffering(cls.api_client, + cls.testData["nw_off_isolated_persistent"]) + cls._cleanup.append(cls.isolated_persistent_network_offering) + except Exception as e: + cls.tearDownClass() + raise unittest.SkipTest("Failure in setUpClass: %s" % e) return @classmethod @@ -154,44 +587,291 @@ def tearDownClass(cls): raise Exception("Warning: Exception during cleanup : %s" % e) return + def setUp(self): + self.apiclient = self.testClient.getApiClient() + self.dbclient = self.testClient.getDbConnection() + self.cleanup = [] + try: + self.account = Account.create(self.apiclient, self.testData["account"], + domainid=self.domain.id) + self.cleanup.append(self.account) + except Exception as e: + self.skipTest("Failed to create account: %s" % e) + return + + def tearDown(self): + try: + # Clean up, terminate the resources created + cleanup_resources(self.apiclient, self.cleanup) + except Exception as e: + raise Exception("Warning: Exception during cleanup : %s" % e) + return + + @data(True, False) + @attr(tags=["advanced"]) + def test_restart_network_with_cleanup(self, value): + """ Test IP reservation rules with network restart operation + # steps + # 1. Create vm in isolated network with ip in guestvmcidr + # 2. Update guestvmcidr + # 3. Restart network with cleanup True/False + # 4. Deploy another VM in the network + # + # validation + # 1. Guest vm cidr should be successfully updated with correct value + # 2. Existing guest vm ip should not be changed after reservation + # 3. Network should be restarted successfully with and without cleanup + # 4. Newly created VM should get ip in guestvmcidr""" + + subnet = "10.1."+str(random.randrange(1,254)) + gateway = subnet +".1" + resultSet = createIsolatedNetwork(self, self.isolated_network_offering.id, + gateway=gateway) + if resultSet[0] == FAIL: + self.fail("Failed to create isolated network") + else: + isolated_network= resultSet[1] + guest_vm_cidr = subnet+".0/29" + + try: + virtual_machine_1 = createVirtualMachine(self, network_id=isolated_network.id, + ip_address=subnet+".3") + except Exception as e: + self.fail("VM creation failed: %s" % e) + + isolated_network.update(self.apiclient, guestvmcidr=guest_vm_cidr) + matchNetworkGuestVmCIDR(self, isolated_network.id, guest_vm_cidr) + vms = VirtualMachine.list(self.apiclient, + id=virtual_machine_1.id) + self.assertEqual(validateList(vms)[0], PASS, "vm list validation failed") + self.assertEqual(vms[0].nic[0].ipaddress, + virtual_machine_1.ipaddress, + "VM IP should not change after reservation") + + #Restart Network + isolated_network.restart(self.apiclient, cleanup=value) + + try: + virtual_machine_2 = createVirtualMachine(self, network_id=isolated_network.id) + if netaddr.IPAddress(virtual_machine_2.ipaddress) not in netaddr.IPNetwork(guest_vm_cidr): + self.fail("Newly created VM doesn't get IP from reserverd CIDR") + except Exception as e: + self.fail("VM creation failed, cannot validate the condition: %s" % e) + return + +@ddt +class TestUpdateIPReservation(cloudstackTestCase): + """Test Updating IP reservation multiple times + """ @classmethod - def create_isolated_network_offering(cls, network_offering): - isolated_network_offering = NetworkOffering.create( - cls.api_client, - cls.services[network_offering], - conservemode=False - ) - # Update network offering state from disabled to enabled. - network_offering_update_response = NetworkOffering.update( - isolated_network_offering, - cls.api_client, - id=isolated_network_offering.id, - state="enabled" - ) - return isolated_network_offering + def setUpClass(cls): + cls.testClient = super(TestUpdateIPReservation, cls).getClsTestClient() + cls.api_client = cls.testClient.getApiClient() + + # Fill services from the external config file + cls.testData = cls.testClient.getParsedTestDataConfig() + + # Get Zone, Domain and templates + cls.domain = get_domain(cls.api_client) + cls.zone = get_zone(cls.api_client, cls.testClient.getZoneForTests()) + cls.template = get_template( + cls.api_client, + cls.zone.id, + cls.testData["ostype"] + ) + if cls.template == FAILED: + assert False, "get_template() failed to return template with description %s" % cls.testData["ostype"] + cls.testData["domainid"] = cls.domain.id + cls.testData["zoneid"] = cls.zone.id + cls.testData["virtual_machine"]["zoneid"] = cls.zone.id + cls.testData["virtual_machine"]["template"] = cls.template.id + cls._cleanup = [] + try: + cls.service_offering = ServiceOffering.create( + cls.api_client, + cls.testData["service_offering"] + ) + cls._cleanup.append(cls.service_offering) + cls.isolated_network_offering = CreateEnabledNetworkOffering(cls.api_client, + cls.testData["isolated_network_offering"]) + cls._cleanup.append(cls.isolated_network_offering) + cls.isolated_persistent_network_offering = CreateEnabledNetworkOffering(cls.api_client, + cls.testData["nw_off_isolated_persistent"]) + cls._cleanup.append(cls.isolated_persistent_network_offering) + except Exception as e: + cls.tearDownClass() + raise unittest.SkipTest("Failure in setUpClass: %s" % e) + return @classmethod - def create_isolated_network(cls, network_offering_id): - isolated_network = Network.create( - cls.api_client, - cls.services["isolated_network"], - networkofferingid=network_offering_id, - accountid=cls.account.name, - domainid=cls.domain.id, - zoneid=cls.zone.id - ) - cls.debug("isolated network is created: " + isolated_network.id) - return isolated_network + 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 = [] + try: + self.account = Account.create(self.apiclient, self.testData["account"], + domainid=self.domain.id) + self.cleanup.append(self.account) + except Exception as e: + self.skipTest("Failed to create account: %s" % e) + return + + def tearDown(self): + try: + # Clean up, terminate the resources created + cleanup_resources(self.apiclient, self.cleanup) + except Exception as e: + raise Exception("Warning: Exception during cleanup : %s" % e) + return + @data("existingVmInclusive", "existingVmExclusive") + @attr(tags=["advanced"]) + def test_update_network_guestvmcidr(self, value): + """ Test updating guest vm cidr of the network after + VMs are already deployed in previous guest VM cidr + # steps + # 1. Create isolated network with user defined cidr + # 2. Deploy VM in the network + # 3. Try to update the guestvmcidr of the network with VM ip in the guestvmcidr and + # deploy another VM + # 4. Try to update the guestvmcidr of the network with VM ip outside the guestvmcidr + # + # validation + # 1. When vm IP is in the guestvmcidr, updation should be successful and + # new VM should get IP from this range + # 2. When VM IP is outside the guestvmcidr, updation should be unsuccessful""" + + random_subnet = str(random.randrange(1,254)) + gateway = "10.1." + random_subnet +".1" + resultSet = createIsolatedNetwork(self, self.isolated_network_offering.id, + gateway=gateway) + if resultSet[0] == FAIL: + self.fail("Failed to create isolated network") + else: + isolated_network= resultSet[1] + guest_vm_cidr = "10.1."+random_subnet+".0/29" + + try: + virtual_machine_1 = createVirtualMachine(self, network_id=isolated_network.id, + ip_address=u"10.1."+random_subnet+".3") + except Exception as e: + self.fail("VM creation failed: %s" % e) + + isolated_network.update(self.apiclient, guestvmcidr=guest_vm_cidr) + matchNetworkGuestVmCIDR(self, isolated_network.id, guest_vm_cidr) + vms = VirtualMachine.list(self.apiclient, + id=virtual_machine_1.id) + self.assertEqual(validateList(vms)[0], PASS, "vm list validation failed") + self.assertEqual(vms[0].nic[0].ipaddress, + virtual_machine_1.ipaddress, + "VM IP should not change after reservation") + + try: + virtual_machine_2 = createVirtualMachine(self, network_id=isolated_network.id) + if netaddr.IPAddress(virtual_machine_2.ipaddress) not in netaddr.IPNetwork(guest_vm_cidr): + self.fail("Newly created VM doesn't get IP from reserverd CIDR") + except Exception as e: + self.fail("VM creation failed, cannot validate the condition: %s" % e) + + # Update guest vm cidr of network again + if value == "existingVmExclusive": + guest_vm_cidr = "10.1."+random_subnet+".10/29" + + try: + isolated_network.update(self.apiclient, guestvmcidr=guest_vm_cidr) + self.fail("Network updation should fail") + except Exception as e: + self.debug("Failed to update guest VM cidr of network: %s" % e) + elif value == "existingVmInclusive": + guest_vm_cidr = "10.1."+random_subnet+".0/28" + + try: + isolated_network.update(self.apiclient, guestvmcidr=guest_vm_cidr) + except Exception as e: + self.fail("Failed to update guest VM cidr of network: %s" % e) + + matchNetworkGuestVmCIDR(self, isolated_network.id, guest_vm_cidr) + + try: + virtual_machine_3 = createVirtualMachine(self, network_id=isolated_network.id) + if netaddr.IPAddress(virtual_machine_3.ipaddress) not in netaddr.IPNetwork(guest_vm_cidr): + self.fail("Newly created VM doesn't get IP from reserverd CIDR") + except Exception as e: + self.fail("VM creation failed, cannot validate the condition: %s" % e) + return + +@ddt +class TestRouterOperations(cloudstackTestCase): + """Test Router operations of network with IP reservation + """ + @classmethod + def setUpClass(cls): + cls.testClient = super(TestRouterOperations, cls).getClsTestClient() + cls.api_client = cls.testClient.getApiClient() + + # Fill services from the external config file + cls.testData = cls.testClient.getParsedTestDataConfig() + + # Get Zone, Domain and templates + cls.domain = get_domain(cls.api_client) + cls.zone = get_zone(cls.api_client, cls.testClient.getZoneForTests()) + cls.template = get_template( + cls.api_client, + cls.zone.id, + cls.testData["ostype"] + ) + if cls.template == FAILED: + assert False, "get_template() failed to return template with description %s" % cls.testData["ostype"] + cls.testData["domainid"] = cls.domain.id + cls.testData["zoneid"] = cls.zone.id + cls.testData["virtual_machine"]["zoneid"] = cls.zone.id + cls.testData["virtual_machine"]["template"] = cls.template.id + cls._cleanup = [] + try: + cls.service_offering = ServiceOffering.create( + cls.api_client, + cls.testData["service_offering"] + ) + cls._cleanup.append(cls.service_offering) + cls.isolated_network_offering = CreateEnabledNetworkOffering(cls.api_client, + cls.testData["isolated_network_offering"]) + cls._cleanup.append(cls.isolated_network_offering) + cls.isolated_persistent_network_offering = CreateEnabledNetworkOffering(cls.api_client, + cls.testData["nw_off_isolated_persistent"]) + cls._cleanup.append(cls.isolated_persistent_network_offering) + except Exception as e: + cls.tearDownClass() + raise unittest.SkipTest("Failure in setUpClass: %s" % e) + 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 = [ ] - update_response = Network.update(self.isolated_persistent_network, self.apiclient, id=self.isolated_persistent_network.id, guestvmcidr=self.services["isolated_network_cidr"]) - if self.services["isolated_network_cidr"] <> update_response.cidr: - raise Exception("problem in updating cidr for test setup") + self.cleanup = [] + try: + self.account = Account.create(self.apiclient, self.testData["account"], + domainid=self.domain.id) + self.cleanup.append(self.account) + except Exception as e: + self.skipTest("Failed to create account: %s" % e) return def tearDown(self): @@ -202,33 +882,214 @@ def tearDown(self): raise Exception("Warning: Exception during cleanup : %s" % e) return - def create_virtual_machine(self, network_id=None, ip_address=None): - virtual_machine = VirtualMachine.create(self.apiclient, - self.services["virtual_machine"], - networkids=network_id, - serviceofferingid=self.service_offering.id, - accountid=self.account.name, - domainid=self.domain.id, - ipaddress=ip_address - ) - self.debug("Virtual Machine is created: " + virtual_machine.id) - self.cleanup.append(virtual_machine) - return virtual_machine + @attr(tags=["advanced"]) + def test_reservation_after_router_restart(self): + """ Test IP reservation working before and after router is restarted + # steps + # 1. Update guestvmcidr of persistent isolated network + # 2. Reboot router + # + # validation + # 1. Guest vm cidr should be successfully updated with correct value + # 2. Network cidr should remain same after router restart""" + subnet = "10.1."+str(random.randrange(1,254)) + gateway = subnet +".1" + resultSet = createIsolatedNetwork(self, self.isolated_persistent_network_offering.id, + gateway=gateway) + if resultSet[0] == FAIL: + self.fail("Failed to create isolated network") + else: + isolated_network= resultSet[1] + guest_vm_cidr = subnet+".0/29" + + isolated_network.update(self.apiclient, guestvmcidr=guest_vm_cidr) + matchNetworkGuestVmCIDR(self, isolated_network.id, guest_vm_cidr) + + routers = Router.list(self.apiclient, + networkid=isolated_network.id, + listall=True) + self.assertEqual(validateList(routers)[0], PASS, "routers list validation failed") + if not routers: + self.fail("Router list should not be empty") + + Router.reboot(self.apiclient, routers[0].id) + networks = Network.list(self.apiclient, id=isolated_network.id) + self.assertEqual(validateList(networks)[0], PASS, "networks list validation failed") + self.assertEqual(networks[0].cidr, guest_vm_cidr, "guestvmcidr should match after router reboot") + return @attr(tags=["advanced"]) + def test_destroy_recreate_router(self): + """ Test IP reservation working after destroying and recreating router + # steps + # 1. Create isolated network and deploy VM in it and update network with + # guestvmcidr + # 2. List the router associated with network and destroy the router + # 3. Restart the network + # 3. Deploy another VM in the network + # + # validation + # 1. Guest vm cidr should be successfully updated with correct value + # 2. existing guest vm ip should not be changed after reservation + # 3. Router should be destroyed and recreated when network is restarted + # 4. New VM should be deployed in the guestvmcidr""" + + subnet = "10.1."+str(random.randrange(1,254)) + gateway = subnet +".1" + resultSet = createIsolatedNetwork(self, self.isolated_network_offering.id, + gateway=gateway) + if resultSet[0] == FAIL: + self.fail("Failed to create isolated network") + else: + isolated_network= resultSet[1] + guest_vm_cidr = subnet+".0/29" + + try: + virtual_machine_1 = createVirtualMachine(self, network_id=isolated_network.id, + ip_address=subnet+".3") + except Exception as e: + self.fail("VM creation failed: %s" % e) + + isolated_network.update(self.apiclient, guestvmcidr=guest_vm_cidr) + matchNetworkGuestVmCIDR(self, isolated_network.id, guest_vm_cidr) + vms = VirtualMachine.list(self.apiclient, + id=virtual_machine_1.id) + self.assertEqual(validateList(vms)[0], PASS, "vm list validation failed") + self.assertEqual(vms[0].nic[0].ipaddress, + virtual_machine_1.ipaddress, + "VM IP should not change after reservation") + + # List router and destroy it + routers = Router.list(self.apiclient, networkid=isolated_network.id, listall=True) + self.assertEqual(validateList(routers)[0], PASS, "Routers list validation failed") + + # Destroy Router + try: + Router.destroy(self.apiclient, id=routers[0].id) + except Exception as e: + self.fail("Failed to destroy router: %s" % e) + + #Restart Network + try: + isolated_network.restart(self.apiclient) + except Exception as e: + self.fail("Failed to restart network: %s" % e) + + try: + virtual_machine_2 = createVirtualMachine(self, network_id=isolated_network.id) + if netaddr.IPAddress(virtual_machine_2.ipaddress) not in netaddr.IPNetwork(guest_vm_cidr): + self.fail("Newly created VM doesn't get IP from reserverd CIDR") + except Exception as e: + self.fail("VM creation failed, cannot validate the condition: %s" % e) + return + +@ddt +class TestFailureScnarios(cloudstackTestCase): + """Test failure scenarios related to IP reservation in network + """ + @classmethod + def setUpClass(cls): + cls.testClient = super(TestFailureScnarios, cls).getClsTestClient() + cls.api_client = cls.testClient.getApiClient() + + # Fill services from the external config file + cls.testData = cls.testClient.getParsedTestDataConfig() + + # Get Zone, Domain and templates + cls.domain = get_domain(cls.api_client) + cls.zone = get_zone(cls.api_client, cls.testClient.getZoneForTests()) + cls.template = get_template( + cls.api_client, + cls.zone.id, + cls.testData["ostype"] + ) + if cls.template == FAILED: + assert False, "get_template() failed to return template with description %s" % cls.testData["ostype"] + cls.testData["domainid"] = cls.domain.id + cls.testData["zoneid"] = cls.zone.id + cls.testData["virtual_machine"]["zoneid"] = cls.zone.id + cls.testData["virtual_machine"]["template"] = cls.template.id + cls._cleanup = [] + try: + cls.service_offering = ServiceOffering.create( + cls.api_client, + cls.testData["service_offering"] + ) + cls._cleanup.append(cls.service_offering) + cls.isolated_network_offering = CreateEnabledNetworkOffering(cls.api_client, + cls.testData["isolated_network_offering"]) + cls._cleanup.append(cls.isolated_network_offering) + cls.isolated_persistent_network_offering = CreateEnabledNetworkOffering(cls.api_client, + cls.testData["nw_off_isolated_persistent"]) + cls._cleanup.append(cls.isolated_persistent_network_offering) + + cls.testData["shared_network_offering"]["specifyVlan"] = "True" + cls.testData["shared_network_offering"]["specifyIpRanges"] = "True" + + #Create Network Offering + cls.shared_network_offering = NetworkOffering.create(cls.api_client, + cls.testData["shared_network_offering"], + conservemode=False) + cls._cleanup.append(cls.shared_network_offering) + + #Update network offering state from disabled to enabled. + NetworkOffering.update(cls.shared_network_offering,cls.api_client,state="enabled") + except Exception as e: + cls.tearDownClass() + raise unittest.SkipTest("Failure in setUpClass: %s" % e) + 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 = [] + try: + self.account = Account.create(self.apiclient, self.testData["account"], + domainid=self.domain.id) + self.cleanup.append(self.account) + except Exception as e: + self.skipTest("Failed to create account: %s" % e) + return + + def tearDown(self): + try: + # Clean up, terminate the resources created + cleanup_resources(self.apiclient, self.cleanup) + except Exception as e: + raise Exception("Warning: Exception during cleanup : %s" % e) + return + + @attr(tags=["advanced", "selfservice"]) def test_network_not_implemented(self): # steps # 1. update guestvmcidr of isolated network (non persistent) # # validation # should throw exception as network is not in implemented state as no vm is created - try: - update_response = Network.update(self.isolated_network, self.apiclient, id=isolated_network.id, guestvmcidr="10.1.1.0/26") - self.fail("Network Update of guest VM CIDR is successful withot any VM deployed in network") - except Exception as e: - self.debug("Network Update of guest VM CIDR should fail as there is no VM deployed in network") - @attr(tags=["advanced"]) + networkOffering = self.isolated_network_offering + resultSet = createIsolatedNetwork(self, networkOffering.id) + if resultSet[0] == FAIL: + self.fail("Failed to create isolated network") + else: + isolated_network = resultSet[1] + + response = isolated_network.update(self.apiclient, guestvmcidr="10.1.1.0/26") + self.assertEqual(response.errorcode, ERROR_CODE_530, "Job should \ + have failed with error code %s, instead got response \ + %s" % (ERROR_CODE_530, response)) + return + + @attr(tags=["advanced", "selfservice"]) def test_vm_create_after_reservation(self): # steps # 1. create vm in persistent isolated network with ip in guestvmcidr @@ -239,14 +1100,31 @@ def test_vm_create_after_reservation(self): # 1. guest vm cidr should be successfully updated with correct value # 2. existing guest vm ip should not be changed after reservation # 3. newly created VM should get ip in guestvmcidr - guest_vm_cidr = u"10.1.1.0/29" + + networkOffering = self.isolated_persistent_network_offering + subnet = "10.1."+str(random.randrange(1,254)) + gateway = subnet + ".1" + isolated_persistent_network = None + resultSet = createIsolatedNetwork(self, networkOffering.id, gateway=gateway) + if resultSet[0] == FAIL: + self.fail("Failed to create isolated network") + else: + isolated_persistent_network = resultSet[1] + guest_vm_cidr = subnet +".0/29" virtual_machine_1 = None try: - virtual_machine_1 = self.create_virtual_machine(network_id=self.isolated_persistent_network.id, ip_address=u"10.1.1.3") + virtual_machine_1 = VirtualMachine.create(self.apiclient, + self.testData["virtual_machine"], + networkids=isolated_persistent_network.id, + serviceofferingid=self.service_offering.id, + accountid=self.account.name, + domainid=self.domain.id, + ipaddress=subnet+".3" + ) except Exception as e: - self.skipTest("VM creation fails in network ") + self.fail("VM creation fails in network: %s" % e) - update_response = Network.update(self.isolated_persistent_network, self.apiclient, id=self.isolated_persistent_network.id, guestvmcidr=guest_vm_cidr) + update_response = Network.update(isolated_persistent_network, self.apiclient, id=isolated_persistent_network.id, guestvmcidr=guest_vm_cidr) self.assertEqual(guest_vm_cidr, update_response.cidr, "cidr in response is not as expected") vm_list = VirtualMachine.list(self.apiclient, id=virtual_machine_1.id) @@ -257,13 +1135,20 @@ def test_vm_create_after_reservation(self): virtual_machine_1.ipaddress, "VM IP should not change after reservation") try: - virtual_machine_2 = self.create_virtual_machine(network_id=self.isolated_persistent_network.id) + virtual_machine_2 = VirtualMachine.create(self.apiclient, + self.testData["virtual_machine"], + networkids=isolated_persistent_network.id, + serviceofferingid=self.service_offering.id, + accountid=self.account.name, + domainid=self.domain.id + ) if netaddr.IPAddress(virtual_machine_2.ipaddress) not in netaddr.IPNetwork(guest_vm_cidr): self.fail("Newly created VM doesn't get IP from reserverd CIDR") except Exception as e: - self.skipTest("VM creation fails, cannot validate the condition") + self.skipTest("VM creation fails, cannot validate the condition: %s" % e) + return - @attr(tags=["advanced"]) + @attr(tags=["advanced", "selfservice"]) def test_reservation_after_router_restart(self): # steps # 1. update guestvmcidr of persistent isolated network @@ -272,32 +1157,45 @@ def test_reservation_after_router_restart(self): # validation # 1. guest vm cidr should be successfully updated with correct value # 2. network cidr should remain same after router restart - guest_vm_cidr = u"10.1.1.0/29" + networkOffering = self.isolated_persistent_network_offering + subnet = "10.1."+str(random.randrange(1,254)) + gateway = subnet + ".1" + isolated_persistent_network = None + resultSet = createIsolatedNetwork(self, networkOffering.id, gateway=gateway) + if resultSet[0] == FAIL: + self.fail("Failed to create isolated network") + else: + isolated_persistent_network = resultSet[1] + + response = verifyNetworkState(self.apiclient, isolated_persistent_network.id,\ + "implemented") + exceptionOccured = response[0] + isNetworkInDesiredState = response[1] + exceptionMessage = response[2] + + if (exceptionOccured or (not isNetworkInDesiredState)): + self.fail(exceptionMessage) + guest_vm_cidr = subnet +".0/29" - update_response = Network.update(self.isolated_persistent_network, self.apiclient, id=self.isolated_persistent_network.id, guestvmcidr=guest_vm_cidr) + update_response = Network.update(isolated_persistent_network, self.apiclient, id=isolated_persistent_network.id, guestvmcidr=guest_vm_cidr) self.assertEqual(guest_vm_cidr, update_response.cidr, "cidr in response is not as expected") routers = Router.list(self.apiclient, - networkid=self.isolated_persistent_network.id, + networkid=isolated_persistent_network.id, listall=True) - self.assertEqual( - isinstance(routers, list), - True, - "list router should return valid response" - ) - if not routers: - self.skipTest("Router list should not be empty, skipping test") + self.assertEqual(validateList(routers)[0], PASS, + "routers list validation failed") Router.reboot(self.apiclient, routers[0].id) - networks = Network.list(self.apiclient, id=self.isolated_persistent_network.id) + networks = Network.list(self.apiclient, id=isolated_persistent_network.id) self.assertEqual( - isinstance(networks, list), - True, + validateList(networks)[0], PASS, "list Networks should return valid response" ) self.assertEqual(networks[0].cidr, guest_vm_cidr, "guestvmcidr should match after router reboot") + return - @attr(tags=["advanced"]) + @attr(tags=["advanced", "selfservice"]) def test_vm_create_outside_cidr_after_reservation(self): # steps # 1. update guestvmcidr of persistent isolated network @@ -306,11 +1204,25 @@ def test_vm_create_outside_cidr_after_reservation(self): # validation # 1. guest vm cidr should be successfully updated with correct value # 2 newly created VM should not be created and result in exception - guest_vm_cidr = u"10.1.1.0/29" - update_response = Network.update(self.isolated_persistent_network, self.apiclient, id=self.isolated_persistent_network.id, guestvmcidr=guest_vm_cidr) + networkOffering = self.isolated_persistent_network_offering + subnet = "10.1."+str(random.randrange(1,254)) + gateway = subnet + ".1" + isolated_persistent_network = None + resultSet = createIsolatedNetwork(self, networkOffering.id, gateway=gateway) + if resultSet[0] == FAIL: + self.fail("Failed to create isolated network") + else: + isolated_persistent_network = resultSet[1] + guest_vm_cidr = subnet +".0/29" + update_response = Network.update(isolated_persistent_network, self.apiclient, id=isolated_persistent_network.id, guestvmcidr=guest_vm_cidr) self.assertEqual(guest_vm_cidr, update_response.cidr, "cidr in response is not as expected") - try: - self.create_virtual_machine(network_id=self.isolated_persistent_network.id, ip_address=u"10.1.1.9") - self.fail("vm should not be created ") - except Exception as e: - self.debug("exception as IP is outside of guestvmcidr") + with self.assertRaises(Exception): + VirtualMachine.create(self.apiclient, + self.testData["virtual_machine"], + networkids=isolated_persistent_network.id, + serviceofferingid=self.service_offering.id, + accountid=self.account.name, + domainid=self.domain.id, + ipaddress="10.1.1.9" + ) + return diff --git a/test/integration/component/test_ldap.py b/test/integration/component/test_ldap.py index d9e7c351cd..5dd9692837 100644 --- a/test/integration/component/test_ldap.py +++ b/test/integration/component/test_ldap.py @@ -29,9 +29,9 @@ 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 marvin.lib.utils import * +from marvin.lib.base import * +from marvin.lib.common import * from nose.plugins.attrib import attr import urllib @@ -128,7 +128,7 @@ def tearDown(self): raise Exception("Warning: Exception during cleanup : %s" % e) return - @attr(tags=["advanced", "basic"]) + @attr(tags=["advanced", "basic", "selfservice"]) def test_01_addLdapConfiguration(self): """ This test configures LDAP and attempts to authenticate as a user. diff --git a/test/integration/component/test_memory_limits.py b/test/integration/component/test_memory_limits.py index 231307f693..5dd3ba0e5b 100644 --- a/test/integration/component/test_memory_limits.py +++ b/test/integration/component/test_memory_limits.py @@ -19,21 +19,21 @@ # Import Local Modules from nose.plugins.attrib import attr from marvin.cloudstackTestCase import cloudstackTestCase, unittest -from marvin.integration.lib.base import ( +from marvin.lib.base import ( Account, ServiceOffering, VirtualMachine, Resources, Domain ) -from marvin.integration.lib.common import (get_domain, +from marvin.lib.common import (get_domain, get_zone, get_template, wait_for_cleanup, findSuitableHostForMigration, get_resource_type ) -from marvin.integration.lib.utils import cleanup_resources +from marvin.lib.utils import cleanup_resources from marvin.codes import ERROR_NO_HOST_FOR_MIGRATION class Services: @@ -91,12 +91,13 @@ class TestMemoryLimits(cloudstackTestCase): @classmethod def setUpClass(cls): - cls.api_client = super(TestMemoryLimits, - cls).getClsTestClient().getApiClient() + cls.testClient = super(TestMemoryLimits, cls).getClsTestClient() + cls.api_client = cls.testClient.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) + cls.domain = get_domain(cls.api_client) + cls.zone = get_zone(cls.api_client, cls.testClient.getZoneForTests()) cls.services["mode"] = cls.zone.networktype @@ -176,7 +177,7 @@ def createInstance(self, service_off, networks=None, api_client=None): except Exception as e: self.fail("Failed to deploy an instance: %s" % e) - @attr(tags=["advanced", "advancedns","simulator"]) + @attr(tags=["advanced", "advancedns","simulator", "selfservice"]) def test_01_stop_start_instance(self): """Test Deploy VM with specified RAM & verify the usage""" @@ -228,7 +229,7 @@ def test_01_stop_start_instance(self): "Resource count should be same after stopping the instance") return - @attr(tags=["advanced", "advancedns","simulator"]) + @attr(tags=["advanced", "advancedns","simulator", "provisioning"]) def test_02_migrate_instance(self): """Test Deploy VM with specified RAM & verify the usage""" @@ -269,7 +270,7 @@ def test_02_migrate_instance(self): "Resource count should be same after stopping the instance") return - @attr(tags=["advanced", "advancedns","simulator"]) + @attr(tags=["advanced", "advancedns","simulator", "selfservice"]) def test_03_delete_instance(self): """Test Deploy VM with specified GB RAM & verify the usage""" @@ -308,7 +309,7 @@ def test_03_delete_instance(self): self.assertEqual(resource_count_after_delete, 0 , "Resource count for %s should be 0" % get_resource_type(resource_id=9))#RAM return - @attr(tags=["advanced", "advancedns","simulator"]) + @attr(tags=["advanced", "advancedns","simulator", "selfservice"]) def test_04_deploy_multiple_vm(self): """Test Deploy multiple VM with specified RAM & verify the usage""" @@ -370,12 +371,13 @@ class TestDomainMemoryLimitsConfiguration(cloudstackTestCase): @classmethod def setUpClass(cls): - cls.api_client = super(TestDomainMemoryLimitsConfiguration, - cls).getClsTestClient().getApiClient() + cls.testClient = super(TestDomainMemoryLimitsConfiguration, cls).getClsTestClient() + cls.api_client = cls.testClient.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) + cls.domain = get_domain(cls.api_client) + cls.zone = get_zone(cls.api_client, cls.testClient.getZoneForTests()) cls.services["mode"] = cls.zone.networktype cls.template = get_template( @@ -479,7 +481,7 @@ def setupAccounts(self): return - @attr(tags=["advanced", "advancedns","simulator"]) + @attr(tags=["advanced", "advancedns","simulator", "selfservice"]) def test_01_stop_start_instance(self): """Test Deploy VM with 5 GB memory & verify the usage""" @@ -498,7 +500,7 @@ def test_01_stop_start_instance(self): self.account = admin self.domain = domain - api_client = self.testClient.createUserApiClient( + api_client = self.testClient.getUserApiClient( UserName=self.account.name, DomainName=self.account.domain) @@ -551,7 +553,7 @@ def test_01_stop_start_instance(self): "Resource count should be same after starting the instance") return - @attr(tags=["advanced", "advancedns","simulator"]) + @attr(tags=["advanced", "advancedns","simulator", "provisioning"]) def test_02_migrate_instance(self): """Test Deploy VM with specified memory & verify the usage""" @@ -570,7 +572,7 @@ def test_02_migrate_instance(self): self.account = admin self.domain = domain - api_client = self.testClient.createUserApiClient( + api_client = self.testClient.getUserApiClient( UserName=self.account.name, DomainName=self.account.domain) @@ -611,7 +613,7 @@ def test_02_migrate_instance(self): "Resource count should be same after starting the instance") return - @attr(tags=["advanced", "advancedns","simulator"]) + @attr(tags=["advanced", "advancedns","simulator", "selfservice"]) def test_03_delete_instance(self): """Test Deploy VM with specified RAM & verify the usage""" @@ -630,7 +632,7 @@ def test_03_delete_instance(self): self.account = admin self.domain = domain - api_client = self.testClient.createUserApiClient( + api_client = self.testClient.getUserApiClient( UserName=self.account.name, DomainName=self.account.domain) @@ -703,7 +705,7 @@ def test_04_deploy_multiple_vm(self): if memory_account_gc[0].max != 8192: self.skipTest("This test case requires configuration value max.account.memory to be 8192") - api_client = self.testClient.createUserApiClient( + api_client = self.testClient.getUserApiClient( UserName=self.account.name, DomainName=self.account.domain) diff --git a/test/integration/component/test_mm_domain_limits.py b/test/integration/component/test_mm_domain_limits.py index a2b7395cd1..bc8c9ea553 100644 --- a/test/integration/component/test_mm_domain_limits.py +++ b/test/integration/component/test_mm_domain_limits.py @@ -19,14 +19,14 @@ # Import Local Modules from nose.plugins.attrib import attr from marvin.cloudstackTestCase import cloudstackTestCase, unittest -from marvin.integration.lib.base import ( +from marvin.lib.base import ( Account, ServiceOffering, VirtualMachine, Resources, Domain ) -from marvin.integration.lib.common import (get_domain, +from marvin.lib.common import (get_domain, get_zone, get_template, wait_for_cleanup, @@ -34,7 +34,7 @@ get_resource_type, update_resource_count ) -from marvin.integration.lib.utils import cleanup_resources +from marvin.lib.utils import cleanup_resources from marvin.codes import ERROR_NO_HOST_FOR_MIGRATION class Services: @@ -92,12 +92,13 @@ class TestDomainMemoryLimits(cloudstackTestCase): @classmethod def setUpClass(cls): - cls.api_client = super(TestDomainMemoryLimits, - cls).getClsTestClient().getApiClient() + cls.testClient = super(TestDomainMemoryLimits, cls).getClsTestClient() + cls.api_client = cls.testClient.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) + cls.domain = get_domain(cls.api_client) + cls.zone = get_zone(cls.api_client, cls.testClient.getZoneForTests()) cls.services["mode"] = cls.zone.networktype cls.template = get_template( @@ -209,7 +210,7 @@ def setupAccounts(self): domainid=self.child_do_admin_2.domainid) return - @attr(tags=["advanced", "advancedns","simulator"]) + @attr(tags=["advanced", "advancedns","simulator", "selfservice"]) def test_01_change_service_offering(self): """Test Deploy VM with specified RAM & verify the usage""" @@ -234,7 +235,7 @@ def test_01_change_service_offering(self): self.debug("Creating an instance with service offering: %s" % self.service_offering.name) - api_client = self.testClient.createUserApiClient( + api_client = self.testClient.getUserApiClient( UserName=self.account.name, DomainName=self.account.domain) @@ -348,7 +349,7 @@ def test_01_change_service_offering(self): return - @attr(tags=["advanced", "advancedns","simulator"]) + @attr(tags=["advanced", "advancedns","simulator", "provisioning"]) def test_02_migrate_vm(self): """Test Deploy VM with specified RAM & verify the usage""" @@ -371,7 +372,7 @@ def test_02_migrate_vm(self): self.debug("Creating an instance with service offering: %s" % self.service_offering.name) - api_client = self.testClient.createUserApiClient( + api_client = self.testClient.getUserApiClient( UserName=self.account.name, DomainName=self.account.domain) @@ -409,7 +410,7 @@ def test_02_migrate_vm(self): "Resource count should be same after migrating the instance") return - @attr(tags=["advanced", "advancedns","simulator"]) + @attr(tags=["advanced", "advancedns","simulator", "selfservice"]) def test_03_delete_vm(self): """Test Deploy VM with specified RAM & verify the usage""" @@ -432,7 +433,7 @@ def test_03_delete_vm(self): self.debug("Creating an instance with service offering: %s" % self.service_offering.name) - api_client = self.testClient.createUserApiClient( + api_client = self.testClient.getUserApiClient( UserName=self.account.name, DomainName=self.account.domain) @@ -468,7 +469,7 @@ def test_03_delete_vm(self): self.assertEqual(resource_count_after_delete, 0 , "Resource count for %s should be 0" % get_resource_type(resource_id=9))#RAM return - @attr(tags=["advanced", "advancedns","simulator"]) + @attr(tags=["advanced", "advancedns","simulator", "selfservice"]) def test_04_deploy_multiple_vm(self): """Test Deploy multiple VM with specified RAM & verify the usage""" @@ -492,7 +493,7 @@ def test_04_deploy_multiple_vm(self): self.debug("Creating an instance with service offering: %s" % self.service_offering.name) - api_client = self.testClient.createUserApiClient( + api_client = self.testClient.getUserApiClient( UserName=self.account.name, DomainName=self.account.domain) @@ -524,12 +525,13 @@ class TestMultipleChildDomainsMemory(cloudstackTestCase): @classmethod def setUpClass(cls): - cls.api_client = super(TestMultipleChildDomainsMemory, - cls).getClsTestClient().getApiClient() + cls.testClient = super(TestMultipleChildDomainsMemory, cls).getClsTestClient() + cls.api_client = cls.testClient.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) + cls.domain = get_domain(cls.api_client) + cls.zone = get_zone(cls.api_client, cls.testClient.getZoneForTests()) cls.services["mode"] = cls.zone.networktype cls.template = get_template( @@ -682,7 +684,7 @@ def setupAccounts(self): } return users - @attr(tags=["advanced", "advancedns","simulator"]) + @attr(tags=["advanced", "advancedns","simulator", "selfservice"]) def test_01_multiple_child_domains(self): """Test memory limits with multiple child domains""" @@ -709,11 +711,11 @@ def test_01_multiple_child_domains(self): self.debug("Setting up account and domain hierarchy") self.setupAccounts() - api_client_cadmin_1 = self.testClient.createUserApiClient( + api_client_cadmin_1 = self.testClient.getUserApiClient( UserName=self.cadmin_1.name, DomainName=self.cadmin_1.domain) - api_client_cadmin_2 = self.testClient.createUserApiClient( + api_client_cadmin_2 = self.testClient.getUserApiClient( UserName=self.cadmin_2.name, DomainName=self.cadmin_2.domain) diff --git a/test/integration/component/test_mm_max_limits.py b/test/integration/component/test_mm_max_limits.py index e10c119f07..34d4147b90 100644 --- a/test/integration/component/test_mm_max_limits.py +++ b/test/integration/component/test_mm_max_limits.py @@ -19,7 +19,7 @@ # Import Local Modules from nose.plugins.attrib import attr from marvin.cloudstackTestCase import cloudstackTestCase, unittest -from marvin.integration.lib.base import ( +from marvin.lib.base import ( Account, ServiceOffering, VirtualMachine, @@ -27,11 +27,11 @@ Domain, Project ) -from marvin.integration.lib.common import (get_domain, +from marvin.lib.common import (get_domain, get_zone, get_template ) -from marvin.integration.lib.utils import cleanup_resources +from marvin.lib.utils import cleanup_resources class Services: """Test memory resource limit services @@ -88,12 +88,13 @@ class TestMaxMemoryLimits(cloudstackTestCase): @classmethod def setUpClass(cls): - cls.api_client = super(TestMaxMemoryLimits, - cls).getClsTestClient().getApiClient() + cls.testClient = super(TestMaxMemoryLimits, cls).getClsTestClient() + cls.api_client = cls.testClient.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) + cls.domain = get_domain(cls.api_client) + cls.zone = get_zone(cls.api_client, cls.testClient.getZoneForTests()) cls.services["mode"] = cls.zone.networktype cls.template = get_template( @@ -239,7 +240,7 @@ def setupAccounts(self, account_limit=2, domain_limit=2, project_limit=2): (responses.domain, responses.domainid, responses.max)) return - @attr(tags=["advanced", "advancedns","simulator"]) + @attr(tags=["advanced", "advancedns","simulator", "selfservice"]) def test_01_deploy_vm_domain_limit_reached(self): """Test Try to deploy VM with admin account where account has not used the resources but @ domain they are not available""" @@ -253,7 +254,7 @@ def test_01_deploy_vm_domain_limit_reached(self): self.debug("Setting up account and domain hierarchy") self.setupAccounts(account_limit=8, domain_limit=4) - api_client = self.testClient.createUserApiClient( + api_client = self.testClient.getUserApiClient( UserName=self.child_do_admin.name, DomainName=self.child_do_admin.domain) @@ -266,7 +267,7 @@ def test_01_deploy_vm_domain_limit_reached(self): service_off=self.service_offering, api_client=api_client) return - @attr(tags=["advanced", "advancedns","simulator"]) + @attr(tags=["advanced", "advancedns","simulator", "selfservice"]) def test_02_deploy_vm_account_limit_reached(self): """Test Try to deploy VM with admin account where account has used the resources but @ domain they are available""" @@ -280,7 +281,7 @@ def test_02_deploy_vm_account_limit_reached(self): self.debug("Setting up account and domain hierarchy") self.setupAccounts(account_limit=7, domain_limit=14) - api_client = self.testClient.createUserApiClient( + api_client = self.testClient.getUserApiClient( UserName=self.child_do_admin.name, DomainName=self.child_do_admin.domain) @@ -296,7 +297,7 @@ def test_02_deploy_vm_account_limit_reached(self): service_off=self.service_offering, api_client=api_client) return - @attr(tags=["advanced", "advancedns","simulator"]) + @attr(tags=["advanced", "advancedns","simulator", "selfservice"]) def test_03_deploy_vm_project_limit_reached(self): """Test TTry to deploy VM with admin account where account has not used the resources but @ project they are not available""" @@ -310,7 +311,7 @@ def test_03_deploy_vm_project_limit_reached(self): self.debug("Setting up account and domain hierarchy") self.setupAccounts(account_limit=8,domain_limit=8, project_limit=4) - api_client = self.testClient.createUserApiClient( + api_client = self.testClient.getUserApiClient( UserName=self.child_do_admin.name, DomainName=self.child_do_admin.domain) @@ -320,7 +321,7 @@ def test_03_deploy_vm_project_limit_reached(self): service_off=self.service_offering, api_client=api_client) return - @attr(tags=["advanced", "advancedns"]) + @attr(tags=["advanced", "advancedns", "selfservice"]) def test_04_deployVm__account_limit_reached(self): """Test Try to deploy VM with admin account where account has used the resources but @ project they are available""" @@ -334,7 +335,7 @@ def test_04_deployVm__account_limit_reached(self): self.debug("Setting up account and domain hierarchy") self.setupAccounts(account_limit=6, project_limit=12, domain_limit=12) - api_client = self.testClient.createUserApiClient( + api_client = self.testClient.getUserApiClient( UserName=self.child_do_admin.name, DomainName=self.child_do_admin.domain) diff --git a/test/integration/component/test_mm_project_limits.py b/test/integration/component/test_mm_project_limits.py index 29a3b54972..593b2b6400 100644 --- a/test/integration/component/test_mm_project_limits.py +++ b/test/integration/component/test_mm_project_limits.py @@ -19,21 +19,21 @@ # Import Local Modules from nose.plugins.attrib import attr from marvin.cloudstackTestCase import cloudstackTestCase, unittest -from marvin.integration.lib.base import ( +from marvin.lib.base import ( Account, ServiceOffering, VirtualMachine, Domain, Project ) -from marvin.integration.lib.common import (get_domain, +from marvin.lib.common import (get_domain, get_zone, get_template, wait_for_cleanup, findSuitableHostForMigration, get_resource_type ) -from marvin.integration.lib.utils import cleanup_resources +from marvin.lib.utils import cleanup_resources from marvin.codes import ERROR_NO_HOST_FOR_MIGRATION class Services: @@ -91,12 +91,13 @@ class TestProjectsMemoryLimits(cloudstackTestCase): @classmethod def setUpClass(cls): - cls.api_client = super(TestProjectsMemoryLimits, - cls).getClsTestClient().getApiClient() + cls.testClient = super(TestProjectsMemoryLimits, cls).getClsTestClient() + cls.api_client = cls.testClient.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) + cls.domain = get_domain(cls.api_client) + cls.zone = get_zone(cls.api_client, cls.testClient.getZoneForTests()) cls.services["mode"] = cls.zone.networktype cls.template = get_template( @@ -137,7 +138,7 @@ def setUp(self): self.debug("Setting up account and domain hierarchy") self.setupProjectAccounts() - api_client = self.testClient.createUserApiClient( + api_client = self.testClient.getUserApiClient( UserName=self.admin.name, DomainName=self.admin.domain) @@ -216,7 +217,7 @@ def setupProjectAccounts(self): "Check project name from list response") return - @attr(tags=["advanced", "advancedns","simulator"]) + @attr(tags=["advanced", "advancedns","simulator", "selfservice"]) def test_01_project_vmlifecycle_start_stop_instance(self): # Validate the following @@ -273,7 +274,7 @@ def test_01_project_vmlifecycle_start_stop_instance(self): "Resource count should be same after starting the instance") return - @attr(tags=["advanced", "advancedns","simulator"]) + @attr(tags=["advanced", "advancedns","simulator", "provisioning"]) def test_02_project_vmlifecycle_migrate_instance(self): # Validate the following @@ -314,7 +315,7 @@ def test_02_project_vmlifecycle_migrate_instance(self): "Resource count should be same after migrating the instance") return - @attr(tags=["advanced", "advancedns","simulator"]) + @attr(tags=["advanced", "advancedns","simulator", "selfservice"]) def test_03_project_vmlifecycle_delete_instance(self): # Validate the following diff --git a/test/integration/component/test_multiple_ip_ranges.py b/test/integration/component/test_multiple_ip_ranges.py index aae90c4cd4..32c39f7c6a 100644 --- a/test/integration/component/test_multiple_ip_ranges.py +++ b/test/integration/component/test_multiple_ip_ranges.py @@ -18,10 +18,10 @@ """ from marvin.cloudstackTestCase import * from marvin.cloudstackAPI import * -from marvin.cloudstackException import cloudstackAPIException -from marvin.integration.lib.utils import * -from marvin.integration.lib.base import * -from marvin.integration.lib.common import * +from marvin.cloudstackException import CloudstackAPIException +from marvin.lib.utils import * +from marvin.lib.base import * +from marvin.lib.common import * from netaddr import * from nose.plugins.attrib import attr @@ -78,12 +78,14 @@ class TestMultipleIpRanges(cloudstackTestCase): @classmethod def setUpClass(cls): - cls.api_client = super(TestMultipleIpRanges, cls).getClsTestClient().getApiClient() + cls.testClient = super(TestMultipleIpRanges, cls).getClsTestClient() + cls.api_client = cls.testClient.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) - cls.pod = get_pod(cls.api_client, cls.zone.id, cls.services) + cls.domain = get_domain(cls.api_client) + cls.zone = get_zone(cls.api_client, cls.testClient.getZoneForTests()) + cls.pod = get_pod(cls.api_client, cls.zone.id) cls.services['mode'] = cls.zone.networktype cls.services["domainid"] = cls.domain.id cls.services["zoneid"] = cls.zone.id @@ -296,7 +298,7 @@ def test_03_del_ip_range(self): #listing vlan ip ranges with the id should through exception , if not mark the test case as failed try: new_vlan.list(self.apiclient, id=new_vlan.vlan.id) - except cloudstackAPIException as cs: + except CloudstackAPIException as cs: self.debug(cs.errorMsg) self.assertTrue(cs.errorMsg.find("entity does not exist")>0, msg="Failed to delete IP range") return @@ -387,7 +389,7 @@ def test_05_add_overlapped_ip_range(self): self.debug("Adding overlapped ip range") try: new_vlan2 = PublicIpRange.create(self.apiclient, self.services["vlan_ip_range"]) - except cloudstackAPIException as cs: + except CloudstackAPIException as cs: self.debug(cs.errorMsg) self.assertTrue(cs.errorMsg.find("already has IPs that overlap with the new range")>0, msg="Fail:CS allowed adding overlapped ip ranges in guest cidr") return @@ -443,7 +445,7 @@ def test_06_add_ip_range_overlapped_with_two_ranges(self): self.debug("Adding ip range overlapped with two cidrs") try: new_vlan3 = PublicIpRange.create(self.apiclient, self.services["vlan_ip_range"]) - except cloudstackAPIException as cs: + except CloudstackAPIException as cs: self.debug(cs.errorMsg) self.assertTrue(cs.errorMsg.find("already has IPs that overlap with the new range")>0, msg="Fail:CS allowed adding overlapped ip ranges in guest cidr") return @@ -496,7 +498,7 @@ def test_07_add_iprange_superset(self): self.debug("Adding IP range super set to existing CIDR") try: new_vlan2 = PublicIpRange.create(self.apiclient, self.services["vlan_ip_range"]) - except cloudstackAPIException as cs: + except CloudstackAPIException as cs: self.debug(cs.errorMsg) self.assertTrue(cs.errorMsg.find("superset")>0, msg="Fail: CS allowed adding ip range superset to existing CIDR") return @@ -549,7 +551,7 @@ def test_08_add_iprange_subset(self): self.debug("Adding ip range subset to existing cidr") try: new_vlan2 = PublicIpRange.create(self.apiclient, self.services["vlan_ip_range"]) - except cloudstackAPIException as cs: + except CloudstackAPIException as cs: self.debug(cs.errorMsg) self.assertTrue(cs.errorMsg.find("subset")>0, msg="Fail: CS allowed adding ip range subset to existing CIDR") return diff --git a/test/integration/component/test_multiple_ips_per_nic.py b/test/integration/component/test_multiple_ips_per_nic.py index dcbb453e7e..2db15e5da5 100644 --- a/test/integration/component/test_multiple_ips_per_nic.py +++ b/test/integration/component/test_multiple_ips_per_nic.py @@ -23,32 +23,35 @@ Design Document: https://cwiki.apache.org/confluence/display/CLOUDSTACK/Multiple+IP+address+per+NIC """ from marvin.cloudstackTestCase import cloudstackTestCase -from marvin.integration.lib.utils import (cleanup_resources, - validateList, - random_gen) -from marvin.integration.lib.base import (Account, - ServiceOffering, - Network, - VirtualMachine, - VpcOffering, - VPC, - NIC, - Domain, - PublicIPAddress, - StaticNATRule, - FireWallRule, - NATRule) -from marvin.integration.lib.common import (get_domain, - get_zone, - get_template, - get_free_vlan, - setSharedNetworkParams, - createEnabledNetworkOffering, - shouldTestBeSkipped) - +from marvin.lib.utils import (cleanup_resources, + validateList, + random_gen) +from marvin.lib.base import (Account, + VirtualMachine, + ServiceOffering, + PublicIPAddress, + NIC, + FireWallRule, + NATRule, + StaticNATRule, + VpcOffering, + Domain, + Network, + Router, + VPC + ) +from marvin.lib.common import (get_domain, + get_zone, + get_template, + get_free_vlan, + setSharedNetworkParams, + createEnabledNetworkOffering, + shouldTestBeSkipped, + wait_for_cleanup) from nose.plugins.attrib import attr -from marvin.codes import PASS, ISOLATED_NETWORK, VPC_NETWORK, SHARED_NETWORK, FAIL +from marvin.codes import PASS, ISOLATED_NETWORK, VPC_NETWORK, SHARED_NETWORK, FAIL, FAILED from ddt import ddt, data +import time def createNetwork(self, networkType): """Create a network of given type (isolated/shared/isolated in VPC)""" @@ -137,21 +140,23 @@ class TestBasicOperations(cloudstackTestCase): @classmethod def setUpClass(cls): - cloudstackTestClient = super(TestBasicOperations,cls).getClsTestClient() - cls.api_client = cloudstackTestClient.getApiClient() + cls.testClient = super(TestBasicOperations, cls).getClsTestClient() + cls.api_client = cls.testClient.getApiClient() # Fill services from the external config file - cls.services = cloudstackTestClient.getConfigParser().parsedDict + cls.services = cls.testClient.getParsedTestDataConfig() # Get Zone, Domain and templates - cls.domain = get_domain(cls.api_client, cls.services) - cls.zone = get_zone(cls.api_client, cls.services) - cls.mode = str(cls.zone.networktype).lower() + cls.domain = get_domain(cls.api_client) + cls.zone = get_zone(cls.api_client, cls.testClient.getZoneForTests()) cls.template = get_template( cls.api_client, cls.zone.id, cls.services["ostype"] ) + if cls.template == FAILED: + assert False, "get_template() failed to return template with description %s" % cls.services["ostype"] + cls.services["virtual_machine"]["zoneid"] = cls.zone.id cls.services["virtual_machine"]["template"] = cls.template.id cls.service_offering = ServiceOffering.create( @@ -159,14 +164,14 @@ def setUpClass(cls): cls.services["service_offering"] ) cls._cleanup = [cls.service_offering] - cls.services["shared_network_offering"]["specifyVlan"] = "True" - cls.services["shared_network_offering"]["specifyIpRanges"] = "True" + cls.services["shared_network_offering_all_services"]["specifyVlan"] = "True" + cls.services["shared_network_offering_all_services"]["specifyIpRanges"] = "True" cls.shared_network_offering = CreateEnabledNetworkOffering(cls.api_client, - cls.services["shared_network_offering"]) + cls.services["shared_network_offering_all_services"]) cls._cleanup.append(cls.shared_network_offering) - - if cls.mode == "advanced": + cls.mode = cls.zone.networktype + if cls.mode.lower() == "advanced": cls.isolated_network_offering = CreateEnabledNetworkOffering(cls.api_client, cls.services["isolated_network_offering"]) cls._cleanup.append(cls.isolated_network_offering) @@ -442,7 +447,7 @@ def test_operations_non_root_admin_api_client(self, value): self.cleanup.append(self.account) self.cleanup.append(child_domain) - apiclient = self.testClient.createUserApiClient(UserName=self.account.name, DomainName=self.account.domain) + apiclient = self.testClient.getUserApiClient(UserName=self.account.name, DomainName=self.account.domain) if(shouldTestBeSkipped(networkType=value, zoneType=self.mode)): self.skipTest("Skipping test as %s network is not supported in basic zone" % value) @@ -459,7 +464,7 @@ def test_operations_non_root_admin_api_client(self, value): try: ipaddress_1 = NIC.addIp(apiclient, id=virtual_machine.nic[0].id) except Exception as e: - self.fail("Failed while adding secondary IP to NIC of vm %s" % virtual_machine.id) + self.fail("Failed while adding secondary IP to NIC of vm %s: %s" % (virtual_machine.id, e)) try: NIC.list(apiclient, virtualmachineid=virtual_machine.id) @@ -486,21 +491,23 @@ class TestNetworkRules(cloudstackTestCase): @classmethod def setUpClass(cls): - cloudstackTestClient = super(TestNetworkRules,cls).getClsTestClient() - cls.api_client = cloudstackTestClient.getApiClient() + cls.testClient = super(TestNetworkRules, cls).getClsTestClient() + cls.api_client = cls.testClient.getApiClient() # Fill services from the external config file - cls.services = cloudstackTestClient.getConfigParser().parsedDict + cls.services = cls.testClient.getParsedTestDataConfig() # Get Zone, Domain and templates - cls.domain = get_domain(cls.api_client, cls.services) - cls.zone = get_zone(cls.api_client, cls.services) - cls.mode = str(cls.zone.networktype).lower() + cls.domain = get_domain(cls.api_client) + cls.zone = get_zone(cls.api_client, cls.testClient.getZoneForTests()) cls.template = get_template( cls.api_client, cls.zone.id, cls.services["ostype"] ) + if cls.template == FAILED: + assert False, "get_template() failed to return template with description %s" % cls.services["ostype"] + cls.services["virtual_machine"]["zoneid"] = cls.zone.id cls.services["virtual_machine"]["template"] = cls.template.id cls.service_offering = ServiceOffering.create( @@ -508,13 +515,14 @@ def setUpClass(cls): cls.services["service_offering"] ) cls._cleanup = [cls.service_offering] - cls.services["shared_network_offering"]["specifyVlan"] = "True" - cls.services["shared_network_offering"]["specifyIpRanges"] = "True" + cls.services["shared_network_offering_all_services"]["specifyVlan"] = "True" + cls.services["shared_network_offering_all_services"]["specifyIpRanges"] = "True" - cls.shared_network_offering = CreateEnabledNetworkOffering(cls.api_client, cls.services["shared_network_offering"]) + cls.shared_network_offering = CreateEnabledNetworkOffering(cls.api_client, + cls.services["shared_network_offering_all_services"]) cls._cleanup.append(cls.shared_network_offering) - - if cls.mode == "advanced": + cls.mode = cls.zone.networktype + if cls.mode.lower() == "advanced": cls.isolated_network_offering = CreateEnabledNetworkOffering(cls.api_client, cls.services["isolated_network_offering"]) cls._cleanup.append(cls.isolated_network_offering) cls.isolated_network_offering_vpc = CreateEnabledNetworkOffering(cls.api_client, cls.services["nw_offering_isolated_vpc"]) @@ -851,3 +859,440 @@ def test_disable_static_nat(self, value): public_ip.delete(self.apiclient) return + +@ddt +class TestVmNetworkOperations(cloudstackTestCase): + """Test VM and Network operations with network rules created on secondary IP + """ + + @classmethod + def setUpClass(cls): + cls.testClient = super(TestVmNetworkOperations, cls).getClsTestClient() + cls.api_client = cls.testClient.getApiClient() + + # Fill services from the external config file + cls.services = cls.testClient.getParsedTestDataConfig() + + # Get Zone, Domain and templates + cls.domain = get_domain(cls.api_client) + cls.zone = get_zone(cls.api_client, cls.testClient.getZoneForTests()) + cls.template = get_template( + cls.api_client, + cls.zone.id, + cls.services["ostype"] + ) + if cls.template == FAILED: + assert False, "get_template() failed to return template with description %s" % cls.services["ostype"] + 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.service_offering] + cls.services["shared_network_offering_all_services"]["specifyVlan"] = "True" + cls.services["shared_network_offering_all_services"]["specifyIpRanges"] = "True" + + cls.shared_network_offering = CreateEnabledNetworkOffering(cls.api_client, + cls.services["shared_network_offering_all_services"]) + cls._cleanup.append(cls.shared_network_offering) + cls.mode = cls.zone.networktype + if cls.mode.lower() == "advanced": + cls.isolated_network_offering = CreateEnabledNetworkOffering(cls.api_client, cls.services["isolated_network_offering"]) + cls._cleanup.append(cls.isolated_network_offering) + cls.isolated_network_offering_vpc = CreateEnabledNetworkOffering(cls.api_client, cls.services["nw_offering_isolated_vpc"]) + cls._cleanup.append(cls.isolated_network_offering_vpc) + cls.vpc_off = VpcOffering.create(cls.api_client, cls.services["vpc_offering"]) + cls.vpc_off.update(cls.api_client, state='Enabled') + cls._cleanup.append(cls.vpc_off) + 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 resources created + cleanup_resources(self.apiclient, self.cleanup) + except Exception as e: + raise Exception("Warning: Exception during cleanup : %s" % e) + return + + def VerifyStaticNatForPublicIp(self, ipaddressid, natrulestatus): + """ List public IP and verify that NAT rule status for the IP is as desired """ + + publiciplist = PublicIPAddress.list(self.apiclient, id=ipaddressid, listall=True) + self.assertEqual(validateList(publiciplist)[0], PASS, "Public IP list validation failed") + self.assertEqual(publiciplist[0].isstaticnat, natrulestatus, "isstaticnat should be %s, it is %s" % + (natrulestatus, publiciplist[0].isstaticnat)) + + return + + @data(ISOLATED_NETWORK, SHARED_NETWORK, VPC_NETWORK) + @attr(tags=["advanced"]) + def test_delete_vm(self, value): + """ Test delete VM and verify network rules are cleaned up""" + + # Steps: + # 1. Create Account and create network in it (isoalted/ shared/ vpc) + # 2. Deploy a VM in this network and account + # 3. Add 2 secondary IPs to the default nic of VM + # 4. Acquire 2 public IPs in the network + # 5. For 1st public IP create nat rule to 1st private IP, for 2nd public IP, create + # static nat rule to 2nd private IP + # 6. Destroy the virtual machine + # 7. Verify that nat rule does not exist and static nat is not enabled for + # secondary IP + + self.account = Account.create(self.apiclient,self.services["account"],domainid=self.domain.id) + self.cleanup.append(self.account) + + network = createNetwork(self, value) + + try: + virtual_machine = VirtualMachine.create(self.apiclient,self.services["virtual_machine"], + networkids=[network.id],serviceofferingid=self.service_offering.id, + accountid=self.account.name,domainid=self.account.domainid) + except Exception as e: + self.fail("vm creation failed: %s" % e) + + # Add secondary IPs to default NIC of VM + try: + ipaddress_1 = NIC.addIp(self.apiclient, id=virtual_machine.nic[0].id) + ipaddress_2 = NIC.addIp(self.apiclient, id=virtual_machine.nic[0].id) + except Exception as e: + self.fail("Failed while adding secondary IP to NIC of vm %s" % virtual_machine.id) + + # Acquire public IP addresses in the network + try: + public_ip_1 = PublicIPAddress.create(self.api_client,accountid=self.account.name, + zoneid=self.zone.id,domainid=self.account.domainid, + networkid=network.id, vpcid = network.vpcid if value == VPC_NETWORK else None) + + public_ip_2 = PublicIPAddress.create(self.api_client,accountid=self.account.name, + zoneid=self.zone.id,domainid=self.account.domainid, + networkid=network.id, vpcid = network.vpcid if value == VPC_NETWORK else None) + except Exception as e: + self.fail("Exception while acquiring public ip address: %s" % e) + + # Create Firewall and natrule for 1st IP and static nat rule for 2nd IP + if value != VPC_NETWORK: + FireWallRule.create(self.apiclient,ipaddressid=public_ip_1.ipaddress.id, + protocol='TCP', cidrlist=[self.services["fwrule"]["cidr"]], + startport=self.services["fwrule"]["startport"],endport=self.services["fwrule"]["endport"]) + + natrule = NATRule.create(self.api_client, virtual_machine, + self.services["natrule"],ipaddressid=public_ip_1.ipaddress.id, + networkid=network.id, vmguestip = ipaddress_1.ipaddress) + + StaticNATRule.enable(self.apiclient, public_ip_2.ipaddress.id, virtual_machine.id, + network.id, vmguestip=ipaddress_2.ipaddress) + + # Delete VM + virtual_machine.delete(self.apiclient) + + # Wait for VMs to expunge + wait_for_cleanup(self.api_client, ["expunge.delay", "expunge.interval"]) + + # Make sure the VM is expunged + retriesCount = 20 + while True: + vms = VirtualMachine.list(self.apiclient, id=virtual_machine.id) + if vms is None: + break + elif retriesCount == 0: + self.fail("Failed to expunge vm even after 20 minutes") + time.sleep(60) + retriesCount -= 1 + + # Try to list nat rule + with self.assertRaises(Exception): + NATRule.list(self.apiclient, id=natrule.id, listall=True) + + # Verify static nat rule is no longer enabled + self.VerifyStaticNatForPublicIp(public_ip_2.ipaddress.id, False) + return + + @data(ISOLATED_NETWORK, SHARED_NETWORK, VPC_NETWORK) + @attr(tags=["advanced"]) + def test_recover_vm(self, value): + """ Test recover VM operation with VM having secondary IPs""" + + # Steps: + # 1. Create Account and create network in it (isoalted/ shared/ vpc) + # 2. Deploy a VM in this network and account + # 3. Add 2 secondary IPs to the default nic of VM + # 4. Acquire 2 public IPs in the network + # 5. For 1st public IP create nat rule to 1st private IP, for 2nd public IP, create + # static nat rule to 2nd private IP + # 6. Destroy the virtual machine and recover it + # 7. Verify that nat and static nat rules exist + + self.account = Account.create(self.apiclient,self.services["account"],domainid=self.domain.id) + self.cleanup.append(self.account) + + network = createNetwork(self, value) + + try: + virtual_machine = VirtualMachine.create(self.apiclient,self.services["virtual_machine"], + networkids=[network.id],serviceofferingid=self.service_offering.id, + accountid=self.account.name,domainid=self.account.domainid) + except Exception as e: + self.fail("vm creation failed: %s" % e) + + try: + ipaddress_1 = NIC.addIp(self.apiclient, id=virtual_machine.nic[0].id) + ipaddress_2 = NIC.addIp(self.apiclient, id=virtual_machine.nic[0].id) + except Exception as e: + self.fail("Failed while adding secondary IP to NIC of vm %s" % virtual_machine.id) + + try: + public_ip_1 = PublicIPAddress.create(self.api_client,accountid=self.account.name, + zoneid=self.zone.id,domainid=self.account.domainid, + networkid=network.id, vpcid = network.vpcid if value == VPC_NETWORK else None) + + public_ip_2 = PublicIPAddress.create(self.api_client,accountid=self.account.name, + zoneid=self.zone.id,domainid=self.account.domainid, + networkid=network.id, vpcid = network.vpcid if value == VPC_NETWORK else None) + except Exception as e: + self.fail("Exception while acquiring public ip address: %s" % e) + + if value != VPC_NETWORK: + FireWallRule.create(self.apiclient,ipaddressid=public_ip_1.ipaddress.id, + protocol='TCP', cidrlist=[self.services["fwrule"]["cidr"]], + startport=self.services["fwrule"]["startport"],endport=self.services["fwrule"]["endport"]) + + natrule = NATRule.create(self.api_client, virtual_machine, + self.services["natrule"],ipaddressid=public_ip_1.ipaddress.id, + networkid=network.id, vmguestip = ipaddress_1.ipaddress) + + StaticNATRule.enable(self.apiclient, public_ip_2.ipaddress.id, virtual_machine.id, + network.id, vmguestip=ipaddress_2.ipaddress) + + virtual_machine.delete(self.apiclient) + virtual_machine.recover(self.apiclient) + + retriesCount = 10 + while True: + vms = VirtualMachine.list(self.apiclient, id=virtual_machine.id) + self.assertEqual(validateList(vms)[0], PASS, "vms list validation failed") + if str(vms[0].state).lower() == "stopped": + break + elif retriesCount == 0: + self.fail("Failed to recover vm even after 10 mins") + time.sleep(60) + retriesCount -= 1 + + natrules = NATRule.list(self.apiclient, id=natrule.id, listall=True) + self.assertEqual(validateList(natrules)[0], PASS, "nat rules validation failed") + + self.VerifyStaticNatForPublicIp(public_ip_2.ipaddress.id, True) + + return + + @data(ISOLATED_NETWORK, SHARED_NETWORK, VPC_NETWORK) + @attr(tags=["advanced"]) + def test_network_restart_cleanup_true(self, value): + """Test network restart (cleanup True) with VM having secondary IPs and related network rules""" + + # Steps: + # 1. Create Account and create network in it (isoalted/ shared/ vpc) + # 2. Deploy a VM in this network and account + # 3. Add 2 secondary IPs to the default nic of VM + # 4. Acquire 2 public IPs in the network + # 5. For 1st public IP create nat rule to 1st private IP, for 2nd public IP, create + # static nat rule to 2nd private IP + # 6. Restart the network with cleanup option True + # 7. Verify that nat and static nat rules exist after network restart + + self.account = Account.create(self.apiclient,self.services["account"],domainid=self.domain.id) + self.cleanup.append(self.account) + + network = createNetwork(self, value) + + try: + virtual_machine = VirtualMachine.create(self.apiclient,self.services["virtual_machine"], + networkids=[network.id],serviceofferingid=self.service_offering.id, + accountid=self.account.name,domainid=self.account.domainid) + except Exception as e: + self.fail("vm creation failed: %s" % e) + + try: + ipaddress_1 = NIC.addIp(self.apiclient, id=virtual_machine.nic[0].id) + ipaddress_2 = NIC.addIp(self.apiclient, id=virtual_machine.nic[0].id) + except Exception as e: + self.fail("Failed while adding secondary IP to NIC of vm %s" % virtual_machine.id) + + try: + public_ip_1 = PublicIPAddress.create(self.api_client,accountid=self.account.name, + zoneid=self.zone.id,domainid=self.account.domainid, + networkid=network.id, vpcid = network.vpcid if value == VPC_NETWORK else None) + + public_ip_2 = PublicIPAddress.create(self.api_client,accountid=self.account.name, + zoneid=self.zone.id,domainid=self.account.domainid, + networkid=network.id, vpcid = network.vpcid if value == VPC_NETWORK else None) + except Exception as e: + self.fail("Exception while acquiring public ip address: %s" % e) + + if value != VPC_NETWORK: + FireWallRule.create(self.apiclient,ipaddressid=public_ip_1.ipaddress.id, + protocol='TCP', cidrlist=[self.services["fwrule"]["cidr"]], + startport=self.services["fwrule"]["startport"],endport=self.services["fwrule"]["endport"]) + + natrule = NATRule.create(self.api_client, virtual_machine, + self.services["natrule"],ipaddressid=public_ip_1.ipaddress.id, + networkid=network.id, vmguestip = ipaddress_1.ipaddress) + + StaticNATRule.enable(self.apiclient, public_ip_2.ipaddress.id, virtual_machine.id, + network.id, vmguestip=ipaddress_2.ipaddress) + + network.restart(self.apiclient, cleanup=True) + + natrulelist = NATRule.list(self.apiclient, id=natrule.id, listall=True) + self.assertEqual(validateList(natrulelist)[0], PASS, "nat rules list validation failed") + + self.VerifyStaticNatForPublicIp(public_ip_2.ipaddress.id, True) + return + + @data(ISOLATED_NETWORK, SHARED_NETWORK, VPC_NETWORK) + @attr(tags=["advanced"]) + def test_network_restart_cleanup_false(self, value): + """Test network restart (cleanup True) with VM having secondary IPs and related network rules""" + + # Steps: + # 1. Create Account and create network in it (isoalted/ shared/ vpc) + # 2. Deploy a VM in this network and account + # 3. Add 2 secondary IPs to the default nic of VM + # 4. Acquire 2 public IPs in the network + # 5. For 1st public IP create nat rule to 1st private IP, for 2nd public IP, create + # static nat rule to 2nd private IP + # 6. Restart the network with cleanup option False + # 7. Verify that nat and static nat rules exist after network restart + + self.account = Account.create(self.apiclient,self.services["account"],domainid=self.domain.id) + self.cleanup.append(self.account) + + network = createNetwork(self, value) + + try: + virtual_machine = VirtualMachine.create(self.apiclient,self.services["virtual_machine"], + networkids=[network.id],serviceofferingid=self.service_offering.id, + accountid=self.account.name,domainid=self.account.domainid) + except Exception as e: + self.fail("vm creation failed: %s" % e) + + try: + ipaddress_1 = NIC.addIp(self.apiclient, id=virtual_machine.nic[0].id) + ipaddress_2 = NIC.addIp(self.apiclient, id=virtual_machine.nic[0].id) + except Exception as e: + self.fail("Failed while adding secondary IP to NIC of vm %s" % virtual_machine.id) + + try: + public_ip_1 = PublicIPAddress.create(self.api_client,accountid=self.account.name, + zoneid=self.zone.id,domainid=self.account.domainid, + networkid=network.id, vpcid = network.vpcid if value == VPC_NETWORK else None) + + public_ip_2 = PublicIPAddress.create(self.api_client,accountid=self.account.name, + zoneid=self.zone.id,domainid=self.account.domainid, + networkid=network.id, vpcid = network.vpcid if value == VPC_NETWORK else None) + except Exception as e: + self.fail("Exception while acquiring public ip address: %s" % e) + + if value != VPC_NETWORK: + FireWallRule.create(self.apiclient,ipaddressid=public_ip_1.ipaddress.id, + protocol='TCP', cidrlist=[self.services["fwrule"]["cidr"]], + startport=self.services["fwrule"]["startport"],endport=self.services["fwrule"]["endport"]) + + natrule = NATRule.create(self.api_client, virtual_machine, + self.services["natrule"],ipaddressid=public_ip_1.ipaddress.id, + networkid=network.id, vmguestip = ipaddress_1.ipaddress) + + StaticNATRule.enable(self.apiclient, public_ip_2.ipaddress.id, virtual_machine.id, + network.id, vmguestip=ipaddress_2.ipaddress) + + network.restart(self.apiclient, cleanup=False) + + natrulelist = NATRule.list(self.apiclient, id=natrule.id, listall=True) + self.assertEqual(validateList(natrulelist)[0], PASS, "nat rules list validation failed") + + self.VerifyStaticNatForPublicIp(public_ip_2.ipaddress.id, True) + return + + @data(ISOLATED_NETWORK, SHARED_NETWORK, VPC_NETWORK) + @attr(tags=["advanced"]) + def test_reboot_router_VM(self, value): + """ Test reboot router and persistence of network rules""" + + # Steps: + # 1. Create Account and create network in it (isoalted/ shared/ vpc) + # 2. Deploy a VM in this network and account + # 3. Add 2 secondary IPs to the default nic of VM + # 4. Acquire 2 public IPs in the network + # 5. For 1st public IP create nat rule to 1st private IP, for 2nd public IP, create + # static nat rule to 2nd private IP + # 6. Reboot router VM + # 7. Verify that nat and static nat rules exist after router restart + + self.account = Account.create(self.apiclient,self.services["account"],domainid=self.domain.id) + self.cleanup.append(self.account) + + network = createNetwork(self, value) + + try: + virtual_machine = VirtualMachine.create(self.apiclient,self.services["virtual_machine"], + networkids=[network.id],serviceofferingid=self.service_offering.id, + accountid=self.account.name,domainid=self.account.domainid) + except Exception as e: + self.fail("vm creation failed: %s" % e) + + try: + ipaddress_1 = NIC.addIp(self.apiclient, id=virtual_machine.nic[0].id) + ipaddress_2 = NIC.addIp(self.apiclient, id=virtual_machine.nic[0].id) + except Exception as e: + self.fail("Failed while adding secondary IP to NIC of vm %s" % virtual_machine.id) + + try: + public_ip_1 = PublicIPAddress.create(self.api_client,accountid=self.account.name, + zoneid=self.zone.id,domainid=self.account.domainid, + networkid=network.id, vpcid = network.vpcid if value == VPC_NETWORK else None) + + public_ip_2 = PublicIPAddress.create(self.api_client,accountid=self.account.name, + zoneid=self.zone.id,domainid=self.account.domainid, + networkid=network.id, vpcid = network.vpcid if value == VPC_NETWORK else None) + except Exception as e: + self.fail("Exception while acquiring public ip address: %s" % e) + + if value != VPC_NETWORK: + FireWallRule.create(self.apiclient,ipaddressid=public_ip_1.ipaddress.id, + protocol='TCP', cidrlist=[self.services["fwrule"]["cidr"]], + startport=self.services["fwrule"]["startport"],endport=self.services["fwrule"]["endport"]) + + natrule = NATRule.create(self.api_client, virtual_machine, + self.services["natrule"],ipaddressid=public_ip_1.ipaddress.id, + networkid=network.id, vmguestip = ipaddress_1.ipaddress) + + StaticNATRule.enable(self.apiclient, public_ip_2.ipaddress.id, virtual_machine.id, + network.id, vmguestip=ipaddress_2.ipaddress) + + routers = Router.list(self.apiclient, networkid=network.id, listall=True) + self.assertEqual(validateList(routers)[0], PASS, "routers list validation failed") + + Router.reboot(self.apiclient, id=routers[0].id) + + natrulelist = NATRule.list(self.apiclient, id=natrule.id, listall=True) + self.assertEqual(validateList(natrulelist)[0], PASS, "nat rules list validation failed") + + self.VerifyStaticNatForPublicIp(public_ip_2.ipaddress.id, True) + return diff --git a/test/integration/component/test_netscaler_configs.py b/test/integration/component/test_netscaler_configs.py index 98c47485e3..6d856094f7 100644 --- a/test/integration/component/test_netscaler_configs.py +++ b/test/integration/component/test_netscaler_configs.py @@ -18,15 +18,28 @@ """ P1 tests for netscaler configurations """ #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.cloudstackTestCase import cloudstackTestCase +#from marvin.cloudstackAPI import * +from marvin.lib.utils import (cleanup_resources, + random_gen) +from marvin.lib.base import (VirtualMachine, + NetworkServiceProvider, + PublicIPAddress, + Account, + Network, + NetScaler, + LoadBalancerRule, + NetworkOffering, + ServiceOffering, + PhysicalNetwork, + Configurations) +from marvin.lib.common import (get_domain, + get_zone, + get_template, + add_netscaler) from marvin.sshClient import SshClient -import datetime +import time class Services: @@ -156,14 +169,13 @@ class TestAddNetScaler(cloudstackTestCase): @classmethod def setUpClass(cls): - cls.api_client = super( - TestAddNetScaler, - cls - ).getClsTestClient().getApiClient() + cls.testClient = super(TestAddNetScaler, cls).getClsTestClient() + cls.api_client = cls.testClient.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) + cls.domain = get_domain(cls.api_client) + cls.zone = get_zone(cls.api_client, cls.testClient.getZoneForTests()) cls._cleanup = [] return @@ -192,7 +204,7 @@ def tearDown(self): raise Exception("Warning: Exception during cleanup : %s" % e) return - @attr(tags = ["advancedns"]) + @attr(tags=["advancedns", "provisioning"]) def test_add_netscaler_device(self): """Test add netscaler device """ @@ -282,14 +294,13 @@ class TestInvalidParametersNetscaler(cloudstackTestCase): @classmethod def setUpClass(cls): - cls.api_client = super( - TestInvalidParametersNetscaler, - cls - ).getClsTestClient().getApiClient() + cls.testClient = super(TestInvalidParametersNetscaler, cls).getClsTestClient() + cls.api_client = cls.testClient.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) + cls.domain = get_domain(cls.api_client) + cls.zone = get_zone(cls.api_client, cls.testClient.getZoneForTests()) cls._cleanup = [] return @@ -318,7 +329,7 @@ def tearDown(self): raise Exception("Warning: Exception during cleanup : %s" % e) return - @attr(tags = ["advancedns"]) + @attr(tags=["advancedns", "provisioning"]) def test_invalid_cred(self): """Test add netscaler device with invalid credential """ @@ -387,7 +398,7 @@ def test_invalid_cred(self): ) return - @attr(tags = ["advancedns"]) + @attr(tags=["advancedns", "provisioning"]) def test_invalid_public_interface(self): """Test add netscaler device with invalid public interface """ @@ -454,7 +465,7 @@ def test_invalid_public_interface(self): ) return - @attr(tags = ["advancedns"]) + @attr(tags=["advancedns", "provisioning"]) def test_invalid_private_interface(self): """Test add netscaler device with invalid private interface """ @@ -526,14 +537,13 @@ class TestNetScalerDedicated(cloudstackTestCase): @classmethod def setUpClass(cls): - cls.api_client = super( - TestNetScalerDedicated, - cls - ).getClsTestClient().getApiClient() + cls.testClient = super(TestNetScalerDedicated, cls).getClsTestClient() + cls.api_client = cls.testClient.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) + cls.domain = get_domain(cls.api_client) + cls.zone = get_zone(cls.api_client, cls.testClient.getZoneForTests()) cls.template = get_template( cls.api_client, cls.zone.id, @@ -562,7 +572,7 @@ def setUpClass(cls): netscaler_provider = nw_service_providers[0] if netscaler_provider.state != 'Enabled': - response = NetworkServiceProvider.update( + NetworkServiceProvider.update( cls.api_client, id=netscaler_provider.id, state='Enabled' @@ -624,11 +634,11 @@ def tearDown(self): self.debug("Cleaning up the resources") #Clean up, terminate the created network offerings cleanup_resources(self.apiclient, self.cleanup) - interval = list_configurations( + interval = Configurations.list( self.apiclient, name='network.gc.interval' ) - wait = list_configurations( + wait = Configurations.list( self.apiclient, name='network.gc.wait' ) @@ -749,14 +759,13 @@ class TestNetScalerShared(cloudstackTestCase): @classmethod def setUpClass(cls): - cls.api_client = super( - TestNetScalerShared, - cls - ).getClsTestClient().getApiClient() + cls.testClient = super(TestNetScalerShared, cls).getClsTestClient() + cls.api_client = cls.testClient.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) + cls.domain = get_domain(cls.api_client) + cls.zone = get_zone(cls.api_client, cls.testClient.getZoneForTests()) cls.template = get_template( cls.api_client, cls.zone.id, @@ -785,7 +794,7 @@ def setUpClass(cls): netscaler_provider = nw_service_providers[0] if netscaler_provider.state != 'Enabled': - response = NetworkServiceProvider.update( + NetworkServiceProvider.update( cls.api_client, id=netscaler_provider.id, state='Enabled' @@ -843,11 +852,11 @@ def tearDown(self): self.debug("Cleaning up the resources") #Clean up, terminate the created network offerings cleanup_resources(self.apiclient, self.cleanup) - interval = list_configurations( + interval = Configurations.list( self.apiclient, name='network.gc.interval' ) - wait = list_configurations( + wait = Configurations.list( self.apiclient, name='network.gc.wait' ) @@ -992,14 +1001,13 @@ class TestNetScalerCustomCapacity(cloudstackTestCase): @classmethod def setUpClass(cls): - cls.api_client = super( - TestNetScalerCustomCapacity, - cls - ).getClsTestClient().getApiClient() + cls.testClient = super(TestNetScalerCustomCapacity, cls).getClsTestClient() + cls.api_client = cls.testClient.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) + cls.domain = get_domain(cls.api_client) + cls.zone = get_zone(cls.api_client, cls.testClient.getZoneForTests()) cls.template = get_template( cls.api_client, cls.zone.id, @@ -1028,7 +1036,7 @@ def setUpClass(cls): netscaler_provider = nw_service_providers[0] if netscaler_provider.state != 'Enabled': - response = NetworkServiceProvider.update( + NetworkServiceProvider.update( cls.api_client, id=netscaler_provider.id, state='Enabled' @@ -1092,11 +1100,11 @@ def tearDown(self): self.debug("Cleaning up the resources") #Clean up, terminate the created network offerings cleanup_resources(self.apiclient, self.cleanup) - interval = list_configurations( + interval = Configurations.list( self.apiclient, name='network.gc.interval' ) - wait = list_configurations( + wait = Configurations.list( self.apiclient, name='network.gc.wait' ) @@ -1249,7 +1257,7 @@ def test_netscaler_custom_capacity(self): self.debug("Deploying VM in account: %s" % self.account_3.name) with self.assertRaises(Exception): # Spawn an instance in that network - virtual_machine_3 = VirtualMachine.create( + VirtualMachine.create( self.apiclient, self.services["virtual_machine"], accountid=self.account_3.name, @@ -1265,14 +1273,13 @@ class TestNetScalerNoCapacity(cloudstackTestCase): @classmethod def setUpClass(cls): - cls.api_client = super( - TestNetScalerNoCapacity, - cls - ).getClsTestClient().getApiClient() + cls.testClient = super(TestNetScalerNoCapacity, cls).getClsTestClient() + cls.api_client = cls.testClient.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) + cls.domain = get_domain(cls.api_client) + cls.zone = get_zone(cls.api_client, cls.testClient.getZoneForTests()) cls.template = get_template( cls.api_client, cls.zone.id, @@ -1301,7 +1308,7 @@ def setUpClass(cls): netscaler_provider = nw_service_providers[0] if netscaler_provider.state != 'Enabled': - response = NetworkServiceProvider.update( + NetworkServiceProvider.update( cls.api_client, id=netscaler_provider.id, state='Enabled' @@ -1365,11 +1372,11 @@ def tearDown(self): self.debug("Cleaning up the resources") #Clean up, terminate the created network offerings cleanup_resources(self.apiclient, self.cleanup) - interval = list_configurations( + interval = Configurations.list( self.apiclient, name='network.gc.interval' ) - wait = list_configurations( + wait = Configurations.list( self.apiclient, name='network.gc.wait' ) @@ -1523,7 +1530,7 @@ def test_netscaler_no_capacity(self): self.debug("Deploying VM in account: %s" % self.account_3.name) with self.assertRaises(Exception): # Spawn an instance in that network - virtual_machine_3 = VirtualMachine.create( + VirtualMachine.create( self.apiclient, self.services["virtual_machine"], accountid=self.account_3.name, @@ -1539,14 +1546,13 @@ class TestGuestNetworkWithNetScaler(cloudstackTestCase): @classmethod def setUpClass(cls): - cls.api_client = super( - TestGuestNetworkWithNetScaler, - cls - ).getClsTestClient().getApiClient() + cls.testClient = super(TestGuestNetworkWithNetScaler, cls).getClsTestClient() + cls.api_client = cls.testClient.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) + cls.domain = get_domain(cls.api_client) + cls.zone = get_zone(cls.api_client, cls.testClient.getZoneForTests()) cls.template = get_template( cls.api_client, cls.zone.id, @@ -1575,7 +1581,7 @@ def setUpClass(cls): netscaler_provider = nw_service_providers[0] if netscaler_provider.state != 'Enabled': - response = NetworkServiceProvider.update( + NetworkServiceProvider.update( cls.api_client, id=netscaler_provider.id, state='Enabled' @@ -1633,11 +1639,11 @@ def tearDown(self): self.debug("Cleaning up the resources") #Clean up, terminate the created network offerings cleanup_resources(self.apiclient, self.cleanup) - interval = list_configurations( + interval = Configurations.list( self.apiclient, name='network.gc.interval' ) - wait = list_configurations( + wait = Configurations.list( self.apiclient, name='network.gc.wait' ) @@ -2037,11 +2043,11 @@ def test_03_delete_account(self): self.debug("Account: %s is deleted!" % self.account_1.name) self.debug("Waiting for network.gc.interval & network.gc.wait..") - interval = list_configurations( + interval = Configurations.list( self.apiclient, name='network.gc.interval' ) - wait = list_configurations( + wait = Configurations.list( self.apiclient, name='network.gc.wait' ) @@ -2096,14 +2102,13 @@ class TestGuestNetworkShutDown(cloudstackTestCase): @classmethod def setUpClass(cls): cls._cleanup = [] - cls.api_client = super( - TestGuestNetworkShutDown, - cls - ).getClsTestClient().getApiClient() + cls.testClient = super(TestGuestNetworkShutDown, cls).getClsTestClient() + cls.api_client = cls.testClient.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) + cls.domain = get_domain(cls.api_client) + cls.zone = get_zone(cls.api_client, cls.testClient.getZoneForTests()) cls.template = get_template( cls.api_client, cls.zone.id, @@ -2231,15 +2236,18 @@ def test_01_stop_all_vms(self): "Stopping all the VM instances for the account: %s" % self.account.name) - self.vm_1.stop(self.apiclient) - self.vm_2.stop(self.apiclient) + try: + self.vm_1.stop(self.apiclient) + self.vm_2.stop(self.apiclient) + except Exception as e: + self.fail("Failed to stop instance: %s" % e) self.debug("Sleep for network.gc.interval + network.gc.wait") - interval = list_configurations( + interval = Configurations.list( self.apiclient, name='network.gc.interval' ) - wait = list_configurations( + wait = Configurations.list( self.apiclient, name='network.gc.wait' ) @@ -2502,14 +2510,13 @@ class TestServiceProvider(cloudstackTestCase): @classmethod def setUpClass(cls): - cls.api_client = super( - TestServiceProvider, - cls - ).getClsTestClient().getApiClient() + cls.testClient = super(TestServiceProvider, cls).getClsTestClient() + cls.api_client = cls.testClient.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) + cls.domain = get_domain(cls.api_client) + cls.zone = get_zone(cls.api_client, cls.testClient.getZoneForTests()) cls.template = get_template( cls.api_client, cls.zone.id, @@ -2538,7 +2545,7 @@ def setUpClass(cls): cls.netscaler_provider = nw_service_providers[0] if cls.netscaler_provider.state != 'Enabled': - response = NetworkServiceProvider.update( + NetworkServiceProvider.update( cls.api_client, id=cls.netscaler_provider.id, state='Enabled' @@ -2595,11 +2602,11 @@ def tearDown(self): self.debug("Cleaning up the resources") #Clean up, terminate the created network offerings cleanup_resources(self.apiclient, self.cleanup) - interval = list_configurations( + interval = Configurations.list( self.apiclient, name='network.gc.interval' ) - wait = list_configurations( + wait = Configurations.list( self.apiclient, name='network.gc.wait' ) @@ -2817,14 +2824,13 @@ class TestDeleteNetscaler(cloudstackTestCase): @classmethod def setUpClass(cls): - cls.api_client = super( - TestDeleteNetscaler, - cls - ).getClsTestClient().getApiClient() + cls.testClient = super(TestDeleteNetscaler, cls).getClsTestClient() + cls.api_client = cls.testClient.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) + cls.domain = get_domain(cls.api_client) + cls.zone = get_zone(cls.api_client, cls.testClient.getZoneForTests()) cls.template = get_template( cls.api_client, cls.zone.id, @@ -2853,7 +2859,7 @@ def setUpClass(cls): netscaler_provider = nw_service_providers[0] if netscaler_provider.state != 'Enabled': - response = NetworkServiceProvider.update( + NetworkServiceProvider.update( cls.api_client, id=netscaler_provider.id, state='Enabled' @@ -2911,11 +2917,11 @@ def tearDown(self): self.debug("Cleaning up the resources") #Clean up, terminate the created network offerings cleanup_resources(self.apiclient, self.cleanup) - interval = list_configurations( + interval = Configurations.list( self.apiclient, name='network.gc.interval' ) - wait = list_configurations( + wait = Configurations.list( self.apiclient, name='network.gc.wait' ) diff --git a/test/integration/component/test_netscaler_lb.py b/test/integration/component/test_netscaler_lb.py index 26df5459b5..4c99aa36d4 100644 --- a/test/integration/component/test_netscaler_lb.py +++ b/test/integration/component/test_netscaler_lb.py @@ -18,15 +18,27 @@ """ P1 tests for netscaler load balancing """ #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.cloudstackTestCase import cloudstackTestCase +from marvin.cloudstackAPI import migrateVirtualMachine +from marvin.lib.utils import (cleanup_resources, + random_gen) +from marvin.lib.base import (Account, + VirtualMachine, + PublicIPAddress, + LoadBalancerRule, + ServiceOffering, + NetworkOffering, + Host, + Network, + NATRule, + Configurations) +from marvin.lib.common import (get_domain, + get_zone, + get_template, + add_netscaler) from marvin.sshClient import SshClient -import datetime +import time class Services: @@ -150,14 +162,13 @@ class TestLbSourceNat(cloudstackTestCase): @classmethod def setUpClass(cls): cls._cleanup = [] - cls.api_client = super( - TestLbSourceNat, - cls - ).getClsTestClient().getApiClient() + cls.testClient = super(TestLbSourceNat, cls).getClsTestClient() + cls.api_client = cls.testClient.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) + cls.domain = get_domain(cls.api_client) + cls.zone = get_zone(cls.api_client, cls.testClient.getZoneForTests()) cls.template = get_template( cls.api_client, cls.zone.id, @@ -210,11 +221,11 @@ def tearDown(self): self.debug("Cleaning up the resources") #Clean up, terminate the created network offerings cleanup_resources(self.apiclient, self.cleanup) - interval = list_configurations( + interval = Configurations.list( self.apiclient, name='network.gc.interval' ) - wait = list_configurations( + wait = Configurations.list( self.apiclient, name='network.gc.wait' ) @@ -359,14 +370,13 @@ class TestLbOnIpWithPf(cloudstackTestCase): @classmethod def setUpClass(cls): cls._cleanup = [] - cls.api_client = super( - TestLbOnIpWithPf, - cls - ).getClsTestClient().getApiClient() + cls.testClient = super(TestLbOnIpWithPf, cls).getClsTestClient() + cls.api_client = cls.testClient.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) + cls.domain = get_domain(cls.api_client) + cls.zone = get_zone(cls.api_client, cls.testClient.getZoneForTests()) cls.template = get_template( cls.api_client, cls.zone.id, @@ -420,11 +430,11 @@ def tearDown(self): self.debug("Cleaning up the resources") #Clean up, terminate the created network offerings cleanup_resources(self.apiclient, self.cleanup) - interval = list_configurations( + interval = Configurations.list( self.apiclient, name='network.gc.interval' ) - wait = list_configurations( + wait = Configurations.list( self.apiclient, name='network.gc.wait' ) @@ -572,14 +582,13 @@ class TestPfOnIpWithLb(cloudstackTestCase): @classmethod def setUpClass(cls): cls._cleanup = [] - cls.api_client = super( - TestPfOnIpWithLb, - cls - ).getClsTestClient().getApiClient() + cls.testClient = super(TestPfOnIpWithLb, cls).getClsTestClient() + cls.api_client = cls.testClient.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) + cls.domain = get_domain(cls.api_client) + cls.zone = get_zone(cls.api_client, cls.testClient.getZoneForTests()) cls.template = get_template( cls.api_client, cls.zone.id, @@ -633,11 +642,11 @@ def tearDown(self): self.debug("Cleaning up the resources") #Clean up, terminate the created network offerings cleanup_resources(self.apiclient, self.cleanup) - interval = list_configurations( + interval = Configurations.list( self.apiclient, name='network.gc.interval' ) - wait = list_configurations( + wait = Configurations.list( self.apiclient, name='network.gc.wait' ) @@ -774,7 +783,7 @@ def test_pf_on_ip_with_lb(self): with self.assertRaises(Exception): NATRule.create( self.apiclient, - virtual_machine, + virtual_machine_1, self.services["natrule"], ipaddressid=ip_with_lb_rule.ipaddress.id ) @@ -786,14 +795,13 @@ class TestLbOnNonSourceNat(cloudstackTestCase): @classmethod def setUpClass(cls): cls._cleanup = [] - cls.api_client = super( - TestLbOnNonSourceNat, - cls - ).getClsTestClient().getApiClient() + cls.testClient = super(TestLbOnNonSourceNat, cls).getClsTestClient() + cls.api_client = cls.testClient.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) + cls.domain = get_domain(cls.api_client) + cls.zone = get_zone(cls.api_client, cls.testClient.getZoneForTests()) cls.template = get_template( cls.api_client, cls.zone.id, @@ -847,11 +855,11 @@ def tearDown(self): self.debug("Cleaning up the resources") #Clean up, terminate the created network offerings cleanup_resources(self.apiclient, self.cleanup) - interval = list_configurations( + interval = Configurations.list( self.apiclient, name='network.gc.interval' ) - wait = list_configurations( + wait = Configurations.list( self.apiclient, name='network.gc.wait' ) @@ -1003,14 +1011,13 @@ class TestAddMultipleVmsLb(cloudstackTestCase): @classmethod def setUpClass(cls): cls._cleanup = [] - cls.api_client = super( - TestAddMultipleVmsLb, - cls - ).getClsTestClient().getApiClient() + cls.testClient = super(TestAddMultipleVmsLb, cls).getClsTestClient() + cls.api_client = cls.testClient.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) + cls.domain = get_domain(cls.api_client) + cls.zone = get_zone(cls.api_client, cls.testClient.getZoneForTests()) cls.template = get_template( cls.api_client, cls.zone.id, @@ -1064,11 +1071,11 @@ def tearDown(self): self.debug("Cleaning up the resources") #Clean up, terminate the created network offerings cleanup_resources(self.apiclient, self.cleanup) - interval = list_configurations( + interval = Configurations.list( self.apiclient, name='network.gc.interval' ) - wait = list_configurations( + wait = Configurations.list( self.apiclient, name='network.gc.wait' ) @@ -1282,14 +1289,13 @@ class TestMultipleLbRules(cloudstackTestCase): @classmethod def setUpClass(cls): cls._cleanup = [] - cls.api_client = super( - TestMultipleLbRules, - cls - ).getClsTestClient().getApiClient() + cls.testClient = super(TestMultipleLbRules, cls).getClsTestClient() + cls.api_client = cls.testClient.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) + cls.domain = get_domain(cls.api_client) + cls.zone = get_zone(cls.api_client, cls.testClient.getZoneForTests()) cls.template = get_template( cls.api_client, cls.zone.id, @@ -1344,11 +1350,11 @@ def tearDown(self): self.debug("Cleaning up the resources") #Clean up, terminate the created network offerings cleanup_resources(self.apiclient, self.cleanup) - interval = list_configurations( + interval = Configurations.list( self.apiclient, name='network.gc.interval' ) - wait = list_configurations( + wait = Configurations.list( self.apiclient, name='network.gc.wait' ) @@ -1601,14 +1607,13 @@ class TestMultipleLbRulesSameIp(cloudstackTestCase): @classmethod def setUpClass(cls): cls._cleanup = [] - cls.api_client = super( - TestMultipleLbRulesSameIp, - cls - ).getClsTestClient().getApiClient() + cls.testClient = super(TestMultipleLbRulesSameIp, cls).getClsTestClient() + cls.api_client = cls.testClient.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) + cls.domain = get_domain(cls.api_client) + cls.zone = get_zone(cls.api_client, cls.testClient.getZoneForTests()) cls.template = get_template( cls.api_client, cls.zone.id, @@ -1663,11 +1668,11 @@ def tearDown(self): self.debug("Cleaning up the resources") #Clean up, terminate the created network offerings cleanup_resources(self.apiclient, self.cleanup) - interval = list_configurations( + interval = Configurations.list( self.apiclient, name='network.gc.interval' ) - wait = list_configurations( + wait = Configurations.list( self.apiclient, name='network.gc.wait' ) @@ -1926,14 +1931,13 @@ class TestLoadBalancingRule(cloudstackTestCase): @classmethod def setUpClass(cls): cls._cleanup = [] - cls.api_client = super( - TestLoadBalancingRule, - cls - ).getClsTestClient().getApiClient() + cls.testClient = super(TestLoadBalancingRule, cls).getClsTestClient() + cls.api_client = cls.testClient.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) + cls.domain = get_domain(cls.api_client) + cls.zone = get_zone(cls.api_client, cls.testClient.getZoneForTests()) cls.template = get_template( cls.api_client, cls.zone.id, @@ -2140,14 +2144,13 @@ class TestDeleteCreateLBRule(cloudstackTestCase): @classmethod def setUpClass(cls): cls._cleanup = [] - cls.api_client = super( - TestDeleteCreateLBRule, - cls - ).getClsTestClient().getApiClient() + cls.testClient = super(TestDeleteCreateLBRule, cls).getClsTestClient() + cls.api_client = cls.testClient.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) + cls.domain = get_domain(cls.api_client) + cls.zone = get_zone(cls.api_client, cls.testClient.getZoneForTests()) cls.template = get_template( cls.api_client, cls.zone.id, @@ -2255,7 +2258,7 @@ def test_01_create_with_same_public_port(self): self.debug("Create a new LB rule with different public port") self.services["lbrule"]["publicport"] = 23 - lb_rule = LoadBalancerRule.create( + LoadBalancerRule.create( self.apiclient, self.services["lbrule"], ipaddressid=self.public_ip.ipaddress.id, @@ -2269,14 +2272,13 @@ class TestVmWithLb(cloudstackTestCase): @classmethod def setUpClass(cls): cls._cleanup = [] - cls.api_client = super( - TestVmWithLb, - cls - ).getClsTestClient().getApiClient() + cls.testClient = super(TestVmWithLb, cls).getClsTestClient() + cls.api_client = cls.testClient.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) + cls.domain = get_domain(cls.api_client) + cls.zone = get_zone(cls.api_client, cls.testClient.getZoneForTests()) cls.template = get_template( cls.api_client, cls.zone.id, @@ -2472,18 +2474,11 @@ def test_02_stop_user_vm(self): # 4. In netscaler, LB rules for this VM still remain configured.But # it will be marked as being down - self.debug("Adding instances: %s, %s to LB rule: %s" % ( - self.vm_1.name, - self.vm_2.name, - self.lb_rule_1.name)) - self.lb_rule_1.assign(self.apiclient, [self.vm_1, self.vm_2]) - self.debug("Assigned instances: %s, %s to LB rule: %s" % ( - self.vm_1.name, - self.vm_2.name, - self.lb_rule_1.name)) - self.debug("Stopping VM instance: %s" % self.vm_2.name) - self.vm_2.stop(self.apiclient) - self.debug("Stopped VM: %s" % self.vm_2.name) + try: + self.lb_rule_1.assign(self.apiclient, [self.vm_1, self.vm_2]) + self.vm_2.stop(self.apiclient) + except Exception as e: + self.fail("Exception occured: %s" % e) try: self.debug( @@ -2652,7 +2647,7 @@ def test_04_migrate_user_vm(self): cmd.virtualmachineid = self.vm_2.id self.apiclient.migrateVirtualMachine(cmd) - list_vm_response = list_virtual_machines( + list_vm_response = VirtualMachine.list( self.apiclient, id=self.vm_2.id ) @@ -2862,11 +2857,11 @@ def test_06_destroy_user_vm(self): self.fail("Exception occured during SSH: %s - %s" % ( self.public_ip_1.ipaddress.ipaddress, e)) - delay = list_configurations( + delay = Configurations.list( self.apiclient, name='expunge.delay' ) - wait = list_configurations( + wait = Configurations.list( self.apiclient, name='expunge.interval' ) diff --git a/test/integration/component/test_netscaler_lb_algo.py b/test/integration/component/test_netscaler_lb_algo.py index 3c18fcd36d..6eda9a3f40 100644 --- a/test/integration/component/test_netscaler_lb_algo.py +++ b/test/integration/component/test_netscaler_lb_algo.py @@ -22,11 +22,10 @@ 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.lib.utils import * +from marvin.lib.base import * +from marvin.lib.common import * from marvin.sshClient import SshClient -import datetime class Services: @@ -117,14 +116,13 @@ class TestLbWithRoundRobin(cloudstackTestCase): @classmethod def setUpClass(cls): cls._cleanup = [] - cls.api_client = super( - TestLbWithRoundRobin, - cls - ).getClsTestClient().getApiClient() + cls.testClient = super(TestLbWithRoundRobin, cls).getClsTestClient() + cls.api_client = cls.testClient.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) + cls.domain = get_domain(cls.api_client) + cls.zone = get_zone(cls.api_client, cls.testClient.getZoneForTests()) cls.template = get_template( cls.api_client, cls.zone.id, @@ -330,14 +328,13 @@ class TestLbWithLeastConn(cloudstackTestCase): @classmethod def setUpClass(cls): cls._cleanup = [] - cls.api_client = super( - TestLbWithLeastConn, - cls - ).getClsTestClient().getApiClient() + cls.testClient = super(TestLbWithLeastConn, cls).getClsTestClient() + cls.api_client = cls.testClient.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) + cls.domain = get_domain(cls.api_client) + cls.zone = get_zone(cls.api_client, cls.testClient.getZoneForTests()) cls.template = get_template( cls.api_client, cls.zone.id, @@ -552,14 +549,13 @@ class TestLbWithSourceIp(cloudstackTestCase): @classmethod def setUpClass(cls): - cls.api_client = super( - TestLbWithSourceIp, - cls - ).getClsTestClient().getApiClient() + cls.testClient = super(TestLbWithSourceIp, cls).getClsTestClient() + cls.api_client = cls.testClient.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) + cls.domain = get_domain(cls.api_client) + cls.zone = get_zone(cls.api_client, cls.testClient.getZoneForTests()) cls.template = get_template( cls.api_client, cls.zone.id, @@ -768,14 +764,13 @@ class TestLbAlgoRrLc(cloudstackTestCase): @classmethod def setUpClass(cls): cls._cleanup = [] - cls.api_client = super( - TestLbAlgoRrLc, - cls - ).getClsTestClient().getApiClient() + cls.testClient = super(TestLbAlgoRrLc, cls).getClsTestClient() + cls.api_client = cls.testClient.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) + cls.domain = get_domain(cls.api_client) + cls.zone = get_zone(cls.api_client, cls.testClient.getZoneForTests()) cls.template = get_template( cls.api_client, cls.zone.id, @@ -973,14 +968,13 @@ class TestLbAlgoLcRr(cloudstackTestCase): @classmethod def setUpClass(cls): cls._cleanup = [] - cls.api_client = super( - TestLbAlgoLcRr, - cls - ).getClsTestClient().getApiClient() + cls.testClient = super(TestLbAlgoLcRr, cls).getClsTestClient() + cls.api_client = cls.testClient.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) + cls.domain = get_domain(cls.api_client) + cls.zone = get_zone(cls.api_client, cls.testClient.getZoneForTests()) cls.template = get_template( cls.api_client, cls.zone.id, @@ -1175,14 +1169,13 @@ class TestLbAlgoRrSb(cloudstackTestCase): @classmethod def setUpClass(cls): cls._cleanup = [] - cls.api_client = super( - TestLbAlgoRrSb, - cls - ).getClsTestClient().getApiClient() + cls.testClient = super(TestLbAlgoRrSb, cls).getClsTestClient() + cls.api_client = cls.testClient.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) + cls.domain = get_domain(cls.api_client) + cls.zone = get_zone(cls.api_client, cls.testClient.getZoneForTests()) cls.template = get_template( cls.api_client, cls.zone.id, @@ -1380,14 +1373,13 @@ class TestLbAlgoSbRr(cloudstackTestCase): @classmethod def setUpClass(cls): cls._cleanup = [] - cls.api_client = super( - TestLbAlgoSbRr, - cls - ).getClsTestClient().getApiClient() + cls.testClient = super(TestLbAlgoSbRr, cls).getClsTestClient() + cls.api_client = cls.testClient.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) + cls.domain = get_domain(cls.api_client) + cls.zone = get_zone(cls.api_client, cls.testClient.getZoneForTests()) cls.template = get_template( cls.api_client, cls.zone.id, @@ -1588,14 +1580,13 @@ class TestLbAlgoSbLc(cloudstackTestCase): @classmethod def setUpClass(cls): cls._cleanup = [] - cls.api_client = super( - TestLbAlgoSbLc, - cls - ).getClsTestClient().getApiClient() + cls.testClient = super(TestLbAlgoSbLc, cls).getClsTestClient() + cls.api_client = cls.testClient.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) + cls.domain = get_domain(cls.api_client) + cls.zone = get_zone(cls.api_client, cls.testClient.getZoneForTests()) cls.template = get_template( cls.api_client, cls.zone.id, @@ -1795,14 +1786,13 @@ class TestLbAlgoLcSb(cloudstackTestCase): @classmethod def setUpClass(cls): cls._cleanup = [] - cls.api_client = super( - TestLbAlgoLcSb, - cls - ).getClsTestClient().getApiClient() + cls.testClient = super(TestLbAlgoLcSb, cls).getClsTestClient() + cls.api_client = cls.testClient.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) + cls.domain = get_domain(cls.api_client) + cls.zone = get_zone(cls.api_client, cls.testClient.getZoneForTests()) cls.template = get_template( cls.api_client, cls.zone.id, diff --git a/test/integration/component/test_netscaler_lb_sticky.py b/test/integration/component/test_netscaler_lb_sticky.py index 6c27a08052..c333f60c68 100644 --- a/test/integration/component/test_netscaler_lb_sticky.py +++ b/test/integration/component/test_netscaler_lb_sticky.py @@ -22,9 +22,9 @@ 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.lib.utils import * +from marvin.lib.base import * +from marvin.lib.common import * from marvin.sshClient import SshClient import datetime @@ -117,14 +117,13 @@ class TestLbStickyPolicy(cloudstackTestCase): @classmethod def setUpClass(cls): cls._cleanup = [] - cls.api_client = super( - TestLbStickyPolicy, - cls - ).getClsTestClient().getApiClient() + cls.testClient = super(TestLbStickyPolicy, cls).getClsTestClient() + cls.api_client = cls.testClient.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) + cls.domain = get_domain(cls.api_client) + cls.zone = get_zone(cls.api_client, cls.testClient.getZoneForTests()) cls.template = get_template( cls.api_client, cls.zone.id, diff --git a/test/integration/component/test_netscaler_nw_off.py b/test/integration/component/test_netscaler_nw_off.py index 3372612aba..af53eb7677 100644 --- a/test/integration/component/test_netscaler_nw_off.py +++ b/test/integration/component/test_netscaler_nw_off.py @@ -18,15 +18,32 @@ """ P1 tests for multiple netscaler instances """ #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.sshClient import SshClient -import datetime +from marvin.cloudstackTestCase import cloudstackTestCase +#from marvin.cloudstackAPI import * +from marvin.lib.utils import (cleanup_resources) +from marvin.lib.base import (NATRule, + LoadBalancerRule, + FireWallRule, + PublicIPAddress, + VirtualMachine, + Network, + Account, + NetScaler, + PhysicalNetwork, + NetworkServiceProvider, + NetworkOffering, + Vpn, + Zone, + ServiceOffering, + Configurations + ) +from marvin.lib.common import (get_domain, + get_zone, + get_template, + add_netscaler, + ) +import time class Services: @@ -191,14 +208,13 @@ class TestAddMultipleNetScaler(cloudstackTestCase): @classmethod def setUpClass(cls): - cls.api_client = super( - TestAddMultipleNetScaler, - cls - ).getClsTestClient().getApiClient() + cls.testClient = super(TestAddMultipleNetScaler, cls).getClsTestClient() + cls.api_client = cls.testClient.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) + cls.domain = get_domain(cls.api_client) + cls.zone = get_zone(cls.api_client, cls.testClient.getZoneForTests()) cls._cleanup = [] return @@ -227,7 +243,7 @@ def tearDown(self): raise Exception("Warning: Exception during cleanup : %s" % e) return - @attr(tags = ["advancedns"]) + @attr(tags=["advancedns", "provisioning"]) def test_add_netscaler_device(self): """Test add netscaler device """ @@ -385,7 +401,7 @@ def tearDown(self): raise Exception("Warning: Exception during cleanup : %s" % e) return - @attr(tags = ["advancedns", "multizone"]) + @attr(tags=["advancedns", "multizone", "provisioning"]) def test_add_mul_netscaler_diff_zone(self): """Test add netscaler devices in different zones """ @@ -506,14 +522,13 @@ class TestNetScalerSharedMode(cloudstackTestCase): @classmethod def setUpClass(cls): - cls.api_client = super( - TestNetScalerSharedMode, - cls - ).getClsTestClient().getApiClient() + cls.testClient = super(TestNetScalerSharedMode, cls).getClsTestClient() + cls.api_client = cls.testClient.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) + cls.domain = get_domain(cls.api_client) + cls.zone = get_zone(cls.api_client, cls.testClient.getZoneForTests()) cls.template = get_template( cls.api_client, cls.zone.id, @@ -542,7 +557,7 @@ def setUpClass(cls): netscaler_provider = nw_service_providers[0] if netscaler_provider.state != 'Enabled': - response = NetworkServiceProvider.update( + NetworkServiceProvider.update( cls.api_client, id=netscaler_provider.id, state='Enabled' @@ -769,7 +784,7 @@ def test_01_netscaler_shared_mode(self): with self.assertRaises(Exception): # Spawn an instance in that network - virtual_machine_3 = VirtualMachine.create( + VirtualMachine.create( self.apiclient, self.services["virtual_machine"], accountid=self.account_3.name, @@ -957,7 +972,7 @@ def test_03_multiple_netscaler_full_capacilty(self): with self.assertRaises(Exception): # Spawn an instance in that network - virtual_machine_5 = VirtualMachine.create( + VirtualMachine.create( self.apiclient, self.services["virtual_machine"], accountid=self.account_5.name, @@ -985,14 +1000,10 @@ def test_04_delete_account_after_capacity_full(self): self.account_4.delete(self.apiclient) self.debug("Account: %s is deleted" % self.account_4.name) - interval = list_configurations( - self.apiclient, - name='network.gc.interval' - ) - wait = list_configurations( - self.apiclient, - name='network.gc.wait' - ) + interval = Configurations.list(self.apiclient, + name='network.gc.interval') + wait = Configurations.list(self.apiclient, + name='network.gc.wait') self.debug("Sleeping for: network.gc.interval + network.gc.wait") # Sleep to ensure that all resources are deleted time.sleep(int(interval[0].value) + int(wait[0].value)) @@ -1051,14 +1062,13 @@ class TestNwOffDedicatedNetscaler(cloudstackTestCase): @classmethod def setUpClass(cls): - cls.api_client = super( - TestNwOffDedicatedNetscaler, - cls - ).getClsTestClient().getApiClient() + cls.testClient = super(TestNwOffDedicatedNetscaler, cls).getClsTestClient() + cls.api_client = cls.testClient.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) + cls.domain = get_domain(cls.api_client) + cls.zone = get_zone(cls.api_client, cls.testClient.getZoneForTests()) cls.template = get_template( cls.api_client, cls.zone.id, @@ -1087,7 +1097,7 @@ def setUpClass(cls): netscaler_provider = nw_service_providers[0] if netscaler_provider.state != 'Enabled': - response = NetworkServiceProvider.update( + NetworkServiceProvider.update( cls.api_client, id=netscaler_provider.id, state='Enabled' @@ -1138,11 +1148,11 @@ def tearDown(self): self.debug("Cleaning up the resources") #Clean up, terminate the created network offerings cleanup_resources(self.apiclient, self.cleanup) - interval = list_configurations( + interval = Configurations.list( self.apiclient, name='network.gc.interval' ) - wait = list_configurations( + wait = Configurations.list( self.apiclient, name='network.gc.wait' ) @@ -1217,14 +1227,13 @@ class TestNwOffNetscaler(cloudstackTestCase): @classmethod def setUpClass(cls): - cls.api_client = super( - TestNwOffNetscaler, - cls - ).getClsTestClient().getApiClient() + cls.testClient = super(TestNwOffNetscaler, cls).getClsTestClient() + cls.api_client = cls.testClient.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) + cls.domain = get_domain(cls.api_client) + cls.zone = get_zone(cls.api_client, cls.testClient.getZoneForTests()) cls.template = get_template( cls.api_client, cls.zone.id, @@ -1260,7 +1269,7 @@ def setUpClass(cls): netscaler_provider = nw_service_providers[0] if netscaler_provider.state != 'Enabled': - response = NetworkServiceProvider.update( + NetworkServiceProvider.update( cls.api_client, id=netscaler_provider.id, state='Enabled' @@ -1330,11 +1339,11 @@ def tearDown(self): self.debug("Cleaning up the resources") #Clean up, terminate the created network offerings cleanup_resources(self.apiclient, self.cleanup) - interval = list_configurations( + interval = Configurations.list( self.apiclient, name='network.gc.interval' ) - wait = list_configurations( + wait = Configurations.list( self.apiclient, name='network.gc.wait' ) @@ -1390,14 +1399,13 @@ def test_ns_shared_nw_dedicated(self): zoneid=self.zone.id ) self.debug("Deploying VM in account: %s" % self.account_1.name) - virtual_machine = VirtualMachine.create( - self.apiclient, - self.services["virtual_machine"], - accountid=self.account_1.name, - domainid=self.account_1.domainid, - serviceofferingid=self.service_offering.id, - networkids=[str(self.network.id)] - ) + VirtualMachine.create( + self.apiclient, + self.services["virtual_machine"], + accountid=self.account_1.name, + domainid=self.account_1.domainid, + serviceofferingid=self.service_offering.id, + networkids=[str(self.network.id)]) # Creating network using the network offering created self.debug("Creating different network with network offering: %s" % self.network_offering.id) @@ -1425,14 +1433,12 @@ def test_ns_shared_nw_dedicated(self): self.debug("Deleting account: %s" % self.account_1.name) self.account_1.delete(self.apiclient) self.debug("Account: %s deleted!" % self.account_1.name) - interval = list_configurations( + interval = Configurations.list( self.apiclient, name='network.gc.interval' ) - wait = list_configurations( - self.apiclient, - name='network.gc.wait' - ) + wait = Configurations.list(self.apiclient, + name='network.gc.wait') self.debug("Sleeping for: network.gc.interval + network.gc.wait") # Sleep to ensure that all resources are deleted time.sleep(int(interval[0].value) + int(wait[0].value)) @@ -1525,14 +1531,13 @@ class TestNwOffSToDUpgrade(cloudstackTestCase): @classmethod def setUpClass(cls): - cls.api_client = super( - TestNwOffSToDUpgrade, - cls - ).getClsTestClient().getApiClient() + cls.testClient = super(TestNwOffSToDUpgrade, cls).getClsTestClient() + cls.api_client = cls.testClient.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) + cls.domain = get_domain(cls.api_client) + cls.zone = get_zone(cls.api_client, cls.testClient.getZoneForTests()) cls.template = get_template( cls.api_client, cls.zone.id, @@ -1569,7 +1574,7 @@ def setUpClass(cls): netscaler_provider = nw_service_providers[0] if netscaler_provider.state != 'Enabled': - response = NetworkServiceProvider.update( + NetworkServiceProvider.update( cls.api_client, id=netscaler_provider.id, state='Enabled' @@ -1639,11 +1644,11 @@ def tearDown(self): self.debug("Cleaning up the resources") #Clean up, terminate the created network offerings cleanup_resources(self.apiclient, self.cleanup) - interval = list_configurations( + interval = Configurations.list( self.apiclient, name='network.gc.interval' ) - wait = list_configurations( + wait = Configurations.list( self.apiclient, name='network.gc.wait' ) @@ -1828,29 +1833,6 @@ def test_shared_to_dedicated_upgrade(self): self.account_1.name) virtual_machine_1.stop(self.apiclient) - list_vm_response = VirtualMachine.list( - self.apiclient, - id=virtual_machine_1.id - ) - - self.debug( - "Verify listVirtualMachines response for virtual machine: %s" \ - % virtual_machine_1.id - ) - - self.assertEqual( - isinstance(list_vm_response, list), - True, - "Check list response returns a valid list" - ) - vm_response = list_vm_response[0] - - self.assertEqual( - vm_response.state, - "Stopped", - "VM state should be running after deployment" - ) - self.debug("All Vms are in stopped state") self.debug("Upgrading the network: %s" % self.network_1.id) self.network_1.update( self.apiclient, @@ -1922,7 +1904,7 @@ def test_shared_to_dedicated_upgrade(self): "Creating LB rule for IP address: %s with round robin algo" % public_ip.ipaddress.ipaddress) - lb_rule = LoadBalancerRule.create( + LoadBalancerRule.create( self.apiclient, self.services["lbrule"], ipaddressid=public_ip.ipaddress.id, @@ -1940,14 +1922,13 @@ class TestNwOffDToSUpgrade(cloudstackTestCase): @classmethod def setUpClass(cls): - cls.api_client = super( - TestNwOffDToSUpgrade, - cls - ).getClsTestClient().getApiClient() + cls.testClient = super(TestNwOffDToSUpgrade, cls).getClsTestClient() + cls.api_client = cls.testClient.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) + cls.domain = get_domain(cls.api_client) + cls.zone = get_zone(cls.api_client, cls.testClient.getZoneForTests()) cls.template = get_template( cls.api_client, cls.zone.id, @@ -1984,7 +1965,7 @@ def setUpClass(cls): netscaler_provider = nw_service_providers[0] if netscaler_provider.state != 'Enabled': - response = NetworkServiceProvider.update( + NetworkServiceProvider.update( cls.api_client, id=netscaler_provider.id, state='Enabled' @@ -2054,11 +2035,11 @@ def tearDown(self): self.debug("Cleaning up the resources") #Clean up, terminate the created network offerings cleanup_resources(self.apiclient, self.cleanup) - interval = list_configurations( + interval = Configurations.list( self.apiclient, name='network.gc.interval' ) - wait = list_configurations( + wait = Configurations.list( self.apiclient, name='network.gc.wait' ) @@ -2233,29 +2214,6 @@ def test_shared_to_dedicated_upgrade(self): self.debug("Stopping all VMs in account: %s" % self.account_3.name) virtual_machine_3.stop(self.apiclient) - list_vm_response = VirtualMachine.list( - self.apiclient, - id=virtual_machine_3.id - ) - - self.debug( - "Verify listVirtualMachines response for virtual machine: %s" \ - % virtual_machine_3.id - ) - - self.assertEqual( - isinstance(list_vm_response, list), - True, - "Check list response returns a valid list" - ) - vm_response = list_vm_response[0] - - self.assertEqual( - vm_response.state, - "Stopped", - "VM state should be stopped" - ) - self.debug("All user VMs stopped") self.debug("Upgrading the network: %s" % self.network_3.id) self.network_3.update( self.apiclient, @@ -2324,7 +2282,7 @@ def test_shared_to_dedicated_upgrade(self): "Creating LB rule for IP address: %s with round robin algo" % public_ip.ipaddress.ipaddress) - lb_rule = LoadBalancerRule.create( + LoadBalancerRule.create( self.apiclient, self.services["lbrule"], ipaddressid=public_ip.ipaddress.id, @@ -2341,15 +2299,13 @@ class TestNOWithNetscaler(cloudstackTestCase): @classmethod def setUpClass(cls): - cls.api_client = super( - TestNOWithNetscaler, - cls - ).getClsTestClient().getApiClient() + cls.testClient = super(TestNOWithNetscaler, cls).getClsTestClient() + cls.api_client = cls.testClient.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) + cls.domain = get_domain(cls.api_client) + cls.zone = get_zone(cls.api_client, cls.testClient.getZoneForTests()) cls.services['mode'] = cls.zone.networktype cls.template = get_template( cls.api_client, @@ -2944,7 +2900,7 @@ def test_02_net_off_conserve_mode_ns(self): # User should be able to enable VPN on source NAT self.debug("Created VPN with source NAT IP: %s" % src_nat.ipaddress) # Assign VPN to source NAT - vpn = Vpn.create( + Vpn.create( self.apiclient, src_nat.id, account=self.account.name, diff --git a/test/integration/component/test_network_offering.py b/test/integration/component/test_network_offering.py index 33c4305933..f2251ff873 100644 --- a/test/integration/component/test_network_offering.py +++ b/test/integration/component/test_network_offering.py @@ -18,14 +18,23 @@ """ P1 tests for network offering """ #Import Local Modules -import marvin from nose.plugins.attrib import attr -from marvin.cloudstackTestCase import * -from marvin.cloudstackAPI import * -from marvin.integration.lib.utils import * -from marvin.integration.lib.base import * -from marvin.integration.lib.common import * -import datetime +from marvin.cloudstackTestCase import cloudstackTestCase +#from marvin.cloudstackAPI import * +from marvin.lib.utils import (cleanup_resources) +from marvin.lib.base import (VirtualMachine, + Account, + Network, + LoadBalancerRule, + PublicIPAddress, + FireWallRule, + NATRule, + Vpn, + ServiceOffering, + NetworkOffering) +from marvin.lib.common import (get_domain, + get_zone, + get_template) class Services: @@ -160,14 +169,13 @@ class TestNOVirtualRouter(cloudstackTestCase): @classmethod def setUpClass(cls): - cls.api_client = super( - TestNOVirtualRouter, - cls - ).getClsTestClient().getApiClient() + cls.testClient = super(TestNOVirtualRouter, cls).getClsTestClient() + cls.api_client = cls.testClient.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) + cls.domain = get_domain(cls.api_client) + cls.zone = get_zone(cls.api_client, cls.testClient.getZoneForTests()) cls.services['mode'] = cls.zone.networktype cls.template = get_template( cls.api_client, @@ -215,7 +223,7 @@ def tearDown(self): raise Exception("Warning: Exception during cleanup : %s" % e) return - @attr(tags = ["advanced"]) + @attr(tags=["advanced", "selfservice"]) def test_01_network_off_without_conserve_mode(self): """Test Network offering with Conserve mode off and VR - All services """ @@ -460,7 +468,7 @@ def test_01_network_off_without_conserve_mode(self): ) return - @attr(tags = ["advanced"]) + @attr(tags=["advanced", "selfservice"]) def test_02_network_off_with_conserve_mode(self): """Test Network offering with Conserve mode ON and VR - All services """ @@ -701,7 +709,7 @@ def test_02_network_off_with_conserve_mode(self): # User should be able to enable VPN on source NAT self.debug("Created VPN with source NAT IP: %s" % src_nat.ipaddress) # Assign VPN to source NAT - vpn = Vpn.create( + Vpn.create( self.apiclient, src_nat.id, account=self.account.name, @@ -733,14 +741,13 @@ class TestNetworkUpgrade(cloudstackTestCase): @classmethod def setUpClass(cls): - cls.api_client = super( - TestNetworkUpgrade, - cls - ).getClsTestClient().getApiClient() + cls.testClient = super(TestNetworkUpgrade, cls).getClsTestClient() + cls.api_client = cls.testClient.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) + cls.domain = get_domain(cls.api_client) + cls.zone = get_zone(cls.api_client, cls.testClient.getZoneForTests()) cls.services['mode'] = cls.zone.networktype cls.template = get_template( cls.api_client, @@ -798,7 +805,7 @@ def tearDown(self): return @attr(speed = "slow") - @attr(tags = ["advancedns"]) + @attr(tags=["advancedns", "provisioning"]) def test_01_nwupgrade_netscaler_conserve_on(self): """Test Nw upgrade to netscaler lb service and conserve mode ON """ @@ -944,7 +951,7 @@ def test_01_nwupgrade_netscaler_conserve_on(self): # Assign VPN to source NAT self.debug("Enabling VPN on source NAT") - vpn = Vpn.create( + Vpn.create( self.apiclient, src_nat.id, account=self.account.name, @@ -998,7 +1005,7 @@ def test_01_nwupgrade_netscaler_conserve_on(self): return @attr(speed = "slow") - @attr(tags = ["advancedns"]) + @attr(tags=["advancedns", "provisioning"]) def test_02_nwupgrade_netscaler_conserve_off(self): """Test Nw upgrade to netscaler lb service and conserve mode OFF """ @@ -1144,7 +1151,7 @@ def test_02_nwupgrade_netscaler_conserve_off(self): # Assign VPN to source NAT self.debug("Enabling VPN on source NAT") - vpn = Vpn.create( + Vpn.create( self.apiclient, src_nat.id, account=self.account.name, @@ -1181,14 +1188,13 @@ def test_02_nwupgrade_netscaler_conserve_off(self): class TestNOWithOnlySourceNAT(cloudstackTestCase): @classmethod def setUpClass(cls): - cls.apiclient = super( - TestNOWithOnlySourceNAT, - cls - ).getClsTestClient().getApiClient() + cls.testClient = super(TestNOWithOnlySourceNAT, cls).getClsTestClient() + cls.apiclient = cls.testClient.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.domain = get_domain(cls.apiclient) + cls.zone = get_zone(cls.apiclient, cls.testClient.getZoneForTests()) cls.services['mode'] = cls.zone.networktype cls.template = get_template( cls.apiclient, @@ -1218,7 +1224,7 @@ def tearDownClass(cls): raise Exception("Warning: Exception during cleanup : %s" % e) return - @attr(tags=["advanced", "advancedns"]) + @attr(tags=["advanced", "advancedns", "selfservice"]) def test_create_network_with_snat(self): """Test to create a network with SourceNAT service only""" @@ -1265,7 +1271,7 @@ def test_create_network_with_snat(self): self.debug("Deploying VM in account: %s on the network %s" % (self.account.name, self.network.id)) # Spawn an instance in that network - virtual_machine = VirtualMachine.create( + VirtualMachine.create( self.apiclient, self.services["virtual_machine"], accountid=self.account.name, diff --git a/test/integration/component/test_non_contiguous_vlan.py b/test/integration/component/test_non_contiguous_vlan.py index 3ebaf3a97e..4609af95f1 100644 --- a/test/integration/component/test_non_contiguous_vlan.py +++ b/test/integration/component/test_non_contiguous_vlan.py @@ -28,17 +28,17 @@ from marvin.cloudstackTestCase import (cloudstackTestCase,unittest) -from marvin.integration.lib.base import (Account, +from marvin.lib.base import (Account, ServiceOffering, PhysicalNetwork, VirtualMachine, ) -from marvin.integration.lib.common import (get_zone, +from marvin.lib.common import (get_zone, get_pod, get_domain, get_template, setNonContiguousVlanIds) -from marvin.integration.lib.utils import (cleanup_resources, +from marvin.lib.utils import (cleanup_resources, xsplit) from nose.plugins.attrib import attr @@ -47,7 +47,7 @@ class Services(): def __init__(self): self.services = { - "vlan": { + "vlan_nc": { "partial_range": ["",""], "full_range": "", }, @@ -89,12 +89,14 @@ class TestNonContiguousVLANRanges(cloudstackTestCase): """ @classmethod def setUpClass(cls): - cls.api_client = super(TestNonContiguousVLANRanges, cls).getClsTestClient().getApiClient() + cls.testClient = super(TestNonContiguousVLANRanges, cls).getClsTestClient() + cls.api_client = cls.testClient.getApiClient() + cls.services = Services().services - # Get Zone, pod, domain - cls.zone = get_zone(cls.api_client, cls.services) - cls.pod = get_pod(cls.api_client, cls.zone.id, cls.services) - cls.domain = get_domain(cls.api_client, cls.services) + # Get Zone, Domain and templates + cls.zone = get_zone(cls.api_client, cls.testClient.getZoneForTests()) + cls.pod = get_pod(cls.api_client, cls.zone.id) + cls.domain = get_domain(cls.api_client) cls.service_offering = ServiceOffering.create( cls.api_client, @@ -123,7 +125,7 @@ def tearDownClass(cls): def setUp(self): self.apiclient = self.testClient.getApiClient() - self.vlan = self.services["vlan"] + self.vlan = self.services["vlan_nc"] self.apiClient = self.testClient.getApiClient() self.physicalnetwork, self.vlan = setNonContiguousVlanIds(self.apiclient, self.zone.id) diff --git a/test/integration/component/test_persistent_networks.py b/test/integration/component/test_persistent_networks.py index 8c1d54d192..d42ffcd4bc 100644 --- a/test/integration/component/test_persistent_networks.py +++ b/test/integration/component/test_persistent_networks.py @@ -14,64 +14,56 @@ # KIND, either express or implied. See the License for the # specific language governing permissions and limitations # under the License. -""" Tests for Persistent Networks without running VMs feature - - Test Plan: https://cwiki.apache.org/confluence/display/CLOUDSTACK/Persistent+Networks+without+a+running+VM - - Issue Link: https://issues.apache.org/jira/browse/CLOUDSTACK-2232 - - Feature Specifications: https://cwiki.apache.org/confluence/display/CLOUDSTACK/FS+-+Persistent+Networks -""" -from marvin.cloudstackTestCase import cloudstackTestCase, unittest -from marvin.integration.lib.utils import (cleanup_resources, - validateList, - get_hypervisor_type) -from marvin.integration.lib.base import (Account, - ServiceOffering, - NetworkOffering, - Network, - VirtualMachine, - PublicIPAddress, - FireWallRule, - Router, - Host, - NATRule, - Project, - LoadBalancerRule, - VpcOffering, - VPC, - Domain, - StaticNATRule, - NetworkACL) -from marvin.integration.lib.common import (get_domain, - get_zone, - get_template, - wait_for_cleanup, - add_netscaler, - verifyNetworkState) - +""" Tests for Persistent Networks without running VMs feature""" +from marvin.lib.utils import (cleanup_resources, + validateList, + get_hypervisor_type) +from marvin.lib.base import (Account, + VPC, + VirtualMachine, + LoadBalancerRule, + Network, + Domain, + Router, + NetworkACL, + PublicIPAddress, + VpcOffering, + ServiceOffering, + Project, + NetworkOffering, + NATRule, + FireWallRule, + Host, + StaticNATRule) +from marvin.lib.common import (get_domain, + get_zone, + get_template, + verifyNetworkState, + add_netscaler, + wait_for_cleanup) from nose.plugins.attrib import attr -from marvin.codes import PASS, FAIL +from marvin.codes import PASS, FAIL, FAILED from marvin.sshClient import SshClient +from marvin.cloudstackTestCase import cloudstackTestCase, unittest from ddt import ddt, data import time @ddt class TestPersistentNetworks(cloudstackTestCase): - """Test Persistent Networks without running VMs - """ - + ''' + Test Persistent Networks without running VMs + ''' @classmethod def setUpClass(cls): - cloudstackTestClient = super(TestPersistentNetworks,cls).getClsTestClient() - cls.api_client = cloudstackTestClient.getApiClient() + cls.testClient = super(TestPersistentNetworks, cls).getClsTestClient() + cls.api_client = cls.testClient.getApiClient() # Fill services from the external config file - cls.services = cloudstackTestClient.getConfigParser().parsedDict + cls.services = cls.testClient.getParsedTestDataConfig() # Get Zone, Domain and templates - cls.domain = get_domain(cls.api_client, cls.services) - cls.zone = get_zone(cls.api_client, cls.services) + cls.domain = get_domain(cls.api_client) + cls.zone = get_zone(cls.api_client, cls.testClient.getZoneForTests()) cls.template = get_template( cls.api_client, cls.zone.id, @@ -209,7 +201,7 @@ def tearDown(self): raise Exception("Warning: Exception during cleanup : %s" % e) return - @attr(tags=["advanced"]) + @attr(tags=["advanced", "selfservice"]) def test_network_state_after_destroying_vms(self): # steps # 1. Create an isolated persistent network @@ -227,7 +219,13 @@ def test_network_state_after_destroying_vms(self): accountid=self.account.name,domainid=self.domain.id, zoneid=self.zone.id) self.cleanup.append(network) - verifyNetworkState(self.apiclient, network.id, "implemented") + response = verifyNetworkState(self.apiclient, network.id, "implemented") + exceptionOccured = response[0] + isNetworkInDesiredState = response[1] + exceptionMessage = response[2] + + if (exceptionOccured or (not isNetworkInDesiredState)): + self.fail(exceptionMessage) self.assertIsNotNone(network.vlan, "vlan must not be null for persistent network") try: @@ -246,9 +244,15 @@ def test_network_state_after_destroying_vms(self): wait_for_cleanup(self.api_client, ["network.gc.interval", "network.gc.wait"]) verifyNetworkState(self.api_client, network.id, "implemented") + exceptionOccured = response[0] + isNetworkInDesiredState = response[1] + exceptionMessage = response[2] + + if (exceptionOccured or (not isNetworkInDesiredState)): + self.fail(exceptionMessage) return - @attr(tags=["advanced"]) + @attr(tags=["advanced", "selfservice"]) def test_shared_network_offering_with_persistent(self): # steps # 1. create shared network offering with persistent field enabled @@ -333,7 +337,13 @@ def test_upgrade_to_persistent_services_VR(self, value): networkofferingid=networkOffering.id, accountid=account.name,domainid=self.domain.id, zoneid=self.zone.id) - verifyNetworkState(self.api_client, isolated_network.id, "allocated") + response = verifyNetworkState(self.api_client, isolated_network.id, "allocated") + exceptionOccured = response[0] + isNetworkInDesiredState = response[1] + exceptionMessage = response[2] + + if (exceptionOccured or (not isNetworkInDesiredState)): + self.fail(exceptionMessage) # Update the network with persistent network offering isolated_network.update(self.apiclient, networkofferingid=self.isolated_persistent_network_offering.id, changecidr=changecidr) @@ -377,7 +387,13 @@ def test_upgrade_to_persistent_services_VR(self, value): wait_for_cleanup(self.api_client, ["network.gc.interval", "network.gc.wait"]) # Check network state now, this will bolster that network updation has taken effect - verifyNetworkState(self.api_client, isolated_network.id, "implemented") + response = verifyNetworkState(self.api_client, isolated_network.id, "implemented") + exceptionOccured = response[0] + isNetworkInDesiredState = response[1] + exceptionMessage = response[2] + + if (exceptionOccured or (not isNetworkInDesiredState)): + self.fail(exceptionMessage) return @attr(tags=["advanced"]) @@ -402,7 +418,13 @@ def test_upgrade_network_VR_to_PersistentRVR(self): networkofferingid=self.isolated_network_offering.id, accountid=account.name,domainid=self.domain.id, zoneid=self.zone.id) - verifyNetworkState(self.api_client, isolated_network.id, "allocated") + response = verifyNetworkState(self.api_client, isolated_network.id, "allocated") + exceptionOccured = response[0] + isNetworkInDesiredState = response[1] + exceptionMessage = response[2] + + if (exceptionOccured or (not isNetworkInDesiredState)): + self.fail(exceptionMessage) # Update network with network offering which has RVR isolated_network.update(self.apiclient, networkofferingid=self.isolated_persistent_network_offering_RVR.id) @@ -444,7 +466,13 @@ def test_upgrade_network_VR_to_PersistentRVR(self): wait_for_cleanup(self.api_client, ["network.gc.interval", "network.gc.wait"]) # Check network state now, this will bolster that network updation has taken effect - verifyNetworkState(self.api_client, isolated_network.id, "implemented") + response = verifyNetworkState(self.api_client, isolated_network.id, "implemented") + exceptionOccured = response[0] + isNetworkInDesiredState = response[1] + exceptionMessage = response[2] + + if (exceptionOccured or (not isNetworkInDesiredState)): + self.fail(exceptionMessage) return @attr(tags=["advanced", "advancedns"]) @@ -475,7 +503,13 @@ def test_upgrade_network_NS_to_persistent_NS(self): networkofferingid=self.isolated_network_offering_netscaler.id, accountid=account.name,domainid=self.domain.id, zoneid=self.zone.id) - verifyNetworkState(self.api_client, isolated_network.id, "allocated") + response = verifyNetworkState(self.api_client, isolated_network.id, "allocated") + exceptionOccured = response[0] + isNetworkInDesiredState = response[1] + exceptionMessage = response[2] + + if (exceptionOccured or (not isNetworkInDesiredState)): + self.fail(exceptionMessage) isolated_network.update(self.apiclient, networkofferingid=self.isolated_persistent_network_offering_netscaler.id, changecidr=True) @@ -515,7 +549,13 @@ def test_upgrade_network_NS_to_persistent_NS(self): wait_for_cleanup(self.api_client, ["network.gc.interval", "network.gc.wait"]) # Check network state now, this will bolster that network updation has taken effect - verifyNetworkState(self.api_client, isolated_network.id, "implemented") + response = verifyNetworkState(self.api_client, isolated_network.id, "implemented") + exceptionOccured = response[0] + isNetworkInDesiredState = response[1] + exceptionMessage = response[2] + + if (exceptionOccured or (not isNetworkInDesiredState)): + self.fail(exceptionMessage) return @data("LB-VR","LB-Netscaler") @@ -888,7 +928,13 @@ def test_change_persistent_network_to_non_persistent(self): wait_for_cleanup(self.api_client, ["network.gc.interval", "network.gc.wait"]) # Check network state now, this will bolster that network updation has taken effect - verifyNetworkState(self.api_client, network.id, "allocated") + response = verifyNetworkState(self.api_client, network.id, "allocated") + exceptionOccured = response[0] + isNetworkInDesiredState = response[1] + exceptionMessage = response[2] + + if (exceptionOccured or (not isNetworkInDesiredState)): + self.fail(exceptionMessage) return @attr(tags=["advanced"]) @@ -951,20 +997,22 @@ class TestAssignVirtualMachine(cloudstackTestCase): @classmethod def setUpClass(cls): - cloudstackTestClient = super(TestAssignVirtualMachine,cls).getClsTestClient() - cls.api_client = cloudstackTestClient.getApiClient() + cls.testClient = super(TestAssignVirtualMachine, cls).getClsTestClient() + cls.api_client = cls.testClient.getApiClient() # Fill services from the external config file - cls.services = cloudstackTestClient.getConfigParser().parsedDict + cls.services = cls.testClient.getParsedTestDataConfig() # Get Zone, Domain and templates - cls.domain = get_domain(cls.api_client, cls.services) - cls.zone = get_zone(cls.api_client, cls.services) + cls.domain = get_domain(cls.api_client) + cls.zone = get_zone(cls.api_client, cls.testClient.getZoneForTests()) cls.template = get_template( cls.api_client, cls.zone.id, cls.services["ostype"] ) + if cls.template == FAILED: + assert False, "get_template() failed to return template" cls.services["virtual_machine"]["zoneid"] = cls.zone.id cls.services["virtual_machine"]["template"] = cls.template.id cls.service_offering = ServiceOffering.create( @@ -1070,7 +1118,13 @@ def test_assign_vm_different_account_VR(self, value): networkofferingid=network_offering.id, accountid=account_1.name,domainid=self.domain.id, zoneid=self.zone.id) - verifyNetworkState(self.api_client, network.id, "implemented") + response = verifyNetworkState(self.api_client, network.id, "implemented") + exceptionOccured = response[0] + isNetworkInDesiredState = response[1] + exceptionMessage = response[2] + + if (exceptionOccured or (not isNetworkInDesiredState)): + self.fail(exceptionMessage) self.assertIsNotNone(network.vlan, "vlan must not be null for persistent network") try: @@ -1078,24 +1132,20 @@ def test_assign_vm_different_account_VR(self, value): networkids=[network.id], serviceofferingid=self.service_offering.id, accountid=account_1.name,domainid=self.domain.id) - except Exception as e: - self.fail("vm creation failed: %s" % e) - - virtual_machine.stop(self.apiclient) - vms = VirtualMachine.list(self.apiclient, id=virtual_machine.id) - self.assertEqual(validateList(vms)[0], PASS, "vm list validation failed, vm list is %s" % vms) - self.assertEqual(str(vms[0].state).lower(), "stopped", "vm state should be stopped, it is %s" % vms[0].state) + virtual_machine.stop(self.apiclient) - # Assign virtual machine to different account - virtual_machine.assign_virtual_machine(self.apiclient, account=account_2.name, domainid=self.domain.id) + # Assign virtual machine to different account + virtual_machine.assign_virtual_machine(self.apiclient, account=account_2.name, domainid=self.domain.id) - # Start VM - virtual_machine.start(self.apiclient) + # Start VM + virtual_machine.start(self.apiclient) - # Verify that new network is created in other account - networks = Network.list(self.apiclient, account=account_2.name, domainid = account_2.domainid) - self.assertEqual(validateList(networks)[0], PASS, "networks list validation failed, list is %s" % networks) + # Verify that new network is created in other account + networks = Network.list(self.apiclient, account=account_2.name, domainid = account_2.domainid) + self.assertEqual(validateList(networks)[0], PASS, "networks list validation failed, list is %s" % networks) + except Exception as e: + self.fail("Exception occured: %s" % e) return @ddt @@ -1105,20 +1155,22 @@ class TestProjectAccountOperations(cloudstackTestCase): @classmethod def setUpClass(cls): - cloudstackTestClient = super(TestProjectAccountOperations,cls).getClsTestClient() - cls.api_client = cloudstackTestClient.getApiClient() + cls.testClient = super(TestProjectAccountOperations, cls).getClsTestClient() + cls.api_client = cls.testClient.getApiClient() # Fill services from the external config file - cls.services = cloudstackTestClient.getConfigParser().parsedDict + cls.services = cls.testClient.getParsedTestDataConfig() # Get Zone, Domain and templates - cls.domain = get_domain(cls.api_client, cls.services) - cls.zone = get_zone(cls.api_client, cls.services) + cls.domain = get_domain(cls.api_client) + cls.zone = get_zone(cls.api_client, cls.testClient.getZoneForTests()) cls.template = get_template( cls.api_client, cls.zone.id, cls.services["ostype"] ) + if cls.template == FAILED: + assert False, "get_template() failed to return template" cls.services["virtual_machine"]["zoneid"] = cls.zone.id cls.services["virtual_machine"]["template"] = cls.template.id cls.service_offering = ServiceOffering.create( @@ -1181,7 +1233,13 @@ def test_account_operations(self, value): networkofferingid=self.isolated_persistent_network_offering.id, accountid=account.name,domainid=self.domain.id, zoneid=self.zone.id) - verifyNetworkState(self.api_client, network.id, "implemented") + response = verifyNetworkState(self.api_client, network.id, "implemented") + exceptionOccured = response[0] + isNetworkInDesiredState = response[1] + exceptionMessage = response[2] + + if (exceptionOccured or (not isNetworkInDesiredState)): + self.fail(exceptionMessage) self.assertIsNotNone(network.vlan, "vlan must not be null for persistent network") if value == "disabled": @@ -1199,7 +1257,13 @@ def test_account_operations(self, value): networks = Network.list(self.apiclient, account=account.name, domainid = account.domainid) self.assertEqual(validateList(networks)[0], PASS, "networks list validation failed, list is %s" % networks) - verifyNetworkState(self.api_client, networks[0].id, "implemented") + response = verifyNetworkState(self.api_client, networks[0].id, "implemented") + exceptionOccured = response[0] + isNetworkInDesiredState = response[1] + exceptionMessage = response[2] + + if (exceptionOccured or (not isNetworkInDesiredState)): + self.fail(exceptionMessage) self.assertIsNotNone(networks[0].vlan, "vlan must not be null for persistent network") return @@ -1250,7 +1314,13 @@ def test_project_operations(self): # Wait for network cleanup interval wait_for_cleanup(self.api_client, ["network.gc.interval", "network.gc.wait"]) - verifyNetworkState(self.apiclient, network.id, "implemented") + response = verifyNetworkState(self.apiclient, network.id, "implemented") + exceptionOccured = response[0] + isNetworkInDesiredState = response[1] + exceptionMessage = response[2] + + if (exceptionOccured or (not isNetworkInDesiredState)): + self.fail(exceptionMessage) return @ddt @@ -1260,20 +1330,22 @@ class TestRestartPersistentNetwork(cloudstackTestCase): @classmethod def setUpClass(cls): - cloudstackTestClient = super(TestRestartPersistentNetwork,cls).getClsTestClient() - cls.api_client = cloudstackTestClient.getApiClient() + cls.testClient = super(TestRestartPersistentNetwork, cls).getClsTestClient() + cls.api_client = cls.testClient.getApiClient() # Fill services from the external config file - cls.services = cloudstackTestClient.getConfigParser().parsedDict + cls.services = cls.testClient.getParsedTestDataConfig() # Get Zone, Domain and templates - cls.domain = get_domain(cls.api_client, cls.services) - cls.zone = get_zone(cls.api_client, cls.services) + cls.domain = get_domain(cls.api_client) + cls.zone = get_zone(cls.api_client, cls.testClient.getZoneForTests()) cls.template = get_template( cls.api_client, cls.zone.id, cls.services["ostype"] ) + if cls.template == FAILED: + assert False, "get_template() failed to return template" cls.services["virtual_machine"]["zoneid"] = cls.zone.id cls.services["virtual_machine"]["template"] = cls.template.id cls.service_offering = ServiceOffering.create( @@ -1384,7 +1456,13 @@ def test_cleanup_persistent_network(self, value): networkofferingid=self.isolated_persistent_network_offering.id, accountid=account.name,domainid=self.domain.id, zoneid=self.zone.id) - verifyNetworkState(self.apiclient, isolated_persistent_network.id, "implemented") + response = verifyNetworkState(self.apiclient, isolated_persistent_network.id, "implemented") + exceptionOccured = response[0] + isNetworkInDesiredState = response[1] + exceptionMessage = response[2] + + if (exceptionOccured or (not isNetworkInDesiredState)): + self.fail(exceptionMessage) self.assertIsNotNone(isolated_persistent_network.vlan, "vlan must not be null for persistent network") self.debug("Listing routers for network: %s" % isolated_persistent_network.name) @@ -1419,6 +1497,12 @@ def test_cleanup_persistent_network(self, value): self.assertEqual(validateList(networks)[0], PASS, "networks list validation failed, list is %s" % networks) verifyNetworkState(self.apiclient, networks[0].id, "implemented") + exceptionOccured = response[0] + isNetworkInDesiredState = response[1] + exceptionMessage = response[2] + + if (exceptionOccured or (not isNetworkInDesiredState)): + self.fail(exceptionMessage) self.assertIsNotNone(networks[0].vlan, "vlan must not be null for persistent network") # Deploy VM @@ -1459,7 +1543,13 @@ def test_cleanup_persistent_network_lb_netscaler(self, value): networkofferingid=self.isolated_persistent_network_offering_netscaler.id, accountid=account.name,domainid=self.domain.id, zoneid=self.zone.id) - verifyNetworkState(self.apiclient, isolated_persistent_network.id, "implemented") + response = verifyNetworkState(self.apiclient, isolated_persistent_network.id, "implemented") + exceptionOccured = response[0] + isNetworkInDesiredState = response[1] + exceptionMessage = response[2] + + if (exceptionOccured or (not isNetworkInDesiredState)): + self.fail(exceptionMessage) self.assertIsNotNone(isolated_persistent_network.vlan, "vlan must not be null for persistent network") self.debug("Listing routers for network: %s" % isolated_persistent_network.name) @@ -1489,7 +1579,13 @@ def test_cleanup_persistent_network_lb_netscaler(self, value): networks = Network.list(self.apiclient, account=account.name, domainid = account.domainid) self.assertEqual(validateList(networks)[0], PASS, "networks list validation failed, list is %s" % networks) - verifyNetworkState(self.apiclient, networks[0].id, "implemented") + response = verifyNetworkState(self.apiclient, networks[0].id, "implemented") + exceptionOccured = response[0] + isNetworkInDesiredState = response[1] + exceptionMessage = response[2] + + if (exceptionOccured or (not isNetworkInDesiredState)): + self.fail(exceptionMessage) self.assertIsNotNone(networks[0].vlan, "vlan must not be null for persistent network") # Deploy VM @@ -1516,25 +1612,28 @@ class TestVPCNetworkOperations(cloudstackTestCase): @classmethod def setUpClass(cls): - cloudstackTestClient = super(TestVPCNetworkOperations,cls).getClsTestClient() - cls.api_client = cloudstackTestClient.getApiClient() + cls.testClient = super(TestVPCNetworkOperations, cls).getClsTestClient() + cls.api_client = cls.testClient.getApiClient() # Fill services from the external config file - cls.services = cloudstackTestClient.getConfigParser().parsedDict + cls.services = cls.testClient.getParsedTestDataConfig() # Get Zone, Domain and templates - cls.domain = get_domain(cls.api_client, cls.services) - cls.zone = get_zone(cls.api_client, cls.services) + cls.domain = get_domain(cls.api_client) + cls.zone = get_zone(cls.api_client, cls.testClient.getZoneForTests()) cls.template = get_template( cls.api_client, cls.zone.id, cls.services["ostype"] ) + if cls.template == FAILED: + assert False, "get_template() failed to return template" + 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.services["service_offerings"]["small"] ) cls.persistent_network_offering_NoLB = NetworkOffering.create(cls.api_client, cls.services["nw_off_persistent_VPCVR_NoLB"], conservemode=False) @@ -1688,21 +1787,45 @@ def test_vpc_network_life_cycle(self, value): networkofferingid=self.persistent_network_offering_NoLB.id, accountid=account.name,domainid=self.domain.id, zoneid=self.zone.id, vpcid=vpc.id, gateway="10.1.1.1", netmask="255.255.255.0") - verifyNetworkState(self.apiclient, persistent_network_1.id, "implemented") + response = verifyNetworkState(self.apiclient, persistent_network_1.id, "implemented") + exceptionOccured = response[0] + isNetworkInDesiredState = response[1] + exceptionMessage = response[2] + + if (exceptionOccured or (not isNetworkInDesiredState)): + self.fail(exceptionMessage) self.assertIsNotNone(persistent_network_1.vlan, "vlan must not be null for persistent network %s" % persistent_network_1.id) persistent_network_2 = Network.create(self.api_client,self.services["isolated_network"], networkofferingid=self.persistent_network_offering_NoLB.id, accountid=account.name,domainid=self.domain.id, zoneid=self.zone.id, vpcid=vpc.id, gateway="10.1.2.1", netmask="255.255.255.0") - verifyNetworkState(self.apiclient, persistent_network_2.id, "implemented") + response = verifyNetworkState(self.apiclient, persistent_network_2.id, "implemented") + exceptionOccured = response[0] + isNetworkInDesiredState = response[1] + exceptionMessage = response[2] + + if (exceptionOccured or (not isNetworkInDesiredState)): + self.fail(exceptionMessage) self.assertIsNotNone(persistent_network_2.vlan, "vlan must not be null for persistent network: %s" % persistent_network_2.id) if value == "restart": # Restart VPC vpc.restart(self.apiclient) - verifyNetworkState(self.apiclient, persistent_network_1.id, "implemented") - verifyNetworkState(self.apiclient, persistent_network_2.id, "implemented") + response = verifyNetworkState(self.apiclient, persistent_network_1.id, "implemented") + exceptionOccured = response[0] + isNetworkInDesiredState = response[1] + exceptionMessage = response[2] + + if (exceptionOccured or (not isNetworkInDesiredState)): + self.fail(exceptionMessage) + response = verifyNetworkState(self.apiclient, persistent_network_2.id, "implemented") + exceptionOccured = response[0] + isNetworkInDesiredState = response[1] + exceptionMessage = response[2] + + if (exceptionOccured or (not isNetworkInDesiredState)): + self.fail(exceptionMessage) elif value == "delete": vpc.delete(self.apiclient) @@ -1752,14 +1875,26 @@ def test_vpc_force_delete_domain(self): networkofferingid=self.persistent_network_offering_NoLB.id, accountid=account_1.name,domainid=account_1.domainid, zoneid=self.zone.id, vpcid=vpc_1.id, gateway="10.1.1.1", netmask="255.255.255.0") - verifyNetworkState(self.apiclient, persistent_network_1.id, "implemented") + response = verifyNetworkState(self.apiclient, persistent_network_1.id, "implemented") + exceptionOccured = response[0] + isNetworkInDesiredState = response[1] + exceptionMessage = response[2] + + if (exceptionOccured or (not isNetworkInDesiredState)): + self.fail(exceptionMessage) self.assertIsNotNone(persistent_network_1.vlan, "vlan must not be null for persistent network %s" % persistent_network_1.id) persistent_network_2 = Network.create(self.api_client,self.services["isolated_network"], networkofferingid=self.persistent_network_offering_NoLB.id, accountid=account_2.name,domainid=account_2.domainid, zoneid=self.zone.id, vpcid=vpc_2.id, gateway="10.1.1.1", netmask="255.255.255.0") - verifyNetworkState(self.apiclient, persistent_network_2.id, "implemented") + response = verifyNetworkState(self.apiclient, persistent_network_2.id, "implemented") + exceptionOccured = response[0] + isNetworkInDesiredState = response[1] + exceptionMessage = response[2] + + if (exceptionOccured or (not isNetworkInDesiredState)): + self.fail(exceptionMessage) self.assertIsNotNone(persistent_network_2.vlan, "vlan must not be null for persistent network: %s" % persistent_network_2.id) # Force delete domain @@ -1813,14 +1948,26 @@ def test_vpc_delete_account(self): networkofferingid=self.persistent_network_offering_NoLB.id, accountid=account.name,domainid=account.domainid, zoneid=self.zone.id, vpcid=vpc.id, gateway="10.1.1.1", netmask="255.255.255.0") - verifyNetworkState(self.apiclient, persistent_network_1.id, "implemented") + response = verifyNetworkState(self.apiclient, persistent_network_1.id, "implemented") + exceptionOccured = response[0] + isNetworkInDesiredState = response[1] + exceptionMessage = response[2] + + if (exceptionOccured or (not isNetworkInDesiredState)): + self.fail(exceptionMessage) self.assertIsNotNone(persistent_network_1.vlan, "vlan must not be null for persistent network %s" % persistent_network_1.id) persistent_network_2 = Network.create(self.api_client,self.services["isolated_network"], networkofferingid=self.persistent_network_offering_LB.id, accountid=account.name,domainid=account.domainid, zoneid=self.zone.id, vpcid=vpc.id, gateway="10.1.2.1", netmask="255.255.255.0") - verifyNetworkState(self.apiclient, persistent_network_2.id, "implemented") + response = verifyNetworkState(self.apiclient, persistent_network_2.id, "implemented") + exceptionOccured = response[0] + isNetworkInDesiredState = response[1] + exceptionMessage = response[2] + + if (exceptionOccured or (not isNetworkInDesiredState)): + self.fail(exceptionMessage) self.assertIsNotNone(persistent_network_2.vlan, "vlan must not be null for persistent network: %s" % persistent_network_2.id) # Deploy VMs in above networks (VM1, VM2 in network1 and VM3, VM4 in network2) @@ -1924,14 +2071,26 @@ def test_vpc_private_gateway_static_route(self): networkofferingid=self.persistent_network_offering_NoLB.id, accountid=account.name,domainid=account.domainid, zoneid=self.zone.id, vpcid=vpc.id, gateway="10.1.1.1", netmask="255.255.255.0") - verifyNetworkState(self.apiclient, persistent_network_1.id, "implemented") + response = verifyNetworkState(self.apiclient, persistent_network_1.id, "implemented") + exceptionOccured = response[0] + isNetworkInDesiredState = response[1] + exceptionMessage = response[2] + + if (exceptionOccured or (not isNetworkInDesiredState)): + self.fail(exceptionMessage) self.assertIsNotNone(persistent_network_1.vlan, "vlan must not be null for persistent network %s" % persistent_network_1.id) persistent_network_2 = Network.create(self.api_client,self.services["isolated_network"], networkofferingid=self.persistent_network_offering_LB.id, accountid=account.name,domainid=account.domainid, zoneid=self.zone.id, vpcid=vpc.id, gateway="10.1.2.1", netmask="255.255.255.0") - verifyNetworkState(self.apiclient, persistent_network_2.id, "implemented") + response = verifyNetworkState(self.apiclient, persistent_network_2.id, "implemented") + exceptionOccured = response[0] + isNetworkInDesiredState = response[1] + exceptionMessage = response[2] + + if (exceptionOccured or (not isNetworkInDesiredState)): + self.fail(exceptionMessage) self.assertIsNotNone(persistent_network_2.vlan, "vlan must not be null for persistent network: %s" % persistent_network_2.id) # Deploy VMs in above networks (VM1, VM2 in network1 and VM3, VM4 in network2) diff --git a/test/integration/component/test_portable_ip.py b/test/integration/component/test_portable_ip.py index 40d80abbea..61268ebc7c 100644 --- a/test/integration/component/test_portable_ip.py +++ b/test/integration/component/test_portable_ip.py @@ -21,25 +21,11 @@ Feature Specifications: https://cwiki.apache.org/confluence/display/CLOUDSTACK/portable+public+IP """ from marvin.cloudstackTestCase import cloudstackTestCase -from marvin.integration.lib.utils import cleanup_resources -from marvin.integration.lib.base import (Account, - NetworkOffering, - ServiceOffering, - Network, - VirtualMachine, - PublicIPAddress, - FireWallRule, - NATRule, - PortablePublicIpRange, - StaticNATRule) -from marvin.integration.lib.common import (get_zone, - get_pod, - get_domain, - get_region, - get_template, - get_portable_ip_range_services, - is_public_ip_in_correct_state) -from netaddr import IPAddress +from marvin.cloudstackException import CloudstackAPIException +from marvin.lib.utils import * +from marvin.lib.base import * +from marvin.lib.common import * +from netaddr import * from marvin.sshClient import SshClient from nose.plugins.attrib import attr @@ -144,6 +130,14 @@ def __init__(self): "protocol": 'TCP', }, "ostype": 'CentOS 5.3 (64-bit)', + "portableIpRange": { + "gateway" : "10.223.252.195", + "netmask" : "255.255.255.192", + "startip" : "10.223.252.196", + "endip" : "10.223.252.197", + "vlan" : "1001" + } + } class TestCreatePortablePublicIpRanges(cloudstackTestCase): @@ -153,13 +147,15 @@ class TestCreatePortablePublicIpRanges(cloudstackTestCase): @classmethod def setUpClass(cls): - cls.api_client = super(TestCreatePortablePublicIpRanges, cls).getClsTestClient().getApiClient() + cls.testClient = super(TestCreatePortablePublicIpRanges, cls).getClsTestClient() + cls.api_client = cls.testClient.getApiClient() + cls.services = Services().services # Get Zone, Domain and templates - cls.region = get_region(cls.api_client, cls.services) - cls.domain = get_domain(cls.api_client, cls.services) - cls.zone = get_zone(cls.api_client, cls.services) - cls.pod = get_pod(cls.api_client, cls.zone.id, cls.services) + cls.region = get_region(cls.api_client) + cls.domain = get_domain(cls.api_client) + cls.zone = get_zone(cls.api_client, cls.testClient.getZoneForTests()) + cls.pod = get_pod(cls.api_client, cls.zone.id) cls.services['mode'] = cls.zone.networktype cls.services["domainid"] = cls.domain.id cls.services["zoneid"] = cls.zone.id @@ -192,14 +188,14 @@ def tearDown(self): raise Exception("Warning: Exception during cleanup : %s" % e) return - @attr(tags=["advanced"]) + @attr(tags=["advanced", "selfservice"]) def test_create_portable_ip_range(self): """Test create new portable ip range """ # 1. Create new portable ip range with root admin api # 2. Portable ip range should be created successfully - portable_ip_range_services = get_portable_ip_range_services(self.config) + portable_ip_range_services = self.services["portableIpRange"] self.debug(portable_ip_range_services) @@ -225,7 +221,7 @@ def test_create_portable_ip_range(self): return - @attr(tags=["advanced"]) + @attr(tags=["advanced", "selfservice"]) def test_create_portable_ip_range_non_root_admin(self): """Test create new portable ip range with non admin root account """ @@ -238,12 +234,12 @@ def test_create_portable_ip_range_non_root_admin(self): domainid=self.domain.id ) - self.api_client_user = self.testClient.createUserApiClient( + self.api_client_user = self.testClient.getUserApiClient( UserName=self.account.name, DomainName=self.account.domain ) - portable_ip_range_services = get_portable_ip_range_services(self.config) + portable_ip_range_services = self.services["portableIpRange"] if portable_ip_range_services is None: self.skipTest('Failed to read config values related to portable ip range') @@ -258,14 +254,14 @@ def test_create_portable_ip_range_non_root_admin(self): return - @attr(tags=["advanced"]) + @attr(tags=["advanced", "selfservice"]) def test_create_portable_ip_range_invalid_region(self): """Test create portable ip range with invalid region id""" # 1. Try to create new portable ip range with invalid region id # 2. Portable ip range creation should fail - portable_ip_range_services = get_portable_ip_range_services(self.config) + portable_ip_range_services = self.services["portableIpRange"] if portable_ip_range_services is None: self.skipTest('Failed to read config values related to portable ip range') @@ -289,13 +285,15 @@ class TestDeletePortablePublicIpRanges(cloudstackTestCase): @classmethod def setUpClass(cls): - cls.api_client = super(TestDeletePortablePublicIpRanges, cls).getClsTestClient().getApiClient() + cls.testClient = super(TestDeletePortablePublicIpRanges, cls).getClsTestClient() + cls.api_client = cls.testClient.getApiClient() + cls.services = Services().services # Get Zone, Domain and templates - cls.region = get_region(cls.api_client, cls.services) - cls.domain = get_domain(cls.api_client, cls.services) - cls.zone = get_zone(cls.api_client, cls.services) - cls.pod = get_pod(cls.api_client, cls.zone.id, cls.services) + cls.region = get_region(cls.api_client) + cls.domain = get_domain(cls.api_client) + cls.zone = get_zone(cls.api_client, cls.testClient.getZoneForTests()) + cls.pod = get_pod(cls.api_client, cls.zone.id) cls.services['mode'] = cls.zone.networktype cls.services["domainid"] = cls.domain.id cls.services["zoneid"] = cls.zone.id @@ -317,7 +315,7 @@ def setUp(self): self.apiclient = self.testClient.getApiClient() self.dbclient = self.testClient.getDbConnection() - portable_ip_range_services = get_portable_ip_range_services(self.config) + portable_ip_range_services = self.services["portableIpRange"] if portable_ip_range_services is None: self.skipTest('Failed to read config values related to portable ip range') @@ -348,7 +346,7 @@ def tearDown(self): raise Exception("Warning: Exception during cleanup : %s" % e) return - @attr(tags=["advanced"]) + @attr(tags=["advanced", "selfservice"]) def test_delete_portable_ip_range(self): """Test delete ip range """ @@ -363,7 +361,7 @@ def test_delete_portable_ip_range(self): return - @attr(tags=["advanced"]) + @attr(tags=["advanced", "selfservice"]) def test_delete_portable_ip_range_non_root_admin(self): """Test delete ip range - non admin root """ @@ -378,7 +376,7 @@ def test_delete_portable_ip_range_non_root_admin(self): self.cleanup.append(self.account) - self.api_client_user = self.testClient.createUserApiClient( + self.api_client_user = self.testClient.getUserApiClient( UserName=self.account.name, DomainName=self.account.domain ) @@ -389,7 +387,7 @@ def test_delete_portable_ip_range_non_root_admin(self): self.portable_ip_range.delete(self.apiclient) return - @attr(tags=["advanced"]) + @attr(tags=["advanced", "selfservice"]) def test_delete_portable_ip_range_in_use(self): """Test delete ip range """ @@ -461,13 +459,15 @@ class TestListPortablePublicIpRanges(cloudstackTestCase): @classmethod def setUpClass(cls): - cls.api_client = super(TestListPortablePublicIpRanges, cls).getClsTestClient().getApiClient() + cls.testClient = super(TestListPortablePublicIpRanges, cls).getClsTestClient() + cls.api_client = cls.testClient.getApiClient() + cls.services = Services().services # Get Zone, Domain and templates - cls.region = get_region(cls.api_client, cls.services) - cls.domain = get_domain(cls.api_client, cls.services) - cls.zone = get_zone(cls.api_client, cls.services) - cls.pod = get_pod(cls.api_client, cls.zone.id, cls.services) + cls.region = get_region(cls.api_client) + cls.domain = get_domain(cls.api_client) + cls.zone = get_zone(cls.api_client, cls.testClient.getZoneForTests()) + cls.pod = get_pod(cls.api_client, cls.zone.id) cls.services['mode'] = cls.zone.networktype cls.services["domainid"] = cls.domain.id cls.services["zoneid"] = cls.zone.id @@ -490,7 +490,7 @@ def setUp(self): self.dbclient = self.testClient.getDbConnection() #create new portable ip range - self.portable_ip_range_services = get_portable_ip_range_services(self.config) + self.portable_ip_range_services = self.services["portableIpRange"] if self.portable_ip_range_services is None: self.skipTest('Failed to read config values related to portable ip range') @@ -521,7 +521,7 @@ def tearDown(self): raise Exception("Warning: Exception during cleanup : %s" % e) return - @attr(tags=["advanced"]) + @attr(tags=["advanced", "selfservice"]) def test_list_portable_ip_range(self): """Test list portable ip ranges """ @@ -553,7 +553,7 @@ def test_list_portable_ip_range(self): "Listed netmask not matching with the netmask of created public ip range") return - @attr(tags=["advanced"]) + @attr(tags=["advanced","swamy", "selfservice"]) def test_list_portable_ip_range_non_root_admin(self): """Test list portable ip ranges with non admin root account """ @@ -569,7 +569,7 @@ def test_list_portable_ip_range_non_root_admin(self): self.cleanup.append(self.account) - self.api_client_user = self.testClient.createUserApiClient( + self.api_client_user = self.testClient.getUserApiClient( UserName=self.account.name, DomainName=self.account.domain ) @@ -585,13 +585,15 @@ class TestAssociatePublicIp(cloudstackTestCase): """ @classmethod def setUpClass(cls): - cls.api_client = super(TestAssociatePublicIp, cls).getClsTestClient().getApiClient() + cls.testClient = super(TestAssociatePublicIp, cls).getClsTestClient() + cls.api_client = cls.testClient.getApiClient() + cls.services = Services().services # Get Zone, Domain and templates - cls.region = get_region(cls.api_client, cls.services) - cls.domain = get_domain(cls.api_client, cls.services) - cls.zone = get_zone(cls.api_client, cls.services) - cls.pod = get_pod(cls.api_client, cls.zone.id, cls.services) + cls.region = get_region(cls.api_client) + cls.domain = get_domain(cls.api_client) + cls.zone = get_zone(cls.api_client, cls.testClient.getZoneForTests()) + cls.pod = get_pod(cls.api_client, cls.zone.id) cls.services['mode'] = cls.zone.networktype cls.services["domainid"] = cls.domain.id cls.services["zoneid"] = cls.zone.id @@ -651,7 +653,7 @@ def setUp(self): self.cleanup = [] - portable_ip_range_services = get_portable_ip_range_services(self.config) + portable_ip_range_services = self.services["portableIpRange"] if portable_ip_range_services is None: self.skipTest('Failed to read config values related to portable ip range') @@ -684,7 +686,7 @@ def tearDown(self): raise Exception("Warning: Exception during cleanup : %s" % e) return - @attr(tags=["advanced"]) + @attr(tags=["advanced", "selfservice"]) def test_associate_ip_address(self): """ Test assocoate public ip address """ @@ -733,7 +735,7 @@ def test_associate_ip_address(self): return - @attr(tags=["advanced"]) + @attr(tags=["advanced", "selfservice"]) def test_associate_ip_address_invalid_zone(self): """ Test Associate IP with invalid zone id """ @@ -756,7 +758,7 @@ def test_associate_ip_address_invalid_zone(self): self.debug("Associating ip address failed") return - @attr(tags=["advanced"]) + @attr(tags=["advanced", "provisioning"]) def test_associate_ip_address_services_enable_disable(self): """ Test enabling and disabling NAT, Firewall services on portable ip """ @@ -852,7 +854,7 @@ def test_associate_ip_address_services_enable_disable(self): portableip.delete(self.apiclient) return - @attr(tags=["advanced"]) + @attr(tags=["advanced", "selfservice"]) def test_associate_ip_address_no_free_ip(self): """ Test assocoate public ip address """ @@ -909,13 +911,15 @@ class TestDisassociatePublicIp(cloudstackTestCase): """ @classmethod def setUpClass(cls): - cls.api_client = super(TestDisassociatePublicIp, cls).getClsTestClient().getApiClient() + cls.testClient = super(TestDisassociatePublicIp, cls).getClsTestClient() + cls.api_client = cls.testClient.getApiClient() + cls.services = Services().services # Get Zone, Domain and templates - cls.region = get_region(cls.api_client, cls.services) - cls.domain = get_domain(cls.api_client, cls.services) - cls.zone = get_zone(cls.api_client, cls.services) - cls.pod = get_pod(cls.api_client, cls.zone.id, cls.services) + cls.region = get_region(cls.api_client) + cls.domain = get_domain(cls.api_client) + cls.zone = get_zone(cls.api_client, cls.testClient.getZoneForTests()) + cls.pod = get_pod(cls.api_client, cls.zone.id) cls.services['mode'] = cls.zone.networktype cls.services["domainid"] = cls.domain.id cls.services["zoneid"] = cls.zone.id @@ -993,7 +997,7 @@ def setUp(self): self.dbclient = self.testClient.getDbConnection() self.cleanup = [] - portable_ip_range_services = get_portable_ip_range_services(self.config) + portable_ip_range_services = self.services["portableIpRange"] if portable_ip_range_services is None: self.skipTest('Failed to read config values related to portable ip range') @@ -1026,7 +1030,7 @@ def tearDown(self): raise Exception("Warning: Exception during cleanup : %s" % e) return - @attr(tags=["advanced"]) + @attr(tags=["advanced", "selfservice"]) def test_disassociate_ip_address_no_services(self): """ Test disassociating portable ip """ @@ -1057,7 +1061,7 @@ def test_disassociate_ip_address_no_services(self): return - @attr(tags=["advanced"]) + @attr(tags=["advanced", "selfservice"]) def test_disassociate_ip_address_services_enabled(self): """ Test disassociating portable ip """ @@ -1118,7 +1122,7 @@ def test_disassociate_ip_address_services_enabled(self): return - @attr(tags=["advanced"]) + @attr(tags=["advanced", "selfservice"]) def test_disassociate_ip_address_other_account(self): """ Test disassociating portable IP with non-owner account """ @@ -1144,7 +1148,7 @@ def test_disassociate_ip_address_other_account(self): domainid=self.domain.id ) - self.api_client_user = self.testClient.createUserApiClient( + self.api_client_user = self.testClient.getUserApiClient( UserName=self.user_account.name, DomainName=self.user_account.domain ) @@ -1168,14 +1172,16 @@ class TestDeleteAccount(cloudstackTestCase): @classmethod def setUpClass(cls): - cls.api_client = super(TestDeleteAccount, cls).getClsTestClient().getApiClient() + cls.testClient = super(TestDeleteAccount, cls).getClsTestClient() + cls.api_client = cls.testClient.getApiClient() + cls.services = Services().services # Get Zone, Domain and templates - cls.region = get_region(cls.api_client, cls.services) - cls.domain = get_domain(cls.api_client, cls.services) - cls.zone = get_zone(cls.api_client, cls.services) + cls.region = get_region(cls.api_client) + cls.domain = get_domain(cls.api_client) + cls.zone = get_zone(cls.api_client, cls.testClient.getZoneForTests()) cls.services['mode'] = cls.zone.networktype - cls.pod = get_pod(cls.api_client, cls.zone.id, cls.services) + cls.pod = get_pod(cls.api_client, cls.zone.id) cls.services['mode'] = cls.zone.networktype cls.services["domainid"] = cls.domain.id cls.services["zoneid"] = cls.zone.id @@ -1213,7 +1219,7 @@ def setUp(self): ) self.cleanup = [] - portable_ip_range_services = get_portable_ip_range_services(self.config) + portable_ip_range_services = self.services["portableIpRange"] if portable_ip_range_services is None: self.skipTest('Failed to read config values related to portable ip range') @@ -1275,7 +1281,7 @@ def tearDown(self): raise Exception("Warning: Exception during cleanup : %s" % e) return - @attr(tags=["advanced"]) + @attr(tags=["advanced", "selfservice"]) def test_delete_account_services_disabled(self): """ test delete account with portable ip with no services enabled """ @@ -1305,7 +1311,7 @@ def test_delete_account_services_disabled(self): return - @attr(tags=["advanced"]) + @attr(tags=["advanced", "selfservice"]) def test_delete_account_services_enabled(self): """ test delete account with portable ip with PF and firewall services enabled """ @@ -1393,13 +1399,15 @@ class TestPortableIpTransferAcrossNetworks(cloudstackTestCase): @classmethod def setUpClass(cls): - cls.api_client = super(TestPortableIpTransferAcrossNetworks, cls).getClsTestClient().getApiClient() + cls.testClient = super(TestPortableIpTransferAcrossNetworks, cls).getClsTestClient() + cls.api_client = cls.testClient.getApiClient() + cls.services = Services().services # Get Zone, Domain and templates - cls.region = get_region(cls.api_client, cls.services) - cls.domain = get_domain(cls.api_client, cls.services) - cls.zone = get_zone(cls.api_client, cls.services) - cls.pod = get_pod(cls.api_client, cls.zone.id, cls.services) + cls.region = get_region(cls.api_client) + cls.domain = get_domain(cls.api_client) + cls.zone = get_zone(cls.api_client, cls.testClient.getZoneForTests()) + cls.pod = get_pod(cls.api_client, cls.zone.id) cls.services['mode'] = cls.zone.networktype cls.services["domainid"] = cls.domain.id cls.services["zoneid"] = cls.zone.id @@ -1488,7 +1496,7 @@ def setUp(self): self.dbclient = self.testClient.getDbConnection() #create new portable ip range - self.portable_ip_range_services = get_portable_ip_range_services(self.config) + self.portable_ip_range_services = self.services["portableIpRange"] if self.portable_ip_range_services is None: self.skipTest('Failed to read config values related to portable ip range') @@ -1519,7 +1527,7 @@ def tearDown(self): raise Exception("Warning: Exception during cleanup : %s" % e) return - @attr(tags=["advanced","swamy"]) + @attr(tags=["advanced","swamy", "selfservice"]) def test_list_portable_ip_range_non_root_admin(self): """Test list portable ip ranges with non admin root account """ diff --git a/test/integration/component/test_project_configs.py b/test/integration/component/test_project_configs.py index be6cf1ce27..4b777fecec 100644 --- a/test/integration/component/test_project_configs.py +++ b/test/integration/component/test_project_configs.py @@ -21,9 +21,9 @@ 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.lib.utils import * +from marvin.lib.base import * +from marvin.lib.common import * from marvin.sshClient import SshClient import datetime @@ -109,13 +109,11 @@ class TestUserProjectCreation(cloudstackTestCase): @classmethod def setUpClass(cls): - cls.api_client = super( - TestUserProjectCreation, - cls - ).getClsTestClient().getApiClient() + cls.testClient = super(TestUserProjectCreation, cls).getClsTestClient() + cls.api_client = cls.testClient.getApiClient() + cls.services = Services().services - # Get Zone - cls.zone = get_zone(cls.api_client, cls.services) + cls.zone = get_zone(cls.api_client, cls.testClient.getZoneForTests()) cls.services['mode'] = cls.zone.networktype configs = Configurations.list( @@ -175,7 +173,7 @@ def tearDown(self): return @attr(configuration = "allow.user.create.projects") - @attr(tags = ["advanced", "basic", "sg", "eip", "advancedns", "simulator"]) + @attr(tags=["advanced", "basic", "sg", "eip", "advancedns", "simulator", "selfservice"]) def test_admin_project_creation(self): """Test create project as a domain admin and domain user """ @@ -275,13 +273,11 @@ class TestProjectCreationNegative(cloudstackTestCase): @classmethod def setUpClass(cls): - cls.api_client = super( - TestProjectCreationNegative, - cls - ).getClsTestClient().getApiClient() + cls.testClient = super(TestProjectCreationNegative, cls).getClsTestClient() + cls.api_client = cls.testClient.getApiClient() + cls.services = Services().services - # Get Zone - cls.zone = get_zone(cls.api_client, cls.services) + cls.zone = get_zone(cls.api_client, cls.testClient.getZoneForTests()) cls.services['mode'] = cls.zone.networktype # Checking for prereqisits - global configs @@ -420,17 +416,15 @@ class TestProjectInviteRequired(cloudstackTestCase): @classmethod def setUpClass(cls): - cls.api_client = super( - TestProjectInviteRequired, - cls - ).getClsTestClient().getApiClient() + cls.testClient = super(TestProjectInviteRequired, cls).getClsTestClient() + cls.api_client = cls.testClient.getApiClient() + cls.services = Services().services - # Get Zone - cls.zone = get_zone(cls.api_client, cls.services) + cls.zone = get_zone(cls.api_client, cls.testClient.getZoneForTests()) cls.services['mode'] = cls.zone.networktype # Create domains, account etc. - cls.domain = get_domain(cls.api_client, cls.services) + cls.domain = get_domain(cls.api_client) # Verify 'project.invite.required' is set to false configs = Configurations.list( @@ -483,7 +477,7 @@ def tearDown(self): raise Exception("Warning: Exception during cleanup : %s" % e) return - @attr(tags = ["advanced", "basic", "sg", "eip", "advancedns", "simulator"]) + @attr(tags=["advanced", "basic", "sg", "eip", "advancedns", "selfservice"]) def test_add_user_to_project(self): """Add user to project when 'project.invite.required' is false""" @@ -572,17 +566,15 @@ class TestProjectInviteRequiredTrue(cloudstackTestCase): @classmethod def setUpClass(cls): - cls.api_client = super( - TestProjectInviteRequiredTrue, - cls - ).getClsTestClient().getApiClient() + cls.testClient = super(TestProjectInviteRequiredTrue, cls).getClsTestClient() + cls.api_client = cls.testClient.getApiClient() + cls.services = Services().services - # Get Zone - cls.zone = get_zone(cls.api_client, cls.services) + cls.zone = get_zone(cls.api_client, cls.testClient.getZoneForTests()) cls.services['mode'] = cls.zone.networktype # Create domains, account etc. - cls.domain = get_domain(cls.api_client, cls.services) + cls.domain = get_domain(cls.api_client) # Verify 'project.invite.required' is set to true configs = Configurations.list( @@ -636,7 +628,7 @@ def tearDown(self): return @attr(configuration = "project.invite.required") - @attr(tags = ["advanced", "basic", "sg", "eip", "advancedns"]) + @attr(tags=["advanced", "basic", "sg", "eip", "advancedns", "selfservice"]) def test_add_user_to_project(self): """Add user to project when 'project.invite.required' is true""" @@ -725,17 +717,15 @@ class TestProjectInviteTimeout(cloudstackTestCase): @classmethod def setUpClass(cls): - cls.api_client = super( - TestProjectInviteTimeout, - cls - ).getClsTestClient().getApiClient() + cls.testClient = super(TestProjectInviteTimeout, cls).getClsTestClient() + cls.api_client = cls.testClient.getApiClient() + cls.services = Services().services - # Get Zone - cls.zone = get_zone(cls.api_client, cls.services) + cls.zone = get_zone(cls.api_client, cls.testClient.getZoneForTests()) cls.services['mode'] = cls.zone.networktype # Create domains, account etc. - cls.domain = get_domain(cls.api_client, cls.services) + cls.domain = get_domain(cls.api_client) # Verify 'project.invite.required' is set to true configs = Configurations.list( diff --git a/test/integration/component/test_project_limits.py b/test/integration/component/test_project_limits.py index 7cb29b7d27..7941313182 100644 --- a/test/integration/component/test_project_limits.py +++ b/test/integration/component/test_project_limits.py @@ -21,9 +21,9 @@ 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.lib.utils import * +from marvin.lib.base import * +from marvin.lib.common import * from marvin.codes import PASS import datetime @@ -124,13 +124,11 @@ class TestProjectLimits(cloudstackTestCase): @classmethod def setUpClass(cls): - cls.api_client = super( - TestProjectLimits, - cls - ).getClsTestClient().getApiClient() + cls.testClient = super(TestProjectLimits, cls).getClsTestClient() + cls.api_client = cls.testClient.getApiClient() + cls.services = Services().services - # Get Zone - cls.zone = get_zone(cls.api_client, cls.services) + cls.zone = get_zone(cls.api_client, cls.testClient.getZoneForTests()) cls.services['mode'] = cls.zone.networktype # Create domains, account etc. @@ -185,7 +183,7 @@ def tearDown(self): raise Exception("Warning: Exception during cleanup : %s" % e) return - @attr(tags=["advanced", "basic", "sg", "eip", "advancedns", "simulator"]) + @attr(tags=["advanced", "basic", "sg", "eip", "advancedns", "simulator", "selfservice"]) def test_01_project_limits(self): """ Test project limits for domain admin """ @@ -352,7 +350,7 @@ def test_01_project_limits(self): return - @attr(tags=["advanced", "basic", "sg", "eip", "advancedns", "simulator"]) + @attr(tags=["advanced", "basic", "sg", "eip", "advancedns", "simulator", "selfservice"]) def test_02_project_limits_normal_user(self): """ Test project limits for normal user """ @@ -502,10 +500,11 @@ class TestResourceLimitsProject(cloudstackTestCase): @classmethod def setUpClass(cls): - cls.api_client = super(TestResourceLimitsProject, cls).getClsTestClient().getApiClient() + cls.testClient = super(TestResourceLimitsProject, cls).getClsTestClient() + cls.api_client = cls.testClient.getApiClient() + cls.services = Services().services - # Get Zone, Domain and templates - cls.zone = get_zone(cls.api_client, cls.services) + cls.zone = get_zone(cls.api_client, cls.testClient.getZoneForTests()) cls.services['mode'] = cls.zone.networktype cls.template = get_template( @@ -576,7 +575,7 @@ def tearDown(self): raise Exception("Warning: Exception during cleanup : %s" % e) return - @attr(tags=["advanced", "basic", "sg", "eip", "advancedns", "simulator"]) + @attr(tags=["advanced", "basic", "sg", "eip", "advancedns", "simulator", "selfservice"]) def test_03_vm_per_project(self): """Test VM limit per project """ @@ -638,7 +637,7 @@ def test_03_vm_per_project(self): ) return - @attr(tags=["advanced", "eip", "advancedns", "simulator"]) + @attr(tags=["advanced", "eip", "advancedns", "simulator", "selfservice"]) def test_04_publicip_per_project(self): """Test Public IP limit per project """ @@ -723,7 +722,7 @@ def test_04_publicip_per_project(self): ) return - @attr(tags=["advanced", "basic", "sg", "eip", "advancedns", "simulator"]) + @attr(tags=["advanced", "basic", "sg", "eip", "advancedns", "simulator", "selfservice"]) def test_05_snapshots_per_project(self): """Test Snapshot limit per project """ @@ -799,7 +798,7 @@ def test_05_snapshots_per_project(self): ) return - @attr(tags=["advanced", "basic", "sg", "eip", "advancedns", "simulator"]) + @attr(tags=["advanced", "basic", "sg", "eip", "advancedns", "simulator", "selfservice"]) def test_06_volumes_per_project(self): """Test Volumes limit per project """ @@ -855,7 +854,7 @@ def test_06_volumes_per_project(self): ) return - @attr(tags=["advanced", "basic", "sg", "eip", "advancedns"]) + @attr(tags=["advanced", "basic", "sg", "eip", "advancedns", "selfservice"]) def test_07_templates_per_project(self): """Test Templates limit per project """ @@ -945,14 +944,12 @@ class TestMaxProjectNetworks(cloudstackTestCase): @classmethod def setUpClass(cls): - cls.api_client = super( - TestMaxProjectNetworks, - cls - ).getClsTestClient().getApiClient() + cls.testClient = super(TestMaxProjectNetworks, cls).getClsTestClient() + cls.api_client = cls.testClient.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) + cls.zone = get_zone(cls.api_client, cls.testClient.getZoneForTests()) + cls.domain = get_domain(cls.api_client) cls.services['mode'] = cls.zone.networktype cls.template = get_template( cls.api_client, diff --git a/test/integration/component/test_project_resources.py b/test/integration/component/test_project_resources.py index d6a732d549..4f61cb0cab 100644 --- a/test/integration/component/test_project_resources.py +++ b/test/integration/component/test_project_resources.py @@ -5,9 +5,9 @@ # 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 @@ -18,8 +18,8 @@ """ #Import Local Modules from nose.plugins.attrib import attr -from marvin.cloudstackTestCase import cloudstackTestCase, unittest -from marvin.integration.lib.base import (VirtualMachine, +from marvin.cloudstackTestCase import cloudstackTestCase +from marvin.lib.base import (VirtualMachine, Account, Project, NATRule, @@ -35,7 +35,7 @@ DiskOffering, LoadBalancerRule) -from marvin.integration.lib.common import (get_zone, +from marvin.lib.common import (get_zone, get_template, get_domain, list_volumes, @@ -44,7 +44,7 @@ get_free_vlan, wait_for_cleanup) -from marvin.integration.lib.utils import cleanup_resources +from marvin.lib.utils import cleanup_resources import random @@ -161,13 +161,11 @@ class TestOfferings(cloudstackTestCase): @classmethod def setUpClass(cls): - cls.api_client = super( - TestOfferings, - cls - ).getClsTestClient().getApiClient() + cls.testClient = super(TestOfferings, cls).getClsTestClient() + cls.api_client = cls.testClient.getApiClient() + cls.services = Services().services - # Get Zone and template - cls.zone = get_zone(cls.api_client, cls.services) + cls.zone = get_zone(cls.api_client, cls.testClient.getZoneForTests()) cls.services['mode'] = cls.zone.networktype cls.template = get_template( cls.api_client, @@ -227,7 +225,7 @@ def tearDown(self): raise Exception("Warning: Exception during cleanup : %s" % e) return - @attr(tags = ["advanced", "basic", "sg", "eip", "advancedns", "simulator"]) + @attr(tags=["advanced", "basic", "sg", "eip", "advancedns", "simulator", "selfservice"]) def test_01_service_offerings(self): """ Test service offerings in a project """ @@ -269,7 +267,7 @@ def test_01_service_offerings(self): return - @attr(tags = ["advanced", "basic", "sg", "eip", "advancedns", "simulator"]) + @attr(tags=["advanced", "basic", "sg", "eip", "advancedns", "simulator", "selfservice"]) def test_02_project_disk_offerings(self): """ Test project disk offerings """ @@ -342,13 +340,11 @@ class TestNetwork(cloudstackTestCase): @classmethod def setUpClass(cls): - cls.api_client = super( - TestNetwork, - cls - ).getClsTestClient().getApiClient() + cls.testClient = super(TestNetwork, cls).getClsTestClient() + cls.api_client = cls.testClient.getApiClient() + cls.services = Services().services - # Get Zone and template - cls.zone = get_zone(cls.api_client, cls.services) + cls.zone = get_zone(cls.api_client, cls.testClient.getZoneForTests()) cls.services['mode'] = cls.zone.networktype cls.template = get_template( cls.api_client, @@ -403,7 +399,7 @@ def tearDown(self): raise Exception("Warning: Exception during cleanup : %s" % e) return - @attr(tags = ["advanced", "advancedns", "simulator"]) + @attr(tags=["advanced", "advancedns", "simulator", "selfservice"]) def test_03_network_create(self): """ Test create network in project """ @@ -462,7 +458,6 @@ def test_03_network_create(self): True, "Check for the valid network list response" ) - network_response = networks[0] self.debug("Deploying VM with network: %s" % network.id) @@ -550,13 +545,11 @@ class TestTemplates(cloudstackTestCase): @classmethod def setUpClass(cls): - cls.api_client = super( - TestTemplates, - cls - ).getClsTestClient().getApiClient() + cls.testClient = super(TestTemplates, cls).getClsTestClient() + cls.api_client = cls.testClient.getApiClient() + cls.services = Services().services - # Get Zone, Domain and templates - cls.zone = get_zone(cls.api_client, cls.services) + cls.zone = get_zone(cls.api_client, cls.testClient.getZoneForTests()) cls.services['mode'] = cls.zone.networktype cls.template = get_template( @@ -628,7 +621,7 @@ def tearDown(self): raise Exception("Warning: Exception during cleanup : %s" % e) return - @attr(tags = ["advanced", "basic", "sg", "eip", "advancedns"]) + @attr(tags=["advanced", "basic", "sg", "eip", "advancedns", "selfservice"]) def test_04_public_template_use_in_project(self): """Test Templates creation in projects """ @@ -637,56 +630,59 @@ def test_04_public_template_use_in_project(self): # 3. Verify that template created in project can be used in project # without any restrictions - self.debug("Deploying VM for with public template: %s" % + try: + self.debug("Deploying VM for with public template: %s" % self.template.id) - virtual_machine_1 = VirtualMachine.create( + virtual_machine_1 = VirtualMachine.create( self.apiclient, self.services["server"], templateid=self.template.id, serviceofferingid=self.service_offering.id, projectid=self.project.id ) - self.cleanup.append(virtual_machine_1) - # Verify VM state - self.assertEqual( + self.cleanup.append(virtual_machine_1) + # Verify VM state + self.assertEqual( virtual_machine_1.state, 'Running', "Check VM state is Running or not" ) - virtual_machine_1.stop(self.apiclient) - # Get the Root disk of VM - volumes = list_volumes( + virtual_machine_1.stop(self.apiclient) + # Get the Root disk of VM + volumes = list_volumes( self.apiclient, projectid=self.project.id, type='ROOT', listall=True ) - self.assertEqual( + self.assertEqual( isinstance(volumes, list), True, "Check for list volume response return valid data" ) - volume = volumes[0] + volume = volumes[0] - self.debug("Creating template from volume: %s" % volume.id) - # Create a template from the ROOTDISK - template_1 = Template.create( + self.debug("Creating template from volume: %s" % volume.id) + # Create a template from the ROOTDISK + template_1 = Template.create( self.apiclient, self.services["template"], volumeid=volume.id, projectid=self.project.id ) - self.cleanup.append(template_1) - # Verify Template state - self.assertEqual( + self.cleanup.append(template_1) + # Verify Template state + self.assertEqual( template_1.isready, True, "Check Template is in ready state or not" ) + except Exception as e: + self.fail("Exception occured: %s" % e) return - @attr(tags = ["advanced", "basic", "sg", "eip", "advancedns"]) + @attr(tags=["advanced", "basic", "sg", "eip", "advancedns", "selfservice"]) def test_05_use_private_template_in_project(self): """Test use of private template in a project """ @@ -696,83 +692,83 @@ def test_05_use_private_template_in_project(self): # be granted to the Project (use API 'updateTemplatePermissions' # with project id to achieve that). - self.debug("Deploying VM for with public template: %s" % + try: + self.debug("Deploying VM for with public template: %s" % self.template.id) - virtual_machine_1 = VirtualMachine.create( + virtual_machine_1 = VirtualMachine.create( self.apiclient, self.services["server"], templateid=self.template.id, serviceofferingid=self.service_offering.id, projectid=self.project.id ) - self.cleanup.append(virtual_machine_1) - # Verify VM state - self.assertEqual( - virtual_machine_1.state, - 'Running', - "Check VM state is Running or not" - ) - self.debug("Stopping the VM: %s" % virtual_machine_1.id) - virtual_machine_1.stop(self.apiclient) - # Get the Root disk of VM - volumes = list_volumes( + self.cleanup.append(virtual_machine_1) + # Verify VM state + self.assertEqual(virtual_machine_1.state, + 'Running', + "Check VM state is Running or not") + virtual_machine_1.stop(self.apiclient) + # Get the Root disk of VM + volumes = list_volumes( self.apiclient, projectid=self.project.id, type='ROOT', listall=True ) - self.assertEqual( + self.assertEqual( isinstance(volumes, list), True, "Check for list volume response return valid data" ) - volume = volumes[0] + volume = volumes[0] - self.debug("Creating template from volume: %s" % volume.id) - # Create a template from the ROOTDISK - template_1 = Template.create( + self.debug("Creating template from volume: %s" % volume.id) + # Create a template from the ROOTDISK + template_1 = Template.create( self.apiclient, self.services["template"], volumeid=volume.id, projectid=self.project.id ) - self.cleanup.append(template_1) - # Verify Template state - self.assertEqual( + self.cleanup.append(template_1) + # Verify Template state + self.assertEqual( template_1.isready, True, "Check Template is in ready state or not" ) - # Update template permissions to grant permission to project - self.debug( - "Updating template permissions:%s to grant access to project: %s" % ( + # Update template permissions to grant permission to project + self.debug( + "Updating template permissions:%s to grant access to project: %s" % ( template_1.id, self.project.id )) - template_1.updatePermissions( + template_1.updatePermissions( self.apiclient, op='add', projectids=self.project.id ) - self.debug("Deploying VM for with privileged template: %s" % + self.debug("Deploying VM for with privileged template: %s" % self.template.id) - virtual_machine_2 = VirtualMachine.create( + virtual_machine_2 = VirtualMachine.create( self.apiclient, self.services["server"], templateid=template_1.id, serviceofferingid=self.service_offering.id, projectid=self.project.id ) - self.cleanup.append(virtual_machine_2) - # Verify VM state - self.assertEqual( + self.cleanup.append(virtual_machine_2) + # Verify VM state + self.assertEqual( virtual_machine_2.state, 'Running', "Check VM state is Running or not" ) + except Exception as e: + self.fail("Exception occured: %s" % e) return @@ -780,13 +776,11 @@ class TestSnapshots(cloudstackTestCase): @classmethod def setUpClass(cls): - cls.api_client = super( - TestSnapshots, - cls - ).getClsTestClient().getApiClient() + cls.testClient = super(TestSnapshots, cls).getClsTestClient() + cls.api_client = cls.testClient.getApiClient() + cls.services = Services().services - # Get Zone, Domain and templates - cls.zone = get_zone(cls.api_client, cls.services) + cls.zone = get_zone(cls.api_client, cls.testClient.getZoneForTests()) cls.services['mode'] = cls.zone.networktype cls.template = get_template( @@ -852,7 +846,7 @@ def tearDown(self): return @attr(speed = "slow") - @attr(tags = ["advanced", "basic", "sg", "eip", "advancedns", "simulator"]) + @attr(tags=["advanced", "basic", "sg", "eip", "advancedns", "simulator", "selfservice"]) def test_06_create_snapshots_in_project(self): """Test create snapshots in project """ @@ -890,7 +884,6 @@ def test_06_create_snapshots_in_project(self): True, "Check for list volume response return valid data" ) - volume = volumes[0] self.debug("Creating snapshot from volume: %s" % volumes[0].id) # Create a snapshot from the ROOTDISK @@ -928,13 +921,11 @@ class TestPublicIpAddress(cloudstackTestCase): @classmethod def setUpClass(cls): - cls.api_client = super( - TestPublicIpAddress, - cls - ).getClsTestClient().getApiClient() + cls.testClient = super(TestPublicIpAddress, cls).getClsTestClient() + cls.api_client = cls.testClient.getApiClient() + cls.services = Services().services - # Get Zone, Domain and templates - cls.zone = get_zone(cls.api_client, cls.services) + cls.zone = get_zone(cls.api_client, cls.testClient.getZoneForTests()) cls.services['mode'] = cls.zone.networktype cls.template = get_template( @@ -1008,7 +999,7 @@ def tearDown(self): raise Exception("Warning: Exception during cleanup : %s" % e) return - @attr(tags = ["advanced", "advancedns"]) + @attr(tags=["advanced", "advancedns", "selfservice"]) def test_07_associate_public_ip(self): """Test associate public IP within the project """ @@ -1213,15 +1204,12 @@ def tearDown(self): @classmethod def setUpClass(cls): + cls.testClient = super(TestSecurityGroup, cls).getClsTestClient() + cls.api_client = cls.testClient.getApiClient() + cls.services = Services().services - cls.api_client = super( - TestSecurityGroup, - cls - ).getClsTestClient().getApiClient() - - # Get Zone, Domain and templates - cls.domain = get_domain(cls.api_client, cls.services) - cls.zone = get_zone(cls.api_client, cls.services) + cls.zone = get_zone(cls.api_client, cls.testClient.getZoneForTests()) + cls.domain = get_domain(cls.api_client) cls.services['mode'] = cls.zone.networktype template = get_template( diff --git a/test/integration/component/test_project_usage.py b/test/integration/component/test_project_usage.py index ba0a63c97e..5e0dda5aff 100644 --- a/test/integration/component/test_project_usage.py +++ b/test/integration/component/test_project_usage.py @@ -5,9 +5,9 @@ # 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 @@ -17,16 +17,29 @@ """ P1 tests for Snapshots """ #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.sshClient import SshClient -import datetime - +from marvin.cloudstackTestCase import cloudstackTestCase, unittest +from marvin.cloudstackAPI import deleteVolume +from marvin.lib.utils import (cleanup_resources) +from marvin.lib.base import (Project, + VirtualMachine, + Account, + Network, + PublicIPAddress, + NATRule, + ServiceOffering, + Vpn, + VpnUser, + Snapshot, + ImageStore, + DiskOffering, + LoadBalancerRule, + Template, + Iso) +from marvin.lib.common import (get_domain, + get_zone, + get_template, + list_volumes) class Services: """Test Snapshots Services @@ -116,14 +129,13 @@ class TestVmUsage(cloudstackTestCase): @classmethod def setUpClass(cls): - cls.api_client = super( - TestVmUsage, - cls - ).getClsTestClient().getApiClient() + cls.testClient = super(TestVmUsage, cls).getClsTestClient() + cls.api_client = cls.testClient.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) + cls.domain = get_domain(cls.api_client) + cls.zone = get_zone(cls.api_client, cls.testClient.getZoneForTests()) cls.services['mode'] = cls.zone.networktype template = get_template( @@ -192,7 +204,7 @@ def tearDown(self): raise Exception("Warning: Exception during cleanup : %s" % e) return - @attr(tags = ["advanced", "basic", "sg", "eip", "advancedns", "simulator"]) + @attr(tags=["advanced", "basic", "sg", "eip", "advancedns", "simulator", "selfservice"]) def test_01_vm_usage(self): """Test Create/Destroy VM and verify usage calculation """ @@ -205,14 +217,19 @@ def test_01_vm_usage(self): # VM.Destroy and volume .delete Event for the created account # 4. Delete the account - self.debug("Stopping the VM: %s" % self.virtual_machine.id) - # Stop the VM - self.virtual_machine.stop(self.apiclient) + try: + self.debug("Stopping the VM: %s" % self.virtual_machine.id) + # Stop the VM + self.virtual_machine.stop(self.apiclient) + except Exception as e: + self.fail("Failed to stop VM: %s" % e) - time.sleep(self.services["sleep"]) - # Destroy the VM - self.debug("Destroying the VM: %s" % self.virtual_machine.id) - self.virtual_machine.delete(self.apiclient) + try: + # Destroy the VM + self.debug("Destroying the VM: %s" % self.virtual_machine.id) + self.virtual_machine.delete(self.apiclient) + except Exception as e: + self.fail("Failed to delete VM: %s" % e) # Fetch project account ID from project UUID self.debug( @@ -311,14 +328,13 @@ class TestPublicIPUsage(cloudstackTestCase): @classmethod def setUpClass(cls): - cls.api_client = super( - TestPublicIPUsage, - cls - ).getClsTestClient().getApiClient() + cls.testClient = super(TestPublicIPUsage, cls).getClsTestClient() + cls.api_client = cls.testClient.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) + cls.domain = get_domain(cls.api_client) + cls.zone = get_zone(cls.api_client, cls.testClient.getZoneForTests()) cls.services['mode'] = cls.zone.networktype cls.template = get_template( @@ -404,7 +420,7 @@ def tearDown(self): raise Exception("Warning: Exception during cleanup : %s" % e) return - @attr(tags = ["advanced", "eip", "advancedns", "simulator"]) + @attr(tags=["advanced", "eip", "advancedns", "simulator", "selfservice"]) def test_01_public_ip_usage(self): """Test Assign new IP and verify usage calculation """ @@ -483,14 +499,13 @@ class TestVolumeUsage(cloudstackTestCase): @classmethod def setUpClass(cls): - cls.api_client = super( - TestVolumeUsage, - cls - ).getClsTestClient().getApiClient() + cls.testClient = super(TestVolumeUsage, cls).getClsTestClient() + cls.api_client = cls.testClient.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) + cls.domain = get_domain(cls.api_client) + cls.zone = get_zone(cls.api_client, cls.testClient.getZoneForTests()) cls.services['mode'] = cls.zone.networktype cls.disk_offering = DiskOffering.create( cls.api_client, @@ -563,7 +578,7 @@ def tearDown(self): raise Exception("Warning: Exception during cleanup : %s" % e) return - @attr(tags = ["advanced", "basic", "sg", "eip", "advancedns", "simulator"]) + @attr(tags=["advanced", "basic", "sg", "eip", "advancedns", "simulator", "selfservice"]) def test_01_volume_usage(self): """Test Create/delete a volume and verify correct usage is recorded """ @@ -577,7 +592,10 @@ def test_01_volume_usage(self): # Stop VM self.debug("Stopping VM with ID: %s" % self.virtual_machine.id) - self.virtual_machine.stop(self.apiclient) + try: + self.virtual_machine.stop(self.apiclient) + except Exception as e: + self.fail("Failed to stop VM: %s" % e) volume_response = list_volumes( self.apiclient, @@ -597,7 +615,10 @@ def test_01_volume_usage(self): data_volume.id, self.virtual_machine.id )) - self.virtual_machine.detach_volume(self.apiclient, data_volume) + try: + self.virtual_machine.detach_volume(self.apiclient, data_volume) + except Exception as e: + self.fail("Failed to detach volume: %s" % e) # Delete Data disk self.debug("Delete volume ID: %s" % data_volume.id) @@ -668,14 +689,13 @@ class TestTemplateUsage(cloudstackTestCase): @classmethod def setUpClass(cls): - cls.api_client = super( - TestTemplateUsage, - cls - ).getClsTestClient().getApiClient() + cls.testClient = super(TestTemplateUsage, cls).getClsTestClient() + cls.api_client = cls.testClient.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) + cls.domain = get_domain(cls.api_client) + cls.zone = get_zone(cls.api_client, cls.testClient.getZoneForTests()) cls.services['mode'] = cls.zone.networktype cls.services["server"]["zoneid"] = cls.zone.id template = get_template( @@ -684,26 +704,28 @@ def setUpClass(cls): cls.services["ostype"] ) cls.services["server"]["zoneid"] = cls.zone.id - cls.account = Account.create( + cls._cleanup = [] + try: + cls.account = Account.create( cls.api_client, cls.services["account"], domainid=cls.domain.id ) - cls.services["account"] = cls.account.name + cls._cleanup.append(cls.account) + cls.services["account"] = cls.account.name - cls.project = Project.create( + cls.project = Project.create( cls.api_client, cls.services["project"], account=cls.account.name, domainid=cls.account.domainid ) - - cls.service_offering = ServiceOffering.create( + cls._cleanup.append(cls.account) + cls.service_offering = ServiceOffering.create( cls.api_client, - cls.services["service_offering"] - ) - #create virtual machine - cls.virtual_machine = VirtualMachine.create( + cls.services["service_offering"]) + #create virtual machine + cls.virtual_machine = VirtualMachine.create( cls.api_client, cls.services["server"], templateid=template.id, @@ -711,25 +733,22 @@ def setUpClass(cls): projectid=cls.project.id ) - #Stop virtual machine - cls.virtual_machine.stop(cls.api_client) + #Stop virtual machine + cls.virtual_machine.stop(cls.api_client) - #Wait before server has be successfully stopped - time.sleep(30) - list_volume = list_volumes( + list_volume = list_volumes( cls.api_client, projectid=cls.project.id, type='ROOT', listall=True ) - if isinstance(list_volume, list): - cls.volume = list_volume[0] - else: - raise Exception("List Volumes failed!") - cls._cleanup = [ - cls.project, - cls.account, - ] + if isinstance(list_volume, list): + cls.volume = list_volume[0] + else: + raise Exception("List Volumes failed!") + except Exception as e: + cls.tearDownClass() + raise unittest.SkipTest("Failed during setUpClass: %s" % e) return @classmethod @@ -755,7 +774,7 @@ def tearDown(self): raise Exception("Warning: Exception during cleanup : %s" % e) return - @attr(tags = ["advanced", "basic", "sg", "eip", "advancedns"]) + @attr(tags=["advanced", "basic", "sg", "eip", "advancedns", "selfservice"]) def test_01_template_usage(self): """Test Upload/ delete a template and verify correct usage is generated for the template uploaded @@ -844,11 +863,13 @@ class TestISOUsage(cloudstackTestCase): @classmethod def setUpClass(cls): - cls.api_client = super(TestISOUsage, cls).getClsTestClient().getApiClient() + cls.testClient = super(TestISOUsage, cls).getClsTestClient() + cls.api_client = cls.testClient.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) + cls.domain = get_domain(cls.api_client) + cls.zone = get_zone(cls.api_client, cls.testClient.getZoneForTests()) cls.services['mode'] = cls.zone.networktype cls.services["server"]["zoneid"] = cls.zone.id cls.services["iso"]["zoneid"] = cls.zone.id @@ -908,7 +929,7 @@ def tearDown(self): raise Exception("Warning: Exception during cleanup : %s" % e) return - @attr(tags = ["advanced", "basic", "sg", "eip", "advancedns"]) + @attr(tags=["advanced", "basic", "sg", "eip", "advancedns", "selfservice"]) def test_01_ISO_usage(self): """Test Create/Delete a ISO and verify its usage is generated correctly """ @@ -990,14 +1011,13 @@ class TestLBRuleUsage(cloudstackTestCase): @classmethod def setUpClass(cls): - cls.api_client = super( - TestLBRuleUsage, - cls - ).getClsTestClient().getApiClient() + cls.testClient = super(TestLBRuleUsage, cls).getClsTestClient() + cls.api_client = cls.testClient.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) + cls.domain = get_domain(cls.api_client) + cls.zone = get_zone(cls.api_client, cls.testClient.getZoneForTests()) cls.services['mode'] = cls.zone.networktype template = get_template( cls.api_client, @@ -1082,7 +1102,7 @@ def tearDown(self): raise Exception("Warning: Exception during cleanup : %s" % e) return - @attr(tags = ["advanced", "eip", "advancedns", "simulator"]) + @attr(tags=["advanced", "eip", "advancedns", "simulator", "selfservice"]) def test_01_lb_usage(self): """Test Create/Delete a LB rule and verify correct usage is recorded """ @@ -1173,14 +1193,13 @@ class TestSnapshotUsage(cloudstackTestCase): @classmethod def setUpClass(cls): - cls.api_client = super( - TestSnapshotUsage, - cls - ).getClsTestClient().getApiClient() + cls.testClient = super(TestSnapshotUsage, cls).getClsTestClient() + cls.api_client = cls.testClient.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) + cls.domain = get_domain(cls.api_client) + cls.zone = get_zone(cls.api_client, cls.testClient.getZoneForTests()) cls.services['mode'] = cls.zone.networktype template = get_template( @@ -1250,7 +1269,7 @@ def tearDown(self): return @attr(speed = "slow") - @attr(tags = ["advanced", "basic", "sg", "eip", "advancedns", "simulator"]) + @attr(tags=["advanced", "basic", "sg", "eip", "advancedns", "simulator", "selfservice"]) def test_01_snapshot_usage(self): """Test Create/Delete a manual snap shot and verify correct usage is recorded @@ -1275,8 +1294,6 @@ def test_01_snapshot_usage(self): "Check if list volumes return a valid data" ) - volume = volumes[0] - # Create a snapshot from the ROOTDISK self.debug("Creating snapshot from volume: %s" % volumes[0].id) snapshot = Snapshot.create(self.apiclient, volumes[0].id) @@ -1351,14 +1368,13 @@ class TestNatRuleUsage(cloudstackTestCase): @classmethod def setUpClass(cls): - cls.api_client = super( - TestNatRuleUsage, - cls - ).getClsTestClient().getApiClient() + cls.testClient = super(TestNatRuleUsage, cls).getClsTestClient() + cls.api_client = cls.testClient.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) + cls.domain = get_domain(cls.api_client) + cls.zone = get_zone(cls.api_client, cls.testClient.getZoneForTests()) cls.services['mode'] = cls.zone.networktype template = get_template( cls.api_client, @@ -1443,7 +1459,7 @@ def tearDown(self): raise Exception("Warning: Exception during cleanup : %s" % e) return - @attr(tags = ["advanced", "advancedns", "simulator"]) + @attr(tags=["advanced", "advancedns", "simulator", "selfservice"]) def test_01_nat_usage(self): """Test Create/Delete a PF rule and verify correct usage is recorded """ @@ -1534,14 +1550,13 @@ class TestVpnUsage(cloudstackTestCase): @classmethod def setUpClass(cls): - cls.api_client = super( - TestVpnUsage, - cls - ).getClsTestClient().getApiClient() + cls.testClient = super(TestVpnUsage, cls).getClsTestClient() + cls.api_client = cls.testClient.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) + cls.domain = get_domain(cls.api_client) + cls.zone = get_zone(cls.api_client, cls.testClient.getZoneForTests()) cls.services['mode'] = cls.zone.networktype template = get_template( cls.api_client, @@ -1627,7 +1642,7 @@ def tearDown(self): raise Exception("Warning: Exception during cleanup : %s" % e) return - @attr(tags = ["advanced", "advancedns", "simulator"]) + @attr(tags=["advanced", "advancedns", "simulator", "selfservice"]) def test_01_vpn_usage(self): """Test Create/Delete a VPN and verify correct usage is recorded """ diff --git a/test/integration/component/test_projects.py b/test/integration/component/test_projects.py index 4b82fc2639..c593fb6d9e 100644 --- a/test/integration/component/test_projects.py +++ b/test/integration/component/test_projects.py @@ -21,9 +21,9 @@ 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.lib.utils import * +from marvin.lib.base import * +from marvin.lib.common import * from marvin.sshClient import SshClient import datetime @@ -103,21 +103,15 @@ class TestMultipleProjectCreation(cloudstackTestCase): @classmethod def setUpClass(cls): - cls.api_client = super( - TestMultipleProjectCreation, - cls - ).getClsTestClient().getApiClient() + cls.testClient = super(TestMultipleProjectCreation, cls).getClsTestClient() + cls.api_client = cls.testClient.getApiClient() + cls.services = Services().services - # Get Zone - cls.zone = get_zone(cls.api_client, cls.services) + # Get Zone, Domain and templates + cls.domain = get_domain(cls.api_client) + cls.zone = get_zone(cls.api_client, cls.testClient.getZoneForTests()) cls.services['mode'] = cls.zone.networktype - # Create domains, account etc. - cls.domain = get_domain( - cls.api_client, - cls.services - ) - configs = Configurations.list( cls.api_client, name='project.invite.required' @@ -168,7 +162,7 @@ def tearDown(self): raise Exception("Warning: Exception during cleanup : %s" % e) return - @attr(tags = ["advanced", "basic", "sg", "eip", "advancedns", "simulator"]) + @attr(tags=["advanced", "basic", "sg", "eip", "advancedns", "simulator", "selfservice"]) def test_01_create_multiple_projects_by_account(self): """ Verify an account can own multiple projects and can belong to multiple projects """ @@ -320,18 +314,14 @@ class TestCrossDomainAccountAdd(cloudstackTestCase): @classmethod def setUpClass(cls): - cls.api_client = super( - TestCrossDomainAccountAdd, - cls - ).getClsTestClient().getApiClient() + cls.testClient = super(TestCrossDomainAccountAdd, cls).getClsTestClient() + cls.api_client = cls.testClient.getApiClient() + cls.services = Services().services - # Get Zone - cls.zone = get_zone(cls.api_client, cls.services) + # Get Zone, Domain and templates + cls.domain = get_domain(cls.api_client) + cls.zone = get_zone(cls.api_client, cls.testClient.getZoneForTests()) cls.services['mode'] = cls.zone.networktype - cls.domain = get_domain( - cls.api_client, - cls.services - ) configs = Configurations.list( cls.api_client, @@ -389,7 +379,7 @@ def tearDown(self): raise Exception("Warning: Exception during cleanup : %s" % e) return - @attr(tags = ["advanced", "basic", "sg", "eip", "advancedns", "simulator"]) + @attr(tags=["advanced", "basic", "sg", "eip", "advancedns", "simulator", "selfservice"]) def test_02_cross_domain_account_add(self): """ Verify No cross domain projects """ @@ -454,18 +444,14 @@ class TestDeleteAccountWithProject(cloudstackTestCase): @classmethod def setUpClass(cls): - cls.api_client = super( - TestDeleteAccountWithProject, - cls - ).getClsTestClient().getApiClient() + cls.testClient = super(TestDeleteAccountWithProject, cls).getClsTestClient() + cls.api_client = cls.testClient.getApiClient() + cls.services = Services().services - # Get Zone - cls.zone = get_zone(cls.api_client, cls.services) + # Get Zone, Domain and templates + cls.domain = get_domain(cls.api_client) + cls.zone = get_zone(cls.api_client, cls.testClient.getZoneForTests()) cls.services['mode'] = cls.zone.networktype - cls.domain = get_domain( - cls.api_client, - cls.services - ) configs = Configurations.list( cls.api_client, @@ -510,7 +496,7 @@ def tearDown(self): raise Exception("Warning: Exception during cleanup : %s" % e) return - @attr(tags = ["advanced", "basic", "sg", "eip", "advancedns", "simulator"]) + @attr(tags=["advanced", "basic", "sg", "eip", "advancedns", "simulator", "selfservice"]) def test_03_delete_account_with_project(self): """ Test As long as the project exists, its owner can't be removed """ @@ -567,13 +553,12 @@ class TestDeleteDomainWithProject(cloudstackTestCase): @classmethod def setUpClass(cls): - cls.api_client = super( - TestDeleteDomainWithProject, - cls - ).getClsTestClient().getApiClient() + cls.testClient = super(TestDeleteDomainWithProject, cls).getClsTestClient() + cls.api_client = cls.testClient.getApiClient() + cls.services = Services().services # Get Zone - cls.zone = get_zone(cls.api_client, cls.services) + cls.zone = get_zone(cls.api_client, cls.testClient.getZoneForTests()) cls.services['mode'] = cls.zone.networktype configs = Configurations.list( @@ -624,7 +609,7 @@ def tearDown(self): raise Exception("Warning: Exception during cleanup : %s" % e) return - @attr(tags = ["advanced", "basic", "sg", "eip", "advancedns", "simulator"]) + @attr(tags=["advanced", "basic", "sg", "eip", "advancedns", "simulator", "selfservice"]) def test_04_delete_domain_with_project(self): """ Test Verify delete domain with cleanup=true should delete projects belonging to the domain @@ -708,17 +693,13 @@ class TestProjectOwners(cloudstackTestCase): @classmethod def setUpClass(cls): - cls.api_client = super( - TestProjectOwners, - cls - ).getClsTestClient().getApiClient() + cls.testClient = super(TestProjectOwners, cls).getClsTestClient() + cls.api_client = cls.testClient.getApiClient() + cls.services = Services().services # Get Zone - cls.domain = get_domain( - cls.api_client, - cls.services - ) - cls.zone = get_zone(cls.api_client, cls.services) + cls.zone = get_zone(cls.api_client, cls.testClient.getZoneForTests()) + cls.domain = get_domain(cls.api_client) cls.services['mode'] = cls.zone.networktype configs = Configurations.list( @@ -770,7 +751,7 @@ def tearDown(self): raise Exception("Warning: Exception during cleanup : %s" % e) return - @attr(tags = ["advanced", "basic", "sg", "eip", "advancedns", "simulator"]) + @attr(tags=["advanced", "basic", "sg", "eip", "advancedns", "simulator", "selfservice"]) def test_05_user_project_owner_promotion(self): """ Test Verify a project user can be later promoted to become a owner @@ -912,7 +893,7 @@ def test_05_user_project_owner_promotion(self): ) return - @attr(tags = ["advanced", "basic", "sg", "eip", "advancedns", "simulator"]) + @attr(tags=["advanced", "basic", "sg", "eip", "advancedns", "simulator", "selfservice"]) def test_06_max_one_project_owner(self): """ Test Verify there can only be one owner of a project at a time """ @@ -1136,18 +1117,14 @@ class TestProjectResources(cloudstackTestCase): @classmethod def setUpClass(cls): - cls.api_client = super( - TestProjectResources, - cls - ).getClsTestClient().getApiClient() + cls.testClient = super(TestProjectResources, cls).getClsTestClient() + cls.api_client = cls.testClient.getApiClient() + cls.services = Services().services # Get Zone - cls.zone = get_zone(cls.api_client, cls.services) + cls.zone = get_zone(cls.api_client, cls.testClient.getZoneForTests()) + cls.domain = get_domain(cls.api_client) cls.services['mode'] = cls.zone.networktype - cls.domain = get_domain( - cls.api_client, - cls.services - ) configs = Configurations.list( cls.api_client, @@ -1203,7 +1180,7 @@ def tearDown(self): raise Exception("Warning: Exception during cleanup : %s" % e) return - @attr(tags = ["advanced", "basic", "sg", "eip", "advancedns", "simulator"]) + @attr(tags=["advanced", "basic", "sg", "eip", "advancedns", "simulator", "selfservice"]) def test_07_project_resources_account_delete(self): """ Test Verify after an account is removed from the project, all its resources stay with the project. """ @@ -1317,7 +1294,7 @@ def test_07_project_resources_account_delete(self): ) return - @attr(tags = ["advanced", "basic", "sg", "eip", "advancedns", "simulator"]) + @attr(tags=["advanced", "basic", "sg", "eip", "advancedns", "simulator", "selfservice"]) def test_08_cleanup_after_project_delete(self): """ Test accounts are unassigned from project after project deletion """ @@ -1440,18 +1417,14 @@ class TestProjectSuspendActivate(cloudstackTestCase): @classmethod def setUpClass(cls): - cls.api_client = super( - TestProjectSuspendActivate, - cls - ).getClsTestClient().getApiClient() + cls.testClient = super(TestProjectSuspendActivate, cls).getClsTestClient() + cls.api_client = cls.testClient.getApiClient() + cls.services = Services().services - # Get Zone, domain, template etc - cls.zone = get_zone(cls.api_client, cls.services) + # Get Zone + cls.zone = get_zone(cls.api_client, cls.testClient.getZoneForTests()) + cls.domain = get_domain(cls.api_client) cls.services['mode'] = cls.zone.networktype - cls.domain = get_domain( - cls.api_client, - cls.services - ) cls.template = get_template( cls.api_client, cls.zone.id, @@ -1529,7 +1502,7 @@ def tearDown(self): raise Exception("Warning: Exception during cleanup : %s" % e) return - @attr(tags = ["advanced", "basic", "sg", "eip", "advancedns", "simulator"]) + @attr(tags=["advanced", "basic", "sg", "eip", "advancedns", "simulator", "selfservice"]) def test_09_project_suspend(self): """ Test Verify after an account is removed from the project, all his resources stay with the project. @@ -1666,7 +1639,7 @@ def test_09_project_suspend(self): ) return - @attr(tags = ["advanced", "basic", "sg", "eip", "advancedns", "simulator"]) + @attr(tags=["advanced", "basic", "sg", "eip", "advancedns", "simulator", "selfservice"]) def test_10_project_activation(self): """ Test project activation after suspension """ diff --git a/test/integration/component/test_recurring_snapshots.py b/test/integration/component/test_recurring_snapshots.py index 06df1708d9..2ef2bc3678 100644 --- a/test/integration/component/test_recurring_snapshots.py +++ b/test/integration/component/test_recurring_snapshots.py @@ -18,9 +18,9 @@ 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.lib.utils import * +from marvin.lib.base import * +from marvin.lib.common import * class Services: """Test Snapshots Services @@ -126,11 +126,13 @@ class TestRecurringSnapshots(cloudstackTestCase): @classmethod def setUpClass(cls): - cls.api_client = super(TestRecurringSnapshots, cls).getClsTestClient().getApiClient() + cls.testClient = super(TestRecurringSnapshots, cls).getClsTestClient() + cls.api_client = cls.testClient.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) + cls.domain = get_domain(cls.api_client) + cls.zone = get_zone(cls.api_client, cls.testClient.getZoneForTests()) cls.services['mode'] = cls.zone.networktype cls.disk_offering = DiskOffering.create( cls.api_client, @@ -216,7 +218,7 @@ def tearDown(self): return @attr(speed = "slow") - @attr(tags = ["advanced", "advancedns", "smoke"]) + @attr(tags=["advanced", "advancedns", "smoke", "selfservice"]) def test_recurring_snapshot_root_disk(self): """Test Recurring Snapshot Root Disk """ @@ -309,7 +311,7 @@ def test_recurring_snapshot_root_disk(self): return @attr(speed = "slow") - @attr(tags = ["advanced", "advancedns", "smoke"]) + @attr(tags=["advanced", "advancedns", "smoke", "selfservice"]) def test_recurring_snapshot_data_disk(self): """Test Recurring Snapshot data Disk """ @@ -402,4 +404,4 @@ def test_recurring_snapshot_data_disk(self): self.services["recurring_snapshot"]["maxsnaps"], "Check maximum number of recurring snapshots retained" ) - return \ No newline at end of file + return diff --git a/test/integration/component/test_redundant_router_cleanups.py b/test/integration/component/test_redundant_router_cleanups.py index e30c102024..444fa3a66b 100644 --- a/test/integration/component/test_redundant_router_cleanups.py +++ b/test/integration/component/test_redundant_router_cleanups.py @@ -5,9 +5,9 @@ # 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 @@ -16,13 +16,22 @@ # under the License. from nose.plugins.attrib import attr -from marvin.integration.lib.base import * -from marvin.integration.lib.utils import * -from marvin.integration.lib.common import * +from marvin.lib.base import (Account, + Network, + ServiceOffering, + NetworkOffering, + VirtualMachine, + Router, + Configurations) +from marvin.lib.utils import cleanup_resources +from marvin.lib.common import (get_domain, + get_zone, + get_template) #Import Local Modules from marvin.cloudstackTestCase import cloudstackTestCase -from marvin.cloudstackAPI import * +from marvin.cloudstackAPI import startRouter +import time class Services: """Test Services for customer defects @@ -137,14 +146,13 @@ class TestRedundantRouterNetworkCleanups(cloudstackTestCase): @classmethod def setUpClass(cls): - cls.api_client = super( - TestRedundantRouterNetworkCleanups, - cls - ).getClsTestClient().getApiClient() + cls.testClient = super(TestRedundantRouterNetworkCleanups, cls).getClsTestClient() + cls.api_client = cls.testClient.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) + cls.domain = get_domain(cls.api_client) + cls.zone = get_zone(cls.api_client, cls.testClient.getZoneForTests()) cls.template = get_template( cls.api_client, cls.zone.id, @@ -201,7 +209,7 @@ def tearDown(self): #raise Exception("Warning: Exception during cleanup : %s" % e) return - @attr(tags=["advanced", "advancedns", "ssh"]) + @attr(tags=["advanced", "advancedns", "ssh", "selfservice"]) def test_restart_ntwk_no_cleanup(self): """Test restarting RvR network without cleanup """ @@ -305,13 +313,6 @@ def test_restart_ntwk_no_cleanup(self): "Length of the list router should be 2 (Backup & master)" ) - if routers[0].redundantstate == 'MASTER': - master_router = routers[0] - backup_router = routers[1] - else: - master_router = routers[1] - backup_router = routers[0] - self.debug("restarting network with cleanup=False") try: network.restart(self.apiclient, cleanup=False) @@ -342,7 +343,7 @@ def test_restart_ntwk_no_cleanup(self): ) return - @attr(tags=["advanced", "advancedns", "ssh"]) + @attr(tags=["advanced", "advancedns", "ssh", "selfservice"]) def test_restart_ntwk_with_cleanup(self): """Test restart RvR network with cleanup """ @@ -446,13 +447,6 @@ def test_restart_ntwk_with_cleanup(self): "Length of the list router should be 2 (Backup & master)" ) - if routers[0].redundantstate == 'MASTER': - master_router = routers[0] - backup_router = routers[1] - else: - master_router = routers[1] - backup_router = routers[0] - self.debug("restarting network with cleanup=True") try: network.restart(self.apiclient, cleanup=True) @@ -483,7 +477,7 @@ def test_restart_ntwk_with_cleanup(self): ) return - @attr(tags=["advanced", "advancedns", "ssh"]) + @attr(tags=["advanced", "advancedns", "ssh", "selfservice"]) def test_network_gc(self): """Test network garbage collection with RVR """ @@ -598,12 +592,12 @@ def test_network_gc(self): self.fail("Failed to stop guest Vm: %s - %s" % (virtual_machine.name, e)) - interval = list_configurations( + interval = Configurations( self.apiclient, name='network.gc.interval' ) delay = int(interval[0].value) - interval = list_configurations( + interval = Configurations.list( self.apiclient, name='network.gc.wait' ) diff --git a/test/integration/component/test_redundant_router_services.py b/test/integration/component/test_redundant_router_services.py index 64bb6e99ac..707b673b53 100644 --- a/test/integration/component/test_redundant_router_services.py +++ b/test/integration/component/test_redundant_router_services.py @@ -17,9 +17,9 @@ from nose.plugins.attrib import attr -from marvin.integration.lib.base import * -from marvin.integration.lib.utils import * -from marvin.integration.lib.common import * +from marvin.lib.base import * +from marvin.lib.utils import * +from marvin.lib.common import * #Import Local Modules from marvin.cloudstackTestCase import cloudstackTestCase @@ -138,14 +138,13 @@ class TestEnableVPNOverRvR(cloudstackTestCase): @classmethod def setUpClass(cls): - cls.api_client = super( - TestEnableVPNOverRvR, - cls - ).getClsTestClient().getApiClient() + cls.testClient = super(TestEnableVPNOverRvR, cls).getClsTestClient() + cls.api_client = cls.testClient.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) + cls.domain = get_domain(cls.api_client) + cls.zone = get_zone(cls.api_client, cls.testClient.getZoneForTests()) cls.template = get_template( cls.api_client, cls.zone.id, @@ -201,7 +200,7 @@ def tearDown(self): raise Exception("Warning: Exception during cleanup : %s" % e) return - @attr(tags=["advanced", "advancedns", "ssh"]) + @attr(tags=["advanced", "advancedns", "ssh", "selfservice"]) def test_enableVPNOverRvR(self): """Test redundant router internals """ diff --git a/test/integration/component/test_redundant_router_upgrades.py b/test/integration/component/test_redundant_router_upgrades.py index e9303c0126..6c177effa2 100644 --- a/test/integration/component/test_redundant_router_upgrades.py +++ b/test/integration/component/test_redundant_router_upgrades.py @@ -17,9 +17,9 @@ from nose.plugins.attrib import attr -from marvin.integration.lib.base import * -from marvin.integration.lib.utils import * -from marvin.integration.lib.common import * +from marvin.lib.base import * +from marvin.lib.utils import * +from marvin.lib.common import * #Import Local Modules from marvin.cloudstackTestCase import cloudstackTestCase @@ -137,14 +137,13 @@ class TestRvRUpgradeDowngrade(cloudstackTestCase): @classmethod def setUpClass(cls): - cls.api_client = super( - TestRvRUpgradeDowngrade, - cls - ).getClsTestClient().getApiClient() + cls.testClient = super(TestRvRUpgradeDowngrade, cls).getClsTestClient() + cls.api_client = cls.testClient.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) + cls.domain = get_domain(cls.api_client) + cls.zone = get_zone(cls.api_client, cls.testClient.getZoneForTests()) cls.template = get_template( cls.api_client, cls.zone.id, @@ -200,7 +199,7 @@ def tearDown(self): raise Exception("Warning: Exception during cleanup : %s" % e) return - @attr(tags=["advanced", "advancedns", "ssh"]) + @attr(tags=["advanced", "advancedns", "ssh", "selfservice"]) def test_upgradeVR_to_redundantVR(self): """Test upgrade virtual router to redundant virtual router """ @@ -345,7 +344,7 @@ def test_upgradeVR_to_redundantVR(self): ) return - @attr(tags=["advanced", "advancedns", "ssh"]) + @attr(tags=["advanced", "advancedns", "ssh", "selfservice"]) def test_downgradeRvR_to_VR(self): """Test downgrade redundant virtual router to virtual router """ diff --git a/test/integration/component/test_region_vpc.py b/test/integration/component/test_region_vpc.py new file mode 100644 index 0000000000..e34806521d --- /dev/null +++ b/test/integration/component/test_region_vpc.py @@ -0,0 +1,523 @@ +# 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 unittest + +""" Component tests for region level VPC functionality +""" +#Import Local Modules +import marvin +from nose.plugins.attrib import attr +from marvin.cloudstackTestCase import * +from marvin.cloudstackAPI import * +from marvin.lib.utils import * +from marvin.lib.base import * +from marvin.lib.common import * +from marvin.sshClient import SshClient +import datetime + + +class Services: + """Test inter VLAN 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": 100, + "memory": 128, + }, + "network_offering": { + "name": 'VPC Network offering', + "displaytext": 'VPC Network off', + "guestiptype": 'Isolated', + "supportedservices": 'Vpn,Dhcp,Dns,SourceNat,PortForwarding,Lb,UserData,StaticNat,NetworkACL, Connectivity', + "traffictype": 'GUEST', + "availability": 'Optional', + "useVpc": 'on', + "serviceProviderList": { + "Vpn": 'VpcVirtualRouter', + "Dhcp": 'VpcVirtualRouter', + "Dns": 'VpcVirtualRouter', + "SourceNat": 'VpcVirtualRouter', + "PortForwarding": 'VpcVirtualRouter', + "Lb": 'VpcVirtualRouter', + "UserData": 'VpcVirtualRouter', + "StaticNat": 'VpcVirtualRouter', + "NetworkACL": 'VpcVirtualRouter', + "Connectivity": 'Ovs' + }, + "serviceCapabilityList": { + "Connectivity": { + "StretchedL2Subnet": "true" + }, + }, + }, + "vpc_offering": { + "name": 'VPC off', + "displaytext": 'VPC off', + "supportedservices": 'Dhcp,Dns,SourceNat,PortForwarding,Vpn,Lb,UserData,StaticNat,Connectivity', + "serviceProviderList": { + "Vpn": 'VpcVirtualRouter', + "Dhcp": 'VpcVirtualRouter', + "Dns": 'VpcVirtualRouter', + "SourceNat": 'VpcVirtualRouter', + "PortForwarding": 'VpcVirtualRouter', + "Lb": 'VpcVirtualRouter', + "UserData": 'VpcVirtualRouter', + "StaticNat": 'VpcVirtualRouter', + "Connectivity": 'Ovs' + }, + "serviceCapabilityList": { + "Connectivity": { + "RegionLevelVpc": "true" + }, + }, + }, + "vpc": { + "name": "TestVPC", + "displaytext": "TestVPC", + "cidr": '10.0.0.1/24' + }, + "network": { + "name": "Test Network", + "displaytext": "Test Network", + "netmask": '255.255.255.0' + }, + "lbrule": { + "name": "SSH", + "alg": "leastconn", + # Algorithm used for load balancing + "privateport": 22, + "publicport": 2222, + "openfirewall": False, + "startport": 2222, + "endport": 2222, + "cidrlist": '0.0.0.0/0', + "protocol": 'TCP' + }, + "natrule": { + "privateport": 22, + "publicport": 22, + "startport": 22, + "endport": 22, + "protocol": "TCP", + "cidrlist": '0.0.0.0/0', + }, + "fw_rule": { + "startport": 1, + "endport": 6000, + "cidr": '0.0.0.0/0', + # Any network (For creating FW rule) + "protocol": "TCP" + }, + "virtual_machine": { + "displayname": "Test VM", + "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 TestRegionVpcOffering(cloudstackTestCase): + + @classmethod + def setUpClass(cls): + testClient = super(TestRegionVpcOffering, cls).getClsTestClient() + cls.apiclient = testClient.getApiClient() + cls.services = testClient.getParsedTestDataConfig() + + # Get Zone, Domain and templates + cls.domain = get_domain(cls.apiclient) + cls.zone = get_zone(cls.apiclient, testClient.getZoneForTests()) + cls.services['mode'] = cls.zone.networktype + + + cls.template = get_template( + cls.apiclient, + cls.zone.id, + cls.services["ostype"] + ) + if cls.template == FAILED: + assert False, "get_template() failed to return template with description %s" % cls.services["ostype"] + + + cls.services["virtual_machine"]["zoneid"] = cls.zone.id + cls.services["virtual_machine"]["template"] = cls.template.id + + cls.service_offering = ServiceOffering.create( + cls.apiclient, + cls.services["service_offering"] + ) + cls._cleanup = [ + cls.service_offering, + ] + return + + @classmethod + def tearDownClass(cls): + try: + #Cleanup resources used + cleanup_resources(cls.apiclient, 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.account = Account.create( + self.apiclient, + self.services["account"], + admin=True, + domainid=self.domain.id + ) + self.cleanup = [] + self.cleanup.insert(0, self.account) + return + + def tearDown(self): + try: + cleanup_resources(self.apiclient, self.cleanup) + except Exception as e: + raise Exception("Warning: Exception during cleanup : %s" % e) + return + + def validate_vpc_offering(self, vpc_offering): + """Validates the VPC offering""" + + self.debug("Check if the VPC offering is created successfully?") + vpc_offs = VpcOffering.list( + self.apiclient, + id=vpc_offering.id + ) + self.assertEqual( + isinstance(vpc_offs, list), + True, + "List VPC offerings should return a valid list" + ) + self.assertEqual( + vpc_offering.name, + vpc_offs[0].name, + "Name of the VPC offering should match with listVPCOff data" + ) + self.assertEqual( + vpc_offering.name, + vpc_offs[0].name, + "Name of the VPC offering should match with listVPCOff data" + ) + self.assertEqual( + vpc_offs[0].regionlevelvpc,True, + "VPC offering is not set up for region level VPC" + ) + self.debug( + "VPC offering is created successfully - %s" % + vpc_offering.name) + return + + def validate_vpc_network(self, network): + """Validates the VPC network""" + + self.debug("Check if the VPC network is created successfully?") + vpc_networks = VPC.list( + self.apiclient, + id=network.id + ) + self.assertEqual( + isinstance(vpc_networks, list), + True, + "List VPC network should return a valid list" + ) + self.assertEqual( + network.name, + vpc_networks[0].name, + "Name of the VPC network should match with listVPC data" + ) + self.debug("VPC network created successfully - %s" % network.name) + return + + @attr(tags=["advanced", "intervlan"]) + def test_01_create_vpc_offering_with_regionlevelvpc_service_capability(self): + """ Test create VPC offering + """ + + # Steps for validation + # 1. Create VPC Offering by specifying all supported Services + # 2. VPC offering should be created successfully. + + self.debug("Creating inter VPC offering") + vpc_off = VpcOffering.create( + self.apiclient, + self.services["vpc_offering"] + ) + + self.debug("Check if the VPC offering is created successfully?") + self.cleanup.append(vpc_off) + self.validate_vpc_offering(vpc_off) + return + + @attr(tags=["advanced", "intervlan"]) + def test_02_create_vpc_from_offering_with_regionlevelvpc_service_capability(self): + """ Test create VPC offering + """ + + # Steps for validation + # 1. Create VPC Offering by specifying all supported Services + # 2. VPC offering should be created successfully. + + self.debug("Creating inter VPC offering") + vpc_off = VpcOffering.create( + self.apiclient, + self.services["vpc_offering"] + ) + vpc_off.update(self.apiclient, state='Enabled') + vpc = VPC.create( + self.apiclient, + self.services["vpc"], + vpcofferingid=vpc_off.id, + zoneid=self.zone.id, + account=self.account.name, + domainid=self.account.domainid + ) + self.assertEqual(vpc.distributedvpcrouter, True, "VPC created should have 'distributedvpcrouter' set to True") + + try: + vpc.delete(self.apiclient) + except Exception as e: + self.fail("Failed to delete VPC network - %s" % e) + return + + @attr(tags=["advanced", "intervlan"]) + def test_03_deploy_vms_in_vpc_with_regionlevelvpc(self): + """Test deploy virtual machines in VPC networks""" + + # 1. Create VPC Offering by specifying all supported Services + # (Vpn,dhcpdns,UserData, SourceNat,Static NAT and PF,LB,NetworkAcl) + # 2. Create a VPC using the above VPC offering + # 3. Create a network as part of this VPC. + # 4. Deploy few Vms. + # 5. Create a LB rule for this VM. + # 6. Create a PF rule for this VM. + # 7. Create a Static Nat rule for this VM. + # 8. Create Ingress rules on the network to open the above created + # LB PF and Static Nat rule + # 9. Create Egress Network ACL for this network to access google.com. + # 10. Enable VPN services + + self.debug("Creating a VPC offering..") + vpc_off = VpcOffering.create( + self.apiclient, + self.services["vpc_offering"] + ) + + vpc_off.update(self.apiclient, state='Enabled') + + self.debug("creating a VPC network in the account: %s" % + self.account.name) + vpc = VPC.create( + self.apiclient, + self.services["vpc"], + vpcofferingid=vpc_off.id, + zoneid=self.zone.id, + account=self.account.name, + domainid=self.account.domainid + ) + self.validate_vpc_network(vpc) + + self.network_offering = NetworkOffering.create( + self.apiclient, + self.services["network_offering"], + conservemode=False + ) + # Enable Network offering + self.network_offering.update(self.apiclient, state='Enabled') + + gateway = vpc.cidr.split('/')[0] + # Split the cidr to retrieve gateway + # for eg. cidr = 10.0.0.1/24 + # Gateway = 10.0.0.1 + + # Creating network using the network offering created + self.debug("Creating network with network offering: %s" % + self.network_offering.id) + network = Network.create( + self.apiclient, + self.services["network"], + accountid=self.account.name, + domainid=self.account.domainid, + networkofferingid=self.network_offering.id, + zoneid=self.zone.id, + gateway=gateway, + vpcid=vpc.id + ) + self.debug("Created network with ID: %s" % network.id) + # Spawn an instance in that network + virtual_machine = VirtualMachine.create( + self.apiclient, + self.services["virtual_machine"], + accountid=self.account.name, + domainid=self.account.domainid, + serviceofferingid=self.service_offering.id, + networkids=[str(network.id)] + ) + self.debug("Deployed VM in network: %s" % network.id) + + self.debug("Associating public IP for network: %s" % network.name) + public_ip = PublicIPAddress.create( + self.apiclient, + accountid=self.account.name, + zoneid=self.zone.id, + domainid=self.account.domainid, + networkid=network.id, + vpcid=vpc.id + ) + self.debug("Associated %s with network %s" % ( + public_ip.ipaddress.ipaddress, + network.id + )) + + self.debug("Creating LB rule for IP address: %s" % + public_ip.ipaddress.ipaddress) + + lb_rule = LoadBalancerRule.create( + self.apiclient, + self.services["lbrule"], + ipaddressid=public_ip.ipaddress.id, + accountid=self.account.name, + networkid=network.id, + vpcid=vpc.id, + domainid=self.account.domainid + ) + + self.debug("Associating public IP for network: %s" % vpc.name) + public_ip_2 = PublicIPAddress.create( + self.apiclient, + accountid=self.account.name, + zoneid=self.zone.id, + domainid=self.account.domainid, + networkid=network.id, + vpcid=vpc.id + ) + self.debug("Associated %s with network %s" % ( + public_ip_2.ipaddress.ipaddress, + network.id + )) + + nat_rule = NATRule.create( + self.apiclient, + virtual_machine, + self.services["natrule"], + ipaddressid=public_ip_2.ipaddress.id, + openfirewall=False, + networkid=network.id, + vpcid=vpc.id + ) + + self.debug("Adding NetwrokACl rules to make PF and LB accessible") + networkacl_1 = NetworkACL.create( + self.apiclient, + networkid=network.id, + services=self.services["natrule"], + traffictype='Ingress' + ) + + networkacl_2 = NetworkACL.create( + self.apiclient, + networkid=network.id, + services=self.services["lbrule"], + traffictype='Ingress' + ) + self.debug("Checking if we can SSH into VM?") + try: + virtual_machine.get_ssh_client( + ipaddress=public_ip_2.ipaddress.ipaddress, + ) + self.debug("SSH into VM is successfully") + except Exception as e: + self.fail("Failed to SSH into VM - %s, %s" % + (public_ip_2.ipaddress.ipaddress, e)) + + self.debug("Associating public IP for network: %s" % network.name) + public_ip_3 = PublicIPAddress.create( + self.apiclient, + accountid=self.account.name, + zoneid=self.zone.id, + domainid=self.account.domainid, + networkid=network.id, + vpcid=vpc.id + ) + self.debug("Associated %s with network %s" % ( + public_ip_3.ipaddress.ipaddress, + network.id + )) + self.debug("Enabling static NAT for IP: %s" % + public_ip_3.ipaddress.ipaddress) + try: + StaticNATRule.enable( + self.apiclient, + ipaddressid=public_ip_3.ipaddress.id, + virtualmachineid=virtual_machine.id, + networkid=network.id + ) + self.debug("Static NAT enabled for IP: %s" % + public_ip_3.ipaddress.ipaddress) + except Exception as e: + self.fail("Failed to enable static NAT on IP: %s - %s" % ( + public_ip_3.ipaddress.ipaddress, e)) + + public_ips = PublicIPAddress.list( + self.apiclient, + networkid=network.id, + listall=True, + isstaticnat=True, + account=self.account.name, + domainid=self.account.domainid + ) + self.assertEqual( + isinstance(public_ips, list), + True, + "List public Ip for network should list the Ip addr" + ) + self.assertEqual( + public_ips[0].ipaddress, + public_ip_3.ipaddress.ipaddress, + "List public Ip for network should list the Ip addr" + ) + # TODO: Remote Access VPN is not yet supported in VPC + return \ No newline at end of file diff --git a/test/integration/component/test_regions.py b/test/integration/component/test_regions.py index 252ba702b2..7b7c4a4db0 100644 --- a/test/integration/component/test_regions.py +++ b/test/integration/component/test_regions.py @@ -17,9 +17,9 @@ 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.lib.utils import * +from marvin.lib.base import * +from marvin.lib.common import * from nose.plugins.attrib import attr from random import choice @@ -41,7 +41,7 @@ class TestRegions(cloudstackTestCase): def setUpClass(cls): cls.api_client = super(TestRegions, cls).getClsTestClient().getApiClient() cls.services = Services().services - cls.domain = get_domain(cls.api_client, cls.services) + cls.domain = get_domain(cls.api_client) cls.cleanup = [] return @@ -67,14 +67,14 @@ def setUp(self): msg="Region creation failed" ) - @attr(tags=["simulator", "basic", "advanced"]) + @attr(tags=["simulator", "basic", "advanced", "selfservice"]) def test_createRegionWithExistingRegionId(self): """Test for duplicate checks on region id """ self.services["region"]["regionname"] = random_gen() #alter region name but not id self.assertRaises(Exception, Region.create, self.api_client, self.services["region"]) - @attr(tags=["simulator", "basic", "advanced"]) + @attr(tags=["simulator", "basic", "advanced", "selfservice"]) def test_createRegionWithExistingRegionName(self): """Test for duplicate checks on region name """ @@ -83,7 +83,7 @@ def test_createRegionWithExistingRegionName(self): self.services["region"]["regionendpoint"] = "http://region" + str(random_int) + ":8080/client" self.assertRaises(Exception, Region.create, self.api_client, self.services["region"]) - @attr(tags=["simulator", "basic", "advanced"]) + @attr(tags=["simulator", "basic", "advanced", "selfservice"]) def test_updateRegion(self): """ Test for update Region """ diff --git a/test/integration/component/test_regions_accounts.py b/test/integration/component/test_regions_accounts.py index 886e6209f2..a554893468 100644 --- a/test/integration/component/test_regions_accounts.py +++ b/test/integration/component/test_regions_accounts.py @@ -17,9 +17,9 @@ 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.lib.utils import * +from marvin.lib.base import * +from marvin.lib.common import * from nose.plugins.attrib import attr class Services: @@ -57,11 +57,11 @@ class TestRegionsAccounts(cloudstackTestCase): def setUpClass(cls): cls.api_client = super(TestRegionsAccounts, cls).getClsTestClient().getApiClient() cls.services = Services().services - cls.domain = get_domain(cls.api_client, cls.services) + cls.domain = get_domain(cls.api_client) cls.cleanup = [] return - @attr(tags=["simulator", "basic", "advanced"]) + @attr(tags=["simulator", "basic", "advanced", "selfservice"]) def test_createAccountWithUUID(self): """Test for creating account by passing id parameter @@ -101,7 +101,7 @@ def test_createAccountWithUUID(self): self.cleanup.append(account) return - @attr(tags=["simulator", "basic", "advanced"]) + @attr(tags=["simulator", "basic", "advanced", "selfservice"]) def test_createUserWithUUID(self): """Test for creating User by passing id parameter @@ -152,7 +152,7 @@ def test_createUserWithUUID(self): ) return - @attr(tags=["simulator", "basic", "advanced"]) + @attr(tags=["simulator", "basic", "advanced", "selfservice"]) def test_createdomainWithUUID(self): """Test for creating Domain by passing id parameter diff --git a/test/integration/component/test_reset_ssh_keypair.py b/test/integration/component/test_reset_ssh_keypair.py index ded2529381..d0ddb18aa1 100644 --- a/test/integration/component/test_reset_ssh_keypair.py +++ b/test/integration/component/test_reset_ssh_keypair.py @@ -19,18 +19,17 @@ """ #Import Local Modules -from marvin.integration.lib.base import (VirtualMachine, +from marvin.lib.base import (VirtualMachine, SSHKeyPair, Account, Template, ServiceOffering, - EgressFireWallRule) -from marvin.integration.lib.common import (get_domain, + EgressFireWallRule, + Volume) +from marvin.lib.common import (get_domain, get_zone, - get_template, - list_virtual_machines, - list_volumes) -from marvin.integration.lib.utils import (cleanup_resources, + get_template) +from marvin.lib.utils import (cleanup_resources, random_gen, validateList) from marvin.cloudstackTestCase import cloudstackTestCase, unittest @@ -114,14 +113,13 @@ class TestResetSSHKeypair(cloudstackTestCase): @classmethod def setUpClass(cls): - cls.api_client = super( - TestResetSSHKeypair, - cls).getClsTestClient().getApiClient() + cls.testClient = super(TestResetSSHKeypair, cls).getClsTestClient() + cls.api_client = cls.testClient.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) + domain = get_domain(cls.api_client) + cls.zone = get_zone(cls.api_client, cls.testClient.getZoneForTests()) cls.services['mode'] = cls.zone.networktype # Set Zones and disk offerings @@ -137,118 +135,93 @@ def setUpClass(cls): cls.services["virtual_machine"]["zoneid"] = cls.zone.id cls.services["virtual_machine"]["template"] = template.id - # Create VMs, NAT Rules etc - cls.account = Account.create( - cls.api_client, - cls.services["account"], - domainid=domain.id - ) - - cls.service_offering = ServiceOffering.create( - cls.api_client, - cls.services["service_offering"] - ) - - cls.virtual_machine = VirtualMachine.create( - cls.api_client, - cls.services["virtual_machine"], - accountid=cls.account.name, - domainid=cls.account.domainid, - serviceofferingid=cls.service_offering.id, - mode=cls.services["mode"] - ) - - networkid = cls.virtual_machine.nic[0].networkid - - # create egress rule to allow wget of my cloud-set-guest-password script - if cls.zone.networktype.lower() == 'advanced': - EgressFireWallRule.create(cls.api_client, + cls._cleanup = [] + try: + # Create VMs, NAT Rules etc + cls.account = Account.create( + cls.api_client, + cls.services["account"], + domainid=domain.id) + cls._cleanup.append(cls.account) + + cls.service_offering = ServiceOffering.create( + cls.api_client, + cls.services["service_offering"]) + cls._cleanup.append(cls.service_offering) + + cls.virtual_machine = VirtualMachine.create( + cls.api_client, + cls.services["virtual_machine"], + accountid=cls.account.name, + domainid=cls.account.domainid, + serviceofferingid=cls.service_offering.id, + mode=cls.services["mode"]) + + networkid = cls.virtual_machine.nic[0].networkid + + # create egress rule to allow wget of my cloud-set-guest-password script + if cls.zone.networktype.lower() == 'advanced': + EgressFireWallRule.create(cls.api_client, networkid=networkid, protocol=cls.services["egress"]["protocol"], startport=cls.services["egress"]["startport"], endport=cls.services["egress"]["endport"], cidrlist=cls.services["egress"]["cidrlist"]) - cls.virtual_machine.password = cls.services["virtual_machine"]["password"] - ssh = cls.virtual_machine.get_ssh_client() - - # below steps are required to get the new password from VR(reset password) - # http://cloudstack.org/dl/cloud-set-guest-password - # Copy this file to /etc/init.d - # chmod +x /etc/init.d/cloud-set-guest-password - # chkconfig --add cloud-set-guest-password - # similar steps to get SSH key from web so as to make it ssh enabled - - cmds = [ - "cd /etc/init.d;wget http://people.apache.org/~tsp/cloud-set-guest-password", - "chmod +x /etc/init.d/cloud-set-guest-password", - "chkconfig --add cloud-set-guest-password", - "cd /etc/init.d;wget http://downloads.sourceforge.net/project/cloudstack/SSH%20Key%20Gen%20Script/" + \ - "cloud-set-guest-sshkey.in?r=http%3A%2F%2Fsourceforge" + \ - ".net%2Fprojects%2Fcloudstack%2Ffiles%2FSSH%2520Key%2520Gen%2520Script%2F&ts=1331225219&use_mirror=iweb", - "chmod +x /etc/init.d/cloud-set-guest-sshkey.in", - "chkconfig --add cloud-set-guest-sshkey.in" - ] - for c in cmds: - result = ssh.execute(c) - - #Stop virtual machine - cls.virtual_machine.stop(cls.api_client) - - # Poll listVM to ensure VM is stopped properly - timeout = cls.services["timeout"] - while True: - time.sleep(cls.services["sleep"]) - - # Ensure that VM is in stopped state - list_vm_response = list_virtual_machines( - cls.api_client, - id=cls.virtual_machine.id - ) - - if isinstance(list_vm_response, list): - - vm = list_vm_response[0] - if vm.state == 'Stopped': - break - - if timeout == 0: + cls.virtual_machine.password = cls.services["virtual_machine"]["password"] + ssh = cls.virtual_machine.get_ssh_client() + + # below steps are required to get the new password from VR(reset password) + # http://cloudstack.org/dl/cloud-set-guest-password + # Copy this file to /etc/init.d + # chmod +x /etc/init.d/cloud-set-guest-password + # chkconfig --add cloud-set-guest-password + # similar steps to get SSH key from web so as to make it ssh enabled + + cmds = [ + "cd /etc/init.d;wget http://people.apache.org/~tsp/cloud-set-guest-password", + "chmod +x /etc/init.d/cloud-set-guest-password", + "chkconfig --add cloud-set-guest-password", + "cd /etc/init.d;wget http://downloads.sourceforge.net/project/cloudstack/SSH%20Key%20Gen%20Script/" + \ + "cloud-set-guest-sshkey.in?r=http%3A%2F%2Fsourceforge" + \ + ".net%2Fprojects%2Fcloudstack%2Ffiles%2FSSH%2520Key%2520Gen%2520Script%2F&ts=1331225219&use_mirror=iweb", + "chmod +x /etc/init.d/cloud-set-guest-sshkey.in", + "chkconfig --add cloud-set-guest-sshkey.in" + ] + for c in cmds: + ssh.execute(c) + + #Stop virtual machine + cls.virtual_machine.stop(cls.api_client) + + list_volume = Volume.list( + cls.api_client, + virtualmachineid=cls.virtual_machine.id, + type='ROOT', + listall=True) + + if isinstance(list_volume, list): + cls.volume = list_volume[0] + else: raise Exception( - "Failed to stop VM (ID: %s) " % - vm.id) - - timeout = timeout - 1 - - list_volume = list_volumes( - cls.api_client, - virtualmachineid=cls.virtual_machine.id, - type='ROOT', - listall=True - ) - if isinstance(list_volume, list): - cls.volume = list_volume[0] - else: - raise Exception( "Exception: Unable to find root volume for VM: %s" % cls.virtual_machine.id) - cls.services["template"]["ostype"] = cls.services["ostype"] - #Create templates for Edit, Delete & update permissions testcases - cls.pw_ssh_enabled_template = Template.create( - cls.api_client, - cls.services["template"], - cls.volume.id, - account=cls.account.name, - domainid=cls.account.domainid - ) - # Delete the VM - No longer needed - cls.virtual_machine.delete(cls.api_client) - - cls._cleanup = [ - cls.service_offering, - cls.pw_ssh_enabled_template, - cls.account - ] + cls.services["template"]["ostype"] = cls.services["ostype"] + #Create templates for Edit, Delete & update permissions testcases + cls.pw_ssh_enabled_template = Template.create( + cls.api_client, + cls.services["template"], + cls.volume.id, + account=cls.account.name, + domainid=cls.account.domainid + ) + cls._cleanup.append(cls.pw_ssh_enabled_template) + # Delete the VM - No longer needed + cls.virtual_machine.delete(cls.api_client) + except Exception as e: + cls.tearDownClass() + raise unittest.SkipTest("Exception in setUpClass: %s" % e) @classmethod def tearDownClass(cls): @@ -955,14 +928,13 @@ class TestResetSSHKeyUserRights(cloudstackTestCase): @classmethod def setUpClass(cls): - cls.api_client = super( - TestResetSSHKeyUserRights, - cls).getClsTestClient().getApiClient() + cls.testClient = super(TestResetSSHKeyUserRights, cls).getClsTestClient() + cls.api_client = cls.testClient.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) + cls.domain = get_domain(cls.api_client) + cls.zone = get_zone(cls.api_client, cls.testClient.getZoneForTests()) cls.services['mode'] = cls.zone.networktype # Set Zones and disk offerings @@ -1028,36 +1000,16 @@ def setUpClass(cls): "chkconfig --add cloud-set-guest-sshkey.in" ] for c in cmds: - result = ssh.execute(c) - - #Stop virtual machine - cls.virtual_machine.stop(cls.api_client) + ssh.execute(c) - # Poll listVM to ensure VM is stopped properly - timeout = cls.services["timeout"] - while True: - time.sleep(cls.services["sleep"]) - - # Ensure that VM is in stopped state - list_vm_response = list_virtual_machines( - cls.api_client, - id=cls.virtual_machine.id - ) - - if isinstance(list_vm_response, list): - - vm = list_vm_response[0] - if vm.state == 'Stopped': - break - - if timeout == 0: - raise Exception( - "Failed to stop VM (ID: %s) " % - vm.id) - - timeout = timeout - 1 + try: + #Stop virtual machine + cls.virtual_machine.stop(cls.api_client) + except Exception as e: + cls.tearDownClass() + raise unittest.SkipTest("Exception in setUpClass: %s" % e) - list_volume = list_volumes( + list_volume = Volume.list( cls.api_client, virtualmachineid=cls.virtual_machine.id, type='ROOT', diff --git a/test/integration/component/test_resource_limits.py b/test/integration/component/test_resource_limits.py index f0d558ec2d..9f9cdfa06e 100644 --- a/test/integration/component/test_resource_limits.py +++ b/test/integration/component/test_resource_limits.py @@ -5,9 +5,9 @@ # 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 @@ -19,7 +19,7 @@ #Import Local Modules from nose.plugins.attrib import attr from marvin.cloudstackTestCase import cloudstackTestCase -from marvin.integration.lib.base import (VirtualMachine, +from marvin.lib.base import (VirtualMachine, Snapshot, Template, PublicIPAddress, @@ -31,14 +31,14 @@ NetworkOffering, ServiceOffering, Configurations) -from marvin.integration.lib.common import (list_volumes, +from marvin.lib.common import (list_volumes, get_domain, get_zone, get_template, update_resource_limit, list_configurations, wait_for_cleanup) -from marvin.integration.lib.utils import cleanup_resources +from marvin.lib.utils import cleanup_resources import time @@ -127,11 +127,13 @@ class TestResourceLimitsAccount(cloudstackTestCase): @classmethod def setUpClass(cls): - cls.api_client = super(TestResourceLimitsAccount, cls).getClsTestClient().getApiClient() + cls.testClient = super(TestResourceLimitsAccount, cls).getClsTestClient() + cls.api_client = cls.testClient.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) + cls.domain = get_domain(cls.api_client) + cls.zone = get_zone(cls.api_client, cls.testClient.getZoneForTests()) cls.services['mode'] = cls.zone.networktype cls.template = get_template( @@ -195,7 +197,7 @@ def tearDown(self): raise Exception("Warning: Exception during cleanup : %s" % e) return - @attr(tags=["advanced", "advancedns", "simulator"]) + @attr(tags=["advanced", "advancedns", "simulator", "selfservice"]) def test_01_vm_per_account(self): """Test VM limit per account """ @@ -288,7 +290,7 @@ def test_01_vm_per_account(self): ) return - @attr(tags=["advanced", "advancedns", "simulator"]) + @attr(tags=["advanced", "advancedns", "simulator", "selfservice"]) def test_02_publicip_per_account(self): """Test Public IP limit per account """ @@ -432,7 +434,7 @@ def test_02_publicip_per_account(self): return @attr(speed="slow") - @attr(tags=["advanced", "advancedns", "simulator"]) + @attr(tags=["advanced", "advancedns", "simulator", "selfservice"]) def test_03_snapshots_per_account(self): """Test Snapshot limit per account """ @@ -591,7 +593,7 @@ def test_03_snapshots_per_account(self): ) return - @attr(tags=["advanced", "advancedns", "simulator"]) + @attr(tags=["advanced", "advancedns", "simulator", "selfservice"]) def test_04_volumes_per_account(self): """Test Volumes limit per account """ @@ -733,7 +735,7 @@ def test_04_volumes_per_account(self): ) return - @attr(tags=["advanced", "advancedns"]) + @attr(tags=["advanced", "advancedns", "selfservice"]) def test_05_templates_per_account(self): """Test Templates limit per account """ @@ -745,11 +747,12 @@ def test_05_templates_per_account(self): # 3. Try to create 2 templates in account 2. Verify account 2 should be # able to create template without any error - self.debug( - "Updating template resource limit for account: %s" % + try: + self.debug( + "Updating template resource limit for account: %s" % self.account_1.name) - # Set usage_vm=1 for Account 1 - update_resource_limit( + # Set usage_vm=1 for Account 1 + update_resource_limit( self.apiclient, 4, # Template account=self.account_1.name, @@ -757,10 +760,10 @@ def test_05_templates_per_account(self): max=1 ) - self.debug( - "Updating volume resource limit for account: %s" % + self.debug( + "Updating volume resource limit for account: %s" % self.account_1.name) - virtual_machine_1 = VirtualMachine.create( + virtual_machine_1 = VirtualMachine.create( self.apiclient, self.services["server"], templateid=self.template.id, @@ -768,19 +771,19 @@ def test_05_templates_per_account(self): domainid=self.account_1.domainid, serviceofferingid=self.service_offering.id ) - self.cleanup.append(virtual_machine_1) - # Verify VM state - self.assertEqual( + self.cleanup.append(virtual_machine_1) + # Verify VM state + self.assertEqual( virtual_machine_1.state, 'Running', "Check VM state is Running or not" ) - self.debug( - "Deploying virtual machine for account: %s" % + self.debug( + "Deploying virtual machine for account: %s" % self.account_2.name) - # Create VM for second account - virtual_machine_2 = VirtualMachine.create( + # Create VM for second account + virtual_machine_2 = VirtualMachine.create( self.apiclient, self.services["server"], templateid=self.template.id, @@ -788,33 +791,33 @@ def test_05_templates_per_account(self): domainid=self.account_2.domainid, serviceofferingid=self.service_offering.id ) - self.cleanup.append(virtual_machine_2) - # Verify VM state - self.assertEqual( + self.cleanup.append(virtual_machine_2) + # Verify VM state + self.assertEqual( virtual_machine_2.state, 'Running', "Check VM state is Running or not" ) - virtual_machine_1.stop(self.apiclient) - # Get the Root disk of VM - volumes = list_volumes( + virtual_machine_1.stop(self.apiclient) + # Get the Root disk of VM + volumes = list_volumes( self.apiclient, virtualmachineid=virtual_machine_1.id, type='ROOT', listall=True ) - self.assertEqual( + self.assertEqual( isinstance(volumes, list), True, "Check for list volume response return valid data" ) - volume = volumes[0] + volume = volumes[0] - self.debug( - "Creating template from volume: %s" % volume.id) - # Create a template from the ROOTDISK (Account 1) - template_1 = Template.create( + self.debug( + "Creating template from volume: %s" % volume.id) + # Create a template from the ROOTDISK (Account 1) + template_1 = Template.create( self.apiclient, self.services["template"], volumeid=volume.id, @@ -822,14 +825,15 @@ def test_05_templates_per_account(self): domainid=self.account_1.domainid, ) - self.cleanup.append(template_1) - # Verify Template state - self.assertEqual( + self.cleanup.append(template_1) + # Verify Template state + self.assertEqual( template_1.isready, True, "Check Template is in ready state or not" ) - + except Exception as e: + self.fail("Exception occured: %s" % e) # Exception should be raised for second snapshot (account_1) with self.assertRaises(Exception): Template.create( @@ -839,25 +843,27 @@ def test_05_templates_per_account(self): account=self.account_1.name, domainid=self.account_1.domainid, ) - virtual_machine_2.stop(self.apiclient) - # Get the Root disk of VM - volumes = list_volumes( + + try: + virtual_machine_2.stop(self.apiclient) + # Get the Root disk of VM + volumes = list_volumes( self.apiclient, virtualmachineid=virtual_machine_2.id, type='ROOT', listall=True ) - self.assertEqual( + self.assertEqual( isinstance(volumes, list), True, "Check for list volume response return valid data" ) - volume = volumes[0] + volume = volumes[0] - self.debug( - "Creating template from volume: %s" % volume.id) - # Create a snapshot from the ROOTDISK (Account 1) - template_2 = Template.create( + self.debug( + "Creating template from volume: %s" % volume.id) + # Create a snapshot from the ROOTDISK (Account 1) + template_2 = Template.create( self.apiclient, self.services["template"], volumeid=volume.id, @@ -865,17 +871,17 @@ def test_05_templates_per_account(self): domainid=self.account_2.domainid, ) - self.cleanup.append(template_2) - # Verify Template state - self.assertEqual( + self.cleanup.append(template_2) + # Verify Template state + self.assertEqual( template_2.isready, True, "Check Template is in ready state or not" - ) - self.debug( - "Creating template from volume: %s" % volume.id) - # Create a second volume from the ROOTDISK (Account 2) - template_3 = Template.create( + ) + self.debug( + "Creating template from volume: %s" % volume.id) + # Create a second volume from the ROOTDISK (Account 2) + template_3 = Template.create( self.apiclient, self.services["template"], volumeid=volume.id, @@ -883,13 +889,15 @@ def test_05_templates_per_account(self): domainid=self.account_2.domainid, ) - self.cleanup.append(template_3) - # Verify Template state - self.assertEqual( + self.cleanup.append(template_3) + # Verify Template state + self.assertEqual( template_3.isready, True, "Check Template is in ready state or not" ) + except Exception as e: + self.fail("Exception occured: %s" % e) return @@ -897,10 +905,11 @@ class TestResourceLimitsDomain(cloudstackTestCase): @classmethod def setUpClass(cls): - cls.api_client = super(TestResourceLimitsDomain, cls).getClsTestClient().getApiClient() + cls.testClient = super(TestResourceLimitsDomain, cls).getClsTestClient() + cls.api_client = cls.testClient.getApiClient() + cls.services = Services().services - # Get Zone, Domain and templates - cls.zone = get_zone(cls.api_client, cls.services) + cls.zone = get_zone(cls.api_client, cls.testClient.getZoneForTests()) cls.services['mode'] = cls.zone.networktype cls.template = get_template( @@ -966,7 +975,7 @@ def tearDown(self): raise Exception("Warning: Exception during cleanup : %s" % e) return - @attr(tags=["advanced", "advancedns", "simulator"]) + @attr(tags=["advanced", "advancedns", "simulator", "selfservice"]) def test_01_vm_per_domain(self): """Test VM limit per domain """ @@ -1032,7 +1041,7 @@ def test_01_vm_per_domain(self): ) return - @attr(tags=["advanced", "advancedns", "simulator"]) + @attr(tags=["advanced", "advancedns", "simulator", "selfservice"]) def test_01_publicip_per_domain(self): """Test Public IP limit per domain """ @@ -1103,7 +1112,7 @@ def test_01_publicip_per_domain(self): return @attr(speed="slow") - @attr(tags=["advanced", "advancedns", "simulator"]) + @attr(tags=["advanced", "advancedns", "simulator", "selfservice"]) def test_03_snapshots_per_domain(self): """Test Snapshot limit per domain """ @@ -1187,7 +1196,7 @@ def test_03_snapshots_per_domain(self): ) return - @attr(tags=["advanced", "advancedns", "simulator"]) + @attr(tags=["advanced", "advancedns", "simulator", "selfservice"]) def test_04_volumes_per_domain(self): """Test Volumes limit per domain """ @@ -1240,7 +1249,7 @@ def test_04_volumes_per_domain(self): ) return - @attr(tags=["advanced", "advancedns"]) + @attr(tags=["advanced", "advancedns", "selfservice"]) def test_05_templates_per_domain(self): """Test Templates limit per domain """ @@ -1253,27 +1262,23 @@ def test_05_templates_per_domain(self): # 4. Try create 3rd template in the domain. It should give the user an # appropriate error and an alert should be generated. - # Set usage_vm=1 for Account 1 - update_resource_limit( + try: + # Set usage_vm=1 for Account 1 + update_resource_limit( self.apiclient, 2, # Volume domainid=self.account.domainid, max=5 ) - self.debug( - "Updating template resource limits for domain: %s" % - self.account.domainid) - # Set usage_vm=1 for Account 1 - update_resource_limit( + # Set usage_vm=1 for Account 1 + update_resource_limit( self.apiclient, 4, # Template domainid=self.account.domainid, max=2 ) - - self.debug("Deploying VM for account: %s" % self.account.name) - virtual_machine_1 = VirtualMachine.create( + virtual_machine_1 = VirtualMachine.create( self.apiclient, self.services["server"], templateid=self.template.id, @@ -1281,31 +1286,31 @@ def test_05_templates_per_domain(self): domainid=self.account.domainid, serviceofferingid=self.service_offering.id ) - self.cleanup.append(virtual_machine_1) - # Verify VM state - self.assertEqual( + self.cleanup.append(virtual_machine_1) + # Verify VM state + self.assertEqual( virtual_machine_1.state, 'Running', "Check VM state is Running or not" ) - virtual_machine_1.stop(self.apiclient) - # Get the Root disk of VM - volumes = list_volumes( + virtual_machine_1.stop(self.apiclient) + # Get the Root disk of VM + volumes = list_volumes( self.apiclient, virtualmachineid=virtual_machine_1.id, type='ROOT', listall=True ) - self.assertEqual( + self.assertEqual( isinstance(volumes, list), True, "Check for list volume response return valid data" ) - volume = volumes[0] + volume = volumes[0] - self.debug("Creating template from volume: %s" % volume.id) - # Create a template from the ROOTDISK - template_1 = Template.create( + self.debug("Creating template from volume: %s" % volume.id) + # Create a template from the ROOTDISK + template_1 = Template.create( self.apiclient, self.services["template"], volumeid=volume.id, @@ -1313,16 +1318,16 @@ def test_05_templates_per_domain(self): domainid=self.account.domainid, ) - self.cleanup.append(template_1) - # Verify Template state - self.assertEqual( + self.cleanup.append(template_1) + # Verify Template state + self.assertEqual( template_1.isready, True, "Check Template is in ready state or not" ) - self.debug("Creating template from volume: %s" % volume.id) - # Create a template from the ROOTDISK - template_2 = Template.create( + self.debug("Creating template from volume: %s" % volume.id) + # Create a template from the ROOTDISK + template_2 = Template.create( self.apiclient, self.services["template"], volumeid=volume.id, @@ -1330,13 +1335,15 @@ def test_05_templates_per_domain(self): domainid=self.account.domainid, ) - self.cleanup.append(template_2) - # Verify Template state - self.assertEqual( + self.cleanup.append(template_2) + # Verify Template state + self.assertEqual( template_2.isready, True, "Check Template is in ready state or not" ) + except Exception as e: + self.fail("Exception occured: %s" % e) # Exception should be raised for second template with self.assertRaises(Exception): @@ -1354,14 +1361,12 @@ class TestMaxAccountNetworks(cloudstackTestCase): @classmethod def setUpClass(cls): - cls.api_client = super( - TestMaxAccountNetworks, - cls - ).getClsTestClient().getApiClient() + cls.testClient = super(TestMaxAccountNetworks, cls).getClsTestClient() + cls.api_client = cls.testClient.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) + cls.zone = get_zone(cls.api_client, cls.testClient.getZoneForTests()) + cls.domain = get_domain(cls.api_client) cls.services['mode'] = cls.zone.networktype cls.template = get_template( cls.api_client, diff --git a/test/integration/component/test_routers.py b/test/integration/component/test_routers.py index ced3f525ca..d729a0779d 100644 --- a/test/integration/component/test_routers.py +++ b/test/integration/component/test_routers.py @@ -21,9 +21,9 @@ 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.lib.utils import * +from marvin.lib.base import * +from marvin.lib.common import * #Import System modules import time @@ -98,11 +98,13 @@ class TestRouterServices(cloudstackTestCase): @classmethod def setUpClass(cls): - cls.api_client = super(TestRouterServices, cls).getClsTestClient().getApiClient() + cls.testClient = super(TestRouterServices, cls).getClsTestClient() + cls.api_client = cls.testClient.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) + cls.domain = get_domain(cls.api_client) + cls.zone = get_zone(cls.api_client, cls.testClient.getZoneForTests()) cls.services['mode'] = cls.zone.networktype cls.template = get_template( cls.api_client, @@ -167,7 +169,7 @@ def setUp(self): self.cleanup = [] return - @attr(tags = ["advanced"]) + @attr(tags=["advanced", "selfservice"]) def test_01_AdvancedZoneRouterServices(self): """Test advanced zone router services """ @@ -318,7 +320,7 @@ def test_01_AdvancedZoneRouterServices(self): return @attr(configuration = "network.gc") - @attr(tags = ["advanced"]) + @attr(tags=["advanced", "selfservice"]) def test_02_NetworkGarbageCollection(self): """Test network garbage collection """ @@ -496,7 +498,7 @@ def test_02_NetworkGarbageCollection(self): self.cleanup.append(self.vm_2) return - @attr(tags = ["advanced"]) + @attr(tags=["advanced", "selfservice"]) def test_03_RouterStartOnVmDeploy(self): """Test router start on VM deploy """ @@ -641,11 +643,13 @@ class TestRouterStopCreatePF(cloudstackTestCase): @classmethod def setUpClass(cls): - cls.api_client = super(TestRouterStopCreatePF, cls).getClsTestClient().getApiClient() + cls.testClient = super(TestRouterStopCreatePF, cls).getClsTestClient() + cls.api_client = cls.testClient.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) + cls.domain = get_domain(cls.api_client) + cls.zone = get_zone(cls.api_client, cls.testClient.getZoneForTests()) cls.services['mode'] = cls.zone.networktype template = get_template( cls.api_client, @@ -703,7 +707,7 @@ def setUp(self): self.cleanup = [] return - @attr(tags = ["advanced", "advancedns"]) + @attr(tags=["advanced", "advancedns", "provisioning"]) def test_01_RouterStopCreatePF(self): """Test router stop create port forwarding """ @@ -853,11 +857,13 @@ class TestRouterStopCreateLB(cloudstackTestCase): @classmethod def setUpClass(cls): - cls.api_client = super(TestRouterStopCreateLB, cls).getClsTestClient().getApiClient() + cls.testClient = super(TestRouterStopCreateLB, cls).getClsTestClient() + cls.api_client = cls.testClient.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) + cls.domain = get_domain(cls.api_client) + cls.zone = get_zone(cls.api_client, cls.testClient.getZoneForTests()) cls.services['mode'] = cls.zone.networktype template = get_template( cls.api_client, @@ -914,7 +920,7 @@ def setUp(self): self.cleanup = [] return - @attr(tags = ["advanced", "advancedns"]) + @attr(tags=["advanced", "advancedns", "provisioning"]) def test_01_RouterStopCreateLB(self): """Test router stop create Load balancing """ @@ -1065,11 +1071,13 @@ class TestRouterStopCreateFW(cloudstackTestCase): @classmethod def setUpClass(cls): - cls.api_client = super(TestRouterStopCreateFW, cls).getClsTestClient().getApiClient() + cls.testClient = super(TestRouterStopCreateFW, cls).getClsTestClient() + cls.api_client = cls.testClient.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) + cls.domain = get_domain(cls.api_client) + cls.zone = get_zone(cls.api_client, cls.testClient.getZoneForTests()) cls.services['mode'] = cls.zone.networktype template = get_template( cls.api_client, @@ -1122,10 +1130,11 @@ def tearDown(self): def setUp(self): self.apiclient = self.testClient.getApiClient() + self.hypervisor = self.testClient.getHypervisorInfo() self.cleanup = [] return - @attr(tags = ["advanced", "advancedns"]) + @attr(tags=["advanced", "advancedns", "provisioning"]) def test_01_RouterStopCreateFW(self): """Test router stop create Firewall rule """ @@ -1255,8 +1264,8 @@ def test_01_RouterStopCreateFW(self): "Check end port of firewall rule" ) # For DNS and DHCP check 'dnsmasq' process status - if (self.apiclient.hypervisor.lower() == 'vmware' - or self.apiclient.hypervisor.lower() == 'hyperv'): + if (self.hypervisor.lower() == 'vmware' + or self.hypervisor.lower() == 'hyperv'): result = get_process_status( self.apiclient.connection.mgtSvr, 22, @@ -1264,7 +1273,7 @@ def test_01_RouterStopCreateFW(self): self.apiclient.connection.passwd, router.linklocalip, 'iptables -t nat -L', - hypervisor=self.apiclient.hypervisor + hypervisor=self.hypervisor ) else: hosts = list_hosts( diff --git a/test/integration/component/test_security_groups.py b/test/integration/component/test_security_groups.py index 8e0739658a..63436131fe 100644 --- a/test/integration/component/test_security_groups.py +++ b/test/integration/component/test_security_groups.py @@ -18,13 +18,21 @@ """ P1 for Security groups """ #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.cloudstackTestCase import cloudstackTestCase +#from marvin.cloudstackAPI import * +from marvin.lib.utils import cleanup_resources +from marvin.lib.base import (Account, + ServiceOffering, + VirtualMachine, + SecurityGroup, + Router, + Host, + Configurations) +from marvin.lib.common import (get_domain, + get_zone, + get_template, + get_process_status) from marvin.sshClient import SshClient #Import System modules @@ -117,12 +125,13 @@ def tearDown(self): @classmethod def setUpClass(cls): - cls.services = Services().services - cls.api_client = super(TestDefaultSecurityGroup, cls).getClsTestClient().getApiClient() + cls.testClient = super(TestDefaultSecurityGroup, cls).getClsTestClient() + cls.api_client = cls.testClient.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) + cls.domain = get_domain(cls.api_client) + cls.zone = get_zone(cls.api_client, cls.testClient.getZoneForTests()) cls.services['mode'] = cls.zone.networktype template = get_template( @@ -185,7 +194,7 @@ def test_01_deployVM_InDefaultSecurityGroup(self): self.debug("Deployed VM with ID: %s" % self.virtual_machine.id) self.cleanup.append(self.virtual_machine) - list_vm_response = list_virtual_machines( + list_vm_response = VirtualMachine.list( self.apiclient, id=self.virtual_machine.id ) @@ -224,7 +233,7 @@ def test_01_deployVM_InDefaultSecurityGroup(self): "Verify list routers response for account: %s" \ % self.account.name ) - routers = list_routers( + routers = Router.list( self.apiclient, zoneid=self.zone.id, listall=True @@ -299,7 +308,7 @@ def test_03_accessInDefaultSecurityGroup(self): self.debug("Deployed VM with ID: %s" % self.virtual_machine.id) self.cleanup.append(self.virtual_machine) - list_vm_response = list_virtual_machines( + list_vm_response = VirtualMachine.list( self.apiclient, id=self.virtual_machine.id ) @@ -361,12 +370,12 @@ def test_03_accessInDefaultSecurityGroup(self): # SSH Attempt to VM should fail with self.assertRaises(Exception): self.debug("SSH into VM: %s" % self.virtual_machine.ssh_ip) - ssh = SshClient( - self.virtual_machine.ssh_ip, - self.virtual_machine.ssh_port, - self.virtual_machine.username, - self.virtual_machine.password - ) + SshClient( + self.virtual_machine.ssh_ip, + self.virtual_machine.ssh_port, + self.virtual_machine.username, + self.virtual_machine.password + ) return @@ -390,12 +399,13 @@ def tearDown(self): @classmethod def setUpClass(cls): - cls.services = Services().services - cls.api_client = super(TestAuthorizeIngressRule, cls).getClsTestClient().getApiClient() + cls.testClient = super(TestAuthorizeIngressRule, cls).getClsTestClient() + cls.api_client = cls.testClient.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) + cls.domain = get_domain(cls.api_client) + cls.zone = get_zone(cls.api_client, cls.testClient.getZoneForTests()) cls.services['mode'] = cls.zone.networktype template = get_template( @@ -526,12 +536,13 @@ def tearDown(self): @classmethod def setUpClass(cls): - cls.services = Services().services - cls.api_client = super(TestRevokeIngressRule, cls).getClsTestClient().getApiClient() + cls.testClient = super(TestRevokeIngressRule, cls).getClsTestClient() + cls.api_client = cls.testClient.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) + cls.domain = get_domain(cls.api_client) + cls.zone = get_zone(cls.api_client, cls.testClient.getZoneForTests()) cls.services['mode'] = cls.zone.networktype template = get_template( @@ -648,7 +659,7 @@ def test_01_revokeIngressRule(self): self.debug("Revoking ingress rule for sec group ID: %s for ssh access" % security_group.id) # Revoke Security group to SSH to VM - result = security_group.revoke( + security_group.revoke( self.apiclient, id=ssh_rule["ruleid"] ) @@ -684,12 +695,13 @@ def tearDown(self): @classmethod def setUpClass(cls): - cls.services = Services().services - cls.api_client = super(TestDhcpOnlyRouter, cls).getClsTestClient().getApiClient() + cls.testClient = super(TestDhcpOnlyRouter, cls).getClsTestClient() + cls.api_client = cls.testClient.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) + cls.domain = get_domain(cls.api_client) + cls.zone = get_zone(cls.api_client, cls.testClient.getZoneForTests()) cls.services['mode'] = cls.zone.networktype template = get_template( @@ -748,7 +760,7 @@ def test_01_dhcpOnlyRouter(self): #2. The only service supported by this router should be dhcp # Find router associated with user account - list_router_response = list_routers( + list_router_response = Router.list( self.apiclient, zoneid=self.zone.id, listall=True @@ -760,7 +772,7 @@ def test_01_dhcpOnlyRouter(self): ) router = list_router_response[0] - hosts = list_hosts( + hosts = Host.list( self.apiclient, zoneid=router.zoneid, type='Routing', @@ -821,12 +833,13 @@ def tearDown(self): @classmethod def setUpClass(cls): - cls.services = Services().services - cls.api_client = super(TestdeployVMWithUserData, cls).getClsTestClient().getApiClient() + cls.testClient = super(TestdeployVMWithUserData, cls).getClsTestClient() + cls.api_client = cls.testClient.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) + cls.domain = get_domain(cls.api_client) + cls.zone = get_zone(cls.api_client, cls.testClient.getZoneForTests()) cls.services['mode'] = cls.zone.networktype template = get_template( @@ -881,7 +894,7 @@ def test_01_deployVMWithUserData(self): # router for this VM # Find router associated with user account - list_router_response = list_routers( + list_router_response = Router.list( self.apiclient, zoneid=self.zone.id, listall=True @@ -985,8 +998,8 @@ def setUp(self): self.services = Services().services # Get Zone, Domain and templates - self.domain = get_domain(self.apiclient, self.services) - self.zone = get_zone(self.apiclient, self.services) + self.domain = get_domain(self.apiclient) + self.zone = get_zone(self.apiclient, self.testClient.getZoneForTests()) self.services['mode'] = self.zone.networktype template = get_template( @@ -1196,7 +1209,7 @@ def test_02_delete_security_grp_withoout_running_vm(self): # Destroy the VM self.virtual_machine.delete(self.apiclient) - config = list_configurations( + config = Configurations.list( self.apiclient, name='expunge.delay' ) @@ -1215,8 +1228,8 @@ def test_02_delete_security_grp_withoout_running_vm(self): self.debug("Deleting Security Group: %s" % security_group.id) security_group.delete(self.apiclient) except Exception as e: - self.fail("Failed to delete security group - ID: %s" \ - % security_group.id + self.fail("Failed to delete security group - ID: %s: %s" \ + % (security_group.id, e) ) return @@ -1232,8 +1245,8 @@ def setUp(self): self.services = Services().services # Get Zone, Domain and templates - self.domain = get_domain(self.apiclient, self.services) - self.zone = get_zone(self.apiclient, self.services) + self.domain = get_domain(self.apiclient) + self.zone = get_zone(self.apiclient, self.testClient.getZoneForTests()) self.services['mode'] = self.zone.networktype template = get_template( @@ -1634,15 +1647,13 @@ def test_03_stopStartVM_verifyIngressAccess(self): % ingress_rule["id"] ) - self.virtual_machine.stop(self.apiclient) - - # Sleep to ensure that VM is in stopped state - time.sleep(self.services["sleep"]) - - self.virtual_machine.start(self.apiclient) - - # Sleep to ensure that VM is in running state - time.sleep(self.services["sleep"]) + try: + self.virtual_machine.stop(self.apiclient) + self.virtual_machine.start(self.apiclient) + # Sleep to ensure that VM is in running state + time.sleep(self.services["sleep"]) + except Exception as e: + self.fail("Exception occured: %s" % e) # SSH should be allowed on 22 port after restart try: diff --git a/test/integration/component/test_shared_networks.py b/test/integration/component/test_shared_networks.py index 99cce19488..f99bfbf8ed 100644 --- a/test/integration/component/test_shared_networks.py +++ b/test/integration/component/test_shared_networks.py @@ -20,7 +20,7 @@ #Import Local Modules from nose.plugins.attrib import attr from marvin.cloudstackTestCase import cloudstackTestCase, unittest -from marvin.integration.lib.base import (Account, +from marvin.lib.base import (Account, Network, NetworkOffering, VirtualMachine, @@ -31,9 +31,9 @@ FireWallRule, ServiceOffering, PublicIPAddress) -from marvin.integration.lib.utils import (cleanup_resources, +from marvin.lib.utils import (cleanup_resources, xsplit) -from marvin.integration.lib.common import (get_domain, +from marvin.lib.common import (get_domain, get_zone, get_template, wait_for_cleanup, @@ -154,16 +154,13 @@ class TestSharedNetworks(cloudstackTestCase): @classmethod def setUpClass(cls): - cls.api_client = super( - TestSharedNetworks, - cls - ).getClsTestClient().getApiClient() + cls.testClient = super(TestSharedNetworks, cls).getClsTestClient() + cls.api_client = cls.testClient.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) + cls.domain = get_domain(cls.api_client) + cls.zone = get_zone(cls.api_client, cls.testClient.getZoneForTests()) cls.template = get_template( cls.api_client, cls.zone.id, @@ -260,7 +257,7 @@ def tearDown(self): return - @attr(tags=["advanced", "advancedns"]) + @attr(tags=["advanced", "advancedns", "selfservice"]) def test_sharedNetworkOffering_01(self): """ Test shared network Offering 01 """ @@ -396,7 +393,7 @@ def test_sharedNetworkOffering_01(self): ) self.debug("NetworkOffering created and enabled: %s" % self.shared_network_offering.id) - @attr(tags=["advanced", "advancedns"]) + @attr(tags=["advanced", "advancedns", "selfservice"]) def test_sharedNetworkOffering_02(self): """ Test Shared Network Offering 02 """ @@ -485,7 +482,7 @@ def test_sharedNetworkOffering_02(self): self.debug("Network Offering creation failed with vlan as False in advance mode and shared guest type. Exception: %s" % e) - @attr(tags=["advanced", "advancedns"]) + @attr(tags=["advanced", "advancedns", "selfservice"]) def test_sharedNetworkOffering_03(self): """ Test Shared Network Offering 03 """ @@ -575,7 +572,7 @@ def test_sharedNetworkOffering_03(self): self.debug("Network Offering creation failed with vlan as true and ip ranges as False in advance mode and with shared guest type.\ Exception : %s" % e) - @attr(tags=["advanced", "advancedns"]) + @attr(tags=["advanced", "advancedns", "selfservice"]) def test_createSharedNetwork_All(self): """ Test Shared Network ALL """ @@ -846,7 +843,7 @@ def test_createSharedNetwork_All(self): if netaddr.IPAddress(unicode(vms[0].nic[0].ipaddress)) not in ip_range: self.fail("Virtual machine ip should be from the ip range assigned to network created.") - @attr(tags=["advanced", "advancedns"]) + @attr(tags=["advanced", "advancedns", "selfservice"]) def test_createSharedNetwork_accountSpecific(self): """ Test Shared Network with scope account """ @@ -1095,7 +1092,7 @@ def test_createSharedNetwork_accountSpecific(self): if netaddr.IPAddress(unicode(vms[0].nic[0].ipaddress)) not in ip_range: self.fail("Virtual machine ip should be from the ip range assigned to network created.") - @attr(tags=["advanced", "advancedns"]) + @attr(tags=["advanced", "advancedns", "selfservice"]) def test_createSharedNetwork_domainSpecific(self): """ Test Shared Network with scope domain """ @@ -1439,7 +1436,7 @@ def test_createSharedNetwork_domainSpecific(self): if netaddr.IPAddress(unicode(vms[0].nic[0].ipaddress)) not in ip_range: self.fail("Virtual machine ip should be from the ip range assigned to network created.") - @attr(tags=["advanced", "advancedns"]) + @attr(tags=["advanced", "advancedns", "selfservice"]) def test_createSharedNetwork_projectSpecific(self): """ Test Shared Network with scope project """ @@ -1716,7 +1713,7 @@ def test_createSharedNetwork_projectSpecific(self): self.fail("Virtual machine ip should be from the ip range assigned to network created.") @unittest.skip("skipped - This is a redundant case and also this is causing issue for rest fo the cases ") - @attr(tags=["advanced", "advancedns"]) + @attr(tags=["advanced", "advancedns", "NA"]) def test_createSharedNetwork_usedVlan(self): """ Test Shared Network with used vlan 01 """ @@ -1860,7 +1857,7 @@ def test_createSharedNetwork_usedVlan(self): self.debug("Network creation failed because the valn id being used by another network. Exception: %s" % e) - @attr(tags=["advanced", "advancedns"]) + @attr(tags=["advanced", "advancedns", "selfservice"]) def test_createSharedNetwork_usedVlan2(self): """ Test Shared Network with used vlan 02 """ @@ -2042,7 +2039,7 @@ def test_createSharedNetwork_usedVlan2(self): except Exception as e: self.debug("Network creation failed because the valn id being used by another network. Exception: %s" % e) - @attr(tags=["advanced", "advancedns"]) + @attr(tags=["advanced", "advancedns", "selfservice"]) def test_deployVM_multipleSharedNetwork(self): """ Test Vm deployment with multiple shared networks """ @@ -2292,7 +2289,7 @@ def test_deployVM_multipleSharedNetwork(self): self.assertTrue(self.network1_admin_account_virtual_machine.nic[0].ipaddress is not None, "ip should be assigned to running virtual machine") - @attr(tags=["advanced", "advancedns"]) + @attr(tags=["advanced", "advancedns", "provisioning"]) def test_deployVM_isolatedAndShared(self): """ Test VM deployment in shared and isolated networks """ @@ -2631,7 +2628,7 @@ def test_deployVM_isolatedAndShared(self): except Exception as e: self.fail("SSH Access failed for %s: %s" % (self.isolated_network_admin_account_virtual_machine.ipaddress, e)) - @attr(tags=["advanced", "advancedns"]) + @attr(tags=["advanced", "advancedns", "selfservice"]) def test_networkWithsubdomainaccessTrue(self): """ Test Shared Network with subdomainaccess=True """ @@ -2762,7 +2759,7 @@ def test_networkWithsubdomainaccessTrue(self): except: self.debug("Network creation failed because subdomainaccess parameter was passed when scope was account.") - @attr(tags=["advanced", "advancedns"]) + @attr(tags=["advanced", "advancedns", "selfservice"]) def test_networkWithsubdomainaccessFalse(self): """ Test shared Network with subdomainaccess=False """ diff --git a/test/integration/component/test_snapshot_gc.py b/test/integration/component/test_snapshot_gc.py index 1e1cc5dd80..42c361cdff 100644 --- a/test/integration/component/test_snapshot_gc.py +++ b/test/integration/component/test_snapshot_gc.py @@ -18,10 +18,10 @@ 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.integration.lib.utils import is_snapshot_on_nfs +from marvin.lib.utils import * +from marvin.lib.base import * +from marvin.lib.common import * +from marvin.lib.utils import is_snapshot_on_nfs class Services: @@ -122,11 +122,13 @@ class TestAccountSnapshotClean(cloudstackTestCase): @classmethod def setUpClass(cls): - cls.api_client = super(TestAccountSnapshotClean, cls).getClsTestClient().getApiClient() + cls.testClient = super(TestAccountSnapshotClean, cls).getClsTestClient() + cls.api_client = cls.testClient.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) + cls.domain = get_domain(cls.api_client) + cls.zone = get_zone(cls.api_client, cls.testClient.getZoneForTests()) cls.services['mode'] = cls.zone.networktype template = get_template( @@ -206,7 +208,7 @@ def tearDown(self): return @attr(speed = "slow") - @attr(tags = ["advanced", "advancedns", "basic", "sg"]) + @attr(tags=["advanced", "advancedns", "basic", "sg", "provisioning"]) def test_02_accountSnapshotClean(self): """Test snapshot cleanup after account deletion """ diff --git a/test/integration/component/test_snapshot_limits.py b/test/integration/component/test_snapshot_limits.py index a1bf1ba2f5..95c64322e4 100644 --- a/test/integration/component/test_snapshot_limits.py +++ b/test/integration/component/test_snapshot_limits.py @@ -18,10 +18,10 @@ 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.integration.lib.utils import is_snapshot_on_nfs +from marvin.lib.utils import * +from marvin.lib.base import * +from marvin.lib.common import * +from marvin.lib.utils import is_snapshot_on_nfs import os @@ -123,11 +123,13 @@ class TestSnapshotLimit(cloudstackTestCase): @classmethod def setUpClass(cls): - cls.api_client = super(TestSnapshotLimit, cls).getClsTestClient().getApiClient() + cls.testClient = super(TestSnapshotLimit, cls).getClsTestClient() + cls.api_client = cls.testClient.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) + cls.domain = get_domain(cls.api_client) + cls.zone = get_zone(cls.api_client, cls.testClient.getZoneForTests()) cls.services['mode'] = cls.zone.networktype cls._cleanup = [] @@ -199,7 +201,7 @@ def tearDown(self): return @attr(speed = "slow") - @attr(tags = ["advanced", "advancedns"]) + @attr(tags=["advanced", "advancedns", "provisioning"]) def test_04_snapshot_limit(self): """Test snapshot limit in snapshot policies """ diff --git a/test/integration/component/test_snapshots.py b/test/integration/component/test_snapshots.py index 17579d63d4..f874bd3770 100644 --- a/test/integration/component/test_snapshots.py +++ b/test/integration/component/test_snapshots.py @@ -20,7 +20,7 @@ from nose.plugins.attrib import attr from marvin.cloudstackTestCase import cloudstackTestCase, unittest -from marvin.integration.lib.base import (Snapshot, +from marvin.lib.base import (Snapshot, Template, VirtualMachine, Account, @@ -28,7 +28,7 @@ DiskOffering, Volume) -from marvin.integration.lib.common import (get_domain, +from marvin.lib.common import (get_domain, get_zone, get_template, list_events, @@ -38,7 +38,7 @@ list_virtual_machines, ) -from marvin.integration.lib.utils import (cleanup_resources, +from marvin.lib.utils import (cleanup_resources, format_volume_to_ext3, random_gen, is_snapshot_on_nfs, @@ -158,11 +158,13 @@ class TestSnapshots(cloudstackTestCase): @classmethod def setUpClass(cls): - cls.api_client = super(TestSnapshots, cls).getClsTestClient().getApiClient() + cls.testClient = super(TestSnapshots, cls).getClsTestClient() + cls.api_client = cls.testClient.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) + cls.domain = get_domain(cls.api_client) + cls.zone = get_zone(cls.api_client, cls.testClient.getZoneForTests()) cls.services['mode'] = cls.zone.networktype cls.disk_offering = DiskOffering.create( cls.api_client, @@ -229,6 +231,7 @@ def tearDownClass(cls): def setUp(self): self.apiclient = self.testClient.getApiClient() + self.hypervisor = self.testClient.getHypervisorInfo() self.dbclient = self.testClient.getDbConnection() self.cleanup = [] return @@ -242,7 +245,7 @@ def tearDown(self): return @attr(speed = "slow") - @attr(tags = ["advanced", "advancedns", "smoke"]) + @attr(tags=["advanced", "advancedns", "smoke", "provisioning"]) def test_02_snapshot_data_disk(self): """Test Snapshot Data Disk """ @@ -289,7 +292,7 @@ def test_02_snapshot_data_disk(self): return @attr(speed = "slow") - @attr(tags = ["advanced", "advancedns", "basic", "sg"]) + @attr(tags=["advanced", "advancedns", "basic", "sg", "provisioning"]) def test_01_volume_from_snapshot(self): """Test Creating snapshot from volume having spaces in name(KVM) """ @@ -534,7 +537,7 @@ def test_01_volume_from_snapshot(self): return @attr(speed = "slow") - @attr(tags = ["advanced", "advancedns", "smoke"]) + @attr(tags=["advanced", "advancedns", "smoke", "provisioning"]) def test_04_delete_snapshot(self): """Test Delete Snapshot """ @@ -593,7 +596,7 @@ def test_04_delete_snapshot(self): return @attr(speed = "slow") - @attr(tags = ["advanced", "advancedns", "basic", "sg"]) + @attr(tags=["advanced", "advancedns", "basic", "sg", "provisioning"]) def test_03_snapshot_detachedDisk(self): """Test snapshot from detached disk """ @@ -719,7 +722,7 @@ def test_03_snapshot_detachedDisk(self): return @attr(speed = "slow") - @attr(tags = ["advanced", "advancedns", "smoke", "xen"]) + @attr(tags=["advanced", "advancedns", "smoke", "xen", "provisioning"]) def test_07_template_from_snapshot(self): """Create Template from snapshot """ @@ -910,11 +913,13 @@ class TestCreateVMSnapshotTemplate(cloudstackTestCase): @classmethod def setUpClass(cls): - cls.api_client = super(TestCreateVMSnapshotTemplate, cls).getClsTestClient().getApiClient() + cls.testClient = super(TestCreateVMSnapshotTemplate, cls).getClsTestClient() + cls.api_client = cls.testClient.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) + cls.domain = get_domain(cls.api_client) + cls.zone = get_zone(cls.api_client, cls.testClient.getZoneForTests()) cls.services['mode'] = cls.zone.networktype cls.template = get_template( @@ -956,6 +961,7 @@ def tearDownClass(cls): def setUp(self): self.apiclient = self.testClient.getApiClient() + self.hypervisor = self.testClient.getHypervisorInfo() self.dbclient = self.testClient.getDbConnection() self.cleanup = [] return @@ -969,7 +975,7 @@ def tearDown(self): return @attr(speed = "slow") - @attr(tags = ["advanced", "advancedns"]) + @attr(tags=["advanced", "advancedns", "provisioning"]) def test_01_createVM_snapshotTemplate(self): """Test create VM, Snapshot and Template """ @@ -1108,11 +1114,14 @@ class TestSnapshotEvents(cloudstackTestCase): @classmethod def setUpClass(cls): - cls.api_client = super(TestSnapshotEvents, cls).getClsTestClient().getApiClient() + cls.testClient = super(TestSnapshotEvents, cls).getClsTestClient() + cls.api_client = cls.testClient.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) + cls.domain = get_domain(cls.api_client) + cls.zone = get_zone(cls.api_client, cls.testClient.getZoneForTests()) cls.services['mode'] = cls.zone.networktype template = get_template( @@ -1163,6 +1172,7 @@ def tearDownClass(cls): def setUp(self): self.apiclient = self.testClient.getApiClient() + self.hypervisor = self.testClient.getHypervisorInfo() self.dbclient = self.testClient.getDbConnection() self.cleanup = [] return @@ -1176,7 +1186,7 @@ def tearDown(self): return @attr(speed = "slow") - @attr(tags = ["advanced", "advancedns"]) + @attr(tags=["advanced", "advancedns", "selfservice"]) def test_05_snapshot_events(self): """Test snapshot events """ diff --git a/test/integration/component/test_snapshots_improvement.py b/test/integration/component/test_snapshots_improvement.py index 77c240d34f..b2b0a546d5 100644 --- a/test/integration/component/test_snapshots_improvement.py +++ b/test/integration/component/test_snapshots_improvement.py @@ -20,10 +20,10 @@ # Import Local Modules from nose.plugins.attrib import attr from marvin.cloudstackTestCase import cloudstackTestCase, unittest -from marvin.integration.lib.utils import (random_gen, +from marvin.lib.utils import (random_gen, is_snapshot_on_nfs, cleanup_resources) -from marvin.integration.lib.base import ( +from marvin.lib.base import ( Account, ServiceOffering, VirtualMachine, @@ -32,7 +32,7 @@ Volume, DiskOffering ) -from marvin.integration.lib.common import (get_domain, +from marvin.lib.common import (get_domain, get_zone, get_template, list_snapshots @@ -126,11 +126,13 @@ class TestSnapshotOnRootVolume(cloudstackTestCase): @classmethod def setUpClass(cls): - cls.api_client = super(TestSnapshotOnRootVolume, - cls).getClsTestClient().getApiClient() + cls.testClient = super(TestSnapshotOnRootVolume, cls).getClsTestClient() + cls.api_client = cls.testClient.getApiClient() + cls.services = Services().services - cls.domain = get_domain(cls.api_client, cls.services) - cls.zone = get_zone(cls.api_client, cls.services) + # Get Zone, Domain and templates + cls.domain = get_domain(cls.api_client) + cls.zone = get_zone(cls.api_client, cls.testClient.getZoneForTests()) cls.template = get_template( cls.api_client, cls.zone.id, @@ -183,7 +185,7 @@ def tearDown(self): raise Exception("Warning: Exception during cleanup : %s" % e) return - @attr(tags=["advanced", "basic"]) + @attr(tags=["advanced", "basic", "provisioning"]) def test_01_snapshot_on_rootVolume(self): """Test create VM with default cent os template and create snapshot on root disk of the vm @@ -299,13 +301,13 @@ class TestCreateSnapshot(cloudstackTestCase): @classmethod def setUpClass(cls): - cls.api_client = super( - TestCreateSnapshot, - cls).getClsTestClient().getApiClient() + cls.testClient = super(TestCreateSnapshot, cls).getClsTestClient() + cls.api_client = cls.testClient.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) + cls.domain = get_domain(cls.api_client) + cls.zone = get_zone(cls.api_client, cls.testClient.getZoneForTests()) cls.template = get_template( cls.api_client, diff --git a/test/integration/component/test_stopped_vm.py b/test/integration/component/test_stopped_vm.py index 4ba94bfc29..04dd859d0c 100644 --- a/test/integration/component/test_stopped_vm.py +++ b/test/integration/component/test_stopped_vm.py @@ -18,13 +18,27 @@ """ P1 for stopped Virtual Maschine life cycle """ #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.cloudstackTestCase import cloudstackTestCase +#from marvin.cloudstackAPI import * +from marvin.lib.utils import cleanup_resources +from marvin.lib.base import (Account, + VirtualMachine, + ServiceOffering, + Volume, + Router, + DiskOffering, + Host, + Iso, + Cluster, + StoragePool, + Configurations, + Template) +from marvin.lib.common import (get_zone, + get_domain, + get_template, + get_builtin_template_info, + update_resource_limit) #Import System modules import time @@ -108,14 +122,13 @@ class TestDeployVM(cloudstackTestCase): @classmethod def setUpClass(cls): - cls.api_client = super( - TestDeployVM, - cls - ).getClsTestClient().getApiClient() + cls.testClient = super(TestDeployVM, cls).getClsTestClient() + cls.api_client = cls.testClient.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) + cls.domain = get_domain(cls.api_client) + cls.zone = get_zone(cls.api_client, cls.testClient.getZoneForTests()) cls.template = get_template( cls.api_client, @@ -170,7 +183,7 @@ def tearDown(self): except Exception as e: self.debug("Warning! Exception in tearDown: %s" % e) - @attr(tags = ["advanced", "eip", "advancedns", "basic", "sg"]) + @attr(tags=["advanced", "eip", "advancedns", "selfservice"]) def test_01_deploy_vm_no_startvm(self): """Test Deploy Virtual Machine with no startVM parameter """ @@ -195,7 +208,7 @@ def test_01_deploy_vm_no_startvm(self): self.debug("Deployed instance in account: %s" % self.account.name) - list_vm_response = list_virtual_machines( + list_vm_response = VirtualMachine.list( self.apiclient, id=self.virtual_machine.id ) @@ -220,7 +233,7 @@ def test_01_deploy_vm_no_startvm(self): ) return - @attr(tags = ["advanced", "eip", "advancedns", "basic", "sg"]) + @attr(tags=["advanced", "eip", "advancedns", "basic", "sg", "selfservice"]) def test_02_deploy_vm_startvm_true(self): """Test Deploy Virtual Machine with startVM=true parameter """ @@ -246,7 +259,7 @@ def test_02_deploy_vm_startvm_true(self): self.debug("Deployed instance in account: %s" % self.account.name) - list_vm_response = list_virtual_machines( + list_vm_response = VirtualMachine.list( self.apiclient, id=self.virtual_machine.id ) @@ -271,7 +284,7 @@ def test_02_deploy_vm_startvm_true(self): ) return - @attr(tags = ["advanced", "eip", "advancedns", "basic", "sg"]) + @attr(tags=["advanced", "eip", "advancedns", "basic", "sg", "selfservice"]) def test_03_deploy_vm_startvm_false(self): """Test Deploy Virtual Machine with startVM=false parameter """ @@ -298,7 +311,7 @@ def test_03_deploy_vm_startvm_false(self): self.debug("Deployed instance in account: %s" % self.account.name) - list_vm_response = list_virtual_machines( + list_vm_response = VirtualMachine.list( self.apiclient, id=self.virtual_machine.id ) @@ -341,17 +354,17 @@ def test_03_deploy_vm_startvm_false(self): ) self.debug("Instance destroyed..waiting till expunge interval") - interval = list_configurations( + interval = Configurations.list( self.apiclient, name='expunge.interval' ) - delay = list_configurations( + delay = Configurations.list( self.apiclient, name='expunge.delay' ) # Sleep to ensure that all resources are deleted time.sleep((int(interval[0].value) + int(delay[0].value))) - list_vm_response = list_virtual_machines( + list_vm_response = VirtualMachine.list( self.apiclient, id=self.virtual_machine.id ) @@ -363,7 +376,7 @@ def test_03_deploy_vm_startvm_false(self): ) return - @attr(tags = ["advanced", "eip", "advancedns", "basic", "sg"]) + @attr(tags=["advanced", "eip", "advancedns", "basic", "sg", "selfservice"]) def test_04_deploy_startvm_false_attach_volume(self): """Test Deploy Virtual Machine with startVM=false and attach volume """ @@ -388,7 +401,7 @@ def test_04_deploy_startvm_false_attach_volume(self): self.debug("Deployed instance in account: %s" % self.account.name) - list_vm_response = list_virtual_machines( + list_vm_response = VirtualMachine.list( self.apiclient, id=self.virtual_machine.id ) @@ -426,10 +439,10 @@ def test_04_deploy_startvm_false_attach_volume(self): try: self.virtual_machine.attach_volume(self.apiclient, volume) except Exception as e: - self.fail("Attach volume failed!") + self.fail("Attach volume failed with Exception: %s" % e) return - @attr(tags = ["advanced", "eip", "advancedns", "basic", "sg"]) + @attr(tags=["advanced", "eip", "advancedns", "basic", "sg", "selfservice"]) def test_05_deploy_startvm_false_change_so(self): """Test Deploy Virtual Machine with startVM=false and change service offering """ @@ -453,7 +466,7 @@ def test_05_deploy_startvm_false_change_so(self): self.debug("Deployed instance in account: %s" % self.account.name) - list_vm_response = list_virtual_machines( + list_vm_response = VirtualMachine.list( self.apiclient, id=self.virtual_machine.id ) @@ -502,7 +515,7 @@ def test_05_deploy_startvm_false_change_so(self): return - @attr(tags = ["advanced", "eip", "advancedns", "basic", "sg"]) + @attr(tags=["advanced", "eip", "advancedns", "basic", "sg", "selfservice"]) def test_06_deploy_startvm_attach_detach(self): """Test Deploy Virtual Machine with startVM=false and attach detach volumes @@ -529,7 +542,7 @@ def test_06_deploy_startvm_attach_detach(self): self.debug("Deployed instance in account: %s" % self.account.name) - list_vm_response = list_virtual_machines( + list_vm_response = VirtualMachine.list( self.apiclient, id=self.virtual_machine.id ) @@ -567,7 +580,7 @@ def test_06_deploy_startvm_attach_detach(self): try: self.virtual_machine.attach_volume(self.apiclient, volume) except Exception as e: - self.fail("Attach volume failed!") + self.fail("Attach volume failed with Exception: %s" % e) self.debug("Detaching the disk: %s" % volume.name) self.virtual_machine.detach_volume(self.apiclient, volume) @@ -587,7 +600,7 @@ def test_06_deploy_startvm_attach_detach(self): ) return - @attr(tags = ["advanced", "eip", "advancedns", "basic", "sg"]) + @attr(tags=["advanced", "eip", "advancedns", "basic", "sg", "selfservice"]) def test_07_deploy_startvm_attach_iso(self): """Test Deploy Virtual Machine with startVM=false and attach ISO """ @@ -612,7 +625,7 @@ def test_07_deploy_startvm_attach_iso(self): self.debug("Deployed instance in account: %s" % self.account.name) - list_vm_response = list_virtual_machines( + list_vm_response = VirtualMachine.list( self.apiclient, id=self.virtual_machine.id ) @@ -678,7 +691,7 @@ def test_07_deploy_startvm_attach_iso(self): ) return - @attr(tags = ["advanced", "eip", "advancedns", "basic", "sg"]) + @attr(tags=["advanced", "eip", "advancedns", "basic", "sg", "selfservice"]) def test_08_deploy_attached_volume(self): """Test Deploy Virtual Machine with startVM=false and attach volume already attached to different machine """ @@ -703,7 +716,7 @@ def test_08_deploy_attached_volume(self): self.debug("Deployed instance in account: %s" % self.account.name) - list_vm_response = list_virtual_machines( + list_vm_response = VirtualMachine.list( self.apiclient, id=self.virtual_machine_1.id ) @@ -739,7 +752,7 @@ def test_08_deploy_attached_volume(self): self.debug("Deployed instance in account: %s" % self.account.name) - list_vm_response = list_virtual_machines( + list_vm_response = VirtualMachine.list( self.apiclient, id=self.virtual_machine_2.id ) @@ -808,7 +821,7 @@ def test_08_deploy_attached_volume(self): ) return - @attr(tags = ["advanced", "eip", "advancedns", "basic", "sg"]) + @attr(tags=["advanced", "eip", "advancedns", "basic", "sg", "selfservice"]) def test_09_stop_vm_migrate_vol(self): """Test Stopped Virtual Machine's ROOT volume migration """ @@ -869,7 +882,7 @@ def test_09_stop_vm_migrate_vol(self): self.debug("Deployed instance in account: %s" % self.account.name) - list_vm_response = list_virtual_machines( + list_vm_response = VirtualMachine.list( self.apiclient, id=self.virtual_machine.id ) @@ -890,28 +903,10 @@ def test_09_stop_vm_migrate_vol(self): "Running", "VM should be in Running state after deployment" ) - self.debug("Stopping instance: %s" % self.virtual_machine.name) - self.virtual_machine.stop(self.apiclient) - self.debug("Instance is stopped!") - self.debug( - "Verify listVirtualMachines response for virtual machine: %s" \ - % self.virtual_machine.id - ) - list_vm_response = list_virtual_machines( - self.apiclient, - id=self.virtual_machine.id - ) - self.assertEqual( - isinstance(list_vm_response, list), - True, - "Check list response returns a valid list" - ) - vm_response = list_vm_response[0] - self.assertEqual( - vm_response.state, - "Stopped", - "VM should be in Stopped state after stoping vm" - ) + try: + self.virtual_machine.stop(self.apiclient) + except Exception as e: + self.fail("failed to stop instance: %s" % e) volumes = Volume.list( self.apiclient, virtualmachineid=self.virtual_machine.id, @@ -962,14 +957,13 @@ class TestDeployHaEnabledVM(cloudstackTestCase): @classmethod def setUpClass(cls): - cls.api_client = super( - TestDeployHaEnabledVM, - cls - ).getClsTestClient().getApiClient() + cls.testClient = super(TestDeployHaEnabledVM, cls).getClsTestClient() + cls.api_client = cls.testClient.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) + cls.domain = get_domain(cls.api_client) + cls.zone = get_zone(cls.api_client, cls.testClient.getZoneForTests()) cls.template = get_template( cls.api_client, @@ -1025,7 +1019,7 @@ def tearDown(self): except Exception as e: self.debug("Warning! Exception in tearDown: %s" % e) - @attr(tags = ["advanced", "eip", "advancedns", "basic", "sg"]) + @attr(tags=["advanced", "eip", "advancedns", "basic", "sg", "selfservice"]) def test_01_deploy_ha_vm_startvm_false(self): """Test Deploy HA enabled Virtual Machine with startvm=false """ @@ -1049,7 +1043,7 @@ def test_01_deploy_ha_vm_startvm_false(self): self.debug("Deployed instance in account: %s" % self.account.name) - list_vm_response = list_virtual_machines( + list_vm_response = VirtualMachine.list( self.apiclient, id=self.virtual_machine.id ) @@ -1074,7 +1068,7 @@ def test_01_deploy_ha_vm_startvm_false(self): ) return - @attr(tags = ["advanced", "eip", "advancedns", "basic", "sg"]) + @attr(tags=["advanced", "eip", "advancedns", "basic", "sg", "selfservice"]) def test_02_deploy_ha_vm_from_iso(self): """Test Deploy HA enabled Virtual Machine from ISO """ @@ -1114,7 +1108,7 @@ def test_02_deploy_ha_vm_from_iso(self): self.debug("Deployed instance in account: %s" % self.account.name) - list_vm_response = list_virtual_machines( + list_vm_response = VirtualMachine.list( self.apiclient, id=self.virtual_machine.id ) @@ -1139,7 +1133,7 @@ def test_02_deploy_ha_vm_from_iso(self): ) return - @attr(tags = ["advanced", "eip", "advancedns", "basic", "sg"]) + @attr(tags=["advanced", "eip", "advancedns", "basic", "sg", "selfservice"]) def test_03_deploy_ha_vm_iso_startvm_false(self): """Test Deploy HA enabled Virtual Machine from ISO with startvm=false """ @@ -1163,7 +1157,7 @@ def test_03_deploy_ha_vm_iso_startvm_false(self): self.debug("Deployed instance in account: %s" % self.account.name) - list_vm_response = list_virtual_machines( + list_vm_response = VirtualMachine.list( self.apiclient, id=self.virtual_machine.id ) @@ -1194,14 +1188,13 @@ class TestRouterStateAfterDeploy(cloudstackTestCase): @classmethod def setUpClass(cls): - cls.api_client = super( - TestRouterStateAfterDeploy, - cls - ).getClsTestClient().getApiClient() + cls.testClient = super(TestRouterStateAfterDeploy, cls).getClsTestClient() + cls.api_client = cls.testClient.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) + cls.domain = get_domain(cls.api_client) + cls.zone = get_zone(cls.api_client, cls.testClient.getZoneForTests()) cls.template = get_template( cls.api_client, @@ -1256,7 +1249,7 @@ def tearDown(self): except Exception as e: self.debug("Warning! Exception in tearDown: %s" % e) - @attr(tags = ["advanced", "eip", "advancedns"]) + @attr(tags=["advanced", "eip", "advancedns", "selfservice"]) def test_01_deploy_vm_no_startvm(self): """Test Deploy Virtual Machine with no startVM parameter """ @@ -1281,7 +1274,7 @@ def test_01_deploy_vm_no_startvm(self): self.debug("Deployed instance in account: %s" % self.account.name) - list_vm_response = list_virtual_machines( + list_vm_response = VirtualMachine.list( self.apiclient, id=self.virtual_machine_1.id ) @@ -1331,7 +1324,7 @@ def test_01_deploy_vm_no_startvm(self): self.debug("Deployed instance in account: %s" % self.account.name) - list_vm_response = list_virtual_machines( + list_vm_response = VirtualMachine.list( self.apiclient, id=self.virtual_machine_2.id ) @@ -1378,11 +1371,11 @@ def test_01_deploy_vm_no_startvm(self): self.virtual_machine_2.delete(self.apiclient) self.debug("Instance destroyed..waiting till expunge interval") - interval = list_configurations( + interval = Configurations.list( self.apiclient, name='expunge.interval' ) - delay = list_configurations( + delay = Configurations.list( self.apiclient, name='expunge.delay' ) @@ -1409,14 +1402,13 @@ class TestDeployVMBasicZone(cloudstackTestCase): @classmethod def setUpClass(cls): - cls.api_client = super( - TestDeployVMBasicZone, - cls - ).getClsTestClient().getApiClient() + cls.testClient = super(TestDeployVMBasicZone, cls).getClsTestClient() + cls.api_client = cls.testClient.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) + cls.domain = get_domain(cls.api_client) + cls.zone = get_zone(cls.api_client, cls.testClient.getZoneForTests()) cls.template = get_template( cls.api_client, @@ -1477,14 +1469,13 @@ class TestDeployVMFromTemplate(cloudstackTestCase): @classmethod def setUpClass(cls): - cls.api_client = super( - TestDeployVMFromTemplate, - cls - ).getClsTestClient().getApiClient() + cls.testClient = super(TestDeployVMFromTemplate, cls).getClsTestClient() + cls.api_client = cls.testClient.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) + cls.domain = get_domain(cls.api_client) + cls.zone = get_zone(cls.api_client, cls.testClient.getZoneForTests()) # Create service, disk offerings etc cls.service_offering = ServiceOffering.create( @@ -1511,8 +1502,8 @@ def tearDownClass(cls): raise Exception("Warning: Exception during cleanup : %s" % e) def setUp(self): - self.apiclient = self.testClient.getApiClient() + self.hypervisor = self.testClient.getHypervisorInfo() self.dbclient = self.testClient.getDbConnection() self.services = Services().services self.services["virtual_machine"]["zoneid"] = self.zone.id @@ -1523,8 +1514,8 @@ def setUp(self): ) builtin_info = get_builtin_template_info(self.apiclient, self.zone.id) - self.services["template"]["url"] = builtin_info[0] - self.services["template"]["hypervisor"] = builtin_info[1] + self.services["template"]["url"] = builtin_info[0] + self.services["template"]["hypervisor"] = builtin_info[1] self.services["template"]["format"] = builtin_info[2] # Register new template @@ -1533,7 +1524,8 @@ def setUp(self): self.services["template"], zoneid=self.zone.id, account=self.account.name, - domainid=self.account.domainid + domainid=self.account.domainid, + hypervisor=self.hypervisor ) self.debug( "Registered a template of format: %s with ID: %s" % ( @@ -1556,7 +1548,7 @@ def tearDown(self): except Exception as e: self.debug("Warning! Exception in tearDown: %s" % e) - @attr(tags = ["advanced", "eip", "advancedns", "basic", "sg"]) + @attr(tags=["advanced", "eip", "advancedns", "basic", "sg", "provisioning"]) def test_deploy_vm_password_enabled(self): """Test Deploy Virtual Machine with startVM=false & enabledpassword in template @@ -1582,7 +1574,7 @@ def test_deploy_vm_password_enabled(self): self.debug("Deployed instance in account: %s" % self.account.name) - list_vm_response = list_virtual_machines( + list_vm_response = VirtualMachine.list( self.apiclient, id=self.virtual_machine.id ) @@ -1609,7 +1601,7 @@ def test_deploy_vm_password_enabled(self): self.virtual_machine.start(self.apiclient) self.debug("Started the instance: %s" % self.virtual_machine.name) - list_vm_response = list_virtual_machines( + list_vm_response = VirtualMachine.list( self.apiclient, id=self.virtual_machine.id ) @@ -1638,14 +1630,13 @@ class TestVMAccountLimit(cloudstackTestCase): @classmethod def setUpClass(cls): - cls.api_client = super( - TestVMAccountLimit, - cls - ).getClsTestClient().getApiClient() + cls.testClient = super(TestVMAccountLimit, cls).getClsTestClient() + cls.api_client = cls.testClient.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) + cls.domain = get_domain(cls.api_client) + cls.zone = get_zone(cls.api_client, cls.testClient.getZoneForTests()) cls.template = get_template( cls.api_client, @@ -1694,7 +1685,7 @@ def tearDown(self): raise Exception("Warning: Exception during cleanup : %s" % e) return - @attr(tags = ["advanced", "eip", "advancedns", "basic", "sg"]) + @attr(tags=["advanced", "eip", "advancedns", "basic", "sg", "selfservice"]) def test_vm_per_account(self): """Test VM limit per account """ @@ -1754,14 +1745,13 @@ class TestUploadAttachVolume(cloudstackTestCase): @classmethod def setUpClass(cls): - cls.api_client = super( - TestUploadAttachVolume, - cls - ).getClsTestClient().getApiClient() + cls.testClient = super(TestUploadAttachVolume, cls).getClsTestClient() + cls.api_client = cls.testClient.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) + cls.domain = get_domain(cls.api_client) + cls.zone = get_zone(cls.api_client, cls.testClient.getZoneForTests()) cls.template = get_template( cls.api_client, @@ -1810,7 +1800,7 @@ def tearDown(self): raise Exception("Warning: Exception during cleanup : %s" % e) return - @attr(tags = ["advanced", "eip", "advancedns", "basic", "sg"]) + @attr(tags=["advanced", "eip", "advancedns", "basic", "sg", "selfservice"]) def test_upload_attach_volume(self): """Test Upload volume and attach to VM in stopped state """ @@ -1864,14 +1854,13 @@ class TestDeployOnSpecificHost(cloudstackTestCase): @classmethod def setUpClass(cls): - cls.api_client = super( - TestDeployOnSpecificHost, - cls - ).getClsTestClient().getApiClient() + cls.testClient = super(TestDeployOnSpecificHost, cls).getClsTestClient() + cls.api_client = cls.testClient.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) + cls.domain = get_domain(cls.api_client) + cls.zone = get_zone(cls.api_client, cls.testClient.getZoneForTests()) cls.template = get_template( cls.api_client, cls.zone.id, diff --git a/test/integration/component/test_storage_motion.py b/test/integration/component/test_storage_motion.py index 194ba97709..5b9086bdc3 100644 --- a/test/integration/component/test_storage_motion.py +++ b/test/integration/component/test_storage_motion.py @@ -20,9 +20,9 @@ import marvin 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.lib.utils import * +from marvin.lib.base import * +from marvin.lib.common import * from nose.plugins.attrib import attr #Import System modules import time @@ -89,12 +89,13 @@ class TestStorageMotion(cloudstackTestCase): @classmethod def setUpClass(cls): - cls.api_client = super(TestStorageMotion, cls).getClsTestClient().getApiClient() - cls.services = Services().services + cls.testClient = super(TestStorageMotion, cls).getClsTestClient() + cls.api_client = cls.testClient.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) + domain = get_domain(cls.api_client) + cls.zone = get_zone(cls.api_client, cls.testClient.getZoneForTests()) cls.services['mode'] = cls.zone.networktype template = get_template( @@ -148,7 +149,7 @@ def tearDown(self): cleanup_resources(self.apiclient, self.cleanup) return - @attr(tags = ["advanced", "basic", "multicluster", "storagemotion", "xenserver"]) + @attr(tags=["advanced", "basic", "multicluster", "storagemotion", "xenserver", "provisioning"]) def test_01_migrate_vm_with_volume(self): """Test migrate virtual machine with its volumes """ @@ -226,7 +227,7 @@ def test_01_migrate_vm_with_volume(self): ) return - @attr(tags = ["advanced", "basic", "multipool", "storagemotion", "xenserver"]) + @attr(tags=["advanced", "basic", "multipool", "storagemotion", "xenserver", "selfservice"]) def test_02_migrate_volume(self): """Test migrate volume of a running vm """ diff --git a/test/integration/component/test_tags.py b/test/integration/component/test_tags.py index 2a6e0764f2..fbe64367bf 100644 --- a/test/integration/component/test_tags.py +++ b/test/integration/component/test_tags.py @@ -17,15 +17,31 @@ """ P1 tests for tags """ #Import Local Modules -import marvin from nose.plugins.attrib import attr -from marvin.cloudstackTestCase import * -from marvin.cloudstackAPI import * -from marvin.integration.lib.utils import * -from marvin.integration.lib.base import * -from marvin.integration.lib.common import * -import datetime - +from marvin.cloudstackTestCase import cloudstackTestCase +from marvin.lib.utils import cleanup_resources +from marvin.lib.base import (Tag, + Account, + VirtualMachine, + Iso, + Volume, + Network, + Host, + DiskOffering, + NATRule, + PublicIPAddress, + FireWallRule, + LoadBalancerRule, + Vpn, + Template, + Snapshot, + ServiceOffering, + Project) +from marvin.lib.common import (get_zone, + get_domain, + get_template) +from marvin.codes import FAILED +import time class Services: """Test tags Services @@ -174,30 +190,28 @@ class TestResourceTags(cloudstackTestCase): @classmethod def setUpClass(cls): - cls.api_client = super( - TestResourceTags, - cls - ).getClsTestClient().getApiClient() + cls.testClient = super(TestResourceTags, cls).getClsTestClient() + cls.api_client = cls.testClient.getApiClient() + cls.services = Services().services - # Get Zone - cls.zone = get_zone(cls.api_client, cls.services) - # 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, - ) - cls.zone = get_zone(cls.api_client, cls.services) + # Get Zone, Domain and templates + cls.zone = get_zone(cls.api_client, cls.testClient.getZoneForTests()) + cls.domain = get_domain(cls.api_client) cls.template = get_template( cls.api_client, cls.zone.id, cls.services["ostype"] ) + if cls.template == FAILED: + assert False, "get_template() failed to return template with description %s" % cls.services["ostype"] + cls.account = Account.create( + cls.api_client, + cls.services["account"], + admin=True, + ) # Create service offerings, disk offerings etc cls.service_offering = ServiceOffering.create( cls.api_client, @@ -266,7 +280,7 @@ def tearDown(self): return - @attr(tags=["advanced"]) + @attr(tags=["advanced", "selfservice"]) def test_01_lbrule_tag(self): """ Test Create tag on LB rule and remove the LB rule """ @@ -409,7 +423,7 @@ def test_01_lbrule_tag(self): self.fail("failed to delete load balancer rule! - %s" % e) return - @attr(tags=["advanced"]) + @attr(tags=["advanced", "selfservice"]) def test_02_natrule_tag(self): """ Test Create tag on nat rule and remove the nat rule """ @@ -546,7 +560,7 @@ def test_02_natrule_tag(self): self.fail("failed to delete port forwarding rule! - %s" % e) return - @attr(tags=["advanced"]) + @attr(tags=["advanced", "selfservice"]) def test_03_firewallrule_tag(self): """ Test Create tag on firewall rule and remove the firewall rule """ @@ -689,7 +703,7 @@ def test_03_firewallrule_tag(self): self.fail("failed to delete firewall rule! - %s" % e) return - @attr(tags=["advanced"]) + @attr(tags=["advanced", "selfservice"]) def test_04_vpn_tag(self): """ Test Create tag on vpn and remove the vpn """ @@ -841,7 +855,7 @@ def test_04_vpn_tag(self): self.fail("failed to disable VPN! - %s" % e) return - @attr(tags=["advanced", "basic"]) + @attr(tags=["advanced", "basic", "selfservice"]) def test_05_vm_tag(self): """ Test creation, listing and deletion tags on UserVM """ @@ -918,7 +932,7 @@ def test_05_vm_tag(self): ) return - @attr(tags=["advanced", "basic"]) + @attr(tags=["advanced", "basic", "selfservice"]) def test_06_template_tag(self): """ Test creation, listing and deletion tag on templates """ @@ -926,14 +940,14 @@ def test_06_template_tag(self): # 1. Create a tag on template/ISO using createTags API # 2. Delete above created tag using deleteTags API - self.debug("Stopping the virtual machine: %s" % self.vm_1.name) - #Stop virtual machine - self.vm_1.stop(self.apiclient) + try: + self.debug("Stopping the virtual machine: %s" % self.vm_1.name) + #Stop virtual machine + self.vm_1.stop(self.apiclient) + except Exception as e: + self.fail("Failed to stop VM: %s" % e) timeout = self.services["timeout"] - #Wait before server has be successfully stopped - time.sleep(self.services["sleep"]) - while True: list_volume = Volume.list( self.apiclient, @@ -992,11 +1006,11 @@ def test_06_template_tag(self): 'CentOS', 'The tag should have original value' ) - - templates = Template.list( + + Template.list( self.apiclient, templatefilter=\ - self.services["template"]["templatefilter"], + self.services["template"]["templatefilter"], listall=True, key='OS', value='CentOS' @@ -1030,7 +1044,7 @@ def test_06_template_tag(self): ) return - @attr(tags=["advanced", "basic"]) + @attr(tags=["advanced", "basic", "selfservice"]) def test_07_iso_tag(self): """ Test creation, listing and deletion tags on ISO """ @@ -1046,10 +1060,8 @@ def test_07_iso_tag(self): ) self.debug("ISO created with ID: %s" % iso.id) - list_iso_response = list_isos( - self.apiclient, - id=iso.id - ) + list_iso_response = Iso.list(self.apiclient, + id=iso.id) self.assertEqual( isinstance(list_iso_response, list), True, @@ -1127,7 +1139,7 @@ def test_07_iso_tag(self): ) return - @attr(tags=["advanced", "basic"]) + @attr(tags=["advanced", "basic", "selfservice"]) def test_08_volume_tag(self): """ Test creation, listing and deletion tagson volume """ @@ -1216,7 +1228,7 @@ def test_08_volume_tag(self): ) return - @attr(tags=["advanced", "basic"]) + @attr(tags=["advanced", "basic", "selfservice"]) def test_09_snapshot_tag(self): """ Test creation, listing and deletion tag son snapshot """ @@ -1227,12 +1239,10 @@ def test_09_snapshot_tag(self): self.debug("Creating snapshot on ROOT volume for VM: %s " % self.vm_1.name) # Get the Root disk of VM - volumes = list_volumes( - self.apiclient, - virtualmachineid=self.vm_1.id, - type='ROOT', - listall=True - ) + volumes = Volume.list(self.apiclient, + virtualmachineid=self.vm_1.id, + type='ROOT', + listall=True) volume = volumes[0] # Create a snapshot from the ROOTDISK @@ -1240,10 +1250,8 @@ def test_09_snapshot_tag(self): self.debug("Snapshot created: ID - %s" % snapshot.id) self.cleanup.append(snapshot) - snapshots = list_snapshots( - self.apiclient, - id=snapshot.id - ) + snapshots = Snapshot.list(self.apiclient, + id=snapshot.id) self.assertEqual( isinstance(snapshots, list), True, @@ -1277,13 +1285,10 @@ def test_09_snapshot_tag(self): 'manual', 'The tag should have original value' ) - - snapshots = list_snapshots( - self.apiclient, - listall=True, - key='type', - value='manual' - ) + snapshots = Snapshot.list(self.apiclient, + listall=True, + key='type', + value='manual') self.assertEqual( isinstance(snapshots, list), True, @@ -1325,7 +1330,7 @@ def test_09_snapshot_tag(self): return - @attr(tags=["advanced"]) + @attr(tags=["advanced", "selfservice"]) def test_10_network_tag(self): """ Testcreation, listing and deletion tags on guest network """ @@ -1527,7 +1532,7 @@ def test_11_migrate_tagged_vm_del(self): ) return - @attr(tags=["advanced", "basic"]) + @attr(tags=["advanced", "basic", "selfservice"]) def test_13_tag_case_insensitive(self): """ Test to verify that tags are not case sensitive """ @@ -1565,21 +1570,16 @@ def test_13_tag_case_insensitive(self): 'India', 'The tag should have original value' ) - self.debug("Creating the same tag with caps for user VM") - try: - tag_2 = Tag.create( - self.apiclient, - resourceIds=self.vm_1.id, - resourceType='userVM', - tags={'REGION': 'INDIA'} - ) + Tag.create(self.apiclient, + resourceIds=self.vm_1.id, + resourceType='userVM', + tags={'REGION': 'INDIA'}) except Exception as e: pass else: assert("Creating same tag in upper case succeeded") - self.debug("Deleting the created tag..") try: tag_1.delete( self.apiclient, @@ -1608,7 +1608,7 @@ def test_13_tag_case_insensitive(self): return - @attr(tags=["advanced", "basic"]) + @attr(tags=["advanced", "basic", "selfservice"]) def test_14_special_char_mutiple_tags(self): """ Test multiple tags and with special characters on same machine """ @@ -1677,7 +1677,7 @@ def test_14_special_char_mutiple_tags(self): ) return - @attr(tags=["advanced"]) + @attr(tags=["advanced", "selfservice"]) def test_15_project_tag(self): """ Test creation, listing and deletion tags on projects """ @@ -1769,7 +1769,7 @@ def test_15_project_tag(self): ) return - @attr(tags=["advanced", "basic"]) + @attr(tags=["advanced", "basic", "selfservice"]) def test_16_query_tags_other_account(self): """ Test Query the tags from other account """ @@ -1787,14 +1787,14 @@ def test_16_query_tags_other_account(self): domainid=self.domain.id ) self.cleanup.append(user_account) - + other_user_account = Account.create( self.apiclient, self.services["other_user"], domainid=self.domain.id ) self.cleanup.append(other_user_account) - + iso = Iso.create( self.apiclient, self.services["iso"], @@ -1803,10 +1803,8 @@ def test_16_query_tags_other_account(self): ) self.debug("ISO created with ID: %s" % iso.id) - list_iso_response = list_isos( - self.apiclient, - id=iso.id - ) + list_iso_response = Iso.list(self.apiclient, + id=iso.id) self.assertEqual( isinstance(list_iso_response, list), True, @@ -1830,8 +1828,6 @@ def test_16_query_tags_other_account(self): domainid=user_account.domainid, key='region', ) - - self.debug("Verify listTag API using user account") self.assertEqual( isinstance(tags, list), True, @@ -1861,7 +1857,7 @@ def test_16_query_tags_other_account(self): return - @attr(tags=["advanced", "basic"]) + @attr(tags=["advanced", "basic", "selfservice"]) def test_17_query_tags_admin_account(self): """ Test Query the tags from admin account """ @@ -1879,33 +1875,25 @@ def test_17_query_tags_admin_account(self): domainid=self.domain.id ) self.cleanup.append(user_account) - + iso = Iso.create( self.apiclient, self.services["iso"], account=user_account.name, domainid=user_account.domainid ) - self.debug("ISO created with ID: %s" % iso.id) - list_iso_response = list_isos( - self.apiclient, - id=iso.id - ) + list_iso_response = Iso.list(self.apiclient, + id=iso.id) self.assertEqual( isinstance(list_iso_response, list), True, "Check list response returns a valid list" ) - - self.debug("Creating a tag for the ISO") - tag = Tag.create( - self.apiclient, - resourceIds=iso.id, - resourceType='ISO', - tags={'region': 'India'} - ) - self.debug("Tag created: %s" % tag.__dict__) + Tag.create(self.apiclient, + resourceIds=iso.id, + resourceType='ISO', + tags={'region': 'India'}) tags = Tag.list( self.apiclient, @@ -1915,8 +1903,6 @@ def test_17_query_tags_admin_account(self): domainid=user_account.domainid, key='region', ) - - self.debug("Verify listTag API using user account") self.assertEqual( isinstance(tags, list), True, @@ -1948,7 +1934,7 @@ def test_17_query_tags_admin_account(self): return - @attr(tags=["advanced", "basic", "simulator"]) + @attr(tags=["advanced", "basic", "simulator", "selfservice"]) def test_18_invalid_list_parameters(self): """ Test listAPI with invalid tags parameter """ @@ -1987,7 +1973,7 @@ def test_18_invalid_list_parameters(self): return - @attr(tags=["advanced", "basic"]) + @attr(tags=["advanced", "basic", "selfservice"]) def test_19_delete_add_same_tag(self): """ Test deletion and addition of same tag on a resource. """ @@ -2093,7 +2079,7 @@ def test_19_delete_add_same_tag(self): self.fail("Failed to delete the tag - %s" % e) return - @attr(tags=["advanced", "basic"]) + @attr(tags=["advanced", "basic", "selfservice"]) def test_20_create_tags_multiple_resources(self): "Test creation of same tag on multiple resources" @@ -2198,51 +2184,25 @@ def test_20_create_tags_multiple_resources(self): return - @attr(tags=["advanced", "basic"]) + @attr(tags=["advanced", "basic", "selfservice"]) def test_21_create_tag_stopped_vm(self): "Test creation of tag on stopped vm." - self.debug("Stopping the virtual machine: %s" % self.vm_1.name) - #Stop virtual machine - self.vm_1.stop(self.apiclient) - - timeout = self.services["timeout"] - #Wait before server has be successfully stopped - time.sleep(self.services["sleep"]) - - list_vm_response = list_virtual_machines( - self.apiclient, - id=self.vm_1.id - ) - - self.debug( - "Verify listVirtualMachines response for virtual machine: %s" \ - % self.vm_1.id - ) - - self.assertEqual( - isinstance(list_vm_response, list), - True, - "Check list response returns a valid list" - ) - vm_response = list_vm_response[0] - - self.assertEqual( - vm_response.state, - "Stopped", - "VM should be in stopped state after deployment" - ) + try: + self.debug("Stopping the virtual machine: %s" % self.vm_1.name) + #Stop virtual machine + self.vm_1.stop(self.apiclient) - self.debug("Creating a tag for user VM") - tag = Tag.create( + self.debug("Creating a tag for user VM") + tag = Tag.create( self.apiclient, resourceIds=self.vm_1.id, resourceType='userVM', tags={'region': 'India'} ) - self.debug("Tag created: %s" % tag.__dict__) + self.debug("Tag created: %s" % tag.__dict__) - tags = Tag.list( + tags = Tag.list( self.apiclient, listall=True, resourceType='userVM', @@ -2251,20 +2211,19 @@ def test_21_create_tag_stopped_vm(self): key='region', value='India' ) - self.assertEqual( + self.assertEqual( isinstance(tags, list), True, "List tags should not return empty response" ) - self.assertEqual( + self.assertEqual( tags[0].value, "India", "Tag created with incorrect value" ) - self.debug("Deleting the created tag..") - try: + self.debug("Deleting the created tag..") tag.delete( self.apiclient, resourceIds=self.vm_1.id, @@ -2272,10 +2231,10 @@ def test_21_create_tag_stopped_vm(self): tags={'region': 'India'} ) except Exception as e: - self.fail("Failed to delete the tag - %s" % e) + self.fail("Exception occured - %s" % e) return - @attr(tags=["advanced", "basic"]) + @attr(tags=["advanced", "basic", "selfservice"]) def test_22_create_tag_destroyed_vm(self): "Test creation of tag on stopped vm." diff --git a/test/integration/component/test_templates.py b/test/integration/component/test_templates.py index 3e836157ac..19852643d6 100644 --- a/test/integration/component/test_templates.py +++ b/test/integration/component/test_templates.py @@ -5,9 +5,9 @@ # 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 @@ -17,15 +17,20 @@ """ P1 tests for Templates """ #Import Local Modules -import marvin from nose.plugins.attrib import attr -from marvin.cloudstackTestCase import * -from marvin.cloudstackAPI import * -from marvin.integration.lib.utils import * -from marvin.integration.lib.base import * -from marvin.integration.lib.common import * -import urllib -from random import random +from marvin.cloudstackTestCase import cloudstackTestCase, unittest +from marvin.cloudstackAPI import listZones +from marvin.lib.utils import (cleanup_resources) +from marvin.lib.base import (Account, + Template, + ServiceOffering, + VirtualMachine, + Snapshot, + Volume) +from marvin.lib.common import (get_domain, + get_zone, + get_template, + get_builtin_template_info) #Import System modules import time @@ -101,8 +106,8 @@ def __init__(self): class TestCreateTemplate(cloudstackTestCase): def setUp(self): - self.apiclient = self.testClient.getApiClient() + self.hypervisor = self.testClient.getHypervisorInfo() self.dbclient = self.testClient.getDbConnection() self.cleanup = [] return @@ -118,12 +123,13 @@ def tearDown(self): @classmethod def setUpClass(cls): - cls.services = Services().services - cls.api_client = super(TestCreateTemplate, cls).getClsTestClient().getApiClient() + cls.testClient = super(TestCreateTemplate, cls).getClsTestClient() + cls.api_client = cls.testClient.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) + cls.domain = get_domain(cls.api_client) + cls.zone = get_zone(cls.api_client, cls.testClient.getZoneForTests()) cls.services['mode'] = cls.zone.networktype cls.services["virtual_machine"]["zoneid"] = cls.zone.id @@ -156,7 +162,7 @@ def tearDownClass(cls): return - @attr(tags = ["advanced", "advancedns"]) + @attr(tags=["advanced", "advancedns", "provisioning"]) def test_01_create_template(self): """Test create public & private template """ @@ -184,7 +190,8 @@ def test_01_create_template(self): self.services["templates"][0], zoneid=self.zone.id, account=self.account.name, - domainid=self.account.domainid + domainid=self.account.domainid, + hypervisor=self.hypervisor ) self.debug( "Registered a template of format: %s with ID: %s" % ( @@ -199,14 +206,13 @@ def test_01_create_template(self): time.sleep(self.services["sleep"]) timeout = self.services["timeout"] while True: - list_template_response = list_templates( - self.apiclient, - templatefilter='all', - id=template.id, - zoneid=self.zone.id, - account=self.account.name, - domainid=self.account.domainid - ) + list_template_response = Template.list( + self.apiclient, + templatefilter='all', + id=template.id, + zoneid=self.zone.id, + account=self.account.name, + domainid=self.account.domainid) if isinstance(list_template_response, list): break elif timeout == 0: @@ -245,12 +251,10 @@ def test_01_create_template(self): mode=self.services["mode"] ) self.debug("creating an instance with template ID: %s" % template.id) - vm_response = list_virtual_machines( - self.apiclient, - id=virtual_machine.id, - account=self.account.name, - domainid=self.account.domainid - ) + vm_response = VirtualMachine.list(self.apiclient, + id=virtual_machine.id, + account=self.account.name, + domainid=self.account.domainid) self.assertEqual( isinstance(vm_response, list), True, @@ -276,12 +280,13 @@ class TestTemplates(cloudstackTestCase): @classmethod def setUpClass(cls): - cls.services = Services().services - cls.api_client = super(TestTemplates, cls).getClsTestClient().getApiClient() + cls.testClient = super(TestTemplates, cls).getClsTestClient() + cls.api_client = cls.testClient.getApiClient() - # Get Zone, templates etc - cls.domain = get_domain(cls.api_client, cls.services) - cls.zone = get_zone(cls.api_client, cls.services) + cls.services = Services().services + # Get Zone, Domain and templates + cls.domain = get_domain(cls.api_client) + cls.zone = get_zone(cls.api_client, cls.testClient.getZoneForTests()) cls.services['mode'] = cls.zone.networktype #populate second zone id for iso copy cmd = listZones.listZonesCmd() @@ -297,20 +302,24 @@ def setUpClass(cls): cls.services["ostype"] ) cls.services["virtual_machine"]["zoneid"] = cls.zone.id - cls.account = Account.create( + cls._cleanup = [] + try: + cls.account = Account.create( cls.api_client, cls.services["account"], domainid=cls.domain.id ) + cls._cleanup.append(cls.account) - cls.services["account"] = cls.account.name - cls.service_offering = ServiceOffering.create( + cls.services["account"] = cls.account.name + cls.service_offering = ServiceOffering.create( cls.api_client, cls.services["service_offering"] ) + cls._cleanup.append(cls.service_offering) - # create virtual machine - cls.virtual_machine = VirtualMachine.create( + # create virtual machine + cls.virtual_machine = VirtualMachine.create( cls.api_client, cls.services["virtual_machine"], templateid=template.id, @@ -318,40 +327,36 @@ def setUpClass(cls): domainid=cls.account.domainid, serviceofferingid=cls.service_offering.id, ) - #Stop virtual machine - cls.virtual_machine.stop(cls.api_client) + #Stop virtual machine + cls.virtual_machine.stop(cls.api_client) - timeout = cls.services["timeout"] - #Wait before server has be successfully stopped - time.sleep(cls.services["sleep"]) + timeout = cls.services["timeout"] - while True: - list_volume = list_volumes( - cls.api_client, - virtualmachineid=cls.virtual_machine.id, - type='ROOT', - listall=True - ) - if isinstance(list_volume, list): - break - elif timeout == 0: - raise Exception("List volumes failed.") + while True: + list_volume = Volume.list( + cls.api_client, + virtualmachineid=cls.virtual_machine.id, + type='ROOT', + listall=True) + if isinstance(list_volume, list): + break + elif timeout == 0: + raise Exception("List volumes failed.") - time.sleep(5) - timeout = timeout - 1 + time.sleep(5) + timeout = timeout - 1 - cls.volume = list_volume[0] + cls.volume = list_volume[0] - #Create template from volume - cls.template = Template.create( + #Create template from volume + cls.template = Template.create( cls.api_client, cls.services["template"], cls.volume.id ) - cls._cleanup = [ - cls.service_offering, - cls.account, - ] + except Exception as e: + cls.tearDownClass() + raise unittest.SkipTest("Failure in setUpClass: %s" % e) @classmethod def tearDownClass(cls): @@ -382,7 +387,7 @@ def tearDown(self): return - @attr(tags = ["advanced", "advancedns"]) + @attr(tags=["advanced", "advancedns", "selfservice"]) def test_01_create_template_volume(self): """Test Create template from volume """ @@ -402,12 +407,11 @@ def test_01_create_template_volume(self): self.debug("creating an instance with template ID: %s" % self.template.id) self.cleanup.append(virtual_machine) - vm_response = list_virtual_machines( - self.apiclient, - id=virtual_machine.id, - account=self.account.name, - domainid=self.account.domainid - ) + vm_response = VirtualMachine.list( + self.apiclient, + id=virtual_machine.id, + account=self.account.name, + domainid=self.account.domainid) #Verify VM response to check whether VM deployment was successful self.assertNotEqual( len(vm_response), @@ -422,7 +426,7 @@ def test_01_create_template_volume(self): ) return - @attr(tags = ["advanced", "advancedns"]) + @attr(tags=["advanced", "advancedns", "selfservice"]) def test_03_delete_template(self): """Test Delete template """ @@ -432,13 +436,12 @@ def test_03_delete_template(self): # 2. Delete the created template and again verify list template response # Verify template response for updated attributes - list_template_response = list_templates( + list_template_response = Template.list( self.apiclient, templatefilter=\ self.services["template"]["templatefilter"], id=self.template.id, - zoneid=self.zone.id - ) + zoneid=self.zone.id) self.assertEqual( isinstance(list_template_response, list), True, @@ -464,7 +467,7 @@ def test_03_delete_template(self): self.template.delete(self.apiclient) self.debug("Delete template: %s successful" % self.template) - list_template_response = list_templates( + list_template_response = Template.list( self.apiclient, templatefilter=\ self.services["template"]["templatefilter"], @@ -479,7 +482,7 @@ def test_03_delete_template(self): return @attr(speed = "slow") - @attr(tags = ["advanced", "advancedns"]) + @attr(tags=["advanced", "advancedns", "selfservice"]) def test_04_template_from_snapshot(self): """Create Template from snapshot """ @@ -490,7 +493,7 @@ def test_04_template_from_snapshot(self): # 4. Deploy Virtual machine using this template # 5. VM should be in running state - volumes = list_volumes( + volumes = Volume.list( self.apiclient, virtualmachineid=self.virtual_machine.id, type='ROOT', @@ -515,7 +518,7 @@ def test_04_template_from_snapshot(self): ) self.cleanup.append(template) # Verify created template - templates = list_templates( + templates = Template.list( self.apiclient, templatefilter=\ self.services["template"]["templatefilter"], @@ -544,7 +547,7 @@ def test_04_template_from_snapshot(self): ) self.cleanup.append(virtual_machine) - vm_response = list_virtual_machines( + vm_response = VirtualMachine.list( self.apiclient, id=virtual_machine.id, account=self.account.name, diff --git a/test/integration/component/test_update_vm.py b/test/integration/component/test_update_vm.py index 0786310e19..1c5c236250 100644 --- a/test/integration/component/test_update_vm.py +++ b/test/integration/component/test_update_vm.py @@ -17,9 +17,9 @@ from marvin.cloudstackTestCase import cloudstackTestCase -from marvin.integration.lib.base import Account, VirtualMachine, ServiceOffering -from marvin.integration.lib.utils import cleanup_resources -from marvin.integration.lib.common import get_zone, get_domain, get_template +from marvin.lib.base import Account, VirtualMachine, ServiceOffering +from marvin.lib.utils import cleanup_resources +from marvin.lib.common import get_zone, get_domain, get_template from nose.plugins.attrib import attr class TestData(object): @@ -61,8 +61,8 @@ def setUp(self): self.apiclient = self.testClient.getApiClient() # Get Zone, Domain and Default Built-in template - self.domain = get_domain(self.apiclient, self.testdata) - self.zone = get_zone(self.apiclient, self.testdata) + self.domain = get_domain(self.apiclient) + self.zone = get_zone(self.apiclient, self.testClient.getZoneForTests()) self.testdata["mode"] = self.zone.networktype self.template = get_template(self.apiclient, self.zone.id, self.testdata["ostype"]) @@ -83,7 +83,7 @@ def setUp(self): self.account ] - @attr(tags = ['advanced', 'simulator', 'basic', 'sg']) + @attr(tags=['advanced', 'simulator', 'basic', 'sg', "selfservice"]) def test_update_vm_name(self): """Test Update VirtualMachine Name @@ -156,4 +156,4 @@ def tearDown(self): try: cleanup_resources(self.apiclient, self.cleanup) except Exception as e: - self.debug("Warning! Exception in tearDown: %s" % e) \ No newline at end of file + self.debug("Warning! Exception in tearDown: %s" % e) diff --git a/test/integration/component/test_usage.py b/test/integration/component/test_usage.py index 5979a0a495..03823bed91 100644 --- a/test/integration/component/test_usage.py +++ b/test/integration/component/test_usage.py @@ -5,9 +5,9 @@ # 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 @@ -17,16 +17,27 @@ """ P1 tests for Snapshots """ #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.sshClient import SshClient -import datetime - +from marvin.cloudstackTestCase import cloudstackTestCase, unittest +from marvin.cloudstackAPI import deleteVolume +from marvin.lib.utils import (cleanup_resources) +from marvin.lib.base import (Account, + ServiceOffering, + NATRule, + VirtualMachine, + Snapshot, + Iso, + ImageStore, + LoadBalancerRule, + PublicIPAddress, + DiskOffering, + Template, + VpnUser, + Vpn, + Volume) +from marvin.lib.common import (get_zone, + get_domain, + get_template) class Services: """Test Snapshots Services @@ -112,11 +123,13 @@ class TestVmUsage(cloudstackTestCase): @classmethod def setUpClass(cls): - cls.api_client = super(TestVmUsage, cls).getClsTestClient().getApiClient() + cls.testClient = super(TestVmUsage, cls).getClsTestClient() + cls.api_client = cls.testClient.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) + cls.domain = get_domain(cls.api_client) + cls.zone = get_zone(cls.api_client, cls.testClient.getZoneForTests()) cls.services['mode'] = cls.zone.networktype template = get_template( @@ -178,7 +191,7 @@ def tearDown(self): raise Exception("Warning: Exception during cleanup : %s" % e) return - @attr(tags = ["advanced", "basic", "sg", "eip", "advancedns", "simulator"]) + @attr(tags=["advanced", "basic", "sg", "eip", "advancedns", "simulator", "selfservice"]) def test_01_vm_usage(self): """Test Create/Destroy VM and verify usage calculation """ @@ -191,14 +204,19 @@ def test_01_vm_usage(self): # VM.Destroy and volume .delete Event for the created account # 4. Delete the account - self.debug("Stopping the VM: %s" % self.virtual_machine.id) - # Stop the VM - self.virtual_machine.stop(self.apiclient) + try: + self.debug("Stopping the VM: %s" % self.virtual_machine.id) + # Stop the VM + self.virtual_machine.stop(self.apiclient) + except Exception as e: + self.fail("Failed to stop instance: %s" % e) - time.sleep(self.services["sleep"]) - # Destroy the VM - self.debug("Destroying the VM: %s" % self.virtual_machine.id) - self.virtual_machine.delete(self.apiclient) + try: + # Destroy the VM + self.debug("Destroying the VM: %s" % self.virtual_machine.id) + self.virtual_machine.delete(self.apiclient) + except Exception as e: + self.fail("Failed to destroy VM: %s" % e) # Fetch account ID from account_uuid self.debug("select id from account where uuid = '%s';" \ @@ -296,11 +314,13 @@ class TestPublicIPUsage(cloudstackTestCase): @classmethod def setUpClass(cls): - cls.api_client = super(TestPublicIPUsage, cls).getClsTestClient().getApiClient() + cls.testClient = super(TestPublicIPUsage, cls).getClsTestClient() + cls.api_client = cls.testClient.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) + cls.domain = get_domain(cls.api_client) + cls.zone = get_zone(cls.api_client, cls.testClient.getZoneForTests()) cls.services['mode'] = cls.zone.networktype template = get_template( @@ -370,7 +390,7 @@ def tearDown(self): raise Exception("Warning: Exception during cleanup : %s" % e) return - @attr(tags = ["advanced", "eip", "advancedns", "simulator"]) + @attr(tags=["advanced", "eip", "advancedns", "simulator", "selfservice"]) def test_01_public_ip_usage(self): """Test Assign new IP and verify usage calculation """ @@ -448,11 +468,13 @@ class TestVolumeUsage(cloudstackTestCase): @classmethod def setUpClass(cls): - cls.api_client = super(TestVolumeUsage, cls).getClsTestClient().getApiClient() + cls.testClient = super(TestVolumeUsage, cls).getClsTestClient() + cls.api_client = cls.testClient.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) + cls.domain = get_domain(cls.api_client) + cls.zone = get_zone(cls.api_client, cls.testClient.getZoneForTests()) cls.services['mode'] = cls.zone.networktype cls.disk_offering = DiskOffering.create( cls.api_client, @@ -518,7 +540,7 @@ def tearDown(self): raise Exception("Warning: Exception during cleanup : %s" % e) return - @attr(tags = ["advanced", "basic", "sg", "eip", "advancedns", "simulator"]) + @attr(tags=["advanced", "basic", "sg", "eip", "advancedns", "simulator", "selfservice"]) def test_01_volume_usage(self): """Test Create/delete a volume and verify correct usage is recorded """ @@ -530,16 +552,18 @@ def test_01_volume_usage(self): # 4. Destroy the Data disk. Volume.delete event is generated for data # disk of the destroyed VM - # Stop VM - self.debug("Stopping VM with ID: %s" % self.virtual_machine.id) - self.virtual_machine.stop(self.apiclient) + try: + # Stop VM + self.debug("Stopping VM with ID: %s" % self.virtual_machine.id) + self.virtual_machine.stop(self.apiclient) + except Exception as e: + self.fail("Failed to stop instance: %s" % e) - volume_response = list_volumes( - self.apiclient, - virtualmachineid=self.virtual_machine.id, - type='DATADISK', - listall=True - ) + volume_response = Volume.list( + self.apiclient, + virtualmachineid=self.virtual_machine.id, + type='DATADISK', + listall=True) self.assertEqual( isinstance(volume_response, list), True, @@ -622,11 +646,13 @@ class TestTemplateUsage(cloudstackTestCase): @classmethod def setUpClass(cls): - cls.api_client = super(TestTemplateUsage, cls).getClsTestClient().getApiClient() + cls.testClient = super(TestTemplateUsage, cls).getClsTestClient() + cls.api_client = cls.testClient.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) + cls.domain = get_domain(cls.api_client) + cls.zone = get_zone(cls.api_client, cls.testClient.getZoneForTests()) cls.services['mode'] = cls.zone.networktype cls.services["server"]["zoneid"] = cls.zone.id template = get_template( @@ -635,19 +661,22 @@ def setUpClass(cls): cls.services["ostype"] ) cls.services["server"]["zoneid"] = cls.zone.id - cls.account = Account.create( + try: + cls.account = Account.create( cls.api_client, cls.services["account"], domainid=cls.domain.id ) - cls.services["account"] = cls.account.name + cls._cleanup.append(cls.account) + cls.services["account"] = cls.account.name - cls.service_offering = ServiceOffering.create( + cls.service_offering = ServiceOffering.create( cls.api_client, cls.services["service_offering"] ) - #create virtual machine - cls.virtual_machine = VirtualMachine.create( + cls._cleanup.append(cls.service_offering) + #create virtual machine + cls.virtual_machine = VirtualMachine.create( cls.api_client, cls.services["server"], templateid=template.id, @@ -657,24 +686,21 @@ def setUpClass(cls): mode=cls.services["mode"] ) - #Stop virtual machine - cls.virtual_machine.stop(cls.api_client) - - #Wait before server has be successfully stopped - time.sleep(30) - list_volume = list_volumes( - cls.api_client, - virtualmachineid=cls.virtual_machine.id, - type='ROOT', - listall=True - ) - if isinstance(list_volume, list): - cls.volume = list_volume[0] - else: - raise Exception("List Volumes failed!") - cls._cleanup = [ - cls.account, - ] + #Stop virtual machine + cls.virtual_machine.stop(cls.api_client) + + list_volume = Volume.list( + cls.api_client, + virtualmachineid=cls.virtual_machine.id, + type='ROOT', + listall=True) + if isinstance(list_volume, list): + cls.volume = list_volume[0] + else: + raise Exception("List Volumes failed!") + except Exception as e: + cls.tearDownClass() + raise unittest.SkipTest("Exception in setUpClass: %s" % e) return @classmethod @@ -700,7 +726,7 @@ def tearDown(self): raise Exception("Warning: Exception during cleanup : %s" % e) return - @attr(tags = ["advanced", "basic", "sg", "eip", "advancedns"]) + @attr(tags=["advanced", "basic", "sg", "eip", "advancedns", "selfservice"]) def test_01_template_usage(self): """Test Upload/ delete a template and verify correct usage is generated for the template uploaded @@ -787,11 +813,13 @@ class TestISOUsage(cloudstackTestCase): @classmethod def setUpClass(cls): - cls.api_client = super(TestISOUsage, cls).getClsTestClient().getApiClient() + cls.testClient = super(TestISOUsage, cls).getClsTestClient() + cls.api_client = cls.testClient.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) + cls.domain = get_domain(cls.api_client) + cls.zone = get_zone(cls.api_client, cls.testClient.getZoneForTests()) cls.services['mode'] = cls.zone.networktype cls.services["server"]["zoneid"] = cls.zone.id cls.services["iso"]["zoneid"] = cls.zone.id @@ -844,7 +872,7 @@ def tearDown(self): raise Exception("Warning: Exception during cleanup : %s" % e) return - @attr(tags = ["advanced", "basic", "sg", "eip", "advancedns"]) + @attr(tags=["advanced", "basic", "sg", "eip", "advancedns", "selfservice"]) def test_01_ISO_usage(self): """Test Create/Delete a ISO and verify its usage is generated correctly """ @@ -924,11 +952,13 @@ class TestLBRuleUsage(cloudstackTestCase): @classmethod def setUpClass(cls): - cls.api_client = super(TestLBRuleUsage, cls).getClsTestClient().getApiClient() + cls.testClient = super(TestLBRuleUsage, cls).getClsTestClient() + cls.api_client = cls.testClient.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) + cls.domain = get_domain(cls.api_client) + cls.zone = get_zone(cls.api_client, cls.testClient.getZoneForTests()) cls.services['mode'] = cls.zone.networktype template = get_template( cls.api_client, @@ -996,7 +1026,7 @@ def tearDown(self): raise Exception("Warning: Exception during cleanup : %s" % e) return - @attr(tags = ["advanced", "eip", "advancedns", "simulator"]) + @attr(tags=["advanced", "eip", "advancedns", "simulator", "selfservice"]) def test_01_lb_usage(self): """Test Create/Delete a LB rule and verify correct usage is recorded """ @@ -1086,11 +1116,13 @@ class TestSnapshotUsage(cloudstackTestCase): @classmethod def setUpClass(cls): - cls.api_client = super(TestSnapshotUsage, cls).getClsTestClient().getApiClient() + cls.testClient = super(TestSnapshotUsage, cls).getClsTestClient() + cls.api_client = cls.testClient.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) + cls.domain = get_domain(cls.api_client) + cls.zone = get_zone(cls.api_client, cls.testClient.getZoneForTests()) cls.services['mode'] = cls.zone.networktype template = get_template( @@ -1153,7 +1185,7 @@ def tearDown(self): return @attr(speed = "slow") - @attr(tags = ["advanced", "basic", "sg", "eip", "advancedns", "simulator"]) + @attr(tags=["advanced", "basic", "sg", "eip", "advancedns", "simulator", "selfservice"]) def test_01_snapshot_usage(self): """Test Create/Delete a manual snap shot and verify correct usage is recorded @@ -1166,20 +1198,17 @@ def test_01_snapshot_usage(self): # 3. Delete the account # Get the Root disk of VM - volumes = list_volumes( - self.apiclient, - virtualmachineid=self.virtual_machine.id, - type='ROOT', - listall=True - ) + volumes = Volume.list( + self.apiclient, + virtualmachineid=self.virtual_machine.id, + type='ROOT', + listall=True) self.assertEqual( isinstance(volumes, list), True, "Check if list volumes return a valid data" ) - volume = volumes[0] - # Create a snapshot from the ROOTDISK self.debug("Creating snapshot from volume: %s" % volumes[0].id) snapshot = Snapshot.create(self.apiclient, volumes[0].id) @@ -1253,11 +1282,13 @@ class TestNatRuleUsage(cloudstackTestCase): @classmethod def setUpClass(cls): - cls.api_client = super(TestNatRuleUsage, cls).getClsTestClient().getApiClient() + cls.testClient = super(TestNatRuleUsage, cls).getClsTestClient() + cls.api_client = cls.testClient.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) + cls.domain = get_domain(cls.api_client) + cls.zone = get_zone(cls.api_client, cls.testClient.getZoneForTests()) cls.services['mode'] = cls.zone.networktype template = get_template( cls.api_client, @@ -1325,7 +1356,7 @@ def tearDown(self): raise Exception("Warning: Exception during cleanup : %s" % e) return - @attr(tags = ["advanced", "advancedns", "simulator"]) + @attr(tags=["advanced", "advancedns", "simulator", "selfservice"]) def test_01_nat_usage(self): """Test Create/Delete a PF rule and verify correct usage is recorded """ @@ -1415,11 +1446,13 @@ class TestVpnUsage(cloudstackTestCase): @classmethod def setUpClass(cls): - cls.api_client = super(TestVpnUsage, cls).getClsTestClient().getApiClient() + cls.testClient = super(TestVpnUsage, cls).getClsTestClient() + cls.api_client = cls.testClient.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) + cls.domain = get_domain(cls.api_client) + cls.zone = get_zone(cls.api_client, cls.testClient.getZoneForTests()) cls.services['mode'] = cls.zone.networktype template = get_template( cls.api_client, @@ -1488,7 +1521,7 @@ def tearDown(self): raise Exception("Warning: Exception during cleanup : %s" % e) return - @attr(tags = ["advanced", "advancedns"]) + @attr(tags=["advanced", "advancedns", "selfservice"]) def test_01_vpn_usage(self): """Test Create/Delete a VPN and verify correct usage is recorded """ diff --git a/test/integration/component/test_vm_passwdenabled.py b/test/integration/component/test_vm_passwdenabled.py index 5cfa52556f..2f68257f89 100644 --- a/test/integration/component/test_vm_passwdenabled.py +++ b/test/integration/component/test_vm_passwdenabled.py @@ -18,9 +18,9 @@ from marvin.cloudstackTestCase import * from marvin.cloudstackAPI import * from marvin.sshClient import SshClient -from marvin.integration.lib.utils import * -from marvin.integration.lib.base import * -from marvin.integration.lib.common import * +from marvin.lib.utils import * +from marvin.lib.base import * +from marvin.lib.common import * from nose.plugins.attrib import attr @@ -92,15 +92,13 @@ class TestVMPasswordEnabled(cloudstackTestCase): @classmethod def setUpClass(cls): - cls.api_client = super( - TestVMPasswordEnabled, - cls - ).getClsTestClient().getApiClient() - cls.services = Services().services + cls.testClient = super(TestVMPasswordEnabled, cls).getClsTestClient() + cls.api_client = cls.testClient.getApiClient() + cls.services = Services().services # Get Zone, Domain and templates - domain = get_domain(cls.api_client, cls.services) - zone = get_zone(cls.api_client, cls.services) + domain = get_domain(cls.api_client) + zone = get_zone(cls.api_client, cls.testClient.getZoneForTests()) cls.services['mode'] = zone.networktype template = get_template( cls.api_client, diff --git a/test/integration/component/test_vmware_drs.py b/test/integration/component/test_vmware_drs.py index 6a99911184..7d3ab7f5cb 100644 --- a/test/integration/component/test_vmware_drs.py +++ b/test/integration/component/test_vmware_drs.py @@ -23,19 +23,19 @@ from marvin.cloudstackTestCase import cloudstackTestCase, unittest -from marvin.integration.lib.base import (Account, +from marvin.lib.base import (Account, AffinityGroup, Host, VirtualMachine, ServiceOffering) -from marvin.integration.lib.common import (get_zone, +from marvin.lib.common import (get_zone, get_template, get_domain, get_pod ) -from marvin.integration.lib.utils import (validateList, +from marvin.lib.utils import (validateList, cleanup_resources, random_gen) @@ -111,25 +111,16 @@ class TestVMPlacement(cloudstackTestCase): @classmethod def setUpClass(cls): - cls.api_client = super( - TestVMPlacement, - cls - ).getClsTestClient().getApiClient() + cls.testClient = super(TestVMPlacement, cls).getClsTestClient() + cls.api_client = cls.testClient.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 - ) + cls.domain = get_domain(cls.api_client) + cls.zone = get_zone(cls.api_client, cls.testClient.getZoneForTests()) cls.pod = get_pod( cls.api_client, - zoneid=cls.zone.id, - services=cls.services - ) + zone_id=cls.zone.id) cls.template = get_template( cls.api_client, cls.zone.id, @@ -178,7 +169,7 @@ def tearDown(self): raise Exception("Warning: Exception during cleanup : %s" % e) return - @attr(tags = ["advanced", "vmware", "multihost"]) + @attr(tags=["advanced", "vmware", "multihost", "provisioning"]) def test_vm_creation_in_fully_automated_mode(self): """ Test VM Creation in automation mode = Fully automated This test requires following preconditions: @@ -280,20 +271,13 @@ class TestAntiAffinityRules(cloudstackTestCase): @classmethod def setUpClass(cls): - cls.api_client = super( - TestAntiAffinityRules, - cls - ).getClsTestClient().getApiClient() + cls.testClient = super(TestAntiAffinityRules, cls).getClsTestClient() + cls.api_client = cls.testClient.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 - ) + cls.domain = get_domain(cls.api_client) + cls.zone = get_zone(cls.api_client, cls.testClient.getZoneForTests()) cls.template = get_template( cls.api_client, cls.zone.id, @@ -352,7 +336,7 @@ def create_aff_grp(self, aff_grp=None, except Exception as e: raise Exception("Error: Creation of Affinity Group failed : %s" %e) - @attr(tags = ["advanced", "vmware", "multihost"]) + @attr(tags=["advanced", "vmware", "multihost", "provisioning"]) def test_vmware_anti_affinity(self): """ Test Set up anti-affinity rules @@ -515,20 +499,13 @@ class TestAffinityRules(cloudstackTestCase): @classmethod def setUpClass(cls): - cls.api_client = super( - TestAffinityRules, - cls - ).getClsTestClient().getApiClient() + cls.testClient = super(TestAffinityRules, cls).getClsTestClient() + cls.api_client = cls.testClient.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 - ) + cls.domain = get_domain(cls.api_client) + cls.zone = get_zone(cls.api_client, cls.testClient.getZoneForTests()) cls.template = get_template( cls.api_client, cls.zone.id, @@ -587,7 +564,7 @@ def create_aff_grp(self, aff_grp=None, except Exception as e: raise Exception("Error: Creation of Affinity Group failed : %s" %e) - @attr(tags = ["advanced", "vmware", "multihost"]) + @attr(tags=["advanced", "vmware", "multihost", "provisioning"]) def test_vmware_affinity(self): """ Test Set up affinity rules diff --git a/test/integration/component/test_volumes.py b/test/integration/component/test_volumes.py index ee0f91dd8c..b5b08e2d5c 100644 --- a/test/integration/component/test_volumes.py +++ b/test/integration/component/test_volumes.py @@ -5,9 +5,9 @@ # 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 @@ -18,11 +18,24 @@ """ #Import Local Modules 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.cloudstackTestCase import cloudstackTestCase +from marvin.cloudstackAPI import (listHypervisorCapabilities, + attachIso, + deleteVolume) +from marvin.lib.utils import cleanup_resources +from marvin.lib.base import (Account, + ServiceOffering, + VirtualMachine, + Volume, + Host, + Iso, + Configurations, + DiskOffering, + Domain) +from marvin.lib.common import (get_domain, + get_zone, + get_template, + get_pod) #Import System modules import time @@ -88,13 +101,14 @@ class TestAttachVolume(cloudstackTestCase): @classmethod def setUpClass(cls): - cls.api_client = super(TestAttachVolume, cls).getClsTestClient().getApiClient() - cls.services = Services().services + cls.testClient = super(TestAttachVolume, cls).getClsTestClient() + cls.api_client = cls.testClient.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) - cls.pod = get_pod(cls.api_client, cls.zone.id, cls.services) + cls.domain = get_domain(cls.api_client) + cls.zone = get_zone(cls.api_client, cls.testClient.getZoneForTests()) + cls.pod = get_pod(cls.api_client, cls.zone.id) cls.services['mode'] = cls.zone.networktype cls.disk_offering = DiskOffering.create( cls.api_client, @@ -185,9 +199,9 @@ def test_01_volume_attach(self): # 5. Start The VM. Start VM should be successful # Create 5 volumes and attach to VM - for i in range(self.max_data_volumes): - self.debug(i) - volume = Volume.create( + try: + for i in range(self.max_data_volumes): + volume = Volume.create( self.apiclient, self.services["volume"], zoneid=self.zone.id, @@ -195,134 +209,99 @@ def test_01_volume_attach(self): domainid=self.account.domainid, diskofferingid=self.disk_offering.id ) - self.debug("Created volume: %s for account: %s" % ( - volume.id, - self.account.name - )) - # Check List Volume response for newly created volume - list_volume_response = list_volumes( + # Check List Volume response for newly created volume + list_volume_response = Volume.list( self.apiclient, id=volume.id ) - self.assertNotEqual( + self.assertNotEqual( list_volume_response, None, "Check if volume exists in ListVolumes" ) - # Attach volume to VM - self.virtual_machine.attach_volume( + # Attach volume to VM + self.virtual_machine.attach_volume( self.apiclient, volume ) - self.debug("Attach volume: %s to VM: %s" % ( - volume.id, - self.virtual_machine.id - )) - # Check all volumes attached to same VM - list_volume_response = list_volumes( + # Check all volumes attached to same VM + list_volume_response = Volume.list( self.apiclient, virtualmachineid=self.virtual_machine.id, type='DATADISK', listall=True ) - self.assertNotEqual( - list_volume_response, - None, - "Check if volume exists in ListVolumes" - ) - self.assertEqual( - isinstance(list_volume_response, list), - True, - "Check list volumes response for valid list" - ) - self.assertEqual( - len(list_volume_response), - self.max_data_volumes, - "Volumes attached to the VM %s. Expected %s" % (len(list_volume_response), self.max_data_volumes) - ) - self.debug("Rebooting the VM: %s" % self.virtual_machine.id) - # Reboot VM - self.virtual_machine.reboot(self.apiclient) - - vm_response = list_virtual_machines( + self.assertNotEqual( + list_volume_response, + None, + "Check if volume exists in ListVolumes") + self.assertEqual( + isinstance(list_volume_response, list), + True, + "Check list volumes response for valid list") + self.assertEqual( + len(list_volume_response), + self.max_data_volumes, + "Volumes attached to the VM %s. Expected %s" % (len(list_volume_response), self.max_data_volumes)) + self.debug("Rebooting the VM: %s" % self.virtual_machine.id) + # Reboot VM + self.virtual_machine.reboot(self.apiclient) + + vm_response = VirtualMachine.list( self.apiclient, id=self.virtual_machine.id, ) - #Verify VM response to check whether VM deployment was successful - self.assertNotEqual( + #Verify VM response to check whether VM deployment was successful + self.assertNotEqual( len(vm_response), 0, "Check VMs available in List VMs response" ) - self.assertEqual( + self.assertEqual( isinstance(vm_response, list), True, "Check list VM response for valid list" ) - vm = vm_response[0] - self.assertEqual( + vm = vm_response[0] + self.assertEqual( vm.state, 'Running', "Check the state of VM" ) - self.debug("Stopping the VM: %s" % self.virtual_machine.id) - # Stop VM - self.virtual_machine.stop(self.apiclient) + # Stop VM + self.virtual_machine.stop(self.apiclient) - vm_response = list_virtual_machines( - self.apiclient, - id=self.virtual_machine.id, - ) - self.assertEqual( - isinstance(vm_response, list), - True, - "Check list VM response for valid list" - ) - - #Verify VM response to check whether VM deployment was successful - self.assertNotEqual( - len(vm_response), - 0, - "Check VMs available in List VMs response" - ) + # Start VM + self.virtual_machine.start(self.apiclient) + # Sleep to ensure that VM is in ready state + time.sleep(self.services["sleep"]) - vm = vm_response[0] - self.assertEqual( - vm.state, - 'Stopped', - "Check the state of VM" - ) - - self.debug("Starting the VM: %s" % self.virtual_machine.id) - # Start VM - self.virtual_machine.start(self.apiclient) - # Sleep to ensure that VM is in ready state - time.sleep(self.services["sleep"]) - - vm_response = list_virtual_machines( + vm_response = VirtualMachine.list( self.apiclient, id=self.virtual_machine.id, ) - self.assertEqual( + self.assertEqual( isinstance(vm_response, list), True, "Check list VM response for valid list" ) - #Verify VM response to check whether VM deployment was successful - self.assertNotEqual( + #Verify VM response to check whether VM deployment was successful + self.assertNotEqual( len(vm_response), 0, "Check VMs available in List VMs response" ) - vm = vm_response[0] - self.assertEqual( + vm = vm_response[0] + self.assertEqual( vm.state, 'Running', "Check the state of VM" ) + except Exception as e: + self.fail("Exception occured: %s" % e) return @attr(tags = ["advanced", "advancedns"]) @@ -348,7 +327,7 @@ def test_02_volume_attach_max(self): self.account.name )) # Check List Volume response for newly created volume - list_volume_response = list_volumes( + list_volume_response = Volume.list( self.apiclient, id=volume.id ) @@ -378,13 +357,14 @@ class TestAttachDetachVolume(cloudstackTestCase): @classmethod def setUpClass(cls): - cls.api_client = super(TestAttachDetachVolume, cls).getClsTestClient().getApiClient() - cls.services = Services().services + cls.testClient = super(TestAttachDetachVolume, cls).getClsTestClient() + cls.api_client = cls.testClient.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) - cls.pod = get_pod(cls.api_client, cls.zone.id, cls.services) + cls.domain = get_domain(cls.api_client) + cls.zone = get_zone(cls.api_client, cls.testClient.getZoneForTests()) + cls.pod = get_pod(cls.api_client, cls.zone.id) cls.services['mode'] = cls.zone.networktype cls.disk_offering = DiskOffering.create( cls.api_client, @@ -474,10 +454,11 @@ def test_01_volume_attach_detach(self): # 5. Stop the VM. Stop VM should be successful # 6. Start The VM. Start VM should be successful - volumes = [] - # Create 5 volumes and attach to VM - for i in range(self.max_data_volumes): - volume = Volume.create( + try: + volumes = [] + # Create 5 volumes and attach to VM + for i in range(self.max_data_volumes): + volume = Volume.create( self.apiclient, self.services["volume"], zoneid=self.zone.id, @@ -485,155 +466,117 @@ def test_01_volume_attach_detach(self): domainid=self.account.domainid, diskofferingid=self.disk_offering.id ) - self.debug("Created volume: %s for account: %s" % ( - volume.id, - self.account.name - )) - self.cleanup.append(volume) - volumes.append(volume) + self.cleanup.append(volume) + volumes.append(volume) - # Check List Volume response for newly created volume - list_volume_response = list_volumes( + # Check List Volume response for newly created volume + list_volume_response = Volume.list( self.apiclient, id=volume.id ) - self.assertNotEqual( - list_volume_response, - None, - "Check if volume exists in ListVolumes" - ) - self.assertEqual( - isinstance(list_volume_response, list), - True, - "Check list volumes response for valid list" - ) - self.debug("Attach volume: %s to VM: %s" % ( - volume.id, - self.virtual_machine.id - )) - # Attach volume to VM - self.virtual_machine.attach_volume( + self.assertNotEqual( + list_volume_response, + None, + "Check if volume exists in ListVolumes") + self.assertEqual( + isinstance(list_volume_response, list), + True, + "Check list volumes response for valid list") + # Attach volume to VM + self.virtual_machine.attach_volume( self.apiclient, volume ) - # Check all volumes attached to same VM - list_volume_response = list_volumes( + # Check all volumes attached to same VM + list_volume_response = Volume.list( self.apiclient, virtualmachineid=self.virtual_machine.id, type='DATADISK', listall=True ) - self.assertNotEqual( + self.assertNotEqual( list_volume_response, None, "Check if volume exists in ListVolumes" ) - self.assertEqual( + self.assertEqual( isinstance(list_volume_response, list), True, "Check list volumes response for valid list" ) - self.assertEqual( - len(list_volume_response), - self.max_data_volumes, - "Volumes attached to the VM %s. Expected %s" % (len(list_volume_response), self.max_data_volumes) - ) + self.assertEqual( + len(list_volume_response), + self.max_data_volumes, + "Volumes attached to the VM %s. Expected %s" % (len(list_volume_response), self.max_data_volumes) + ) - # Detach all volumes from VM - for volume in volumes: - self.debug("Detach volume: %s to VM: %s" % ( - volume.id, - self.virtual_machine.id - )) - self.virtual_machine.detach_volume( + # Detach all volumes from VM + for volume in volumes: + self.virtual_machine.detach_volume( self.apiclient, volume ) - # Reboot VM - self.debug("Rebooting the VM: %s" % self.virtual_machine.id) - self.virtual_machine.reboot(self.apiclient) - # Sleep to ensure that VM is in ready state - time.sleep(self.services["sleep"]) + # Reboot VM + self.debug("Rebooting the VM: %s" % self.virtual_machine.id) + self.virtual_machine.reboot(self.apiclient) + # Sleep to ensure that VM is in ready state + time.sleep(self.services["sleep"]) - vm_response = list_virtual_machines( + vm_response = VirtualMachine.list( self.apiclient, id=self.virtual_machine.id, ) - #Verify VM response to check whether VM deployment was successful - self.assertEqual( + #Verify VM response to check whether VM deployment was successful + self.assertEqual( isinstance(vm_response, list), True, "Check list VM response for valid list" ) - self.assertNotEqual( + self.assertNotEqual( len(vm_response), 0, "Check VMs available in List VMs response" ) - vm = vm_response[0] - self.assertEqual( + vm = vm_response[0] + self.assertEqual( vm.state, 'Running', "Check the state of VM" ) - # Stop VM - self.debug("Stopping the VM: %s" % self.virtual_machine.id) - self.virtual_machine.stop(self.apiclient) - # Sleep to ensure that VM is in ready state - time.sleep(self.services["sleep"]) + # Stop VM + self.virtual_machine.stop(self.apiclient) - vm_response = list_virtual_machines( - self.apiclient, - id=self.virtual_machine.id, - ) - #Verify VM response to check whether VM deployment was successful - self.assertEqual( - isinstance(vm_response, list), - True, - "Check list VM response for valid list" - ) - self.assertNotEqual( - len(vm_response), - 0, - "Check VMs available in List VMs response" - ) - vm = vm_response[0] - self.assertEqual( - vm.state, - 'Stopped', - "Check the state of VM" - ) + # Start VM + self.virtual_machine.start(self.apiclient) + # Sleep to ensure that VM is in ready state + time.sleep(self.services["sleep"]) - # Start VM - self.debug("Starting the VM: %s" % self.virtual_machine.id) - self.virtual_machine.start(self.apiclient) - # Sleep to ensure that VM is in ready state - time.sleep(self.services["sleep"]) - - vm_response = list_virtual_machines( + vm_response = VirtualMachine.list( self.apiclient, id=self.virtual_machine.id, ) - #Verify VM response to check whether VM deployment was successful - self.assertEqual( + #Verify VM response to check whether VM deployment was successful + self.assertEqual( isinstance(vm_response, list), True, "Check list VM response for valid list" ) - self.assertNotEqual( + self.assertNotEqual( len(vm_response), 0, "Check VMs available in List VMs response" ) - vm = vm_response[0] - self.assertEqual( + vm = vm_response[0] + self.assertEqual( vm.state, 'Running', "Check the state of VM" ) + except Exception as e: + self.fail("Exception occuered: %s" % e) return @@ -641,13 +584,14 @@ class TestAttachVolumeISO(cloudstackTestCase): @classmethod def setUpClass(cls): - cls.api_client = super(TestAttachVolumeISO, cls).getClsTestClient().getApiClient() - cls.services = Services().services + cls.testClient = super(TestAttachVolumeISO, cls).getClsTestClient() + cls.api_client = cls.testClient.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) - cls.pod = get_pod(cls.api_client, cls.zone.id, cls.services) + cls.domain = get_domain(cls.api_client) + cls.zone = get_zone(cls.api_client, cls.testClient.getZoneForTests()) + cls.pod = get_pod(cls.api_client, cls.zone.id) cls.services['mode'] = cls.zone.networktype cls.disk_offering = DiskOffering.create( cls.api_client, @@ -751,7 +695,7 @@ def test_01_volume_iso_attach(self): self.account.name )) # Check List Volume response for newly created volume - list_volume_response = list_volumes( + list_volume_response = Volume.list( self.apiclient, id=volume.id ) @@ -772,7 +716,7 @@ def test_01_volume_iso_attach(self): ) # Check all volumes attached to same VM - list_volume_response = list_volumes( + list_volume_response = Volume.list( self.apiclient, virtualmachineid=self.virtual_machine.id, type='DATADISK', @@ -823,7 +767,7 @@ def test_01_volume_iso_attach(self): self.apiclient.attachIso(cmd) # Verify ISO is attached to VM - vm_response = list_virtual_machines( + vm_response = VirtualMachine.list( self.apiclient, id=self.virtual_machine.id, ) @@ -852,11 +796,13 @@ class TestVolumes(cloudstackTestCase): @classmethod def setUpClass(cls): - cls.api_client = super(TestVolumes, cls).getClsTestClient().getApiClient() + cls.testClient = super(TestVolumes, cls).getClsTestClient() + cls.api_client = cls.testClient.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) + cls.domain = get_domain(cls.api_client) + cls.zone = get_zone(cls.api_client, cls.testClient.getZoneForTests()) cls.services['mode'] = cls.zone.networktype cls.disk_offering = DiskOffering.create( cls.api_client, @@ -923,7 +869,7 @@ def tearDown(self): cleanup_resources(self.apiclient, self.cleanup) return - @attr(tags = ["advanced", "advancedns"]) + @attr(tags=["advanced", "advancedns", "selfservice"]) def test_01_attach_volume(self): """Attach a created Volume to a Running VM """ @@ -936,7 +882,7 @@ def test_01_attach_volume(self): # response before volume attach (to VM) # Check the list volumes response for vmname and virtualmachineid - list_volume_response = list_volumes( + list_volume_response = Volume.list( self.apiclient, id=self.volume.id ) @@ -977,7 +923,7 @@ def test_01_attach_volume(self): self.virtual_machine.attach_volume(self.apiclient, self.volume) # Check all volumes attached to same VM - list_volume_response = list_volumes( + list_volume_response = Volume.list( self.apiclient, virtualmachineid=self.virtual_machine.id, type='DATADISK', @@ -1006,7 +952,7 @@ def test_01_attach_volume(self): ) return - @attr(tags = ["advanced", "advancedns"]) + @attr(tags=["advanced", "advancedns", "selfservice"]) def test_02_detach_volume(self): """Detach a Volume attached to a VM """ @@ -1025,7 +971,7 @@ def test_02_detach_volume(self): #Sleep to ensure the current state will reflected in other calls time.sleep(self.services["sleep"]) - list_volume_response = list_volumes( + list_volume_response = Volume.list( self.apiclient, id=self.volume.id ) @@ -1053,7 +999,7 @@ def test_02_detach_volume(self): ) return - @attr(tags = ["advanced", "advancedns"]) + @attr(tags=["advanced", "advancedns", "selfservice"]) def test_03_delete_detached_volume(self): """Delete a Volume unattached to an VM """ @@ -1069,7 +1015,7 @@ def test_03_delete_detached_volume(self): #Sleep to ensure the current state will reflected in other calls time.sleep(self.services["sleep"]) - list_volume_response = list_volumes( + list_volume_response = Volume.list( self.apiclient, id=self.volume.id, ) @@ -1080,7 +1026,7 @@ def test_03_delete_detached_volume(self): ) return - @attr(tags=["advanced", "advancedns", "simulator", "basic", "eip", "sg"]) + @attr(tags=["advanced", "advancedns", "simulator", "basic", "eip", "sg", "selfservice"]) def test_create_volume_under_domain(self): """Create a volume under a non-root domain as non-root-domain user @@ -1105,7 +1051,7 @@ def test_create_volume_under_domain(self): ) self.assertTrue(domuser is not None) - domapiclient = self.testClient.getUserApiClient(account=domuser.name, domain=dom.name) + domapiclient = self.testClient.getUserApiClient(UserName=domuser.name, DomainName=dom.name) diskoffering = DiskOffering.list(self.apiclient) self.assertTrue(isinstance(diskoffering, list), msg="DiskOffering list is not a list?") @@ -1133,15 +1079,12 @@ class TestDeployVmWithCustomDisk(cloudstackTestCase): @classmethod def setUpClass(cls): - cls.api_client = super( - TestDeployVmWithCustomDisk, - cls - ).getClsTestClient().getApiClient() + cls.testClient = super(TestDeployVmWithCustomDisk, cls).getClsTestClient() + cls.api_client = cls.testClient.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) + cls.domain = get_domain(cls.api_client) + cls.zone = get_zone(cls.api_client, cls.testClient.getZoneForTests()) cls.services['mode'] = cls.zone.networktype cls.disk_offering = DiskOffering.create( cls.api_client, diff --git a/test/integration/component/test_vpc.py b/test/integration/component/test_vpc.py index 1af8d8122e..e9d396e8b8 100644 --- a/test/integration/component/test_vpc.py +++ b/test/integration/component/test_vpc.py @@ -20,11 +20,11 @@ #Import Local Modules from nose.plugins.attrib import attr from marvin.cloudstackTestCase import * -from marvin.cloudstackException import cloudstackAPIException +from marvin.cloudstackException import CloudstackAPIException from marvin.cloudstackAPI import * -from marvin.integration.lib.utils import * -from marvin.integration.lib.base import * -from marvin.integration.lib.common import * +from marvin.lib.utils import * +from marvin.lib.base import * +from marvin.lib.common import * class Services: @@ -175,14 +175,13 @@ class TestVPC(cloudstackTestCase): @classmethod def setUpClass(cls): - cls.api_client = super( - TestVPC, - cls - ).getClsTestClient().getApiClient() + cls.testClient = super(TestVPC, cls).getClsTestClient() + cls.api_client = cls.testClient.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) + cls.domain = get_domain(cls.api_client) + cls.zone = get_zone(cls.api_client, cls.testClient.getZoneForTests()) cls.template = get_template( cls.api_client, cls.zone.id, @@ -286,7 +285,7 @@ def validate_vpc_network(self, network, state=None): return #list_vpc_apis should be the first case otherwise the vpc counts would be wrong - @attr(tags=["advanced", "intervlan"]) + @attr(tags=["advanced", "intervlan", "selfservice"]) def test_01_list_vpc_apis(self): """ Test list VPC APIs """ @@ -465,7 +464,7 @@ def test_01_list_vpc_apis(self): ) return - @attr(tags=["advanced", "intervlan"]) + @attr(tags=["advanced", "intervlan", "selfservice"]) def test_02_restart_vpc_no_networks(self): """ Test restart VPC having no networks """ @@ -496,7 +495,7 @@ def test_02_restart_vpc_no_networks(self): self.validate_vpc_network(vpc, state='Enabled') return - @attr(tags=["advanced", "intervlan"]) + @attr(tags=["advanced", "intervlan", "selfservice"]) def test_03_restart_vpc_with_networks(self): """ Test restart VPC having networks """ @@ -581,7 +580,7 @@ def test_03_restart_vpc_with_networks(self): self.validate_vpc_network(vpc, state='Enabled') return - @attr(tags=["advanced", "intervlan"]) + @attr(tags=["advanced", "intervlan", "selfservice"]) def test_04_delete_vpc_no_networks(self): """ Test delete VPC having no networks """ @@ -621,7 +620,7 @@ def test_04_delete_vpc_no_networks(self): ) return - @attr(tags=["advanced", "intervlan"]) + @attr(tags=["advanced", "intervlan", "selfservice"]) def test_05_delete_vpc_with_networks(self): """ Test delete VPC having networks """ @@ -752,7 +751,7 @@ def test_05_delete_vpc_with_networks(self): ) return - @attr(tags=["advanced", "intervlan"]) + @attr(tags=["advanced", "intervlan", "selfservice"]) def test_06_list_vpc_apis_admin(self): """ Test list VPC APIs for different user roles """ @@ -812,7 +811,7 @@ def test_06_list_vpc_apis_admin(self): ) return - @attr(tags=["advanced", "intervlan", "multiple"]) + @attr(tags=["advanced", "intervlan", "multiple", "provisioning"]) def test_07_restart_network_vm_running(self): """ Test Restart VPC when there are multiple networks associated """ @@ -1161,7 +1160,7 @@ def test_07_restart_network_vm_running(self): ) return - @attr(tags=["advanced", "intervlan"]) + @attr(tags=["advanced", "intervlan", "provisioning"]) def test_08_delete_vpc(self): """ Test vpc deletion after account deletion """ @@ -1527,7 +1526,7 @@ def test_08_delete_vpc(self): ) return - @attr(tags=["advanced", "intervlan"]) + @attr(tags=["advanced", "intervlan", "selfservice"]) def test_09_vpc_create(self): """ Test to create vpc and verify VPC state, VR and SourceNatIP """ @@ -1588,7 +1587,7 @@ def test_09_vpc_create(self): "Source Nat IP address was not allocated to VR" ) - @attr(tags=["advanced", "intervlan"]) + @attr(tags=["advanced", "intervlan", "selfservice"]) def test_10_nonoverlaping_cidrs(self): """ Test creation of multiple VPCs with non-overlapping CIDRs """ @@ -1640,7 +1639,7 @@ def test_10_nonoverlaping_cidrs(self): assert("VPC created with overlapping CIDR") return - @attr(tags=["advanced", "intervlan"]) + @attr(tags=["advanced", "intervlan", "provisioning"]) def test_11_deploy_vm_wo_network_netdomain(self): """ Test deployment of vm in a VPC without network domain """ @@ -1794,7 +1793,7 @@ def validate_vm_netdomain(self, vm, vpc, network, expected_netdomain): (vm_domain, expected_netdomain) ) - @attr(tags=["advanced", "intervlan"]) + @attr(tags=["advanced", "intervlan", "selfservice"]) def test_12_deploy_vm_with_netdomain(self): """ Test deployment of vm in a VPC with network domain """ @@ -1849,7 +1848,7 @@ def test_12_deploy_vm_with_netdomain(self): networkdomain='test.netdomain' ) - @attr(tags=["advanced", "intervlan"]) + @attr(tags=["advanced", "intervlan", "provisioning"]) def test_13_deploy_vm_with_vpc_netdomain(self): """ Test deployment of vm in a VPC with network domain """ @@ -1914,7 +1913,7 @@ def test_13_deploy_vm_with_vpc_netdomain(self): self.validate_vm_netdomain(virtual_machine, vpc, network, netdomain) - @attr(tags=["advanced", "intervlan"]) + @attr(tags=["advanced", "intervlan", "selfservice"]) def test_14_deploy_vm_1(self): """ Test vm deploy in network by a user where VPC was created without account/domain ID """ @@ -1934,10 +1933,10 @@ def test_14_deploy_vm_1(self): self.debug("creating a VPC network in the account: %s" % user.name) - userapiclient = self.testClient.createUserApiClient( + userapiclient = self.testClient.getUserApiClient( UserName=user.name, DomainName=user.domain, - acctType=0) + type=0) vpc = VPC.create( @@ -1990,7 +1989,7 @@ def test_14_deploy_vm_1(self): return - @attr(tags=["advanced", "intervlan"]) + @attr(tags=["advanced", "intervlan", "selfservice"]) def test_15_deploy_vm_2(self): """ Test deployment of vm in a network in a domain admin account where VPC is created without account/domain ID """ @@ -2017,8 +2016,8 @@ def test_15_deploy_vm_2(self): #0 - User, 1 - Root Admin, 2 - Domain Admin userapiclient = self.testClient.getUserApiClient( - account=user.name, - domain=self.services["domain"]["name"], + UserName=user.name, + DomainName=self.services["domain"]["name"], type=2) vpc = VPC.create( @@ -2071,7 +2070,7 @@ def test_15_deploy_vm_2(self): return - @attr(tags=["advanced", "intervlan"]) + @attr(tags=["advanced", "intervlan", "selfservice"]) def test_16_deploy_vm_for_user_by_admin(self): """ Test deployment of vm in a network by root admin for user. """ @@ -2092,8 +2091,8 @@ def test_16_deploy_vm_for_user_by_admin(self): user.name) userapiclient = self.testClient.getUserApiClient( - account=user.name, - domain=user.domain, + UserName=user.name, + DomainName=user.domain, type=0) vpc = VPC.create( @@ -2148,7 +2147,7 @@ def test_16_deploy_vm_for_user_by_admin(self): return - @attr(tags=["advanced", "intervlan"]) + @attr(tags=["advanced", "intervlan", "selfservice"]) def test_17_deploy_vm_for_user_by_domain_admin(self): """ Test deployment of vm in a network by domain admin for user. """ @@ -2171,8 +2170,8 @@ def test_17_deploy_vm_for_user_by_domain_admin(self): self.debug("Created account: %s" % domain_admin.name) self.cleanup.append(domain_admin) da_apiclient = self.testClient.getUserApiClient( - account=domain_admin.name, - domain=domain_admin.domain, + UserName=domain_admin.name, + DomainName=domain_admin.domain, type=2) user = Account.create( @@ -2188,11 +2187,11 @@ def test_17_deploy_vm_for_user_by_domain_admin(self): #0 - User, 1 - Root Admin, 2 - Domain Admin userapiclient = self.testClient.getUserApiClient( - account=user.name, - domain=user.domain, + UserName=user.name, + DomainName=user.domain, type=0) - with self.assertRaises(cloudstackAPIException): + with self.assertRaises(CloudstackAPIException): vpc = VPC.create( da_apiclient, self.services["vpc"], @@ -2202,7 +2201,7 @@ def test_17_deploy_vm_for_user_by_domain_admin(self): zoneid=self.zone.id, ) - @attr(tags=["advanced", "intervlan"]) + @attr(tags=["advanced", "intervlan", "selfservice"]) def test_18_create_net_for_user_diff_domain_by_doadmin(self): """ Test creation of network by domain admin for user from different domain """ @@ -2222,8 +2221,8 @@ def test_18_create_net_for_user_diff_domain_by_doadmin(self): self.debug("Created account: %s" % domain_admin.name) self.cleanup.append(domain_admin) da_apiclient = self.testClient.getUserApiClient( - account=domain_admin.name, - domain=self.services["domain"]["name"], + UserName=domain_admin.name, + DomainName=self.services["domain"]["name"], type=2) user = Account.create( @@ -2239,8 +2238,8 @@ def test_18_create_net_for_user_diff_domain_by_doadmin(self): #0 - User, 1 - Root Admin, 2 - Domain Admin userapiclient = self.testClient.getUserApiClient( - account=user.name, - domain=user.domain, + UserName=user.name, + DomainName=user.domain, type=0) vpc = VPC.create( @@ -2279,7 +2278,7 @@ def test_18_create_net_for_user_diff_domain_by_doadmin(self): vpcid=vpc.id ) - @attr(tags=["advanced", "intervlan"]) + @attr(tags=["advanced", "intervlan", "selfservice"]) def test_19_create_vpc_wo_params(self): """ Test creation of VPC without mandatory parameters """ @@ -2339,7 +2338,7 @@ def test_19_create_vpc_wo_params(self): domainid=self.account.domainid ) - @attr(tags=["advanced", "intervlan"]) + @attr(tags=["advanced", "intervlan", "selfservice"]) def test_20_update_vpc_name_display_text(self): """ Test to verify updation of vpc name and display text """ diff --git a/test/integration/component/test_vpc_distributed_routing_offering.py b/test/integration/component/test_vpc_distributed_routing_offering.py index 0fa7de7934..cc9a19154f 100644 --- a/test/integration/component/test_vpc_distributed_routing_offering.py +++ b/test/integration/component/test_vpc_distributed_routing_offering.py @@ -23,9 +23,9 @@ 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.lib.utils import * +from marvin.lib.base import * +from marvin.lib.common import * from marvin.sshClient import SshClient import datetime @@ -154,24 +154,27 @@ class TestVPCDistributedRouterOffering(cloudstackTestCase): @classmethod def setUpClass(cls): - cls.api_client = super( - TestVPCDistributedRouterOffering, - cls - ).getClsTestClient().getApiClient() - cls.services = Services().services + testClient = super(TestVPCDistributedRouterOffering, cls).getClsTestClient() + cls.apiclient = testClient.getApiClient() + cls.services = testClient.getParsedTestDataConfig() + # Get Zone, Domain and templates - cls.domain = get_domain(cls.api_client, cls.services) - cls.zone = get_zone(cls.api_client, cls.services) + cls.domain = get_domain(cls.apiclient) + cls.zone = get_zone(cls.apiclient, testClient.getZoneForTests()) + cls.services['mode'] = cls.zone.networktype + cls.template = get_template( - cls.api_client, - cls.zone.id, - cls.services["ostype"] - ) + cls.apiclient, + cls.zone.id, + cls.services["ostype"] + ) + if cls.template == FAILED: + assert False, "get_template() failed to return template with description %s" % cls.services["ostype"] 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.apiclient, cls.services["service_offering"] ) cls._cleanup = [ @@ -183,7 +186,7 @@ def setUpClass(cls): def tearDownClass(cls): try: #Cleanup resources used - cleanup_resources(cls.api_client, cls._cleanup) + cleanup_resources(cls.apiclient, cls._cleanup) except Exception as e: raise Exception("Warning: Exception during cleanup : %s" % e) return diff --git a/test/integration/component/test_vpc_network.py b/test/integration/component/test_vpc_network.py index c393401403..a449948c91 100644 --- a/test/integration/component/test_vpc_network.py +++ b/test/integration/component/test_vpc_network.py @@ -21,8 +21,8 @@ from nose.plugins.attrib import attr from marvin.cloudstackTestCase import cloudstackTestCase, unittest from marvin.cloudstackAPI import startVirtualMachine, stopVirtualMachine -from marvin.integration.lib.utils import cleanup_resources, validateList -from marvin.integration.lib.base import (VirtualMachine, +from marvin.lib.utils import cleanup_resources, validateList +from marvin.lib.base import (VirtualMachine, ServiceOffering, Account, NATRule, @@ -35,7 +35,7 @@ StaticNATRule, NetworkACL, PublicIPAddress) -from marvin.integration.lib.common import (get_zone, +from marvin.lib.common import (get_zone, get_domain, get_template, wait_for_cleanup, @@ -239,17 +239,17 @@ class TestVPCNetwork(cloudstackTestCase): @classmethod def setUpClass(cls): - cls.api_client = super( - TestVPCNetwork, - cls - ).getClsTestClient().getApiClient() + cls.testClient = super(TestVPCNetwork, cls).getClsTestClient() + cls.api_client = cls.testClient.getApiClient() + cls.services = Services().services + # Added an attribute to track if Netscaler addition was successful. # Value is checked in tests and if not configured, Netscaler tests will be skipped cls.ns_configured = False # Get Zone, Domain and templates - cls.domain = get_domain(cls.api_client, cls.services) - cls.zone = get_zone(cls.api_client, cls.services) + cls.domain = get_domain(cls.api_client) + cls.zone = get_zone(cls.api_client, cls.testClient.getZoneForTests()) cls.template = get_template( cls.api_client, cls.zone.id, @@ -695,7 +695,7 @@ def test_05_create_network_ext_LB(self): return @unittest.skip("skipped - RvR didn't support VPC currently ") - @attr(tags=["advanced", "intervlan"]) + @attr(tags=["advanced", "intervlan", "NA"]) def test_06_create_network_with_rvr(self): """ Test create network with redundant router capability """ @@ -769,7 +769,7 @@ def test_06_create_network_with_rvr(self): self.debug("Network creation failed") return - @attr(tags=["advanced", "intervlan"]) + @attr(tags=["advanced", "intervlan", "selfservice"]) def test_07_create_network_unsupported_services(self): """ Test create network services not supported by VPC (Should fail) """ @@ -836,7 +836,7 @@ def test_07_create_network_unsupported_services(self): self.debug("Network creation failed as VPC doesn't have LB service") return - @attr(tags=["advanced", "intervlan"]) + @attr(tags=["advanced", "intervlan", "selfservice"]) def test_08_create_network_without_sourceNAT(self): """ Test create network without sourceNAT service in VPC (should fail) """ @@ -1003,17 +1003,17 @@ class TestVPCNetworkRanges(cloudstackTestCase): @classmethod def setUpClass(cls): - cls.api_client = super( - TestVPCNetworkRanges, - cls - ).getClsTestClient().getApiClient() + cls.testClient = super(TestVPCNetworkRanges, cls).getClsTestClient() + cls.api_client = cls.testClient.getApiClient() + cls.services = Services().services + # Added an attribute to track if Netscaler addition was successful. # Value is checked in tests and if not configured, Netscaler tests will be skipped cls.ns_configured = False # Get Zone, Domain and templates - cls.domain = get_domain(cls.api_client, cls.services) - cls.zone = get_zone(cls.api_client, cls.services) + cls.domain = get_domain(cls.api_client) + cls.zone = get_zone(cls.api_client, cls.testClient.getZoneForTests()) cls.template = get_template( cls.api_client, cls.zone.id, @@ -1186,7 +1186,7 @@ def test_01_create_network_outside_range(self, value): "Network creation failed as network cidr range is outside of vpc") return - @attr(tags=["advanced", "intervlan"]) + @attr(tags=["advanced", "intervlan", "selfservice"]) def test_02_create_network_outside_range(self): """ Test create network outside cidr range of VPC """ @@ -1541,14 +1541,14 @@ class TestVPCNetworkUpgrade(cloudstackTestCase): @classmethod def setUpClass(cls): - cls.api_client = super( - TestVPCNetworkUpgrade, - cls - ).getClsTestClient().getApiClient() + cls.testClient = super(TestVPCNetworkUpgrade, cls).getClsTestClient() + cls.api_client = cls.testClient.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) + cls.domain = get_domain(cls.api_client) + cls.zone = get_zone(cls.api_client, cls.testClient.getZoneForTests()) cls.template = get_template( cls.api_client, cls.zone.id, @@ -1645,7 +1645,7 @@ def validate_vpc_network(self, network, state=None): self.debug("VPC network validated - %s" % network.name) return - @attr(tags=["advanced", "intervlan"]) + @attr(tags=["advanced", "intervlan", "provisioning"]) def test_01_network_services_upgrade(self): """ Test update Network that is part of a VPC to a network offering that has more services """ @@ -1933,8 +1933,6 @@ def test_01_network_services_upgrade(self): except Exception as e: self.fail("Failed to stop VMs, %s" % e) - wait_for_cleanup(self.apiclient, ["expunge.interval", "expunge.delay"]) - # When all Vms ain network are stopped, network state changes from Implemented --> Shutdown --> Allocated # We can't update the network when it is in Shutodown state, hence we should wait for the state to change to # Allocated and then update the network @@ -2007,7 +2005,7 @@ def test_01_network_services_upgrade(self): ) return - @attr(tags=["advanced", "intervlan"]) + @attr(tags=["advanced", "intervlan", "provisioning"]) def test_02_network_vpcvr2vr_upgrade(self): """ Test update Network that is NOT part of a VPC to a nw offering that has services that are provided by VPCVR and vice versa """ @@ -2108,8 +2106,6 @@ def test_02_network_vpcvr2vr_upgrade(self): except Exception as e: self.fail("Failed to stop VMs, %s" % e) - wait_for_cleanup(self.apiclient, ["expunge.interval", "expunge.delay"]) - self.debug("Upgrading network offering to support PF services") with self.assertRaises(Exception): network_1.update( @@ -2123,14 +2119,14 @@ class TestVPCNetworkGc(cloudstackTestCase): @classmethod def setUpClass(cls): - cls.api_client = super( - TestVPCNetworkGc, - cls - ).getClsTestClient().getApiClient() + cls.testClient = super(TestVPCNetworkGc, cls).getClsTestClient() + cls.api_client = cls.testClient.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) + cls.domain = get_domain(cls.api_client) + cls.zone = get_zone(cls.api_client, cls.testClient.getZoneForTests()) cls.template = get_template( cls.api_client, cls.zone.id, @@ -2341,7 +2337,7 @@ def validate_vpc_network(self, network, state=None): self.debug("VPC network validated - %s" % network.name) return - @attr(tags=["advanced", "intervlan"]) + @attr(tags=["advanced", "intervlan", "provisioning"]) def test_01_wait_network_gc(self): """ Test network gc after shutdown of vms in the network """ @@ -2367,7 +2363,7 @@ def test_01_wait_network_gc(self): self.assertEqual(lbrules, None, "LBrules were not cleared after network GC thread is run") return - @attr(tags=["advanced", "intervlan"]) + @attr(tags=["advanced", "intervlan", "provisioning"]) def test_02_start_vm_network_gc(self): """ Test network rules after starting a VpcVr that was shutdown after network.gc """ @@ -2441,7 +2437,7 @@ def test_02_start_vm_network_gc(self): ) return - @attr(tags=["advanced", "intervlan"]) + @attr(tags=["advanced", "intervlan", "provisioning"]) def test_03_restart_vpcvr(self): """ Test Stop all the Vms that are part of the a Network (Wait for network GC).Restart VPCVR. diff --git a/test/integration/component/test_vpc_network_lbrules.py b/test/integration/component/test_vpc_network_lbrules.py index d623fb9bc5..a5625e7216 100644 --- a/test/integration/component/test_vpc_network_lbrules.py +++ b/test/integration/component/test_vpc_network_lbrules.py @@ -20,7 +20,7 @@ #Import Local Modules from nose.plugins.attrib import attr from marvin.cloudstackTestCase import cloudstackTestCase, unittest -from marvin.integration.lib.base import (stopRouter, +from marvin.lib.base import (stopRouter, startRouter, Account, VpcOffering, @@ -34,11 +34,11 @@ VirtualMachine, LoadBalancerRule, StaticNATRule) -from marvin.integration.lib.common import (get_domain, +from marvin.lib.common import (get_domain, get_zone, get_template, list_routers) -from marvin.integration.lib.utils import cleanup_resources +from marvin.lib.utils import cleanup_resources import socket import time @@ -181,14 +181,13 @@ def setUpClass(cls): # We want to fail quicker if it's failure socket.setdefaulttimeout(60) - cls.api_client = super( - TestVPCNetworkLBRules, - cls - ).getClsTestClient().getApiClient() + cls.testClient = super(TestVPCNetworkLBRules, cls).getClsTestClient() + cls.api_client = cls.testClient.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) + cls.domain = get_domain(cls.api_client) + cls.zone = get_zone(cls.api_client, cls.testClient.getZoneForTests()) cls.template = get_template( cls.api_client, cls.zone.id, @@ -507,7 +506,7 @@ def create_egress_Internet_Rule(self, network): return nwacl_internet_1 - @attr(tags=["advanced", "intervlan"]) + @attr(tags=["advanced", "intervlan", "selfservice"]) def test_01_VPC_LBRulesListing(self): """ Test case no 210 and 227: List Load Balancing Rules belonging to a VPC """ @@ -555,7 +554,7 @@ def test_01_VPC_LBRulesListing(self): ) return - @attr(tags=["advanced", "intervlan"]) + @attr(tags=["advanced", "intervlan", "provisioning"]) def test_02_VPC_CreateLBRuleInMultipleNetworks(self): """ Test Create LB rules for 1 network which is part of a two/multiple virtual networks of a VPC using a new Public IP Address available with the VPC when the Virtual Router is in Running State @@ -580,7 +579,7 @@ def test_02_VPC_CreateLBRuleInMultipleNetworks(self): self.check_wget_from_vm(vm_1, public_ip_1, testnegative=False) return - @attr(tags=["advanced", "intervlan"]) + @attr(tags=["advanced", "intervlan", "provisioning"]) def test_03_VPC_CreateLBRuleInMultipleNetworksVRStoppedState(self): """ Test case no 222 : Create LB rules for a two/multiple virtual networks of a VPC using a new Public IP Address available with the VPC when the Virtual Router is in Stopped State @@ -616,7 +615,7 @@ def test_03_VPC_CreateLBRuleInMultipleNetworksVRStoppedState(self): self.check_wget_from_vm(vm_1, public_ip_1, testnegative=False) return - @attr(tags=["advanced","advancedns", "intervlan"]) + @attr(tags=["advanced","advancedns", "intervlan", "provisioning"]) def test_04_VPC_CreateLBRuleInMultipleNetworksVRStoppedState(self): """ Test case no 222 : Create LB rules for a two/multiple virtual networks of a VPC using a new Public IP Address available with the VPC when the Virtual Router is in Stopped State @@ -646,7 +645,7 @@ def test_04_VPC_CreateLBRuleInMultipleNetworksVRStoppedState(self): self.check_wget_from_vm(vm_1, public_ip_1, testnegative=False) return - @attr(tags=["advanced", "intervlan"]) + @attr(tags=["advanced", "intervlan", "provisioning"]) def test_05_VPC_CreateAndDeleteLBRule(self): """ Test case no 214 : Delete few(not all) LB rules for a single virtual network of a VPC belonging to a single Public IP Address when the Virtual Router is in Running State @@ -677,7 +676,7 @@ def test_05_VPC_CreateAndDeleteLBRule(self): self.check_ssh_into_vm(vm_1, public_ip_1, testnegative=True) return - @attr(tags=["advanced", "intervlan"]) + @attr(tags=["advanced", "intervlan", "provisioning"]) def test_06_VPC_CreateAndDeleteLBRuleVRStopppedState(self): """ Test Delete few(not all) LB rules for a single virtual network of a VPC belonging to a single Public IP Address when the Virtual Router is in Stopped State @@ -714,7 +713,7 @@ def test_06_VPC_CreateAndDeleteLBRuleVRStopppedState(self): self.check_ssh_into_vm(vm_1, public_ip_1, testnegative=True) return - @attr(tags=["advanced", "intervlan"]) + @attr(tags=["advanced", "intervlan", "provisioning"]) def test_07_VPC_CreateAndDeleteAllLBRule(self): """ Test Delete all LB rules for a single virtual network of a VPC belonging to a single Public IP Address when the Virtual Router is in Running State @@ -747,7 +746,7 @@ def test_07_VPC_CreateAndDeleteAllLBRule(self): self.check_wget_from_vm(vm_1, public_ip_1, testnegative=True) return - @attr(tags=["advanced", "intervlan"]) + @attr(tags=["advanced", "intervlan", "provisioning"]) def test_08_VPC_CreateAndDeleteAllLBRuleVRStoppedState(self): """ Test Delete all LB rules for a single virtual network of a VPC belonging to a single Public IP Address when the Virtual Router is in Stopped State @@ -780,7 +779,7 @@ def test_08_VPC_CreateAndDeleteAllLBRuleVRStoppedState(self): self.check_wget_from_vm(vm_1, public_ip_1, testnegative=True) return - @attr(tags=["advanced", "intervlan"]) + @attr(tags=["advanced", "intervlan", "provisioning"]) def test_09_VPC_LBRuleCreateFailMultipleVPC(self): """ Test User should not be allowed to create a LB rule for a VM that belongs to a different VPC. """ @@ -818,7 +817,7 @@ def test_09_VPC_LBRuleCreateFailMultipleVPC(self): self.debug('Failed to Create LB rule vm_3 and vm_4') return - @attr(tags=["advanced", "intervlan"]) + @attr(tags=["advanced", "intervlan", "selfservice"]) def test_10_VPC_FailedToCreateLBRuleNonVPCNetwork(self): """ Test User should not be allowed to create a LB rule for a VM that does not belong to any VPC. """ @@ -855,7 +854,7 @@ def test_10_VPC_FailedToCreateLBRuleNonVPCNetwork(self): self.debug('Failed to Create LB rule vm_3 and vm_4 in network2') return - @attr(tags=["advanced", "intervlan"]) + @attr(tags=["advanced", "intervlan", "provisioning"]) def test_11_VPC_LBRuleCreateNotAllowed(self): """ Test case no 217 and 236: User should not be allowed to create a LB rule for a VM that does not belong to the same network but belongs to the same VPC. @@ -893,7 +892,7 @@ def test_11_VPC_LBRuleCreateNotAllowed(self): self.debug('Failed to Create LB rule vm_3 and vm_1') return - @attr(tags=["advanced", "intervlan"]) + @attr(tags=["advanced", "intervlan", "selfservice"]) def test_12_VPC_LBRuleCreateFailForRouterIP(self): """ Test User should not be allowed to create a LB rule on an Ipaddress that Source Nat enabled. """ @@ -921,7 +920,7 @@ def test_12_VPC_LBRuleCreateFailForRouterIP(self): self.debug('Failed to Create LB rule vm_2 and vm_1') return - @attr(tags=["advanced", "intervlan"]) + @attr(tags=["advanced", "intervlan", "provisioning"]) def test_13_VPC_LBRuleCreateFailForPFSourceNATIP(self): """ Test User should not be allowed to create a LB rule on an Ipaddress that already has a PF rule. """ @@ -951,7 +950,7 @@ def test_13_VPC_LBRuleCreateFailForPFSourceNATIP(self): self.debug('Failed to Create LB rule vm_2 and vm_1') return - @attr(tags=["advanced", "intervlan"]) + @attr(tags=["advanced", "intervlan", "selfservice"]) def test_14_VPC_LBRuleCreateFailForStaticNatRule(self): """ Test User should not be allowed to create a LB rule on an Ipaddress that already has a Static Nat rule. """ @@ -980,7 +979,7 @@ def test_14_VPC_LBRuleCreateFailForStaticNatRule(self): self.debug('Failed to Create LB rule vm_2 and vm_1') return - @attr(tags=["advanced", "intervlan"]) + @attr(tags=["advanced", "intervlan", "selfservice"]) def test_15_VPC_ReleaseIPForLBRuleCreated(self): """ Test release Ip address that has a LB rule assigned to it. """ diff --git a/test/integration/component/test_vpc_network_pfrules.py b/test/integration/component/test_vpc_network_pfrules.py index c65da4136a..31e7320267 100644 --- a/test/integration/component/test_vpc_network_pfrules.py +++ b/test/integration/component/test_vpc_network_pfrules.py @@ -19,7 +19,7 @@ """ from nose.plugins.attrib import attr from marvin.cloudstackTestCase import cloudstackTestCase, unittest -from marvin.integration.lib.base import (stopRouter, +from marvin.lib.base import (stopRouter, startRouter, Account, VpcOffering, @@ -32,11 +32,11 @@ Network, VirtualMachine, LoadBalancerRule) -from marvin.integration.lib.common import (get_domain, +from marvin.lib.common import (get_domain, get_zone, get_template, list_routers) -from marvin.integration.lib.utils import cleanup_resources +from marvin.lib.utils import cleanup_resources import socket import time @@ -182,14 +182,13 @@ def setUpClass(cls): # We want to fail quicker if it's failure socket.setdefaulttimeout(60) - cls.api_client = super( - TestVPCNetworkPFRules, - cls - ).getClsTestClient().getApiClient() + cls.testClient = super(TestVPCNetworkPFRules, cls).getClsTestClient() + cls.api_client = cls.testClient.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) + cls.domain = get_domain(cls.api_client) + cls.zone = get_zone(cls.api_client, cls.testClient.getZoneForTests()) cls.template = get_template( cls.api_client, cls.zone.id, @@ -484,7 +483,7 @@ def open_egress_to_world(self, network): return nwacl_internet_1 - @attr(tags=["advanced", "intervlan"]) + @attr(tags=["advanced", "intervlan", "provisioning"]) def test_01_network_services_VPC_StopCreatePF(self): """ Test : Create VPC PF rules on acquired public ip when VpcVirtualRouter is stopped """ @@ -515,7 +514,7 @@ def test_01_network_services_VPC_StopCreatePF(self): self.check_ssh_into_vm(vm_1, public_ip_1, testnegative=False) return - @attr(tags=["advanced", "intervlan"]) + @attr(tags=["advanced", "intervlan", "provisioning"]) def test_02_network_services_VPC_CreatePF(self): """ Test Create VPC PF rules on acquired public ip when VpcVirtualRouter is Running """ @@ -535,7 +534,7 @@ def test_02_network_services_VPC_CreatePF(self): self.check_ssh_into_vm(vm_1, public_ip_1, testnegative=False) return - @attr(tags=["advanced", "intervlan"]) + @attr(tags=["advanced", "intervlan", "provisioning"]) def test_03_network_services_VPC_StopCreateMultiplePF(self): """ Test Create multiple VPC PF rules on acquired public ip in diff't networks when VpcVirtualRouter is stopped """ @@ -571,7 +570,7 @@ def test_03_network_services_VPC_StopCreateMultiplePF(self): self.check_ssh_into_vm(vm_2, public_ip_2, testnegative=False) return - @attr(tags=["advanced", "intervlan"]) + @attr(tags=["advanced", "intervlan", "provisioning"]) def test_04_network_services_VPC_CreateMultiplePF(self): """ Test Create multiple VPC PF rules on acquired public ip in diff't networks when VpcVirtualRouter is running """ @@ -599,7 +598,7 @@ def test_04_network_services_VPC_CreateMultiplePF(self): self.check_ssh_into_vm(vm_2, public_ip_2, testnegative=False) return - @attr(tags=["advanced", "intervlan"]) + @attr(tags=["advanced", "intervlan", "provisioning"]) def test_05_network_services_VPC_StopDeletePF(self): """ Test delete a PF rule in VPC when VpcVirtualRouter is Stopped """ @@ -630,7 +629,7 @@ def test_05_network_services_VPC_StopDeletePF(self): self.check_wget_from_vm(vm_1, public_ip_1, testnegative=True) return - @attr(tags=["advanced", "intervlan"]) + @attr(tags=["advanced", "intervlan", "provisioning"]) def test_06_network_services_VPC_DeletePF(self): """ Test delete a PF rule in VPC when VpcVirtualRouter is Running """ @@ -657,7 +656,7 @@ def test_06_network_services_VPC_DeletePF(self): self.check_wget_from_vm(vm_1, public_ip_1, testnegative=True) return - @attr(tags=["advanced", "intervlan"]) + @attr(tags=["advanced", "intervlan", "provisioning"]) def test_07_network_services_VPC_StopDeleteAllPF(self): """ Test delete all PF rules in VPC when VpcVirtualRouter is Stopped """ @@ -691,7 +690,7 @@ def test_07_network_services_VPC_StopDeleteAllPF(self): self.check_wget_from_vm(vm_1, public_ip_1, testnegative=True) return - @attr(tags=["advanced", "intervlan"]) + @attr(tags=["advanced", "intervlan", "provisioning"]) def test_08_network_services_VPC_DeleteAllPF(self): """ Test delete all PF rules in VPC when VpcVirtualRouter is Running """ @@ -721,7 +720,7 @@ def test_08_network_services_VPC_DeleteAllPF(self): self.check_wget_from_vm(vm_1, public_ip_1, testnegative=True) return - @attr(tags=["advanced", "intervlan"]) + @attr(tags=["advanced", "intervlan", "provisioning"]) def test_09_network_services_VPC_StopDeleteAllMultiplePF(self): """ Test delete all PF rules in VPC across multiple networks when VpcVirtualRouter is Stopped """ @@ -788,7 +787,7 @@ def test_09_network_services_VPC_StopDeleteAllMultiplePF(self): self.check_wget_from_vm(vm_4, public_ip_4, testnegative=True) return - @attr(tags=["advanced", "intervlan"]) + @attr(tags=["advanced", "intervlan", "provisioning"]) def test_10_network_services_VPC_DeleteAllMultiplePF(self): """ Test delete all PF rules in VPC across multiple networks when VpcVirtualRouter is Running """ diff --git a/test/integration/component/test_vpc_network_staticnatrule.py b/test/integration/component/test_vpc_network_staticnatrule.py index 46e34796f6..65cb044c9a 100644 --- a/test/integration/component/test_vpc_network_staticnatrule.py +++ b/test/integration/component/test_vpc_network_staticnatrule.py @@ -19,7 +19,7 @@ """ from nose.plugins.attrib import attr from marvin.cloudstackTestCase import cloudstackTestCase, unittest -from marvin.integration.lib.base import (Account, +from marvin.lib.base import (Account, VpcOffering, VPC, ServiceOffering, @@ -32,11 +32,11 @@ StaticNATRule) from marvin.cloudstackAPI import (stopRouter, startRouter) -from marvin.integration.lib.common import (get_domain, +from marvin.lib.common import (get_domain, get_zone, get_template, list_routers) -from marvin.integration.lib.utils import cleanup_resources +from marvin.lib.utils import cleanup_resources import socket import time @@ -182,14 +182,13 @@ def setUpClass(cls): # We want to fail quicker if it's failure socket.setdefaulttimeout(60) - cls.api_client = super( - TestVPCNetworkPFRules, - cls - ).getClsTestClient().getApiClient() + cls.testClient = super(TestVPCNetworkPFRules, cls).getClsTestClient() + cls.api_client = cls.testClient.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) + cls.domain = get_domain(cls.api_client) + cls.zone = get_zone(cls.api_client, cls.testClient.getZoneForTests()) cls.template = get_template( cls.api_client, cls.zone.id, @@ -495,7 +494,7 @@ def create_ingress_rule(self, network, services=None): return nwacl_nat - @attr(tags=["advanced", "intervlan"]) + @attr(tags=["advanced", "intervlan", "provisioning"]) def test_01_VPC_StaticNatRuleCreateStoppedState(self): """ Test case no extra : """ @@ -523,7 +522,7 @@ def test_01_VPC_StaticNatRuleCreateStoppedState(self): return - @attr(tags=["advanced", "intervlan"]) + @attr(tags=["advanced", "intervlan", "provisioning"]) def test_02_VPC_CreateStaticNatRule(self): """ Test case no 229 : Create Static NAT Rule for a single virtual network of a VPC using a new Public IP Address available with the VPC when the Virtual Router is in Running State @@ -546,7 +545,7 @@ def test_02_VPC_CreateStaticNatRule(self): self.check_ssh_into_vm(vm_1, public_ip_1, testnegative=False) return - @attr(tags=["advanced", "intervlan"]) + @attr(tags=["advanced", "intervlan", "provisioning"]) def test_03_VPC_StopCreateMultipleStaticNatRuleStopppedState(self): """ Test case no extra : Create Static Nat Rule rules for a two/multiple virtual networks of a VPC using a new Public IP Address available with the VPC when Virtual Router is in Stopped State @@ -586,7 +585,7 @@ def test_03_VPC_StopCreateMultipleStaticNatRuleStopppedState(self): self.check_ssh_into_vm(vm_2, public_ip_2, testnegative=False) return - @attr(tags=["advanced", "intervlan"]) + @attr(tags=["advanced", "intervlan", "provisioning"]) def test_04_VPC_CreateMultipleStaticNatRule(self): """ Test case no 230 : Create Static NAT Rules for a two/multiple virtual networks of a VPC using a new Public IP Address available with the VPC when the Virtual Router is in Running State @@ -619,7 +618,7 @@ def test_04_VPC_CreateMultipleStaticNatRule(self): self.check_ssh_into_vm(vm_2, public_ip_2, testnegative=False) return - @attr(tags=["advanced", "intervlan"]) + @attr(tags=["advanced", "intervlan", "provisioning"]) def test_05_network_services_VPC_DeleteAllPF(self): """ Test case no 232: Delete all Static NAT Rules for a single virtual network of a VPC belonging to a single Public IP Address when the Virtual Router is in Running State @@ -651,7 +650,7 @@ def test_05_network_services_VPC_DeleteAllPF(self): self.check_wget_from_vm(vm_1, public_ip_1, testnegative=True) return - @attr(tags=["advanced", "intervlan"]) + @attr(tags=["advanced", "intervlan", "provisioning"]) def test_06_network_services_VPC_DeleteAllMultiplePF(self): """ Test case no 233: Delete all Static NAT rules for two/multiple virtual networks of a VPC. Observe the status of the Public IP Addresses of the rules when the Virtual Router is in Running State. diff --git a/test/integration/component/test_vpc_offerings.py b/test/integration/component/test_vpc_offerings.py index 699cef9d8f..f190773aab 100644 --- a/test/integration/component/test_vpc_offerings.py +++ b/test/integration/component/test_vpc_offerings.py @@ -23,9 +23,9 @@ 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.lib.utils import * +from marvin.lib.base import * +from marvin.lib.common import * from marvin.sshClient import SshClient import datetime @@ -137,14 +137,13 @@ class TestVPCOffering(cloudstackTestCase): @classmethod def setUpClass(cls): - cls.api_client = super( - TestVPCOffering, - cls - ).getClsTestClient().getApiClient() + cls.testClient = super(TestVPCOffering, cls).getClsTestClient() + cls.api_client = cls.testClient.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) + cls.domain = get_domain(cls.api_client) + cls.zone = get_zone(cls.api_client, cls.testClient.getZoneForTests()) cls.template = get_template( cls.api_client, cls.zone.id, @@ -235,7 +234,7 @@ def validate_vpc_network(self, network): self.debug("VPC network created successfully - %s" % network.name) return - @attr(tags=["advanced", "intervlan"]) + @attr(tags=["advanced", "intervlan", "selfservice"]) def test_01_create_vpc_offering(self): """ Test create VPC offering """ @@ -255,7 +254,7 @@ def test_01_create_vpc_offering(self): self.validate_vpc_offering(vpc_off) return - @attr(tags=["advanced", "intervlan"]) + @attr(tags=["advanced", "intervlan", "provisioning"]) def test_02_deploy_vms_in_vpc_nw(self): """Test deploy virtual machines in VPC networks""" @@ -457,7 +456,7 @@ def test_02_deploy_vms_in_vpc_nw(self): # TODO: Remote Access VPN is not yet supported in VPC return - @attr(tags=["advanced", "intervlan"]) + @attr(tags=["advanced", "intervlan", "selfservice"]) def test_03_vpc_off_without_lb(self): """Test VPC offering without load balancing service""" @@ -578,7 +577,7 @@ def test_03_vpc_off_without_lb(self): ) return - @attr(tags=["advanced", "intervlan"]) + @attr(tags=["advanced", "intervlan", "selfservice"]) def test_04_vpc_off_without_static_nat(self): """Test VPC offering without static NAT service""" @@ -697,7 +696,7 @@ def test_04_vpc_off_without_static_nat(self): ) return - @attr(tags=["advanced", "intervlan"]) + @attr(tags=["advanced", "intervlan", "selfservice"]) def test_05_vpc_off_without_pf(self): """Test VPC offering without port forwarding service""" @@ -815,7 +814,7 @@ def test_05_vpc_off_without_pf(self): ) return - @attr(tags=["advanced", "intervlan"]) + @attr(tags=["advanced", "intervlan", "selfservice"]) def test_06_vpc_off_invalid_services(self): """Test VPC offering with invalid services""" @@ -847,7 +846,7 @@ def test_06_vpc_off_invalid_services(self): self.fail("Failed to create the VPC offering - %s" % e) return - @attr(tags=["advanced", "intervlan"]) + @attr(tags=["advanced", "intervlan", "selfservice"]) def test_07_update_vpc_off(self): """Test update VPC offering""" @@ -936,7 +935,7 @@ def test_07_update_vpc_off(self): ) return - @attr(tags=["advanced", "intervlan"]) + @attr(tags=["advanced", "intervlan", "selfservice"]) def test_08_list_vpc_off(self): """Test list VPC offering""" diff --git a/test/integration/component/test_vpc_routers.py b/test/integration/component/test_vpc_routers.py index a83662740d..3cf537ae0b 100644 --- a/test/integration/component/test_vpc_routers.py +++ b/test/integration/component/test_vpc_routers.py @@ -22,9 +22,9 @@ 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.lib.utils import * +from marvin.lib.base import * +from marvin.lib.common import * import datetime @@ -169,16 +169,15 @@ class TestVPCRoutersBasic(cloudstackTestCase): @classmethod def setUpClass(cls): - cls.apiclient = super( - TestVPCRoutersBasic, - cls - ).getClsTestClient().getApiClient() + cls.testClient = super(TestVPCRoutersBasic, cls).getClsTestClient() + cls.api_client = cls.testClient.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.domain = get_domain(cls.api_client) + cls.zone = get_zone(cls.api_client, cls.testClient.getZoneForTests()) cls.template = get_template( - cls.apiclient, + cls.api_client, cls.zone.id, cls.services["ostype"] ) @@ -186,16 +185,16 @@ def setUpClass(cls): cls.services["virtual_machine"]["template"] = cls.template.id cls.service_offering = ServiceOffering.create( - cls.apiclient, + cls.api_client, cls.services["service_offering"] ) cls.vpc_off = VpcOffering.create( - cls.apiclient, + cls.api_client, cls.services["vpc_offering"] ) - cls.vpc_off.update(cls.apiclient, state='Enabled') + cls.vpc_off.update(cls.api_client, state='Enabled') cls.account = Account.create( - cls.apiclient, + cls.api_client, cls.services["account"], admin=True, domainid=cls.domain.id @@ -203,13 +202,13 @@ def setUpClass(cls): cls._cleanup = [cls.account] cls._cleanup.append(cls.vpc_off) #cls.debug("Enabling the VPC offering created") - cls.vpc_off.update(cls.apiclient, state='Enabled') + cls.vpc_off.update(cls.api_client, state='Enabled') #cls.debug("creating a VPC network in the account: %s" % # cls.account.name) cls.services["vpc"]["cidr"] = '10.1.1.1/16' cls.vpc = VPC.create( - cls.apiclient, + cls.api_client, cls.services["vpc"], vpcofferingid=cls.vpc_off.id, zoneid=cls.zone.id, @@ -224,13 +223,13 @@ def setUpClass(cls): def tearDownClass(cls): try: #Cleanup resources used - cleanup_resources(cls.apiclient, cls._cleanup) + 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.api_client = self.testClient.getApiClient() return @@ -242,7 +241,7 @@ def validate_vpc_offering(self, vpc_offering): self.debug("Check if the VPC offering is created successfully?") vpc_offs = VpcOffering.list( - self.apiclient, + self.api_client, id=vpc_offering.id ) self.assertEqual( @@ -265,7 +264,7 @@ def validate_vpc_network(self, network, state=None): self.debug("Check if the VPC network is created successfully?") vpc_networks = VPC.list( - self.apiclient, + self.api_client, id=network.id ) self.assertEqual( @@ -291,7 +290,7 @@ def migrate_router(self, router): """ Migrate the router """ self.debug("Checking if the host is available for migration?") - hosts = Host.list(self.apiclient, zoneid=self.zone.id, type='Routing') + hosts = Host.list(self.api_client, zoneid=self.zone.id, type='Routing') self.assertEqual( isinstance(hosts, list), @@ -319,7 +318,7 @@ def migrate_router(self, router): cmd.isAsync = "false" cmd.hostid = host.id cmd.virtualmachineid = router.id - self.apiclient.migrateSystemVm(cmd) + self.api_client.migrateSystemVm(cmd) except Exception as e: self.fail("Failed to migrate instance, %s" % e) @@ -329,7 +328,7 @@ def migrate_router(self, router): #List routers to check state of router router_response = list_routers( - self.apiclient, + self.api_client, id=router.id ) self.assertEqual( @@ -343,7 +342,7 @@ def migrate_router(self, router): " still %s" % (host.id, router.hostid)) return - @attr(tags=["advanced", "intervlan"]) + @attr(tags=["advanced", "intervlan", "selfservice"]) def test_01_stop_start_router_after_creating_vpc(self): """ Test to stop and start router after creation of VPC """ @@ -358,7 +357,7 @@ def test_01_stop_start_router_after_creating_vpc(self): # Stop the VPC Router routers = Router.list( - self.apiclient, + self.api_client, account=self.account.name, domainid=self.account.domainid, listall=True @@ -374,11 +373,11 @@ def test_01_stop_start_router_after_creating_vpc(self): #Stop the router cmd = stopRouter.stopRouterCmd() cmd.id = router.id - self.apiclient.stopRouter(cmd) + self.api_client.stopRouter(cmd) #List routers to check state of router router_response = list_routers( - self.apiclient, + self.api_client, id=router.id ) self.assertEqual( @@ -399,11 +398,11 @@ def test_01_stop_start_router_after_creating_vpc(self): self.debug("Starting the router with ID: %s" % router.id) cmd = startRouter.startRouterCmd() cmd.id = router.id - self.apiclient.startRouter(cmd) + self.api_client.startRouter(cmd) #List routers to check state of router router_response = list_routers( - self.apiclient, + self.api_client, id=router.id ) self.assertEqual( @@ -421,7 +420,7 @@ def test_01_stop_start_router_after_creating_vpc(self): return - @attr(tags=["advanced", "intervlan"]) + @attr(tags=["advanced", "intervlan", "selfservice"]) def test_02_reboot_router_after_creating_vpc(self): """ Test to reboot the router after creating a VPC """ @@ -433,7 +432,7 @@ def test_02_reboot_router_after_creating_vpc(self): self.validate_vpc_offering(self.vpc_off) self.validate_vpc_network(self.vpc) routers = Router.list( - self.apiclient, + self.api_client, account=self.account.name, domainid=self.account.domainid, listall=True @@ -449,11 +448,11 @@ def test_02_reboot_router_after_creating_vpc(self): #Reboot the router cmd = rebootRouter.rebootRouterCmd() cmd.id = router.id - self.apiclient.rebootRouter(cmd) + self.api_client.rebootRouter(cmd) #List routers to check state of router router_response = list_routers( - self.apiclient, + self.api_client, id=router.id ) self.assertEqual( @@ -470,7 +469,7 @@ def test_02_reboot_router_after_creating_vpc(self): return - @attr(tags=["advanced", "intervlan"]) + @attr(tags=["advanced", "intervlan", "provisioning"]) def test_03_migrate_router_after_creating_vpc(self): """ Test migration of router to another host after creating VPC """ @@ -478,7 +477,7 @@ def test_03_migrate_router_after_creating_vpc(self): self.validate_vpc_network(self.vpc) routers = Router.list( - self.apiclient, + self.api_client, account=self.account.name, domainid=self.account.domainid, listall=True @@ -491,7 +490,7 @@ def test_03_migrate_router_after_creating_vpc(self): self.migrate_router(routers[0]) return - @attr(tags=["advanced", "intervlan"]) + @attr(tags=["advanced", "intervlan", "selfservice"]) def test_04_change_service_offerring_vpc(self): """ Tests to change service offering of the Router after creating a vpc @@ -505,7 +504,7 @@ def test_04_change_service_offerring_vpc(self): self.validate_vpc_network(self.vpc) routers = Router.list( - self.apiclient, + self.api_client, account=self.account.name, domainid=self.account.domainid, listall=True @@ -521,15 +520,15 @@ def test_04_change_service_offerring_vpc(self): self.debug("Stopping the router with ID: %s" % router.id) cmd = stopRouter.stopRouterCmd() cmd.id = router.id - self.apiclient.stopRouter(cmd) + self.api_client.stopRouter(cmd) service_offering = ServiceOffering.create( - self.apiclient, + self.api_client, self.services["service_offering_new"] ) self.debug("Changing service offering for the Router %s" % router.id) try: - router = Router.change_service_offering(self.apiclient, + router = Router.change_service_offering(self.api_client, router.id, service_offering.id ) @@ -538,7 +537,7 @@ def test_04_change_service_offerring_vpc(self): self.debug("Router %s" % router) routers = Router.list( - self.apiclient, + self.api_client, account=self.account.name, domainid=self.account.domainid, listall=True @@ -552,7 +551,7 @@ def test_04_change_service_offerring_vpc(self): ) return - @attr(tags=["advanced", "intervlan"]) + @attr(tags=["advanced", "intervlan", "selfservice"]) def test_05_destroy_router_after_creating_vpc(self): """ Test to destroy the router after creating a VPC """ @@ -562,7 +561,7 @@ def test_05_destroy_router_after_creating_vpc(self): self.validate_vpc_offering(self.vpc_off) self.validate_vpc_network(self.vpc) routers = Router.list( - self.apiclient, + self.api_client, account=self.account.name, domainid=self.account.domainid, listall=True @@ -573,12 +572,12 @@ def test_05_destroy_router_after_creating_vpc(self): "List Routers should return a valid list" ) - Router.destroy( self.apiclient, + Router.destroy( self.api_client, id=routers[0].id ) routers = Router.list( - self.apiclient, + self.api_client, account=self.account.name, domainid=self.account.domainid, listall=True @@ -594,17 +593,16 @@ class TestVPCRouterOneNetwork(cloudstackTestCase): @classmethod def setUpClass(cls): - cls.apiclient = super( - TestVPCRouterOneNetwork, - cls - ).getClsTestClient().getApiClient() cls._cleanup = [] + cls.testClient = super(TestVPCRouterOneNetwork, cls).getClsTestClient() + cls.api_client = cls.testClient.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.domain = get_domain(cls.api_client) + cls.zone = get_zone(cls.api_client, cls.testClient.getZoneForTests()) cls.template = get_template( - cls.apiclient, + cls.api_client, cls.zone.id, cls.services["ostype"] ) @@ -612,19 +610,19 @@ def setUpClass(cls): cls.services["virtual_machine"]["template"] = cls.template.id cls.service_offering = ServiceOffering.create( - cls.apiclient, + cls.api_client, cls.services["service_offering"] ) cls._cleanup.append(cls.service_offering) cls.vpc_off = VpcOffering.create( - cls.apiclient, + cls.api_client, cls.services["vpc_offering"] ) - cls.vpc_off.update(cls.apiclient, state='Enabled') + cls.vpc_off.update(cls.api_client, state='Enabled') cls._cleanup.append(cls.vpc_off) cls.account = Account.create( - cls.apiclient, + cls.api_client, cls.services["account"], admin=True, domainid=cls.domain.id @@ -633,7 +631,7 @@ def setUpClass(cls): cls.services["vpc"]["cidr"] = '10.1.1.1/16' cls.vpc = VPC.create( - cls.apiclient, + cls.api_client, cls.services["vpc"], vpcofferingid=cls.vpc_off.id, zoneid=cls.zone.id, @@ -642,7 +640,7 @@ def setUpClass(cls): ) private_gateway = PrivateGateway.create( - cls.apiclient, + cls.api_client, gateway='10.1.3.1', ipaddress='10.1.3.100', netmask='255.255.255.0', @@ -650,34 +648,34 @@ def setUpClass(cls): vpcid=cls.vpc.id ) cls.gateways = PrivateGateway.list( - cls.apiclient, + cls.api_client, id=private_gateway.id, listall=True ) static_route = StaticRoute.create( - cls.apiclient, + cls.api_client, cidr='11.1.1.1/24', gatewayid=private_gateway.id ) cls.static_routes = StaticRoute.list( - cls.apiclient, + cls.api_client, id=static_route.id, listall=True ) cls.nw_off = NetworkOffering.create( - cls.apiclient, + cls.api_client, cls.services["network_offering"], conservemode=False ) # Enable Network offering - cls.nw_off.update(cls.apiclient, state='Enabled') + cls.nw_off.update(cls.api_client, state='Enabled') cls._cleanup.append(cls.nw_off) # Creating network using the network offering created cls.network_1 = Network.create( - cls.apiclient, + cls.api_client, cls.services["network"], accountid=cls.account.name, domainid=cls.account.domainid, @@ -689,7 +687,7 @@ def setUpClass(cls): # Spawn an instance in that network vm_1 = VirtualMachine.create( - cls.apiclient, + cls.api_client, cls.services["virtual_machine"], accountid=cls.account.name, domainid=cls.account.domainid, @@ -697,7 +695,7 @@ def setUpClass(cls): networkids=[str(cls.network_1.id)] ) vm_2 = VirtualMachine.create( - cls.apiclient, + cls.api_client, cls.services["virtual_machine"], accountid=cls.account.name, domainid=cls.account.domainid, @@ -707,7 +705,7 @@ def setUpClass(cls): # Spawn an instance in that network vm_3 = VirtualMachine.create( - cls.apiclient, + cls.api_client, cls.services["virtual_machine"], accountid=cls.account.name, domainid=cls.account.domainid, @@ -716,14 +714,14 @@ def setUpClass(cls): ) vms = VirtualMachine.list( - cls.apiclient, + cls.api_client, account=cls.account.name, domainid=cls.account.domainid, listall=True ) public_ip_1 = PublicIPAddress.create( - cls.apiclient, + cls.api_client, accountid=cls.account.name, zoneid=cls.zone.id, domainid=cls.account.domainid, @@ -732,7 +730,7 @@ def setUpClass(cls): ) nat_rule = NATRule.create( - cls.apiclient, + cls.api_client, vm_1, cls.services["natrule"], ipaddressid=public_ip_1.ipaddress.id, @@ -742,14 +740,14 @@ def setUpClass(cls): ) nwacl_nat = NetworkACL.create( - cls.apiclient, + cls.api_client, networkid=cls.network_1.id, services=cls.services["natrule"], traffictype='Ingress' ) public_ip_2 = PublicIPAddress.create( - cls.apiclient, + cls.api_client, accountid=cls.account.name, zoneid=cls.zone.id, domainid=cls.account.domainid, @@ -758,7 +756,7 @@ def setUpClass(cls): ) try: StaticNATRule.enable( - cls.apiclient, + cls.api_client, ipaddressid=public_ip_2.ipaddress.id, virtualmachineid=vm_2.id, networkid=cls.network_1.id @@ -768,7 +766,7 @@ def setUpClass(cls): public_ip_2.ipaddress.ipaddress, e)) public_ips = PublicIPAddress.list( - cls.apiclient, + cls.api_client, networkid=cls.network_1.id, listall=True, isstaticnat=True, @@ -776,7 +774,7 @@ def setUpClass(cls): domainid=cls.account.domainid ) public_ip_3 = PublicIPAddress.create( - cls.apiclient, + cls.api_client, accountid=cls.account.name, zoneid=cls.zone.id, domainid=cls.account.domainid, @@ -785,7 +783,7 @@ def setUpClass(cls): ) lb_rule = LoadBalancerRule.create( - cls.apiclient, + cls.api_client, cls.services["lbrule"], ipaddressid=public_ip_3.ipaddress.id, accountid=cls.account.name, @@ -794,17 +792,17 @@ def setUpClass(cls): domainid=cls.account.domainid ) - lb_rule.assign(cls.apiclient, [vm_3]) + lb_rule.assign(cls.api_client, [vm_3]) nwacl_lb = NetworkACL.create( - cls.apiclient, + cls.api_client, networkid=cls.network_1.id, services=cls.services["lbrule"], traffictype='Ingress' ) nwacl_internet_1 = NetworkACL.create( - cls.apiclient, + cls.api_client, networkid=cls.network_1.id, services=cls.services["http_rule"], traffictype='Egress' @@ -814,20 +812,20 @@ def setUpClass(cls): def tearDownClass(cls): try: #Cleanup resources used - cleanup_resources(cls.apiclient, cls._cleanup) + 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.api_client = self.testClient.getApiClient() self.cleanup = [] return def tearDown(self): try: #Clean up, terminate the created network offerings - cleanup_resources(self.apiclient, self.cleanup) + cleanup_resources(self.api_client, self.cleanup) except Exception as e: raise Exception("Warning: Exception during cleanup : %s" % e) @@ -838,7 +836,7 @@ def validate_vpc_offering(self, vpc_offering): self.debug("Check if the VPC offering is created successfully?") vpc_offs = VpcOffering.list( - self.apiclient, + self.api_client, id=vpc_offering.id ) self.assertEqual( @@ -861,7 +859,7 @@ def validate_vpc_network(self, network, state=None): self.debug("Check if the VPC network is created successfully?") vpc_networks = VPC.list( - self.apiclient, + self.api_client, id=network.id ) self.assertEqual( @@ -887,13 +885,13 @@ def validate_network_rules(self): """ Validate network rules """ vms = VirtualMachine.list( - self.apiclient, + self.api_client, account=self.account.name, domainid=self.account.domainid, listall=True ) public_ips = PublicIPAddress.list( - self.apiclient, + self.api_client, account=self.account.name, domainid=self.account.domainid, listall=True @@ -927,7 +925,7 @@ def migrate_router(self, router): """ Migrate the router """ self.debug("Checking if the host is available for migration?") - hosts = Host.list(self.apiclient, zoneid=self.zone.id, type='Routing') + hosts = Host.list(self.api_client, zoneid=self.zone.id, type='Routing') self.assertEqual( isinstance(hosts, list), @@ -955,7 +953,7 @@ def migrate_router(self, router): cmd.isAsync = "false" cmd.hostid = host.id cmd.virtualmachineid = router.id - self.apiclient.migrateSystemVm(cmd) + self.api_client.migrateSystemVm(cmd) except Exception as e: self.fail("Failed to migrate instance, %s" % e) @@ -965,7 +963,7 @@ def migrate_router(self, router): #List routers to check state of router router_response = list_routers( - self.apiclient, + self.api_client, id=router.id ) self.assertEqual( @@ -980,7 +978,7 @@ def migrate_router(self, router): return - @attr(tags=["advanced", "intervlan"]) + @attr(tags=["advanced", "intervlan", "provisioining"]) def test_01_start_stop_router_after_addition_of_one_guest_network(self): """ Test start/stop of router after addition of one guest network """ @@ -1012,7 +1010,7 @@ def test_01_start_stop_router_after_addition_of_one_guest_network(self): # Stop the VPC Router routers = Router.list( - self.apiclient, + self.api_client, account=self.account.name, domainid=self.account.domainid, listall=True @@ -1028,11 +1026,11 @@ def test_01_start_stop_router_after_addition_of_one_guest_network(self): #Stop the router cmd = stopRouter.stopRouterCmd() cmd.id = router.id - self.apiclient.stopRouter(cmd) + self.api_client.stopRouter(cmd) #List routers to check state of router router_response = list_routers( - self.apiclient, + self.api_client, id=router.id ) self.assertEqual( @@ -1053,11 +1051,11 @@ def test_01_start_stop_router_after_addition_of_one_guest_network(self): self.debug("Starting the router with ID: %s" % router.id) cmd = startRouter.startRouterCmd() cmd.id = router.id - self.apiclient.startRouter(cmd) + self.api_client.startRouter(cmd) #List routers to check state of router router_response = list_routers( - self.apiclient, + self.api_client, id=router.id ) self.assertEqual( @@ -1075,7 +1073,7 @@ def test_01_start_stop_router_after_addition_of_one_guest_network(self): return - @attr(tags=["advanced", "intervlan"]) + @attr(tags=["advanced", "intervlan", "selfservice"]) def test_02_reboot_router_after_addition_of_one_guest_network(self): """ Test reboot of router after addition of one guest network """ @@ -1106,7 +1104,7 @@ def test_02_reboot_router_after_addition_of_one_guest_network(self): ) routers = Router.list( - self.apiclient, + self.api_client, account=self.account.name, domainid=self.account.domainid, listall=True @@ -1122,11 +1120,11 @@ def test_02_reboot_router_after_addition_of_one_guest_network(self): #Reboot the router cmd = rebootRouter.rebootRouterCmd() cmd.id = router.id - self.apiclient.rebootRouter(cmd) + self.api_client.rebootRouter(cmd) #List routers to check state of router router_response = list_routers( - self.apiclient, + self.api_client, id=router.id ) self.assertEqual( @@ -1142,7 +1140,7 @@ def test_02_reboot_router_after_addition_of_one_guest_network(self): ) return - @attr(tags=["advanced", "intervlan"]) + @attr(tags=["advanced", "intervlan", "provisioning"]) def test_03_migrate_router_after_addition_of_one_guest_network(self): """ Test migrate of router after addition of one guest network """ @@ -1172,7 +1170,7 @@ def test_03_migrate_router_after_addition_of_one_guest_network(self): "List static route should return a valid response" ) routers = Router.list( - self.apiclient, + self.api_client, account=self.account.name, domainid=self.account.domainid, listall=True @@ -1185,7 +1183,7 @@ def test_03_migrate_router_after_addition_of_one_guest_network(self): self.migrate_router(routers[0]) return - @attr(tags=["advanced", "intervlan"]) + @attr(tags=["advanced", "intervlan", "selfservice"]) def test_04_chg_srv_off_router_after_addition_of_one_guest_network(self): """ Test to change service offering of router after addition of one guest network """ @@ -1216,7 +1214,7 @@ def test_04_chg_srv_off_router_after_addition_of_one_guest_network(self): ) routers = Router.list( - self.apiclient, + self.api_client, account=self.account.name, domainid=self.account.domainid, listall=True @@ -1232,15 +1230,15 @@ def test_04_chg_srv_off_router_after_addition_of_one_guest_network(self): self.debug("Stopping the router with ID: %s" % router.id) cmd = stopRouter.stopRouterCmd() cmd.id = router.id - self.apiclient.stopRouter(cmd) + self.api_client.stopRouter(cmd) service_offering = ServiceOffering.create( - self.apiclient, + self.api_client, self.services["service_offering_new"] ) self.debug("Changing service offering for the Router %s" % router.id) try: - router = Router.change_service_offering(self.apiclient, + router = Router.change_service_offering(self.api_client, router.id, service_offering.id ) @@ -1249,7 +1247,7 @@ def test_04_chg_srv_off_router_after_addition_of_one_guest_network(self): self.debug("Router %s" % router) routers = Router.list( - self.apiclient, + self.api_client, account=self.account.name, domainid=self.account.domainid, listall=True @@ -1263,7 +1261,7 @@ def test_04_chg_srv_off_router_after_addition_of_one_guest_network(self): ) return - @attr(tags=["advanced", "intervlan"]) + @attr(tags=["advanced", "intervlan", "selfservice"]) def test_05_destroy_router_after_addition_of_one_guest_network(self): """ Test destroy of router after addition of one guest network """ @@ -1294,7 +1292,7 @@ def test_05_destroy_router_after_addition_of_one_guest_network(self): ) routers = Router.list( - self.apiclient, + self.api_client, account=self.account.name, domainid=self.account.domainid, listall=True @@ -1305,12 +1303,12 @@ def test_05_destroy_router_after_addition_of_one_guest_network(self): "List Routers should return a valid list" ) - Router.destroy( self.apiclient, + Router.destroy( self.api_client, id=routers[0].id ) routers = Router.list( - self.apiclient, + self.api_client, account=self.account.name, domainid=self.account.domainid, listall=True diff --git a/test/integration/component/test_vpc_vm_life_cycle.py b/test/integration/component/test_vpc_vm_life_cycle.py index e40067ea86..fd995cdd5d 100644 --- a/test/integration/component/test_vpc_vm_life_cycle.py +++ b/test/integration/component/test_vpc_vm_life_cycle.py @@ -19,9 +19,9 @@ """ #Import Local Modules from nose.plugins.attrib import attr -from marvin.cloudstackTestCase import cloudstackTestCase, unittest -from marvin.integration.lib.utils import cleanup_resources, validateList -from marvin.integration.lib.base import (VirtualMachine, +from marvin.cloudstackTestCase import cloudstackTestCase +from marvin.lib.utils import cleanup_resources, validateList +from marvin.lib.base import (VirtualMachine, NATRule, LoadBalancerRule, StaticNATRule, @@ -35,7 +35,7 @@ Account, ServiceOffering, Host) -from marvin.integration.lib.common import (get_domain, +from marvin.lib.common import (get_domain, get_zone, get_template, get_free_vlan, @@ -212,14 +212,13 @@ class TestVMLifeCycleVPC(cloudstackTestCase): @classmethod def setUpClass(cls): - cls.api_client = super( - TestVMLifeCycleVPC, - cls - ).getClsTestClient().getApiClient() + cls.testClient = super(TestVMLifeCycleVPC, cls).getClsTestClient() + cls.api_client = cls.testClient.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) + cls.domain = get_domain(cls.api_client) + cls.zone = get_zone(cls.api_client, cls.testClient.getZoneForTests()) cls.template = get_template( cls.api_client, cls.zone.id, @@ -873,14 +872,13 @@ class TestVMLifeCycleSharedNwVPC(cloudstackTestCase): @classmethod def setUpClass(cls): - cls.api_client = super( - TestVMLifeCycleSharedNwVPC, - cls - ).getClsTestClient().getApiClient() + cls.testClient = super(TestVMLifeCycleSharedNwVPC, cls).getClsTestClient() + cls.api_client = cls.testClient.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) + cls.domain = get_domain(cls.api_client) + cls.zone = get_zone(cls.api_client, cls.testClient.getZoneForTests()) cls.template = get_template( cls.api_client, cls.zone.id, @@ -1258,24 +1256,6 @@ def test_02_stop_instance_in_network(self): except Exception as e: self.fail("Failed to stop the virtual instances, %s" % e) - self.debug("Check if the instance is in stopped state?") - vms = VirtualMachine.list( - self.apiclient, - id=self.vm_2.id, - listall=True - ) - self.assertEqual( - isinstance(vms, list), - True, - "List virtual machines should return a valid list" - ) - vm = vms[0] - self.assertEqual( - vm.state, - "Stopped", - "Virtual machine should be in stopped state" - ) - self.debug("Validating if network rules are coonfigured properly?") self.validate_network_rules() return @@ -1660,14 +1640,13 @@ class TestVMLifeCycleBothIsolated(cloudstackTestCase): @classmethod def setUpClass(cls): - cls.api_client = super( - TestVMLifeCycleBothIsolated, - cls - ).getClsTestClient().getApiClient() + cls.testClient = super(TestVMLifeCycleBothIsolated, cls).getClsTestClient() + cls.api_client = cls.testClient.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) + cls.domain = get_domain(cls.api_client) + cls.zone = get_zone(cls.api_client, cls.testClient.getZoneForTests()) cls.template = get_template( cls.api_client, cls.zone.id, @@ -1995,14 +1974,13 @@ class TestVMLifeCycleStoppedVPCVR(cloudstackTestCase): @classmethod def setUpClass(cls): - cls.api_client = super( - TestVMLifeCycleStoppedVPCVR, - cls - ).getClsTestClient().getApiClient() + cls.testClient = super(TestVMLifeCycleStoppedVPCVR, cls).getClsTestClient() + cls.api_client = cls.testClient.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) + cls.domain = get_domain(cls.api_client) + cls.zone = get_zone(cls.api_client, cls.testClient.getZoneForTests()) cls.template = get_template( cls.api_client, cls.zone.id, @@ -2681,14 +2659,13 @@ class TestVMLifeCycleDiffHosts(cloudstackTestCase): def setUpClass(cls): try: - cls.api_client = super( - TestVMLifeCycleDiffHosts, - cls - ).getClsTestClient().getApiClient() + cls.testClient = super(TestVMLifeCycleDiffHosts, cls).getClsTestClient() + cls.api_client = cls.testClient.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) + cls.domain = get_domain(cls.api_client) + cls.zone = get_zone(cls.api_client, cls.testClient.getZoneForTests()) cls.template = get_template( cls.api_client, cls.zone.id, @@ -3104,35 +3081,7 @@ def test_02_stop_instance_in_network(self): self.account.name) try: self.vm_1.stop(self.apiclient) - - list_vm_response = list_virtual_machines( - self.apiclient, - id=self.vm_1.id - ) - - vm_response = list_vm_response[0] - - self.assertEqual( - vm_response.state, - 'Stopped', - "VM state should be stopped" - ) - self.vm_2.stop(self.apiclient) - - list_vm_response = list_virtual_machines( - self.apiclient, - id=self.vm_2.id - ) - - vm_response = list_vm_response[0] - - self.assertEqual( - vm_response.state, - 'Stopped', - "VM state should be stopped" - ) - except Exception as e: self.fail("Failed to stop the virtual instances, %s" % e) diff --git a/test/integration/component/test_vpc_vms_deployment.py b/test/integration/component/test_vpc_vms_deployment.py index 0a244ab656..1c1f93d37e 100644 --- a/test/integration/component/test_vpc_vms_deployment.py +++ b/test/integration/component/test_vpc_vms_deployment.py @@ -20,7 +20,7 @@ #Import Local Modules from nose.plugins.attrib import attr from marvin.cloudstackTestCase import cloudstackTestCase, unittest -from marvin.integration.lib.base import (VirtualMachine, +from marvin.lib.base import (VirtualMachine, NetworkOffering, VpcOffering, VPC, @@ -36,13 +36,13 @@ StaticNATRule, Configurations) -from marvin.integration.lib.common import (get_domain, +from marvin.lib.common import (get_domain, get_zone, get_template, wait_for_cleanup, get_free_vlan) -from marvin.integration.lib.utils import cleanup_resources +from marvin.lib.utils import cleanup_resources from marvin.cloudstackAPI import rebootRouter @@ -166,14 +166,13 @@ class TestVMDeployVPC(cloudstackTestCase): @classmethod def setUpClass(cls): - cls.api_client = super( - TestVMDeployVPC, - cls - ).getClsTestClient().getApiClient() + cls.testClient = super(TestVMDeployVPC, cls).getClsTestClient() + cls.api_client = cls.testClient.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) + cls.domain = get_domain(cls.api_client) + cls.zone = get_zone(cls.api_client, cls.testClient.getZoneForTests()) cls.template = get_template( cls.api_client, cls.zone.id, @@ -276,7 +275,7 @@ def validate_vpc_network(self, network, state=None): self.debug("VPC network validated - %s" % network.name) return - @attr(tags=["advanced", "intervlan"]) + @attr(tags=["advanced", "intervlan", "selfservice"]) def test_01_deploy_vms_in_network(self): """ Test deploy VMs in VPC networks """ @@ -490,7 +489,7 @@ def test_01_deploy_vms_in_network(self): ) return - @attr(tags=["advanced", "intervlan"]) + @attr(tags=["advanced", "intervlan", "selfservice"]) def test_02_deploy_vms_delete_network(self): """ Test deploy VMs in VPC networks and delete one of the network """ @@ -742,7 +741,7 @@ def test_02_deploy_vms_delete_network(self): ) return - @attr(tags=["advanced", "intervlan"]) + @attr(tags=["advanced", "intervlan", "selfservice"]) def test_03_deploy_vms_delete_add_network(self): """ Test deploy VMs, delete one of the network and add another one """ @@ -1011,7 +1010,7 @@ def test_03_deploy_vms_delete_add_network(self): ) return - @attr(tags=["advanced", "intervlan"]) + @attr(tags=["advanced", "intervlan", "selfservice"]) def test_04_deploy_vms_delete_add_network_noLb(self): """ Test deploy VMs, delete one network without LB and add another one """ @@ -1305,7 +1304,7 @@ def test_04_deploy_vms_delete_add_network_noLb(self): ) return - @attr(tags=["advanced", "intervlan"]) + @attr(tags=["advanced", "intervlan", "selfservice"]) def test_05_create_network_max_limit(self): """ Test create networks in VPC upto maximum limit for hypervisor """ @@ -1476,7 +1475,7 @@ def test_05_create_network_max_limit(self): ) return - @attr(tags=["advanced", "intervlan"]) + @attr(tags=["advanced", "intervlan", "selfservice"]) def test_06_delete_network_vm_running(self): """ Test delete network having running instances in VPC """ @@ -1718,7 +1717,7 @@ def test_06_delete_network_vm_running(self): ) return - @attr(tags=["advanced", "intervlan"]) + @attr(tags=["advanced", "intervlan", "selfservice"]) def test_07_delete_network_with_rules(self): """ Test delete network that has PF/staticNat/LB rules/Network Acl """ diff --git a/test/integration/component/test_vpn_users.py b/test/integration/component/test_vpn_users.py index 02dd02622a..c8b3a2dbac 100644 --- a/test/integration/component/test_vpn_users.py +++ b/test/integration/component/test_vpn_users.py @@ -19,9 +19,9 @@ """ # Import Local Modules from nose.plugins.attrib import attr -from marvin.cloudstackException import cloudstackAPIException +from marvin.cloudstackException import CloudstackAPIException from marvin.cloudstackTestCase import cloudstackTestCase -from marvin.integration.lib.base import ( +from marvin.lib.base import ( Account, ServiceOffering, VirtualMachine, @@ -31,11 +31,11 @@ Configurations, NATRule ) -from marvin.integration.lib.common import (get_domain, +from marvin.lib.common import (get_domain, get_zone, get_template ) -from marvin.integration.lib.utils import cleanup_resources +from marvin.lib.utils import cleanup_resources class Services: @@ -94,12 +94,13 @@ def __init__(self): class TestVPNUsers(cloudstackTestCase): @classmethod def setUpClass(cls): - cls.api_client = super(TestVPNUsers, - cls).getClsTestClient().getApiClient() + cls.testClient = super(TestVPNUsers, cls).getClsTestClient() + cls.api_client = cls.testClient.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) + cls.domain = get_domain(cls.api_client) + cls.zone = get_zone(cls.api_client, cls.testClient.getZoneForTests()) cls.services["mode"] = cls.zone.networktype @@ -155,7 +156,7 @@ def setUp(self): services=self.services["virtual_machine"] ) return - except cloudstackAPIException as e: + except CloudstackAPIException as e: self.tearDown() raise e @@ -258,7 +259,7 @@ def test_01_VPN_user_limit(self): self.debug("Limit exceeded exception raised!") return - @attr(tags=["advanced", "advancedns"]) + @attr(tags=["advanced", "advancedns", "selfservice"]) def test_02_use_vpn_port(self): """Test create VPN when L2TP port in use""" @@ -289,7 +290,7 @@ def test_02_use_vpn_port(self): self.debug("Create VPN connection failed! Test successful!") return - @attr(tags=["advanced", "advancedns"]) + @attr(tags=["advanced", "advancedns", "selfservice"]) def test_03_enable_vpn_use_port(self): """Test create NAT rule when VPN when L2TP enabled""" @@ -315,7 +316,7 @@ def test_03_enable_vpn_use_port(self): self.debug("Create NAT rule failed! Test successful!") return - @attr(tags=["advanced", "advancedns"]) + @attr(tags=["advanced", "advancedns", "selfservice"]) def test_04_add_new_users(self): """Test add new users to existing VPN""" @@ -343,7 +344,7 @@ def test_04_add_new_users(self): self.fail("Failed to create new VPN user: %s" % e) return - @attr(tags=["advanced", "advancedns"]) + @attr(tags=["advanced", "advancedns", "selfservice"]) def test_05_add_duplicate_user(self): """Test add duplicate user to existing VPN""" @@ -366,7 +367,7 @@ def test_05_add_duplicate_user(self): self.create_VPN_Users(rand_name=False) return - @attr(tags=["advanced", "advancedns"]) + @attr(tags=["advanced", "advancedns", "selfservice"]) def test_06_add_VPN_user_global_admin(self): """Test as global admin, add a new VPN user to an existing VPN entry that was created by another account.""" @@ -396,7 +397,7 @@ def test_06_add_VPN_user_global_admin(self): domainid=self.account.domainid) self.cleanup.append(admin) self.debug("Creating API client for newly created user") - api_client = self.testClient.createUserApiClient( + api_client = self.testClient.getUserApiClient( UserName=self.account.name, DomainName=self.account.domain) @@ -409,7 +410,7 @@ def test_06_add_VPN_user_global_admin(self): e) return - @attr(tags=["advanced", "advancedns"]) + @attr(tags=["advanced", "advancedns", "selfservice"]) def test_07_add_VPN_user_domain_admin(self): """Test as domain admin, add a new VPN user to an existing VPN entry that was created by another account.""" @@ -438,7 +439,7 @@ def test_07_add_VPN_user_domain_admin(self): domainid=self.account.domainid) self.cleanup.append(admin) self.debug("Creating API client for newly created user") - api_client = self.testClient.createUserApiClient( + api_client = self.testClient.getUserApiClient( UserName=self.account.name, DomainName=self.account.domain) diff --git a/test/integration/smoke/test_affinity_groups.py b/test/integration/smoke/test_affinity_groups.py index c96a580f19..4f3f9ec875 100644 --- a/test/integration/smoke/test_affinity_groups.py +++ b/test/integration/smoke/test_affinity_groups.py @@ -16,52 +16,15 @@ # specific language governing permissions and limitations # under the License. +from marvin.codes import FAILED 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.lib.utils import * +from marvin.lib.base import * +from marvin.lib.common import * from marvin.sshClient import SshClient from nose.plugins.attrib import attr -class Services: - """Test Account Services - """ - - 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 - }, - "ostype": 'CentOS 5.3 (64-bit)', - "virtual_machine" : { - "affinity": { - "name": "webvms", - "type": "host anti-affinity", - }, - "hypervisor" : "XenServer", - } - } - - class TestDeployVmWithAffinityGroup(cloudstackTestCase): """ This test deploys a virtual machine into a user account @@ -70,36 +33,40 @@ class TestDeployVmWithAffinityGroup(cloudstackTestCase): @classmethod def setUpClass(cls): - cls.api_client = super(TestDeployVmWithAffinityGroup, cls).getClsTestClient().getApiClient() - cls.services = Services().services + cls.testClient = super(TestDeployVmWithAffinityGroup, cls).getClsTestClient() + zone_name = cls.testClient.getZoneForTests() + cls.apiclient = cls.testClient.getApiClient() + cls.domain = get_domain(cls.apiclient) + cls.services = cls.testClient.getParsedTestDataConfig() # Get Zone, Domain and templates - cls.domain = get_domain(cls.api_client, cls.services) - cls.zone = get_zone(cls.api_client, cls.services) + cls.zone = get_zone(cls.apiclient, cls.testClient.getZoneForTests()) + cls.template = get_template( - cls.api_client, + cls.apiclient, cls.zone.id, cls.services["ostype"] ) + + if cls.template == FAILED: + assert False, "get_template() failed to return template with description %s" % 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.api_client, + cls.apiclient, 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.apiclient, + cls.services["service_offerings"] ) - cls.ag = AffinityGroup.create(cls.api_client, cls.services["virtual_machine"]["affinity"], - account=cls.services["account"], domainid=cls.domain.id) + cls.ag = AffinityGroup.create(cls.apiclient, cls.services["virtual_machine"]["affinity"], + account=cls.account.name, domainid=cls.domain.id) cls._cleanup = [ cls.service_offering, @@ -108,7 +75,7 @@ def setUpClass(cls): ] return - @attr(tags=["simulator", "basic", "advanced", "multihost"]) + @attr(tags=["simulator", "basic", "advanced", "multihost", "selfservice"]) def test_DeployVmAntiAffinityGroup(self): """ test DeployVM in anti-affinity groups @@ -118,7 +85,7 @@ def test_DeployVmAntiAffinityGroup(self): """ #deploy VM1 in affinity group created in setUp vm1 = VirtualMachine.create( - self.api_client, + self.apiclient, self.services["virtual_machine"], templateid=self.template.id, accountid=self.account.name, @@ -128,7 +95,7 @@ def test_DeployVmAntiAffinityGroup(self): ) list_vm1 = list_virtual_machines( - self.api_client, + self.apiclient, id=vm1.id ) self.assertEqual( @@ -151,7 +118,7 @@ def test_DeployVmAntiAffinityGroup(self): #deploy VM2 in affinity group created in setUp vm2 = VirtualMachine.create( - self.api_client, + self.apiclient, self.services["virtual_machine"], templateid=self.template.id, accountid=self.account.name, @@ -160,7 +127,7 @@ def test_DeployVmAntiAffinityGroup(self): affinitygroupnames=[self.ag.name] ) list_vm2 = list_virtual_machines( - self.api_client, + self.apiclient, id=vm2.id ) self.assertEqual( @@ -189,6 +156,6 @@ def test_DeployVmAntiAffinityGroup(self): def tearDownClass(cls): try: #Clean up, terminate the created templates - cleanup_resources(cls.api_client, cls._cleanup) + 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_deploy_vgpu_enabled_vm.py b/test/integration/smoke/test_deploy_vgpu_enabled_vm.py index a09e87e6f2..13fad61d85 100644 --- a/test/integration/smoke/test_deploy_vgpu_enabled_vm.py +++ b/test/integration/smoke/test_deploy_vgpu_enabled_vm.py @@ -23,16 +23,19 @@ #Import Integration Libraries #base - contains all resources as entities and defines create, delete, list operations on them -from marvin.integration.lib.base import Account, VirtualMachine, ServiceOffering +from marvin.lib.base import Account, VirtualMachine, ServiceOffering #utils - utility classes for common cleanup, external library wrappers etc -from marvin.integration.lib.utils import cleanup_resources +from marvin.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 marvin.lib.common import get_zone, get_domain, get_template + +from marvin.codes import FAILED from nose.plugins.attrib import attr + class Services: """Test VM Life Cycle Services """ @@ -116,12 +119,15 @@ def setUp(self): self.apiclient = self.testClient.getApiClient() # Get Zone, Domain and Default Built-in template - self.domain = get_domain(self.apiclient, self.services) - self.zone = get_zone(self.apiclient, self.services) + self.domain = get_domain(self.apiclient) + self.zone = get_zone(self.apiclient, self.testClient.getZoneForTests()) self.services["mode"] = self.zone.networktype # Before running this test, register a windows template with ostype as 'Windows 7 (32-bit)' - self.template = get_template(self.apiclient, self.zone.id, self.services["ostype"], templatetype='USER') + self.services["ostype"] = 'Windows 7 (32-bit)' + self.template = get_template(self.apiclient, self.zone.id, self.services["ostype"]) + if self.template == FAILED: + assert False, "get_template() failed to return template with description %s" % self.services["ostype"] #create a user account self.account = Account.create( self.apiclient, @@ -146,7 +152,7 @@ def setUp(self): self.account ] - @attr(tags = ['advanced', 'simulator', 'basic', 'vgpu']) + @attr(tags = ['advanced', 'simulator', 'basic', 'vgpu', 'provisioning']) def test_deploy_vgpu_enabled_vm(self): """Test Deploy Virtual Machine diff --git a/test/integration/smoke/test_deploy_vm.py b/test/integration/smoke/test_deploy_vm.py index fcde2294df..473b020280 100644 --- a/test/integration/smoke/test_deploy_vm.py +++ b/test/integration/smoke/test_deploy_vm.py @@ -22,68 +22,36 @@ #Import Integration Libraries +from marvin.codes import FAILED #base - contains all resources as entities and defines create, delete, list operations on them -from marvin.integration.lib.base import Account, VirtualMachine, ServiceOffering +from marvin.lib.base import Account, VirtualMachine, ServiceOffering, SimulatorMock #utils - utility classes for common cleanup, external library wrappers etc -from marvin.integration.lib.utils import cleanup_resources +from marvin.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 marvin.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 - """ - def __init__(self): - self.testdata = { - #data to create an account - "account": { - "email": "test@test.com", - "firstname": "Test", - "lastname": "User", - "username": "test", - "password": "password", - }, - #data reqd for virtual machine creation - "virtual_machine" : { - "name" : "testvm", - "displayname" : "Test VM", - }, - #data reqd for virtual machine creation - "virtual_machine2" : { - "name" : "testvm2", - "displayname" : "Test VM2", - }, - #small service offering - "service_offering": { - "small": { - "name": "Small Instance", - "displaytext": "Small Instance", - "cpunumber": 1, - "cpuspeed": 100, - "memory": 256, - }, - }, - "ostype": 'CentOS 5.3 (64-bit)', - } - - class TestDeployVM(cloudstackTestCase): """Test deploy a VM into a user account """ def setUp(self): - self.testdata = TestData().testdata self.apiclient = self.testClient.getApiClient() + self.testdata = self.testClient.getParsedTestDataConfig() + # Get Zone, Domain and Default Built-in template - self.domain = get_domain(self.apiclient, self.testdata) - self.zone = get_zone(self.apiclient, self.testdata) + self.domain = get_domain(self.apiclient) + self.zone = get_zone(self.apiclient, self.testClient.getZoneForTests()) self.testdata["mode"] = self.zone.networktype self.template = get_template(self.apiclient, self.zone.id, self.testdata["ostype"]) + if self.template == FAILED: + self.fail("get_template() failed to return template with description %s" % self.testdata["ostype"]) + #create a user account self.account = Account.create( self.apiclient, @@ -93,7 +61,7 @@ def setUp(self): #create a service offering self.service_offering = ServiceOffering.create( self.apiclient, - self.testdata["service_offering"]["small"] + self.testdata["service_offerings"]["small"] ) #build cleanup list self.cleanup = [ @@ -101,7 +69,7 @@ def setUp(self): self.account ] - @attr(tags = ['advanced', 'simulator', 'basic', 'sg']) + @attr(tags = ['advanced', 'simulator', 'basic', 'sg', 'selfservice']) def test_deploy_vm(self): """Test Deploy Virtual Machine @@ -120,22 +88,11 @@ def test_deploy_vm(self): ) 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" - ) + self.assertTrue(isinstance(list_vms, list) and len(list_vms) > 0, msg="List VM response empty") vm = list_vms[0] self.assertEqual( @@ -154,7 +111,7 @@ def test_deploy_vm(self): msg="VM is not in Running state" ) - @attr(tags = ['advanced', 'simulator', 'basic', 'sg']) + @attr(tags = ['advanced', 'simulator', 'basic', 'sg', 'selfservice']) def test_deploy_vm_multiple(self): """Test Multiple Deploy Virtual Machine @@ -186,7 +143,6 @@ def test_deploy_vm_multiple(self): self.debug( "Verify listVirtualMachines response for virtual machines: %s, %s" % (self.virtual_machine.id, self.virtual_machine2.id) ) - self.assertEqual( isinstance(list_vms, list), True, @@ -204,3 +160,225 @@ def tearDown(self): except Exception as e: self.debug("Warning! Exception in tearDown: %s" % e) +class TestDeployVMVolumeCreationFailure(cloudstackTestCase): + """Test VM deploy into user account with volume creation failure + """ + + def setUp(self): + self.testdata = self.testClient.getParsedTestDataConfig() + self.apiclient = self.testClient.getApiClient() + + # Get Zone, Domain and Default Built-in template + self.domain = get_domain(self.apiclient) + self.zone = get_zone(self.apiclient, self.testClient.getZoneForTests()) + self.testdata["mode"] = self.zone.networktype + self.template = get_template(self.apiclient, self.zone.id, self.testdata["ostype"]) + + #create a user account + self.account = Account.create( + self.apiclient, + self.testdata["account"], + domainid=self.domain.id + ) + #create a service offering + self.service_offering = ServiceOffering.create( + self.apiclient, + self.testdata["service_offerings"]["small"] + ) + #create first VM + self.virtual_machine = VirtualMachine.create( + self.apiclient, + self.testdata["virtual_machine"], + accountid=self.account.name, + zoneid=self.zone.id, + domainid=self.account.domainid, + serviceofferingid=self.service_offering.id, + templateid=self.template.id) + #mock to simulate volume creation failure + self.mock_volume_failure = SimulatorMock.create( + apiclient=self.apiclient, + command="CopyCommand", + count=6) + #build cleanup list + self.cleanup = [ + self.service_offering, + self.account, + self.mock_volume_failure + ] + + @attr(tags = ['selfservice']) + def test_deploy_vm_volume_creation_failure(self): + """Test Deploy Virtual Machine - volume creation failure and retry + + # Validate the following: + # 1. 1st VM creation failed + # 2. Check there were 4 failed volume creation retries (mock count = (6-4) = 2) + # 3. 2nd VM creation succeeded + # 4. Check there were 2 failed volume creation retries (mock count = (2-2) = 0) + # 5. ListVM returns accurate information + """ + self.virtual_machine = None + with self.assertRaises(Exception): + self.virtual_machine = VirtualMachine.create( + self.apiclient, + self.testdata["virtual_machine2"], + accountid=self.account.name, + zoneid=self.zone.id, + domainid=self.account.domainid, + serviceofferingid=self.service_offering.id, + templateid=self.template.id) + + self.mock_volume_failure = self.mock_volume_failure.query(self.apiclient) + self.assertEqual( + self.mock_volume_failure.count, + 2, + msg="Volume failure mock not executed") + + self.virtual_machine = VirtualMachine.create( + self.apiclient, + self.testdata["virtual_machine3"], + accountid=self.account.name, + zoneid=self.zone.id, + domainid=self.account.domainid, + serviceofferingid=self.service_offering.id, + templateid=self.template.id) + list_vms = VirtualMachine.list(self.apiclient, id=self.virtual_machine.id) + self.assertTrue(isinstance(list_vms, list) and len(list_vms) > 0, msg="List VM response empty") + vm = list_vms[0] + self.assertEqual( + vm.id, + self.virtual_machine.id, + "VM ids do not match") + self.assertEqual( + vm.name, + self.virtual_machine.name, + "VM names do not match") + self.assertEqual( + vm.state, + "Running", + msg="VM is not in Running state") + + self.mock_volume_failure = self.mock_volume_failure.query(self.apiclient) + self.assertEqual( + self.mock_volume_failure.count, + 0, + msg="Volume failure mock not executed") + + def tearDown(self): + try: + cleanup_resources(self.apiclient, self.cleanup) + except Exception as e: + self.debug("Warning! Exception in tearDown: %s" % e) + + +class TestDeployVMStartFailure(cloudstackTestCase): + """Test VM deploy into user account with start operation failure + """ + + def setUp(self): + self.testdata = self.testClient.getParsedTestDataConfig() + self.apiclient = self.testClient.getApiClient() + + # Get Zone, Domain and Default Built-in template + self.domain = get_domain(self.apiclient) + self.zone = get_zone(self.apiclient, self.testClient.getZoneForTests()) + self.testdata["mode"] = self.zone.networktype + self.template = get_template(self.apiclient, self.zone.id, self.testdata["ostype"]) + + #create a user account + self.account = Account.create( + self.apiclient, + self.testdata["account"], + domainid=self.domain.id + ) + #create a service offering + self.service_offering = ServiceOffering.create( + self.apiclient, + self.testdata["service_offerings"]["small"] + ) + #create first VM + self.virtual_machine = VirtualMachine.create( + self.apiclient, + self.testdata["virtual_machine"], + accountid=self.account.name, + zoneid=self.zone.id, + domainid=self.account.domainid, + serviceofferingid=self.service_offering.id, + templateid=self.template.id) + #mock to simulate vm start failure + self.mock_start_failure = SimulatorMock.create( + apiclient=self.apiclient, + command="StartCommand", + count=6) + #build cleanup list + self.cleanup = [ + self.service_offering, + self.account, + self.mock_start_failure + ] + + @attr(tags = ['selfservice']) + def test_deploy_vm_start_failure(self): + """Test Deploy Virtual Machine - start operation failure and retry + + # Validate the following: + # 1. 1st VM creation failed + # 2. Check there were 4 failed start operation retries (mock count = (6-4) = 2) + # 3. 2nd VM creation succeeded + # 4. Check there were 2 failed start operation retries (mock count = (2-2) = 0) + # 5. ListVM returns accurate information + """ + self.virtual_machine = None + with self.assertRaises(Exception): + self.virtual_machine = VirtualMachine.create( + self.apiclient, + self.testdata["virtual_machine2"], + accountid=self.account.name, + zoneid=self.zone.id, + domainid=self.account.domainid, + serviceofferingid=self.service_offering.id, + templateid=self.template.id) + + self.mock_start_failure = self.mock_start_failure.query(self.apiclient) + self.assertEqual( + self.mock_start_failure.count, + 2, + msg="Start failure mock not executed") + + self.virtual_machine = VirtualMachine.create( + self.apiclient, + self.testdata["virtual_machine3"], + accountid=self.account.name, + zoneid=self.zone.id, + domainid=self.account.domainid, + serviceofferingid=self.service_offering.id, + templateid=self.template.id) + list_vms = VirtualMachine.list(self.apiclient, id=self.virtual_machine.id) + self.assertTrue(isinstance(list_vms, list) and len(list_vms) > 0, msg="List VM response empty") + vm = list_vms[0] + self.assertEqual( + vm.id, + self.virtual_machine.id, + "VM ids do not match") + self.assertEqual( + vm.name, + self.virtual_machine.name, + "VM names do not match") + self.assertEqual( + vm.state, + "Running", + msg="VM is not in Running state") + + self.mock_start_failure = self.mock_start_failure.query(self.apiclient) + self.assertEqual( + self.mock_start_failure.count, + 0, + msg="Start failure mock not executed") + + def tearDown(self): + try: + cleanup_resources(self.apiclient, self.cleanup) + except Exception as e: + self.debug("Warning! Exception in tearDown: %s" % e) + + diff --git a/test/integration/smoke/test_deploy_vm_root_resize.py b/test/integration/smoke/test_deploy_vm_root_resize.py new file mode 100644 index 0000000000..5d73876db6 --- /dev/null +++ b/test/integration/smoke/test_deploy_vm_root_resize.py @@ -0,0 +1,272 @@ +# 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. + +#Test from the Marvin - Testing in Python wiki + +#All tests inherit from cloudstackTestCase +from marvin.cloudstackTestCase import cloudstackTestCase + +#Import Integration Libraries + +#base - contains all resources as entities and defines create, delete, list operations on them +from marvin.lib.base import Account, VirtualMachine, ServiceOffering + +#utils - utility classes for common cleanup, external library wrappers etc +from marvin.lib.utils import cleanup_resources + +#common - commonly used methods for all tests are listed here +from marvin.lib.common import get_zone, get_domain, get_template, list_volumes + +from marvin.codes import FAILED + +from nose.plugins.attrib import attr + +class TestData(object): + """Test data object that is required to create resources + """ + def __init__(self): + self.testdata = { + #data to create an account + "account": { + "email": "test@test.com", + "firstname": "Test", + "lastname": "User", + "username": "test", + "password": "password", + }, + #data reqd for virtual machine creation + "virtual_machine" : { + "name" : "testvm", + "displayname" : "Test VM", + }, + #small service offering + "service_offering": { + "small": { + "name": "Small Instance", + "displaytext": "Small Instance", + "cpunumber": 1, + "cpuspeed": 100, + "memory": 256, + }, + }, + "ostype": 'CentOS 5.3 (64-bit)', + } + +class TestDeployVM(cloudstackTestCase): + """Test deploy a VM into a user account + """ + + def setUp(self): + self.testdata = TestData().testdata + self.apiclient = self.testClient.getApiClient() + self.hypervisor = self.testClient.getHypervisorInfo() + + # Get Zone, Domain and Default Built-in template + self.domain = get_domain(self.apiclient) + self.zone = get_zone(self.apiclient, self.testClient.getZoneForTests()) + self.testdata["mode"] = self.zone.networktype + self.template = get_template(self.apiclient, self.zone.id, self.testdata["ostype"]) + if self.template == FAILED: + assert False, "get_template() failed to return template " +# for testing with specific template +# self.template = get_template(self.apiclient, self.zone.id, self.testdata["ostype"], templatetype='USER', services = {"template":'31f52a4d-5681-43f7-8651-ad4aaf823618'}) + + + #create a user account + self.account = Account.create( + self.apiclient, + self.testdata["account"], + domainid=self.domain.id + ) + #create a service offering + self.service_offering = ServiceOffering.create( + self.apiclient, + self.testdata["service_offering"]["small"] + ) + #build cleanup list + self.cleanup = [ + self.service_offering, + self.account + ] + + @attr(tags = ['advanced', 'simulator', 'basic', 'sg', 'provisioning']) + def test_00_deploy_vm_root_resize(self): + """Test deploy virtual machine with root resize + + # Validate the following: + # 1. listVirtualMachines returns accurate information + # 2. root disk has new size per listVolumes + # 3. Rejects non-supported hypervisor types + """ + if(self.hypervisor == 'kvm'): + newrootsize = (self.template.size >> 30) + 2 + self.virtual_machine = VirtualMachine.create( + self.apiclient, + self.testdata["virtual_machine"], + accountid=self.account.name, + zoneid=self.zone.id, + domainid=self.account.domainid, + serviceofferingid=self.service_offering.id, + templateid=self.template.id, + rootdisksize=newrootsize, + hypervisor=self.hypervisor + ) + + 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.id, + self.virtual_machine.id, + "Virtual Machine ids do not match" + ) + self.assertEqual( + vm.name, + self.virtual_machine.name, + "Virtual Machine names do not match" + ) + self.assertEqual( + vm.state, + "Running", + msg="VM is not in Running state" + ) + + # get root vol from created vm, verify it is correct size + list_volume_response = list_volumes( + self.apiclient, + virtualmachineid=self.virtual_machine.id, + type='ROOT', + listall=True + ) + + rootvolume = list_volume_response[0] + success = False + if rootvolume is not None and rootvolume.size == (newrootsize << 30): + success = True + + self.assertEqual( + success, + True, + "Check if the root volume resized appropriately" + ) + else: + self.debug("hypervisor %s unsupported for test 00, verifying it errors properly" % self.hypervisor) + + newrootsize = (self.template.size >> 30) + 2 + success = False + try: + self.virtual_machine = VirtualMachine.create( + self.apiclient, + self.testdata["virtual_machine"], + accountid=self.account.name, + zoneid=self.zone.id, + domainid=self.account.domainid, + serviceofferingid=self.service_offering.id, + templateid=self.template.id, + rootdisksize=newrootsize, + hypervisor=self.hypervisor + ) + except Exception as ex: + if "Hypervisor XenServer does not support rootdisksize override" in str(ex): + success = True + else: + self.debug("virtual machine create did not fail appropriately. Error was actually : " + str(ex)); + + self.assertEqual(success, True, "Check if unsupported hypervisor %s fails appropriately" % self.hypervisor) + + @attr(tags = ['advanced', 'simulator', 'basic', 'sg', 'provisioning']) + def test_01_deploy_vm_root_resize(self): + """Test proper failure to deploy virtual machine with rootdisksize of 0 + """ + if (self.hypervisor == 'kvm'): + newrootsize = 0 + success = False + try: + self.virtual_machine = VirtualMachine.create( + self.apiclient, + self.testdata["virtual_machine"], + accountid=self.account.name, + zoneid=self.zone.id, + domainid=self.account.domainid, + serviceofferingid=self.service_offering.id, + templateid=self.template.id, + rootdisksize=newrootsize, + hypervisor=self.hypervisor + ) + except Exception as ex: + if "rootdisk size should be a non zero number" in str(ex): + success = True + else: + self.debug("virtual machine create did not fail appropriately. Error was actually : " + str(ex)); + + self.assertEqual(success, True, "Check if passing 0 as rootdisksize fails appropriately") + else: + self.debug("test 01 does not support hypervisor type " + self.hypervisor); + + @attr(tags = ['advanced', 'simulator', 'basic', 'sg', 'provisioning']) + def test_02_deploy_vm_root_resize(self): + """Test proper failure to deploy virtual machine with rootdisksize less than template size + """ + if (self.hypervisor == 'kvm'): + newrootsize = (self.template.size >> 30) - 1 + + self.assertEqual(newrootsize > 0, True, "Provided template is less than 1G in size, cannot run test") + + success = False + try: + self.virtual_machine = VirtualMachine.create( + self.apiclient, + self.testdata["virtual_machine"], + accountid=self.account.name, + zoneid=self.zone.id, + domainid=self.account.domainid, + serviceofferingid=self.service_offering.id, + templateid=self.template.id, + rootdisksize=newrootsize, + hypervisor=self.hypervisor + ) + except Exception as ex: + if "rootdisksize override is smaller than template size" in str(ex): + success = True + else: + self.debug("virtual machine create did not fail appropriately. Error was actually : " + str(ex)); + + self.assertEqual(success, True, "Check if passing rootdisksize < templatesize fails appropriately") + else: + self.debug("test 01 does not support hypervisor type " + self.hypervisor); + + def tearDown(self): + try: + cleanup_resources(self.apiclient, self.cleanup) + except Exception as e: + self.debug("Warning! Exception in tearDown: %s" % e) diff --git a/test/integration/smoke/test_deploy_vm_with_userdata.py b/test/integration/smoke/test_deploy_vm_with_userdata.py index e3788cfbc2..7616b82d4b 100644 --- a/test/integration/smoke/test_deploy_vm_with_userdata.py +++ b/test/integration/smoke/test_deploy_vm_with_userdata.py @@ -16,62 +16,33 @@ # under the License. from marvin.cloudstackTestCase import cloudstackTestCase -from marvin.integration.lib.base import (ServiceOffering, +from marvin.lib.base import (ServiceOffering, VirtualMachine, Account) -from marvin.integration.lib.common import get_template, get_zone, list_virtual_machines -from marvin.integration.lib.utils import cleanup_resources +from marvin.lib.common import get_template, get_zone, list_virtual_machines +from marvin.lib.utils import cleanup_resources from nose.plugins.attrib import attr - +from marvin.codes import FAILED import random import string -class Services: - def __init__(self): - self.services = { - "account": { - "email": "test@test.com", - "firstname": "Test", - "lastname": "User", - "username": "test", - "password": "password", - }, - "virtual_machine": { - "displayname": "Test VM", - "username": "root", - "password": "password", - "ssh_port": 22, - "hypervisor": 'XenServer', - "privateport": 22, - "publicport": 22, - "protocol": 'TCP', - }, - "ostype": 'CentOS 5.3 (64-bit)', - "service_offering": { - "name": "Tiny Instance", - "displaytext": "Tiny Instance", - "cpunumber": 1, - "cpuspeed": 100, - "memory": 256, - }, - } - - class TestDeployVmWithUserData(cloudstackTestCase): """Tests for UserData """ @classmethod def setUpClass(cls): - cls.apiClient = super(TestDeployVmWithUserData, cls).getClsTestClient().getApiClient() - cls.services = Services().services - cls.zone = get_zone(cls.apiClient, cls.services) + testClient = super(TestDeployVmWithUserData, cls).getClsTestClient() + cls.apiClient = testClient.getApiClient() + cls.services = testClient.getParsedTestDataConfig() + + cls.zone = get_zone(cls.apiClient, testClient.getZoneForTests()) if cls.zone.localstorageenabled: #For devcloud since localstroage is enabled - cls.services["service_offering"]["storagetype"] = "local" + cls.services["service_offerings"]["storagetype"] = "local" cls.service_offering = ServiceOffering.create( cls.apiClient, - cls.services["service_offering"] + cls.services["service_offerings"] ) cls.account = Account.create(cls.apiClient, services=cls.services["account"]) cls.cleanup = [cls.account] @@ -80,6 +51,10 @@ def setUpClass(cls): cls.zone.id, cls.services["ostype"] ) + + if cls.template == FAILED: + assert False, "get_template() failed to return template with description %s" % cls.services["ostype"] + cls.debug("Successfully created account: %s, id: \ %s" % (cls.account.name,\ cls.account.id)) @@ -92,7 +67,10 @@ def setUpClass(cls): user_data = ''.join(random.choice(string.ascii_uppercase + string.digits) for x in range(2500)) cls.services["virtual_machine"]["userdata"] = user_data - @attr(tags=["simulator", "devcloud", "basic", "advanced"]) + def setup(self): + self.hypervisor = self.testClient.getHypervisorInfo() + + @attr(tags=["simulator", "devcloud", "basic", "advanced", "post", "provisioning"]) def test_deployvm_userdata_post(self): """Test userdata as POST, size > 2k """ @@ -117,7 +95,7 @@ def test_deployvm_userdata_post(self): 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") - @attr(tags=["simulator", "devcloud", "basic", "advanced"]) + @attr(tags=["simulator", "devcloud", "basic", "advanced", "provisioning"]) def test_deployvm_userdata(self): """Test userdata as GET, size > 2k """ 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 b4d35e0305..420925e378 100644 --- a/test/integration/smoke/test_deploy_vms_with_varied_deploymentplanners.py +++ b/test/integration/smoke/test_deploy_vms_with_varied_deploymentplanners.py @@ -15,40 +15,13 @@ # specific language governing permissions and limitations # under the License. +from marvin.codes import FAILED from marvin.cloudstackTestCase import cloudstackTestCase -from marvin.integration.lib.base import Account, VirtualMachine, ServiceOffering, Host, Cluster -from marvin.integration.lib.common import get_zone, get_domain, get_template -from marvin.integration.lib.utils import cleanup_resources +from marvin.lib.base import Account, VirtualMachine, ServiceOffering, Host, Cluster +from marvin.lib.common import get_zone, get_domain, get_template +from marvin.lib.utils import 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 @@ -56,16 +29,22 @@ class TestDeployVmWithVariedPlanners(cloudstackTestCase): @classmethod def setUpClass(cls): - cls.apiclient = super(TestDeployVmWithVariedPlanners, cls).getClsTestClient().getApiClient() - cls.services = Services().services + testClient = super(TestDeployVmWithVariedPlanners, cls).getClsTestClient() + cls.apiclient = testClient.getApiClient() + cls.services = testClient.getParsedTestDataConfig() + # Get Zone, Domain and templates - cls.domain = get_domain(cls.apiclient, cls.services) - cls.zone = get_zone(cls.apiclient, cls.services) + cls.domain = get_domain(cls.apiclient) + cls.zone = get_zone(cls.apiclient, testClient.getZoneForTests()) cls.template = get_template( cls.apiclient, cls.zone.id, cls.services["ostype"] ) + + if cls.template == FAILED: + assert false, "get_template() failed to return template with description %s" % cls.services["ostype"] + cls.services["virtual_machine"]["zoneid"] = cls.zone.id cls.services["template"] = cls.template.id cls.services["zoneid"] = cls.zone.id @@ -75,21 +54,20 @@ def setUpClass(cls): cls.services["account"], domainid=cls.domain.id ) - cls.services["account"] = cls.account.name cls.hosts = Host.list(cls.apiclient, type='Routing') cls.clusters = Cluster.list(cls.apiclient) cls.cleanup = [ cls.account ] - @attr(tags=["simulator", "advanced", "basic", "sg"]) + @attr(tags=["simulator", "advanced", "basic", "sg", "selfservice"]) 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"], + self.services["service_offerings"], deploymentplanner='FirstFitPlanner' ) @@ -126,13 +104,13 @@ def test_deployvm_firstfit(self): msg="VM is not in Running state" ) - @attr(tags=["simulator", "advanced", "basic", "sg"]) + @attr(tags=["simulator", "advanced", "basic", "sg", "selfservice"]) def test_deployvm_userdispersing(self): """Test deploy VMs using user dispersion planner """ self.service_offering_userdispersing = ServiceOffering.create( self.apiclient, - self.services["service_offering"], + self.services["service_offerings"], deploymentplanner='UserDispersingPlanner' ) @@ -185,13 +163,13 @@ def test_deployvm_userdispersing(self): self.debug("VMs (%s, %s) meant to be dispersed are deployed in the same cluster %s" % ( vm1.id, vm2.id, vm1clusterid)) - @attr(tags=["simulator", "advanced", "basic", "sg"]) + @attr(tags=["simulator", "advanced", "basic", "sg", "selfservice"]) def test_deployvm_userconcentrated(self): """Test deploy VMs using user concentrated planner """ self.service_offering_userconcentrated = ServiceOffering.create( self.apiclient, - self.services["service_offering"], + self.services["service_offerings"], deploymentplanner='UserConcentratedPodPlanner' ) diff --git a/test/integration/smoke/test_disk_offerings.py b/test/integration/smoke/test_disk_offerings.py index 4588a26c8b..780c154270 100644 --- a/test/integration/smoke/test_disk_offerings.py +++ b/test/integration/smoke/test_disk_offerings.py @@ -20,30 +20,17 @@ import marvin 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.lib.utils import * +from marvin.lib.base import * +from marvin.lib.common import * from nose.plugins.attrib import attr _multiprocess_shared_ = True -class Services: - """Test Disk offerings Services - """ - - def __init__(self): - self.services = { - "off": { - "name": "Disk offering", - "displaytext": "Disk offering", - "disksize": 1 # in GB - }, - } - class TestCreateDiskOffering(cloudstackTestCase): def setUp(self): - self.services = Services().services + self.services = self.testClient.getParsedTestDataConfig() self.apiclient = self.testClient.getApiClient() self.dbclient = self.testClient.getDbConnection() self.cleanup = [] @@ -58,17 +45,17 @@ def tearDown(self): raise Exception("Warning: Exception during cleanup : %s" % e) return - @attr(tags = ["advanced", "basic", "eip", "sg", "advancedns", "simulator", "smoke"]) + @attr(tags = ["advanced", "basic", "eip", "sg", "advancedns", "simulator", "smoke", "selfservice"]) def test_01_create_disk_offering(self): - """Test to create disk offering""" + """Test to create disk offering # Validate the following: # 1. createDiskOfferings should return valid info for new offering # 2. The Cloud Database contains the valid information - + """ disk_offering = DiskOffering.create( self.apiclient, - self.services["off"] + self.services["disk_offering"] ) self.cleanup.append(disk_offering) @@ -92,16 +79,96 @@ def test_01_create_disk_offering(self): self.assertEqual( disk_response.displaytext, - self.services["off"]["displaytext"], + self.services["disk_offering"]["displaytext"], "Check server id in createServiceOffering" ) self.assertEqual( disk_response.name, - self.services["off"]["name"], + self.services["disk_offering"]["name"], "Check name in createServiceOffering" ) return + @attr(hypervisor="kvm") + @attr(tags = ["advanced", "basic", "eip", "sg", "advancedns", "simulator", "smoke"]) + def test_02_create_sparse_type_disk_offering(self): + """Test to create a sparse type disk offering""" + + # Validate the following: + # 1. createDiskOfferings should return valid info for new offering + # 2. The Cloud Database contains the valid information + + disk_offering = DiskOffering.create( + self.apiclient, + self.services["sparse"] + ) + self.cleanup.append(disk_offering) + + self.debug("Created Disk offering with ID: %s" % disk_offering.id) + + list_disk_response = list_disk_offering( + self.apiclient, + id=disk_offering.id + ) + self.assertEqual( + isinstance(list_disk_response, list), + True, + "Check list response returns a valid list" + ) + self.assertNotEqual( + len(list_disk_response), + 0, + "Check Disk offering is created" + ) + disk_response = list_disk_response[0] + + self.assertEqual( + disk_response.provisioningtype, + self.services["sparse"]["provisioningtype"], + "Check provisionig type in createServiceOffering" + ) + return + + + @attr(hypervisor="kvm") + @attr(tags = ["advanced", "basic", "eip", "sg", "advancedns", "simulator", "smoke"]) + def test_04_create_fat_type_disk_offering(self): + """Test to create a sparse type disk offering""" + + # Validate the following: + # 1. createDiskOfferings should return valid info for new offering + # 2. The Cloud Database contains the valid information + + disk_offering = DiskOffering.create( + self.apiclient, + self.services["fat"] + ) + self.cleanup.append(disk_offering) + + self.debug("Created Disk offering with ID: %s" % disk_offering.id) + + list_disk_response = list_disk_offering( + self.apiclient, + id=disk_offering.id + ) + self.assertEqual( + isinstance(list_disk_response, list), + True, + "Check list response returns a valid list" + ) + self.assertNotEqual( + len(list_disk_response), + 0, + "Check Disk offering is created" + ) + disk_response = list_disk_response[0] + + self.assertEqual( + disk_response.provisioningtype, + self.services["fat"]["provisioningtype"], + "Check provisionig type in createServiceOffering" + ) + return class TestDiskOfferings(cloudstackTestCase): @@ -122,15 +189,17 @@ def tearDown(self): @classmethod def setUpClass(cls): - cls.services = Services().services - cls.api_client = super(TestDiskOfferings, cls).getClsTestClient().getApiClient() + testClient = super(TestDiskOfferings, cls).getClsTestClient() + cls.apiclient = cls.testClient.getApiClient() + cls.services = cls.testClient.getParsedTestDataConfig() + cls.disk_offering_1 = DiskOffering.create( - cls.api_client, - cls.services["off"] + cls.apiclient, + cls.services["disk_offering"] ) cls.disk_offering_2 = DiskOffering.create( - cls.api_client, - cls.services["off"] + cls.apiclient, + cls.services["disk_offering"] ) cls._cleanup = [cls.disk_offering_1] return @@ -138,21 +207,22 @@ def setUpClass(cls): @classmethod def tearDownClass(cls): try: - cls.api_client = super(TestDiskOfferings, cls).getClsTestClient().getApiClient() - cleanup_resources(cls.api_client, cls._cleanup) + cls.apiclient = super(TestDiskOfferings, cls).getClsTestClient().getApiClient() + cleanup_resources(cls.apiclient, cls._cleanup) except Exception as e: raise Exception("Warning: Exception during cleanup : %s" % e) return - @attr(tags = ["advanced", "basic", "eip", "sg", "advancedns", "simulator", "smoke"]) + @attr(tags = ["advanced", "basic", "eip", "sg", "advancedns", "simulator", "smoke", "selfservice"]) def test_02_edit_disk_offering(self): - """Test to update existing disk offering""" + """Test to update existing disk offering # Validate the following: # 1. updateDiskOffering should return # a valid information for newly created offering #Generate new name & displaytext from random data + """ random_displaytext = random_gen() random_name = random_gen() @@ -195,14 +265,14 @@ def test_02_edit_disk_offering(self): ) return - @attr(tags = ["advanced", "basic", "eip", "sg", "advancedns", "simulator", "smoke"]) + @attr(tags = ["advanced", "basic", "eip", "sg", "advancedns", "simulator", "smoke", "selfservice"]) def test_03_delete_disk_offering(self): - """Test to delete disk offering""" + """Test to delete disk offering # Validate the following: # 1. deleteDiskOffering should return # a valid information for newly created offering - + """ self.disk_offering_2.delete(self.apiclient) self.debug("Deleted Disk offering with ID: %s" % diff --git a/test/integration/smoke/test_global_settings.py b/test/integration/smoke/test_global_settings.py index 5cd3654b22..ace2db3191 100644 --- a/test/integration/smoke/test_global_settings.py +++ b/test/integration/smoke/test_global_settings.py @@ -19,9 +19,9 @@ #Import Local Modules 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.lib.utils import * +from marvin.lib.base import * +from marvin.lib.common import * from nose.plugins.attrib import attr #Import System modules @@ -32,7 +32,7 @@ class TestUpdateConfigWithScope(cloudstackTestCase): def setUp(self): self.apiClient = self.testClient.getApiClient() - @attr(tags=["simulator", "devcloud", "basic", "advanced"]) + @attr(tags=["simulator", "devcloud", "basic", "advanced", "selfservice"]) def test_UpdateConfigParamWithScope(self): """ test update configuration setting at zone level scope diff --git a/test/integration/smoke/test_guest_vlan_range.py b/test/integration/smoke/test_guest_vlan_range.py index 07e141d0fe..bfef4a8e65 100644 --- a/test/integration/smoke/test_guest_vlan_range.py +++ b/test/integration/smoke/test_guest_vlan_range.py @@ -21,43 +21,22 @@ 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.lib.utils import * +from marvin.lib.base import * +from marvin.lib.common import * import datetime - -class Services: - """Test Dedicating Guest Vlan Ranges - """ - - def __init__(self): - self.services = { - "domain": { - "name": "Domain", - }, - "account": { - "email": "test@test.com", - "firstname": "Test", - "lastname": "User", - "username": "test", - "password": "password", - }, - "name": "testphysicalnetwork", - - "vlan": "2118-2120", - } - - class TestDedicateGuestVlanRange(cloudstackTestCase): @classmethod def setUpClass(cls): - cls.apiclient = super(TestDedicateGuestVlanRange, cls).getClsTestClient().getApiClient() - cls.services = Services().services + testClient = super(TestDedicateGuestVlanRange, cls).getClsTestClient() + cls.apiclient = testClient.getApiClient() + cls.services = testClient.getParsedTestDataConfig() + # Get Zone, Domain - cls.domain = get_domain(cls.apiclient, cls.services) - cls.zone = get_zone(cls.apiclient, cls.services) + cls.domain = get_domain(cls.apiclient) + cls.zone = get_zone(cls.apiclient, testClient.getZoneForTests()) # Create Account cls.account = Account.create( @@ -99,13 +78,14 @@ def tearDown(self): raise Exception("Warning: Exception during cleanup : %s" % e) return - @attr(tags=["simulator", "advanced", "guestvlanrange", "dedicate", "release"]) + @attr(tags=["simulator", "advanced", "guestvlanrange", "dedicate", "release", "selfservice"]) def test_dedicateGuestVlanRange(self): """Test guest vlan range dedication """ """Assume a physical network is available """ + """ # Validate the following: # 1. List the available physical network using ListPhysicalNetwork # 2. Add a Guest Vlan range to the available physical network using UpdatePhysicalNetwork @@ -114,7 +94,7 @@ def test_dedicateGuestVlanRange(self): # 5. Release the dedicated guest vlan range back to the system # 6. Verify guest vlan range has been released, verify with listDedicatedGuestVlanRanges # 7. Remove the added guest vlan range using UpdatePhysicalNetwork - + """ self.debug("Adding guest vlan range") diff --git a/test/integration/smoke/test_hosts.py b/test/integration/smoke/test_hosts.py index 6f7d400eda..52827aa7fe 100644 --- a/test/integration/smoke/test_hosts.py +++ b/test/integration/smoke/test_hosts.py @@ -20,9 +20,9 @@ import marvin 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.lib.utils import * +from marvin.lib.base import * +from marvin.lib.common import * from nose.plugins.attrib import attr #Import System modules @@ -30,81 +30,15 @@ _multiprocess_shared_ = True -class Services: - """Test Hosts & Clusters Services - """ - - def __init__(self): - self.services = { - "clusters": { - 0: { - "clustername": "Xen Cluster", - "clustertype": "CloudManaged", - # CloudManaged or ExternalManaged" - "hypervisor": "XenServer", - # Hypervisor type - }, - 1: { - "clustername": "KVM Cluster", - "clustertype": "CloudManaged", - # CloudManaged or ExternalManaged" - "hypervisor": "KVM", - # Hypervisor type - }, - 2: { - "hypervisor": 'VMware', - # Hypervisor type - "clustertype": 'ExternalManaged', - # CloudManaged or ExternalManaged" - "username": 'administrator', - "password": 'fr3sca', - "url": 'http://192.168.100.17/CloudStack-Clogeny-Pune/Pune-1', - # Format:http://vCenter Host/Datacenter/Cluster - "clustername": 'VMWare Cluster', - }, - }, - "hosts": { - "xenserver": { - # Must be name of corresponding Hypervisor type - # in cluster in small letters - "hypervisor": 'XenServer', - # Hypervisor type - "clustertype": 'CloudManaged', - # CloudManaged or ExternalManaged" - "url": 'http://192.168.100.211', - "username": "root", - "password": "fr3sca", - }, - "kvm": { - "hypervisor": 'KVM', - # Hypervisor type - "clustertype": 'CloudManaged', - # CloudManaged or ExternalManaged" - "url": 'http://192.168.100.212', - "username": "root", - "password": "fr3sca", - }, - "vmware": { - "hypervisor": 'VMware', - # Hypervisor type - "clustertype": 'ExternalManaged', - # CloudManaged or ExternalManaged" - "url": 'http://192.168.100.203', - "username": "administrator", - "password": "fr3sca", - }, - }, - } - class TestHosts(cloudstackTestCase): def setUp(self): - self.apiclient = self.testClient.getApiClient() + self.hypervisor = self.testClient.getHypervisorInfo() self.dbclient = self.testClient.getDbConnection() - self.services = Services().services - self.zone = get_zone(self.apiclient, self.services) - self.pod = get_pod(self.apiclient, self.zone.id, self.services) + self.services = self.testClient.getParsedTestDataConfig() + self.zone = get_zone(self.apiclient, self.testClient.getZoneForTests()) + self.pod = get_pod(self.apiclient, self.zone.id) self.cleanup = [] return @@ -118,24 +52,26 @@ def tearDown(self): raise Exception("Warning: Exception during cleanup : %s" % e) return - @unittest.skip("skipped - our environments will not add hosts") + @attr(tags=["selfservice"]) def test_01_clusters(self): - """Test Add clusters & hosts - XEN, KVM, VWARE - """ + """Test Add clusters & hosts - simulator + # Validate the following: - # 1. Verify hypervisortype returned by API is Xen/KVM/VWare + # 1. Verify hypervisortype returned by API is Simulator/Xen/KVM/VWare # 2. Verify that the cluster is in 'Enabled' allocation state # 3. Verify that the host is added successfully and in Up state # with listHosts API response - #Create clusters with Hypervisor type XEN/KVM/VWare + #Create clusters with Hypervisor type Simulator/XEN/KVM/VWare + """ for k, v in self.services["clusters"].items(): cluster = Cluster.create( self.apiclient, v, zoneid=self.zone.id, - podid=self.pod.id + podid=self.pod.id, + hypervisor=self.hypervisor ) self.debug( "Created Cluster for hypervisor type %s & ID: %s" %( @@ -166,8 +102,11 @@ def test_01_clusters(self): cluster, self.services["hosts"][hypervisor_type], zoneid=self.zone.id, - podid=self.pod.id + podid=self.pod.id, + hypervisor=self.hypervisor ) + if host == FAILED: + self.fail("Host Creation Failed") self.debug( "Created host (ID: %s) in cluster ID %s" %( host.id, diff --git a/test/integration/smoke/test_internal_lb.py b/test/integration/smoke/test_internal_lb.py index 7510169921..d6f3477595 100644 --- a/test/integration/smoke/test_internal_lb.py +++ b/test/integration/smoke/test_internal_lb.py @@ -17,80 +17,29 @@ """ Tests for configuring Internal Load Balancing Rules. """ #Import Local Modules +from marvin.codes import FAILED 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.lib.utils import * +from marvin.lib.base import * +from marvin.lib.common import * from nose.plugins.attrib import attr - -class Services: - def __init__(self): - self.services = { - "account": { - "email": "test@test.com", - "firstname": "Test", - "lastname": "User", - "username": "test", - "password": "password", - }, - "virtual_machine": { - "displayname": "Test VM", - "username": "root", - "password": "password", - "ssh_port": 22, - "hypervisor": 'XenServer', - "privateport": 22, - "publicport": 22, - "protocol": 'TCP', - }, - "ostype": 'CentOS 5.3 (64-bit)', - "service_offering": { - "name": "Tiny Instance", - "displaytext": "Tiny Instance", - "cpunumber": 1, - "cpuspeed": 100, - "memory": 256, - }, - "network_offering": { - "name": "Network offering for internal lb service", - "displaytext": "Network offering for internal lb service", - "guestiptype": "Isolated", - "traffictype": "Guest", - "supportedservices": "Vpn,Dhcp,Dns,Lb,UserData,SourceNat,StaticNat,PortForwarding,NetworkACL", - "serviceProviderList": { - "Dhcp": "VpcVirtualRouter", - "Dns": "VpcVirtualRouter", - "Vpn": "VpcVirtualRouter", - "UserData": "VpcVirtualRouter", - "Lb": "InternalLbVM", - "SourceNat": "VpcVirtualRouter", - "StaticNat": "VpcVirtualRouter", - "PortForwarding": "VpcVirtualRouter", - "NetworkACL": "VpcVirtualRouter", - }, - "serviceCapabilityList": { - "SourceNat": {"SupportedSourceNatTypes": "peraccount"}, - "Lb": {"lbSchemes": "internal", "SupportedLbIsolation": "dedicated"} - } - } - } - - class TestInternalLb(cloudstackTestCase): """Test Internal LB """ @classmethod def setUpClass(cls): - cls.apiclient = super(TestInternalLb, cls).getClsTestClient().getApiClient() - cls.services = Services().services - cls.zone = get_zone(cls.apiclient, cls.services) + testClient = super(TestInternalLb, cls).getClsTestClient() + cls.apiclient = testClient.getApiClient() + cls.services = testClient.getParsedTestDataConfig() + + cls.zone = get_zone(cls.apiclient, testClient.getZoneForTests()) cls.domain = get_domain(cls.apiclient) cls.service_offering = ServiceOffering.create( cls.apiclient, - cls.services["service_offering"] + cls.services["service_offerings"] ) cls.account = Account.create(cls.apiclient, services=cls.services["account"]) cls.template = get_template( @@ -98,18 +47,22 @@ def setUpClass(cls): cls.zone.id, cls.services["ostype"] ) + + if cls.template == FAILED: + assert False, "get_template() failed to return template with description %s" % cls.services["ostype"] + cls.debug("Successfully created account: %s, id: \ %s" % (cls.account.name,\ cls.account.id)) cls.cleanup = [cls.account] - @attr(tags=["smoke", "advanced"]) + @attr(tags=["smoke", "advanced", "provisioning"]) def test_internallb(self): """Test create, delete, assign, remove of internal loadbalancer - """ - - #1) Create and enable network offering with Internal Lb vm service - self.networkOffering = NetworkOffering.create(self.apiclient, self.services["network_offering"], conservemode=False) + """ + #1) Create and enable network offering with Internal Lb vm service + self.networkOffering = NetworkOffering.create(self.apiclient, self.services["network_offering_internal_lb"], conservemode=False) + #TODO: SIMENH:modify this test to verify lb rules by sending request from another tier self.networkOffering.update(self.apiclient, state="Enabled") #2) Create VPC and network in it diff --git a/test/integration/smoke/test_iso.py b/test/integration/smoke/test_iso.py index 75289b8fbe..5821ec7d14 100644 --- a/test/integration/smoke/test_iso.py +++ b/test/integration/smoke/test_iso.py @@ -20,9 +20,9 @@ import marvin 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.lib.utils import * +from marvin.lib.base import * +from marvin.lib.common import * from nose.plugins.attrib import attr import urllib from random import random @@ -31,69 +31,19 @@ _multiprocess_shared_ = True -class Services: - """Test ISO Services - """ - - def __init__(self): - self.services = { - "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", - }, - "iso_1": - { - "displaytext": "Test ISO 1", - "name": "ISO 1", - "url": "http://people.apache.org/~tsp/dummy.iso", - # Source URL where ISO is located - "isextractable": True, - "isfeatured": True, - "ispublic": True, - "ostype": "CentOS 5.3 (64-bit)", - }, - "iso_2": - { - "displaytext": "Test ISO 2", - "name": "ISO 2", - "url": "http://people.apache.org/~tsp/dummy.iso", - # Source URL where ISO is located - "isextractable": True, - "isfeatured": True, - "ispublic": True, - "ostype": "CentOS 5.3 (64-bit)", - "mode": 'HTTP_DOWNLOAD', - # Used in Extract template, value must be HTTP_DOWNLOAD - }, - "isfeatured": True, - "ispublic": True, - "isextractable": True, - "bootable": True, # For edit template - "passwordenabled": True, - "sleep": 60, - "timeout": 10, - "ostype": "CentOS 5.3 (64-bit)", - # CentOS 5.3 (64 bit) - } - - class TestCreateIso(cloudstackTestCase): - +#TODO: SIMENH: check the existence of registered of ISO in secondary deploy a VM with registered ISO. can be added \ +# as another test def setUp(self): - self.services = Services().services + self.services = self.testClient.getParsedTestDataConfig() self.apiclient = self.testClient.getApiClient() self.dbclient = self.testClient.getDbConnection() # Get Zone, Domain and templates - self.domain = get_domain(self.apiclient, self.services) - self.zone = get_zone(self.apiclient, self.services) + self.domain = get_domain(self.apiclient) + self.zone = get_zone(self.apiclient, self.testClient.getZoneForTests()) self.services['mode'] = self.zone.networktype self.services["domainid"] = self.domain.id - self.services["iso_2"]["zoneid"] = self.zone.id + self.services["iso2"]["zoneid"] = self.zone.id self.account = Account.create( self.apiclient, @@ -108,8 +58,8 @@ def setUp(self): if not isinstance(ostypes, list): raise unittest.SkipTest("OSTypeId for given description not found") - self.services["iso_1"]["ostypeid"] = ostypes[0].id - self.services["iso_2"]["ostypeid"] = ostypes[0].id + self.services["iso1"]["ostypeid"] = ostypes[0].id + self.services["iso2"]["ostypeid"] = ostypes[0].id self.services["ostypeid"] = ostypes[0].id self.cleanup = [self.account] @@ -125,7 +75,7 @@ def tearDown(self): return - @attr(tags = ["advanced", "basic", "eip", "sg", "advancedns", "smoke"]) + @attr(tags = ["advanced", "basic", "eip", "sg", "advancedns", "smoke", "selfservice"]) def test_01_create_iso(self): """Test create public & private ISO """ @@ -138,7 +88,7 @@ def test_01_create_iso(self): iso = Iso.create( self.apiclient, - self.services["iso_2"], + self.services["iso2"], account=self.account.name, domainid=self.account.domainid ) @@ -169,17 +119,17 @@ def test_01_create_iso(self): self.assertEqual( iso_response.displaytext, - self.services["iso_2"]["displaytext"], + self.services["iso2"]["displaytext"], "Check display text of newly created ISO" ) self.assertEqual( iso_response.name, - self.services["iso_2"]["name"], + self.services["iso2"]["name"], "Check name of newly created ISO" ) self.assertEqual( iso_response.zoneid, - self.services["iso_2"]["zoneid"], + self.services["iso2"]["zoneid"], "Check zone ID of newly created ISO" ) return @@ -189,62 +139,62 @@ class TestISO(cloudstackTestCase): @classmethod def setUpClass(cls): - cls.services = Services().services - cls.api_client = super(TestISO, cls).getClsTestClient().getApiClient() + testClient = super(TestISO, cls).getClsTestClient() + cls.apiclient = testClient.getApiClient() + cls.services = testClient.getParsedTestDataConfig() # Get Zone, Domain and templates - cls.domain = get_domain(cls.api_client, cls.services) - cls.zone = get_zone(cls.api_client, cls.services) + cls.domain = get_domain(cls.apiclient) + cls.zone = get_zone(cls.apiclient, cls.testClient.getZoneForTests()) cls.services["domainid"] = cls.domain.id - cls.services["iso_1"]["zoneid"] = cls.zone.id - cls.services["iso_2"]["zoneid"] = cls.zone.id + cls.services["iso1"]["zoneid"] = cls.zone.id + cls.services["iso2"]["zoneid"] = cls.zone.id cls.services["sourcezoneid"] = cls.zone.id #populate second zone id for iso copy cmd = listZones.listZonesCmd() - cls.zones = cls.api_client.listZones(cmd) + cls.zones = cls.apiclient.listZones(cmd) if not isinstance(cls.zones, list): raise Exception("Failed to find zones.") #Create an account, ISOs etc. cls.account = Account.create( - cls.api_client, + cls.apiclient, cls.services["account"], domainid=cls.domain.id ) - cls.services["account"] = cls.account.name # Finding the OsTypeId from Ostype ostypes = list_os_types( - cls.api_client, + cls.apiclient, description=cls.services["ostype"] ) if not isinstance(ostypes, list): raise unittest.SkipTest("OSTypeId for given description not found") - cls.services["iso_1"]["ostypeid"] = ostypes[0].id - cls.services["iso_2"]["ostypeid"] = ostypes[0].id + cls.services["iso1"]["ostypeid"] = ostypes[0].id + cls.services["iso2"]["ostypeid"] = ostypes[0].id cls.services["ostypeid"] = ostypes[0].id cls.iso_1 = Iso.create( - cls.api_client, - cls.services["iso_1"], + cls.apiclient, + cls.services["iso1"], account=cls.account.name, domainid=cls.account.domainid ) try: - cls.iso_1.download(cls.api_client) + cls.iso_1.download(cls.apiclient) except Exception as e: raise Exception("Exception while downloading ISO %s: %s"\ % (cls.iso_1.id, e)) cls.iso_2 = Iso.create( - cls.api_client, - cls.services["iso_2"], + cls.apiclient, + cls.services["iso2"], account=cls.account.name, domainid=cls.account.domainid ) try: - cls.iso_2.download(cls.api_client) + cls.iso_2.download(cls.apiclient) except Exception as e: raise Exception("Exception while downloading ISO %s: %s"\ % (cls.iso_2.id, e)) @@ -255,9 +205,9 @@ def setUpClass(cls): @classmethod def tearDownClass(cls): try: - cls.api_client = super(TestISO, cls).getClsTestClient().getApiClient() + cls.apiclient = super(TestISO, cls).getClsTestClient().getApiClient() #Clean up, terminate the created templates - cleanup_resources(cls.api_client, cls._cleanup) + cleanup_resources(cls.apiclient, cls._cleanup) except Exception as e: raise Exception("Warning: Exception during cleanup : %s" % e) @@ -279,7 +229,7 @@ def tearDown(self): return - @attr(tags = ["advanced", "basic", "eip", "sg", "advancedns", "smoke"]) + @attr(tags = ["advanced", "basic", "eip", "sg", "advancedns", "smoke", "selfservice"]) def test_02_edit_iso(self): """Test Edit ISO """ @@ -344,7 +294,7 @@ def test_02_edit_iso(self): ) return - @attr(tags = ["advanced", "basic", "eip", "sg", "advancedns", "smoke"]) + @attr(tags = ["advanced", "basic", "eip", "sg", "advancedns", "smoke", "selfservice"]) def test_03_delete_iso(self): """Test delete ISO """ @@ -372,7 +322,7 @@ def test_03_delete_iso(self): ) return - @attr(tags = ["advanced", "basic", "eip", "sg", "advancedns", "smoke"]) + @attr(tags = ["advanced", "basic", "eip", "sg", "advancedns", "smoke", "provisioning"]) def test_04_extract_Iso(self): "Test for extract ISO" @@ -386,21 +336,9 @@ def test_04_extract_Iso(self): cmd = extractIso.extractIsoCmd() cmd.id = self.iso_2.id - cmd.mode = self.services["iso_2"]["mode"] - cmd.zoneid = self.services["iso_2"]["zoneid"] + cmd.mode = self.services["iso2"]["mode"] + cmd.zoneid = self.services["iso2"]["zoneid"] list_extract_response = self.apiclient.extractIso(cmd) - - try: - #Format URL to ASCII to retrieve response code - formatted_url = urllib.unquote_plus(list_extract_response.url) - url_response = urllib.urlopen(formatted_url) - response_code = url_response.getcode() - except Exception: - self.fail( - "Extract ISO Failed with invalid URL %s (ISO id: %s)" \ - % (formatted_url, self.iso_2.id) - ) - self.assertEqual( list_extract_response.id, self.iso_2.id, @@ -408,14 +346,26 @@ def test_04_extract_Iso(self): ) self.assertEqual( list_extract_response.extractMode, - self.services["iso_2"]["mode"], + self.services["iso2"]["mode"], "Check mode of extraction" ) self.assertEqual( list_extract_response.zoneid, - self.services["iso_2"]["zoneid"], + self.services["iso2"]["zoneid"], "Check zone ID of extraction" ) + + try: + #Format URL to ASCII to retrieve response code + formatted_url = urllib.unquote_plus(list_extract_response.url) + url_response = urllib.urlopen(formatted_url) + response_code = url_response.getcode() + except Exception: + self.fail( + "Extract ISO Failed with invalid URL %s (ISO id: %s)" \ + % (formatted_url, self.iso_2.id) + ) + self.assertEqual( response_code, 200, @@ -423,7 +373,7 @@ def test_04_extract_Iso(self): ) return - @attr(tags = ["advanced", "basic", "eip", "sg", "advancedns", "smoke"]) + @attr(tags = ["advanced", "basic", "eip", "sg", "advancedns", "smoke", "selfservice"]) def test_05_iso_permissions(self): """Update & Test for ISO permissions""" @@ -475,7 +425,7 @@ def test_05_iso_permissions(self): ) return - @attr(tags = ["advanced", "basic", "eip", "sg", "advancedns", "smoke", "multizone"]) + @attr(tags = ["advanced", "basic", "eip", "sg", "advancedns", "smoke", "multizone", "provisioning"]) def test_06_copy_iso(self): """Test for copy ISO from one zone to another""" diff --git a/test/integration/smoke/test_loadbalance.py b/test/integration/smoke/test_loadbalance.py index 5f80c38303..daa5fee3d2 100644 --- a/test/integration/smoke/test_loadbalance.py +++ b/test/integration/smoke/test_loadbalance.py @@ -15,154 +15,86 @@ # specific language governing permissions and limitations # under the License. +from marvin.codes import FAILED from marvin.cloudstackTestCase import * from marvin.cloudstackAPI import * from marvin.sshClient import SshClient -from marvin.integration.lib.utils import * -from marvin.integration.lib.base import * -from marvin.integration.lib.common import * +from marvin.lib.utils import * +from marvin.lib.base import * +from marvin.lib.common import * from nose.plugins.attrib import attr #Import System modules import time _multiprocess_shared_ = True -class Services: - """Test Network Services - """ - - def __init__(self): - self.services = { - "ostype": "CentOS 5.3 (64-bit)", - # Cent OS 5.3 (64 bit) - "lb_switch_wait": 10, - # Time interval after which LB switches the requests - "sleep": 60, - "timeout":10, - "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", - }, - "service_offering": { - "name": "Tiny Instance", - "displaytext": "Tiny Instance", - "cpunumber": 1, - "cpuspeed": 100, - # in MHz - "memory": 256, - # In MBs - }, - "account": { - "email": "test@test.com", - "firstname": "Test", - "lastname": "User", - "username": "test", - "password": "password", - }, - "server": - { - "displayname": "Small Instance", - "username": "root", - "password": "password", - "hypervisor": 'XenServer', - "privateport": 22, - "publicport": 22, - "ssh_port": 22, - "protocol": 'TCP', - }, - "natrule": - { - "privateport": 22, - "publicport": 2222, - "protocol": "TCP" - }, - "lbrule": - { - "name": "SSH", - "alg": "roundrobin", - # Algorithm used for load balancing - "privateport": 22, - "publicport": 2222, - "protocol": 'TCP' - } - } - class TestLoadBalance(cloudstackTestCase): @classmethod def setUpClass(cls): - cls.api_client = super(TestLoadBalance, cls).getClsTestClient().getApiClient() - cls.services = Services().services + testClient = super(TestLoadBalance, cls).getClsTestClient() + cls.apiclient = testClient.getApiClient() + cls.services = testClient.getParsedTestDataConfig() + # Get Zone, Domain and templates - cls.domain = get_domain(cls.api_client, cls.services) - cls.zone = get_zone(cls.api_client, cls.services) + cls.domain = get_domain(cls.apiclient) + cls.zone = get_zone(cls.apiclient, testClient.getZoneForTests()) template = get_template( - cls.api_client, + cls.apiclient, cls.zone.id, cls.services["ostype"] ) - cls.services["server"]["zoneid"] = cls.zone.id + if template == FAILED: + assert False, "get_template() failed to return template with description %s" % cls.services["ostype"] + + cls.services["virtual_machine"]["zoneid"] = cls.zone.id #Create an account, network, VM and IP addresses cls.account = Account.create( - cls.api_client, + cls.apiclient, cls.services["account"], admin=True, domainid=cls.domain.id ) cls.service_offering = ServiceOffering.create( - cls.api_client, - cls.services["service_offering"] + cls.apiclient, + cls.services["service_offerings"] ) cls.vm_1 = VirtualMachine.create( - cls.api_client, - cls.services["server"], + cls.apiclient, + cls.services["virtual_machine"], templateid=template.id, accountid=cls.account.name, domainid=cls.account.domainid, serviceofferingid=cls.service_offering.id ) cls.vm_2 = VirtualMachine.create( - cls.api_client, - cls.services["server"], + cls.apiclient, + cls.services["virtual_machine"], templateid=template.id, accountid=cls.account.name, domainid=cls.account.domainid, serviceofferingid=cls.service_offering.id ) cls.vm_3 = VirtualMachine.create( - cls.api_client, - cls.services["server"], + cls.apiclient, + cls.services["virtual_machine"], templateid=template.id, accountid=cls.account.name, domainid=cls.account.domainid, serviceofferingid=cls.service_offering.id ) cls.non_src_nat_ip = PublicIPAddress.create( - cls.api_client, + cls.apiclient, cls.account.name, cls.zone.id, cls.account.domainid, - cls.services["server"] + cls.services["virtual_machine"] ) # Open up firewall port for SSH cls.fw_rule = FireWallRule.create( - cls.api_client, + cls.apiclient, ipaddressid=cls.non_src_nat_ip.ipaddress.id, protocol=cls.services["lbrule"]["protocol"], cidrlist=['0.0.0.0/0'], @@ -185,7 +117,7 @@ def tearDown(self): @classmethod def tearDownClass(cls): - cleanup_resources(cls.api_client, cls._cleanup) + cleanup_resources(cls.apiclient, cls._cleanup) return def try_ssh(self, ip_addr, hostnames): @@ -208,10 +140,10 @@ def try_ssh(self, ip_addr, hostnames): except Exception as e: self.fail("%s: SSH failed for VM with IP Address: %s" % (e, ip_addr)) - time.sleep(self.services["lb_switch_wait"]) + time.sleep(10) return - @attr(tags = ["advanced", "advancedns", "smoke"]) + @attr(tags = ["advanced", "advancedns", "smoke", "provisioning"]) def test_01_create_lb_rule_src_nat(self): """Test to create Load balancing rule with source NAT""" @@ -371,7 +303,7 @@ def test_01_create_lb_rule_src_nat(self): self.try_ssh(src_nat_ip_addr.ipaddress, hostnames) return - @attr(tags = ["advanced", "advancedns", "smoke"]) + @attr(tags = ["advanced", "advancedns", "smoke", "provisioning"]) def test_02_create_lb_rule_non_nat(self): """Test to create Load balancing rule with non source NAT""" @@ -489,7 +421,7 @@ def test_02_create_lb_rule_non_nat(self): self.try_ssh(self.non_src_nat_ip.ipaddress.ipaddress, hostnames) return - @attr(tags = ["advanced", "advancedns", "smoke"]) + @attr(tags = ["advanced", "advancedns", "smoke", "provisioning"]) def test_assign_and_removal_lb(self): """Test for assign & removing load balancing rule""" diff --git a/test/integration/smoke/test_multipleips_per_nic.py b/test/integration/smoke/test_multipleips_per_nic.py index 7d180641d6..ad3a3cf2e0 100644 --- a/test/integration/smoke/test_multipleips_per_nic.py +++ b/test/integration/smoke/test_multipleips_per_nic.py @@ -16,6 +16,7 @@ # under the License. #Test from the Marvin - Testing in Python wiki +from marvin.codes import FAILED #All tests inherit from cloudstackTestCase from marvin.cloudstackTestCase import cloudstackTestCase @@ -23,13 +24,13 @@ #Import Integration Libraries #base - contains all resources as entities and defines create, delete, list operations on them -from marvin.integration.lib.base import Account, VirtualMachine, ServiceOffering +from marvin.lib.base import Account, VirtualMachine, ServiceOffering #utils - utility classes for common cleanup, external library wrappers etc -from marvin.integration.lib.utils import cleanup_resources +from marvin.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 marvin.lib.common import get_zone, get_domain, get_template from marvin.cloudstackAPI.addIpToNic import addIpToNicCmd from marvin.cloudstackAPI.removeIpFromNic import removeIpFromNicCmd @@ -38,52 +39,23 @@ from nose.plugins.attrib import attr -class TestData(object): - """Test data object that is required to create resources - """ - def __init__(self): - self.testdata = { - #data to create an account - "account": { - "email": "test@test.com", - "firstname": "Test", - "lastname": "User", - "username": "test", - "password": "password", - }, - #data reqd for virtual machine creation - "virtual_machine" : { - "name" : "testvm", - "displayname" : "Test VM", - }, - #small service offering - "service_offering": { - "small": { - "name": "Small Instance", - "displaytext": "Small Instance", - "cpunumber": 1, - "cpuspeed": 100, - "memory": 256, - }, - }, - "ostype": 'CentOS 5.3 (64-bit)', - } - - class TestDeployVM(cloudstackTestCase): """Test deploy a VM into a user account """ def setUp(self): - self.testdata = TestData().testdata + self.testdata = self.testClient.getParsedTestDataConfig() self.apiclient = self.testClient.getApiClient() # Get Zone, Domain and Default Built-in template - self.domain = get_domain(self.apiclient, self.testdata) - self.zone = get_zone(self.apiclient, self.testdata) + self.domain = get_domain(self.apiclient) + self.zone = get_zone(self.apiclient, self.testClient.getZoneForTests()) self.testdata["mode"] = self.zone.networktype self.template = get_template(self.apiclient, self.zone.id, self.testdata["ostype"]) + if self.template == FAILED: + assert False, "get_template() failed to return template with description %s" % self.testdata["ostype"] + #create a user account self.account = Account.create( self.apiclient, @@ -93,7 +65,7 @@ def setUp(self): #create a service offering self.service_offering = ServiceOffering.create( self.apiclient, - self.testdata["service_offering"]["small"] + self.testdata["service_offerings"]["small"] ) #build cleanup list self.cleanup = [ @@ -150,8 +122,9 @@ def setUp(self): msg="VM is not in Running state" ) - @attr(tags = ['advanced', 'simulator', 'basic']) + @attr(tags = ['advanced', 'simulator', 'basic', "provisioning"]) def test_nic_secondaryip_add_remove(self): + #TODO: SIMENH: add verification list_vms = VirtualMachine.list(self.apiclient, id=self.virtual_machine.id) vm = list_vms[0] nicid = vm.nic[0].id diff --git a/test/integration/smoke/test_network.py b/test/integration/smoke/test_network.py index 732fe15825..6beb0710a8 100644 --- a/test/integration/smoke/test_network.py +++ b/test/integration/smoke/test_network.py @@ -18,139 +18,67 @@ """ #Import Local Modules import marvin -from marvin.cloudstackException import cloudstackAPIException +from marvin.codes import FAILED +from marvin.cloudstackException import CloudstackAPIException from marvin.cloudstackTestCase import * from marvin.cloudstackAPI import * from marvin.sshClient import SshClient -from marvin.integration.lib.utils import * -from marvin.integration.lib.base import * -from marvin.integration.lib.common import * +from marvin.lib.utils import * +from marvin.lib.base import * +from marvin.lib.common import * from nose.plugins.attrib import attr #Import System modules import time _multiprocess_shared_ = True -class Services: - """Test Network Services - """ - - def __init__(self): - self.services = { - "ostype": "CentOS 5.3 (64-bit)", - # Cent OS 5.3 (64 bit) - "lb_switch_wait": 10, - # Time interval after which LB switches the requests - "sleep": 60, - "timeout":10, - "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", - }, - "service_offering": { - "name": "Tiny Instance", - "displaytext": "Tiny Instance", - "cpunumber": 1, - "cpuspeed": 100, - # in MHz - "memory": 256, - # In MBs - }, - "account": { - "email": "test@test.com", - "firstname": "Test", - "lastname": "User", - "username": "test", - "password": "password", - }, - "server": - { - "displayname": "Small Instance", - "username": "root", - "password": "password", - "hypervisor": 'XenServer', - "privateport": 22, - "publicport": 22, - "ssh_port": 22, - "protocol": 'TCP', - }, - "natrule": - { - "privateport": 22, - "publicport": 22, - "protocol": "TCP" - }, - "lbrule": - { - "name": "SSH", - "alg": "roundrobin", - # Algorithm used for load balancing - "privateport": 22, - "publicport": 2222, - "protocol": 'TCP' - } - } - class TestPublicIP(cloudstackTestCase): def setUp(self): self.apiclient = self.testClient.getApiClient() - self.services = Services().services @classmethod def setUpClass(cls): - cls.api_client = super(TestPublicIP, cls).getClsTestClient().getApiClient() - cls.services = Services().services + testClient = super(TestPublicIP, cls).getClsTestClient() + cls.apiclient = testClient.getApiClient() + cls.services = testClient.getParsedTestDataConfig() + # Get Zone, Domain and templates - cls.domain = get_domain(cls.api_client, cls.services) - cls.zone = get_zone(cls.api_client, cls.services) + cls.domain = get_domain(cls.apiclient) + cls.zone = get_zone(cls.apiclient, testClient.getZoneForTests()) cls.services['mode'] = cls.zone.networktype # Create Accounts & networks cls.account = Account.create( - cls.api_client, + cls.apiclient, cls.services["account"], admin=True, domainid=cls.domain.id ) cls.user = Account.create( - cls.api_client, + cls.apiclient, cls.services["account"], domainid=cls.domain.id ) cls.services["network"]["zoneid"] = cls.zone.id cls.network_offering = NetworkOffering.create( - cls.api_client, + cls.apiclient, cls.services["network_offering"], ) # Enable Network offering - cls.network_offering.update(cls.api_client, state='Enabled') + cls.network_offering.update(cls.apiclient, state='Enabled') cls.services["network"]["networkoffering"] = cls.network_offering.id cls.account_network = Network.create( - cls.api_client, + cls.apiclient, cls.services["network"], cls.account.name, cls.account.domainid ) cls.user_network = Network.create( - cls.api_client, + cls.apiclient, cls.services["network"], cls.user.name, cls.user.domainid @@ -158,13 +86,13 @@ def setUpClass(cls): # Create Source NAT IP addresses account_src_nat_ip = PublicIPAddress.create( - cls.api_client, + cls.apiclient, cls.account.name, cls.zone.id, cls.account.domainid ) user_src_nat_ip = PublicIPAddress.create( - cls.api_client, + cls.apiclient, cls.user.name, cls.zone.id, cls.user.domainid @@ -182,12 +110,12 @@ def setUpClass(cls): def tearDownClass(cls): try: #Cleanup resources used - cleanup_resources(cls.api_client, cls._cleanup) + cleanup_resources(cls.apiclient, cls._cleanup) except Exception as e: raise Exception("Warning: Exception during cleanup : %s" % e) return - @attr(tags = ["advanced", "advancedns", "smoke"]) + @attr(tags = ["advanced", "advancedns", "smoke", "selfservice"]) def test_public_ip_admin_account(self): """Test for Associate/Disassociate public IP address for admin account""" @@ -223,6 +151,7 @@ def test_public_ip_admin_account(self): ) ip_address.delete(self.apiclient) + time.sleep(30) # Validate the following: # 1.listPublicIpAddresses should no more return the released address @@ -231,13 +160,18 @@ def test_public_ip_admin_account(self): id=ip_address.ipaddress.id ) self.assertEqual( - list_pub_ip_addr_resp, - None, - "Check if disassociated IP Address is no longer available" - ) + isinstance(list_pub_ip_addr_resp, list), + True, + "Check list response returns a valid list" + ) + self.assertEqual( + len(list_pub_ip_addr_resp), + 0, + "Check if the list public ip api response is not zero" + ) return - @attr(tags = ["advanced", "advancedns", "smoke"]) + @attr(tags = ["advanced", "advancedns", "smoke", "selfservice"]) def test_public_ip_user_account(self): """Test for Associate/Disassociate public IP address for user account""" @@ -293,32 +227,35 @@ class TestPortForwarding(cloudstackTestCase): @classmethod def setUpClass(cls): - cls.api_client = super(TestPortForwarding, cls).getClsTestClient().getApiClient() - cls.services = Services().services - + testClient = super(TestPortForwarding, cls).getClsTestClient() + cls.apiclient = testClient.getApiClient() + cls.services = testClient.getParsedTestDataConfig() # Get Zone, Domain and templates - cls.domain = get_domain(cls.api_client, cls.services) - cls.zone = get_zone(cls.api_client, cls.services) + cls.domain = get_domain(cls.apiclient) + cls.zone = get_zone(cls.apiclient, testClient.getZoneForTests()) template = get_template( - cls.api_client, + cls.apiclient, cls.zone.id, cls.services["ostype"] ) + if template == FAILED: + assert False, "get_template() failed to return template with description %s" % cls.services["ostype"] + #Create an account, network, VM and IP addresses cls.account = Account.create( - cls.api_client, + cls.apiclient, cls.services["account"], admin=True, domainid=cls.domain.id ) - cls.services["server"]["zoneid"] = cls.zone.id + cls.services["virtual_machine"]["zoneid"] = cls.zone.id cls.service_offering = ServiceOffering.create( - cls.api_client, - cls.services["service_offering"] + cls.apiclient, + cls.services["service_offerings"] ) cls.virtual_machine = VirtualMachine.create( - cls.api_client, - cls.services["server"], + cls.apiclient, + cls.services["virtual_machine"], templateid=template.id, accountid=cls.account.name, domainid=cls.account.domainid, @@ -338,8 +275,8 @@ def setUp(self): @classmethod def tearDownClass(cls): try: - cls.api_client = super(TestPortForwarding, cls).getClsTestClient().getApiClient() - cleanup_resources(cls.api_client, cls._cleanup) + cls.apiclient = super(TestPortForwarding, cls).getClsTestClient().getApiClient() + cleanup_resources(cls.apiclient, cls._cleanup) except Exception as e: raise Exception("Warning: Exception during cleanup : %s" % e) @@ -347,7 +284,7 @@ def tearDown(self): cleanup_resources(self.apiclient, self.cleanup) return - @attr(tags = ["advanced", "advancedns", "smoke"]) + @attr(tags = ["advanced", "advancedns", "smoke", "provisioning"]) def test_01_port_fwd_on_src_nat(self): """Test for port forwarding on source NAT""" @@ -437,22 +374,27 @@ def test_01_port_fwd_on_src_nat(self): )) self.virtual_machine.get_ssh_client(src_nat_ip_addr.ipaddress) - + vm_response = VirtualMachine.list( + self.apiclient, + id=self.virtual_machine.id + ) + if vm_response[0].state != 'Running': + self.fail("State of VM : %s is not found to be Running" % str(self.virtual_machine.ipaddress)) + except Exception as e: self.fail( "SSH Access failed for %s: %s" % \ (self.virtual_machine.ipaddress, e) ) - nat_rule.delete(self.apiclient) - try: + nat_rule.delete(self.apiclient) list_nat_rule_response = list_nat_rules( self.apiclient, id=nat_rule.id ) - except cloudstackAPIException: - self.debug("Nat Rule is deleted") + except CloudstackAPIException: + self.fail("Nat Rule Deletion or Listing Failed") # Check if the Public SSH port is inaccessible with self.assertRaises(Exception): @@ -464,13 +406,11 @@ def test_01_port_fwd_on_src_nat(self): src_nat_ip_addr.ipaddress, self.virtual_machine.ssh_port, self.virtual_machine.username, - self.virtual_machine.password, - retries=2, - delay=0 + self.virtual_machine.password ) return - @attr(tags = ["advanced", "advancedns", "smoke"]) + @attr(tags = ["advanced", "advancedns", "smoke", "provisioning"]) def test_02_port_fwd_on_non_src_nat(self): """Test for port forwarding on non source NAT""" @@ -483,7 +423,7 @@ def test_02_port_fwd_on_non_src_nat(self): self.account.name, self.zone.id, self.account.domainid, - self.services["server"] + self.services["virtual_machine"] ) self.cleanup.append(ip_address) @@ -569,7 +509,7 @@ def test_02_port_fwd_on_non_src_nat(self): self.apiclient, id=nat_rule.id ) - except cloudstackAPIException: + except CloudstackAPIException: self.debug("Nat Rule is deleted") # Check if the Public SSH port is inaccessible @@ -596,17 +536,19 @@ class TestRebootRouter(cloudstackTestCase): def setUp(self): self.apiclient = self.testClient.getApiClient() - self.services = Services().services + self.services = self.testClient.getParsedTestDataConfig() # Get Zone, Domain and templates - self.domain = get_domain(self.apiclient, self.services) - self.zone = get_zone(self.apiclient, self.services) + self.domain = get_domain(self.apiclient) + self.zone = get_zone(self.apiclient, self.testClient.getZoneForTests()) template = get_template( self.apiclient, self.zone.id, self.services["ostype"] ) - self.services["server"]["zoneid"] = self.zone.id + if template == FAILED: + self.fail("get_template() failed to return template with description %s" % self.services["ostype"]) + self.services["virtual_machine"]["zoneid"] = self.zone.id #Create an account, network, VM and IP addresses self.account = Account.create( @@ -617,11 +559,11 @@ def setUp(self): ) self.service_offering = ServiceOffering.create( self.apiclient, - self.services["service_offering"] + self.services["service_offerings"] ) self.vm_1 = VirtualMachine.create( self.apiclient, - self.services["server"], + self.services["virtual_machine"], templateid=template.id, accountid=self.account.name, domainid=self.account.domainid, @@ -646,7 +588,7 @@ def setUp(self): self.vm_1.account, self.vm_1.zoneid, self.vm_1.domainid, - self.services["server"] + self.services["virtual_machine"] ) #Open up firewall port for SSH fw_rule = FireWallRule.create( @@ -680,7 +622,7 @@ def setUp(self): ] return - @attr(tags = ["advanced", "advancedns", "smoke"]) + @attr(tags = ["advanced", "advancedns", "smoke", "provisioning"]) def test_reboot_router(self): """Test for reboot router""" @@ -696,7 +638,8 @@ def test_reboot_router(self): routers = list_routers( self.apiclient, account=self.account.name, - domainid=self.account.domainid + domainid=self.account.domainid, + listall=True ) self.assertEqual( isinstance(routers, list), @@ -762,17 +705,17 @@ class TestReleaseIP(cloudstackTestCase): def setUp(self): self.apiclient = self.testClient.getApiClient() - self.services = Services().services + self.services = self.testClient.getParsedTestDataConfig() # Get Zone, Domain and templates - self.domain = get_domain(self.apiclient, self.services) - self.zone = get_zone(self.apiclient, self.services) + self.domain = get_domain(self.apiclient) + self.zone = get_zone(self.apiclient, self.testClient.getZoneForTests()) template = get_template( self.apiclient, self.zone.id, self.services["ostype"] ) - self.services["server"]["zoneid"] = self.zone.id + self.services["virtual_machine"]["zoneid"] = self.zone.id #Create an account, network, VM, Port forwarding rule, LB rules self.account = Account.create( @@ -784,12 +727,12 @@ def setUp(self): self.service_offering = ServiceOffering.create( self.apiclient, - self.services["service_offering"] + self.services["service_offerings"] ) self.virtual_machine = VirtualMachine.create( self.apiclient, - self.services["server"], + self.services["virtual_machine"], templateid=template.id, accountid=self.account.name, domainid=self.account.domainid, @@ -835,7 +778,7 @@ def setUp(self): def tearDown(self): cleanup_resources(self.apiclient, self.cleanup) - @attr(tags = ["advanced", "advancedns", "smoke"]) + @attr(tags = ["advanced", "advancedns", "smoke", "selfservice"]) def test_releaseIP(self): """Test for release public IP address""" @@ -867,7 +810,7 @@ def test_releaseIP(self): id=self.nat_rule.id ) self.debug("List NAT Rule response" + str(list_nat_rule)) - except cloudstackAPIException: + except CloudstackAPIException: self.debug("Port Forwarding Rule is deleted") # listLoadBalancerRules should not list @@ -878,7 +821,7 @@ def test_releaseIP(self): id=self.lb_rule.id ) self.debug("List LB Rule response" + str(list_lb_rule)) - except cloudstackAPIException: + except CloudstackAPIException: self.debug("Port Forwarding Rule is deleted") # SSH Attempt though public IP should fail @@ -899,17 +842,17 @@ class TestDeleteAccount(cloudstackTestCase): def setUp(self): self.apiclient = self.testClient.getApiClient() - self.services = Services().services + self.services = self.testClient.getParsedTestDataConfig() # Get Zone, Domain and templates - self.domain = get_domain(self.apiclient, self.services) - self.zone = get_zone(self.apiclient, self.services) + self.domain = get_domain(self.apiclient) + self.zone = get_zone(self.apiclient, self.testClient.getZoneForTests()) template = get_template( self.apiclient, self.zone.id, self.services["ostype"] ) - self.services["server"]["zoneid"] = self.zone.id + self.services["virtual_machine"]["zoneid"] = self.zone.id #Create an account, network, VM and IP addresses self.account = Account.create( @@ -920,11 +863,11 @@ def setUp(self): ) self.service_offering = ServiceOffering.create( self.apiclient, - self.services["service_offering"] + self.services["service_offerings"] ) self.vm_1 = VirtualMachine.create( self.apiclient, - self.services["server"], + self.services["virtual_machine"], templateid=template.id, accountid=self.account.name, domainid=self.account.domainid, @@ -960,7 +903,7 @@ def setUp(self): self.cleanup = [] return - @attr(tags = ["advanced", "advancedns", "smoke"]) + @attr(tags = ["advanced", "advancedns", "smoke", "selfservice"]) def test_delete_account(self): """Test for delete account""" @@ -993,7 +936,7 @@ def test_delete_account(self): account=self.account.name, domainid=self.account.domainid ) - except cloudstackAPIException: + except CloudstackAPIException: self.debug("Port Forwarding Rule is deleted") # ListPortForwardingRules should not @@ -1004,7 +947,7 @@ def test_delete_account(self): account=self.account.name, domainid=self.account.domainid ) - except cloudstackAPIException: + except CloudstackAPIException: self.debug("NATRule is deleted") #Retrieve router for the user account @@ -1012,14 +955,15 @@ def test_delete_account(self): routers = list_routers( self.apiclient, account=self.account.name, - domainid=self.account.domainid + domainid=self.account.domainid, + listall=True ) self.assertEqual( routers, None, "Check routers are properly deleted." ) - except cloudstackAPIException: + except CloudstackAPIException: self.debug("Router is deleted") except Exception as e: diff --git a/test/integration/smoke/test_network_acl.py b/test/integration/smoke/test_network_acl.py index 3363e460dd..68e5067da8 100644 --- a/test/integration/smoke/test_network_acl.py +++ b/test/integration/smoke/test_network_acl.py @@ -17,77 +17,27 @@ """ Tests for Network ACLs in VPC """ #Import Local Modules +from marvin.codes import FAILED 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.lib.utils import * +from marvin.lib.base import * +from marvin.lib.common import * from nose.plugins.attrib import attr -class Services: - def __init__(self): - self.services = { - "account": { - "email": "test@test.com", - "firstname": "Test", - "lastname": "User", - "username": "test", - "password": "password", - }, - "virtual_machine": { - "displayname": "Test VM", - "username": "root", - "password": "password", - "ssh_port": 22, - "hypervisor": 'XenServer', - "privateport": 22, - "publicport": 22, - "protocol": 'TCP', - }, - "ostype": 'CentOS 5.3 (64-bit)', - "service_offering": { - "name": "Tiny Instance", - "displaytext": "Tiny Instance", - "cpunumber": 1, - "cpuspeed": 100, - "memory": 256, - }, - "network_offering": { - "name": "Network offering for internal lb service", - "displaytext": "Network offering for internal lb service", - "guestiptype": "Isolated", - "traffictype": "Guest", - "supportedservices": "Vpn,Dhcp,Dns,Lb,UserData,SourceNat,StaticNat,PortForwarding,NetworkACL", - "serviceProviderList": { - "Dhcp": "VpcVirtualRouter", - "Dns": "VpcVirtualRouter", - "Vpn": "VpcVirtualRouter", - "UserData": "VpcVirtualRouter", - "Lb": "InternalLbVM", - "SourceNat": "VpcVirtualRouter", - "StaticNat": "VpcVirtualRouter", - "PortForwarding": "VpcVirtualRouter", - "NetworkACL": "VpcVirtualRouter", - }, - "serviceCapabilityList": { - "SourceNat": {"SupportedSourceNatTypes": "peraccount"}, - "Lb": {"lbSchemes": "internal", "SupportedLbIsolation": "dedicated"} - } - } - } - - class TestNetworkACL(cloudstackTestCase): @classmethod def setUpClass(cls): - cls.apiclient = super(TestNetworkACL, cls).getClsTestClient().getApiClient() - cls.services = Services().services - cls.zone = get_zone(cls.apiclient, cls.services) + testClient = super(TestNetworkACL, cls).getClsTestClient() + cls.apiclient = testClient.getApiClient() + cls.services = testClient.getParsedTestDataConfig() + + cls.zone = get_zone(cls.apiclient, testClient.getZoneForTests()) cls.domain = get_domain(cls.apiclient) cls.service_offering = ServiceOffering.create( cls.apiclient, - cls.services["service_offering"] + cls.services["service_offerings"] ) cls.account = Account.create(cls.apiclient, services=cls.services["account"]) cls.template = get_template( @@ -95,13 +45,18 @@ def setUpClass(cls): cls.zone.id, cls.services["ostype"] ) + + if cls.template == FAILED: + assert False, "get_template() failed to return template with description %s" % cls.services["ostype"] + cls.debug("Successfully created account: %s, id: \ %s" % (cls.account.name,\ cls.account.id)) cls.cleanup = [cls.account] - @attr(tags=["advanced"]) + @attr(tags=["advanced", "provisioning"]) def test_network_acl(self): + #TODO: SIMENH: add actual verification Logic for rules. """Test network ACL lists and items in VPC""" # 0) Get the default network offering for VPC diff --git a/test/integration/smoke/test_nic.py b/test/integration/smoke/test_nic.py index ac95685f37..592a8391a0 100644 --- a/test/integration/smoke/test_nic.py +++ b/test/integration/smoke/test_nic.py @@ -16,125 +16,23 @@ # under the License. """ NIC tests for VM """ import marvin +from marvin.codes import FAILED from marvin.cloudstackTestCase import * from marvin.cloudstackAPI import * from marvin.sshClient import SshClient -from marvin.integration.lib.utils import * -from marvin.integration.lib.base import * -from marvin.integration.lib.common import * +from marvin.lib.utils import * +from marvin.lib.base import * +from marvin.lib.common import * from nose.plugins.attrib import attr import signal import sys import time -class 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", - }, - # Create a small virtual machine instance with disk offering - "small": { - "displayname": "testserver", - "username": "root", # VM creds for SSH - "password": "password", - "ssh_port": 22, - "hypervisor": 'XenServer', - "privateport": 22, - "publicport": 22, - "protocol": 'TCP', - }, - "service_offerings": { - "tiny": { - "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_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", - "name": "testISO", - "url": "http://people.apache.org/~tsp/dummy.iso", - # Source URL where ISO is located - "ostype": 'CentOS 5.3 (64-bit)', - "mode": 'HTTP_DOWNLOAD', # Downloading existing ISO - }, - "template": { - "displaytext": "Cent OS Template", - "name": "Cent OS Template", - "passwordenabled": True, - }, - "sleep": 60, - "timeout": 10, - #Migrate VM to hostid - "ostype": 'CentOS 5.3 (64-bit)', - # CentOS 5.3 (64-bit) - } - class TestNic(cloudstackTestCase): def setUp(self): self.cleanup = [] - self.cleaning_up = 0 - def signal_handler(signal, frame): self.tearDown() sys.exit(0) @@ -145,16 +43,13 @@ def signal_handler(signal, frame): try: self.apiclient = self.testClient.getApiClient() self.dbclient = self.testClient.getDbConnection() - self.services = Services().services + self.services = self.testClient.getParsedTestDataConfig() # Get Zone, Domain and templates - domain = get_domain(self.apiclient, self.services) - zone = get_zone(self.apiclient, self.services) + domain = get_domain(self.apiclient) + zone = get_zone(self.apiclient, self.testClient.getZoneForTests()) self.services['mode'] = zone.networktype - if zone.networktype != 'Advanced': - self.skipTest("Cannot run this test with a basic zone, please use advanced!") - #if local storage is enabled, alter the offerings to use localstorage #this step is needed for devcloud if zone.localstorageenabled == True: @@ -169,7 +64,7 @@ def signal_handler(signal, frame): self.services["small"]["zoneid"] = zone.id self.services["small"]["template"] = template.id - self.services["iso"]["zoneid"] = zone.id + self.services["iso1"]["zoneid"] = zone.id self.services["network"]["zoneid"] = zone.id # Create Account, VMs, NAT Rules etc @@ -224,8 +119,9 @@ def signal_handler(signal, frame): except Exception as ex: self.debug("Exception during NIC test SETUP!: " + str(ex)) - @attr(tags = ["devcloud", "advanced", "advancedns", "smoke", "basic", "sg"]) + @attr(tags = ["devcloud", "smoke", "advanced", "advancedns", "provisioning"]) def test_01_nic(self): + #TODO: SIMENH: add validation """Test to add and update added nic to a virtual machine""" try: @@ -364,14 +260,6 @@ def test_01_nic(self): self.assertEqual(True, False, "Exception during NIC test!: " + str(ex)) def tearDown(self): - if self.services['mode'] != 'Advanced': - self.debug("Cannot run this test with a basic zone, please use advanced!") - return - - if self.cleaning_up == 1: - return - - self.cleaning_up = 1 try: for obj in self.cleanup: try: @@ -379,8 +267,6 @@ def tearDown(self): time.sleep(10) except Exception as ex: self.debug("Error deleting: " + str(obj) + ", exception: " + str(ex)) - except Exception as e: self.debug("Warning! Exception in tearDown: %s" % e) - self.cleaning_up = 0 diff --git a/test/integration/smoke/test_non_contigiousvlan.py b/test/integration/smoke/test_non_contigiousvlan.py index f1736ae447..a84e62fc39 100644 --- a/test/integration/smoke/test_non_contigiousvlan.py +++ b/test/integration/smoke/test_non_contigiousvlan.py @@ -18,8 +18,8 @@ from marvin import cloudstackTestCase from marvin.cloudstackAPI import * from marvin.cloudstackTestCase import cloudstackTestCase -from marvin.integration.lib.base import Account -from marvin.integration.lib.base import PhysicalNetwork +from marvin.lib.base import Account +from marvin.lib.base import PhysicalNetwork from nose.plugins.attrib import attr class Services(): @@ -32,7 +32,7 @@ def __init__(self): } -@attr(tags = ["simulator", "advanced"]) +@attr(tags = ["simulator", "advanced", "selfservice"]) class TestUpdatePhysicalNetwork(cloudstackTestCase): """ Test to extend physical network vlan range diff --git a/test/integration/smoke/test_over_provisioning.py b/test/integration/smoke/test_over_provisioning.py index 28f32b7af9..1c5d8a520f 100644 --- a/test/integration/smoke/test_over_provisioning.py +++ b/test/integration/smoke/test_over_provisioning.py @@ -19,9 +19,9 @@ #Import Local Modules 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.lib.utils import * +from marvin.lib.base import * +from marvin.lib.common import * from nose.plugins.attrib import attr #Import System modules @@ -32,7 +32,7 @@ class TestUpdateOverProvision(cloudstackTestCase): def setUp(self): self.apiClient = self.testClient.getApiClient() - @attr(tags=["simulator", "devcloud", "basic", "advanced"]) + @attr(tags=["simulator", "devcloud", "basic", "advanced", "selfservice"]) def test_UpdateStorageOverProvisioningFactor(self): """ test update configuration setting at storage scope @@ -67,7 +67,11 @@ def test_UpdateStorageOverProvisioningFactor(self): self.poolId = pool.id """ list overprovisioning factor for storage pool """ - factorOld = float(pool.overprovisionfactor) + failed = 0 + if pool.overprovisionfactor is None: + failed = 1 + self.assertNotEqual(failed,1,"pool.overprovisionfactor is none") + factorOld = float(str(pool.overprovisionfactor)) factorNew = str(factorOld + 1.0) """ update setting for the pool""" @@ -85,7 +89,11 @@ def test_UpdateStorageOverProvisioningFactor(self): id = self.poolId ) pool = storage_pools[0] - factorNew = float(pool.overprovisionfactor) + failed = 0 + if pool.overprovisionfactor is None: + failed = 1 + self.assertNotEqual(failed,1,"pool.overprovisionfactor is none") + factorNew = float(str(pool.overprovisionfactor)) self.assertNotEqual(int(factorNew), int(factorOld)," Check if overprovision factor of storage pool has changed") self.assertEqual(int(factorNew), int(factorOld + 1.0)," Check if overprovision factor of storage pool has increased by 1") @@ -100,8 +108,11 @@ def tearDown(self): pool = storage_pools[0] updateConfigurationCmd = updateConfiguration.updateConfigurationCmd() updateConfigurationCmd.name = "storage.overprovisioning.factor" - factorOld = float(pool.overprovisionfactor) + factorOld = 0 + if pool.overprovisionfactor is not None: + factorOld = float(str(pool.overprovisionfactor)) factorNew = str(factorOld - 1.0) - updateConfigurationCmd.value = factorNew - updateConfigurationCmd.storageid = pool.id - updateConfigurationResponse = self.apiClient.updateConfiguration(updateConfigurationCmd) + if factorNew > 0: + updateConfigurationCmd.value = factorNew + updateConfigurationCmd.storageid = pool.id + updateConfigurationResponse = self.apiClient.updateConfiguration(updateConfigurationCmd) diff --git a/test/integration/smoke/test_portable_publicip.py b/test/integration/smoke/test_portable_publicip.py index 0faed7163c..2d02a7114e 100644 --- a/test/integration/smoke/test_portable_publicip.py +++ b/test/integration/smoke/test_portable_publicip.py @@ -18,73 +18,11 @@ 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.lib.utils import * +from marvin.lib.base import * +from marvin.lib.common import * 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" : "172.1.1.1", - "netmask" : "255.255.255.0", - "startip" : "172.1.1.10", - "endip" : "172.1.1.20", - "regionid" : "1", - "vlan" :"10", - "isportable" : "true", - "virtual_machine" : { - "affinity": { - "name": "webvms", - "type": "host anti-affinity", - }, - "hypervisor" : "XenServer", - } - } - class TestPortablePublicIPRange(cloudstackTestCase): """ @@ -95,15 +33,17 @@ class TestPortablePublicIPRange(cloudstackTestCase): """ @classmethod def setUpClass(cls): - cls.api_client = super(TestPortablePublicIPRange, cls).getClsTestClient().getApiClient() - cls.services = Services().services + testClient = super(TestPortablePublicIPRange, cls).getClsTestClient() + cls.apiclient = testClient.getApiClient() + cls.services = testClient.getParsedTestDataConfig() + # Get Zone, Domain - cls.domain = get_domain(cls.api_client, cls.services) - cls.zone = get_zone(cls.api_client, cls.services) + cls.domain = get_domain(cls.apiclient) + cls.zone = get_zone(cls.apiclient, cls.testClient.getZoneForTests()) # Create Account cls.account = Account.create( - cls.api_client, + cls.apiclient, cls.services["account"], domainid=cls.domain.id ) @@ -116,7 +56,7 @@ def setUpClass(cls): def tearDownClass(cls): try: # Cleanup resources used - cleanup_resources(cls.api_client, cls._cleanup) + cleanup_resources(cls.apiclient, cls._cleanup) except Exception as e: raise Exception("Warning: Exception during cleanup : %s" % e) return @@ -135,13 +75,13 @@ def tearDown(self): raise Exception("Warning: Exception during cleanup : %s" % e) return - @attr(tags = ["simulator", "basic", "advanced", "portablepublicip"]) + @attr(tags = ["simulator", "basic", "advanced", "portablepublicip", "selfservice"]) 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.apiclient, self.services ) self.debug("attempting to verify portable Public IP range is created") @@ -161,29 +101,31 @@ class TestPortablePublicIPAcquire(cloudstackTestCase): """ @classmethod def setUpClass(cls): - cls.api_client = super(TestPortablePublicIPAcquire, cls).getClsTestClient().getApiClient() - cls.services = Services().services + testClient = super(TestPortablePublicIPAcquire, cls).getClsTestClient() + cls.apiclient = testClient.getApiClient() + cls.services = testClient.getParsedTestDataConfig() + # Get Zone, Domain - cls.domain = get_domain(cls.api_client, cls.services) - cls.zone = get_zone(cls.api_client, cls.services) + cls.domain = get_domain(cls.apiclient) + cls.zone = get_zone(cls.apiclient, cls.testClient.getZoneForTests()) # Create Account cls.account = Account.create( - cls.api_client, + cls.apiclient, cls.services["account"], domainid=cls.domain.id ) cls.services["network"]["zoneid"] = cls.zone.id cls.network_offering = NetworkOffering.create( - cls.api_client, + cls.apiclient, cls.services["network_offering"], ) # Enable Network offering - cls.network_offering.update(cls.api_client, state='Enabled') + cls.network_offering.update(cls.apiclient, state='Enabled') cls.services["network"]["networkoffering"] = cls.network_offering.id cls.account_network = Network.create( - cls.api_client, + cls.apiclient, cls.services["network"], cls.account.name, cls.account.domainid @@ -200,7 +142,7 @@ def setUpClass(cls): def tearDownClass(cls): try: # Cleanup resources used - cleanup_resources(cls.api_client, cls._cleanup) + cleanup_resources(cls.apiclient, cls._cleanup) except Exception as e: raise Exception("Warning: Exception during cleanup : %s" % e) return @@ -219,19 +161,19 @@ def tearDown(self): raise Exception("Warning: Exception during cleanup : %s" % e) return - @attr(tags = ["simulator", "advanced", "portablepublicip"]) + @attr(tags = ["simulator", "advanced", "portablepublicip", "selfservice"]) 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.apiclient, self.services ) - ip_address = PublicIPAddress.create(self.api_client, self.account.name, + ip_address = PublicIPAddress.create(self.apiclient, self.account.name, self.zone.id, self.account.domainid, isportable=True) - ip_address.delete(self.api_client) + ip_address.delete(self.apiclient) self.portable_ip_range.delete(self.apiclient) return diff --git a/test/integration/smoke/test_primary_storage.py b/test/integration/smoke/test_primary_storage.py index 5cf31b13d8..3147d86645 100644 --- a/test/integration/smoke/test_primary_storage.py +++ b/test/integration/smoke/test_primary_storage.py @@ -20,43 +20,24 @@ import marvin 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.lib.utils import * +from marvin.lib.base import * +from marvin.lib.common import * from nose.plugins.attrib import attr #Import System modules import time _multiprocess_shared_ = True -class Services: - """Test Primary storage Services - """ - - def __init__(self): - self.services = { - "nfs": - { - "url": "nfs://10.147.28.7/export/home/talluri/testprimary", - # Format: File_System_Type/Location/Path - "name": "Primary XEN" - }, - "iscsi": { - "url": "iscsi://192.168.100.21/iqn.2012-01.localdomain.clo-cstack-cos6:iser/1", - # Format : iscsi://IP Address/IQN number/LUN# - "name": "Primary iSCSI" - } - } - class TestPrimaryStorageServices(cloudstackTestCase): def setUp(self): self.apiclient = self.testClient.getApiClient() - self.services = Services().services + self.services = self.testClient.getParsedTestDataConfig() self.cleanup = [] # Get Zone and pod - self.zone = get_zone(self.apiclient, self.services) + self.zone = get_zone(self.apiclient, self.testClient.getZoneForTests()) self.pod = get_pod(self.apiclient, self.zone.id) return @@ -70,7 +51,7 @@ def tearDown(self): raise Exception("Warning: Exception during cleanup : %s" % e) return - @attr(tags = ["advanced", "advancedns", "smoke", "basic", "sg"]) + @attr(tags = ["advanced", "advancedns", "smoke", "basic", "sg", "selfservice"]) def test_01_primary_storage_nfs(self): """Test primary storage pools - XEN, KVM, VMWare """ @@ -163,7 +144,7 @@ def test_01_primary_storage_nfs(self): return - @attr(tags = ["advanced", "advancedns", "smoke", "basic", "sg"]) + @attr(tags = ["advanced", "advancedns", "smoke", "basic", "sg", "selfservice"]) def test_01_primary_storage_iscsi(self): """Test primary storage pools - XEN, KVM, VMWare """ @@ -218,7 +199,7 @@ def test_01_primary_storage_iscsi(self): self.assertEqual( storage.type, - 'NetworkFilesystem', + 'IscsiLUN', "Check storage pool type " ) diff --git a/test/integration/smoke/test_privategw_acl.py b/test/integration/smoke/test_privategw_acl.py index 9c37e5e7fc..c86beb1ecf 100644 --- a/test/integration/smoke/test_privategw_acl.py +++ b/test/integration/smoke/test_privategw_acl.py @@ -19,9 +19,9 @@ #Import Local Modules 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.lib.utils import * +from marvin.lib.base import * +from marvin.lib.common import * from nose.plugins.attrib import attr @@ -39,8 +39,9 @@ def setUp(self): self.privateGwId = None - @attr(tags=["advanced"]) + @attr(tags=["advanced", "selfservice"]) def test_privategw_acl(self): + #TODO: SIMENH: add a new test to verification of ACL rules # 1) Create VPC self.createVPC() @@ -104,25 +105,7 @@ def createNetwork(self): self.assertIsNotNone(createNetworkResponse.id, "Network failed to create") self.networkId = createNetworkResponse.id - def deployVm(self): - deployVirtualMachineCmd = deployVirtualMachine.deployVirtualMachineCmd() - deployVirtualMachineCmd.networkids = self.networkId - deployVirtualMachineCmd.serviceofferingid = self.serviceOfferingId - deployVirtualMachineCmd.zoneid = self.zoneId - deployVirtualMachineCmd.templateid = self.templateId - deployVirtualMachineCmd.hypervisor = "XenServer" - deployVMResponse = self.apiClient.deployVirtualMachine(deployVirtualMachineCmd) - - def deployVm(self): - deployVirtualMachineCmd = deployVirtualMachine.deployVirtualMachineCmd() - deployVirtualMachineCmd.networkids = TestNetworkACL.networkId - deployVirtualMachineCmd.serviceofferingid = TestNetworkACL.serviceOfferingId - deployVirtualMachineCmd.zoneid = TestNetworkACL.zoneId - deployVirtualMachineCmd.templateid = TestNetworkACL.templateId - deployVirtualMachineCmd.hypervisor = "XenServer" - deployVMResponse = self.apiClient.deployVirtualMachine(deployVirtualMachineCmd) - TestNetworkACL.vmId = deployVMResponse.id - self.vmId = deployVMResponse.id + def createPvtGw(self): createPrivateGatewayCmd = createPrivateGateway.createPrivateGatewayCmd() @@ -145,7 +128,4 @@ def replaceacl(self): def tearDown(self): #destroy the vm - if self.vmId is not None: - destroyVirtualMachineCmd = destroyVirtualMachine.destroyVirtualMachineCmd() - destroyVirtualMachineCmd.id = self.vmId - destroyVirtualMachineResponse = self.apiClient.destroyVirtualMachine(destroyVirtualMachineCmd) + return diff --git a/test/integration/smoke/test_public_ip_range.py b/test/integration/smoke/test_public_ip_range.py index e1d78d99d1..b961dc3477 100644 --- a/test/integration/smoke/test_public_ip_range.py +++ b/test/integration/smoke/test_public_ip_range.py @@ -21,50 +21,26 @@ 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.lib.utils import * +from marvin.lib.base import * +from marvin.lib.common import * import datetime -class Services: - """Test Dedicating Public IP addresses - """ - - def __init__(self): - self.services = { - "domain": { - "name": "Domain", - }, - "account": { - "email": "test@test.com", - "firstname": "Test", - "lastname": "User", - "username": "test", - "password": "password", - }, - "gateway": "10.102.197.1", - "netmask": "255.255.255.0", - "forvirtualnetwork": "true", - "startip": "10.102.197.70", - "endip": "10.102.197.73", - "zoneid": "1", - "podid": "", - "vlan": "4444", - } - class TestDedicatePublicIPRange(cloudstackTestCase): @classmethod def setUpClass(cls): - cls.api_client = super(TestDedicatePublicIPRange, cls).getClsTestClient().getApiClient() - cls.services = Services().services + cls.testClient = super(TestDedicatePublicIPRange, cls).getClsTestClient() + cls.apiclient = cls.testClient.getApiClient() + cls.services = cls.testClient.getParsedTestDataConfig() # Get Zone, Domain - cls.domain = get_domain(cls.api_client, cls.services) - cls.zone = get_zone(cls.api_client, cls.services) - + cls.domain = get_domain(cls.apiclient) + cls.zone = get_zone(cls.apiclient, cls.testClient.getZoneForTests()) + cls.services["zoneid"] = cls.zone.id + cls.pod = get_pod(cls.apiclient, cls.zone.id) # Create Account cls.account = Account.create( - cls.api_client, + cls.apiclient, cls.services["account"], domainid=cls.domain.id ) @@ -77,7 +53,7 @@ def setUpClass(cls): def tearDownClass(cls): try: # Cleanup resources used - cleanup_resources(cls.api_client, cls._cleanup) + cleanup_resources(cls.apiclient, cls._cleanup) except Exception as e: raise Exception("Warning: Exception during cleanup : %s" % e) return @@ -96,7 +72,7 @@ def tearDown(self): raise Exception("Warning: Exception during cleanup : %s" % e) return - @attr(tags = ["simulator", "advanced", "publiciprange", "dedicate", "release"]) + @attr(tags = ["simulator", "advanced", "publiciprange", "dedicate", "release", "selfservice"]) def test_dedicatePublicIpRange(self): """Test public IP range dedication """ @@ -112,7 +88,7 @@ def test_dedicatePublicIpRange(self): self.debug("Creating Public IP range") self.public_ip_range = PublicIpRange.create( - self.api_client, + self.apiclient, self.services ) list_public_ip_range_response = PublicIpRange.list( diff --git a/test/integration/smoke/test_pvlan.py b/test/integration/smoke/test_pvlan.py index aeb47f953c..9178e624c3 100644 --- a/test/integration/smoke/test_pvlan.py +++ b/test/integration/smoke/test_pvlan.py @@ -21,9 +21,9 @@ from marvin.cloudstackTestCase import * from marvin.cloudstackAPI import * from marvin.sshClient import SshClient -from marvin.integration.lib.utils import * -from marvin.integration.lib.base import * -from marvin.integration.lib.common import * +from marvin.lib.utils import * +from marvin.lib.base import * +from marvin.lib.common import * from nose.plugins.attrib import attr import telnetlib @@ -38,10 +38,14 @@ class TestPVLAN(cloudstackTestCase): vlan = 1234 isolatedpvlan = 567 - def setUp(self): - self.apiClient = self.testClient.getApiClient() + @classmethod + def setUpClass(cls): + cls.testClient = super(TestPVLAN, cls).getClsTestClient() + cls.apiClient = cls.testClient.getApiClient() + cls.zone = get_zone(cls.apiClient, cls.testClient.getZoneForTests()) + cls.zoneId = cls.zone.id - @attr(tags = ["advanced"]) + @attr(tags = ["advanced", "selfservice"]) def test_create_pvlan_network(self): self.debug("Test create pvlan network") createNetworkCmd = createNetwork.createNetworkCmd() @@ -76,12 +80,6 @@ def test_create_pvlan_network(self): createNetworkCmd.ip6cidr="fc00:1234::/64" createNetworkCmd.startipv6="fc00:1234::10" createNetworkCmd.endipv6="fc00:1234::20" - err = 0; - try: - createNetworkResponse = self.apiClient.createNetwork(createNetworkCmd) - except Exception as e: - err = 1; - self.debug("Try alloc with ipv6, got:%s" % e) - self.assertEqual(err, 1, "Shouldn't allow create PVLAN network with IPv6"); - - + err = 0 + with self.assertRaises(Exception): + self.apiClient.createNetwork(createNetworkCmd) diff --git a/test/integration/smoke/test_regions.py b/test/integration/smoke/test_regions.py index 5d12e74e8d..389f878756 100644 --- a/test/integration/smoke/test_regions.py +++ b/test/integration/smoke/test_regions.py @@ -17,42 +17,33 @@ 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.lib.utils import * +from marvin.lib.base import * +from marvin.lib.common import * from nose.plugins.attrib import attr -class Services: - def __init__(self): - self.services = { - "region": { - "regionid": "2", - "regionname": "Region2", - "regionendpoint": "http://region2:8080/client" - } - } - - class TestRegions(cloudstackTestCase): """Test Regions - basic region creation """ @classmethod def setUpClass(cls): - cls.api_client = super(TestRegions, cls).getClsTestClient().getApiClient() - cls.services = Services().services - cls.domain = get_domain(cls.api_client, cls.services) + testClient = super(TestRegions, cls).getClsTestClient() + cls.apiclient = testClient.getApiClient() + cls.services = testClient.getParsedTestDataConfig() + + cls.domain = get_domain(cls.apiclient) cls.cleanup = [] - @attr(tags=["simulator", "basic", "advanced"]) + @attr(tags=["simulator", "basic", "advanced", "selfservice"]) def test_createRegion(self): """ Test for create region """ - region = Region.create(self.api_client, + region = Region.create(self.apiclient, self.services["region"] ) - list_region = Region.list(self.api_client, + list_region = Region.list(self.apiclient, id=self.services["region"]["regionid"] ) @@ -86,8 +77,8 @@ def test_createRegion(self): def tearDownClass(cls): try: #Clean up - cleanup_resources(cls.api_client, cls.cleanup) - list_region = Region.list(cls.api_client, id=cls.services["region"]["regionid"]) + cleanup_resources(cls.apiclient, cls.cleanup) + list_region = Region.list(cls.apiclient, id=cls.services["region"]["regionid"]) assert list_region is None, "Region deletion fails" except Exception as e: - raise Exception("Warning: Region cleanup/delete fails with : %s" % e) \ No newline at end of file + raise Exception("Warning: Region cleanup/delete fails with : %s" % e) diff --git a/test/integration/smoke/test_reset_vm_on_reboot.py b/test/integration/smoke/test_reset_vm_on_reboot.py index 4e52f0fa8d..4709df4d09 100644 --- a/test/integration/smoke/test_reset_vm_on_reboot.py +++ b/test/integration/smoke/test_reset_vm_on_reboot.py @@ -18,106 +18,56 @@ """ #Import Local Modules import marvin +from marvin.codes import FAILED 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.lib.utils import * +from marvin.lib.base import * +from marvin.lib.common import * from nose.plugins.attrib import attr _multiprocess_shared_ = True -class Services: - """Test VM Life Cycle Services - """ - - def __init__(self): - self.services = { - - "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": - { - "small": - { - # Small service offering ID to for change VM - # service offering from medium to small - "name": "SmallInstance_volatile", - "displaytext": "SmallInstance_volatile", - "cpunumber": 1, - "cpuspeed": 100, - "memory": 256, - }, - }, - #Change this - "template": { - "displaytext": "xs", - "name": "xs", - "passwordenabled": False, - }, - "sleep": 60, - "timeout": 10, - #Migrate VM to hostid - "ostype": 'CentOS 5.3 (64-bit)', - # CentOS 5.3 (64-bit) - } - - class TestResetVmOnReboot(cloudstackTestCase): @classmethod def setUpClass(cls): - cls.api_client = super(TestResetVmOnReboot, cls).getClsTestClient().getApiClient() - cls.services = Services().services + testClient = super(TestResetVmOnReboot, cls).getClsTestClient() + cls.apiclient = testClient.getApiClient() + cls.services = testClient.getParsedTestDataConfig() # Get Zone, Domain and templates - domain = get_domain(cls.api_client, cls.services) - zone = get_zone(cls.api_client, cls.services) + domain = get_domain(cls.apiclient) + zone = get_zone(cls.apiclient, testClient.getZoneForTests()) cls.services['mode'] = zone.networktype template = get_template( - cls.api_client, + cls.apiclient, zone.id, cls.services["ostype"] ) + if template == FAILED: + assert False, "get_template() failed to return template with description %s" % cls.services["ostype"] + # Set Zones and disk offerings ?? cls.services["small"]["zoneid"] = zone.id cls.services["small"]["template"] = template.id # Create account, service offerings, vm. cls.account = Account.create( - cls.api_client, + cls.apiclient, cls.services["account"], domainid=domain.id ) cls.small_offering = ServiceOffering.create( - cls.api_client, + cls.apiclient, cls.services["service_offerings"]["small"], isvolatile="true" ) #create a virtual machine cls.virtual_machine = VirtualMachine.create( - cls.api_client, + cls.apiclient, cls.services["small"], accountid=cls.account.name, domainid=cls.account.domainid, @@ -131,8 +81,8 @@ def setUpClass(cls): @classmethod def tearDownClass(cls): - cls.api_client = super(TestResetVmOnReboot, cls).getClsTestClient().getApiClient() - cleanup_resources(cls.api_client, cls._cleanup) + cls.apiclient = super(TestResetVmOnReboot, cls).getClsTestClient().getApiClient() + cleanup_resources(cls.apiclient, cls._cleanup) return def setUp(self): @@ -146,8 +96,9 @@ def tearDown(self): return @attr(hypervisor="xenserver") - @attr(tags=["advanced", "basic"]) + @attr(tags=["advanced", "basic", "selfservice"]) def test_01_reset_vm_on_reboot(self): + #TODO: SIMENH: add new test to check volume contents """Test reset virtual machine on reboot """ # Validate the following diff --git a/test/integration/smoke/test_resource_detail.py b/test/integration/smoke/test_resource_detail.py index 00a7b5c417..7f4a6e7686 100644 --- a/test/integration/smoke/test_resource_detail.py +++ b/test/integration/smoke/test_resource_detail.py @@ -21,113 +21,46 @@ from marvin.cloudstackTestCase import * from marvin.cloudstackAPI import * from marvin.sshClient import SshClient -from marvin.integration.lib.utils import * -from marvin.integration.lib.base import * -from marvin.integration.lib.common import * +from marvin.lib.utils import * +from marvin.lib.base import * +from marvin.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 = { - - "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', - }, - "disk_offering": { - "displaytext": "Small", - "name": "Small", - "storagetype": "shared", - "disksize": 1 - }, - "service_offerings": - { - "small": - { - # Small service offering ID to for change VM - # service offering from medium to small - "name": "SmallInstance", - "displaytext": "SmallInstance", - "cpunumber": 1, - "cpuspeed": 100, - "memory": 256, - }, - "big": - { - # Big service offering ID to for change VM - "name": "BigInstance", - "displaytext": "BigInstance", - "cpunumber": 1, - "cpuspeed": 100, - "memory": 512, - } - }, - #Change this - "template": { - "displaytext": "xs", - "name": "xs", - "passwordenabled": False, - }, - "sleep": 60, - "timeout": 10, - #Migrate VM to hostid - "ostype": 'CentOS 5.6 (64-bit)', - # CentOS 5.3 (64-bit) - } class TestResourceDetail(cloudstackTestCase): @classmethod def setUpClass(cls): - cls.api_client = super(TestResourceDetail, cls).getClsTestClient().getApiClient() - cls.services = Services().services + testClient = super(TestResourceDetail, cls).getClsTestClient() + cls.apiclient = testClient.getApiClient() + cls.services = testClient.getParsedTestDataConfig() # Get Zone, Domain and templates - domain = get_domain(cls.api_client, cls.services) - zone = get_zone(cls.api_client, cls.services) + domain = get_domain(cls.apiclient) + zone = get_zone(cls.apiclient, testClient.getZoneForTests()) cls.services['mode'] = zone.networktype # Set Zones and disk offerings ?? # Create account, service offerings, vm. cls.account = Account.create( - cls.api_client, + cls.apiclient, cls.services["account"], domainid=domain.id ) cls.disk_offering = DiskOffering.create( - cls.api_client, + cls.apiclient, cls.services["disk_offering"] ) #create a volume cls.volume = Volume.create( - cls.api_client, + cls.apiclient, { "diskname" : "ndm"}, zoneid=zone.id, account=cls.account.name, @@ -142,8 +75,8 @@ def setUpClass(cls): @classmethod def tearDownClass(cls): - cls.api_client = super(TestResourceDetail, cls).getClsTestClient().getApiClient() - cleanup_resources(cls.api_client, cls._cleanup) + cls.apiclient = super(TestResourceDetail, cls).getClsTestClient().getApiClient() + cleanup_resources(cls.apiclient, cls._cleanup) return def setUp(self): @@ -156,7 +89,7 @@ def tearDown(self): cleanup_resources(self.apiclient, self.cleanup) return - @attr(tags = ["advanced", "xenserver"]) + @attr(tags = ["advanced", "xenserver", "selfservice"]) def test_01_updatevolumedetail(self): """Test volume detail """ @@ -175,7 +108,7 @@ def test_01_updatevolumedetail(self): listResourceDetailCmd = listResourceDetails.listResourceDetailsCmd() listResourceDetailCmd.resourceid = self.volume.id listResourceDetailCmd.resourcetype = "Volume" - listResourceDetailResponse = self.api_client.listResourceDetails(listResourceDetailCmd) + listResourceDetailResponse = self.apiclient.listResourceDetails(listResourceDetailCmd) self.assertEqual(listResourceDetailResponse, None, "Check if the list API \ returns an empty response") diff --git a/test/integration/smoke/test_routers.py b/test/integration/smoke/test_routers.py index 7d324136e8..f77a051c03 100644 --- a/test/integration/smoke/test_routers.py +++ b/test/integration/smoke/test_routers.py @@ -18,88 +18,55 @@ """ #Import Local Modules import marvin +from marvin.codes import FAILED from marvin.cloudstackTestCase import * from marvin.cloudstackAPI import * from marvin.sshClient import SshClient -from marvin.integration.lib.utils import * -from marvin.integration.lib.base import * -from marvin.integration.lib.common import * +from marvin.lib.utils import * +from marvin.lib.base import * +from marvin.lib.common import * from nose.plugins.attrib import attr #Import System modules import time _multiprocess_shared_ = True -class Services: - """Test router Services - """ - - def __init__(self): - self.services = { - "service_offering": { - "name": "Tiny Instance", - "displaytext": "Tiny Instance", - "cpunumber": 1, - "cpuspeed": 100, # in MHz - "memory": 128, # In MBs - }, - "virtual_machine": - { - "displayname": "Test VM", - "username": "root", - "password": "password", - "ssh_port": 22, - "hypervisor": 'XenServer', - "privateport": 22, - "publicport": 22, - "protocol": 'TCP', - }, - "account": { - "email": "test@test.com", - "firstname": "Test", - "lastname": "User", - "username": "testuser", - "password": "password", - }, - "ostype": "CentOS 5.3 (64-bit)", - "sleep": 60, - "timeout": 10, - } - class TestRouterServices(cloudstackTestCase): @classmethod def setUpClass(cls): - cls.api_client = super( - TestRouterServices, - cls - ).getClsTestClient().getApiClient() - cls.services = Services().services + testClient = super(TestRouterServices, cls).getClsTestClient() + cls.apiclient = testClient.getApiClient() + cls.services = testClient.getParsedTestDataConfig() + # Get Zone, Domain and templates - cls.domain = get_domain(cls.api_client, cls.services) - cls.zone = get_zone(cls.api_client, cls.services) + cls.domain = get_domain(cls.apiclient) + cls.zone = get_zone(cls.apiclient, testClient.getZoneForTests()) cls.services['mode'] = cls.zone.networktype template = get_template( - cls.api_client, + cls.apiclient, cls.zone.id, cls.services["ostype"] ) + if template == FAILED: + cls.fail("get_template() failed to return template with description %s" % cls.services["ostype"]) + cls.services["virtual_machine"]["zoneid"] = cls.zone.id #Create an account, network, VM and IP addresses cls.account = Account.create( - cls.api_client, + cls.apiclient, cls.services["account"], domainid=cls.domain.id ) cls.service_offering = ServiceOffering.create( - cls.api_client, - cls.services["service_offering"] + cls.apiclient, + cls.services["service_offerings"] ) cls.vm_1 = VirtualMachine.create( - cls.api_client, + cls.apiclient, cls.services["virtual_machine"], templateid=template.id, accountid=cls.account.name, @@ -115,12 +82,12 @@ def setUpClass(cls): @classmethod def tearDownClass(cls): try: - cls.api_client = super( + cls.apiclient = super( TestRouterServices, cls ).getClsTestClient().getApiClient() #Clean up, terminate the created templates - cleanup_resources(cls.api_client, cls.cleanup) + cleanup_resources(cls.apiclient, cls.cleanup) except Exception as e: raise Exception("Warning: Exception during cleanup : %s" % e) @@ -128,9 +95,10 @@ def tearDownClass(cls): def setUp(self): self.apiclient = self.testClient.getApiClient() + self.hypervisor = self.testClient.getHypervisorInfo() return - @attr(tags = ["advanced", "basic", "sg", "smoke"]) + @attr(tags = ["advanced", "basic", "sg", "smoke", "provisioning"]) def test_01_router_internal_basic(self): """Test router internal basic zone """ @@ -143,13 +111,14 @@ def test_01_router_internal_basic(self): if self.zone.networktype == "Basic": list_router_response = list_routers( self.apiclient, - listall="true" + listall=True ) else: list_router_response = list_routers( self.apiclient, account=self.account.name, - domainid=self.account.domainid + domainid=self.account.domainid, + listall=True ) self.assertEqual( isinstance(list_router_response, list), @@ -180,7 +149,7 @@ def test_01_router_internal_basic(self): "Check list router response for router state" ) - if self.apiclient.hypervisor.lower() == 'vmware': + if self.hypervisor.lower() == 'vmware': result = get_process_status( self.apiclient.connection.mgtSvr, 22, @@ -188,7 +157,7 @@ def test_01_router_internal_basic(self): self.apiclient.connection.passwd, router.linklocalip, "service dnsmasq status", - hypervisor=self.apiclient.hypervisor + hypervisor=self.hypervisor ) else: try: @@ -218,7 +187,7 @@ def test_01_router_internal_basic(self): - @attr(tags = ["advanced", "smoke"]) + @attr(tags = ["advanced", "smoke", "provisioning"]) def test_02_router_internal_adv(self): """Test router internal advanced zone """ @@ -231,7 +200,8 @@ def test_02_router_internal_adv(self): list_router_response = list_routers( self.apiclient, account=self.account.name, - domainid=self.account.domainid + domainid=self.account.domainid, + listall=True ) self.assertEqual( isinstance(list_router_response, list), @@ -262,7 +232,7 @@ def test_02_router_internal_adv(self): "Check list router response for router state" ) - if self.apiclient.hypervisor.lower() == 'vmware': + if self.hypervisor.lower() == 'vmware': result = get_process_status( self.apiclient.connection.mgtSvr, 22, @@ -270,7 +240,7 @@ def test_02_router_internal_adv(self): self.apiclient.connection.passwd, router.linklocalip, "service dnsmasq status", - hypervisor=self.apiclient.hypervisor + hypervisor=self.hypervisor ) else: try: @@ -294,7 +264,7 @@ def test_02_router_internal_adv(self): "Check dnsmasq service is running or not" ) - if self.apiclient.hypervisor.lower() == 'vmware': + if self.hypervisor.lower() == 'vmware': result = get_process_status( self.apiclient.connection.mgtSvr, 22, @@ -302,7 +272,7 @@ def test_02_router_internal_adv(self): self.apiclient.connection.passwd, router.linklocalip, "service haproxy status", - hypervisor=self.apiclient.hypervisor + hypervisor=self.hypervisor ) else: try: @@ -326,7 +296,7 @@ def test_02_router_internal_adv(self): self.debug("Haproxy process status: %s" % res) return - @attr(tags = ["advanced", "advancedns", "smoke"]) + @attr(tags = ["advanced", "advancedns", "smoke", "selfservice"]) def test_03_restart_network_cleanup(self): """Test restart network """ @@ -340,7 +310,8 @@ def test_03_restart_network_cleanup(self): list_router_response = list_routers( self.apiclient, account=self.account.name, - domainid=self.account.domainid + domainid=self.account.domainid, + listall=True ) self.assertEqual( isinstance(list_router_response, list), @@ -388,7 +359,8 @@ def test_03_restart_network_cleanup(self): list_router_response = list_routers( self.apiclient, account=self.account.name, - domainid=self.account.domainid + domainid=self.account.domainid, + listall=True ) self.assertEqual( isinstance(list_router_response, list), @@ -404,7 +376,7 @@ def test_03_restart_network_cleanup(self): ) return - @attr(tags = ["advanced", "advancedns", "smoke"]) + @attr(tags = ["advanced", "advancedns", "smoke", "provisioning"]) def test_04_restart_network_wo_cleanup(self): """Test restart network without cleanup """ @@ -450,7 +422,8 @@ def test_04_restart_network_wo_cleanup(self): list_router_response = list_routers( self.apiclient, account=self.account.name, - domainid=self.account.domainid + domainid=self.account.domainid, + listall=True ) self.assertEqual( isinstance(list_router_response, list), @@ -473,7 +446,7 @@ def test_04_restart_network_wo_cleanup(self): ) host = hosts[0] - if self.apiclient.hypervisor.lower() == 'vmware': + if self.hypervisor.lower() == 'vmware': res = get_process_status( self.apiclient.connection.mgtSvr, 22, @@ -481,7 +454,7 @@ def test_04_restart_network_wo_cleanup(self): self.apiclient.connection.passwd, router.linklocalip, "uptime", - hypervisor=self.apiclient.hypervisor + hypervisor=self.hypervisor ) else: try: @@ -520,7 +493,7 @@ def test_04_restart_network_wo_cleanup(self): ) return - @attr(tags = ["advanced", "advancedns", "smoke"]) + @attr(tags = ["advanced", "advancedns", "smoke", "selfservice"]) def test_05_router_basic(self): """Test router basic setup """ @@ -533,7 +506,8 @@ def test_05_router_basic(self): list_router_response = list_routers( self.apiclient, account=self.account.name, - domainid=self.account.domainid + domainid=self.account.domainid, + listall=True ) self.assertEqual( isinstance(list_router_response, list), @@ -586,7 +560,7 @@ def test_05_router_basic(self): ) return - @attr(tags = ["advanced", "advancedns", "smoke"]) + @attr(tags = ["advanced", "advancedns", "smoke", "selfservice"]) def test_06_router_advanced(self): """Test router advanced setup """ @@ -599,7 +573,8 @@ def test_06_router_advanced(self): list_router_response = list_routers( self.apiclient, account=self.account.name, - domainid=self.account.domainid + domainid=self.account.domainid, + listall=True ) self.assertEqual( isinstance(list_router_response, list), @@ -669,7 +644,7 @@ def test_06_router_advanced(self): ) return - @attr(tags = ["advanced", "advancedns", "smoke"]) + @attr(tags = ["advanced", "advancedns", "smoke", "selfservice"]) def test_07_stop_router(self): """Test stop router """ @@ -680,7 +655,8 @@ def test_07_stop_router(self): list_router_response = list_routers( self.apiclient, account=self.account.name, - domainid=self.account.domainid + domainid=self.account.domainid, + listall=True ) self.assertEqual( isinstance(list_router_response, list), @@ -698,7 +674,8 @@ def test_07_stop_router(self): #List routers to check state of router router_response = list_routers( self.apiclient, - id=router.id + id=router.id, + listall=True ) self.assertEqual( isinstance(router_response, list), @@ -713,7 +690,7 @@ def test_07_stop_router(self): ) return - @attr(tags = ["advanced", "advancedns", "smoke"]) + @attr(tags = ["advanced", "advancedns", "smoke", "selfservice"]) def test_08_start_router(self): """Test start router """ @@ -724,7 +701,8 @@ def test_08_start_router(self): list_router_response = list_routers( self.apiclient, account=self.account.name, - domainid=self.account.domainid + domainid=self.account.domainid, + listall=True ) self.assertEqual( isinstance(list_router_response, list), @@ -743,7 +721,8 @@ def test_08_start_router(self): #List routers to check state of router router_response = list_routers( self.apiclient, - id=router.id + id=router.id, + listall=True ) self.assertEqual( isinstance(router_response, list), @@ -758,7 +737,7 @@ def test_08_start_router(self): ) return - @attr(tags = ["advanced", "advancedns", "smoke"]) + @attr(tags = ["advanced", "advancedns", "smoke", "selfservice"]) def test_09_reboot_router(self): """Test reboot router """ @@ -769,7 +748,8 @@ def test_09_reboot_router(self): list_router_response = list_routers( self.apiclient, account=self.account.name, - domainid=self.account.domainid + domainid=self.account.domainid, + listall=True ) self.assertEqual( isinstance(list_router_response, list), @@ -790,7 +770,8 @@ def test_09_reboot_router(self): #List routers to check state of router router_response = list_routers( self.apiclient, - id=router.id + id=router.id, + listall=True ) self.assertEqual( isinstance(router_response, list), diff --git a/test/integration/smoke/test_scale_vm.py b/test/integration/smoke/test_scale_vm.py index 1d1726dc90..08f9ce5c81 100644 --- a/test/integration/smoke/test_scale_vm.py +++ b/test/integration/smoke/test_scale_vm.py @@ -18,119 +18,60 @@ """ #Import Local Modules import marvin +from marvin.codes import FAILED 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.lib.utils import * +from marvin.lib.base import * +from marvin.lib.common import * from nose.plugins.attrib import attr _multiprocess_shared_ = True -class Services: - """Test VM Life Cycle Services - """ - - def __init__(self): - self.services = { - - "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": - { - "small": - { - # Small service offering ID to for change VM - # service offering from medium to small - "name": "SmallInstance", - "displaytext": "SmallInstance", - "cpunumber": 1, - "cpuspeed": 100, - "memory": 256, - }, - "big": - { - # Big service offering ID to for change VM - "name": "BigInstance", - "displaytext": "BigInstance", - "cpunumber": 1, - "cpuspeed": 100, - "memory": 512, - } - }, - #Change this - "template": { - "displaytext": "xs", - "name": "xs", - "passwordenabled": False, - }, - "sleep": 60, - "timeout": 10, - #Migrate VM to hostid - "ostype": 'CentOS 5.3 (64-bit)', - # CentOS 5.3 (64-bit) - } - - class TestScaleVm(cloudstackTestCase): @classmethod def setUpClass(cls): - cls.api_client = super(TestScaleVm, cls).getClsTestClient().getApiClient() - cls.services = Services().services + testClient = super(TestScaleVm, cls).getClsTestClient() + cls.apiclient = testClient.getApiClient() + cls.services = testClient.getParsedTestDataConfig() # Get Zone, Domain and templates - domain = get_domain(cls.api_client, cls.services) - zone = get_zone(cls.api_client, cls.services) + domain = get_domain(cls.apiclient) + zone = get_zone(cls.apiclient, testClient.getZoneForTests()) cls.services['mode'] = zone.networktype template = get_template( - cls.api_client, + cls.apiclient, zone.id, cls.services["ostype"] ) + if template == FAILED: + assert False, "get_template() failed to return template with description %s" % cls.services["ostype"] + # Set Zones and disk offerings ?? cls.services["small"]["zoneid"] = zone.id cls.services["small"]["template"] = template.id # Create account, service offerings, vm. cls.account = Account.create( - cls.api_client, + cls.apiclient, cls.services["account"], domainid=domain.id ) cls.small_offering = ServiceOffering.create( - cls.api_client, + cls.apiclient, cls.services["service_offerings"]["small"] ) cls.big_offering = ServiceOffering.create( - cls.api_client, + cls.apiclient, cls.services["service_offerings"]["big"] ) #create a virtual machine cls.virtual_machine = VirtualMachine.create( - cls.api_client, + cls.apiclient, cls.services["small"], accountid=cls.account.name, domainid=cls.account.domainid, @@ -144,8 +85,8 @@ def setUpClass(cls): @classmethod def tearDownClass(cls): - cls.api_client = super(TestScaleVm, cls).getClsTestClient().getApiClient() - cleanup_resources(cls.api_client, cls._cleanup) + cls.apiclient = super(TestScaleVm, cls).getClsTestClient().getApiClient() + cleanup_resources(cls.apiclient, cls._cleanup) return def setUp(self): @@ -159,7 +100,7 @@ def tearDown(self): return @attr(hypervisor="xenserver") - @attr(tags=["advanced", "basic"]) + @attr(tags=["advanced", "basic", "provisioning"]) def test_01_scale_vm(self): """Test scale virtual machine """ diff --git a/test/integration/smoke/test_secondary_storage.py b/test/integration/smoke/test_secondary_storage.py index ff9692f9c8..90304b357c 100644 --- a/test/integration/smoke/test_secondary_storage.py +++ b/test/integration/smoke/test_secondary_storage.py @@ -20,9 +20,9 @@ import marvin 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.lib.utils import * +from marvin.lib.base import * +from marvin.lib.common import * from nose.plugins.attrib import attr #Import System modules @@ -33,7 +33,7 @@ class TestSecStorageServices(cloudstackTestCase): @classmethod def setUpClass(cls): - cls.api_client = super(TestSecStorageServices, cls).getClsTestClient().getApiClient() + cls.apiclient = super(TestSecStorageServices, cls).getClsTestClient().getApiClient() cls._cleanup = [] return @@ -41,7 +41,7 @@ def setUpClass(cls): def tearDownClass(cls): try: #Cleanup resources used - cleanup_resources(cls.api_client, cls._cleanup) + cleanup_resources(cls.apiclient, cls._cleanup) except Exception as e: raise Exception("Warning: Exception during cleanup : %s" % e) return @@ -81,7 +81,7 @@ def tearDown(self): raise Exception("Warning: Exception during cleanup : %s" % e) return - @attr(tags = ["advanced", "advancedns", "smoke", "basic", "eip", "sg"]) + @attr(tags = ["advanced", "advancedns", "smoke", "basic", "eip", "sg", "selfservice"]) def test_01_sys_vm_start(self): """Test system VM start """ @@ -160,7 +160,7 @@ def test_01_sys_vm_start(self): ) return - @attr(tags = ["advanced", "advancedns", "smoke", "basic", "eip", "sg"]) + @attr(tags = ["advanced", "advancedns", "smoke", "basic", "eip", "sg", "selfservice"]) def test_02_sys_template_ready(self): """Test system templates are ready """ @@ -187,6 +187,8 @@ def test_02_sys_template_ready(self): listall=True, account='system' ) + self.assertEqual(validateList(list_template_response)[0], PASS,\ + "templates list validation failed") # Ensure all BUILTIN templates are downloaded templateid = None diff --git a/test/integration/smoke/test_service_offerings.py b/test/integration/smoke/test_service_offerings.py index 968dc5622f..980e11017b 100644 --- a/test/integration/smoke/test_service_offerings.py +++ b/test/integration/smoke/test_service_offerings.py @@ -17,15 +17,16 @@ """ BVT tests for Service offerings""" #Import Local Modules +from marvin.codes import FAILED from marvin.cloudstackTestCase import cloudstackTestCase from marvin.cloudstackAPI import changeServiceForVirtualMachine,updateServiceOffering -from marvin.integration.lib.utils import (isAlmostEqual, +from marvin.lib.utils import (isAlmostEqual, cleanup_resources, random_gen) -from marvin.integration.lib.base import (ServiceOffering, +from marvin.lib.base import (ServiceOffering, Account, VirtualMachine) -from marvin.integration.lib.common import (list_service_offering, +from marvin.lib.common import (list_service_offering, list_virtual_machines, get_domain, get_zone, @@ -35,93 +36,13 @@ _multiprocess_shared_ = True -class Services: - """Test Service offerings Services - """ - - def __init__(self): - self.services = { - "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", - }, - "off": - { - "name": "Service Offering", - "displaytext": "Service Offering", - "cpunumber": 1, - "cpuspeed": 100, # MHz - "memory": 128, # in MBs - }, - "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', - }, - "medium": # Create a medium virtual machine instance - { - "displayname": "testserver", - "username": "root", - "password": "password", - "ssh_port": 22, - "hypervisor": 'XenServer', - "privateport": 22, - "publicport": 22, - "protocol": 'TCP', - }, - "service_offerings": - { - "tiny": - { - "name": "Tiny Instance", - "displaytext": "Tiny Instance", - "cpunumber": 1, - "cpuspeed": 100, # in MHz - "memory": 128, # In MBs - }, - "small": - { - # Small service offering ID to for change VM - # service offering from medium to small - "name": "Small Instance", - "displaytext": "Small Instance", - "cpunumber": 1, - "cpuspeed": 100, - "memory": 128, - }, - "medium": - { - # Medium service offering ID to for - # change VM service offering from small to medium - "name": "Medium Instance", - "displaytext": "Medium Instance", - "cpunumber": 1, - "cpuspeed": 100, - "memory": 256, - } - }, - "ostype": 'CentOS 5.3 (64-bit)', - } - class TestCreateServiceOffering(cloudstackTestCase): def setUp(self): self.apiclient = self.testClient.getApiClient() self.dbclient = self.testClient.getDbConnection() self.cleanup = [] - self.services = Services().services + self.services = self.testClient.getParsedTestDataConfig() def tearDown(self): try: @@ -133,7 +54,7 @@ def tearDown(self): return - @attr(tags=["advanced", "advancedns", "smoke", "basic", "eip", "sg"]) + @attr(tags=["advanced", "advancedns", "smoke", "basic", "eip", "sg", "selfservice"]) def test_01_create_service_offering(self): """Test to create service offering""" @@ -143,7 +64,7 @@ def test_01_create_service_offering(self): service_offering = ServiceOffering.create( self.apiclient, - self.services["off"] + self.services["service_offerings"] ) self.cleanup.append(service_offering) @@ -164,31 +85,30 @@ def test_01_create_service_offering(self): 0, "Check Service offering is created" ) - service_response = list_service_response[0] self.assertEqual( list_service_response[0].cpunumber, - self.services["off"]["cpunumber"], + self.services["service_offerings"]["cpunumber"], "Check server id in createServiceOffering" ) self.assertEqual( list_service_response[0].cpuspeed, - self.services["off"]["cpuspeed"], + self.services["service_offerings"]["cpuspeed"], "Check cpuspeed in createServiceOffering" ) self.assertEqual( list_service_response[0].displaytext, - self.services["off"]["displaytext"], + self.services["service_offerings"]["displaytext"], "Check server displaytext in createServiceOfferings" ) self.assertEqual( list_service_response[0].memory, - self.services["off"]["memory"], + self.services["service_offerings"]["memory"], "Check memory in createServiceOffering" ) self.assertEqual( list_service_response[0].name, - self.services["off"]["name"], + self.services["service_offerings"]["name"], "Check name in createServiceOffering" ) return @@ -212,25 +132,30 @@ def tearDown(self): @classmethod def setUpClass(cls): - cls.api_client = super(TestServiceOfferings, cls).getClsTestClient().getApiClient() - cls.services = Services().services - domain = get_domain(cls.api_client, cls.services) - cls.zone = get_zone(cls.api_client, cls.services) + testClient = super(TestServiceOfferings, cls).getClsTestClient() + cls.apiclient = testClient.getApiClient() + cls.services = testClient.getParsedTestDataConfig() + + domain = get_domain(cls.apiclient) + cls.zone = get_zone(cls.apiclient, testClient.getZoneForTests()) cls.services['mode'] = cls.zone.networktype cls.service_offering_1 = ServiceOffering.create( - cls.api_client, - cls.services["off"] + cls.apiclient, + cls.services["service_offerings"] ) cls.service_offering_2 = ServiceOffering.create( - cls.api_client, - cls.services["off"] + cls.apiclient, + cls.services["service_offerings"] ) template = get_template( - cls.api_client, + cls.apiclient, cls.zone.id, cls.services["ostype"] ) + if template == FAILED: + assert False, "get_template() failed to return template with description %s" % cls.services["ostype"] + # Set Zones and disk offerings cls.services["small"]["zoneid"] = cls.zone.id cls.services["small"]["template"] = template.id @@ -240,22 +165,22 @@ def setUpClass(cls): # Create VMs, NAT Rules etc cls.account = Account.create( - cls.api_client, + cls.apiclient, cls.services["account"], domainid=domain.id ) cls.small_offering = ServiceOffering.create( - cls.api_client, + cls.apiclient, cls.services["service_offerings"]["small"] ) cls.medium_offering = ServiceOffering.create( - cls.api_client, + cls.apiclient, cls.services["service_offerings"]["medium"] ) cls.medium_virtual_machine = VirtualMachine.create( - cls.api_client, + cls.apiclient, cls.services["medium"], accountid=cls.account.name, domainid=cls.account.domainid, @@ -272,15 +197,15 @@ def setUpClass(cls): @classmethod def tearDownClass(cls): try: - cls.api_client = super(TestServiceOfferings, cls).getClsTestClient().getApiClient() + cls.apiclient = super(TestServiceOfferings, cls).getClsTestClient().getApiClient() #Clean up, terminate the created templates - cleanup_resources(cls.api_client, cls._cleanup) + cleanup_resources(cls.apiclient, cls._cleanup) except Exception as e: raise Exception("Warning: Exception during cleanup : %s" % e) return - @attr(tags=["advanced", "advancedns", "smoke", "basic", "eip", "sg"]) + @attr(tags=["advanced", "advancedns", "smoke", "basic", "eip", "sg", "selfservice"]) def test_02_edit_service_offering(self): """Test to update existing service offering""" @@ -331,7 +256,7 @@ def test_02_edit_service_offering(self): return - @attr(tags=["advanced", "advancedns", "smoke", "basic", "eip", "sg"]) + @attr(tags=["advanced", "advancedns", "smoke", "basic", "eip", "sg", "selfservice"]) def test_03_delete_service_offering(self): """Test to delete service offering""" @@ -357,7 +282,7 @@ def test_03_delete_service_offering(self): return - @attr(tags=["advanced", "advancedns", "smoke"]) + @attr(tags=["advanced", "advancedns", "smoke", "provisioning"]) def test_04_change_offering_small(self): """Test to change service to a small capacity """ @@ -367,23 +292,10 @@ def test_04_change_offering_small(self): # 2. Using listVM command verify that this Vm # has Small service offering Id. - self.debug("Stopping VM - ID: %s" % self.medium_virtual_machine.id) - self.medium_virtual_machine.stop(self.apiclient) - # Ensure that VM is in stopped state - list_vm_response = list_virtual_machines( - self.apiclient, - id=self.medium_virtual_machine.id - ) - if isinstance(list_vm_response, list): - vm = list_vm_response[0] - if vm.state == 'Stopped': - self.debug("VM state: %s" % vm.state) - else: - raise Exception( - "Failed to stop VM (ID: %s) in change service offering" % vm.id) - - self.debug("Change Service offering VM - ID: %s" % - self.medium_virtual_machine.id) + try: + self.medium_virtual_machine.stop(self.apiclient) + except Exception as e: + self.fail("Failed to stop VM: %s" % e) cmd = changeServiceForVirtualMachine.changeServiceForVirtualMachineCmd() cmd.id = self.medium_virtual_machine.id diff --git a/test/integration/smoke/test_snapshots.py b/test/integration/smoke/test_snapshots.py index 6ee7c6271c..a960e7095b 100644 --- a/test/integration/smoke/test_snapshots.py +++ b/test/integration/smoke/test_snapshots.py @@ -15,129 +15,35 @@ # specific language governing permissions and limitations # under the License. +from marvin.codes import FAILED 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 - }, - "disk_offering": { - "displaytext": "Small Disk", - "name": "Small Disk", - "disksize": 1 - }, - "server_with_disk": - { - "displayname": "Test VM -With Disk", - "username": "root", - "password": "password", - "ssh_port": 22, - "hypervisor": 'XenServer', - "privateport": 22, - "publicport": 22, - "protocol": 'TCP', - }, - - "server_without_disk": - { - "displayname": "Test VM-No Disk", - "username": "root", - "password": "password", - "ssh_port": 22, - "hypervisor": 'XenServer', - "privateport": 22, - # For NAT rule creation - "publicport": 22, - "protocol": 'TCP', - }, - "server": { - "displayname": "TestVM", - "username": "root", - "password": "password", - "ssh_port": 22, - "hypervisor": 'XenServer', - "privateport": 22, - "publicport": 22, - "protocol": 'TCP', - }, - "mgmt_server": { - "ipaddress": '192.168.100.21', - "username": "root", - "password": "password", - "port": 22, - }, - "recurring_snapshot": { - "intervaltype": 'HOURLY', - # Frequency of snapshots - "maxsnaps": 1, # Should be min 2 - "schedule": 1, - "timezone": 'US/Arizona', - # Timezone Formats - http://cloud.mindtouch.us/CloudStack_Documentation/Developer's_Guide%3A_CloudStack - }, - "templates": { - "displaytext": 'Template', - "name": 'Template', - "ostype": "CentOS 5.3 (64-bit)", - "templatefilter": 'self', - }, - "volume": { - "diskname": "APP Data Volume", - "size": 1, # in GBs - "diskdevice": ['/dev/xvdb', '/dev/sdb', '/dev/hdb', '/dev/vdb' ], # Data Disk - }, - "paths": { - "mount_dir": "/mnt/tmp", - "sub_dir": "test", - "sub_lvl_dir1": "test1", - "sub_lvl_dir2": "test2", - "random_data": "random.data", - }, - "ostype": "CentOS 5.3 (64-bit)", - # Cent OS 5.3 (64 bit) - "sleep": 60, - "timeout": 10, - } - +from marvin.lib.utils import * +from marvin.lib.base import * +from marvin.lib.common import * class TestSnapshotRootDisk(cloudstackTestCase): @classmethod def setUpClass(cls): - cls.api_client = super(TestSnapshotRootDisk, cls).getClsTestClient().getApiClient() - cls.services = Services().services + testClient = super(TestSnapshotRootDisk, cls).getClsTestClient() + cls.apiclient = testClient.getApiClient() + cls.services = testClient.getParsedTestDataConfig() + # Get Zone, Domain and templates - cls.domain = get_domain(cls.api_client, cls.services) - cls.zone = get_zone(cls.api_client, cls.services) + cls.domain = get_domain(cls.apiclient) + cls.zone = get_zone(cls.apiclient, testClient.getZoneForTests()) cls.services['mode'] = cls.zone.networktype template = get_template( - cls.api_client, + cls.apiclient, cls.zone.id, cls.services["ostype"] ) + if template == FAILED: + assert False, "get_template() failed to return template with description %s" % cls.services["ostype"] + cls.services["domainid"] = cls.domain.id cls.services["server_without_disk"]["zoneid"] = cls.zone.id cls.services["templates"]["ostypeid"] = template.ostypeid @@ -145,20 +51,17 @@ def setUpClass(cls): # Create VMs, NAT Rules etc cls.account = Account.create( - cls.api_client, + cls.apiclient, 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.apiclient, + cls.services["service_offerings"] ) cls.virtual_machine = cls.virtual_machine_with_disk = \ VirtualMachine.create( - cls.api_client, + cls.apiclient, cls.services["server_without_disk"], templateid=template.id, accountid=cls.account.name, @@ -176,7 +79,7 @@ def setUpClass(cls): def tearDownClass(cls): try: #Cleanup resources used - cleanup_resources(cls.api_client, cls._cleanup) + cleanup_resources(cls.apiclient, cls._cleanup) except Exception as e: raise Exception("Warning: Exception during cleanup : %s" % e) return @@ -196,7 +99,7 @@ def tearDown(self): return @attr(speed = "slow") - @attr(tags = ["advanced", "advancedns", "smoke"]) + @attr(tags = ["advanced", "advancedns", "smoke", "provisioning"]) def test_01_snapshot_root_disk(self): """Test Snapshot Root Disk """ diff --git a/test/integration/smoke/test_ssvm.py b/test/integration/smoke/test_ssvm.py index a2b9eabc13..ffa620b2db 100644 --- a/test/integration/smoke/test_ssvm.py +++ b/test/integration/smoke/test_ssvm.py @@ -21,9 +21,9 @@ from marvin.cloudstackTestCase import * from marvin.cloudstackAPI import * from marvin.sshClient import SshClient -from marvin.integration.lib.utils import * -from marvin.integration.lib.base import * -from marvin.integration.lib.common import * +from marvin.lib.utils import * +from marvin.lib.base import * +from marvin.lib.common import * from nose.plugins.attrib import attr import telnetlib @@ -31,24 +31,14 @@ import time _multiprocess_shared_ = True -class Services: - """Test SSVM Services - """ - - def __init__(self): - self.services = { - "sleep": 60, - "timeout": 10, - } - class TestSSVMs(cloudstackTestCase): def setUp(self): - self.apiclient = self.testClient.getApiClient() + self.hypervisor = self.testClient.getHypervisorInfo() self.cleanup = [] - self.services = Services().services - self.zone = get_zone(self.apiclient, self.services) + self.services = self.testClient.getParsedTestDataConfig() + self.zone = get_zone(self.apiclient, self.testClient.getZoneForTests()) return def tearDown(self): @@ -60,7 +50,7 @@ def tearDown(self): raise Exception("Warning: Exception during cleanup : %s" % e) return - @attr(tags = ["advanced", "advancedns", "smoke", "basic", "sg"]) + @attr(tags = ["advanced", "advancedns", "smoke", "basic", "sg", "selfservice"]) def test_01_list_sec_storage_vm(self): """Test List secondary storage VMs """ @@ -178,7 +168,7 @@ def test_01_list_sec_storage_vm(self): ) return - @attr(tags = ["advanced", "advancedns", "smoke", "basic", "sg"]) + @attr(tags = ["advanced", "advancedns", "smoke", "basic", "sg", "selfservice"]) def test_02_list_cpvm_vm(self): """Test List console proxy VMs """ @@ -290,7 +280,7 @@ def test_02_list_cpvm_vm(self): ) return - @attr(tags = ["advanced", "advancedns", "smoke", "basic", "sg"]) + @attr(tags = ["advanced", "advancedns", "smoke", "basic", "sg", "provisioning"]) def test_03_ssvm_internals(self): """Test SSVM Internals""" @@ -329,7 +319,7 @@ def test_03_ssvm_internals(self): self.debug("Running SSVM check script") - if self.apiclient.hypervisor.lower() == 'vmware': + if self.hypervisor.lower() == 'vmware': #SSH into SSVMs is done via management server for Vmware result = get_process_status( self.apiclient.connection.mgtSvr, @@ -338,7 +328,7 @@ def test_03_ssvm_internals(self): self.apiclient.connection.passwd, ssvm.privateip, "/usr/local/cloud/systemvm/ssvm-check.sh |grep -e ERROR -e WARNING -e FAIL", - hypervisor=self.apiclient.hypervisor + hypervisor=self.hypervisor ) else: try: @@ -369,7 +359,7 @@ def test_03_ssvm_internals(self): ) #Check status of cloud service - if self.apiclient.hypervisor.lower() == 'vmware': + if self.hypervisor.lower() == 'vmware': #SSH into SSVMs is done via management server for Vmware result = get_process_status( self.apiclient.connection.mgtSvr, @@ -378,7 +368,7 @@ def test_03_ssvm_internals(self): self.apiclient.connection.passwd, ssvm.privateip, "service cloud status", - hypervisor=self.apiclient.hypervisor + hypervisor=self.hypervisor ) else: try: @@ -403,7 +393,7 @@ def test_03_ssvm_internals(self): ) return - @attr(tags = ["advanced", "advancedns", "smoke", "basic", "sg"]) + @attr(tags = ["advanced", "advancedns", "smoke", "basic", "sg", "provisioning"]) def test_04_cpvm_internals(self): """Test CPVM Internals""" @@ -453,7 +443,7 @@ def test_04_cpvm_internals(self): self.debug("Checking cloud process status") - if self.apiclient.hypervisor.lower() == 'vmware': + if self.hypervisor.lower() == 'vmware': #SSH into SSVMs is done via management server for vmware result = get_process_status( self.apiclient.connection.mgtSvr, @@ -462,7 +452,7 @@ def test_04_cpvm_internals(self): self.apiclient.connection.passwd, cpvm.privateip, "service cloud status", - hypervisor=self.apiclient.hypervisor + hypervisor=self.hypervisor ) else: try: @@ -486,7 +476,7 @@ def test_04_cpvm_internals(self): ) return - @attr(tags = ["advanced", "advancedns", "smoke", "basic", "sg"]) + @attr(tags = ["advanced", "advancedns", "smoke", "basic", "sg", "provisioning"]) def test_05_stop_ssvm(self): """Test stop SSVM """ @@ -562,7 +552,7 @@ def test_05_stop_ssvm(self): self.test_03_ssvm_internals() return - @attr(tags = ["advanced", "advancedns", "smoke", "basic", "sg"]) + @attr(tags = ["advanced", "advancedns", "smoke", "basic", "sg", "provisioning"]) def test_06_stop_cpvm(self): """Test stop CPVM """ @@ -635,7 +625,7 @@ def test_06_stop_cpvm(self): self.test_04_cpvm_internals() return - @attr(tags = ["advanced", "advancedns", "smoke", "basic", "sg"]) + @attr(tags = ["advanced", "advancedns", "smoke", "basic", "sg", "provisioning"]) def test_07_reboot_ssvm(self): """Test reboot SSVM """ @@ -721,7 +711,7 @@ def test_07_reboot_ssvm(self): self.test_03_ssvm_internals() return - @attr(tags = ["advanced", "advancedns", "smoke", "basic", "sg"]) + @attr(tags = ["advanced", "advancedns", "smoke", "basic", "sg", "provisioning"]) def test_08_reboot_cpvm(self): """Test reboot CPVM """ @@ -808,7 +798,7 @@ def test_08_reboot_cpvm(self): self.test_04_cpvm_internals() return - @attr(tags = ["advanced", "advancedns", "smoke", "basic", "sg"]) + @attr(tags = ["advanced", "advancedns", "smoke", "basic", "sg", "provisioning"]) def test_09_destroy_ssvm(self): """Test destroy SSVM """ @@ -890,7 +880,7 @@ def test_09_destroy_ssvm(self): self.test_03_ssvm_internals() return - @attr(tags = ["advanced", "advancedns", "smoke", "basic", "sg"]) + @attr(tags = ["advanced", "advancedns", "smoke", "basic", "sg", "provisioning"]) def test_10_destroy_cpvm(self): """Test destroy CPVM """ diff --git a/test/integration/smoke/test_templates.py b/test/integration/smoke/test_templates.py index e371ad436a..c7594bb85d 100644 --- a/test/integration/smoke/test_templates.py +++ b/test/integration/smoke/test_templates.py @@ -5,9 +5,9 @@ # 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 @@ -17,87 +17,31 @@ """ BVT tests for Templates ISO """ #Import Local Modules -import marvin -from marvin.cloudstackTestCase import * -from marvin.cloudstackAPI import * -from marvin.sshClient import SshClient -from marvin.integration.lib.utils import * -from marvin.integration.lib.base import * -from marvin.integration.lib.common import * +from marvin.codes import FAILED +from marvin.cloudstackTestCase import cloudstackTestCase, unittest +from marvin.cloudstackAPI import (updateTemplate, + extractTemplate, + listZones, + updateTemplatePermissions, + deleteTemplate, + copyTemplate) +from marvin.lib.utils import random_gen, cleanup_resources +from marvin.lib.base import (Account, + ServiceOffering, + VirtualMachine, + DiskOffering, + Template, + Volume) +from marvin.lib.common import (get_domain, + get_zone, + get_template) from nose.plugins.attrib import attr import urllib -from random import random #Import System modules -import datetime +import time _multiprocess_shared_ = True -class Services: - """Test Templates 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": 100, # in MHz - "memory": 128, # In MBs - }, - "disk_offering": { - "displaytext": "Small", - "name": "Small", - "disksize": 1 - }, - "virtual_machine": { - "displayname": "testVM", - "hypervisor": 'XenServer', - "protocol": 'TCP', - "ssh_port": 22, - "username": "root", - "password": "password", - "privateport": 22, - "publicport": 22, - }, - "volume": { - "diskname": "Test Volume", - }, - "template_1": { - "displaytext": "Cent OS Template", - "name": "Cent OS Template", - "ostype": "CentOS 5.3 (64-bit)", - }, - "template_2": { - "displaytext": "Public Template", - "name": "Public template", - "ostype": "CentOS 5.3 (64-bit)", - "isfeatured": True, - "ispublic": True, - "isextractable": True, - "mode": "HTTP_DOWNLOAD", - }, - "templatefilter": 'self', - "isfeatured": True, - "ispublic": True, - "isextractable": False, - "bootable": True, - "passwordenabled": True, - "ostype": "CentOS 5.3 (64-bit)", - "sleep": 30, - "timeout": 10, - } - - class TestCreateTemplate(cloudstackTestCase): def setUp(self): @@ -118,45 +62,53 @@ def tearDown(self): @classmethod def setUpClass(cls): - cls.services = Services().services - cls.api_client = super(TestCreateTemplate, cls).getClsTestClient().getApiClient() + + testClient = super(TestCreateTemplate, cls).getClsTestClient() + cls.apiclient = testClient.getApiClient() + cls.services = testClient.getParsedTestDataConfig() # Get Zone, Domain and templates - cls.domain = get_domain(cls.api_client, cls.services) - cls.zone = get_zone(cls.api_client, cls.services) + cls.domain = get_domain(cls.apiclient) + cls.zone = get_zone(cls.apiclient, testClient.getZoneForTests()) cls.services['mode'] = cls.zone.networktype - cls.disk_offering = DiskOffering.create( - cls.api_client, + + cls._cleanup = [] + try: + cls.disk_offering = DiskOffering.create( + cls.apiclient, cls.services["disk_offering"] ) - template = get_template( - cls.api_client, + cls._cleanup.append(cls.disk_offering) + template = get_template( + cls.apiclient, cls.zone.id, cls.services["ostype"] ) - cls.services["template_1"]["ostypeid"] = template.ostypeid - cls.services["template_2"]["ostypeid"] = template.ostypeid - cls.services["ostypeid"] = template.ostypeid - - cls.services["virtual_machine"]["zoneid"] = cls.zone.id - cls.services["volume"]["diskoffering"] = cls.disk_offering.id - cls.services["volume"]["zoneid"] = cls.zone.id - cls.services["sourcezoneid"] = cls.zone.id - - cls.account = Account.create( - cls.api_client, + if template == FAILED: + assert False, "get_template() failed to return template with description %s" % cls.services["ostype"] + + cls.services["template"]["ostypeid"] = template.ostypeid + cls.services["template_2"]["ostypeid"] = template.ostypeid + cls.services["ostypeid"] = template.ostypeid + + cls.services["virtual_machine"]["zoneid"] = cls.zone.id + cls.services["volume"]["diskoffering"] = cls.disk_offering.id + cls.services["volume"]["zoneid"] = cls.zone.id + cls.services["sourcezoneid"] = cls.zone.id + cls.account = Account.create( + cls.apiclient, 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._cleanup.append(cls.account) + cls.service_offering = ServiceOffering.create( + cls.apiclient, + cls.services["service_offerings"] ) - #create virtual machine - cls.virtual_machine = VirtualMachine.create( - cls.api_client, + cls._cleanup.append(cls.service_offering) + #create virtual machine + cls.virtual_machine = VirtualMachine.create( + cls.apiclient, cls.services["virtual_machine"], templateid=template.id, accountid=cls.account.name, @@ -164,62 +116,35 @@ def setUpClass(cls): serviceofferingid=cls.service_offering.id, mode=cls.services["mode"] ) + #Stop virtual machine + cls.virtual_machine.stop(cls.apiclient) - #Stop virtual machine - cls.virtual_machine.stop(cls.api_client) - - # Poll listVM to ensure VM is stopped properly - timeout = cls.services["timeout"] - while True: - time.sleep(cls.services["sleep"]) - - # Ensure that VM is in stopped state - list_vm_response = list_virtual_machines( - cls.api_client, - id=cls.virtual_machine.id - ) - - if isinstance(list_vm_response, list): - - vm = list_vm_response[0] - if vm.state == 'Stopped': - break - - if timeout == 0: - raise Exception( - "Failed to stop VM (ID: %s) in change service offering" % - vm.id) - - timeout = timeout - 1 - - list_volume = list_volumes( - cls.api_client, + list_volume = Volume.list( + cls.apiclient, virtualmachineid=cls.virtual_machine.id, type='ROOT', listall=True ) - cls.volume = list_volume[0] - cls._cleanup = [ - cls.account, - cls.service_offering, - cls.disk_offering, - ] + cls.volume = list_volume[0] + except Exception as e: + cls.tearDownClass() + raise unittest.SkipTest("Exception in setUpClass: %s" % e) return @classmethod def tearDownClass(cls): try: - cls.api_client = super(TestCreateTemplate, cls).getClsTestClient().getApiClient() + cls.apiclient = super(TestCreateTemplate, cls).getClsTestClient().getApiClient() #Cleanup resources used - cleanup_resources(cls.api_client, cls._cleanup) + cleanup_resources(cls.apiclient, cls._cleanup) except Exception as e: raise Exception("Warning: Exception during cleanup : %s" % e) return - @attr(tags = ["advanced", "advancedns", "smoke"]) + @attr(tags = ["advanced", "advancedns", "smoke", "selfservice"]) def test_01_create_template(self): """Test create public & private template """ @@ -233,7 +158,7 @@ def test_01_create_template(self): #Create template from Virtual machine and Volume ID template = Template.create( self.apiclient, - self.services["template_1"], + self.services["template"], self.volume.id, account=self.account.name, domainid=self.account.domainid @@ -242,7 +167,7 @@ def test_01_create_template(self): self.debug("Created template with ID: %s" % template.id) - list_template_response = list_templates( + list_template_response = Template.list( self.apiclient, templatefilter=\ self.services["templatefilter"], @@ -264,18 +189,18 @@ def test_01_create_template(self): self.assertEqual( template_response.displaytext, - self.services["template_1"]["displaytext"], + self.services["template"]["displaytext"], "Check display text of newly created template" ) name = template_response.name self.assertEqual( - name.count(self.services["template_1"]["name"]), + name.count(self.services["template"]["name"]), 1, "Check name of newly created template" ) self.assertEqual( template_response.ostypeid, - self.services["template_1"]["ostypeid"], + self.services["template"]["ostypeid"], "Check osTypeID of newly created template" ) return @@ -286,60 +211,61 @@ class TestTemplates(cloudstackTestCase): @classmethod def setUpClass(cls): - cls.services = Services().services - cls.api_client = super(TestTemplates, cls).getClsTestClient().getApiClient() + testClient = super(TestTemplates, cls).getClsTestClient() + cls.apiclient = testClient.getApiClient() + cls.services = testClient.getParsedTestDataConfig() # Get Zone, Domain and templates - cls.domain = get_domain(cls.api_client, cls.services) - cls.zone = get_zone(cls.api_client, cls.services) + cls.domain = get_domain(cls.apiclient) + cls.zone = get_zone(cls.apiclient, cls.testClient.getZoneForTests()) cls.services['mode'] = cls.zone.networktype #populate second zone id for iso copy cmd = listZones.listZonesCmd() - cls.zones = cls.api_client.listZones(cmd) + cls.zones = cls.apiclient.listZones(cmd) if not isinstance(cls.zones, list): raise Exception("Failed to find zones.") cls.disk_offering = DiskOffering.create( - cls.api_client, + cls.apiclient, cls.services["disk_offering"] ) template = get_template( - cls.api_client, + cls.apiclient, cls.zone.id, cls.services["ostype"] ) + if template == FAILED: + assert False, "get_template() failed to return template with description %s" % cls.services["ostype"] + cls.services["virtual_machine"]["zoneid"] = cls.zone.id cls.services["volume"]["diskoffering"] = cls.disk_offering.id cls.services["volume"]["zoneid"] = cls.zone.id cls.services["template_2"]["zoneid"] = cls.zone.id cls.services["sourcezoneid"] = cls.zone.id - cls.services["template_1"]["ostypeid"] = template.ostypeid + cls.services["template"]["ostypeid"] = template.ostypeid cls.services["template_2"]["ostypeid"] = template.ostypeid cls.services["ostypeid"] = template.ostypeid - + print "Before:",cls.services cls.account = Account.create( - cls.api_client, + cls.apiclient, cls.services["account"], admin=True, domainid=cls.domain.id ) - + print "After:",cls.services cls.user = Account.create( - cls.api_client, + cls.apiclient, 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.apiclient, + cls.services["service_offerings"] ) #create virtual machine cls.virtual_machine = VirtualMachine.create( - cls.api_client, + cls.apiclient, cls.services["virtual_machine"], templateid=template.id, accountid=cls.account.name, @@ -348,34 +274,10 @@ def setUpClass(cls): mode=cls.services["mode"] ) #Stop virtual machine - cls.virtual_machine.stop(cls.api_client) - - # Poll listVM to ensure VM is stopped properly - timeout = cls.services["timeout"] - while True: - time.sleep(cls.services["sleep"]) - - # Ensure that VM is in stopped state - list_vm_response = list_virtual_machines( - cls.api_client, - id=cls.virtual_machine.id - ) - - if isinstance(list_vm_response, list): - - vm = list_vm_response[0] - if vm.state == 'Stopped': - break - - if timeout == 0: - raise Exception( - "Failed to stop VM (ID: %s) in change service offering" % - vm.id) - - timeout = timeout - 1 + cls.virtual_machine.stop(cls.apiclient) - list_volume = list_volumes( - cls.api_client, + list_volume = Volume.list( + cls.apiclient, virtualmachineid=cls.virtual_machine.id, type='ROOT', listall=True @@ -384,19 +286,19 @@ def setUpClass(cls): cls.volume = list_volume[0] except Exception as e: raise Exception( - "Exception: Unable to find root volume foe VM: %s" % - cls.virtual_machine.id) + "Exception: Unable to find root volume foe VM: %s - %s" % + (cls.virtual_machine.id, e)) #Create templates for Edit, Delete & update permissions testcases cls.template_1 = Template.create( - cls.api_client, - cls.services["template_1"], + cls.apiclient, + cls.services["template"], cls.volume.id, account=cls.account.name, domainid=cls.account.domainid ) cls.template_2 = Template.create( - cls.api_client, + cls.apiclient, cls.services["template_2"], cls.volume.id, account=cls.account.name, @@ -412,9 +314,9 @@ def setUpClass(cls): @classmethod def tearDownClass(cls): try: - cls.api_client = super(TestTemplates, cls).getClsTestClient().getApiClient() + cls.apiclient = super(TestTemplates, cls).getClsTestClient().getApiClient() #Cleanup created resources such as templates and VMs - cleanup_resources(cls.api_client, cls._cleanup) + cleanup_resources(cls.apiclient, cls._cleanup) except Exception as e: raise Exception("Warning: Exception during cleanup : %s" % e) @@ -438,7 +340,7 @@ def tearDown(self): return - @attr(tags = ["advanced", "advancedns", "smoke", "basic", "sg"]) + @attr(tags = ["advanced", "advancedns", "smoke", "basic", "sg", "selfservice", "test"]) def test_02_edit_template(self): """Test Edit template """ @@ -468,7 +370,7 @@ def test_02_edit_template(self): timeout = self.services["timeout"] while True: # Verify template response for updated attributes - list_template_response = list_templates( + list_template_response = Template.list( self.apiclient, templatefilter=\ self.services["templatefilter"], @@ -521,7 +423,7 @@ def test_02_edit_template(self): ) return - @attr(tags = ["advanced", "advancedns", "smoke", "basic", "sg"]) + @attr(tags = ["advanced", "advancedns", "smoke", "basic", "sg", "selfservice"]) def test_03_delete_template(self): """Test delete template """ @@ -534,7 +436,7 @@ def test_03_delete_template(self): self.template_1.delete(self.apiclient) - list_template_response = list_templates( + list_template_response = Template.list( self.apiclient, templatefilter=\ self.services["templatefilter"], @@ -550,7 +452,7 @@ def test_03_delete_template(self): ) return - @attr(tags = ["advanced", "advancedns", "smoke", "basic", "sg"]) + @attr(tags = ["advanced", "advancedns", "smoke", "basic", "sg", "provisioning"]) def test_04_extract_template(self): "Test for extract template" @@ -601,7 +503,7 @@ def test_04_extract_template(self): ) return - @attr(tags = ["advanced", "advancedns", "smoke", "basic", "sg"]) + @attr(tags = ["advanced", "advancedns", "smoke", "basic", "sg", "selfservice"]) def test_05_template_permissions(self): """Update & Test for template permissions""" @@ -621,7 +523,7 @@ def test_05_template_permissions(self): cmd.isextractable = self.services["isextractable"] self.apiclient.updateTemplatePermissions(cmd) - list_template_response = list_templates( + list_template_response = Template.list( self.apiclient, templatefilter='featured', id=self.template_2.id, @@ -654,7 +556,7 @@ def test_05_template_permissions(self): ) return - @attr(tags = ["advanced", "advancedns", "smoke", "basic", "sg", "multizone"]) + @attr(tags = ["advanced", "advancedns", "smoke", "basic", "sg", "multizone", "provisioning"]) def test_06_copy_template(self): """Test for copy template from one zone to another""" @@ -678,7 +580,7 @@ def test_06_copy_template(self): self.apiclient.copyTemplate(cmd) # Verify template is copied to another zone using ListTemplates - list_template_response = list_templates( + list_template_response = Template.list( self.apiclient, templatefilter=\ self.services["templatefilter"], @@ -712,7 +614,7 @@ def test_06_copy_template(self): timeout = self.services["timeout"] while True: time.sleep(self.services["sleep"]) - list_template_response = list_templates( + list_template_response = Template.list( self.apiclient, templatefilter=\ self.services["templatefilter"], @@ -745,14 +647,14 @@ def test_06_copy_template(self): self.apiclient.deleteTemplate(cmd) return - @attr(tags = ["advanced", "advancedns", "smoke", "basic", "sg"]) + @attr(tags = ["advanced", "advancedns", "smoke", "basic", "sg", "selfservice"]) def test_07_list_public_templates(self): """Test only public templates are visible to normal user""" # Validate the following # 1. ListTemplates should show only 'public' templates for normal user - list_template_response = list_templates( + list_template_response = Template.list( self.apiclient, templatefilter='featured', account=self.user.name, @@ -777,14 +679,14 @@ def test_07_list_public_templates(self): ) return - @attr(tags = ["advanced", "advancedns", "smoke", "basic", "sg"]) + @attr(tags = ["advanced", "advancedns", "smoke", "basic", "sg", "selfservice"]) def test_08_list_system_templates(self): """Test System templates are not visible to normal user""" # Validate the following # 1. ListTemplates should not show 'SYSTEM' templates for normal user - list_template_response = list_templates( + list_template_response = Template.list( self.apiclient, templatefilter='featured', account=self.user.name, diff --git a/test/integration/smoke/test_vm_ha.py b/test/integration/smoke/test_vm_ha.py new file mode 100644 index 0000000000..406394635c --- /dev/null +++ b/test/integration/smoke/test_vm_ha.py @@ -0,0 +1,199 @@ +# 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. + +#Test from the Marvin - Testing in Python wiki + +import time + +#All tests inherit from cloudstackTestCase +from marvin.cloudstackTestCase import cloudstackTestCase + +#Import Integration Libraries + +#base - contains all resources as entities and defines create, delete, list operations on them +from marvin.lib.base import Account, VirtualMachine, Cluster, Host, ServiceOffering, Configurations, SimulatorMock + +#utils - utility classes for common cleanup, external library wrappers etc +from marvin.lib.utils import cleanup_resources + +#common - commonly used methods for all tests are listed here +from marvin.lib.common import get_zone, get_domain, get_template + +from nose.plugins.attrib import attr + +class TestDeployVMHA(cloudstackTestCase): + """Test VM HA + """ + + def setUp(self): + self.testdata = self.testClient.getParsedTestDataConfig() + self.apiclient = self.testClient.getApiClient() + + # Get Zone, Domain and Default Built-in template + self.domain = get_domain(self.apiclient) + self.zone = get_zone(self.apiclient, self.testClient.getZoneForTests()) + + self.testdata["mode"] = self.zone.networktype + self.template = get_template(self.apiclient, self.zone.id, self.testdata["ostype"]) + + self.hosts = [] + suitablecluster = None + clusters = Cluster.list(self.apiclient) + self.assertTrue(isinstance(clusters, list) and len(clusters) > 0, msg = "No clusters found") + for cluster in clusters: + self.hosts = Host.list(self.apiclient, clusterid=cluster.id, type='Routing') + if isinstance(self.hosts, list) and len(self.hosts) >= 2: + suitablecluster = cluster + break + self.assertTrue(isinstance(self.hosts, list) and len(self.hosts) >= 2, msg = "Atleast 2 hosts required in cluster for VM HA test") + #update host tags + for host in self.hosts: + Host.update(self.apiclient, id=host.id, hosttags=self.testdata["service_offerings"]["hasmall"]["hosttags"]) + + #create a user account + self.account = Account.create( + self.apiclient, + self.testdata["account"], + domainid=self.domain.id + ) + #create a service offering + self.service_offering = ServiceOffering.create( + self.apiclient, + self.testdata["service_offerings"]["hasmall"] + ) + #deploy ha vm + self.virtual_machine = VirtualMachine.create( + self.apiclient, + self.testdata["virtual_machine"], + accountid=self.account.name, + zoneid=self.zone.id, + domainid=self.account.domainid, + serviceofferingid=self.service_offering.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.assertTrue(isinstance(list_vms, list) and len(list_vms) == 1, msg = "List VM response was empty") + self.virtual_machine = list_vms[0] + + self.mock_checkhealth = SimulatorMock.create( + apiclient=self.apiclient, + command="CheckHealthCommand", + zoneid=suitablecluster.zoneid, + podid=suitablecluster.podid, + clusterid=suitablecluster.id, + hostid=self.virtual_machine.hostid, + value="result:fail") + self.mock_ping = SimulatorMock.create( + apiclient=self.apiclient, + command="PingCommand", + zoneid=suitablecluster.zoneid, + podid=suitablecluster.podid, + clusterid=suitablecluster.id, + hostid=self.virtual_machine.hostid, + value="result:fail") + self.mock_checkvirtualmachine = SimulatorMock.create( + apiclient=self.apiclient, + command="CheckVirtualMachineCommand", + zoneid=suitablecluster.zoneid, + podid=suitablecluster.podid, + clusterid=suitablecluster.id, + hostid=self.virtual_machine.hostid, + value="result:fail") + self.mock_pingtest = SimulatorMock.create( + apiclient=self.apiclient, + command="PingTestCommand", + zoneid=suitablecluster.zoneid, + podid=suitablecluster.podid, + value="result:fail") + self.mock_checkonhost_list = [] + for host in self.hosts: + if host.id != self.virtual_machine.hostid: + self.mock_checkonhost_list.append(SimulatorMock.create( + apiclient=self.apiclient, + command="CheckOnHostCommand", + zoneid=suitablecluster.zoneid, + podid=suitablecluster.podid, + clusterid=suitablecluster.id, + hostid=host.id, + value="result:fail")) + #build cleanup list + self.cleanup = [ + self.service_offering, + self.account, + self.mock_checkhealth, + self.mock_ping, + self.mock_checkvirtualmachine, + self.mock_pingtest + ] + self.cleanup = self.cleanup + self.mock_checkonhost_list + + @attr(tags = ['selfservice']) + def test_vm_ha(self): + """Test VM HA + + # Validate the following: + # VM started on other host in cluster + """ + + #wait for VM to HA + ping_timeout = Configurations.list(self.apiclient, name="ping.timeout") + ping_interval = Configurations.list(self.apiclient, name="ping.interval") + total_duration = int(float(ping_timeout[0].value) * float(ping_interval[0].value)) + time.sleep(total_duration) + + duration = 0 + vm = None + while duration < total_duration: + list_vms = VirtualMachine.list(self.apiclient, id=self.virtual_machine.id) + self.assertTrue(isinstance(list_vms, list) and len(list_vms) == 1, msg = "List VM response was empty") + vm = list_vms[0] + if vm.hostid != self.virtual_machine.hostid and vm.state == "Running": + break + else: + time.sleep(10) + duration = duration + 10 + + self.assertEqual( + vm.id, + self.virtual_machine.id, + "VM ids do not match") + self.assertEqual( + vm.name, + self.virtual_machine.name, + "VM names do not match") + self.assertEqual( + vm.state, + "Running", + msg="VM is not in Running state") + self.assertNotEqual( + vm.hostid, + self.virtual_machine.hostid, + msg="VM is not started on another host as part of HA") + + def tearDown(self): + try: + for host in self.hosts: + Host.update(self.apiclient, id=host.id, hosttags="") + + cleanup_resources(self.apiclient, self.cleanup) + except Exception as e: + self.debug("Warning! Exception in tearDown: %s" % e) + diff --git a/test/integration/smoke/test_vm_iam.py b/test/integration/smoke/test_vm_iam.py index 29e587bbd3..be75a79737 100644 --- a/test/integration/smoke/test_vm_iam.py +++ b/test/integration/smoke/test_vm_iam.py @@ -20,9 +20,10 @@ import marvin 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.lib.utils import * +from marvin.lib.base import * +from marvin.lib.common import * +from marvin.codes import FAILED from nose.plugins.attrib import attr #Import System modules import time @@ -103,7 +104,8 @@ class TestVMIam(cloudstackTestCase): @classmethod def setUpClass(self): - self.apiclient = super(TestVMIam, self).getClsTestClient().getApiClient() + testClient = super(TestVMIam, self).getClsTestClient() + self.apiclient = testClient.getApiClient() self.services = Services().services # backup default apikey and secretkey @@ -191,7 +193,7 @@ def setUpClass(self): self.services["service_offering"]["small"] ) - self.zone = get_zone(self.apiclient, self.services) + self.zone = get_zone(self.apiclient, testClient.getZoneForTests()) self.services['mode'] = self.zone.networktype self.template = get_template(self.apiclient, self.zone.id, self.services["ostype"]) @@ -280,7 +282,7 @@ def tearDown(self): - @attr(tags = ["devcloud", "advanced", "advancedns", "smoke", "basic", "sg"]) + @attr(tags = ["devcloud", "advanced", "advancedns", "smoke", "basic", "sg", "selfservice"]) def test_01_list_own_vm(self): # listVM command should return owne's VM @@ -357,7 +359,7 @@ def test_01_list_own_vm(self): return - @attr(tags = ["devcloud", "advanced", "advancedns", "smoke", "basic", "sg"]) + @attr(tags = ["devcloud", "advanced", "advancedns", "smoke", "basic", "sg", "selfservice"]) def test_02_grant_domain_vm(self): # Validate the following @@ -406,7 +408,7 @@ def test_02_grant_domain_vm(self): return - @attr(tags = ["devcloud", "advanced", "advancedns", "smoke", "basic", "sg"]) + @attr(tags = ["devcloud", "advanced", "advancedns", "smoke", "basic", "sg", "selfservice"]) def test_03_grant_account_vm(self): # Validate the following @@ -459,7 +461,7 @@ def test_03_grant_account_vm(self): return - @attr(tags = ["devcloud", "advanced", "advancedns", "smoke", "basic", "sg"]) + @attr(tags = ["devcloud", "advanced", "advancedns", "smoke", "basic", "sg", "selfservice"]) def test_04_revoke_account_vm(self): # Validate the following @@ -502,7 +504,7 @@ def test_04_revoke_account_vm(self): return - @attr(tags = ["devcloud", "advanced", "advancedns", "smoke", "basic", "sg"]) + @attr(tags = ["devcloud", "advanced", "advancedns", "smoke", "basic", "sg", "selfservice"]) def test_05_revoke_domain_vm(self): # Validate the following @@ -543,7 +545,7 @@ def test_05_revoke_domain_vm(self): return - @attr(tags = ["devcloud", "advanced", "advancedns", "smoke", "basic", "sg"]) + @attr(tags = ["devcloud", "advanced", "advancedns", "smoke", "basic", "sg", "selfservice"]) def test_06_grant_resource_vm(self): # Validate the following @@ -590,7 +592,7 @@ def test_06_grant_resource_vm(self): return - @attr(tags = ["devcloud", "advanced", "advancedns", "smoke", "basic", "sg"]) + @attr(tags = ["devcloud", "advanced", "advancedns", "smoke", "basic", "sg", "selfservice"]) def test_07_revoke_resource_vm(self): # Validate the following @@ -632,7 +634,7 @@ def test_07_revoke_resource_vm(self): return - @attr(tags = ["devcloud", "advanced", "advancedns", "smoke", "basic", "sg"]) + @attr(tags = ["devcloud", "advanced", "advancedns", "smoke", "basic", "sg", "selfservice"]) def test_08_policy_attach_account(self): # Validate the following @@ -680,7 +682,7 @@ def test_08_policy_attach_account(self): return - @attr(tags = ["devcloud", "advanced", "advancedns", "smoke", "basic", "sg"]) + @attr(tags = ["devcloud", "advanced", "advancedns", "smoke", "basic", "sg", "selfservice"]) def test_09_policy_detach_account(self): # Validate the following diff --git a/test/integration/smoke/test_vm_life_cycle.py b/test/integration/smoke/test_vm_life_cycle.py index c164f59985..fea3ddebc0 100644 --- a/test/integration/smoke/test_vm_life_cycle.py +++ b/test/integration/smoke/test_vm_life_cycle.py @@ -18,138 +18,40 @@ """ #Import Local Modules from marvin.cloudstackTestCase import cloudstackTestCase -from marvin.cloudstackAPI import (detachIso, +from marvin.cloudstackAPI import (recoverVirtualMachine, + destroyVirtualMachine, attachIso, - recoverVirtualMachine, - destroyVirtualMachine) -from marvin.integration.lib.utils import (cleanup_resources, - validateList, - get_hypervisor_type) -from marvin.integration.lib.base import (Account, - ServiceOffering, - VirtualMachine, - Iso, - Host) -from marvin.integration.lib.common import (get_domain, - get_zone, - get_template, - list_virtual_machines, - list_configurations, - list_routers, - list_isos) -from marvin.codes import PASS + detachIso) +from marvin.lib.utils import (cleanup_resources, + validateList, + get_hypervisor_type) +from marvin.lib.base import (Account, + ServiceOffering, + VirtualMachine, + Host, + Iso, + Router, + Configurations) +from marvin.lib.common import (get_domain, + get_zone, + get_template) +from marvin.codes import FAILED, PASS 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', - }, - "medium": # Create a medium virtual machine instance - { - "displayname": "testserver", - "username": "root", - "password": "password", - "ssh_port": 22, - "hypervisor": 'XenServer', - "privateport": 22, - "publicport": 22, - "protocol": 'TCP', - }, - "service_offerings": - { - "tiny": - { - "name": "Tiny Instance", - "displaytext": "Tiny Instance", - "cpunumber": 1, - "cpuspeed": 100, # in MHz - "memory": 128, # In MBs - }, - "small": - { - # Small service offering ID to for change VM - # service offering from medium to small - "name": "Small Instance", - "displaytext": "Small Instance", - "cpunumber": 1, - "cpuspeed": 100, - "memory": 256, - }, - "medium": - { - # Medium service offering ID to for - # change VM service offering from small to medium - "name": "Medium Instance", - "displaytext": "Medium Instance", - "cpunumber": 1, - "cpuspeed": 100, - "memory": 256, - } - }, - "iso": # ISO settings for Attach/Detach ISO tests - { - "displaytext": "Test ISO", - "name": "testISO", - "url": "http://people.apache.org/~tsp/dummy.iso", - # Source URL where ISO is located - "ostype": 'CentOS 5.3 (64-bit)', - "mode": 'HTTP_DOWNLOAD', # Downloading existing ISO - }, - "template": { - "displaytext": "Cent OS Template", - "name": "Cent OS Template", - "passwordenabled": True, - }, - "diskdevice": ['/dev/vdc', '/dev/vdb', '/dev/hdb', '/dev/hdc', '/dev/xvdd', '/dev/cdrom', '/dev/sr0', '/dev/cdrom1' ], - # 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 TestDeployVM(cloudstackTestCase): @classmethod def setUpClass(cls): - cls.services = Services().services - cls.apiclient = super(TestDeployVM, cls).getClsTestClient().getApiClient() + testClient = super(TestDeployVM, cls).getClsTestClient() + cls.apiclient = testClient.getApiClient() + cls.services = testClient.getParsedTestDataConfig() + # Get Zone, Domain and templates - domain = get_domain(cls.apiclient, cls.services) - cls.zone = get_zone(cls.apiclient, cls.services) + domain = get_domain(cls.apiclient) + cls.zone = get_zone(cls.apiclient, testClient.getZoneForTests()) cls.services['mode'] = cls.zone.networktype #If local storage is enabled, alter the offerings to use localstorage @@ -164,13 +66,16 @@ def setUpClass(cls): cls.zone.id, cls.services["ostype"] ) + if template == FAILED: + assert False, "get_template() failed to return template with description %s" % cls.services["ostype"] + # Set Zones and disk offerings cls.services["small"]["zoneid"] = cls.zone.id cls.services["small"]["template"] = template.id cls.services["medium"]["zoneid"] = cls.zone.id cls.services["medium"]["template"] = template.id - cls.services["iso"]["zoneid"] = cls.zone.id + cls.services["iso1"]["zoneid"] = cls.zone.id cls.account = Account.create( cls.apiclient, @@ -217,7 +122,7 @@ def test_deploy_vm(self): # Validate the following: # 1. Virtual Machine is accessible via SSH # 2. listVirtualMachines returns accurate information - list_vm_response = list_virtual_machines( + list_vm_response = VirtualMachine.list( self.apiclient, id=self.virtual_machine.id ) @@ -258,6 +163,7 @@ def test_deploy_vm(self): @attr(tags = ["simulator", "advanced"]) def test_advZoneVirtualRouter(self): + #TODO: SIMENH: duplicate test, remove it """ Test advanced zone virtual router 1. Is Running @@ -265,7 +171,7 @@ def test_advZoneVirtualRouter(self): 3. Has a linklocalip, publicip and a guestip @return: """ - routers = list_routers(self.apiclient, account=self.account.name) + routers = Router.list(self.apiclient, account=self.account.name, listall=True) self.assertTrue(len(routers) > 0, msg = "No virtual router found") router = routers[0] @@ -280,13 +186,14 @@ def test_advZoneVirtualRouter(self): @attr(hypervisor = ["simulator"]) @attr(mode = ["basic"]) def test_basicZoneVirtualRouter(self): + #TODO: SIMENH: duplicate test, remove it """ Tests for basic zone virtual router 1. Is Running 2. is in the account the VM was deployed in @return: """ - routers = list_routers(self.apiclient, account=self.account.name) + routers = Router.list(self.apiclient, account=self.account.name, listall=True) self.assertTrue(len(routers) > 0, msg = "No virtual router found") router = routers[0] @@ -301,12 +208,13 @@ class TestVMLifeCycle(cloudstackTestCase): @classmethod def setUpClass(cls): - cls.api_client = super(TestVMLifeCycle, cls).getClsTestClient().getApiClient() - cls.services = Services().services + testClient = super(TestVMLifeCycle, cls).getClsTestClient() + cls.apiclient = testClient.getApiClient() + cls.services = testClient.getParsedTestDataConfig() # Get Zone, Domain and templates - domain = get_domain(cls.api_client, cls.services) - cls.zone = get_zone(cls.api_client, cls.services) + domain = get_domain(cls.apiclient) + cls.zone = get_zone(cls.apiclient, cls.testClient.getZoneForTests()) cls.services['mode'] = cls.zone.networktype #if local storage is enabled, alter the offerings to use localstorage @@ -317,37 +225,40 @@ def setUpClass(cls): cls.services["service_offerings"]["medium"]["storagetype"] = 'local' template = get_template( - cls.api_client, + cls.apiclient, cls.zone.id, cls.services["ostype"] ) + if template == FAILED: + assert False, "get_template() failed to return template with description %s" % cls.services["ostype"] + # Set Zones and disk offerings cls.services["small"]["zoneid"] = cls.zone.id cls.services["small"]["template"] = template.id cls.services["medium"]["zoneid"] = cls.zone.id cls.services["medium"]["template"] = template.id - cls.services["iso"]["zoneid"] = cls.zone.id + cls.services["iso1"]["zoneid"] = cls.zone.id # Create VMs, NAT Rules etc cls.account = Account.create( - cls.api_client, + cls.apiclient, cls.services["account"], domainid=domain.id ) cls.small_offering = ServiceOffering.create( - cls.api_client, + cls.apiclient, cls.services["service_offerings"]["small"] ) cls.medium_offering = ServiceOffering.create( - cls.api_client, + cls.apiclient, cls.services["service_offerings"]["medium"] ) #create small and large virtual machines cls.small_virtual_machine = VirtualMachine.create( - cls.api_client, + cls.apiclient, cls.services["small"], accountid=cls.account.name, domainid=cls.account.domainid, @@ -355,7 +266,7 @@ def setUpClass(cls): mode=cls.services["mode"] ) cls.medium_virtual_machine = VirtualMachine.create( - cls.api_client, + cls.apiclient, cls.services["medium"], accountid=cls.account.name, domainid=cls.account.domainid, @@ -363,7 +274,7 @@ def setUpClass(cls): mode=cls.services["mode"] ) cls.virtual_machine = VirtualMachine.create( - cls.api_client, + cls.apiclient, cls.services["small"], accountid=cls.account.name, domainid=cls.account.domainid, @@ -378,8 +289,8 @@ def setUpClass(cls): @classmethod def tearDownClass(cls): - cls.api_client = super(TestVMLifeCycle, cls).getClsTestClient().getApiClient() - cleanup_resources(cls.api_client, cls._cleanup) + cls.apiclient = super(TestVMLifeCycle, cls).getClsTestClient().getApiClient() + cleanup_resources(cls.apiclient, cls._cleanup) return def setUp(self): @@ -393,7 +304,7 @@ def tearDown(self): return - @attr(tags = ["devcloud", "advanced", "advancedns", "smoke", "basic", "sg"]) + @attr(tags = ["devcloud", "advanced", "advancedns", "smoke", "basic", "sg", "selfservice"]) def test_01_stop_vm(self): """Test Stop Virtual Machine """ @@ -402,34 +313,13 @@ def test_01_stop_vm(self): # 1. Should Not be able to login to the VM. # 2. listVM command should return # this VM.State of this VM should be ""Stopped"". - - self.debug("Stopping VM - ID: %s" % self.virtual_machine.id) - self.small_virtual_machine.stop(self.apiclient) - - list_vm_response = list_virtual_machines( - self.apiclient, - id=self.small_virtual_machine.id - ) - - self.assertEqual( - isinstance(list_vm_response, list), - True, - "Check list response returns a valid list" - ) - self.assertNotEqual( - len(list_vm_response), - 0, - "Check VM available in List Virtual Machines" - ) - - self.assertEqual( - list_vm_response[0].state, - "Stopped", - "Check virtual machine is in stopped state" - ) + try: + self.small_virtual_machine.stop(self.apiclient) + except Exception as e: + self.fail("Failed to stop VM: %s" % e) return - @attr(tags = ["devcloud", "advanced", "advancedns", "smoke", "basic", "sg"]) + @attr(tags = ["devcloud", "advanced", "advancedns", "smoke", "basic", "sg", "selfservice"]) def test_02_start_vm(self): """Test Start Virtual Machine """ @@ -440,7 +330,7 @@ def test_02_start_vm(self): self.debug("Starting VM - ID: %s" % self.virtual_machine.id) self.small_virtual_machine.start(self.apiclient) - list_vm_response = list_virtual_machines( + list_vm_response = VirtualMachine.list( self.apiclient, id=self.small_virtual_machine.id ) @@ -467,7 +357,7 @@ def test_02_start_vm(self): ) return - @attr(tags = ["devcloud", "advanced", "advancedns", "smoke", "basic", "sg"]) + @attr(tags = ["devcloud", "advanced", "advancedns", "smoke", "basic", "sg", "selfservice"]) def test_03_reboot_vm(self): """Test Reboot Virtual Machine """ @@ -480,7 +370,7 @@ def test_03_reboot_vm(self): self.debug("Rebooting VM - ID: %s" % self.virtual_machine.id) self.small_virtual_machine.reboot(self.apiclient) - list_vm_response = list_virtual_machines( + list_vm_response = VirtualMachine.list( self.apiclient, id=self.small_virtual_machine.id ) @@ -504,7 +394,7 @@ def test_03_reboot_vm(self): return - @attr(tags = ["devcloud", "advanced", "advancedns", "smoke", "basic", "sg"]) + @attr(tags = ["devcloud", "advanced", "advancedns", "smoke", "basic", "sg", "selfservice"]) def test_06_destroy_vm(self): """Test destroy Virtual Machine """ @@ -517,7 +407,7 @@ def test_06_destroy_vm(self): self.debug("Destroy VM - ID: %s" % self.small_virtual_machine.id) self.small_virtual_machine.delete(self.apiclient) - list_vm_response = list_virtual_machines( + list_vm_response = VirtualMachine.list( self.apiclient, id=self.small_virtual_machine.id ) @@ -540,8 +430,9 @@ def test_06_destroy_vm(self): ) return - @attr(tags = ["devcloud", "advanced", "advancedns", "smoke", "basic", "sg"]) + @attr(tags = ["devcloud", "advanced", "advancedns", "smoke", "basic", "sg", "selfservice"]) def test_07_restore_vm(self): + #TODO: SIMENH: add another test the data on the restored VM. """Test recover Virtual Machine """ @@ -556,7 +447,7 @@ def test_07_restore_vm(self): cmd.id = self.small_virtual_machine.id self.apiclient.recoverVirtualMachine(cmd) - list_vm_response = list_virtual_machines( + list_vm_response = VirtualMachine.list( self.apiclient, id=self.small_virtual_machine.id ) @@ -580,7 +471,7 @@ def test_07_restore_vm(self): return - @attr(tags = ["advanced", "advancedns", "smoke", "basic", "sg", "multihost"]) + @attr(tags = ["advanced", "advancedns", "smoke", "basic", "sg", "multihost", "selfservice"]) def test_08_migrate_vm(self): """Test migrate VM """ @@ -625,7 +516,7 @@ def test_08_migrate_vm(self): #deploy VM on target host self.vm_to_migrate = VirtualMachine.create( - self.api_client, + self.apiclient, self.services["small"], accountid=self.account.name, domainid=self.account.domainid, @@ -638,9 +529,9 @@ def test_08_migrate_vm(self): migrate_host.id )) - self.vm_to_migrate.migrate(self.api_client, migrate_host.id) + self.vm_to_migrate.migrate(self.apiclient, migrate_host.id) - list_vm_response = list_virtual_machines( + list_vm_response = VirtualMachine.list( self.apiclient, id=self.vm_to_migrate.id ) @@ -667,7 +558,7 @@ def test_08_migrate_vm(self): @attr(configuration = "expunge.interval") @attr(configuration = "expunge.delay") - @attr(tags = ["devcloud", "advanced", "advancedns", "smoke", "basic", "sg"]) + @attr(tags = ["devcloud", "advanced", "advancedns", "smoke", "basic", "sg", "selfservice"]) def test_09_expunge_vm(self): """Test destroy(expunge) Virtual Machine """ @@ -680,7 +571,7 @@ def test_09_expunge_vm(self): cmd.id = self.small_virtual_machine.id self.apiclient.destroyVirtualMachine(cmd) - config = list_configurations( + config = Configurations.list( self.apiclient, name='expunge.delay' ) @@ -690,14 +581,14 @@ def test_09_expunge_vm(self): #VM should be destroyed unless expunge thread hasn't run #Wait for two cycles of the expunge thread - config = list_configurations( + config = Configurations.list( self.apiclient, name='expunge.interval' ) expunge_cycle = int(config[0].value) wait_time = expunge_cycle * 2 while wait_time >= 0: - list_vm_response = list_virtual_machines( + list_vm_response = VirtualMachine.list( self.apiclient, id=self.small_virtual_machine.id ) @@ -716,7 +607,7 @@ def test_09_expunge_vm(self): ) return - @attr(tags = ["advanced", "advancedns", "smoke", "basic", "sg"]) + @attr(tags = ["advanced", "advancedns", "smoke", "basic", "sg", "provisioning"]) def test_10_attachAndDetach_iso(self): """Test for attach and detach ISO to virtual machine""" @@ -730,7 +621,7 @@ def test_10_attachAndDetach_iso(self): iso = Iso.create( self.apiclient, - self.services["iso"], + self.services["iso1"], account=self.account.name, domainid=self.account.domainid ) @@ -758,11 +649,12 @@ def test_10_attachAndDetach_iso(self): self.fail("SSH failed for virtual machine: %s - %s" % (self.virtual_machine.ipaddress, e)) - cmds = "mkdir -p %s" % self.services["mount_dir"] + mount_dir = "/mnt/tmp" + cmds = "mkdir -p %s" % mount_dir self.assert_(ssh_client.execute(cmds) == [], "mkdir failed within guest") for diskdevice in self.services["diskdevice"]: - res = ssh_client.execute("mount -rt iso9660 {} {}".format(diskdevice, self.services["mount_dir"])) + res = ssh_client.execute("mount -rt iso9660 {} {}".format(diskdevice, mount_dir)) if res == []: self.services["mount"] = diskdevice break @@ -775,7 +667,7 @@ def test_10_attachAndDetach_iso(self): self.debug("Found a mount point at %s with size %s" % (res, size)) # Get ISO size - iso_response = list_isos( + iso_response = Iso.list( self.apiclient, id=iso.id ) @@ -787,7 +679,7 @@ def test_10_attachAndDetach_iso(self): try: #Unmount ISO - command = "umount %s" % self.services["mount_dir"] + command = "umount %s" % mount_dir ssh_client.execute(command) except Exception as e: self.fail("SSH failed for virtual machine: %s - %s" % diff --git a/test/integration/smoke/test_vm_snapshots.py b/test/integration/smoke/test_vm_snapshots.py index b49a37c45b..e884d42dcf 100644 --- a/test/integration/smoke/test_vm_snapshots.py +++ b/test/integration/smoke/test_vm_snapshots.py @@ -16,83 +16,33 @@ # under the License. # Import Local Modules -import marvin +from marvin.codes import FAILED 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 - } +from marvin.lib.utils import * +from marvin.lib.base import * +from marvin.lib.common import * class TestVmSnapshot(cloudstackTestCase): @classmethod def setUpClass(cls): - cls.api_client = super(TestVmSnapshot, cls).getClsTestClient().getApiClient() - cls.services = Services().services + testClient = super(TestVmSnapshot, cls).getClsTestClient() + cls.apiclient = testClient.getApiClient() + cls.services = testClient.getParsedTestDataConfig() # Get Zone, Domain and templates - cls.domain = get_domain(cls.api_client, cls.services) - cls.zone = get_zone(cls.api_client, cls.services) + cls.domain = get_domain(cls.apiclient) + cls.zone = get_zone(cls.apiclient, testClient.getZoneForTests()) template = get_template( - cls.api_client, + cls.apiclient, cls.zone.id, cls.services["ostype"] ) + if template == FAILED: + assert False, "get_template() failed to return template with description %s" % cls.services["ostype"] + cls.services["domainid"] = cls.domain.id cls.services["server"]["zoneid"] = cls.zone.id cls.services["templates"]["ostypeid"] = template.ostypeid @@ -100,27 +50,27 @@ def setUpClass(cls): # Create VMs, NAT Rules etc cls.account = Account.create( - cls.api_client, + cls.apiclient, 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.apiclient, + cls.services["service_offerings"] ) cls.virtual_machine = VirtualMachine.create( - cls.api_client, + cls.apiclient, cls.services["server"], templateid=template.id, accountid=cls.account.name, domainid=cls.account.domainid, serviceofferingid=cls.service_offering.id, - mode=cls.services["mode"] + mode=cls.zone.networktype ) cls.random_data_0 = random_gen(size=100) + cls.test_dir = "/tmp" + cls.random_data = "random.data" cls._cleanup = [ cls.service_offering, cls.account, @@ -131,7 +81,7 @@ def setUpClass(cls): def tearDownClass(cls): try: # Cleanup resources used - cleanup_resources(cls.api_client, cls._cleanup) + cleanup_resources(cls.apiclient, cls._cleanup) except Exception as e: raise Exception("Warning: Exception during cleanup : %s" % e) return @@ -150,7 +100,7 @@ def tearDown(self): raise Exception("Warning: Exception during cleanup : %s" % e) return - @attr(tags=["advanced", "advancedns", "smoke"]) + @attr(tags=["advanced", "advancedns", "smoke", "provisioning"]) def test_01_create_vm_snapshots(self): """Test to create VM snapshots """ @@ -160,8 +110,8 @@ def test_01_create_vm_snapshots(self): 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"]) + "echo %s > %s/%s" % (self.random_data_0, self.test_dir, self.random_data), + "cat %s/%s" % (self.test_dir, self.random_data) ] for c in cmds: @@ -184,8 +134,8 @@ def test_01_create_vm_snapshots(self): self.apiclient, self.virtual_machine.id, "false", - self.services["snapshot_name"], - self.services["snapshot_displaytext"] + "TestSnapshot", + "Dsiplay Text" ) self.assertEqual( vm_snapshot.state, @@ -194,7 +144,7 @@ def test_01_create_vm_snapshots(self): ) return - @attr(tags=["advanced", "advancedns", "smoke"]) + @attr(tags=["advanced", "advancedns", "smoke", "provisioning"]) def test_02_revert_vm_snapshots(self): """Test to revert VM snapshots """ @@ -203,8 +153,8 @@ def test_02_revert_vm_snapshots(self): 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"]) + "rm -rf %s/%s" % (self.test_dir, self.random_data), + "ls %s/%s" % (self.test_dir, self.random_data) ] for c in cmds: @@ -263,7 +213,7 @@ def test_02_revert_vm_snapshots(self): ssh_client = self.virtual_machine.get_ssh_client(reconnect=True) cmds = [ - "cat %s/%s" % (self.services["test_dir"], self.services["random_data"]) + "cat %s/%s" % (self.test_dir, self.random_data) ] for c in cmds: @@ -281,7 +231,7 @@ def test_02_revert_vm_snapshots(self): "Check the random data is equal with the ramdom file!" ) - @attr(tags=["advanced", "advancedns", "smoke"]) + @attr(tags=["advanced", "advancedns", "smoke", "provisioning"]) def test_03_delete_vm_snapshots(self): """Test to delete vm snapshots """ diff --git a/test/integration/smoke/test_volumes.py b/test/integration/smoke/test_volumes.py index 8f41803638..5908e2b5a5 100644 --- a/test/integration/smoke/test_volumes.py +++ b/test/integration/smoke/test_volumes.py @@ -17,14 +17,25 @@ """ BVT tests for Volumes """ #Import Local Modules -import marvin -from marvin.cloudstackTestCase import * -from marvin.cloudstackException import * -from marvin.cloudstackAPI import * -from marvin.sshClient import SshClient -from marvin.integration.lib.utils import * -from marvin.integration.lib.base import * -from marvin.integration.lib.common import * +from marvin.cloudstackTestCase import cloudstackTestCase +#from marvin.cloudstackException import * +from marvin.cloudstackAPI import (deleteVolume, + extractVolume, + resizeVolume) +#from marvin.sshClient import SshClient +from marvin.lib.utils import (cleanup_resources, + format_volume_to_ext3) +from marvin.lib.base import (ServiceOffering, + VirtualMachine, + Account, + Volume, + Host, + DiskOffering) +from marvin.lib.common import (get_domain, + get_zone, + get_template) +from marvin.lib.utils import checkVolumeSize +from marvin.codes import SUCCESS, FAILED from nose.plugins.attrib import attr #Import System modules import os @@ -34,103 +45,55 @@ _multiprocess_shared_ = True -class Services: - """Test Volume 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": 100, # in MHz - "memory": 260 # In MBs - - }, - "disk_offering": { - "displaytext": "Small", - "name": "Small", - "disksize": 1 - }, - 'resized_disk_offering': { - "displaytext": "Resized", - "name": "Resized", - "disksize": 3 - }, - "volume_offerings": { - 0: { - "diskname": "TestDiskServ", - }, - }, - "customdisksize": 1, # GBs - "username": "root", # Creds for SSH to VM - "password": "password", - "ssh_port": 22, - "diskname": "TestDiskServ", - "hypervisor": 'KVM', - "privateport": 22, - "publicport": 22, - "protocol": 'TCP', - "ostype": 'CentOS 5.5 (64-bit)', - "sleep": 10, - "timeout": 600, - } - - class TestCreateVolume(cloudstackTestCase): @classmethod def setUpClass(cls): - cls.api_client = super(TestCreateVolume, cls).getClsTestClient().getApiClient() - cls.services = Services().services - + testClient = super(TestCreateVolume, cls).getClsTestClient() + cls.apiclient = testClient.getApiClient() + cls.services = testClient.getParsedTestDataConfig() # Get Zone, Domain and templates - cls.domain = get_domain(cls.api_client, cls.services) - cls.zone = get_zone(cls.api_client, cls.services) + cls.domain = get_domain(cls.apiclient) + cls.zone = get_zone(cls.apiclient, testClient.getZoneForTests()) cls.services['mode'] = cls.zone.networktype cls.disk_offering = DiskOffering.create( - cls.api_client, + cls.apiclient, cls.services["disk_offering"] ) + cls.sparse_disk_offering = DiskOffering.create( + cls.apiclient, + cls.services["sparse_disk_offering"] + ) cls.custom_disk_offering = DiskOffering.create( - cls.api_client, + cls.apiclient, cls.services["disk_offering"], custom=True ) template = get_template( - cls.api_client, + cls.apiclient, cls.zone.id, cls.services["ostype"] ) + if template == FAILED: + assert False, "get_template() failed to return template with description %s" % cls.services["ostype"] + cls.services["domainid"] = cls.domain.id cls.services["zoneid"] = cls.zone.id cls.services["template"] = template.id cls.services["customdiskofferingid"] = cls.custom_disk_offering.id - + cls.services["diskname"] = cls.services["volume"]["diskname"] # Create VMs, NAT Rules etc cls.account = Account.create( - cls.api_client, + cls.apiclient, 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.apiclient, + cls.services["service_offerings"] ) cls.virtual_machine = VirtualMachine.create( - cls.api_client, + cls.apiclient, cls.services, accountid=cls.account.name, domainid=cls.account.domainid, @@ -150,7 +113,7 @@ def setUp(self): self.dbclient = self.testClient.getDbConnection() self.cleanup = [] - @attr(tags = ["advanced", "advancedns", "smoke", "basic"]) + @attr(tags = ["advanced", "advancedns", "smoke", "basic", "provisioning"]) def test_01_create_volume(self): """Test Volume creation for all Disk Offerings (incl. custom) """ @@ -172,6 +135,18 @@ def test_01_create_volume(self): self.debug("Created a volume with ID: %s" % volume.id) self.volumes.append(volume) + if self.virtual_machine.hypervisor == "KVM": + sparse_volume = Volume.create( + self.apiClient, + self.services, + zoneid=self.zone.id, + account=self.account.name, + domainid=self.account.domainid, + diskofferingid=self.sparse_disk_offering.id + ) + self.debug("Created a sparse volume: %s" % sparse_volume.id) + self.volumes.append(sparse_volume) + volume = Volume.create_custom_disk( self.apiClient, self.services, @@ -184,10 +159,9 @@ def test_01_create_volume(self): #Attach a volume with different disk offerings #and check the memory allocated to each of them for volume in self.volumes: - list_volume_response = list_volumes( - self.apiClient, - id=volume.id - ) + list_volume_response = Volume.list( + self.apiClient, + id=volume.id) self.assertEqual( isinstance(list_volume_response, list), True, @@ -221,13 +195,12 @@ def test_01_create_volume(self): time.sleep(self.services["sleep"]) # Ensure that VM is in running state - list_vm_response = list_virtual_machines( + list_vm_response = VirtualMachine.list( self.apiClient, id=self.virtual_machine.id ) if isinstance(list_vm_response, list): - vm = list_vm_response[0] if vm.state == 'Running': self.debug("VM state: %s" % vm.state) @@ -236,31 +209,17 @@ def test_01_create_volume(self): if timeout == 0: raise Exception( "Failed to start VM (ID: %s) " % vm.id) - timeout = timeout - 1 - try: - ssh = self.virtual_machine.get_ssh_client( + vol_sz = str(list_volume_response[0].size) + ssh = self.virtual_machine.get_ssh_client( reconnect=True ) - c = "/sbin/fdisk -l" - res = ssh.execute(c) - - except Exception as e: - self.fail("SSH access failed for VM: %s - %s" % - (self.virtual_machine.ipaddress, e)) - - # Disk /dev/sda doesn't contain a valid partition table - # Disk /dev/sda: 21.5 GB, 21474836480 bytes - result = str(res) - self.debug("fdisk result: %s" % result) - - self.assertEqual( - str(list_volume_response[0].size) in result, - True, - "Check if promised disk size actually available" - ) + ret = checkVolumeSize(ssh_handle=ssh,size_to_verify=vol_sz) + self.debug(" Volume Size Expected %s Actual :%s" %(vol_sz,ret[1])) self.virtual_machine.detach_volume(self.apiClient, volume) + self.assertEqual(ret[0],SUCCESS,"Check if promised disk size actually available") + time.sleep(self.services["sleep"]) def tearDown(self): #Clean up, terminate the created volumes @@ -270,8 +229,8 @@ def tearDown(self): @classmethod def tearDownClass(cls): try: - cls.api_client = super(TestCreateVolume, cls).getClsTestClient().getApiClient() - cleanup_resources(cls.api_client, cls._cleanup) + cls.apiclient = super(TestCreateVolume, cls).getClsTestClient().getApiClient() + cleanup_resources(cls.apiclient, cls._cleanup) except Exception as e: raise Exception("Warning: Exception during cleanup : %s" % e) @@ -280,31 +239,36 @@ class TestVolumes(cloudstackTestCase): @classmethod def setUpClass(cls): - cls.api_client = super(TestVolumes, cls).getClsTestClient().getApiClient() - cls.services = Services().services + testClient = super(TestVolumes, cls).getClsTestClient() + cls.apiclient = testClient.getApiClient() + cls.services = testClient.getParsedTestDataConfig() + # Get Zone, Domain and templates - cls.domain = get_domain(cls.api_client, cls.services) - cls.zone = get_zone(cls.api_client, cls.services) + cls.domain = get_domain(cls.apiclient) + cls.zone = get_zone(cls.apiclient, testClient.getZoneForTests()) cls.services['mode'] = cls.zone.networktype cls.disk_offering = DiskOffering.create( - cls.api_client, + cls.apiclient, cls.services["disk_offering"] ) cls.resized_disk_offering = DiskOffering.create( - cls.api_client, + cls.apiclient, cls.services["resized_disk_offering"] ) cls.custom_resized_disk_offering = DiskOffering.create( - cls.api_client, + cls.apiclient, cls.services["resized_disk_offering"], custom=True ) template = get_template( - cls.api_client, + cls.apiclient, cls.zone.id, cls.services["ostype"] ) + if template == FAILED: + assert False, "get_template() failed to return template with description %s" % cls.services["ostype"] + cls.services["domainid"] = cls.domain.id cls.services["zoneid"] = cls.zone.id cls.services["template"] = template.id @@ -314,18 +278,16 @@ def setUpClass(cls): # Create VMs, VMs etc cls.account = Account.create( - cls.api_client, + cls.apiclient, 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.apiclient, + cls.services["service_offerings"] ) cls.virtual_machine = VirtualMachine.create( - cls.api_client, + cls.apiclient, cls.services, accountid=cls.account.name, domainid=cls.account.domainid, @@ -334,7 +296,7 @@ def setUpClass(cls): ) cls.volume = Volume.create( - cls.api_client, + cls.apiclient, cls.services, account=cls.account.name, domainid=cls.account.domainid @@ -351,7 +313,7 @@ def setUpClass(cls): @classmethod def tearDownClass(cls): try: - cleanup_resources(cls.api_client, cls._cleanup) + cleanup_resources(cls.apiclient, cls._cleanup) except Exception as e: raise Exception("Warning: Exception during cleanup : %s" % e) @@ -368,7 +330,7 @@ def tearDown(self): cleanup_resources(self.apiClient, self.cleanup) return - @attr(tags = ["advanced", "advancedns", "smoke", "basic"]) + @attr(tags = ["advanced", "advancedns", "smoke", "basic", "provisioning"]) def test_02_attach_volume(self): """Attach a created Volume to a Running VM """ @@ -384,7 +346,7 @@ def test_02_attach_volume(self): )) self.virtual_machine.attach_volume(self.apiClient, self.volume) self.attached = True - list_volume_response = list_volumes( + list_volume_response = Volume.list( self.apiClient, id=self.volume.id ) @@ -414,7 +376,7 @@ def test_02_attach_volume(self): (self.virtual_machine.ipaddress, e)) return - @attr(tags = ["advanced", "advancedns", "smoke", "basic"]) + @attr(tags = ["advanced", "advancedns", "smoke", "basic", "selfservice"]) def test_03_download_attached_volume(self): """Download a Volume attached to a VM """ @@ -436,7 +398,7 @@ def test_03_download_attached_volume(self): with self.assertRaises(Exception): self.apiClient.extractVolume(cmd) - @attr(tags = ["advanced", "advancedns", "smoke", "basic"]) + @attr(tags = ["advanced", "advancedns", "smoke", "basic", "selfservice"]) def test_04_delete_attached_volume(self): """Delete a Volume attached to a VM """ @@ -457,7 +419,7 @@ def test_04_delete_attached_volume(self): with self.assertRaises(Exception): self.apiClient.deleteVolume(cmd) - @attr(tags = ["advanced", "advancedns", "smoke", "basic"]) + @attr(tags = ["advanced", "advancedns", "smoke", "basic", "selfservice"]) def test_05_detach_volume(self): """Detach a Volume attached to a VM """ @@ -476,7 +438,7 @@ def test_05_detach_volume(self): self.attached = False #Sleep to ensure the current state will reflected in other calls time.sleep(self.services["sleep"]) - list_volume_response = list_volumes( + list_volume_response = Volume.list( self.apiClient, id=self.volume.id ) @@ -499,7 +461,7 @@ def test_05_detach_volume(self): ) return - @attr(tags = ["advanced", "advancedns", "smoke", "basic"]) + @attr(tags = ["advanced", "advancedns", "smoke", "basic", "provisioning"]) def test_06_download_detached_volume(self): """Download a Volume unattached to an VM """ @@ -536,7 +498,7 @@ def test_06_download_detached_volume(self): % (extract_vol.url, self.volume.id) ) - @attr(tags = ["advanced", "advancedns", "smoke", "basic"]) + @attr(tags = ["advanced", "advancedns", "smoke", "basic", "selfservice"]) def test_07_resize_fail(self): """Test resize (negative) non-existent volume""" # Verify the size is the new size is what we wanted it to be. @@ -548,7 +510,7 @@ def test_07_resize_fail(self): cmd.diskofferingid = self.services['resizeddiskofferingid'] success = False try: - response = self.apiClient.resizeVolume(cmd) + self.apiClient.resizeVolume(cmd) except Exception as ex: #print str(ex) if "invalid" in str(ex): @@ -563,7 +525,7 @@ def test_07_resize_fail(self): cmd.diskofferingid = "invalid id" success = False try: - response = self.apiClient.resizeVolume(cmd) + self.apiClient.resizeVolume(cmd) except Exception as ex: if "invalid" in str(ex): success = True @@ -571,6 +533,31 @@ def test_07_resize_fail(self): success, True, "ResizeVolume - verify disk offering is handled appropriately") + + # try to resize a root disk with a disk offering, root can only be resized by size= + # get root vol from created vm + list_volume_response = Volume.list( + self.apiClient, + virtualmachineid=self.virtual_machine.id, + type='ROOT', + listall=True + ) + + rootvolume = list_volume_response[0] + + cmd.id = rootvolume.id + cmd.diskofferingid = self.services['diskofferingid'] + success = False + try: + self.apiClient.resizeVolume(cmd) + except Exception as ex: + if "Can only resize Data volumes" in str(ex): + success = True + self.assertEqual( + success, + True, + "ResizeVolume - verify root disks cannot be resized by disk offering id") + # Ok, now let's try and resize a volume that is not custom. cmd.id = self.volume.id cmd.diskofferingid = self.services['diskofferingid'] @@ -600,7 +587,7 @@ def test_07_resize_fail(self): count = 0 success = True while count < 10: - list_volume_response = list_volumes( + list_volume_response = Volume.list( self.apiClient, id=self.volume.id, type='DATADISK' @@ -625,7 +612,7 @@ def test_07_resize_fail(self): return - @attr(tags = ["advanced", "advancedns", "smoke", "basic"]) + @attr(tags = ["advanced", "advancedns", "smoke", "basic", "provisioning"]) def test_08_resize_volume(self): """Test resize a volume""" # Verify the size is the new size is what we wanted it to be. @@ -647,6 +634,7 @@ def test_08_resize_volume(self): elif hosts[0].hypervisor.lower() == "vmware": self.skipTest("Resize Volume is unsupported on VmWare") + # resize the data disk self.debug("Resize Volume ID: %s" % self.volume.id) cmd = resizeVolume.resizeVolumeCmd() @@ -658,7 +646,7 @@ def test_08_resize_volume(self): count = 0 success = False while count < 3: - list_volume_response = list_volumes( + list_volume_response = Volume.list( self.apiClient, id=self.volume.id, type='DATADISK' @@ -675,7 +663,48 @@ def test_08_resize_volume(self): self.assertEqual( success, True, - "Check if the volume resized appropriately" + "Check if the data volume resized appropriately" + ) + + # resize the root disk + self.debug("Resize Root for : %s" % self.virtual_machine.id) + + # get root vol from created vm + list_volume_response = Volume.list( + self.apiClient, + virtualmachineid=self.virtual_machine.id, + type='ROOT', + listall=True + ) + + rootvolume = list_volume_response[0] + + cmd = resizeVolume.resizeVolumeCmd() + cmd.id = rootvolume.id + cmd.size = 10 + + self.apiClient.resizeVolume(cmd) + + count = 0 + success = False + while count < 3: + list_volume_response = Volume.list( + self.apiClient, + id=rootvolume.id + ) + for vol in list_volume_response: + if vol.id == rootvolume.id and vol.size == 10737418240L and vol.state == 'Ready': + success = True + if success: + break + else: + time.sleep(10) + count += 1 + + self.assertEqual( + success, + True, + "Check if the root volume resized appropriately" ) #start the vm if it is on xenserver @@ -685,7 +714,7 @@ def test_08_resize_volume(self): time.sleep(30) return - @attr(tags = ["advanced", "advancedns", "smoke","basic"]) + @attr(tags = ["advanced", "advancedns", "smoke","basic", "selfservice"]) def test_09_delete_detached_volume(self): """Delete a Volume unattached to an VM """ @@ -699,7 +728,7 @@ def test_09_delete_detached_volume(self): self.debug("Delete Volume ID: %s" % self.volume.id) self.volume_1 = Volume.create( - self.api_client, + self.apiclient, self.services, account=self.account.name, domainid=self.account.domainid @@ -712,7 +741,7 @@ def test_09_delete_detached_volume(self): cmd.id = self.volume_1.id self.apiClient.deleteVolume(cmd) - list_volume_response = list_volumes( + list_volume_response = Volume.list( self.apiClient, id=self.volume_1.id, type='DATADISK' diff --git a/test/integration/smoke/test_vpc_vpn.py b/test/integration/smoke/test_vpc_vpn.py index 5e97c79065..03826e95de 100644 --- a/test/integration/smoke/test_vpc_vpn.py +++ b/test/integration/smoke/test_vpc_vpn.py @@ -17,105 +17,29 @@ """ Tests for VPN in VPC """ #Import Local Modules +from marvin.codes import FAILED 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.lib.utils import * +from marvin.lib.base import * +from marvin.lib.common import * from nose.plugins.attrib import attr import time -class Services: - def __init__(self): - self.services = { - "account": { - "email": "test@test.com", - "firstname": "Test", - "lastname": "User", - "username": "test", - "password": "password", - }, - "virtual_machine": { - "displayname": "Test VM", - "username": "root", - "password": "password", - "ssh_port": 22, - "hypervisor": 'XenServer', - "privateport": 22, - "publicport": 22, - "protocol": 'TCP', - }, - "ostype": 'CentOS 5.3 (64-bit)', - "service_offering": { - "name": "Tiny Instance", - "displaytext": "Tiny Instance", - "cpunumber": 1, - "cpuspeed": 100, - "memory": 256, - }, - "network_offering": { - "name": "Network offering for internal vpc", - "displaytext": "Network offering for internal vpc", - "guestiptype": "Isolated", - "traffictype": "Guest", - "supportedservices": "Vpn,Dhcp,Dns,Lb,UserData,SourceNat,StaticNat,PortForwarding,NetworkACL", - "serviceProviderList": { - "Dhcp": "VpcVirtualRouter", - "Dns": "VpcVirtualRouter", - "Vpn": "VpcVirtualRouter", - "UserData": "VpcVirtualRouter", - "Lb": "InternalLbVM", - "SourceNat": "VpcVirtualRouter", - "StaticNat": "VpcVirtualRouter", - "PortForwarding": "VpcVirtualRouter", - "NetworkACL": "VpcVirtualRouter", - }, - "serviceCapabilityList": { - "SourceNat": {"SupportedSourceNatTypes": "peraccount"}, - "Lb": {"lbSchemes": "internal", "SupportedLbIsolation": "dedicated"} - } - }, - "vpn_user": { - "username": "test", - "password": "password", - }, - "vpc": { - "name": "vpc_vpn", - "displaytext": "vpc-vpn", - "cidr": "10.1.1.0/24" - }, - "ntwk": { - "name": "tier1", - "displaytext": "vpc-tier1", - "gateway" : "10.1.1.1", - "netmask" : "255.255.255.192" - }, - "vpc2": { - "name": "vpc2_vpn", - "displaytext": "vpc2-vpn", - "cidr": "10.2.1.0/24" - }, - "ntwk2": { - "name": "tier2", - "displaytext": "vpc-tier2", - "gateway" : "10.2.1.1", - "netmask" : "255.255.255.192" - } - } - - class TestVpcRemoteAccessVpn(cloudstackTestCase): @classmethod def setUpClass(cls): - cls.apiclient = super(TestVpcRemoteAccessVpn, cls).getClsTestClient().getApiClient() - cls.services = Services().services - cls.zone = get_zone(cls.apiclient, cls.services) + testClient = super(TestVpcRemoteAccessVpn, cls).getClsTestClient() + cls.apiclient = testClient.getApiClient() + cls.services = testClient.getParsedTestDataConfig() + + cls.zone = get_zone(cls.apiclient, testClient.getZoneForTests()) cls.domain = get_domain(cls.apiclient) cls.service_offering = ServiceOffering.create( cls.apiclient, - cls.services["service_offering"] + cls.services["service_offerings"] ) cls.account = Account.create(cls.apiclient, services=cls.services["account"]) cls.template = get_template( @@ -123,9 +47,12 @@ def setUpClass(cls): cls.zone.id, cls.services["ostype"] ) + if cls.template == FAILED: + assert False, "get_template() failed to return template with description %s" % cls.services["ostype"] + cls.cleanup = [cls.account] - @attr(tags=["advanced"]) + @attr(tags=["advanced", "selfservice"]) def test_vpc_remote_access_vpn(self): """Test VPN in VPC""" @@ -211,13 +138,15 @@ class TestVpcSite2SiteVpn(cloudstackTestCase): @classmethod def setUpClass(cls): - cls.apiclient = super(TestVpcSite2SiteVpn, cls).getClsTestClient().getApiClient() - cls.services = Services().services - cls.zone = get_zone(cls.apiclient, cls.services) + testClient = super(TestVpcSite2SiteVpn, cls).getClsTestClient() + cls.apiclient = testClient.getApiClient() + cls.services = testClient.getParsedTestDataConfig() + + cls.zone = get_zone(cls.apiclient, testClient.getZoneForTests()) cls.domain = get_domain(cls.apiclient) cls.service_offering = ServiceOffering.create( cls.apiclient, - cls.services["service_offering"] + cls.services["service_offerings"] ) cls.account = Account.create(cls.apiclient, services=cls.services["account"]) cls.template = get_template( @@ -225,9 +154,12 @@ def setUpClass(cls): cls.zone.id, cls.services["ostype"] ) + if cls.template == FAILED: + assert False, "get_template() failed to return template with description %s" % cls.services["ostype"] + cls.cleanup = [cls.account] - @attr(tags=["advanced"]) + @attr(tags=["advanced", "selfservice"]) def test_vpc_site2site_vpn(self): """Test VPN in VPC""" diff --git a/tools/appliance/definitions/systemvm64template/definition.rb b/tools/appliance/definitions/systemvm64template/definition.rb index bea2fdebbe..f9308a0558 100644 --- a/tools/appliance/definitions/systemvm64template/definition.rb +++ b/tools/appliance/definitions/systemvm64template/definition.rb @@ -4,7 +4,7 @@ :disk_size => '2500', :disk_format => 'VDI', :hostiocache => 'off', :os_type_id => 'Debian_64', :iso_file => "debian-7.4.0-amd64-netinst.iso", - :iso_src => "http://ftp.acc.umu.se/mirror/cdimage/release/7.4.0/amd64/iso-cd/debian-7.4.0-amd64-netinst.iso", + :iso_src => "http://cdimage.debian.org/mirror/cdimage/archive/7.4.0/amd64/iso-cd/debian-7.4.0-amd64-netinst.iso", :iso_md5 => "e7e9433973f082a297793c3c5010b2c5", :iso_download_timeout => "1000", :boot_wait => "10", :boot_cmd_sequence => [ diff --git a/tools/appliance/definitions/systemvm64template/postinstall.sh b/tools/appliance/definitions/systemvm64template/postinstall.sh index cc8ead9d94..f6e6cdd1fe 100644 --- a/tools/appliance/definitions/systemvm64template/postinstall.sh +++ b/tools/appliance/definitions/systemvm64template/postinstall.sh @@ -81,7 +81,7 @@ install_packages() { dpkg -i hv-kvp-daemon_3.1_amd64.deb #libraries required for rdp client (Hyper-V) - apt-get --no-install-recommends -q -y --force-yes install libtcnative-1 libssl-dev libapr1-dev + DEBIAN_FRONTEND=noninteractive apt-get --no-install-recommends -qq -y --force-yes install libtcnative-1 libssl-dev libapr1-dev # vmware tools apt-get --no-install-recommends -q -y --force-yes install open-vm-tools diff --git a/tools/appliance/definitions/systemvmtemplate/definition.rb b/tools/appliance/definitions/systemvmtemplate/definition.rb index c8b24d6268..fcaab4d0c3 100644 --- a/tools/appliance/definitions/systemvmtemplate/definition.rb +++ b/tools/appliance/definitions/systemvmtemplate/definition.rb @@ -4,7 +4,7 @@ :disk_size => '2500', :disk_format => 'VDI', :hostiocache => 'off', :os_type_id => 'Debian', :iso_file => "debian-7.4.0-i386-netinst.iso", - :iso_src => "http://ftp.acc.umu.se/mirror/cdimage/release/7.4.0/i386/iso-cd/debian-7.4.0-i386-netinst.iso", + :iso_src => "http://cdimage.debian.org/mirror/cdimage/archive/7.4.0/i386/iso-cd/debian-7.4.0-i386-netinst.iso", :iso_md5 => "7339b668a81b417ac023d73739dc6a03", :iso_download_timeout => "1000", :boot_wait => "10", :boot_cmd_sequence => [ diff --git a/tools/devcloud-kvm/devcloud-kvm-advanced-fusion.cfg b/tools/devcloud-kvm/devcloud-kvm-advanced-fusion.cfg index 53e1a441b2..2084417cbe 100644 --- a/tools/devcloud-kvm/devcloud-kvm-advanced-fusion.cfg +++ b/tools/devcloud-kvm/devcloud-kvm-advanced-fusion.cfg @@ -120,20 +120,14 @@ "port": 3306, "user": "cloud" }, - "logger": [ - { - "name": "TestClient", - "file": "/var/log/testclient.log" - }, - { - "name": "TestCase", - "file": "/var/log/testcase.log" - } - ], + "logger": { + "LogFolderPath": "/tmp/" + }, "mgtSvr": [ { "mgtSvrIp": "172.17.10.10", - "port": 8096 + "port": 8096, + "hypervisor": "kvm" } ] } diff --git a/tools/devcloud-kvm/devcloud-kvm-advanced.cfg b/tools/devcloud-kvm/devcloud-kvm-advanced.cfg index 53e1a441b2..74c36b718d 100644 --- a/tools/devcloud-kvm/devcloud-kvm-advanced.cfg +++ b/tools/devcloud-kvm/devcloud-kvm-advanced.cfg @@ -133,7 +133,8 @@ "mgtSvr": [ { "mgtSvrIp": "172.17.10.10", - "port": 8096 + "port": 8096, + "hypervisor": "kvm" } ] } diff --git a/tools/devcloud-kvm/devcloud-kvm.cfg b/tools/devcloud-kvm/devcloud-kvm.cfg index 3122e5a979..ab7f9a5276 100644 --- a/tools/devcloud-kvm/devcloud-kvm.cfg +++ b/tools/devcloud-kvm/devcloud-kvm.cfg @@ -104,7 +104,8 @@ "mgtSvr": [ { "mgtSvrIp": "127.0.0.1", - "port": 8096 + "port": 8096, + "hypervisor": "kvm" } ], "dbSvr": diff --git a/tools/devcloud/devcloud-advanced_juniper-contrail.cfg b/tools/devcloud/devcloud-advanced_juniper-contrail.cfg new file mode 100644 index 0000000000..35b551a2aa --- /dev/null +++ b/tools/devcloud/devcloud-advanced_juniper-contrail.cfg @@ -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. +# +# This configuration is meant for running advanced networking , with management server on the laptop, +# It requires that the user run a DNS resolver within devcloud via 'apt-get install dnsmasq' +# +# +{ + "zones": [ + { + "localstorageenabled": "true", + "name": "default", + "dns1": "8.8.8.8", + "physical_networks": [ + { + "broadcastdomainrange": "Zone", + "name": "ip-fabric", + "traffictypes": [ + { + "xen": "Pool-wide network associated with eth0", + "typ": "Management" + }, + { + "xen": "Pool-wide network associated with eth0", + "typ": "Guest" + }, + { + "xen": "Pool-wide network associated with eth1", + "typ": "Public" + } + ], + "providers": [ + { + "broadcastdomainrange": "ZONE", + "name": "JuniperContrailRouter" + } + ], + "isolationmethods": [ + "L3VPN" + ] + } + ], + "ipranges": [ + { + "startip": "10.0.3.100", + "endip": "10.0.3.199", + "netmask": "255.255.255.0", + "vlan": "untagged", + "gateway": "10.0.3.2" + } + ], + "networktype": "Advanced", + "pods": [ + { + "endip": "192.168.56.249", + "name": "a6", + "startip": "192.168.56.200", + "netmask": "255.255.255.0", + "clusters": [ + { + "clustername": "a6-xen", + "hypervisor": "XenServer", + "hosts": [ + { + "username": "root", + "url": "http://192.168.56.10/", + "password": "password" + } + ], + "clustertype": "CloudManaged" + } + ], + "gateway": "192.168.56.1" + } + ], + "internaldns1": "192.168.56.10", + "secondaryStorages": [ + { + "url": "nfs://192.168.56.10:/opt/storage/secondary", + "provider": "NFS", + "details": [ ] + } + ] + } + ], + "dbSvr": { + "dbSvr": "127.0.0.1", + "passwd": "cloud", + "db": "cloud", + "port": 3306, + "user": "cloud" + }, + "logger": [ + { + "name": "TestClient", + "file": "/var/log/testclient.log" + }, + { + "name": "TestCase", + "file": "/var/log/testcase.log" + } + ], + "mgtSvr": [ + { + "mgtSvrIp": "127.0.0.1", + "port": 8096 + } + ] +} diff --git a/tools/marvin/marvin/__init__.py b/tools/marvin/marvin/__init__.py index 7af168e20b..7102e3f310 100644 --- a/tools/marvin/marvin/__init__.py +++ b/tools/marvin/marvin/__init__.py @@ -15,4 +15,4 @@ # specific language governing permissions and limitations # under the License. -#Marvin - The cloudstack test client +# Marvin - The cloudstack test client diff --git a/tools/marvin/marvin/asyncJobMgr.py b/tools/marvin/marvin/asyncJobMgr.py index e24170e18f..00e8c19b3c 100644 --- a/tools/marvin/marvin/asyncJobMgr.py +++ b/tools/marvin/marvin/asyncJobMgr.py @@ -16,7 +16,7 @@ # under the License. import threading -import cloudstackException +from marvin import cloudstackException import time import Queue import copy @@ -26,12 +26,14 @@ class job(object): + def __init__(self): self.id = None self.cmd = None class jobStatus(object): + def __init__(self): self.result = None self.status = None @@ -47,6 +49,7 @@ def __str__(self): class workThread(threading.Thread): + def __init__(self, in_queue, outqueue, apiClient, db=None, lock=None): threading.Thread.__init__(self) self.inqueue = in_queue @@ -62,7 +65,7 @@ def queryAsynJob(self, job): try: self.lock.acquire() result = self.connection.poll(job.jobId, job.responsecls).jobresult - except cloudstackException.cloudstackAPIException, e: + except cloudstackException.CloudstackAPIException as e: result = str(e) finally: self.lock.release() @@ -102,7 +105,7 @@ def executeCmd(self, job): except: pass jobstatus.status = True - except cloudstackException.cloudstackAPIException, e: + except cloudstackException.CloudstackAPIException as e: jobstatus.result = str(e) jobstatus.status = False except: @@ -129,6 +132,7 @@ def run(self): class jobThread(threading.Thread): + def __init__(self, inqueue, interval): threading.Thread.__init__(self) self.inqueue = inqueue @@ -149,12 +153,14 @@ def run(self): class outputDict(object): + def __init__(self): self.lock = threading.Condition() self.dict = {} class asyncJobMgr(object): + def __init__(self, apiClient, db): self.inqueue = Queue.Queue() self.output = outputDict() diff --git a/tools/marvin/marvin/cloudstackConnection.py b/tools/marvin/marvin/cloudstackConnection.py index fb03e3be3a..8044da7ec6 100644 --- a/tools/marvin/marvin/cloudstackConnection.py +++ b/tools/marvin/marvin/cloudstackConnection.py @@ -21,21 +21,37 @@ import hmac import hashlib import time -import cloudstackException from cloudstackAPI import * import jsonHelper +from marvin.codes import ( + FAILED, + INVALID_RESPONSE, + INVALID_INPUT, + JOB_FAILED, + JOB_INPROGRESS, + JOB_CANCELLED, + JOB_SUCCEEDED +) from requests import ( ConnectionError, HTTPError, Timeout, RequestException - ) +) +from marvin.cloudstackException import ( + InvalidParameterException, + GetDetailExceptionInfo) -class cloudConnection(object): +class CSConnection(object): + + ''' + @Desc: Connection Class to make API\Command calls to the + CloudStack Management Server + Sends the GET\POST requests to CS based upon the + information provided and retrieves the parsed response. + ''' - """ Connections to make API calls to the cloudstack management server - """ def __init__(self, mgmtDet, asyncTimeout=3600, logger=None, path='client/api'): self.apiKey = mgmtDet.apiKey @@ -44,238 +60,326 @@ def __init__(self, mgmtDet, asyncTimeout=3600, logger=None, self.port = mgmtDet.port self.user = mgmtDet.user self.passwd = mgmtDet.passwd - self.certCAPath = mgmtDet.certCAPath - self.certPath = mgmtDet.certPath + self.certPath = () + if mgmtDet.certCAPath != "NA" and mgmtDet.certPath != "NA": + self.certPath = (mgmtDet.certCAPath, mgmtDet.certPath) self.logger = logger self.path = path self.retries = 5 + self.__lastError = '' self.mgtDetails = mgmtDet - self.protocol = "http" self.asyncTimeout = asyncTimeout self.auth = True if self.port == 8096 or \ (self.apiKey is None and self.securityKey is None): self.auth = False - if mgmtDet.useHttps == "True": - self.protocol = "https" - self.baseurl = "%s://%s:%d/%s"\ + self.protocol = "https" if mgmtDet.useHttps == "True" else "http" + self.httpsFlag = True if self.protocol == "https" else False + self.baseUrl = "%s://%s:%d/%s"\ % (self.protocol, self.mgtSvr, self.port, self.path) def __copy__(self): - return cloudConnection(self.mgtDetails, - self.asyncTimeout, - self.logger, - self.path) - - def poll(self, jobid, response): - """ - polls the completion of a given jobid - @param jobid: - @param response: - @return: - """ - cmd = queryAsyncJobResult.queryAsyncJobResultCmd() - cmd.jobid = jobid - timeout = self.asyncTimeout - - while timeout > 0: - asyncResonse = self.marvinRequest(cmd, response_type=response) + return CSConnection(self.mgtDetails, + self.asyncTimeout, + self.logger, + self.path) - if asyncResonse.jobstatus == 2: - raise cloudstackException.cloudstackAPIException( - "asyncquery", asyncResonse.jobresult) - elif asyncResonse.jobstatus == 1: - return asyncResonse - - time.sleep(5) - if self.logger is not None: - self.logger.debug("job: %s still processing," - "will timeout in %ds" % (jobid, timeout)) - timeout = timeout - 5 + def __poll(self, jobid, response_cmd): + ''' + @Name : __poll + @Desc: polls for the completion of a given jobid + @Input 1. jobid: Monitor the Jobid for CS + 2. response_cmd:response command for request cmd + @return: FAILED if jobid is cancelled,failed + Else return async_response + ''' + try: + cmd = queryAsyncJobResult.queryAsyncJobResultCmd() + cmd.jobid = jobid + timeout = self.asyncTimeout + start_time = time.time() + end_time = time.time() + async_response = FAILED + self.logger.debug("=== Jobid: %s Started ===" % (str(jobid))) + while timeout > 0: + async_response = self.\ + marvinRequest(cmd, response_type=response_cmd) + if async_response != FAILED: + job_status = async_response.jobstatus + if job_status in [JOB_FAILED, + JOB_CANCELLED, + JOB_SUCCEEDED]: + break + time.sleep(5) + timeout -= 5 + self.logger.debug("=== JobId:%s is Still Processing, " + "Will TimeOut in:%s ====" % (str(jobid), + str(timeout))) + end_time = time.time() + tot_time = int(start_time - end_time) + self.logger.debug( + "===Jobid:%s ; StartTime:%s ; EndTime:%s ; " + "TotalTime:%s===" % + (str(jobid), str(time.ctime(start_time)), + str(time.ctime(end_time)), str(tot_time))) + return async_response + except Exception as e: + self.__lastError = e + self.logger.exception("==== __poll: Exception Occurred :%s ====" % + str(self.__lastError)) + return FAILED - raise cloudstackException.cloudstackAPIException( - "asyncquery", "Async job timeout %s" % jobid) + def getLastError(self): + ''' + @Name : getLastError + @Desc : Returns the last error from marvinRequest + ''' + return self.__lastError - def sign(self, payload): + def __sign(self, payload): """ - signs a given request URL when the apiKey and secretKey are known - - @param payload: dict of GET params to be signed - @return: the signature of the payload + @Name : __sign + @Desc:signs a given request URL when the apiKey and + secretKey are known + @Input: payload: dictionary of params be signed + @Output: the signature of the payload """ params = zip(payload.keys(), payload.values()) params.sort(key=lambda k: str.lower(k[0])) - hashStr = "&".join( + hash_str = "&".join( ["=".join( [str.lower(r[0]), str.lower( urllib.quote_plus(str(r[1])) - ).replace("+", "%20")] + ).replace("+", "%20")] ) for r in params] ) signature = base64.encodestring(hmac.new( - self.securityKey, hashStr, hashlib.sha1).digest()).strip() - self.logger.debug("Computed Signature by Marvin: %s" % signature) + self.securityKey, hash_str, hashlib.sha1).digest()).strip() return signature - def request(self, command, auth=True, payload={}, method='GET'): + def __sendPostReqToCS(self, url, payload): + ''' + @Name : __sendPostReqToCS + @Desc : Sends the POST Request to CS + @Input : url: URL to send post req + payload:Payload information as part of request + @Output: Returns response from POST output + else FAILED + ''' + try: + response = requests.post(url, + params=payload, + cert=self.certPath, + verify=self.httpsFlag) + return response + except Exception as e: + self.__lastError = e + self.logger.\ + exception("__sendPostReqToCS : Exception " + "Occurred: %s" % str(self.__lastError)) + return FAILED + + def __sendGetReqToCS(self, url, payload): + ''' + @Name : __sendGetReqToCS + @Desc : Sends the GET Request to CS + @Input : url: URL to send post req + payload:Payload information as part of request + @Output: Returns response from GET output + else FAILED + ''' + try: + response = requests.get(url, + params=payload, + cert=self.certPath, + verify=self.httpsFlag) + return response + except Exception as e: + self.__lastError = e + self.logger.exception("__sendGetReqToCS : Exception Occurred: %s" % + str(self.__lastError)) + return FAILED + + def __sendCmdToCS(self, command, auth=True, payload={}, method='GET'): """ - Makes requests using auth or over integration port - @param command: cloudstack API command name + @Name : __sendCmdToCS + @Desc : Makes requests to CS using the Inputs provided + @Input: command: cloudstack API command name eg: deployVirtualMachineCommand - @param auth: Authentication (apikey,secretKey) => True + auth: Authentication (apikey,secretKey) => True else False for integration.api.port - @param payload: request data composed as a dictionary - @param method: GET/POST via HTTP - @return: + payload: request data composed as a dictionary + method: GET/POST via HTTP + @output: FAILED or else response from CS """ - payload["command"] = command - payload["response"] = "json" - - if auth: - payload["apiKey"] = self.apiKey - signature = self.sign(payload) - payload["signature"] = signature - try: - #https_flag : Signifies whether to verify connection over \ - #http or https, \ - #initialized to False, will be set to true if user provided https - #connection - https_flag = False - cert_path = () - if self.protocol == "https": - https_flag = True - if self.certCAPath != "NA" and self.certPath != "NA": - cert_path = (self.certCAPath, self.certPath) + payload["command"] = command + payload["response"] = "json" + + if auth: + payload["apiKey"] = self.apiKey + payload["signature"] = self.__sign(payload) - #Verify whether protocol is "http", then call the request over http - if self.protocol == "http": + # Verify whether protocol is "http" or "https", then send the + # request + if self.protocol in ["http", "https"]: + self.logger.debug("Payload: %s" % str(payload)) if method == 'POST': - response = requests.post(self.baseurl, params=payload, - verify=https_flag) - else: - response = requests.get(self.baseurl, params=payload, - verify=https_flag) + self.logger.debug("=======Sending POST Cmd : %s=======" + % str(command)) + return self.__sendPostReqToCS(self.baseUrl, payload) + if method == "GET": + self.logger.debug("========Sending GET Cmd : %s=======" + % str(command)) + return self.__sendGetReqToCS(self.baseUrl, payload) else: - ''' - If protocol is https, then create the connection url with \ - user provided certificates \ - provided as part of cert - ''' - try: - if method == 'POST': - response = requests.post(self.baseurl, - params=payload, - cert=cert_path, - verify=https_flag) - else: - response = requests.get(self.baseurl, params=payload, - cert=cert_path, - verify=https_flag) - except Exception, e: - ''' - If an exception occurs with user provided CA certs, \ - then try with default certs, \ - we dont need to mention here the cert path - ''' - self.logger.debug("Creating CS connection over https \ - didnt worked with user provided certs \ - , so trying with no certs %s" % e) - if method == 'POST': - response = requests.post(self.baseurl, - params=payload, - verify=https_flag) - else: - response = requests.get(self.baseurl, - params=payload, - verify=https_flag) - except ConnectionError, c: - self.logger.debug("Connection refused. Reason: %s : %s" % - (self.baseurl, c)) - raise c - except HTTPError, h: - self.logger.debug("Http Error.Server returned error code: %s" % h) - raise h - except Timeout, t: - self.logger.debug("Connection timed out with %s" % t) - raise t - except RequestException, r: - self.logger.debug("RequestException from server %s" % r) - raise r - except Exception, e: - self.logger.debug("Error returned by server %s" % r) - raise e - else: - return response + self.logger.exception("__sendCmdToCS: Invalid Protocol") + return FAILED + except Exception as e: + self.__lastError = e + self.logger.exception("__sendCmdToCS: Exception:%s" % + GetDetailExceptionInfo(e)) + return FAILED - def sanitizeCommand(self, cmd): + def __sanitizeCmd(self, cmd): """ - Removes None values, Validates all required params are present - @param cmd: Cmd object eg: createPhysicalNetwork - @return: + @Name : __sanitizeCmd + @Desc : Removes None values, Validates all required params are present + @Input: cmd: Cmd object eg: createPhysicalNetwork + @Output: Returns command name, asynchronous or not,request payload + FAILED for failed cases """ - requests = {} - required = [] - for attribute in dir(cmd): - if not attribute.startswith('__'): - if attribute == "isAsync": - isAsync = getattr(cmd, attribute) - elif attribute == "required": - required = getattr(cmd, attribute) - else: - requests[attribute] = getattr(cmd, attribute) - - cmdname = cmd.__class__.__name__.replace("Cmd", "") - for requiredPara in required: - if requests[requiredPara] is None: - raise cloudstackException.cloudstackAPIException( - cmdname, "%s is required" % requiredPara) - for param, value in requests.items(): - if value is None: - requests.pop(param) - elif isinstance(value, list): - if len(value) == 0: - requests.pop(param) - else: - if not isinstance(value[0], dict): - requests[param] = ",".join(value) + try: + cmd_name = '' + payload = {} + required = [] + isAsync = "false" + for attribute in dir(cmd): + if not attribute.startswith('__'): + if attribute == "isAsync": + isAsync = getattr(cmd, attribute) + elif attribute == "required": + required = getattr(cmd, attribute) else: - requests.pop(param) - i = 0 - for val in value: - for k, v in val.iteritems(): - requests["%s[%d].%s" % (param, i, k)] = v - i = i + 1 - return cmdname.strip(), isAsync, requests + payload[attribute] = getattr(cmd, attribute) + cmd_name = cmd.__class__.__name__.replace("Cmd", "") + for required_param in required: + if payload[required_param] is None: + self.logger.debug("CmdName: %s Parameter : %s is Required" + % (cmd_name, required_param)) + self.__lastError = InvalidParameterException( + "Invalid Parameters") + return FAILED + for param, value in payload.items(): + if value is None: + payload.pop(param) + elif isinstance(value, list): + if len(value) == 0: + payload.pop(param) + else: + if not isinstance(value[0], dict): + payload[param] = ",".join(value) + else: + payload.pop(param) + i = 0 + for val in value: + for k, v in val.iteritems(): + payload["%s[%d].%s" % (param, i, k)] = v + i += 1 + return cmd_name.strip(), isAsync, payload + except Exception as e: + self.__lastError = e + self.logger.\ + exception("__sanitizeCmd: CmdName : " + "%s : Exception:%s" % (cmd_name, + GetDetailExceptionInfo(e))) + return FAILED + + def __parseAndGetResponse(self, cmd_response, response_cls, is_async): + ''' + @Name : __parseAndGetResponse + @Desc : Verifies the Response(from CS) and returns an + appropriate json parsed Response + @Input: cmd_response: Command Response from cs + response_cls : Mapping class for this Response + is_async: Whether the cmd is async or not. + @Output:Response output from CS + ''' + try: + try: + ret = jsonHelper.getResultObj( + cmd_response.json(), + response_cls) + except TypeError: + ret = jsonHelper.getResultObj(cmd_response.json, response_cls) + + ''' + If the response is asynchronous, poll and return response + else return response as it is + ''' + if is_async == "false": + self.logger.debug("Response : %s" % str(ret)) + return ret + else: + response = self.__poll(ret.jobid, response_cls) + self.logger.debug("Response : %s" % str(response)) + return response.jobresult if response != FAILED else FAILED + except Exception as e: + self.__lastError = e + self.logger.\ + exception("Exception:%s" % GetDetailExceptionInfo(e)) + return FAILED def marvinRequest(self, cmd, response_type=None, method='GET', data=''): """ - Requester for marvin command objects - @param cmd: marvin's command from cloudstackAPI - @param response_type: response type of the command in cmd - @param method: HTTP GET/POST, defaults to GET - @return: + @Name : marvinRequest + @Desc: Handles Marvin Requests + @Input cmd: marvin's command from cloudstackAPI + response_type: response type of the command in cmd + method: HTTP GET/POST, defaults to GET + @Output: Response received from CS + Exception in case of Error\Exception """ - cmdname, isAsync, payload = self.sanitizeCommand(cmd) - self.logger.debug("sending %s request: %s %s" % (method, cmdname, - str(payload))) - response = self.request(cmdname, - self.auth, - payload=payload, - method=method) - if response is None: - return None - self.logger.debug("Request: %s Response: %s" % (response.url, - response.text)) try: - response = jsonHelper.getResultObj(response.json(), response_type) - except TypeError: - response = jsonHelper.getResultObj(response.json, response_type) + ''' + 1. Verify the Inputs Provided + ''' + if (cmd is None or cmd == '')or \ + (response_type is None or response_type == ''): + self.logger.exception("marvinRequest : Invalid Command Input") + raise InvalidParameterException("Invalid Parameter") - if isAsync == "false": - return response - else: - asyncJobId = response.jobid - response = self.poll(asyncJobId, response_type) - return response.jobresult + ''' + 2. Sanitize the Command + ''' + sanitize_cmd_out = self.__sanitizeCmd(cmd) + + if sanitize_cmd_out == FAILED: + raise self.__lastError + + cmd_name, is_async, payload = sanitize_cmd_out + ''' + 3. Send Command to CS + ''' + cmd_response = self.__sendCmdToCS(cmd_name, + self.auth, + payload=payload, + method=method) + if cmd_response == FAILED: + raise self.__lastError + + ''' + 4. Check if the Command Response received above is valid or Not. + If not return Invalid Response + ''' + ret = self.__parseAndGetResponse(cmd_response, + response_type, + is_async) + if ret == FAILED: + raise self.__lastError + return ret + except Exception as e: + self.logger.exception("marvinRequest : CmdName: %s Exception: %s" % + (str(cmd), GetDetailExceptionInfo(e))) + raise e diff --git a/tools/marvin/marvin/cloudstackException.py b/tools/marvin/marvin/cloudstackException.py index 6200003bbc..c2eb57a423 100644 --- a/tools/marvin/marvin/cloudstackException.py +++ b/tools/marvin/marvin/cloudstackException.py @@ -15,8 +15,13 @@ # specific language governing permissions and limitations # under the License. +import sys +import traceback +from marvin.codes import (INVALID_INPUT, EXCEPTION_OCCURRED) + + +class CloudstackAPIException(Exception): -class cloudstackAPIException(Exception): def __init__(self, cmd="", result=""): self.errorMsg = "Execute cmd: %s failed, due to: %s" % (cmd, result) @@ -25,6 +30,7 @@ def __str__(self): class InvalidParameterException(Exception): + def __init__(self, msg=''): self.errorMsg = msg @@ -33,6 +39,7 @@ def __str__(self): class dbException(Exception): + def __init__(self, msg=''): self.errorMsg = msg @@ -41,8 +48,18 @@ def __str__(self): class internalError(Exception): + def __init__(self, msg=''): self.errorMsg = msg def __str__(self): return self.errorMsg + + +def GetDetailExceptionInfo(e): + if e is not None: + exc_type, exc_value, exc_traceback = sys.exc_info() + return str(repr(traceback.format_exception( + exc_type, exc_value, exc_traceback))) + else: + return EXCEPTION_OCCURRED diff --git a/tools/marvin/marvin/cloudstackTestCase.py b/tools/marvin/marvin/cloudstackTestCase.py index 6456bb1fe6..5cb4a10928 100644 --- a/tools/marvin/marvin/cloudstackTestCase.py +++ b/tools/marvin/marvin/cloudstackTestCase.py @@ -16,7 +16,7 @@ # under the License. import unittest -from marvin.integration.lib.utils import verifyElementInList +from marvin.lib.utils import verifyElementInList from marvin.codes import PASS @@ -37,7 +37,7 @@ def __init__(self, *args, **kws): class cloudstackTestCase(unittest.case.TestCase): clstestclient = None - def assertElementInList(inp, toverify, responsevar=None, pos=0, + def assertElementInList(inp, toverify, responsevar=None, pos=0, assertmsg="TC Failed for reason"): ''' @Name: assertElementInList @@ -46,7 +46,7 @@ def assertElementInList(inp, toverify, responsevar=None, pos=0, Takes one additional argument of what message to assert with when failed ''' - out = verifyElementInList(inp, toverify, responsevar, pos) + out = verifyElementInList(inp, toverify, responsevar, pos) unittest.TestCase.assertEquals(out[0], PASS, "msg:%s" % out[1]) @classmethod diff --git a/tools/marvin/marvin/cloudstackTestClient.py b/tools/marvin/marvin/cloudstackTestClient.py index 4ac510b03a..86b0a4bbd5 100644 --- a/tools/marvin/marvin/cloudstackTestClient.py +++ b/tools/marvin/marvin/cloudstackTestClient.py @@ -15,201 +15,434 @@ # specific language governing permissions and limitations # under the License. -import cloudstackConnection -import asyncJobMgr -import dbConnection -from cloudstackAPI import * -import random -import string -import hashlib -from configGenerator import ConfigManager -from marvin.integration.lib.utils import random_gen - -''' -@Desc : CloudStackTestClient is encapsulated class for getting various \ - clients viz., apiclient,dbconnection etc -@Input : mgmtDetails : Management Server Details - dbSvrDetails: Database Server details of Management \ +from marvin.cloudstackConnection import CSConnection +from marvin.asyncJobMgr import asyncJobMgr +from marvin.dbConnection import DbConnection +from marvin.cloudstackAPI import * +from marvin.codes import (FAILED, PASS, ADMIN, DOMAIN_ADMIN, + USER, SUCCESS, XEN_SERVER) +from marvin.configGenerator import ConfigManager +from marvin.cloudstackException import GetDetailExceptionInfo +from marvin.lib.utils import (random_gen, validateList) +from marvin.cloudstackAPI.cloudstackAPIClient import CloudStackAPIClient + + +class CSTestClient(object): + + ''' + @Desc : CloudStackTestClient is encapsulated entity for creating and + getting various clients viz., apiclient, + user api client, dbconnection, test Data parsed + information etc + @Input : + mgmt_details : Management Server Details + dbsvr_details: Database Server details of Management \ Server. Retrieved from configuration file. - asyncTimeout : - defaultWorkerThreads : - logger : provides logging facilities for this library -''' - - -class cloudstackTestClient(object): - def __init__(self, mgmtDetails, - dbSvrDetails, asyncTimeout=3600, - defaultWorkerThreads=10, - logger=None): - self.mgmtDetails = mgmtDetails - self.connection = \ - cloudstackConnection.cloudConnection(self.mgmtDetails, - asyncTimeout, - logger) - self.apiClient =\ - cloudstackAPIClient.CloudStackAPIClient(self.connection) - self.dbConnection = None - if dbSvrDetails is not None: - self.createDbConnection(dbSvrDetails.dbSvr, dbSvrDetails.port, - dbSvrDetails.user, - dbSvrDetails.passwd, dbSvrDetails.db) - ''' - Provides the Configuration Object to users through getConfigParser - The purpose of this object is to parse the config - and provide dictionary of the config so users can - use that configuration.Users can later call getConfig - on this object and it will return the default parsed - config dictionary from default configuration file, - they can overwrite it with providing their own - configuration file as well. - ''' - self.configObj = ConfigManager() - self.asyncJobMgr = None - self.id = None - self.defaultWorkerThreads = defaultWorkerThreads + async_timeout : Timeout for Async queries + default_worker_threads : Number of worker threads + logger : provides logging facilities for this library + zone : The zone on which test suites using this test client will run + ''' + + def __init__(self, mgmt_details, + dbsvr_details, + async_timeout=3600, + logger=None, + test_data_filepath=None, + zone=None, + hypervisor_type=None): + self.__mgmtDetails = mgmt_details + self.__dbSvrDetails = dbsvr_details + self.__csConnection = None + self.__dbConnection = None + self.__testClient = None + self.__asyncTimeOut = async_timeout + self.__logger = logger + self.__apiClient = None + self.__userApiClient = None + self.__asyncJobMgr = None + self.__id = None + self.__hypervisor = hypervisor_type + self.__testDataFilePath = test_data_filepath + self.__parsedTestDataConfig = None + self.__zone = zone + self.__setHypervisorInfo() @property def identifier(self): - return self.id + return self.__id @identifier.setter def identifier(self, id): - self.id = id + self.__id = id + + def getParsedTestDataConfig(self): + ''' + @Name : getParsedTestDataConfig + @Desc : Provides the TestData Config needed for + Tests are to Run + @Output : Returns the Parsed Test Data Dictionary + ''' + out = self.__parsedTestDataConfig + return out + + def getZoneForTests(self): + ''' + @Name : getZoneForTests + @Desc : Provides the Zone against which Tests are to run + If zone name provided to marvin plugin is none + it will get it from Test Data Config File + Even, if it is not available, return None + @Output : Returns the Zone Name + ''' + return self.__zone + + def getHypervisorInfo(self): + ''' + @Name : getHypervisorInfo + @Desc : Provides the hypervisor Information to test users + @Output : Return Hypervisor Information + ''' + return self.__hypervisor + + def __setHypervisorInfo(self): + ''' + @Name : __setHypervisorInfo + @Desc: Set the HyperVisor details; + default to XenServer + ''' + try: + if not self.__hypervisor: + self.__hypervisor = XEN_SERVER + return SUCCESS + except Exception as e: + print "\n Exception Occurred Under __setHypervisorInfo " \ + "%s" % GetDetailExceptionInfo(e) + return FAILED + + def __createApiClient(self): + try: + ''' + Step1 : Create a CS Connection Object + ''' + mgmt_details = self.__mgmtDetails + self.__csConnection = CSConnection(mgmt_details, + self.__asyncTimeOut, + self.__logger) + + ''' + Step2 : Create API Client with earlier created connection object + ''' + self.__apiClient = CloudStackAPIClient(self.__csConnection) + + ''' + Step3: If API Key is not provided as part of Management Details, + then verify and register + ''' + if mgmt_details.apiKey is None: + list_user = listUsers.listUsersCmd() + list_user.account = "admin" + list_user_res = self.__apiClient.listUsers(list_user) + if list_user_res is None or\ + (validateList(list_user_res)[0] != PASS): + self.__logger.error("__createApiClient: API " + "Client Creation Failed") + return FAILED + user_id = list_user_res[0].id + api_key = list_user_res[0].apikey + security_key = list_user_res[0].secretkey + if api_key is None: + ret = self.__getKeys(user_id) + if ret != FAILED: + mgmt_details.apiKey = ret[0] + mgmt_details.securityKey = ret[1] + else: + self.__logger.error("__createApiClient: API Client " + "Creation Failed while " + "Registering User") + return FAILED + else: + mgmt_details.port = 8080 + mgmt_details.apiKey = api_key + mgmt_details.securityKey = security_key + ''' + Now Create the Connection objects and Api Client using + new details + ''' + self.__csConnection = CSConnection(mgmt_details, + self.__asyncTimeOut, + self.__logger) + self.__apiClient = CloudStackAPIClient(self.__csConnection) + return SUCCESS + except Exception as e: + self.__logger.exception(" Exception Occurred Under " + "__createApiClient: %s" % + GetDetailExceptionInfo(e)) + return FAILED + + def __createDbConnection(self): + ''' + @Name : ___createDbConnection + @Desc : Creates the CloudStack DB Connection + ''' + host = "localhost" if self.__dbSvrDetails.dbSvr is None \ + else self.__dbSvrDetails.dbSvr + port = 3306 if self.__dbSvrDetails.port is None \ + else self.__dbSvrDetails.port + user = "cloud" if self.__dbSvrDetails.user is None \ + else self.__dbSvrDetails.user + passwd = 'cloud' if self.__dbSvrDetails.passwd is None \ + else self.__dbSvrDetails.passwd + db = 'cloud' if self.__dbSvrDetails.db is None \ + else self.__dbSvrDetails.db + self.__dbConnection = DbConnection(host, port, user, passwd, db) + + def __getKeys(self, userid): + ''' + @Name : ___getKeys + @Desc : Retrieves the API and Secret Key for the provided Userid + @Input: userid: Userid to register + @Output: FAILED or tuple with apikey and secretkey + ''' + try: + register_user = registerUserKeys.registerUserKeysCmd() + register_user.id = userid + register_user_res = \ + self.__apiClient.registerUserKeys(register_user) + if not register_user_res: + return FAILED + return (register_user_res.apikey, register_user_res.secretkey) + except Exception as e: + self.__logger.exception("Exception Occurred Under __geKeys : " + "%s" % GetDetailExceptionInfo(e)) + return FAILED + + def createTestClient(self): + ''' + @Name : createTestClient + @Desc : Creates the Test Client. + The test Client is used by test suites + Here we create ParsedTestData Config. + Creates a DB Connection. + Creates an API Client + @Output : FAILED In case of an issue\Failure + SUCCESS in case of Success of this function + ''' + try: + ''' + 1. Create Config Object + Provides the Configuration Object to test suites through + getConfigParser. The purpose of this config object is to + parse the default config and provide dictionary of the + config so users can use that configuration. + Users can later call getConfig on this object and it will + return the default parsed config dictionary from default + configuration file. They can overwrite it with + providing their own configuration file as well. + ''' + ''' + 1. Check Config,Zone,Hypervisor Information + ''' + self.__configObj = ConfigManager(self.__testDataFilePath) + + if not self.__configObj or not self.__hypervisor: + self.__logger.error("createTestClient : " + "Either Hypervisor is None or " + "Not able to create " + "ConfigManager Object") + return FAILED - def createDbConnection(self, host="localhost", port=3306, user='cloud', - passwd='cloud', db='cloud'): - self.dbConnection = dbConnection.dbConnection(host, port, user, - passwd, db) + self.__parsedTestDataConfig = self.__configObj.getConfig() + self.__logger.debug("Parsing Test data successful") + + ''' + 2. Create DB Connection + ''' + self.__createDbConnection() + ''' + 3. Creates API Client + ''' + ret = self.__createApiClient() + if ret == FAILED: + self.__logger.\ + error("==== Test Client Creation Failed ====") + else: + self.__logger.\ + debug("==== Test Client Creation Successful ====") + return ret + except Exception as e: + self.__logger.exception("Exception Occurred " + "Under createTestClient " + ": %s" % GetDetailExceptionInfo(e)) + return FAILED def isAdminContext(self): """ - A user is a regular user if he fails to listDomains; + @Name : isAdminContext + @Desc:A user is a regular user if he fails to listDomains; if he is a domain-admin, he can list only domains that are non-ROOT; if he is an admin, he can list the ROOT domain successfully """ try: listdom = listDomains.listDomainsCmd() listdom.name = 'ROOT' - listdomres = self.apiClient.listDomains(listdom) - rootdom = listdomres[0].name - if rootdom == 'ROOT': - return 1 # admin - else: - return 2 # domain-admin + listdomres = self.__apiClient.listDomains(listdom) + if listdomres != FAILED: + rootdom = listdomres[0].name + if rootdom == 'ROOT': + return ADMIN + else: + return DOMAIN_ADMIN + return USER except: - return 0 # user - - def createUserApiClient(self, UserName, DomainName, acctType=0): - if not self.isAdminContext(): - return self.apiClient + return USER - listDomain = listDomains.listDomainsCmd() - listDomain.listall = True - listDomain.name = DomainName - try: - domains = self.apiClient.listDomains(listDomain) - domId = domains[0].id - except: - cdomain = createDomain.createDomainCmd() - cdomain.name = DomainName - domain = self.apiClient.createDomain(cdomain) - domId = domain.id - - cmd = listAccounts.listAccountsCmd() - cmd.name = UserName - cmd.domainid = domId + def __createUserApiClient(self, UserName, DomainName, acctType=0): + ''' + @Name : ___createUserApiClient + @Desc : Creates a User API Client with given + UserName\DomainName Parameters + @Input: UserName: Username to be created in cloudstack + DomainName: Domain under which the above account be created + accType: Type of Account EX: Root,Non Root etc + @Output: Return the API client for the user + ''' try: - accounts = self.apiClient.listAccounts(cmd) - acctId = accounts[0].id - except: - createAcctCmd = createAccount.createAccountCmd() - createAcctCmd.accounttype = acctType - createAcctCmd.domainid = domId - createAcctCmd.email = "test-" + random_gen()\ - + "@cloudstack.org" - createAcctCmd.firstname = UserName - createAcctCmd.lastname = UserName - createAcctCmd.password = 'password' - createAcctCmd.username = UserName - acct = self.apiClient.createAccount(createAcctCmd) - acctId = acct.id - - listuser = listUsers.listUsersCmd() - listuser.username = UserName - - listuserRes = self.apiClient.listUsers(listuser) - userId = listuserRes[0].id - apiKey = listuserRes[0].apikey - securityKey = listuserRes[0].secretkey - - if apiKey is None: - registerUser = registerUserKeys.registerUserKeysCmd() - registerUser.id = userId - registerUserRes = self.apiClient.registerUserKeys(registerUser) - apiKey = registerUserRes.apikey - securityKey = registerUserRes.secretkey - - mgtDetails = self.mgmtDetails - mgtDetails.apiKey = apiKey - mgtDetails.securityKey = securityKey - - newUserConnection =\ - cloudstackConnection.cloudConnection(mgtDetails, - self.connection.asyncTimeout, - self.connection.logger) - self.userApiClient =\ - cloudstackAPIClient.CloudStackAPIClient(newUserConnection) - self.userApiClient.connection = newUserConnection - self.userApiClient.hypervisor = self.apiClient.hypervisor - return self.userApiClient + if not self.isAdminContext(): + return self.__apiClient + mgmt_details = self.__mgmtDetails + listDomain = listDomains.listDomainsCmd() + listDomain.listall = True + listDomain.name = DomainName + try: + domains = self.__apiClient.listDomains(listDomain) + domId = domains[0].id + except: + cdomain = createDomain.createDomainCmd() + cdomain.name = DomainName + domain = self.__apiClient.createDomain(cdomain) + domId = domain.id + + cmd = listAccounts.listAccountsCmd() + cmd.name = UserName + cmd.domainid = domId + cmd.listall = True + try: + accounts = self.__apiClient.listAccounts(cmd) + acctId = accounts[0].id + except: + createAcctCmd = createAccount.createAccountCmd() + createAcctCmd.accounttype = acctType + createAcctCmd.domainid = domId + createAcctCmd.email = "test-" + random_gen()\ + + "@cloudstack.org" + createAcctCmd.firstname = UserName + createAcctCmd.lastname = UserName + createAcctCmd.password = 'password' + createAcctCmd.username = UserName + acct = self.__apiClient.createAccount(createAcctCmd) + acctId = acct.id + + listuser = listUsers.listUsersCmd() + listuser.username = UserName + + listuserRes = self.__apiClient.listUsers(listuser) + userId = listuserRes[0].id + apiKey = listuserRes[0].apikey + securityKey = listuserRes[0].secretkey + + if apiKey is None: + ret = self.__getKeys(userId) + if ret != FAILED: + mgmt_details.apiKey = ret[0] + mgmt_details.securityKey = ret[1] + else: + self.__logger.error("__createUserApiClient: " + "User API Client Creation." + " While Registering User Failed") + return FAILED + else: + mgmt_details.port = 8080 + mgmt_details.apiKey = apiKey + mgmt_details.securityKey = securityKey + + newUserConnection =\ + CSConnection(mgmt_details, + self.__csConnection.asyncTimeout, + self.__csConnection.logger) + self.__userApiClient = CloudStackAPIClient(newUserConnection) + self.__userApiClient.connection = newUserConnection + self.__userApiClient.hypervisor = self.__hypervisor + return self.__userApiClient + except Exception as e: + self.__logger.exception("Exception Occurred " + "Under getUserApiClient : %s" % + GetDetailExceptionInfo(e)) + return FAILED def close(self): - if self.connection is not None: - self.connection.close() + if self.__csConnection is not None: + self.__csConnection.close() def getDbConnection(self): - return self.dbConnection + ''' + @Name : getDbConnection + @Desc : Retrieves the DB Connection Handle + ''' + return self.__dbConnection def getConfigParser(self): - return self.configObj + ''' + @Name : getConfigParser + @Desc : Provides the ConfigManager Interface to TestClients + ''' + return self.__configObj def getApiClient(self): - self.apiClient.id = self.identifier - return self.apiClient + if self.__apiClient: + self.__apiClient.id = self.identifier + return self.__apiClient + return None - def getUserApiClient(self, account, domain, type=0): + def getUserApiClient(self, UserName=None, DomainName=None, type=0): """ - 0 - user - 1 - admin - 2 - domain admin + @Name : getUserApiClient + @Desc : Provides the User API Client to test Users + 0 - user ; 1 - admin;2 - domain admin + @OutPut : FAILED In case of an issue + else User API Client """ - self.createUserApiClient(account, domain, type) - if hasattr(self, "userApiClient"): - return self.userApiClient - return None + if UserName is None or DomainName is None: + return FAILED + return self.__createUserApiClient(UserName, DomainName, type) def submitCmdsAndWait(self, cmds, workers=1): - '''FixME, httplib has issue if more than one thread submitted''' - if self.asyncJobMgr is None: - self.asyncJobMgr = asyncJobMgr.asyncJobMgr(self.apiClient, - self.dbConnection) - return self.asyncJobMgr.submitCmdsAndWait(cmds, workers) + ''' + @Desc : FixME, httplib has issue if more than one thread submitted + ''' + if self.__asyncJobMgr is None: + self.__asyncJobMgr = asyncJobMgr(self.__apiClient, + self.__dbConnection) + return self.__asyncJobMgr.submitCmdsAndWait(cmds, workers) def submitJob(self, job, ntimes=1, nums_threads=10, interval=1): ''' - submit one job and execute the same job ntimes, with nums_threads - of threads + @Desc : submit one job and execute the same job + ntimes, with nums_threads of threads ''' - if self.asyncJobMgr is None: - self.asyncJobMgr = asyncJobMgr.asyncJobMgr(self.apiClient, - self.dbConnection) - self.asyncJobMgr.submitJobExecuteNtimes(job, ntimes, nums_threads, - interval) + if self.__asyncJobMgr is None: + self.__asyncJobMgr = asyncJobMgr(self.__apiClient, + self.__dbConnection) + self.__asyncJobMgr.submitJobExecuteNtimes(job, ntimes, + nums_threads, + interval) def submitJobs(self, jobs, nums_threads=10, interval=1): - '''submit n jobs, execute them with nums_threads of threads''' - if self.asyncJobMgr is None: - self.asyncJobMgr = asyncJobMgr.asyncJobMgr(self.apiClient, - self.dbConnection) - self.asyncJobMgr.submitJobs(jobs, nums_threads, interval) + ''' + @Desc :submit n jobs, execute them with nums_threads + of threads + ''' + if self.__asyncJobMgr is None: + self.__asyncJobMgr = asyncJobMgr(self.__apiClient, + self.__dbConnection) + self.__asyncJobMgr.submitJobs(jobs, nums_threads, interval) diff --git a/tools/marvin/marvin/codegenerator.py b/tools/marvin/marvin/codegenerator.py index e0f056f66a..e5015c6dfd 100644 --- a/tools/marvin/marvin/codegenerator.py +++ b/tools/marvin/marvin/codegenerator.py @@ -25,6 +25,7 @@ class cmdParameterProperty(object): + def __init__(self): self.name = None self.required = False @@ -34,6 +35,7 @@ def __init__(self): class cloudStackCmd(object): + def __init__(self): self.name = "" self.desc = "" @@ -42,7 +44,8 @@ def __init__(self): self.response = [] -class codeGenerator(object): +class CodeGenerator(object): + """ Apache CloudStack- marvin python classes can be generated from the json returned by API discovery or from the xml spec of commands generated by @@ -208,12 +211,12 @@ def finalize(self): body += self.space + '@property' + self.newline body += self.space + 'def id(self):' + self.newline - body += self.space*2 + 'return self._id' + self.newline + body += self.space * 2 + 'return self._id' + self.newline body += self.newline body += self.space + '@id.setter' + self.newline body += self.space + 'def id(self, identifier):' + self.newline - body += self.space*2 + 'self._id = identifier' + self.newline + body += self.space * 2 + 'self._id = identifier' + self.newline body += self.newline for cmdName in self.cmdsName: @@ -340,7 +343,7 @@ def constructResponseFromJSON(self, response): paramProperty.desc = response['description'] if 'type' in response: if response['type'] in ['list', 'map', 'set']: - #Here list becomes a subproperty + # Here list becomes a subproperty if 'response' in response: for innerResponse in response['response']: subProperty =\ @@ -356,9 +359,9 @@ def loadCmdFromJSON(self, apiStream): jsonOut = apiStream.readlines() assert len(jsonOut) > 0 apiDict = json.loads(jsonOut[0]) - if not 'listapisresponse' in apiDict: + if 'listapisresponse' not in apiDict: raise Exception("API discovery plugin response failed") - if not 'count' in apiDict['listapisresponse']: + if 'count' not in apiDict['listapisresponse']: raise Exception("Malformed api response") apilist = apiDict['listapisresponse']['api'] @@ -394,7 +397,8 @@ def loadCmdFromJSON(self, apiStream): csCmd.request.append(paramProperty) for response in cmd['response']: - #FIXME: ExtractImage related APIs return empty dicts in response + # FIXME: ExtractImage related APIs return empty dicts in + # response if len(response) > 0: paramProperty = self.constructResponseFromJSON(response) csCmd.response.append(paramProperty) @@ -409,11 +413,11 @@ def generateCodeFromJSON(self, endpointUrl): @return: The classes in cloudstackAPI/ formed from api discovery json """ if endpointUrl.find('response=json') >= 0: - apiStream = urllib2.urlopen(endpointUrl) - cmds = self.loadCmdFromJSON(apiStream) - for cmd in cmds: - self.generate(cmd) - self.finalize() + apiStream = urllib2.urlopen(endpointUrl) + cmds = self.loadCmdFromJSON(apiStream) + for cmd in cmds: + self.generate(cmd) + self.finalize() def getText(elements): @@ -454,7 +458,7 @@ def getText(elements): print parser.print_help() exit(1) - cg = codeGenerator(folder) + cg = CodeGenerator(folder) if options.spec is not None: cg.generateCodeFromXML(apiSpecFile) elif options.endpoint is not None: diff --git a/tools/marvin/marvin/codes.py b/tools/marvin/marvin/codes.py index e4a0f6a789..c72a6bde8f 100644 --- a/tools/marvin/marvin/codes.py +++ b/tools/marvin/marvin/codes.py @@ -31,6 +31,11 @@ """ RUNNING = "Running" +STOPPED = "Stopped" +STOPPING = "Stopping" +STARTING = "Starting" +DESTROYED = "Destroyed" +EXPUNGING = "Expunging" RECURRING = "RECURRING" ENABLED = "Enabled" NETWORK_OFFERING = "network_offering" @@ -47,8 +52,33 @@ FAILED = "FAILED" UNKNOWN_ERROR = "Unknown Error" EXCEPTION = "EXCEPTION" +INVALID_RESPONSE = "Invalid Response" +''' +Async Job Related Codes +''' +JOB_INPROGRESS = 0 +JOB_SUCCEEDED = 1 +JOB_FAILED = 2 +JOB_CANCELLED = 3 +ERROR_CODE_530 = 530 +''' +User Related Codes +''' BASIC_ZONE = "basic" ISOLATED_NETWORK = "ISOLATED" SHARED_NETWORK = "SHARED" VPC_NETWORK = "VPC" -ERROR_NO_HOST_FOR_MIGRATION = "Could not find suitable host for migration, please ensure setup has required no. of hosts" +ERROR_NO_HOST_FOR_MIGRATION = \ + "Could not find suitable host for migration, " \ + "please ensure setup has required no. of hosts" +NAT_RULE = "nat rule" +STATIC_NAT_RULE = "static nat rule" +UNKNOWN = "UNKNOWN" +FAULT = "FAULT" +MASTER = "MASTER" +ADMIN = 1 +DOMAIN_ADMIN = 2 +USER = 0 +XEN_SERVER = "XenServer" +ADMIN_ACCOUNT = 'ADMIN_ACCOUNT' +USER_ACCOUNT = 'USER_ACCOUNT' diff --git a/tools/marvin/marvin/integration/lib/__init__.py b/tools/marvin/marvin/config/__init__.py similarity index 99% rename from tools/marvin/marvin/integration/lib/__init__.py rename to tools/marvin/marvin/config/__init__.py index 978b68af62..13a83393a9 100644 --- a/tools/marvin/marvin/integration/lib/__init__.py +++ b/tools/marvin/marvin/config/__init__.py @@ -5,9 +5,9 @@ # 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 diff --git a/tools/marvin/marvin/config/config.cfg b/tools/marvin/marvin/config/config.cfg deleted file mode 100644 index 356a291191..0000000000 --- a/tools/marvin/marvin/config/config.cfg +++ /dev/null @@ -1,392 +0,0 @@ -# Licensed to the Apache Software Foundation (ASF) under one -# or more contributor license agreements. See the NOTICE file -# distributed with this work for additional information -# regarding copyright ownership. The ASF licenses this file -# to you under the Apache License, Version 2.0 (the -# "License"); you may not use this file except in compliance -# with the License. You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, -# software distributed under the License is distributed on an -# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY -# KIND, either express or implied. See the License for the -# specific language governing permissions and limitations -# under the License. -# -# Use the common configs added such as account, network_offerings, domain, project, -# or add your own data if required separately for any test case -{ - "domain": - { - "name": "domain" - } - , - "project": - { - "name": "Project", - "displaytext": "Test project" - }, - "account": { - "email": "test-account@test.com", - "firstname": "test", - "lastname": "test", - "username": "test-account", - "password": "password" - }, - "service_offering": { - "name": "Tiny Instance", - "displaytext": "Tiny Instance", - "cpunumber": 1, - "cpuspeed": 100, - "memory": 128 - }, - "isolated_network_offering": { - "name": "Isolated Network offering", - "displaytext": "Isolated Network offering", - "guestiptype": "Isolated", - "supportedservices": "Dhcp,Dns,SourceNat,PortForwarding,Vpn,Firewall,Lb,UserData,StaticNat", - "traffictype": "GUEST", - "availability": "Optional'", - "serviceProviderList": { - "Dhcp": "VirtualRouter", - "Dns": "VirtualRouter", - "SourceNat": "VirtualRouter", - "PortForwarding": "VirtualRouter", - "Vpn": "VirtualRouter", - "Firewall": "VirtualRouter", - "Lb": "VirtualRouter", - "UserData": "VirtualRouter", - "StaticNat": "VirtualRouter" - } - }, - "isolated_network": { - "name": "Isolated Network", - "displaytext": "Isolated Network" - }, - "virtual_machine": { - "displayname": "Test VM", - "username": "root", - "password": "password", - "ssh_port": 22, - "privateport": 22, - "publicport": 22, - "protocol": "TCP" - }, - "shared_network": { - "name": "Test Shared Network", - "displaytext": "Test Shared Network", - "vlan" : "", - "gateway" :"", - "netmask" :"", - "startip" :"", - "endip" :"", - "acltype" : "Domain", - "scope":"all" - }, - "shared_network_offering_sg": { - "name": "SharedNwOffering-sg", - "displaytext": "SharedNwOffering-sg", - "guestiptype": "Shared", - "supportedservices": "Dhcp,Dns,UserData,SecurityGroup", - "specifyVlan" : "False", - "specifyIpRanges" : "False", - "traffictype": "GUEST", - "serviceProviderList" : { - "Dhcp": "VirtualRouter", - "Dns": "VirtualRouter", - "UserData": "VirtualRouter", - "SecurityGroup": "SecurityGroupProvider" - } - }, - "shared_network_sg": { - "name": "Shared-Network-SG-Test", - "displaytext": "Shared-Network_SG-Test", - "networkofferingid":"", - "vlan" : "", - "gateway" :"", - "netmask" :"255.255.255.0", - "startip" :"", - "endip" :"", - "acltype" : "Domain", - "scope":"all" - }, - "vpc_offering": { - "name": "VPC off", - "displaytext": "VPC off", - "supportedservices": "Dhcp,Dns,SourceNat,PortForwarding,Vpn,Lb,UserData,StaticNat,NetworkACL" - }, - "vpc": { - "name": "TestVPC", - "displaytext": "TestVPC", - "cidr": "10.0.0.1/24" - }, - "shared_network_offering": { - "name": "SharedNwOffering", - "displaytext": "SharedNwOffering", - "guestiptype": "Shared", - "supportedservices": "Dhcp,Dns,UserData", - "specifyVlan" : "False", - "specifyIpRanges" : "False", - "traffictype": "GUEST", - "serviceProviderList" : { - "Dhcp": "VirtualRouter", - "Dns": "VirtualRouter", - "UserData": "VirtualRouter" - } - }, - "security_group" : { "name": "custom_Sec_Grp" }, - "ingress_rule": { - "protocol": "TCP", - "startport": "22", - "endport": "22", - "cidrlist": "0.0.0.0/0" - }, - "ostype": "CentOS 5.3 (64-bit)", - "sleep": 90, - "timeout": 10, - "netscaler_VPX": { - "ipaddress": "10.223.240.174", - "username": "nsroot", - "password": "nsroot", - "networkdevicetype": "NetscalerVPXLoadBalancer", - "publicinterface": "1/1", - "privateinterface": "1/2", - "numretries": 2, - "lbdevicededicated": "True", - "lbdevicecapacity": 2, - "port": 22 - }, - "nw_offering_shared_persistent": { - "name": "Network offering for Shared Persistent Network", - "displaytext": "Network offering-DA services", - "guestiptype": "Shared", - "supportedservices": "Dhcp,Dns,SourceNat,PortForwarding,Vpn,Firewall,Lb,UserData,StaticNat", - "traffictype": "GUEST", - "availability": "Optional", - "ispersistent": "True", - "serviceProviderList": { - "Dhcp": "VirtualRouter", - "Dns": "VirtualRouter", - "SourceNat": "VirtualRouter", - "PortForwarding": "VirtualRouter", - "Vpn": "VirtualRouter", - "Firewall": "VirtualRouter", - "Lb": "VirtualRouter", - "UserData": "VirtualRouter", - "StaticNat": "VirtualRouter" - } - }, - "nw_off_isolated_persistent": { - "name": "Network offering for Isolated Persistent Network", - "displaytext": "Network Offering for Isolated Persistent Network", - "guestiptype": "Isolated", - "supportedservices": "Dhcp,Dns,SourceNat,PortForwarding,Vpn,Firewall,Lb,UserData,StaticNat", - "traffictype":"GUEST", - "availability":"Optional", - "ispersistent": "True", - "serviceProviderList": { - "Dhcp": "VirtualRouter", - "Dns": "VirtualRouter", - "SourceNat": "VirtualRouter", - "PortForwarding": "VirtualRouter", - "Vpn": "VirtualRouter", - "Firewall": "VirtualRouter", - "Lb": "VirtualRouter", - "UserData": "VirtualRouter", - "StaticNat": "VirtualRouter" - } - }, - "nw_off_isolated_persistent_netscaler": { - "name": "Network offering for Isolated Persistent Network", - "displaytext": "Network Offering for Isolated Persistent Network", - "guestiptype": "Isolated", - "supportedservices": "Dhcp,Dns,SourceNat,PortForwarding,Vpn,Firewall,Lb,UserData,StaticNat", - "traffictype": "GUEST", - "availability": "Optional", - "ispersistent": "True", - "serviceProviderList": { - "Dhcp": "VirtualRouter", - "Dns": "VirtualRouter", - "SourceNat": "VirtualRouter", - "PortForwarding": "VirtualRouter", - "Vpn": "VirtualRouter", - "Firewall": "VirtualRouter", - "Lb": "Netscaler", - "UserData": "VirtualRouter", - "StaticNat": "VirtualRouter" - } - }, - "nw_offering_isolated": { - "name": "Network offering for Isolated Persistent Network", - "displaytext": "Network offering-DA services", - "guestiptype": "Isolated", - "supportedservices": "Dhcp,Dns,SourceNat,PortForwarding,Vpn,Firewall,Lb,UserData,StaticNat", - "traffictype": "GUEST", - "availability": "Optional", - "serviceProviderList": { - "Dhcp": "VirtualRouter", - "Dns": "VirtualRouter", - "SourceNat": "VirtualRouter", - "PortForwarding": "VirtualRouter", - "Vpn": "VirtualRouter", - "Firewall": "VirtualRouter", - "Lb": "VirtualRouter", - "UserData": "VirtualRouter", - "StaticNat": "VirtualRouter" - } - }, - "nw_off_isolated_netscaler": { - "name": "Network offering for Isolated Persistent Network", - "displaytext": "Network offering-DA services", - "guestiptype": "Isolated", - "supportedservices": "Dhcp,Dns,SourceNat,PortForwarding,Vpn,Firewall,Lb,UserData,StaticNat", - "traffictype": "GUEST", - "availability": "Optional", - "serviceProviderList": { - "Dhcp": "VirtualRouter", - "Dns": "VirtualRouter", - "SourceNat": "VirtualRouter", - "PortForwarding": "VirtualRouter", - "Vpn": "VirtualRouter", - "Firewall": "VirtualRouter", - "Lb": "Netscaler", - "UserData": "VirtualRouter", - "StaticNat": "VirtualRouter" - } - }, - "nw_off_persistent_RVR": { - "name": "Network offering-RVR services", - "displaytext": "Network off-RVR services", - "guestiptype": "Isolated", - "supportedservices": "Vpn,Dhcp,Dns,SourceNat,PortForwarding,Firewall,Lb,UserData,StaticNat", - "traffictype": "GUEST", - "availability": "Optional", - "ispersistent": "True", - "serviceProviderList": { - "Vpn": "VirtualRouter", - "Dhcp": "VirtualRouter", - "Dns": "VirtualRouter", - "SourceNat": "VirtualRouter", - "PortForwarding": "VirtualRouter", - "Firewall": "VirtualRouter", - "Lb": "VirtualRouter", - "UserData": "VirtualRouter", - "StaticNat": "VirtualRouter" - }, - "serviceCapabilityList": { - "SourceNat": { - "SupportedSourceNatTypes": "peraccount", - "RedundantRouter": "true" - }, - "lb": { - "SupportedLbIsolation": "dedicated" - } - } - }, - "nw_off_persistent_VPCVR_NoLB": { - "name": "Persistent Network VPC No LB", - "displaytext": "Persistent Network VPC No LB", - "guestiptype": "Isolated", - "supportedservices": "Dhcp,Dns,SourceNat,PortForwarding,Vpn,UserData,StaticNat,NetworkACL", - "traffictype": "GUEST", - "availability": "Optional", - "ispersistent": "False", - "useVpc": "on", - "serviceProviderList": { - "Dhcp": "VpcVirtualRouter", - "Dns": "VpcVirtualRouter", - "SourceNat": "VpcVirtualRouter", - "PortForwarding": "VpcVirtualRouter", - "Vpn": "VpcVirtualRouter", - "UserData": "VpcVirtualRouter", - "StaticNat": "VpcVirtualRouter", - "NetworkACL": "VpcVirtualRouter" - } - }, - "nw_off_persistent_VPCVR_LB": { - "name": "Persistent Network VPC with LB", - "displaytext": "Persistent Network VPC No LB", - "guestiptype": "Isolated", - "supportedservices": "Dhcp,Dns,SourceNat,PortForwarding,Vpn,Lb,UserData,StaticNat,NetworkACL", - "traffictype": "GUEST", - "availability": "Optional", - "ispersistent": "False", - "useVpc": "on", - "serviceProviderList": { - "Dhcp": "VpcVirtualRouter", - "Dns": "VpcVirtualRouter", - "SourceNat": "VpcVirtualRouter", - "PortForwarding": "VpcVirtualRouter", - "Vpn": "VpcVirtualRouter", - "Lb": "VpcVirtualRouter", - "UserData": "VpcVirtualRouter", - "StaticNat": "VpcVirtualRouter", - "NetworkACL": "VpcVirtualRouter" - } - }, - "nw_offering_isolated_vpc": { - "name": "Isolated Network for VPC", - "displaytext": "Isolated Network for VPC", - "guestiptype": "Isolated", - "supportedservices": "Dhcp,Dns,SourceNat,PortForwarding,Vpn,UserData,StaticNat,NetworkACL", - "traffictype": "GUEST", - "availability": "Optional", - "ispersistent": "False", - "useVpc": "on", - "serviceProviderList": { - "Dhcp": "VpcVirtualRouter", - "Dns": "VpcVirtualRouter", - "SourceNat": "VpcVirtualRouter", - "PortForwarding": "VpcVirtualRouter", - "Vpn": "VpcVirtualRouter", - "UserData": "VpcVirtualRouter", - "StaticNat": "VpcVirtualRouter", - "NetworkACL": "VpcVirtualRouter" - } - }, - "natrule": { - "privateport": 22, - "publicport": 22, - "startport": 22, - "endport": 22, - "protocol": "TCP", - "cidrlist": "0.0.0.0/0" - }, - "fwrule": { - "startport": 22, - "endport": 22, - "cidr": "0.0.0.0/0", - "protocol": "TCP" - }, - "lbrule": { - "name": "SSH", - "alg": "leastconn", - # Algorithm used for load balancing - "privateport": 22, - "publicport": 22, - "openfirewall": "False", - "startport": 22, - "endport": 22, - "protocol": "TCP", - "cidrlist": "0.0.0.0/0" - }, - "icmprule": { - "icmptype": -1, - "icmpcode": -1, - "cidrlist": "0.0.0.0/0", - "protocol": "ICMP" - }, - "host_password": "password", - "advanced_sg": { - "zone": { - "name": "", - "dns1": "8.8.8.8", - "internaldns1": "192.168.100.1", - "networktype": "Advanced", - "securitygroupenabled": "true" - }, - "securitygroupenabled": "true" - } -} diff --git a/tools/marvin/marvin/config/test_data.py b/tools/marvin/marvin/config/test_data.py new file mode 100644 index 0000000000..026f5ff559 --- /dev/null +++ b/tools/marvin/marvin/config/test_data.py @@ -0,0 +1,833 @@ +# 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. + +test_data = { + "region": { + "regionid": "2", + "regionname": "Region2", + "regionendpoint": "http://region2:8080/client" + }, + "zone": "NA", + "hypervisor": "XenServer", + "deleteDC": True, + "vdomain": { + "name": "domain" + }, + "domain": {"name": "domain"}, + "email": "test@test.com", + "gateway": "172.1.1.1", + "netmask": "255.255.255.0", + "startip": "172.1.1.10", + "endip": "172.1.1.20", + "regionid": "1", + "vlan": "10", + "isportable": "true", + + "project": { + "name": "Project", + "displaytext": "Test project" + }, + "account": { + "email": "test-account@test.com", + "firstname": "test", + "lastname": "test", + "username": "test-account", + "password": "password" + }, + "small": { + "displayname": "testserver", + "username": "root", + "password": "password", + "ssh_port": 22, + "hypervisor": "XenServer", + "privateport": 22, + "publicport": 22, + "protocol": 'TCP', + }, + "medium": { + "displayname": "testserver", + "username": "root", + "password": "password", + "ssh_port": 22, + "hypervisor": 'XenServer', + "privateport": 22, + "publicport": 22, + "protocol": 'TCP', + }, + "service_offering": { + "name": "Tiny Instance", + "displaytext": "Tiny Instance", + "cpunumber": 1, + "cpuspeed": 100, # in MHz + "memory": 128, # In MBs + }, + "service_offerings": { + "name": "Tiny Instance", + "displaytext": "Tiny Instance", + "cpunumber": 1, + "cpuspeed": 100, + "memory": 128, + + "tiny": { + "name": "Tiny Instance", + "displaytext": "Tiny Instance", + "cpunumber": 1, + "cpuspeed": 100, + "memory": 128, + }, + "small": { + "name": "Small Instance", + "displaytext": "Small Instance", + "cpunumber": 1, + "cpuspeed": 100, + "memory": 256 + }, + "medium": { + "name": "Medium Instance", + "displaytext": "Medium Instance", + "cpunumber": 1, + "cpuspeed": 100, + "memory": 256, + }, + "big": { + "name": "BigInstance", + "displaytext": "BigInstance", + "cpunumber": 1, + "cpuspeed": 100, + "memory": 512, + }, + "hasmall": { + "name": "HA Small Instance", + "displaytext": "HA Small Instance", + "cpunumber": 1, + "cpuspeed": 100, + "memory": 256, + "hosttags": "ha", + "offerha": True, + }, + }, + "disk_offering": { + "name": "Disk offering", + "displaytext": "Disk offering", + "disksize": 1 + }, + 'resized_disk_offering': { + "displaytext": "Resized", + "name": "Resized", + "disksize": 3 + }, + "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", + }, + "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', + }, + }, + "nw_off_isolated_netscaler": { + "name": "Network offering-ns services", + "displaytext": "Network offering-ns services", + "guestiptype": "Isolated", + "supportedservices": + "Dhcp,Dns,SourceNat,PortForwarding,Vpn,Firewall,Lb,UserData,StaticNat", + "traffictype": "GUEST", + "availability": "Optional'", + "serviceProviderList": { + "Dhcp": "VirtualRouter", + "Dns": "VirtualRouter", + "SourceNat": "VirtualRouter", + "PortForwarding": "VirtualRouter", + "Vpn": "VirtualRouter", + "Firewall": "VirtualRouter", + "Lb": "NetScaler", + "UserData": "VirtualRouter", + "StaticNat": "VirtualRouter" + } + }, + "nw_off_isolated_persistent": { + "name": 'Test Nw off isolated persistent', + "displaytext": 'Test Nw off isolated persistent', + "guestiptype": 'Isolated', + "supportedservices": 'Dhcp,Dns,SourceNat,PortForwarding', + "traffictype": 'GUEST', + "ispersistent": 'True', + "availability": 'Optional', + "serviceProviderList": { + "Dhcp": 'VirtualRouter', + "Dns": 'VirtualRouter', + "SourceNat": 'VirtualRouter', + "PortForwarding": 'VirtualRouter', + }, + }, + "isolated_network_offering": { + "name": "Network offering-DA services", + "displaytext": "Network offering-DA services", + "guestiptype": "Isolated", + "supportedservices": + "Dhcp,Dns,SourceNat,PortForwarding,Vpn,Firewall,Lb,UserData,StaticNat", + "traffictype": "GUEST", + "availability": "Optional'", + "serviceProviderList": { + "Dhcp": "VirtualRouter", + "Dns": "VirtualRouter", + "SourceNat": "VirtualRouter", + "PortForwarding": "VirtualRouter", + "Vpn": "VirtualRouter", + "Firewall": "VirtualRouter", + "Lb": "VirtualRouter", + "UserData": "VirtualRouter", + "StaticNat": "VirtualRouter" + } + }, + "isolated_network": { + "name": "Isolated Network", + "displaytext": "Isolated Network" + }, + "netscaler_VPX": { + "ipaddress": "10.223.240.174", + "username": "nsroot", + "password": "nsroot", + "networkdevicetype": "NetscalerVPXLoadBalancer", + "publicinterface": "1/1", + "privateinterface": "1/2", + "numretries": 2, + "lbdevicededicated": "True", + "lbdevicecapacity": 2, + "port": 22 + }, + "virtual_machine": { + "displayname": "Test VM", + "username": "root", + "password": "password", + "ssh_port": 22, + "privateport": 22, + "publicport": 22, + "protocol": "TCP", + "affinity": { + "name": "webvms", + "type": "host anti-affinity", + }, + }, + "virtual_machine2": { + "name": "testvm2", + "displayname": "Test VM2", + }, + "virtual_machine3": { + "name": "testvm3", + "displayname": "Test VM3", + }, + "server_without_disk": { + "displayname": "Test VM-No Disk", + "username": "root", + "password": "password", + "ssh_port": 22, + "hypervisor": 'XenServer', + "privateport": 22, + "publicport": 22, + "protocol": 'TCP', + }, + "shared_network": { + "name": "MySharedNetwork - Test", + "displaytext": "MySharedNetwork", + "vlan": "", + "gateway": "", + "netmask": "", + "startip": "", + "endip": "", + "acltype": "Domain", + "scope": "all" + }, + "shared_network_offering": { + "name": "MySharedOffering-shared", + "displaytext": "MySharedOffering", + "guestiptype": "Shared", + "supportedservices": "Dhcp,Dns,UserData", + "specifyVlan": "False", + "specifyIpRanges": "False", + "traffictype": "GUEST", + "serviceProviderList": { + "Dhcp": "VirtualRouter", + "Dns": "VirtualRouter", + "UserData": "VirtualRouter" + } + }, + "shared_network_offering_all_services": { + "name": "shaared network offering with services enabled", + "displaytext": "Shard network offering", + "guestiptype": "Shared", + "supportedservices": "Dhcp,Dns,SourceNat,PortForwarding,Vpn,Firewall,Lb,UserData,StaticNat", + "specifyVlan": "False", + "specifyIpRanges": "False", + "traffictype": "GUEST", + "serviceProviderList": { + "Dhcp": "VirtualRouter", + "Dns": "VirtualRouter", + "UserData": "VirtualRouter", + "SourceNat": "VirtualRouter", + "PortForwarding": "VirtualRouter", + "Vpn": "VirtualRouter", + "Firewall": "VirtualRouter", + "Lb": "VirtualRouter", + "UserData": "VirtualRouter", + "StaticNat": "VirtualRouter" + } + }, + "shared_network_offering_sg": { + "name": "MySharedOffering-sg", + "displaytext": "MySharedOffering-sg", + "guestiptype": "Shared", + "supportedservices": "Dhcp,Dns,UserData,SecurityGroup", + "specifyVlan": "False", + "specifyIpRanges": "False", + "traffictype": "GUEST", + "serviceProviderList": { + "Dhcp": "VirtualRouter", + "Dns": "VirtualRouter", + "UserData": "VirtualRouter", + "SecurityGroup": "SecurityGroupProvider" + } + }, + "shared_network_sg": { + "name": "Shared-Network-SG-Test", + "displaytext": "Shared-Network_SG-Test", + "networkofferingid": "1", + "vlan": "", + "gateway": "", + "netmask": "255.255.255.0", + "startip": "", + "endip": "", + "acltype": "Domain", + "scope": "all" + }, + "vpc_offering": { + "name": "VPC off", + "displaytext": "VPC off", + "supportedservices": + "Dhcp,Dns,SourceNat,PortForwarding,Vpn,Lb,UserData,StaticNat,NetworkACL" + }, + "vpc": { + "name": "TestVPC", + "displaytext": "TestVPC", + "cidr": "10.0.0.1/24" + }, + "clusters": { + 0: { + "clustername": "Xen Cluster", + "clustertype": "CloudManaged", + "hypervisor": "XenServer", + }, + 1: { + "clustername": "KVM Cluster", + "clustertype": "CloudManaged", + "hypervisor": "KVM", + }, + 2: { + "hypervisor": 'VMware', + "clustertype": 'ExternalManaged', + "username": 'administrator', + "password": 'fr3sca', + "url": 'http://192.168.100.17/CloudStack-Clogeny-Pune/Pune-1', + "clustername": 'VMWare Cluster', + }, + }, + "hosts": { + "xenserver": { + "hypervisor": 'XenServer', + "clustertype": 'CloudManaged', + "url": 'http://192.168.100.211', + "username": "root", + "password": "fr3sca", + }, + "kvm": { + "hypervisor": 'KVM', + "clustertype": 'CloudManaged', + "url": 'http://192.168.100.212', + "username": "root", + "password": "fr3sca", + }, + "vmware": { + "hypervisor": 'VMware', + "clustertype": 'ExternalManaged', + "url": 'http://192.168.100.203', + "username": "administrator", + "password": "fr3sca", + }, + }, + "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', + }, + }, + "nw_off_isolated_RVR": { + "name": "Network offering-RVR services", + "displaytext": "Network off-RVR services", + "guestiptype": "Isolated", + "supportedservices": "Vpn,Dhcp,Dns,SourceNat,PortForwarding,Firewall,Lb,UserData,StaticNat", + "traffictype": "GUEST", + "availability": "Optional", + "ispersistent": "False", + "serviceProviderList": { + "Vpn": "VirtualRouter", + "Dhcp": "VirtualRouter", + "Dns": "VirtualRouter", + "SourceNat": "VirtualRouter", + "PortForwarding": "VirtualRouter", + "Firewall": "VirtualRouter", + "Lb": "VirtualRouter", + "UserData": "VirtualRouter", + "StaticNat": "VirtualRouter" + }, + "serviceCapabilityList": { + "SourceNat": { + "SupportedSourceNatTypes": "peraccount", + "RedundantRouter": "true" + }, + "lb": { + "SupportedLbIsolation": "dedicated" + } + } + }, + "nw_off_persistent_RVR": { + "name": 'Network offering-RVR services', + "displaytext": 'Network off-RVR services', + "guestiptype": 'Isolated', + "supportedservices": + 'Vpn,Dhcp,Dns,SourceNat,PortForwarding,Firewall,Lb,UserData,StaticNat', + "traffictype": 'GUEST', + "ispersistent": 'True', + "availability": 'Optional', + "serviceProviderList": { + "Vpn": 'VirtualRouter', + "Dhcp": 'VirtualRouter', + "Dns": 'VirtualRouter', + "SourceNat": 'VirtualRouter', + "PortForwarding": 'VirtualRouter', + "Firewall": 'VirtualRouter', + "Lb": 'VirtualRouter', + "UserData": 'VirtualRouter', + "StaticNat": 'VirtualRouter', + }, + "serviceCapabilityList": { + "SourceNat": { + "SupportedSourceNatTypes": "peraccount", + "RedundantRouter": "true", + }, + "lb": { + "SupportedLbIsolation": "dedicated" + }, + }, + }, + "nw_offering_isolated_vpc": { + "name": "Isolated Network for VPC", + "displaytext": "Isolated Network for VPC", + "guestiptype": "Isolated", + "supportedservices": "Dhcp,Dns,SourceNat,PortForwarding,Vpn,UserData,StaticNat,NetworkACL", + "traffictype": "GUEST", + "availability": "Optional", + "ispersistent": "False", + "useVpc": "on", + "serviceProviderList": { + "Dhcp": "VpcVirtualRouter", + "Dns": "VpcVirtualRouter", + "SourceNat": "VpcVirtualRouter", + "PortForwarding": "VpcVirtualRouter", + "Vpn": "VpcVirtualRouter", + "UserData": "VpcVirtualRouter", + "StaticNat": "VpcVirtualRouter", + "NetworkACL": "VpcVirtualRouter" + } + }, + "nw_off_persistent_VPCVR_LB": { + "name": "Persistent Network VPC with LB", + "displaytext": "Persistent Network VPC No LB", + "guestiptype": "Isolated", + "supportedservices": "Dhcp,Dns,SourceNat,PortForwarding,Vpn,Lb,UserData,StaticNat,NetworkACL", + "traffictype": "GUEST", + "availability": "Optional", + "ispersistent": "False", + "useVpc": "on", + "serviceProviderList": { + "Dhcp": "VpcVirtualRouter", + "Dns": "VpcVirtualRouter", + "SourceNat": "VpcVirtualRouter", + "PortForwarding": "VpcVirtualRouter", + "Vpn": "VpcVirtualRouter", + "Lb": "VpcVirtualRouter", + "UserData": "VpcVirtualRouter", + "StaticNat": "VpcVirtualRouter", + "NetworkACL": "VpcVirtualRouter" + } + }, + "nw_off_persistent_VPCVR_NoLB": { + "name": "Persistent Network VPC No LB", + "displaytext": "Persistent Network VPC No LB", + "guestiptype": "Isolated", + "supportedservices": "Dhcp,Dns,SourceNat,PortForwarding,Vpn,UserData,StaticNat,NetworkACL", + "traffictype": "GUEST", + "availability": "Optional", + "ispersistent": "False", + "useVpc": "on", + "serviceProviderList": { + "Dhcp": "VpcVirtualRouter", + "Dns": "VpcVirtualRouter", + "SourceNat": "VpcVirtualRouter", + "PortForwarding": "VpcVirtualRouter", + "Vpn": "VpcVirtualRouter", + "UserData": "VpcVirtualRouter", + "StaticNat": "VpcVirtualRouter", + "NetworkACL": "VpcVirtualRouter" + } + }, + "nw_offering_shared_persistent": { + "name": "Network offering for Shared Persistent Network", + "displaytext": "Network offering-DA services", + "guestiptype": "Shared", + "supportedservices": "Dhcp,Dns,SourceNat,PortForwarding,Vpn,Firewall,Lb,UserData,StaticNat", + "traffictype": "GUEST", + "availability": "Optional", + "ispersistent": "True", + "serviceProviderList": { + "Dhcp": "VirtualRouter", + "Dns": "VirtualRouter", + "SourceNat": "VirtualRouter", + "PortForwarding": "VirtualRouter", + "Vpn": "VirtualRouter", + "Firewall": "VirtualRouter", + "Lb": "VirtualRouter", + "UserData": "VirtualRouter", + "StaticNat": "VirtualRouter" + } + }, + "fwrule": { + "startport": 22, + "endport": 22, + "cidr": "0.0.0.0/0", + "protocol": "TCP" + }, + "nw_off_isolated_persistent_netscaler": { + "name": 'Netscaler', + "displaytext": 'Netscaler', + "guestiptype": 'Isolated', + "supportedservices": + 'Dhcp,Dns,SourceNat,PortForwarding,Vpn,Firewall,Lb,UserData,StaticNat', + "traffictype": 'GUEST', + "ispersistent": 'True', + "availability": 'Optional', + "serviceProviderList": { + "Dhcp": 'VirtualRouter', + "Dns": 'VirtualRouter', + "SourceNat": 'VirtualRouter', + "PortForwarding": 'VirtualRouter', + "Vpn": 'VirtualRouter', + "Firewall": 'VirtualRouter', + "Lb": 'Netscaler', + "UserData": 'VirtualRouter', + "StaticNat": 'VirtualRouter', + }, + + }, + "nw_off_persistent_VPCVR_NoLB": { + "name": 'VPC Network offering', + "displaytext": 'VPC Network off', + "guestiptype": 'Isolated', + "supportedservices": + 'Vpn,Dhcp,Dns,SourceNat,PortForwarding,UserData,StaticNat,NetworkACL', + "traffictype": 'GUEST', + "availability": 'Optional', + "ispersistent": 'True', + "useVpc": 'on', + "serviceProviderList": { + "Vpn": 'VpcVirtualRouter', + "Dhcp": 'VpcVirtualRouter', + "Dns": 'VpcVirtualRouter', + "SourceNat": 'VpcVirtualRouter', + "PortForwarding": 'VpcVirtualRouter', + "UserData": 'VpcVirtualRouter', + "StaticNat": 'VpcVirtualRouter', + "NetworkACL": 'VpcVirtualRouter' + }, + + }, + "network_offering_internal_lb": { + "name": "Network offering for internal lb service", + "displaytext": "Network offering for internal lb service", + "guestiptype": "Isolated", + "traffictype": "Guest", + "supportedservices": + "Vpn,Dhcp,Dns,Lb,UserData,SourceNat,StaticNat,PortForwarding,NetworkACL", + "serviceProviderList": { + "Dhcp": "VpcVirtualRouter", + "Dns": "VpcVirtualRouter", + "Vpn": "VpcVirtualRouter", + "UserData": "VpcVirtualRouter", + "Lb": "InternalLbVM", + "SourceNat": "VpcVirtualRouter", + "StaticNat": "VpcVirtualRouter", + "PortForwarding": "VpcVirtualRouter", + "NetworkACL": "VpcVirtualRouter", + }, + "serviceCapabilityList": { + "SourceNat": {"SupportedSourceNatTypes": "peraccount"}, + "Lb": {"lbSchemes": "internal", "SupportedLbIsolation": "dedicated"} + } + }, + "natrule": { + "privateport": 22, + "publicport": 2222, + "protocol": "TCP" + }, + "lbrule": { + "name": "SSH", + "alg": "roundrobin", + "privateport": 22, + "publicport": 2222, + "protocol": 'TCP' + }, + "icmprule": { + "icmptype": -1, + "icmpcode": -1, + "cidrlist": "0.0.0.0/0", + "protocol": "ICMP" + }, + "iso": { + "displaytext": "Test ISO", + "name": "ISO", + "url": "http://people.apache.org/~tsp/dummy.iso", + "bootable": False, + "ispublic": False, + "ostype": "CentOS 5.6 (64-bit)", + }, + "iso1": { + "displaytext": "Test ISO 1", + "name": "ISO 1", + "url": "http://people.apache.org/~tsp/dummy.iso", + "isextractable": True, + "isfeatured": True, + "ispublic": True, + "ostype": "CentOS 5.6 (64-bit)", + }, + "iso2": { + "displaytext": "Test ISO 2", + "name": "ISO 2", + "url": "http://people.apache.org/~tsp/dummy.iso", + "isextractable": True, + "isfeatured": True, + "ispublic": True, + "ostype": "CentOS 5.6 (64-bit)", + "mode": 'HTTP_DOWNLOAD', + }, + "isfeatured": True, + "ispublic": True, + "isextractable": True, + "bootable": True, + "passwordenabled": True, + + "template": { + "displaytext": "xs", + "name": "xs", + "passwordenabled": False, + }, + "template_2": { + "displaytext": "Public Template", + "name": "Public template", + "ostype": "CentOS 5.6 (64-bit)", + "isfeatured": True, + "ispublic": True, + "isextractable": True, + "mode": "HTTP_DOWNLOAD", + }, + "templatefilter": 'self', + + "templates": { + "displaytext": 'Template', + "name": 'Template', + "ostype": "CentOS 5.3 (64-bit)", + "templatefilter": 'self', + }, + "security_group": {"name": "custom_Sec_Grp"}, + "ingress_rule": { + "protocol": "TCP", + "startport": "22", + "endport": "22", + "cidrlist": "0.0.0.0/0" + }, + "vpncustomergateway": { + "ipsecpsk": "secreatKey", + "ikepolicy": "aes128-sha1", + "ikelifetime": "86400", + "esppolicy": "aes128-sha1", + "epslifetime": "3600", + "dpd": "false" + }, + "ostype": "CentOS 5.6 (64-bit)", + "sleep": 90, + "timeout": 10, + "page": 1, + "pagesize": 2, + "listall": 'true', + "host_password": "password", + "advanced_sg": { + "zone": { + "name": "", + "dns1": "8.8.8.8", + "internaldns1": "192.168.100.1", + "networktype": "Advanced", + "securitygroupenabled": "true" + }, + "securitygroupenabled": "true" + }, + "vlan": "10", + "portableiprange_vlan": { + "part": ["4090-4091", "4092-4095"], + "full": "4090-4095" + }, + "nfs": { + "url": "nfs://nfs/export/automation/1/testprimary", + "name": "Primary XEN" + }, + "iscsi": { + "url": + "iscsi://192.168.100.21/iqn.2012-01.localdomain.clo-cstack-cos6:iser/1", + "name": "Primary iSCSI" + }, + "volume": {"diskname": "Test Volume"}, + "custom_volume": { + "customdisksize": 1, + "diskname": "Custom disk", + }, + "upload_volume": { + "diskname": "UploadVol", + "format": "VHD", + "url": + "http://10.147.28.7/templates/393d3550-05ef-330f-9b8c-745b0e699759.vhd", + "checksum": "", + }, + "recurring_snapshot": { + "maxsnaps": 2, + "timezone": "US/Arizona", + }, + "volume_offerings": { + 0: {"diskname": "TestDiskServ"}, + }, + "diskdevice": ['/dev/vdc', '/dev/vdb', '/dev/hdb', '/dev/hdc', + '/dev/xvdd', '/dev/cdrom', '/dev/sr0', '/dev/cdrom1'], + + # test_vpc_vpn.py + "vpn_user": { + "username": "test", + "password": "password", + }, + "vpc": { + "name": "vpc_vpn", + "displaytext": "vpc-vpn", + "cidr": "10.1.1.0/24" + }, + "ntwk": { + "name": "tier1", + "displaytext": "vpc-tier1", + "gateway": "10.1.1.1", + "netmask": "255.255.255.192" + }, + "vpc2": { + "name": "vpc2_vpn", + "displaytext": "vpc2-vpn", + "cidr": "10.2.1.0/24" + }, + "ntwk2": { + "name": "tier2", + "displaytext": "vpc-tier2", + "gateway": "10.2.1.1", + "netmask": "255.255.255.192" + }, + "server": { + "displayname": "TestVM", + "username": "root", + "password": "password", + "ssh_port": 22, + "hypervisor": 'XenServer', + "privateport": 22, + "publicport": 22, + "protocol": 'TCP' + }, + "privateport": 22, + "publicport": 22, + "protocol": 'TCP', + "forvirtualnetwork": "true", + "customdisksize": 1, + "diskname": "Test Volume", + "portableIpRange": { + "gateway": "10.223.252.195", + "netmask": "255.255.255.192", + "startip": "10.223.252.196", + "endip": "10.223.252.197", + "vlan": "1001" + }, + "sparse": { + "name": "Sparse Type Disk offering", + "displaytext": + "Sparse Type Disk offering", + "disksize": 1, # in GB + "provisioningtype": "sparse" + }, + "fat": { + "name": "Fat Type Disk offering", + "displaytext": + "Fat Type Disk offering", + "disksize": 1, # in GB + "provisioningtype": "fat" + }, + "sparse_disk_offering": { + "displaytext": "Sparse", + "name": "Sparse", + "provisioningtype": "sparse", + "disksize": 1 + }, + "host_anti_affinity": { + "name": "hostantiaffinity", + "type": "host anti-affinity", + }, +} diff --git a/tools/marvin/marvin/configGenerator.py b/tools/marvin/marvin/configGenerator.py index 0b4a0a132b..66609da751 100644 --- a/tools/marvin/marvin/configGenerator.py +++ b/tools/marvin/marvin/configGenerator.py @@ -20,9 +20,12 @@ from optparse import OptionParser import jsonHelper from marvin.codes import * +from marvin.cloudstackException import GetDetailExceptionInfo +from marvin.config.test_data import test_data class managementServer(object): + def __init__(self): self.mgtSvrIp = None self.port = 8096 @@ -34,6 +37,7 @@ def __init__(self): class dbServer(object): + def __init__(self): self.dbSvr = None self.port = 3306 @@ -43,27 +47,31 @@ def __init__(self): class configuration(object): + def __init__(self): self.name = None self.value = None class logger(object): + def __init__(self): - '''TestCase/TestClient''' - self.logFolderPath = None + self.LogFolderPath = None class cloudstackConfiguration(object): + def __init__(self): self.zones = [] self.mgtSvr = [] self.dbSvr = None self.globalConfig = [] self.logger = None + self.TestData = None class zone(object): + def __init__(self): self.dns1 = None self.internaldns1 = None @@ -83,6 +91,7 @@ def __init__(self): class trafficType(object): + def __init__(self, typ, labeldict=None): self.typ = typ # Guest/Management/Public if labeldict: @@ -95,6 +104,7 @@ def __init__(self, typ, labeldict=None): class pod(object): + def __init__(self): self.gateway = None self.name = None @@ -109,6 +119,7 @@ def __init__(self): class VmwareDc(object): + def __init__(self): self.zoneid = None self.name = None @@ -118,6 +129,7 @@ def __init__(self): class cluster(object): + def __init__(self): self.clustername = None self.clustertype = None @@ -132,6 +144,7 @@ def __init__(self): class host(object): + def __init__(self): self.hypervisor = None self.password = None @@ -149,6 +162,7 @@ def __init__(self): class physicalNetwork(object): + def __init__(self): self.name = None self.tags = [] @@ -163,6 +177,7 @@ def __init__(self): class provider(object): + def __init__(self, name=None): self.name = name self.state = None @@ -173,6 +188,7 @@ def __init__(self, name=None): class network(object): + def __init__(self): self.displaytext = None self.name = None @@ -185,6 +201,7 @@ def __init__(self): class iprange(object): + def __init__(self): '''tagged/untagged''' self.gateway = None @@ -198,12 +215,14 @@ def __init__(self): class primaryStorage(object): + def __init__(self): self.name = None self.url = None class secondaryStorage(object): + def __init__(self): self.url = None self.provider = None @@ -211,6 +230,7 @@ def __init__(self): class cacheStorage(object): + def __init__(self): self.url = None self.provider = None @@ -218,6 +238,7 @@ def __init__(self): class s3(object): + def __init__(self): self.accesskey = None self.secretkey = None @@ -230,6 +251,7 @@ def __init__(self): class netscaler(object): + def __init__(self, hostname=None, username='nsroot', password='nsroot'): self.hostname = hostname self.username = username @@ -246,11 +268,12 @@ def getUrl(self): def __repr__(self): req = zip(self.__dict__.keys(), self.__dict__.values()) - return self.hostname+"?" + "&".join(["=".join([r[0], r[1]]) - for r in req]) + return self.hostname + "?" + "&".join(["=".join([r[0], r[1]]) + for r in req]) class srx(object): + def __init__(self, hostname=None, username='root', password='admin'): self.hostname = hostname self.username = username @@ -269,11 +292,12 @@ def getUrl(self): def __repr__(self): req = zip(self.__dict__.keys(), self.__dict__.values()) - return self.hostname+"?" + "&".join(["=".join([r[0], r[1]]) - for r in req]) + return self.hostname + "?" + "&".join(["=".join([r[0], r[1]]) + for r in req]) class bigip(object): + def __init__(self, hostname=None, username='root', password='default'): self.hostname = hostname self.username = username @@ -290,14 +314,14 @@ def getUrl(self): def __repr__(self): req = zip(self.__dict__.keys(), self.__dict__.values()) - return self.hostname+"?" + "&".join(["=".join([r[0], r[1]]) - for r in req]) + return self.hostname + "?" + "&".join(["=".join([r[0], r[1]]) + for r in req]) class ConfigManager(object): ''' - @Name: configManager + @Name: ConfigManager @Desc: 1. It provides the basic configuration facilities to marvin. 2. User can just add configuration files for his tests, deployment etc, under one config folder before running their tests. @@ -328,16 +352,21 @@ class ConfigManager(object): "getConfig" API,once configObj is returned. ''' - def __init__(self): - # Joining path with current directory will avoid relative path issue - # It will take correct path irrespective of from where the test case is run - dirPath = os.path.dirname(__file__) - self.filePath = os.path.join(dirPath, 'config/config.cfg') - self.parsedDict = None - if self.__verifyFile(self.filePath) is not False: - self.parsedDict = self.__parseConfig(self.filePath) - - def __parseConfig(self, file): + def __init__(self, cfg_file=None): + self.__filePath = cfg_file + self.__parsedCfgDict = None + ''' + Set the Configuration + ''' + self.__setConfig() + + def __setConfig(self): + if not self.__verifyFile(): + dirPath = os.path.dirname(__file__) + self.__filePath = str(os.path.join(dirPath, "config/test_data.py")) + self.__parsedCfgDict = self.__parseConfig() + + def __parseConfig(self): ''' @Name : __parseConfig @Description: Parses the Input configuration Json file @@ -348,36 +377,38 @@ def __parseConfig(self, file): ''' config_dict = None try: - configlines = [] - with open(file, 'r') as fp: - for line in fp: - if len(line) != 0: + if self.__filePath.endswith(".py"): + config_dict = test_data + else: + configLines = [] + with open(self.__filePath, 'r') as fp: + for line in fp: ws = line.strip() - if ws[0] not in ["#"]: - configlines.append(ws) - config_dict = json.loads("\n".join(configlines)) - except Exception, e: - #Will replace with log once we have logging done - print "\n Exception occurred under __parseConfig", e + if not ws.startswith("#"): + configLines.append(ws) + config = json.loads("\n".join(configLines)) + config_dict = config + except Exception as e: + # Will replace with log once we have logging done + print "\n Exception occurred under ConfigManager:__parseConfig" \ + " :%s", GetDetailExceptionInfo(e) finally: return config_dict - def __verifyFile(self, file): + def __verifyFile(self): ''' @Name : __parseConfig @Description: Parses the Input configuration Json file and returns a dictionary from the file. - @Input : file NA + @Input : NA @Output : True or False based upon file input validity and availability ''' - if file is None or file == '': - return False - if os.path.exists(file) is False: + if self.__filePath is None or self.__filePath == '': return False - return True + return os.path.exists(self.__filePath) - def __getSectionData(self, return_dict, section=None): + def getSectionData(self, section=None): ''' @Name: getSectionData @Desc: Gets the Section data of a particular section @@ -386,43 +417,30 @@ def __getSectionData(self, return_dict, section=None): section to be returned from this dict @Output:Section matching inside the parsed data ''' - if return_dict is not None: - inp = return_dict - elif self.parsedDict is None: + if self.__parsedCfgDict is None or section is None: + print "\nEither Parsed Dictionary is None or Section is None" return INVALID_INPUT - else: - inp = self.parsedDict - if section is not None: - return inp.get(section) - else: - return inp + return self.__parsedCfgDict.get(section) - def getConfig(self, file_path=None, section=None): + def getConfig(self): ''' - @Name: getConfig - @Desc : Parses and converts the given configuration file to dictionary - @Input : file_path: path where the configuration needs to be passed - section: specific section inside the file - @Output: INVALID_INPUT: This value is returned if the input - is invalid or not able to be parsed - Parsed configuration dictionary from json file + @Name : getConfig + @Desc : Returns the Parsed Dictionary of Config Provided + @Input : NA + @Output: ParsedDict if successful if cfg file provided is valid + None if cfg file is invalid or not able to be parsed ''' - ret = None - if file not in [None, '']: - if self.__verifyFile(file_path) is False: - return INVALID_INPUT - else: - ret = self.__parseConfig(file_path) - return self.__getSectionData(ret, section) + out = self.__parsedCfgDict + return out def getDeviceUrl(obj): req = zip(obj.__dict__.keys(), obj.__dict__.values()) if obj.hostname: - return "http://" + obj.hostname+"?" + "&".join(["=".join([r[0], - r[1]]) - for r in req]) + return "http://" + obj.hostname + "?" + "&".join(["=".join([r[0], + r[1]]) + for r in req]) else: return None @@ -437,11 +455,11 @@ def descSetupInBasicMode(): z.dns2 = "8.8.4.4" z.internaldns1 = "192.168.110.254" z.internaldns2 = "192.168.110.253" - z.name = "test"+str(l) + z.name = "test" + str(l) z.networktype = 'Basic' z.securitygroupenabled = 'True' - #If security groups are reqd + # If security groups are reqd sgprovider = provider() sgprovider.broadcastdomainrange = 'Pod' sgprovider.name = 'SecurityGroupProvider' @@ -467,15 +485,15 @@ def descSetupInBasicMode(): ip = iprange() ip.gateway = p.gateway ip.netmask = p.netmask - ip.startip = "192.168.%d.%d" % (i, j*20) - ip.endip = "192.168.%d.%d" % (i, j*20+10) + ip.startip = "192.168.%d.%d" % (i, j * 20) + ip.endip = "192.168.%d.%d" % (i, j * 20 + 10) p.guestIpRanges.append(ip) '''add 10 clusters''' for j in range(2): c = cluster() - c.clustername = "test"+str(l)+str(i) + str(j) + c.clustername = "test" + str(l) + str(i) + str(j) c.clustertype = "CloudManaged" c.hypervisor = "Simulator" @@ -484,15 +502,16 @@ def descSetupInBasicMode(): h = host() h.username = "root" h.password = "password" - memory = 8*1024*1024*1024 - localstorage = 1*1024*1024*1024*1024 + memory = 8 * 1024 * 1024 * 1024 + localstorage = 1 * 1024 * 1024 * 1024 * 1024 h.url = "http://sim/%d%d%d%d" % (l, i, j, k) c.hosts.append(h) '''add 2 primary storages''' for m in range(2): primary = primaryStorage() - primary.name = "primary"+str(l) + str(i) + str(j) + str(m) + primary.name = "primary" + \ + str(l) + str(i) + str(j) + str(m) primary.url = "nfs://localhost/path%s" % (str(l) + str(i) + str(j) + str(m)) c.primaryStorages.append(primary) @@ -504,7 +523,7 @@ def descSetupInBasicMode(): '''add two secondary''' for i in range(5): secondary = secondaryStorage() - secondary.url = "nfs://localhost/path"+str(l) + str(i) + secondary.url = "nfs://localhost/path" + str(l) + str(i) z.secondaryStorages.append(secondary) zs.zones.append(z) @@ -546,7 +565,7 @@ def descSetupInEipMode(): z.dns2 = "8.8.4.4" z.internaldns1 = "192.168.110.254" z.internaldns2 = "192.168.110.253" - z.name = "test"+str(l) + z.name = "test" + str(l) z.networktype = 'Basic' ips = iprange() @@ -557,7 +576,7 @@ def descSetupInEipMode(): ips.netmask = "255.255.255.0" z.ipranges.append(ips) - #If security groups are reqd + # If security groups are reqd sgprovider = provider() sgprovider.broadcastdomainrange = 'Pod' sgprovider.name = 'SecurityGroupProvider' @@ -591,15 +610,15 @@ def descSetupInEipMode(): ip = iprange() ip.gateway = p.gateway ip.netmask = p.netmask - ip.startip = "192.168.%d.%d" % (i, j*20) - ip.endip = "192.168.%d.%d" % (i, j*20+10) + ip.startip = "192.168.%d.%d" % (i, j * 20) + ip.endip = "192.168.%d.%d" % (i, j * 20 + 10) p.guestIpRanges.append(ip) '''add 10 clusters''' for j in range(2): c = cluster() - c.clustername = "test"+str(l)+str(i) + str(j) + c.clustername = "test" + str(l) + str(i) + str(j) c.clustertype = "CloudManaged" c.hypervisor = "Simulator" @@ -614,7 +633,8 @@ def descSetupInEipMode(): '''add 2 primary storages''' for m in range(2): primary = primaryStorage() - primary.name = "primary"+str(l) + str(i) + str(j) + str(m) + primary.name = "primary" + \ + str(l) + str(i) + str(j) + str(m) primary.url = "nfs://localhost/path%s" % (str(l) + str(i) + str(j) + str(m)) @@ -627,7 +647,7 @@ def descSetupInEipMode(): '''add two secondary''' for i in range(5): secondary = secondaryStorage() - secondary.url = "nfs://localhost/path"+str(l) + str(i) + secondary.url = "nfs://localhost/path" + str(l) + str(i) z.secondaryStorages.append(secondary) zs.zones.append(z) @@ -667,7 +687,7 @@ def descSetupInAdvancedMode(): z.dns2 = "8.8.4.4" z.internaldns1 = "192.168.110.254" z.internaldns2 = "192.168.110.253" - z.name = "test"+str(l) + z.name = "test" + str(l) z.networktype = 'Advanced' z.guestcidraddress = "10.1.1.0/24" z.vlan = "100-2000" @@ -703,7 +723,7 @@ def descSetupInAdvancedMode(): '''add 10 clusters''' for j in range(2): c = cluster() - c.clustername = "test"+str(l)+str(i) + str(j) + c.clustername = "test" + str(l) + str(i) + str(j) c.clustertype = "CloudManaged" c.hypervisor = "Simulator" @@ -714,7 +734,7 @@ def descSetupInAdvancedMode(): h.password = "password" memory = 8 * 1024 * 1024 * 1024 localstorage = 1 * 1024 * 1024 * 1024 * 1024 - #h.url = "http://sim/%d%d%d%d/cpucore=1&cpuspeed=8000&\ + # h.url = "http://sim/%d%d%d%d/cpucore=1&cpuspeed=8000&\ # memory=%d&localstorage=%d"%(l, i, j, k, memory, # localstorage) h.url = "http://sim/%d%d%d%d" % (l, i, j, k) @@ -723,8 +743,9 @@ def descSetupInAdvancedMode(): '''add 2 primary storages''' for m in range(2): primary = primaryStorage() - primary.name = "primary"+str(l) + str(i) + str(j) + str(m) - #primary.url = "nfs://localhost/path%s/size=%d" % + primary.name = "primary" + \ + str(l) + str(i) + str(j) + str(m) + # primary.url = "nfs://localhost/path%s/size=%d" % # (str(l) + str(i) + str(j) + str(m), size) primary.url = "nfs://localhost/path%s" % (str(l) + str(i) + str(j) @@ -738,7 +759,7 @@ def descSetupInAdvancedMode(): '''add two secondary''' for i in range(5): secondary = secondaryStorage() - secondary.url = "nfs://localhost/path"+str(l) + str(i) + secondary.url = "nfs://localhost/path" + str(l) + str(i) z.secondaryStorages.append(secondary) '''add default public network''' @@ -788,7 +809,7 @@ def descSetupInAdvancedsgMode(): z.dns2 = "8.8.4.4" z.internaldns1 = "192.168.110.254" z.internaldns2 = "192.168.110.253" - z.name = "test"+str(l) + z.name = "test" + str(l) z.networktype = 'Advanced' z.vlan = "100-2000" z.securitygroupenabled = "true" @@ -797,7 +818,7 @@ def descSetupInAdvancedsgMode(): pn.name = "test-network" pn.traffictypes = [trafficType("Guest"), trafficType("Management")] - #If security groups are reqd + # If security groups are reqd sgprovider = provider() sgprovider.broadcastdomainrange = 'ZONE' sgprovider.name = 'SecurityGroupProvider' @@ -817,7 +838,7 @@ def descSetupInAdvancedsgMode(): '''add 10 clusters''' for j in range(2): c = cluster() - c.clustername = "test"+str(l)+str(i) + str(j) + c.clustername = "test" + str(l) + str(i) + str(j) c.clustertype = "CloudManaged" c.hypervisor = "Simulator" @@ -828,18 +849,17 @@ def descSetupInAdvancedsgMode(): h.password = "password" memory = 8 * 1024 * 1024 * 1024 localstorage = 1 * 1024 * 1024 * 1024 * 1024 - #h.url = "http://sim/%d%d%d%d/cpucore=1&cpuspeed=8000&\ - #memory=%d&localstorage=%d" % (l, i, j, k, memory, - #localstorage) + # h.url = "http://sim/%d%d%d%d/cpucore=1&cpuspeed=8000&\ + # memory=%d&localstorage=%d" % (l, i, j, k, memory, + # localstorage) h.url = "http://sim/%d%d%d%d" % (l, i, j, k) c.hosts.append(h) '''add 2 primary storages''' for m in range(2): primary = primaryStorage() - primary.name = "primary"+str(l) + str(i) + str(j) + str(m) - #primary.url = "nfs://localhost/path%s/size=%d" % \ - #(str(l) + str(i) + str(j) + str(m), size) + primary.name = "primary" + \ + str(l) + str(i) + str(j) + str(m) primary.url = "nfs://localhost/path%s" % \ (str(l) + str(i) + str(j) + str(m)) c.primaryStorages.append(primary) @@ -851,7 +871,7 @@ def descSetupInAdvancedsgMode(): '''add two secondary''' for i in range(5): secondary = secondaryStorage() - secondary.url = "nfs://localhost/path"+str(l) + str(i) + secondary.url = "nfs://localhost/path" + str(l) + str(i) z.secondaryStorages.append(secondary) '''add default guest network''' @@ -901,18 +921,19 @@ def generate_setup_config(config, file=None): def getSetupConfig(file): - if not os.path.exists(file): - raise IOError("config file %s not found. \ - please specify a valid config file" % file) - config = cloudstackConfiguration() - configLines = [] - with open(file, 'r') as fp: - for line in fp: - ws = line.strip() - if not ws.startswith("#"): - configLines.append(ws) - config = json.loads("\n".join(configLines)) - return jsonHelper.jsonLoader(config) + try: + config = cloudstackConfiguration() + configLines = [] + with open(file, 'r') as fp: + for line in fp: + ws = line.strip() + if not ws.startswith("#"): + configLines.append(ws) + config = json.loads("\n".join(configLines)) + return jsonHelper.jsonLoader(config) + except Exception as e: + print "\nException Occurred under getSetupConfig %s" % \ + GetDetailExceptionInfo(e) if __name__ == "__main__": parser = OptionParser() diff --git a/tools/marvin/marvin/dbConnection.py b/tools/marvin/marvin/dbConnection.py index 99014abfa2..66c6cb1773 100644 --- a/tools/marvin/marvin/dbConnection.py +++ b/tools/marvin/marvin/dbConnection.py @@ -20,12 +20,13 @@ from mysql import connector from mysql.connector import errors from contextlib import closing -import cloudstackException +from marvin import cloudstackException import sys import os -class dbConnection(object): +class DbConnection(object): + def __init__(self, host="localhost", port=3306, user='cloud', passwd='cloud', db='cloud'): self.host = host @@ -51,7 +52,7 @@ def execute(self, sql=None, params=None): try: resultRow = cursor.fetchall() except errors.InterfaceError: - #Raised on empty result - DML + # Raised on empty result - DML resultRow = [] return resultRow @@ -68,7 +69,7 @@ def executeSqlFromFile(self, fileName=None): return self.execute(sqls) if __name__ == "__main__": - db = dbConnection() + db = DbConnection() ''' try: diff --git a/tools/marvin/marvin/deployAndRun.py b/tools/marvin/marvin/deployAndRun.py index 56747a7cb2..9f392e5e5a 100644 --- a/tools/marvin/marvin/deployAndRun.py +++ b/tools/marvin/marvin/deployAndRun.py @@ -15,13 +15,13 @@ # specific language governing permissions and limitations # under the License. -from tcExecuteEngine import TestCaseExecuteEngine +from .tcExecuteEngine import TestCaseExecuteEngine import sys import os import traceback import time from argparse import ArgumentParser -from marvinInit import MarvinInit +from .marvinInit import MarvinInit from marvin.codes import (SUCCESS, FAILED, EXCEPTION, @@ -96,9 +96,9 @@ def startMarvin(cfg_file, load_flag): else: print "\nMarvin Initialization Failed" exit(1) - except Exception, e: - print "\n Exception occurred while starting Marvin %s" % str(e) - exit(1) + except Exception as e: + print "\n Exception occurred while starting Marvin %s" % str(e) + exit(1) def runTCs(num_iter, inp1, inp2): diff --git a/tools/marvin/marvin/deployDataCenter.py b/tools/marvin/marvin/deployDataCenter.py index c4f6e1e137..4d8be5826c 100644 --- a/tools/marvin/marvin/deployDataCenter.py +++ b/tools/marvin/marvin/deployDataCenter.py @@ -15,462 +15,775 @@ # specific language governing permissions and limitations # under the License. -"""Deploy datacenters according to a json configuration file""" -import configGenerator -import cloudstackException -import cloudstackTestClient -import logging -from cloudstackAPI import * -from os import path -from time import sleep +""" +@Desc : +class DeployDataCenters: Deploys DeleteDataCenters according to a json + configuration file. +class DeleteDataCenters: Deletes a DataCenter based upon the dc cfg + settings provided. + This settings file is the exported + configuration from DeployDataCenters post + its success +""" +from marvin import configGenerator +from marvin.cloudstackException import ( + InvalidParameterException, + GetDetailExceptionInfo) +from marvin.cloudstackAPI import * +from marvin.codes import (FAILED, SUCCESS) +from marvin.lib.utils import (random_gen) +from marvin.config.test_data import test_data +from sys import exit +import os +import pickle +from time import sleep, strftime, localtime from optparse import OptionParser -class deployDataCenters(object): - - def __init__(self, cfg, logger=None): - self.config = cfg - self.tcRunLogger = logger +class DeployDataCenters(object): + + ''' + @Desc : Deploys the Data Center with information provided. + Once the Deployment is successful, it will export + the DataCenter settings to an obj file + ( can be used if wanted to delete the created DC) + ''' + + def __init__(self, + test_client, + cfg, + logger=None, + log_folder_path=None + ): + self.__testClient = test_client + self.__config = cfg + self.__tcRunLogger = logger + self.__logFolderPath = log_folder_path + self.__apiClient = None + self.__cleanUp = {} + + def __persistDcConfig(self): + try: + if self.__logFolderPath: + dc_file_path = self.__logFolderPath + "/dc_entries.obj" + else: + ts = strftime("%b_%d_%Y_%H_%M_%S", localtime()) + dc_file_path = "dc_entries_" + str(ts) + ".obj" + file_to_write = open(dc_file_path, 'w') + if file_to_write: + pickle.dump(self.__cleanUp, file_to_write) + print "\n=== Data Center Settings are dumped to %s===" % \ + dc_file_path + self.__tcRunLogger.debug( + "\n=== Data Center Settings are dumped to %s===" % + dc_file_path) + except Exception as e: + print "Exception Occurred while persisting DC Settings: %s" % \ + GetDetailExceptionInfo(e) + + def __cleanAndExit(self): + try: + print "\n===deploy dc failed, so cleaning the created entries===" + if not test_data.get("deleteDC", None): + print "\n=== Deploy DC Clean Up flag not set. So, exiting ===" + exit(1) + self.__tcRunLogger.debug( + "===Deploy DC Failed, So Cleaning to Exit===") + remove_dc_obj = DeleteDataCenters(self.__testClient, + dc_cfg=self.__cleanUp, + tc_run_logger=self.__tcRunLogger + ) + if remove_dc_obj: + if remove_dc_obj.removeDataCenter() == FAILED: + print "\n===Removing DataCenter Failed===" + self.__tcRunLogger.debug( + "===Removing DataCenter Failed===") + else: + print "\n===Removing DataCenter Successful===" + self.__tcRunLogger.debug( + "===Removing DataCenter Successful===") + exit(1) + except Exception as e: + print "Exception Occurred during DC CleanUp: %s" % \ + GetDetailExceptionInfo(e) + + def __addToCleanUp(self, type, id): + if type not in self.__cleanUp.keys(): + self.__cleanUp[type] = [] + self.__cleanUp[type].append(id) + if "order" not in self.__cleanUp.keys(): + self.__cleanUp["order"] = [] + if type not in self.__cleanUp["order"]: + self.__cleanUp["order"].append(type) def addHosts(self, hosts, zoneId, podId, clusterId, hypervisor): - if hosts is None: - return - for host in hosts: - hostcmd = addHost.addHostCmd() - hostcmd.clusterid = clusterId - hostcmd.cpunumber = host.cpunumer - hostcmd.cpuspeed = host.cpuspeed - hostcmd.hostmac = host.hostmac - hostcmd.hosttags = host.hosttags - hostcmd.hypervisor = host.hypervisor - hostcmd.memory = host.memory - hostcmd.password = host.password - hostcmd.podid = podId - hostcmd.url = host.url - hostcmd.username = host.username - hostcmd.zoneid = zoneId - hostcmd.hypervisor = hypervisor - self.apiClient.addHost(hostcmd) + try: + if hosts is None: + return + for host in hosts: + hostcmd = addHost.addHostCmd() + hostcmd.clusterid = clusterId + hostcmd.cpunumber = host.cpunumer + hostcmd.cpuspeed = host.cpuspeed + hostcmd.hostmac = host.hostmac + hostcmd.hosttags = host.hosttags + hostcmd.hypervisor = host.hypervisor + hostcmd.memory = host.memory + hostcmd.password = host.password + hostcmd.podid = podId + hostcmd.url = host.url + hostcmd.username = host.username + hostcmd.zoneid = zoneId + hostcmd.hypervisor = hypervisor + ret = self.__apiClient.addHost(hostcmd) + if ret: + self.__tcRunLogger.debug("=== Add Host Successful ===") + self.__addToCleanUp("Host", ret[0].id) + except Exception as e: + print "Exception Occurred %s" % GetDetailExceptionInfo(e) + self.__tcRunLogger.exception("=== Adding Host Failed ===") + self.__cleanAndExit() def addVmWareDataCenter(self, vmwareDc): - vdc = addVmwareDc.addVmwareDcCmd() - vdc.zoneid = vmwareDc.zoneid - vdc.name = vmwareDc.name - vdc.vcenter = vmwareDc.vcenter - vdc.username = vmwareDc.username - vdc.password = vmwareDc.password - self.apiClient.addVmwareDc(vdc) + try: + vdc = addVmwareDc.addVmwareDcCmd() + vdc.zoneid = vmwareDc.zoneid + vdc.name = vmwareDc.name + vdc.vcenter = vmwareDc.vcenter + vdc.username = vmwareDc.username + vdc.password = vmwareDc.password + ret = self.__apiClient.addVmwareDc(vdc) + if ret.id: + self.__tcRunLogger.debug("=== Adding VmWare DC Successful===") + self.__addToCleanUp("VmwareDc", ret.id) + except Exception as e: + print "Exception Occurred: %s" % GetDetailExceptionInfo(e) + self.__tcRunLogger.exception("=== Adding VmWare DC Failed===") + self.__cleanAndExit() def createClusters(self, clusters, zoneId, podId, vmwareDc=None): - if clusters is None: - return - - if vmwareDc is not None: - vmwareDc.zoneid = zoneId - self.addVmWareDataCenter(vmwareDc) - - for cluster in clusters: - clustercmd = addCluster.addClusterCmd() - clustercmd.clustername = cluster.clustername - clustercmd.clustertype = cluster.clustertype - clustercmd.hypervisor = cluster.hypervisor - clustercmd.password = cluster.password - clustercmd.podid = podId - clustercmd.url = cluster.url - clustercmd.username = cluster.username - clustercmd.zoneid = zoneId - clusterresponse = self.apiClient.addCluster(clustercmd) - clusterId = clusterresponse[0].id - - if cluster.hypervisor.lower() != "vmware": - self.addHosts(cluster.hosts, zoneId, podId, clusterId, - cluster.hypervisor) - self.waitForHost(zoneId, clusterId) - self.createPrimaryStorages(cluster.primaryStorages, zoneId, podId, - clusterId) + try: + if clusters is None: + return + if vmwareDc is not None: + vmwareDc.zoneid = zoneId + self.addVmWareDataCenter(vmwareDc) + + for cluster in clusters: + clustercmd = addCluster.addClusterCmd() + clustercmd.clustername = cluster.clustername + clustercmd.clustertype = cluster.clustertype + clustercmd.hypervisor = cluster.hypervisor + clustercmd.password = cluster.password + clustercmd.podid = podId + clustercmd.url = cluster.url + clustercmd.username = cluster.username + clustercmd.zoneid = zoneId + clusterresponse = self.__apiClient.addCluster(clustercmd) + if clusterresponse[0].id: + clusterId = clusterresponse[0].id + self.__tcRunLogger.\ + debug("Cluster Name : %s Id : %s Created Successfully" + % (str(cluster.clustername), str(clusterId))) + self.__addToCleanUp("Cluster", clusterId) + if cluster.hypervisor.lower() != "vmware": + self.addHosts(cluster.hosts, zoneId, podId, clusterId, + cluster.hypervisor) + self.waitForHost(zoneId, clusterId) + self.createPrimaryStorages(cluster.primaryStorages, + zoneId, + podId, + clusterId) + except Exception as e: + print "Exception Occurred %s" % GetDetailExceptionInfo(e) + self.__tcRunLogger.exception("====Cluster %s Creation Failed" + "=====" % + str(cluster.clustername)) + self.__cleanAndExit() def waitForHost(self, zoneId, clusterId): """ Wait for the hosts in the zoneid, clusterid to be up - 2 retries with 30s delay """ - retry, timeout = 2, 30 - cmd = listHosts.listHostsCmd() - cmd.clusterid, cmd.zoneid = clusterId, zoneId - hosts = self.apiClient.listHosts(cmd) - while retry != 0: - for host in hosts: - if host.state != 'Up': - break - sleep(timeout) - retry = retry - 1 - - def createPrimaryStorages(self, primaryStorages, zoneId, podId, clusterId): - if primaryStorages is None: - return - for primary in primaryStorages: - primarycmd = createStoragePool.createStoragePoolCmd() - primarycmd.details = primary.details - primarycmd.name = primary.name - primarycmd.podid = podId - primarycmd.tags = primary.tags - primarycmd.url = primary.url - primarycmd.zoneid = zoneId - primarycmd.clusterid = clusterId - self.apiClient.createStoragePool(primarycmd) - - def createPods(self, pods, zoneId, networkId=None): - if pods is None: - return - for pod in pods: - createpod = createPod.createPodCmd() - createpod.name = pod.name - createpod.gateway = pod.gateway - createpod.netmask = pod.netmask - createpod.startip = pod.startip - createpod.endip = pod.endip - createpod.zoneid = zoneId - createpodResponse = self.apiClient.createPod(createpod) - podId = createpodResponse.id - - if pod.guestIpRanges is not None and networkId is not None: - self.createVlanIpRanges("Basic", pod.guestIpRanges, zoneId, - podId, networkId) - - self.createClusters(pod.clusters, zoneId, podId, - vmwareDc=pod.vmwaredc) + try: + retry, timeout = 2, 30 + cmd = listHosts.listHostsCmd() + cmd.clusterid, cmd.zoneid = clusterId, zoneId + hosts = self.__apiClient.listHosts(cmd) + while retry != 0: + for host in hosts: + if host.state != 'Up': + break + sleep(timeout) + retry = retry - 1 + except Exception as e: + print "\nException Occurred:%s" %\ + GetDetailExceptionInfo(e) + self.__tcRunLogger.exception("=== List Hosts Failed===") + self.__cleanAndExit() + + def createPrimaryStorages(self, + primaryStorages, + zoneId, + podId, + clusterId): + try: + if primaryStorages is None: + return + for primary in primaryStorages: + primarycmd = createStoragePool.createStoragePoolCmd() + primarycmd.details = primary.details + primarycmd.name = primary.name + primarycmd.podid = podId + primarycmd.tags = primary.tags + primarycmd.url = primary.url + primarycmd.zoneid = zoneId + primarycmd.clusterid = clusterId + ret = self.__apiClient.createStoragePool(primarycmd) + if ret.id: + self.__tcRunLogger.debug( + "=== Creating Storage Pool Successful===") + self.__addToCleanUp("StoragePool", ret.id) + except Exception as e: + print "Exception Occurred: %s" % GetDetailExceptionInfo(e) + self.__tcRunLogger.\ + exception("=== Create Storage Pool Failed===") + self.__cleanAndExit() + + def createPods(self, + pods, + zoneId, + networkId=None): + try: + if pods is None: + return + for pod in pods: + createpod = createPod.createPodCmd() + createpod.name = pod.name + createpod.gateway = pod.gateway + createpod.netmask = pod.netmask + createpod.startip = pod.startip + createpod.endip = pod.endip + createpod.zoneid = zoneId + createpodResponse = self.__apiClient.createPod(createpod) + if createpodResponse.id: + podId = createpodResponse.id + self.__tcRunLogger.debug("Pod Name : %s Id : %s " + "Created Successfully" % + (str(pod.name), str(podId))) + self.__addToCleanUp("Pod", podId) + if pod.guestIpRanges is not None and networkId is not None: + self.createVlanIpRanges("Basic", pod.guestIpRanges, zoneId, + podId, networkId) + self.createClusters(pod.clusters, zoneId, podId, + vmwareDc=pod.vmwaredc) + except Exception as e: + print "Exception Occurred: %s" % GetDetailExceptionInfo(e) + self.__tcRunLogger.\ + exception("====Pod: %s Creation " + "Failed=====" % str(pod.name)) + self.__cleanAndExit() def createVlanIpRanges(self, mode, ipranges, zoneId, podId=None, networkId=None, forvirtualnetwork=None): - if ipranges is None: - return - for iprange in ipranges: - vlanipcmd = createVlanIpRange.createVlanIpRangeCmd() - vlanipcmd.account = iprange.account - vlanipcmd.domainid = iprange.domainid - vlanipcmd.endip = iprange.endip - vlanipcmd.gateway = iprange.gateway - vlanipcmd.netmask = iprange.netmask - vlanipcmd.networkid = networkId - vlanipcmd.podid = podId - vlanipcmd.startip = iprange.startip - vlanipcmd.zoneid = zoneId - vlanipcmd.vlan = iprange.vlan - if mode == "Basic": - if forvirtualnetwork: - vlanipcmd.forvirtualnetwork = "true" + try: + if ipranges is None: + return + for iprange in ipranges: + vlanipcmd = createVlanIpRange.createVlanIpRangeCmd() + vlanipcmd.account = iprange.account + vlanipcmd.domainid = iprange.domainid + vlanipcmd.endip = iprange.endip + vlanipcmd.gateway = iprange.gateway + vlanipcmd.netmask = iprange.netmask + vlanipcmd.networkid = networkId + vlanipcmd.podid = podId + vlanipcmd.startip = iprange.startip + vlanipcmd.zoneid = zoneId + vlanipcmd.vlan = iprange.vlan + if mode == "Basic": + if forvirtualnetwork: + vlanipcmd.forvirtualnetwork = "true" + else: + vlanipcmd.forvirtualnetwork = "false" else: - vlanipcmd.forvirtualnetwork = "false" - else: - vlanipcmd.forvirtualnetwork = "true" - self.apiClient.createVlanIpRange(vlanipcmd) + vlanipcmd.forvirtualnetwork = "true" + ret = self.__apiClient.createVlanIpRange(vlanipcmd) + if ret.id: + self.__tcRunLogger.debug( + "=== Creating Vlan Ip Range Successful===") + self.__addToCleanUp("VlanIpRange", ret.id) + except Exception as e: + print "Exception Occurred: %s" % GetDetailExceptionInfo(e) + self.__tcRunLogger.\ + exception("=== Create Vlan Ip Range Failed===") + self.__cleanAndExit() def createSecondaryStorages(self, secondaryStorages, zoneId): - if secondaryStorages is None: - return - for secondary in secondaryStorages: - secondarycmd = addImageStore.addImageStoreCmd() - secondarycmd.url = secondary.url - secondarycmd.provider = secondary.provider - secondarycmd.details = [] - - if secondarycmd.provider == 'S3' \ - or secondarycmd.provider == "Swift": - for key, value in vars(secondary.details).iteritems(): - secondarycmd.details.append({ + try: + if secondaryStorages is None: + return + for secondary in secondaryStorages: + secondarycmd = addImageStore.addImageStoreCmd() + secondarycmd.url = secondary.url + secondarycmd.provider = secondary.provider + secondarycmd.details = [] + + if secondarycmd.provider == 'S3' \ + or secondarycmd.provider == "Swift": + for key, value in vars(secondary.details).iteritems(): + secondarycmd.details.append({ + 'key': key, + 'value': value + }) + if secondarycmd.provider == "NFS": + secondarycmd.zoneid = zoneId + ret = self.__apiClient.addImageStore(secondarycmd) + if ret.id: + self.__tcRunLogger.debug( + "===Add Image Store Successful===") + self.__addToCleanUp("ImageStore", ret.id) + except Exception as e: + print "Exception Occurred: %s" % GetDetailExceptionInfo(e) + self.__tcRunLogger.\ + exception("=== Add Image Store Failed===") + self.__cleanAndExit() + + def createCacheStorages(self, cacheStorages, zoneId): + try: + if cacheStorages is None: + return + for cache in cacheStorages: + cachecmd = createSecondaryStagingStore.\ + createSecondaryStagingStoreCmd() + cachecmd.url = cache.url + cachecmd.provider = cache.provider + cachecmd.zoneid = zoneId + cachecmd.details = [] + + if cache.details: + for key, value in vars(cache.details).iteritems(): + cachecmd.details.append({ 'key': key, 'value': value }) - if secondarycmd.provider == "NFS": - secondarycmd.zoneid = zoneId - self.apiClient.addImageStore(secondarycmd) - - def createCacheStorages(self, cacheStorages, zoneId): - if cacheStorages is None: - return - for cache in cacheStorages: - cachecmd = createSecondaryStagingStore.\ - createSecondaryStagingStoreCmd() - cachecmd.url = cache.url - cachecmd.provider = cache.provider - cachecmd.zoneid = zoneId - cachecmd.details = [] - - if cache.details: - for key, value in vars(cache.details).iteritems(): - cachecmd.details.append({ - 'key': key, - 'value': value - }) - self.apiClient.createSecondaryStagingStore(cachecmd) + ret = self.__apiClient.createSecondaryStagingStore(cachecmd) + if ret.id: + self.__tcRunLogger.debug( + "===Creating Secondary StagingStore Successful===") + self.__addToCleanUp("SecondaryStagingStore", ret.id) + except Exception as e: + print "Exception Occurred: %s" % GetDetailExceptionInfo(e) + self.__tcRunLogger.\ + exception("=== Creating " + "SecondaryStagingStorage Failed===") + self.__cleanAndExit() def createNetworks(self, networks, zoneId): - if networks is None: - return - for network in networks: - networkcmd = createNetwork.createNetworkCmd() - networkcmd.displaytext = network.displaytext - networkcmd.name = network.name - networkcmd.networkofferingid = network.networkofferingid - networkcmd.zoneid = zoneId - - ipranges = network.ipranges - if ipranges: - iprange = ipranges.pop() - networkcmd.startip = iprange.startip - networkcmd.endip = iprange.endip - networkcmd.gateway = iprange.gateway - networkcmd.netmask = iprange.netmask - - networkcmdresponse = self.apiClient.createNetwork(networkcmd) - networkId = networkcmdresponse.id - return networkId + try: + if networks is None: + return + for network in networks: + networkcmd = createNetwork.createNetworkCmd() + networkcmd.displaytext = network.displaytext + networkcmd.name = network.name + networkcmd.networkofferingid = network.networkofferingid + networkcmd.zoneid = zoneId + + ipranges = network.ipranges + if ipranges: + iprange = ipranges.pop() + networkcmd.startip = iprange.startip + networkcmd.endip = iprange.endip + networkcmd.gateway = iprange.gateway + networkcmd.netmask = iprange.netmask + networkcmdresponse = self.__apiClient.createNetwork(networkcmd) + if networkcmdresponse.id: + networkId = networkcmdresponse.id + self.__tcRunLogger.\ + debug("Creating Network Name : %s Id : %s Successful" + % (str(network.name), str(networkId))) + self.__addToCleanUp("Network", networkId) + return networkId + except Exception as e: + print "Exception Occurred %s" % GetDetailExceptionInfo(e) + self.__tcRunLogger.\ + exception("====Network : %s " + "Creation Failed=====" % str(network.name)) + self.__cleanAndExit() def createPhysicalNetwork(self, net, zoneid): - phynet = createPhysicalNetwork.createPhysicalNetworkCmd() - phynet.zoneid = zoneid - phynet.name = net.name - phynet.isolationmethods = net.isolationmethods - phynetwrk = self.apiClient.createPhysicalNetwork(phynet) - self.addTrafficTypes(phynetwrk.id, net.traffictypes) - return phynetwrk - - def updatePhysicalNetwork(self, networkid, state="Enabled", vlan=None): - upnet = updatePhysicalNetwork.updatePhysicalNetworkCmd() - upnet.id = networkid - upnet.state = state - if vlan: - upnet.vlan = vlan - return self.apiClient.updatePhysicalNetwork(upnet) + try: + phynet = createPhysicalNetwork.createPhysicalNetworkCmd() + phynet.zoneid = zoneid + phynet.name = net.name + phynet.isolationmethods = net.isolationmethods + phynetwrk = self.__apiClient.createPhysicalNetwork(phynet) + if phynetwrk.id: + self.__tcRunLogger.\ + debug("Creating Physical Network Name : " + "%s Id : %s Successful" % (str(phynet.name), + str(phynetwrk.id))) + self.__addToCleanUp("PhysicalNetwork", phynetwrk.id) + self.addTrafficTypes(phynetwrk.id, net.traffictypes) + return phynetwrk + except Exception as e: + print "Exception Occurred: %s" % GetDetailExceptionInfo(e) + self.__tcRunLogger.exception("====Physical Network " + "Creation Failed=====") + self.__cleanAndExit() + + def updatePhysicalNetwork(self, networkid, state="Enabled", + vlan=None): + try: + upnet = updatePhysicalNetwork.updatePhysicalNetworkCmd() + upnet.id = networkid + upnet.state = state + if vlan: + upnet.vlan = vlan + ret = self.__apiClient.updatePhysicalNetwork(upnet) + return ret + except Exception as e: + print "Exception Occurred: %s" % GetDetailExceptionInfo(e) + self.__tcRunLogger.\ + exception("====Update Physical Network Failed=====") + self.__cleanAndExit() def enableProvider(self, provider_id): - upnetprov =\ - updateNetworkServiceProvider.updateNetworkServiceProviderCmd() - upnetprov.id = provider_id - upnetprov.state = "Enabled" - self.apiClient.updateNetworkServiceProvider(upnetprov) + try: + upnetprov =\ + updateNetworkServiceProvider.updateNetworkServiceProviderCmd() + upnetprov.id = provider_id + upnetprov.state = "Enabled" + ret = self.__apiClient.updateNetworkServiceProvider(upnetprov) + if ret.id: + self.__tcRunLogger.debug( + "===Update Network Service Provider Successfull===") + except Exception as e: + print "Exception Occurred: %s" % GetDetailExceptionInfo(e) + self.__tcRunLogger.\ + exception( + "====Update Network Service Provider Failed=====") + self.__cleanAndExit() def configureProviders(self, phynetwrk, providers): """ We will enable the virtualrouter elements for all zones. Other providers like NetScalers, SRX, etc are explicitly added/configured """ - - for provider in providers: - pnetprov = listNetworkServiceProviders.\ - listNetworkServiceProvidersCmd() - pnetprov.physicalnetworkid = phynetwrk.id - pnetprov.state = "Disabled" - pnetprov.name = provider.name - pnetprovres = self.apiClient.listNetworkServiceProviders(pnetprov) - - if pnetprovres and len(pnetprovres) > 0: - if provider.name == 'VirtualRouter'\ - or provider.name == 'VpcVirtualRouter': - vrprov = listVirtualRouterElements.\ - listVirtualRouterElementsCmd() - vrprov.nspid = pnetprovres[0].id - vrprovresponse = self.apiClient.\ - listVirtualRouterElements(vrprov) - vrprovid = vrprovresponse[0].id - - vrconfig = \ - configureVirtualRouterElement.\ - configureVirtualRouterElementCmd() - vrconfig.enabled = "true" - vrconfig.id = vrprovid - self.apiClient.configureVirtualRouterElement(vrconfig) - self.enableProvider(pnetprovres[0].id) - elif provider.name == 'InternalLbVm': - internallbprov = listInternalLoadBalancerElements.\ - listInternalLoadBalancerElementsCmd() - internallbprov.nspid = pnetprovres[0].id - internallbresponse = self.apiClient.\ - listInternalLoadBalancerElements(internallbprov) - internallbid = internallbresponse[0].id - - internallbconfig = \ - configureInternalLoadBalancerElement.\ - configureInternalLoadBalancerElementCmd() - internallbconfig.enabled = "true" - internallbconfig.id = internallbid - self.apiClient.\ - configureInternalLoadBalancerElement(internallbconfig) - self.enableProvider(pnetprovres[0].id) - elif provider.name == 'SecurityGroupProvider': - self.enableProvider(pnetprovres[0].id) - elif provider.name in ['Netscaler', 'JuniperSRX', 'F5BigIp']: - netprov = addNetworkServiceProvider.\ - addNetworkServiceProviderCmd() - netprov.name = provider.name - netprov.physicalnetworkid = phynetwrk.id - result = self.apiClient.addNetworkServiceProvider(netprov) - for device in provider.devices: - if provider.name == 'Netscaler': - dev = addNetscalerLoadBalancer.\ - addNetscalerLoadBalancerCmd() - dev.username = device.username - dev.password = device.password - dev.networkdevicetype = device.networkdevicetype - dev.url = configGenerator.getDeviceUrl(device) - dev.physicalnetworkid = phynetwrk.id - self.apiClient.addNetscalerLoadBalancer(dev) - elif provider.name == 'JuniperSRX': - dev = addSrxFirewall.addSrxFirewallCmd() - dev.username = device.username - dev.password = device.password - dev.networkdevicetype = device.networkdevicetype - dev.url = configGenerator.getDeviceUrl(device) - dev.physicalnetworkid = phynetwrk.id - self.apiClient.addSrxFirewall(dev) - elif provider.name == 'F5BigIp': - dev = addF5LoadBalancer.addF5LoadBalancerCmd() - dev.username = device.username - dev.password = device.password - dev.networkdevicetype = device.networkdevicetype - dev.url = configGenerator.getDeviceUrl(device) - dev.physicalnetworkid = phynetwrk.id - self.apiClient.addF5LoadBalancer(dev) - else: - raise cloudstackException.\ - InvalidParameterException("Device %s doesn't match\ - any know provider type" % device) - self.enableProvider(result.id) + try: + for provider in providers: + pnetprov = listNetworkServiceProviders.\ + listNetworkServiceProvidersCmd() + pnetprov.physicalnetworkid = phynetwrk.id + pnetprov.state = "Disabled" + pnetprov.name = provider.name + pnetprovres = self.__apiClient.listNetworkServiceProviders( + pnetprov) + if pnetprovres and len(pnetprovres) > 0: + if provider.name == 'VirtualRouter'\ + or provider.name == 'VpcVirtualRouter': + vrprov = listVirtualRouterElements.\ + listVirtualRouterElementsCmd() + vrprov.nspid = pnetprovres[0].id + vrprovresponse = self.__apiClient.\ + listVirtualRouterElements(vrprov) + vrprovid = vrprovresponse[0].id + vrconfig = \ + configureVirtualRouterElement.\ + configureVirtualRouterElementCmd() + vrconfig.enabled = "true" + vrconfig.id = vrprovid + self.__apiClient.\ + configureVirtualRouterElement(vrconfig) + self.enableProvider(pnetprovres[0].id) + elif provider.name == 'InternalLbVm': + internallbprov = listInternalLoadBalancerElements.\ + listInternalLoadBalancerElementsCmd() + internallbprov.nspid = pnetprovres[0].id + internallbresponse = self.__apiClient.\ + listInternalLoadBalancerElements(internallbprov) + internallbid = internallbresponse[0].id + internallbconfig = \ + configureInternalLoadBalancerElement.\ + configureInternalLoadBalancerElementCmd() + internallbconfig.enabled = "true" + internallbconfig.id = internallbid + self.__apiClient.\ + configureInternalLoadBalancerElement( + internallbconfig) + self.enableProvider(pnetprovres[0].id) + elif provider.name == 'SecurityGroupProvider': + self.enableProvider(pnetprovres[0].id) + elif provider.name in ['JuniperContrailRouter', 'JuniperContrailVpcRouter']: + netprov = addNetworkServiceProvider.\ + addNetworkServiceProviderCmd() + netprov.name = provider.name + netprov.physicalnetworkid = phynetwrk.id + result = self.apiClient.addNetworkServiceProvider(netprov) + self.enableProvider(result.id) + elif provider.name in ['Netscaler', 'JuniperSRX', 'F5BigIp']: + netprov = addNetworkServiceProvider.\ + addNetworkServiceProviderCmd() + netprov.name = provider.name + netprov.physicalnetworkid = phynetwrk.id + result = self.__apiClient.addNetworkServiceProvider( + netprov) + if result.id: + self.__tcRunLogger.\ + debug("==== AddNetworkServiceProvider " + "Successful=====") + self.__addToCleanUp( + "NetworkServiceProvider", + result.id) + for device in provider.devices: + if provider.name == 'Netscaler': + dev = addNetscalerLoadBalancer.\ + addNetscalerLoadBalancerCmd() + dev.username = device.username + dev.password = device.password + dev.networkdevicetype = device.networkdevicetype + dev.url = configGenerator.getDeviceUrl(device) + dev.physicalnetworkid = phynetwrk.id + ret = self.__apiClient.addNetscalerLoadBalancer( + dev) + if ret.id: + self.__tcRunLogger.\ + debug("==== AddNetScalerLB " + "Successful=====") + self.__addToCleanUp( + "NetscalerLoadBalancer", + ret.id) + elif provider.name == 'JuniperSRX': + dev = addSrxFirewall.addSrxFirewallCmd() + dev.username = device.username + dev.password = device.password + dev.networkdevicetype = device.networkdevicetype + dev.url = configGenerator.getDeviceUrl(device) + dev.physicalnetworkid = phynetwrk.id + ret = self.__apiClient.addSrxFirewall(dev) + if ret.id: + self.__tcRunLogger.\ + debug("==== AddSrx " + "Successful=====") + self.__addToCleanUp("SrxFirewall", ret.id) + elif provider.name == 'F5BigIp': + dev = addF5LoadBalancer.addF5LoadBalancerCmd() + dev.username = device.username + dev.password = device.password + dev.networkdevicetype = device.networkdevicetype + dev.url = configGenerator.getDeviceUrl(device) + dev.physicalnetworkid = phynetwrk.id + ret = self.__apiClient.addF5LoadBalancer(dev) + if ret.id: + self.__tcRunLogger.\ + debug("==== AddF5 " + "Successful=====") + self.__addToCleanUp("F5LoadBalancer", ret.id) + else: + raise InvalidParameterException( + "Device %s doesn't match " + "any know provider " + "type" % device) + self.enableProvider(result.id) + except Exception as e: + print "Exception Occurred: %s" % GetDetailExceptionInfo(e) + self.__tcRunLogger.\ + exception("====List Network " + "Service Providers Failed=====") + self.__cleanAndExit() def addTrafficTypes(self, physical_network_id, traffictypes): [self.addTrafficType(physical_network_id, traffic_type) for traffic_type in traffictypes] def addTrafficType(self, physical_network_id, traffictype): - traffic_type = addTrafficType.addTrafficTypeCmd() - traffic_type.physicalnetworkid = physical_network_id - traffic_type.traffictype = traffictype.typ - traffic_type.kvmnetworklabel = traffictype.kvm\ - if traffictype.kvm is not None else None - traffic_type.xennetworklabel = traffictype.xen\ - if traffictype.xen is not None else None - traffic_type.vmwarenetworklabel = traffictype.vmware\ - if traffictype.vmware is not None else None - traffic_type.simulatorlabel = traffictype.simulator\ - if traffictype.simulator is not None else None - return self.apiClient.addTrafficType(traffic_type) + try: + traffic_type = addTrafficType.addTrafficTypeCmd() + traffic_type.physicalnetworkid = physical_network_id + traffic_type.traffictype = traffictype.typ + traffic_type.kvmnetworklabel = traffictype.kvm\ + if traffictype.kvm is not None else None + traffic_type.xennetworklabel = traffictype.xen\ + if traffictype.xen is not None else None + traffic_type.vmwarenetworklabel = traffictype.vmware\ + if traffictype.vmware is not None else None + traffic_type.simulatorlabel = traffictype.simulator\ + if traffictype.simulator is not None else None + ret = self.__apiClient.addTrafficType(traffic_type) + if ret.id: + self.__tcRunLogger.debug("===Add TrafficType Successful====") + self.__addToCleanUp("TrafficType", ret.id) + return ret + except Exception as e: + print "Exception Occurred: %s" % GetDetailExceptionInfo(e) + self.__tcRunLogger.\ + exception("==== Add TrafficType Failed=====") + self.__cleanAndExit() def enableZone(self, zoneid, allocation_state="Enabled"): - zoneCmd = updateZone.updateZoneCmd() - zoneCmd.id = zoneid - zoneCmd.allocationstate = allocation_state - return self.apiClient.updateZone(zoneCmd) + try: + zoneCmd = updateZone.updateZoneCmd() + zoneCmd.id = zoneid + zoneCmd.allocationstate = allocation_state + ret = self.__apiClient.updateZone(zoneCmd) + if ret.id: + self.__tcRunLogger.debug("==== Enable Zone SuccessFul=====") + return ret + except Exception as e: + print "Exception Occurred: %s" % GetDetailExceptionInfo(e) + self.__tcRunLogger.exception("==== Enable Zone Failed=====") + self.__cleanAndExit() def updateZoneDetails(self, zoneid, details): - zoneCmd = updateZone.updateZoneCmd() - zoneCmd.id = zoneid - zoneCmd.details = details - return self.apiClient.updateZone(zoneCmd) + try: + zoneCmd = updateZone.updateZoneCmd() + zoneCmd.id = zoneid + zoneCmd.details = details + ret = self.__apiClient.updateZone(zoneCmd) + if ret.id: + self.__tcRunLogger.debug("=== Update Zone SuccessFul===") + return ret + except Exception as e: + print "Exception Occurred: %s" % GetDetailExceptionInfo(e) + self.__tcRunLogger.exception("==== Update Zone Failed=====") + self.__cleanAndExit() + + def createZone(self, zone, rec=0): + try: + zoneresponse = self.__apiClient.createZone(zone) + if zoneresponse.id: + self.__addToCleanUp("Zone", zoneresponse.id) + self.__tcRunLogger.\ + debug("Zone Name : %s Id : %s Created Successfully" % + (str(zone.name), str(zoneresponse.id))) + return zoneresponse.id + else: + self.__tcRunLogger.\ + exception("====Zone : %s Creation Failed=====" % + str(zone.name)) + print "\n====Zone : %s Creation Failed=====" % str(zone.name) + if not rec: + zone.name = zone.name + "_" + random_gen() + self.__tcRunLogger.\ + debug("====Recreating Zone With New Name : " + "%s" % zone.name) + print "\n====Recreating Zone With New Name ====", \ + str(zone.name) + return self.createZone(zone, 1) + except Exception as e: + print "\nException Occurred under createZone : %s" % \ + GetDetailExceptionInfo(e) + self.__tcRunLogger.exception("====Create Zone Failed ===") + return FAILED def createZones(self, zones): - for zone in zones: - createzone = createZone.createZoneCmd() - createzone.dns1 = zone.dns1 - createzone.dns2 = zone.dns2 - createzone.internaldns1 = zone.internaldns1 - createzone.internaldns2 = zone.internaldns2 - createzone.name = zone.name - createzone.securitygroupenabled = zone.securitygroupenabled - createzone.localstorageenabled = zone.localstorageenabled - createzone.networktype = zone.networktype - if zone.securitygroupenabled != "true": - createzone.guestcidraddress = zone.guestcidraddress - - zoneresponse = self.apiClient.createZone(createzone) - zoneId = zoneresponse.id - - for pnet in zone.physical_networks: - phynetwrk = self.createPhysicalNetwork(pnet, zoneId) - self.configureProviders(phynetwrk, pnet.providers) - self.updatePhysicalNetwork(phynetwrk.id, "Enabled", - vlan=pnet.vlan) - - if zone.networktype == "Basic": - listnetworkoffering =\ - listNetworkOfferings.listNetworkOfferingsCmd() - listnetworkoffering.name =\ - "DefaultSharedNetscalerEIPandELBNetworkOffering" \ - if len(filter(lambda x: - x.typ == 'Public', - zone.physical_networks[0]. - traffictypes)) > 0 \ - else "DefaultSharedNetworkOfferingWithSGService" - if zone.networkofferingname is not None: - listnetworkoffering.name = zone.networkofferingname - - listnetworkofferingresponse = \ - self.apiClient.listNetworkOfferings(listnetworkoffering) - - guestntwrk = configGenerator.network() - guestntwrk.displaytext = "guestNetworkForBasicZone" - guestntwrk.name = "guestNetworkForBasicZone" - guestntwrk.zoneid = zoneId - guestntwrk.networkofferingid = \ - listnetworkofferingresponse[0].id - - networkid = self.createNetworks([guestntwrk], zoneId) - self.createPods(zone.pods, zoneId, networkid) - if self.isEipElbZone(zone): + try: + for zone in zones: + zonecmd = createZone.createZoneCmd() + zonecmd.dns1 = zone.dns1 + zonecmd.dns2 = zone.dns2 + zonecmd.internaldns1 = zone.internaldns1 + zonecmd.internaldns2 = zone.internaldns2 + zonecmd.name = zone.name + zonecmd.securitygroupenabled = zone.securitygroupenabled + zonecmd.localstorageenabled = zone.localstorageenabled + zonecmd.networktype = zone.networktype + if zone.securitygroupenabled != "true": + zonecmd.guestcidraddress = zone.guestcidraddress + zoneId = self.createZone(zonecmd) + if zoneId == FAILED: + self.__tcRunLogger.\ + exception( + "====Zone: %s Creation Failed. So Exiting=====" % + str(zone.name)) + self.__cleanAndExit() + for pnet in zone.physical_networks: + phynetwrk = self.createPhysicalNetwork(pnet, zoneId) + self.configureProviders(phynetwrk, pnet.providers) + self.updatePhysicalNetwork(phynetwrk.id, "Enabled", + vlan=pnet.vlan) + if zone.networktype == "Basic": + listnetworkoffering =\ + listNetworkOfferings.listNetworkOfferingsCmd() + listnetworkoffering.name =\ + "DefaultSharedNetscalerEIPandELBNetworkOffering" \ + if len(filter(lambda x: + x.typ == 'Public', + zone.physical_networks[0]. + traffictypes)) > 0 \ + else "DefaultSharedNetworkOfferingWithSGService" + if zone.networkofferingname is not None: + listnetworkoffering.name = zone.networkofferingname + listnetworkofferingresponse = \ + self.__apiClient.listNetworkOfferings( + listnetworkoffering) + guestntwrk = configGenerator.network() + guestntwrk.displaytext = "guestNetworkForBasicZone" + guestntwrk.name = "guestNetworkForBasicZone" + guestntwrk.zoneid = zoneId + guestntwrk.networkofferingid = \ + listnetworkofferingresponse[0].id + networkid = self.createNetworks([guestntwrk], zoneId) + self.createPods(zone.pods, zoneId, networkid) + if self.isEipElbZone(zone): + self.createVlanIpRanges( + zone.networktype, zone.ipranges, + zoneId, forvirtualnetwork=True) + isPureAdvancedZone = (zone.networktype == "Advanced" + and zone.securitygroupenabled != "true") + if isPureAdvancedZone: + self.createPods(zone.pods, zoneId) self.createVlanIpRanges(zone.networktype, zone.ipranges, - zoneId, forvirtualnetwork=True) - - isPureAdvancedZone = (zone.networktype == "Advanced" - and zone.securitygroupenabled != "true") - if isPureAdvancedZone: - self.createPods(zone.pods, zoneId) - self.createVlanIpRanges(zone.networktype, zone.ipranges, - zoneId) - elif (zone.networktype == "Advanced" - and zone.securitygroupenabled == "true"): - listnetworkoffering =\ - listNetworkOfferings.listNetworkOfferingsCmd() - listnetworkoffering.name =\ - "DefaultSharedNetworkOfferingWithSGService" - if zone.networkofferingname is not None: - listnetworkoffering.name = zone.networkofferingname - - listnetworkofferingresponse = \ - self.apiClient.listNetworkOfferings(listnetworkoffering) - - networkcmd = createNetwork.createNetworkCmd() - networkcmd.displaytext = "Shared SG enabled network" - networkcmd.name = "Shared SG enabled network" - networkcmd.networkofferingid =\ - listnetworkofferingresponse[0].id - networkcmd.zoneid = zoneId - - ipranges = zone.ipranges - if ipranges: - iprange = ipranges.pop() - networkcmd.startip = iprange.startip - networkcmd.endip = iprange.endip - networkcmd.gateway = iprange.gateway - networkcmd.netmask = iprange.netmask - networkcmd.vlan = iprange.vlan - - networkcmdresponse = self.apiClient.createNetwork(networkcmd) - networkId = networkcmdresponse.id - self.createPods(zone.pods, zoneId, networkId) - - '''Note: Swift needs cache storage first''' - self.createCacheStorages(zone.cacheStorages, zoneId) - self.createSecondaryStorages(zone.secondaryStorages, zoneId) - - enabled = getattr(zone, 'enabled', 'True') - if enabled == 'True' or enabled is None: - self.enableZone(zoneId, "Enabled") - details = getattr(zone, 'details') - if details is not None: - det = [d.__dict__ for d in details] - self.updateZoneDetails(zoneId, det) - - return + zoneId) + elif (zone.networktype == "Advanced" + and zone.securitygroupenabled == "true"): + listnetworkoffering =\ + listNetworkOfferings.listNetworkOfferingsCmd() + listnetworkoffering.name =\ + "DefaultSharedNetworkOfferingWithSGService" + if zone.networkofferingname is not None: + listnetworkoffering.name = zone.networkofferingname + listnetworkofferingresponse = \ + self.__apiClient.listNetworkOfferings( + listnetworkoffering) + networkcmd = createNetwork.createNetworkCmd() + networkcmd.displaytext = "Shared SG enabled network" + networkcmd.name = "Shared SG enabled network" + networkcmd.networkofferingid =\ + listnetworkofferingresponse[0].id + networkcmd.zoneid = zoneId + ipranges = zone.ipranges + if ipranges: + iprange = ipranges.pop() + networkcmd.startip = iprange.startip + networkcmd.endip = iprange.endip + networkcmd.gateway = iprange.gateway + networkcmd.netmask = iprange.netmask + networkcmd.vlan = iprange.vlan + networkcmdresponse = self.__apiClient.createNetwork( + networkcmd) + if networkcmdresponse.id: + self.__addToCleanUp("Network", networkcmdresponse.id) + self.__tcRunLogger.\ + debug("create Network Successful. NetworkId : %s " + % str(networkcmdresponse.id)) + self.createPods(zone.pods, zoneId, networkcmdresponse.id) + '''Note: Swift needs cache storage first''' + self.createCacheStorages(zone.cacheStorages, zoneId) + self.createSecondaryStorages(zone.secondaryStorages, zoneId) + enabled = getattr(zone, 'enabled', 'True') + if enabled == 'True' or enabled is None: + self.enableZone(zoneId, "Enabled") + details = getattr(zone, 'details') + if details is not None: + det = [d.__dict__ for d in details] + self.updateZoneDetails(zoneId, det) + return + except Exception as e: + print "\nException Occurred %s" % GetDetailExceptionInfo(e) + self.__tcRunLogger.exception("==== Create Zones Failed ===") def isEipElbZone(self, zone): if (zone.networktype == "Basic" @@ -479,64 +792,30 @@ def isEipElbZone(self, zone): return True return False - def registerApiKey(self): - listuser = listUsers.listUsersCmd() - listuser.account = "admin" - listuserRes = self.testClient.getApiClient().listUsers(listuser) - userId = listuserRes[0].id - apiKey = listuserRes[0].apikey - securityKey = listuserRes[0].secretkey - if apiKey is None: - registerUser = registerUserKeys.registerUserKeysCmd() - registerUser.id = userId - registerUserRes = \ - self.testClient.getApiClient().registerUserKeys(registerUser) - - apiKey = registerUserRes.apikey - securityKey = registerUserRes.secretkey - - self.config.mgtSvr[0].port = 8080 - self.config.mgtSvr[0].apiKey = apiKey - self.config.mgtSvr[0].securityKey = securityKey - return apiKey, securityKey - - def loadCfg(self): - ''' Retrieving Management Server Connection Details ''' - mgtDetails = self.config.mgtSvr[0] - ''' Retrieving Database Connection Details''' - dbSvrDetails = self.config.dbSvr - - self.testClient = \ - cloudstackTestClient.\ - cloudstackTestClient(mgtDetails, - dbSvrDetails, - logger=self.tcRunLogger) - - if mgtDetails.apiKey is None: - mgtDetails.apiKey, mgtDetails.securityKey = self.registerApiKey() - mgtDetails.port = 8080 - self.testClient = \ - cloudstackTestClient.cloudstackTestClient( - mgtDetails, - dbSvrDetails, - logger=self.tcRunLogger) - - self.apiClient = self.testClient.getApiClient() - """set hypervisor""" - if mgtDetails.hypervisor: - self.apiClient.hypervisor = mgtDetails.hypervisor - else: - self.apiClient.hypervisor = "XenServer" # Defaults to Xenserver + def setClient(self): + ''' + @Name : setClient + @Desc : Sets the API Client retrieved from test client + ''' + self.__apiClient = self.__testClient.getApiClient() def updateConfiguration(self, globalCfg): - if globalCfg is None: - return None - - for config in globalCfg: - updateCfg = updateConfiguration.updateConfigurationCmd() - updateCfg.name = config.name - updateCfg.value = config.value - self.apiClient.updateConfiguration(updateCfg) + try: + if globalCfg is None or self.__apiClient is None: + return None + for config in globalCfg: + updateCfg = updateConfiguration.updateConfigurationCmd() + updateCfg.name = config.name + updateCfg.value = config.value + ret = self.__apiClient.updateConfiguration(updateCfg) + if ret.id: + self.__tcRunLogger.debug( + "==UpdateConfiguration Successfull===") + except Exception as e: + print "Exception Occurred %s" % GetDetailExceptionInfo(e) + self.__tcRunLogger.\ + exception("===UpdateConfiguration Failed===") + self.__cleanAndExit() def copyAttributesToCommand(self, source, command): map(lambda attr: setattr(command, attr, getattr(source, attr, None)), @@ -544,42 +823,307 @@ def copyAttributesToCommand(self, source, command): ["required", "isAsync"], dir(command))) def configureS3(self, s3): - if s3 is None: - return - command = addS3.addS3Cmd() - self.copyAttributesToCommand(s3, command) - self.apiClient.addS3(command) + try: + if s3 is None: + return + command = addS3.addS3Cmd() + self.copyAttributesToCommand(s3, command) + ret = self.__apiClient.addS3(command) + if ret.id: + self.__tcRunLogger.debug("===AddS3 Successfull===") + self.__addToCleanUp("s3", ret.id) + except Exception as e: + self.__tcRunLogger.exception("====AddS3 Failed===") + self.__cleanAndExit() def deploy(self): - self.loadCfg() - self.updateConfiguration(self.config.globalConfig) - self.createZones(self.config.zones) - self.configureS3(self.config.s3) + try: + print "\n==== Deploy DC Started ====" + self.__tcRunLogger.debug("\n==== Deploy DC Started ====") + ''' + Step1 : Set the Client + ''' + self.setClient() + ''' + Step2: Update the Configuration + ''' + self.updateConfiguration(self.__config.globalConfig) + ''' + Step3 :Deploy the Zone + ''' + self.createZones(self.__config.zones) + self.configureS3(self.__config.s3) + ''' + Persist the Configuration to an external file post DC creation + ''' + self.__persistDcConfig() + print "\n====Deploy DC Successful=====" + self.__tcRunLogger.debug("\n====Deploy DC Successful====") + return SUCCESS + except Exception as e: + print "\nException Occurred Under deploy :%s" % \ + GetDetailExceptionInfo(e) + self.__tcRunLogger.debug("\n====Deploy DC Failed====") + print "\n====Deploy DC Failed====" + self.__cleanAndExit() + return FAILED + + +class DeleteDataCenters: + + ''' + @Desc : Deletes the Data Center using the settings provided. + tc_client :Client for deleting the DC. + dc_cfg_file : obj file exported by DeployDataCenter + when successfully created DC. + This file is serialized one containing + entries with successful DC. + dc_cfg: If dc_cfg_file, is not available, we can use + the dictionary of elements to delete. + tc_run_logger: Logger to dump log messages. + ''' + + def __init__(self, + tc_client, + dc_cfg_file=None, + dc_cfg=None, + tc_run_logger=None + ): + self.__dcCfgFile = dc_cfg_file + self.__dcCfg = dc_cfg + self.__tcRunLogger = tc_run_logger + self.__apiClient = None + self.__testClient = tc_client + + def __deleteCmds(self, cmd_name, cmd_obj): + ''' + @Name : __deleteCmds + @Desc : Deletes the entities provided by cmd + ''' + if cmd_name.lower() == "deletehostcmd": + cmd_obj.forcedestroylocalstorage = "true" + cmd_obj.force = "true" + ''' + Step1 : Prepare Host For Maintenance + ''' + host_maint_cmd = prepareHostForMaintenance.\ + prepareHostForMaintenanceCmd() + host_maint_cmd.id = cmd_obj.id + host_maint_resp = self.__apiClient.prepareHostForMaintenance( + host_maint_cmd) + if host_maint_resp: + ''' + Step2 : List Hosts for Resource State + ''' + list_host_cmd = listHosts.listHostsCmd() + list_host_cmd.id = cmd_obj.id + retries = 3 + for i in xrange(retries): + list_host_resp = self.__apiClient.\ + listHosts(list_host_cmd) + if (list_host_resp) and\ + (list_host_resp[0].resourcestate == 'Maintenance'): + break + sleep(30) + if cmd_name.lower() == "deletestoragepoolcmd": + cmd_obj.forced = "true" + store_maint_cmd = enableStorageMaintenance.\ + enableStorageMaintenanceCmd() + store_maint_cmd.id = cmd_obj.id + store_maint_resp = self.__apiClient.\ + enableStorageMaintenance(store_maint_cmd) + if store_maint_resp: + list_store_cmd = listStoragePools.listStoragePoolsCmd() + list_store_cmd.id = cmd_obj.id + retries = 3 + for i in xrange(retries): + store_maint_resp = self.__apiClient.\ + listStoragePools(list_store_cmd) + if (store_maint_resp) and \ + (store_maint_resp[0].state == 'Maintenance'): + break + sleep(30) + return cmd_obj + + def __setClient(self): + ''' + @Name : setClient + @Desc : Sets the API Client retrieved from test client + ''' + self.__apiClient = self.__testClient.getApiClient() + + def __cleanEntries(self): + ''' + @Name : __cleanAndEntries + @Description: Cleans up the created DC in order of creation + ''' + try: + ret = FAILED + if "order" in self.__dcCfg.keys() and len(self.__dcCfg["order"]): + self.__dcCfg["order"].reverse() + print "\n====Clean Up Entries===", self.__dcCfg + for type in self.__dcCfg["order"]: + self.__tcRunLogger.debug( + "====CleanUp Started For Type: %s====" % + type) + if type: + temp_ids = self.__dcCfg[type] + ids = [items for items in temp_ids if items] + for id in ids: + del_mod = "delete" + type + del_cmd = getattr( + globals()[del_mod], + del_mod + "Cmd") + del_cmd_obj = del_cmd() + del_cmd_resp = getattr( + globals()[del_mod], + del_mod + "Response") + del_cmd_obj.id = id + del_cmd_obj = self.__deleteCmds( + del_mod + + "Cmd", + del_cmd_obj) + del_func = getattr(self.__apiClient, del_mod) + del_cmd_resp = del_func(del_cmd_obj) + if del_cmd_resp: + self.__tcRunLogger.debug( + "====%s CleanUp Failed. ID: %s ===" % + (type, id)) + else: + self.__tcRunLogger.debug( + "====%s CleanUp Successful. ID : %s===" % + (type, id)) + ret = SUCCESS + except Exception as e: + print "\n==== Exception Under __cleanEntries: %s ==== % " \ + % GetDetailExceptionInfo(e) + self.__tcRunLogger.exception( + "\n==== Exception Under __cleanEntries: %s ==== % " % + GetDetailExceptionInfo(e)) + finally: + return ret + + def removeDataCenter(self): + ''' + @Name : removeDataCenter + @Desc : Removes the Data Center provided by Configuration + If Input dc file configuration is None, uses the cfg provided + else uses the dc file to get the configuration + ''' + try: + self.__setClient() + self.__tcRunLogger.debug("====DeployDC: CleanUp Started====") + print "\n====DeployDC: CleanUp Started====" + ret = FAILED + if self.__dcCfgFile: + file_to_read = open(self.__dcCfgFile, 'r') + if file_to_read: + self.__dcCfg = pickle.load(file_to_read) + if self.__dcCfg: + ret = self.__cleanEntries() + except Exception as e: + print "\n==== Exception Under removeDataCenter: %s ====" % \ + GetDetailExceptionInfo(e) + self.__tcRunLogger.exception( + "===DeployDC CleanUp FAILED: %s ====" % + GetDetailExceptionInfo(e)) + finally: + return ret + if __name__ == "__main__": + ''' + @Desc : This module facilitates the following: + 1. Deploying DataCenter by using the input provided + configuration. + EX: python deployDataCenter.py -i + 2. Removes a created DataCenter by providing + the input configuration file and data center settings file + EX: python deployDataCenter.py -i + -r + ''' parser = OptionParser() parser.add_option("-i", "--input", action="store", - default="./datacenterCfg", dest="input", help="the path \ - where the json config file generated, by default is \ - ./datacenterCfg") - + default=None, dest="input", + help="the path \ + where the json config file generated") + + parser.add_option("-r", "--remove", action="store", + default=None, dest="remove", + help="path to file\ + where the created dc entries are kept") (options, args) = parser.parse_args() + + ''' + Verify the input validity + ''' + if options.input is None and options.remove is None: + print "\n==== For DeployDataCenter: Please Specify a " \ + "Valid Input Configuration File====" + print "\n==== For DeleteDataCenters: Please Specify a " \ + "Valid Input Configuration File and DC Settings====" + exit(1) + + ''' + Imports the Modules Required + ''' from marvin.marvinLog import MarvinLog - cfg = configGenerator.getSetupConfig(options.input) + from marvin.cloudstackTestClient import CSTestClient + + ''' + Step1: Create the Logger + ''' log_obj = MarvinLog("CSLog") - tcRunLogger = log_obj.setLogHandler("/tmp/debug.log") - deploy = deployDataCenters(cfg, tcRunLogger) - deploy.deploy() - - """ - create = createStoragePool.createStoragePoolCmd() - create.clusterid = 1 - create.podid = 2 - create.name = "fdffdf" - create.url = "nfs://jfkdjf/fdkjfkd" - create.zoneid = 2 - - deploy = deployDataCenters("./datacenterCfg") - deploy.loadCfg() - deploy.apiClient.createStoragePool(create) - """ + cfg = configGenerator.getSetupConfig(options.input) + log = cfg.logger + + ret = log_obj.createLogs("DeployDataCenter", + log) + if ret != FAILED: + log_folder_path = log_obj.getLogFolderPath() + tc_run_logger = log_obj.getLogger() + else: + print "\n===Log Creation Failed. Please Check===" + exit(1) + + ''' + Step2 : Create Test Client + ''' + obj_tc_client = CSTestClient(cfg.mgtSvr[0], cfg.dbSvr, + logger=tc_run_logger) + if obj_tc_client and obj_tc_client.createTestClient() == FAILED: + print "\n=== TestClient Creation Failed===" + exit(1) + + ''' + Step3: Verify and continue whether to deploy a DC or remove a DC + ''' + + if (options.input) and (os.path.isfile(options.input)) and \ + (options.remove is None): + ''' + @Desc : Deploys a Data Center with provided Config + ''' + deploy = DeployDataCenters(obj_tc_client, + cfg, + tc_run_logger, + log_folder_path=log_folder_path) + deploy.deploy() + exit(1) + + if options.remove and os.path.isfile(options.remove) and options.input: + ''' + @Desc : Removes a Data Center with provided Config + ''' + remove_dc_obj = DeleteDataCenters(obj_tc_client, + dc_cfg_file=options.remove, + tc_run_logger=tc_run_logger + ) + if remove_dc_obj: + if remove_dc_obj.removeDataCenter() == FAILED: + print "\n===Removing DataCenter Failed===" + tc_run_logger.debug("\n===Removing DataCenter Failed===") + else: + print "\n===Removing DataCenter Successful===" + tc_run_logger.debug("\n===Removing DataCenter Successful===") + exit(1) diff --git a/tools/marvin/marvin/jsonHelper.py b/tools/marvin/marvin/jsonHelper.py index ae40b8dabf..3f48a00ba6 100644 --- a/tools/marvin/marvin/jsonHelper.py +++ b/tools/marvin/marvin/jsonHelper.py @@ -18,11 +18,13 @@ import cloudstackException import json import inspect -from cloudstackAPI import * +from marvin.cloudstackAPI import * class jsonLoader(object): + '''The recursive class for building and representing objects with.''' + def __init__(self, obj): for k in obj: v = obj[k] @@ -52,6 +54,7 @@ def __str__(self): class jsonDump(object): + @staticmethod def __serialize(obj): """Recursively walk object's hierarchy.""" @@ -145,7 +148,7 @@ def getResultObj(returnObj, responsecls=None): errMsg = "errorCode: %s, errorText:%s" % (result.errorcode, result.errortext) respname = responseName.replace("response", "") - raise cloudstackException.cloudstackAPIException(respname, errMsg) + raise cloudstackException.CloudstackAPIException(respname, errMsg) if result.count is not None: for key in result.__dict__.iterkeys(): @@ -247,7 +250,7 @@ def getResultObj(returnObj, responsecls=None): }''' try: asynJob = getResultObj(result) - except cloudstackException.cloudstackAPIException, e: + except cloudstackException.CloudstackAPIException as e: print e result = '{ "queryasyncjobresultresponse" : {} }' diff --git a/tools/marvin/marvin/integration/__init__.py b/tools/marvin/marvin/lib/__init__.py similarity index 98% rename from tools/marvin/marvin/integration/__init__.py rename to tools/marvin/marvin/lib/__init__.py index 57823fcc16..13a83393a9 100644 --- a/tools/marvin/marvin/integration/__init__.py +++ b/tools/marvin/marvin/lib/__init__.py @@ -5,14 +5,12 @@ # 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. - - diff --git a/tools/marvin/marvin/integration/lib/base.py b/tools/marvin/marvin/lib/base.py old mode 100755 new mode 100644 similarity index 80% rename from tools/marvin/marvin/integration/lib/base.py rename to tools/marvin/marvin/lib/base.py index b7e2be4755..03b03b61e3 --- a/tools/marvin/marvin/integration/lib/base.py +++ b/tools/marvin/marvin/lib/base.py @@ -20,8 +20,12 @@ """ import marvin -from utils import is_server_ssh_ready, random_gen from marvin.cloudstackAPI import * +from marvin.codes import (FAILED, FAIL, PASS, RUNNING, STOPPED, + STARTING, DESTROYED, EXPUNGING, + STOPPING) +from marvin.cloudstackException import GetDetailExceptionInfo +from marvin.lib.utils import validateList, is_server_ssh_ready, random_gen # Import System modules import time import hashlib @@ -29,7 +33,9 @@ class Domain: + """ Domain Life Cycle """ + def __init__(self, items): self.__dict__.update(items) @@ -77,11 +83,15 @@ def list(cls, apiclient, **kwargs): """Lists domains""" cmd = listDomains.listDomainsCmd() [setattr(cmd, k, v) for k, v in kwargs.items()] + if 'account' in kwargs.keys() and 'domainid' in kwargs.keys(): + cmd.listall=True return(apiclient.listDomains(cmd)) class Account: + """ Account Life Cycle """ + def __init__(self, items): self.__dict__.update(items) @@ -99,16 +109,16 @@ def create(cls, apiclient, services, admin=False, domainid=None): cmd.password = services["password"] - username = "-".join([services["username"], random_gen(id=apiclient.id)]) + username = "-".join([services["username"], + random_gen(id=apiclient.id)]) # Trim username to 99 characters to prevent failure cmd.username = username[:99] if len(username) > 99 else username if "accountUUID" in services: - cmd.accountid = "-".join([services["accountUUID"],random_gen()]) + cmd.accountid = "-".join([services["accountUUID"], random_gen()]) if "userUUID" in services: - cmd.userid = "-".join([services["userUUID"],random_gen()]) - + cmd.userid = "-".join([services["userUUID"], random_gen()]) if domainid: cmd.domainid = domainid @@ -129,6 +139,8 @@ def list(cls, apiclient, **kwargs): cmd = listAccounts.listAccountsCmd() [setattr(cmd, k, v) for k, v in kwargs.items()] + if 'account' in kwargs.keys() and 'domainid' in kwargs.keys(): + cmd.listall=True return(apiclient.listAccounts(cmd)) def disable(self, apiclient, lock=False): @@ -140,7 +152,9 @@ def disable(self, apiclient, lock=False): class User: + """ User Life Cycle """ + def __init__(self, items): self.__dict__.update(items) @@ -156,7 +170,7 @@ def create(cls, apiclient, services, account, domainid): cmd.lastname = services["lastname"] if "userUUID" in services: - cmd.userid = "-".join([services["userUUID"],random_gen()]) + cmd.userid = "-".join([services["userUUID"], random_gen()]) cmd.password = services["password"] cmd.username = "-".join([services["username"], random_gen()]) @@ -177,6 +191,8 @@ def list(cls, apiclient, **kwargs): cmd = listUsers.listUsersCmd() [setattr(cmd, k, v) for k, v in kwargs.items()] + if 'account' in kwargs.keys() and 'domainid' in kwargs.keys(): + cmd.listall=True return(apiclient.listUsers(cmd)) @classmethod @@ -217,8 +233,19 @@ def login(cls, apiclient, username, password, domain=None, domainid=None): class VirtualMachine: + """Manage virtual machine lifecycle""" + '''Class level variables''' + # Variables denoting VM state - start + STOPPED = STOPPED + RUNNING = RUNNING + DESTROYED = DESTROYED + EXPUNGING = EXPUNGING + STOPPING = STOPPING + STARTING = STARTING + # Varibles denoting VM state - end + def __init__(self, items, services): self.__dict__.update(items) if "username" in services: @@ -240,7 +267,8 @@ def __init__(self, items, services): @classmethod def ssh_access_group(cls, apiclient, cmd): """ - Programs the security group with SSH access before deploying virtualmachine + Programs the security group with SSH + access before deploying virtualmachine @return: """ zone_list = Zone.list( @@ -249,12 +277,13 @@ def ssh_access_group(cls, apiclient, cmd): domainid=cmd.domainid if cmd.domainid else None ) zone = zone_list[0] - #check if security groups settings is enabled for the zone + # check if security groups settings is enabled for the zone if zone.securitygroupsenabled: list_security_groups = SecurityGroup.list( apiclient, account=cmd.account, domainid=cmd.domainid, + listall=True, securitygroupname="basic_sec_grp" ) @@ -271,9 +300,11 @@ def ssh_access_group(cls, apiclient, cmd): "endport": 22, "cidrlist": "0.0.0.0/0" } - #Authorize security group for above ingress rule - basic_mode_security_group.authorize(apiclient, sec_grp_services, account=cmd.account, - domainid=cmd.domainid) + # Authorize security group for above ingress rule + basic_mode_security_group.authorize(apiclient, + sec_grp_services, + account=cmd.account, + domainid=cmd.domainid) else: basic_mode_security_group = list_security_groups[0] @@ -283,7 +314,8 @@ def ssh_access_group(cls, apiclient, cmd): cmd.securitygroupids = [basic_mode_security_group.id] @classmethod - def access_ssh_over_nat(cls, apiclient, services, virtual_machine, allow_egress=False): + def access_ssh_over_nat( + cls, apiclient, services, virtual_machine, allow_egress=False): """ Program NAT and PF rules to open up ssh access to deployed guest @return: @@ -321,11 +353,13 @@ def access_ssh_over_nat(cls, apiclient, services, virtual_machine, allow_egress= @classmethod def create(cls, apiclient, services, templateid=None, accountid=None, - domainid=None, zoneid=None, networkids=None, serviceofferingid=None, - securitygroupids=None, projectid=None, startvm=None, - diskofferingid=None, affinitygroupnames=None, affinitygroupids=None, group=None, - hostid=None, keypair=None, ipaddress=None, mode='default', method='GET', - customcpunumber=None, customcpuspeed=None, custommemory=None): + domainid=None, zoneid=None, networkids=None, + serviceofferingid=None, securitygroupids=None, + projectid=None, startvm=None, diskofferingid=None, + affinitygroupnames=None, affinitygroupids=None, group=None, + hostid=None, keypair=None, ipaddress=None, mode='default', + method='GET', hypervisor="XenServer", customcpunumber=None, + customcpuspeed=None, custommemory=None, rootdisksize=None): """Create the instance""" cmd = deployVirtualMachine.deployVirtualMachineCmd() @@ -339,7 +373,7 @@ def create(cls, apiclient, services, templateid=None, accountid=None, cmd.zoneid = zoneid elif "zoneid" in services: cmd.zoneid = services["zoneid"] - cmd.hypervisor = apiclient.hypervisor + cmd.hypervisor = hypervisor if "displayname" in services: cmd.displayname = services["displayname"] @@ -394,12 +428,12 @@ def create(cls, apiclient, services, templateid=None, accountid=None, cmd.securitygroupids = [str(sg_id) for sg_id in securitygroupids] if "affinitygroupnames" in services: - cmd.affinitygroupnames = services["affinitygroupnames"] + cmd.affinitygroupnames = services["affinitygroupnames"] elif affinitygroupnames: - cmd.affinitygroupnames = affinitygroupnames + cmd.affinitygroupnames = affinitygroupnames if affinitygroupids: - cmd.affinitygroupids = affinitygroupids + cmd.affinitygroupids = affinitygroupids if projectid: cmd.projectid = projectid @@ -413,7 +447,7 @@ def create(cls, apiclient, services, templateid=None, accountid=None, if "userdata" in services: cmd.userdata = base64.urlsafe_b64encode(services["userdata"]) - cmd.details = [{"cpuNumber": "","cpuSpeed":"","memory":""}] + cmd.details = [{}] if customcpunumber: cmd.details[0]["cpuNumber"] = customcpunumber @@ -424,28 +458,37 @@ def create(cls, apiclient, services, templateid=None, accountid=None, if custommemory: cmd.details[0]["memory"] = custommemory + if rootdisksize >= 0: + cmd.details[0]["rootdisksize"] = rootdisksize + if group: cmd.group = group - #program default access to ssh + # program default access to ssh if mode.lower() == 'basic': cls.ssh_access_group(apiclient, cmd) virtual_machine = apiclient.deployVirtualMachine(cmd, method=method) virtual_machine.ssh_ip = virtual_machine.nic[0].ipaddress - if startvm == False: + if startvm is False: virtual_machine.public_ip = virtual_machine.nic[0].ipaddress return VirtualMachine(virtual_machine.__dict__, services) - #program ssh access over NAT via PF + # program ssh access over NAT via PF if mode.lower() == 'advanced': - cls.access_ssh_over_nat(apiclient, services, virtual_machine, allow_egress=allow_egress) + cls.access_ssh_over_nat( + apiclient, + services, + virtual_machine, + allow_egress=allow_egress) elif mode.lower() == 'basic': if virtual_machine.publicip is not None: - vm_ssh_ip = virtual_machine.publicip #EIP/ELB (netscaler) enabled zone + # EIP/ELB (netscaler) enabled zone + vm_ssh_ip = virtual_machine.publicip else: - vm_ssh_ip = virtual_machine.nic[0].ipaddress #regular basic zone with security group + # regular basic zone with security group + vm_ssh_ip = virtual_machine.nic[0].ipaddress virtual_machine.ssh_ip = vm_ssh_ip virtual_machine.public_ip = vm_ssh_ip @@ -457,11 +500,17 @@ def start(self, apiclient): cmd.id = self.id apiclient.startVirtualMachine(cmd) - def stop(self, apiclient): + def stop(self, apiclient, forced=None): """Stop the instance""" cmd = stopVirtualMachine.stopVirtualMachineCmd() cmd.id = self.id + if forced: + cmd.forced = forced apiclient.stopVirtualMachine(cmd) + response = self.getState(apiclient, VirtualMachine.STOPPED) + if response[0] == FAIL: + raise Exception(response[1]) + return def reboot(self, apiclient): """Reboot the instance""" @@ -483,12 +532,14 @@ def restore(self, apiclient, templateid=None): cmd.templateid = templateid return apiclient.restoreVirtualMachine(cmd) - def get_ssh_client(self, ipaddress=None, reconnect=False, port=None, keyPairFileLocation=None): + def get_ssh_client( + self, ipaddress=None, reconnect=False, port=None, + keyPairFileLocation=None): """Get SSH object of VM""" # If NAT Rules are not created while VM deployment in Advanced mode # then, IP address must be passed - if ipaddress != None: + if ipaddress is not None: self.ssh_ip = ipaddress if port: self.ssh_port = port @@ -498,21 +549,48 @@ def get_ssh_client(self, ipaddress=None, reconnect=False, port=None, keyPairFile if reconnect: self.ssh_client = is_server_ssh_ready( - self.ssh_ip, - self.ssh_port, - self.username, - self.password, - keyPairFileLocation=keyPairFileLocation - ) + self.ssh_ip, + self.ssh_port, + self.username, + self.password, + keyPairFileLocation=keyPairFileLocation + ) self.ssh_client = self.ssh_client or is_server_ssh_ready( - self.ssh_ip, - self.ssh_port, - self.username, - self.password, - keyPairFileLocation=keyPairFileLocation - ) + self.ssh_ip, + self.ssh_port, + self.username, + self.password, + keyPairFileLocation=keyPairFileLocation + ) return self.ssh_client + def getState(self, apiclient, state, timeout=600): + """List VM and check if its state is as expected + @returnValue - List[Result, Reason] + 1) Result - FAIL if there is any exception + in the operation or VM state does not change + to expected state in given time else PASS + 2) Reason - Reason for failure""" + + returnValue = [FAIL, "VM state not trasited to %s,\ + operation timed out" % state] + + while timeout>0: + try: + vms = VirtualMachine.list(apiclient, id=self.id, listAll=True) + validationresult = validateList(vms) + if validationresult[0] == FAIL: + raise Exception("VM list validation failed: %s" % validationresult[2]) + elif str(vms[0].state).lower() == str(state).lower(): + returnValue = [PASS, None] + break + except Exception as e: + returnValue = [FAIL, e] + break + time.sleep(60) + timeout -= 60 + return returnValue + def resetSshKey(self, apiclient, **kwargs): """Resets SSH key""" @@ -576,7 +654,8 @@ def remove_nic(self, apiclient, nicId): def update_default_nic(self, apiclient, nicId): """Set a NIC to be the default network adapter for a VM""" - cmd = updateDefaultNicForVirtualMachine.updateDefaultNicForVirtualMachineCmd() + cmd = updateDefaultNicForVirtualMachine.\ + updateDefaultNicForVirtualMachineCmd() cmd.nicid = nicId cmd.virtualmachineid = self.id return apiclient.updateDefaultNicForVirtualMachine(cmd) @@ -591,12 +670,20 @@ def attach_iso(self, apiclient, iso): def detach_iso(self, apiclient): """Detach ISO to instance""" cmd = detachIso.detachIsoCmd() - cmd.id = self.id + cmd.virtualmachineid = self.id return apiclient.detachIso(cmd) + def scale_virtualmachine(self, apiclient, serviceOfferingId): + """ Scale up of service offering for the Instance""" + cmd = scaleVirtualMachine.scaleVirtualMachineCmd() + cmd.id = self.id + cmd.serviceofferingid = serviceOfferingId + return apiclient.scaleVirtualMachine(cmd) + def change_service_offering(self, apiclient, serviceOfferingId): """Change service offering of the instance""" - cmd = changeServiceForVirtualMachine.changeServiceForVirtualMachineCmd() + cmd = changeServiceForVirtualMachine.\ + changeServiceForVirtualMachineCmd() cmd.id = self.id cmd.serviceofferingid = serviceOfferingId return apiclient.changeServiceForVirtualMachine(cmd) @@ -607,12 +694,15 @@ def list(cls, apiclient, **kwargs): cmd = listVirtualMachines.listVirtualMachinesCmd() [setattr(cmd, k, v) for k, v in kwargs.items()] + if 'account' in kwargs.keys() and 'domainid' in kwargs.keys(): + cmd.listall=True return(apiclient.listVirtualMachines(cmd)) def resetPassword(self, apiclient): """Resets VM password if VM created using password enabled template""" - cmd = resetPasswordForVirtualMachine.resetPasswordForVirtualMachineCmd() + cmd = resetPasswordForVirtualMachine.\ + resetPasswordForVirtualMachineCmd() cmd.id = self.id try: response = apiclient.resetPasswordForVirtualMachine(cmd) @@ -624,15 +714,15 @@ def resetPassword(self, apiclient): def assign_virtual_machine(self, apiclient, account, domainid): """Move a user VM to another user under same domain.""" - cmd = assignVirtualMachine.assignVirtualMachineCmd() + cmd = assignVirtualMachine.assignVirtualMachineCmd() cmd.virtualmachineid = self.id - cmd.account = account - cmd.domainid = domainid + cmd.account = account + cmd.domainid = domainid try: response = apiclient.assignVirtualMachine(cmd) return response except Exception as e: - raise Exception("assignVirtualMachine failed - %s" %e) + raise Exception("assignVirtualMachine failed - %s" % e) def update_affinity_group(self, apiclient, affinitygroupids=None, affinitygroupnames=None): @@ -649,12 +739,12 @@ def update_affinity_group(self, apiclient, affinitygroupids=None, return apiclient.updateVMAffinityGroup(cmd) def scale(self, apiclient, serviceOfferingId, - customcpunumber=None, customcpuspeed=None, custommemory=None): + customcpunumber=None, customcpuspeed=None, custommemory=None): """Change service offering of the instance""" cmd = scaleVirtualMachine.scaleVirtualMachineCmd() cmd.id = self.id cmd.serviceofferingid = serviceOfferingId - cmd.details = [{"cpuNumber": "","cpuSpeed":"","memory":""}] + cmd.details = [{"cpuNumber": "", "cpuSpeed": "", "memory": ""}] if customcpunumber: cmd.details[0]["cpuNumber"] = customcpunumber if customcpuspeed: @@ -665,8 +755,10 @@ def scale(self, apiclient, serviceOfferingId, class Volume: + """Manage Volume Life cycle """ + def __init__(self, items): self.__dict__.update(items) @@ -703,7 +795,7 @@ def create(cls, apiclient, services, zoneid=None, account=None, @classmethod def create_custom_disk(cls, apiclient, services, account=None, - domainid=None, diskofferingid=None): + domainid=None, diskofferingid=None): """Create Volume from Custom disk offering""" cmd = createVolume.createVolumeCmd() cmd.name = services["diskname"] @@ -759,6 +851,8 @@ def list(cls, apiclient, **kwargs): cmd = listVolumes.listVolumesCmd() [setattr(cmd, k, v) for k, v in kwargs.items()] + if 'account' in kwargs.keys() and 'domainid' in kwargs.keys(): + cmd.listall=True return(apiclient.listVolumes(cmd)) def resize(self, apiclient, **kwargs): @@ -769,7 +863,8 @@ def resize(self, apiclient, **kwargs): return(apiclient.resizeVolume(cmd)) @classmethod - def upload(cls, apiclient, services, zoneid=None, account=None, domainid=None, url=None): + def upload(cls, apiclient, services, zoneid=None, + account=None, domainid=None, url=None): """Uploads the volume to specified account""" cmd = uploadVolume.uploadVolumeCmd() @@ -794,10 +889,10 @@ def wait_for_upload(self, apiclient, timeout=10, interval=60): while True: volume_response = Volume.list( - apiclient, - id=self.id, - zoneid=self.zoneid, - ) + apiclient, + id=self.id, + zoneid=self.zoneid, + ) if isinstance(volume_response, list): volume = volume_response[0] @@ -812,7 +907,7 @@ def wait_for_upload(self, apiclient, timeout=10, interval=60): elif 'Installing' not in volume.state: raise Exception( "Error in uploading volume: status - %s" % - volume.state) + volume.state) elif timeout == 0: break @@ -821,6 +916,16 @@ def wait_for_upload(self, apiclient, timeout=10, interval=60): timeout = timeout - 1 return + @classmethod + def extract(cls, apiclient, volume_id, zoneid, mode): + """Extracts the volume""" + + cmd = extractVolume.extractVolumeCmd() + cmd.id = volume_id + cmd.zoneid = zoneid + cmd.mode = mode + return Volume(apiclient.extractVolume(cmd).__dict__) + @classmethod def migrate(cls, apiclient, **kwargs): """Migrate a volume""" @@ -828,15 +933,18 @@ def migrate(cls, apiclient, **kwargs): [setattr(cmd, k, v) for k, v in kwargs.items()] return(apiclient.migrateVolume(cmd)) + class Snapshot: + """Manage Snapshot Lifecycle """ + def __init__(self, items): self.__dict__.update(items) @classmethod def create(cls, apiclient, volume_id, account=None, - domainid=None, projectid=None): + domainid=None, projectid=None): """Create Snapshot""" cmd = createSnapshot.createSnapshotCmd() cmd.volumeid = volume_id @@ -860,10 +968,13 @@ def list(cls, apiclient, **kwargs): cmd = listSnapshots.listSnapshotsCmd() [setattr(cmd, k, v) for k, v in kwargs.items()] + if 'account' in kwargs.keys() and 'domainid' in kwargs.keys(): + cmd.listall=True return(apiclient.listSnapshots(cmd)) class Template: + """Manage template life cycle""" def __init__(self, items): @@ -888,16 +999,20 @@ def create(cls, apiclient, services, volumeid=None, if not isinstance(ostypes, list): raise Exception( "Unable to find Ostype id with desc: %s" % - services["ostype"]) + services["ostype"]) cmd.ostypeid = ostypes[0].id else: raise Exception( - "Unable to find Ostype is required for creating template") + "Unable to find Ostype is required for creating template") - cmd.isfeatured = services["isfeatured"] if "isfeatured" in services else False - cmd.ispublic = services["ispublic"] if "ispublic" in services else False - cmd.isextractable = services["isextractable"] if "isextractable" in services else False - cmd.passwordenabled = services["passwordenabled"] if "passwordenabled" in services else False + cmd.isfeatured = services[ + "isfeatured"] if "isfeatured" in services else False + cmd.ispublic = services[ + "ispublic"] if "ispublic" in services else False + cmd.isextractable = services[ + "isextractable"] if "isextractable" in services else False + cmd.passwordenabled = services[ + "passwordenabled"] if "passwordenabled" in services else False if volumeid: cmd.volumeid = volumeid @@ -914,7 +1029,7 @@ def create(cls, apiclient, services, volumeid=None, @classmethod def register(cls, apiclient, services, zoneid=None, - account=None, domainid=None): + account=None, domainid=None, hypervisor=None): """Create template from URL""" # Create template from Virtual machine and Volume ID @@ -922,7 +1037,7 @@ def register(cls, apiclient, services, zoneid=None, cmd.displaytext = services["displaytext"] cmd.name = "-".join([services["name"], random_gen()]) cmd.format = services["format"] - cmd.hypervisor = apiclient.hypervisor + cmd.hypervisor = hypervisor if "ostypeid" in services: cmd.ostypeid = services["ostypeid"] @@ -935,11 +1050,11 @@ def register(cls, apiclient, services, zoneid=None, if not isinstance(ostypes, list): raise Exception( "Unable to find Ostype id with desc: %s" % - services["ostype"]) + services["ostype"]) cmd.ostypeid = ostypes[0].id else: raise Exception( - "Unable to find Ostype is required for registering template") + "Unable to find Ostype is required for registering template") cmd.url = services["url"] @@ -948,10 +1063,14 @@ def register(cls, apiclient, services, zoneid=None, else: cmd.zoneid = services["zoneid"] - cmd.isfeatured = services["isfeatured"] if "isfeatured" in services else False - cmd.ispublic = services["ispublic"] if "ispublic" in services else False - cmd.isextractable = services["isextractable"] if "isextractable" in services else False - cmd.passwordenabled = services["passwordenabled"] if "passwordenabled" in services else False + cmd.isfeatured = services[ + "isfeatured"] if "isfeatured" in services else False + cmd.ispublic = services[ + "ispublic"] if "ispublic" in services else False + cmd.isextractable = services[ + "isextractable"] if "isextractable" in services else False + cmd.passwordenabled = services[ + "passwordenabled"] if "passwordenabled" in services else False if account: cmd.account = account @@ -978,15 +1097,15 @@ def extract(cls, apiclient, id, mode, zoneid=None): @classmethod def create_from_snapshot(cls, apiclient, snapshot, services, - random_name=True): + random_name=True): """Create Template from snapshot""" # Create template from Virtual machine and Snapshot ID cmd = createTemplate.createTemplateCmd() cmd.displaytext = services["displaytext"] cmd.name = "-".join([ - services["name"], - random_gen() - ]) if random_name else services["name"] + services["name"], + random_gen() + ]) if random_name else services["name"] if "ostypeid" in services: cmd.ostypeid = services["ostypeid"] @@ -999,11 +1118,11 @@ def create_from_snapshot(cls, apiclient, snapshot, services, if not isinstance(ostypes, list): raise Exception( "Unable to find Ostype id with desc: %s" % - services["ostype"]) + services["ostype"]) cmd.ostypeid = ostypes[0].id else: raise Exception( - "Unable to find Ostype is required for creating template") + "Unable to find Ostype is required for creating template") cmd.snapshotid = snapshot.id return Template(apiclient.createTemplate(cmd).__dict__) @@ -1022,11 +1141,11 @@ def download(self, apiclient, timeout=5, interval=60): while True: template_response = Template.list( - apiclient, - id=self.id, - zoneid=self.zoneid, - templatefilter='self' - ) + apiclient, + id=self.id, + zoneid=self.zoneid, + templatefilter='self' + ) if isinstance(template_response, list): template = template_response[0] @@ -1043,7 +1162,7 @@ def download(self, apiclient, timeout=5, interval=60): elif 'Installing' not in template.status: raise Exception( "Error in downloading template: status - %s" % - template.status) + template.status) elif timeout == 0: break @@ -1061,16 +1180,38 @@ def updatePermissions(self, apiclient, **kwargs): [setattr(cmd, k, v) for k, v in kwargs.items()] return(apiclient.updateTemplatePermissions(cmd)) + def update(self, apiclient, **kwargs): + """Updates the template details""" + + cmd = updateTemplate.updateTemplateCmd() + cmd.id = self.id + [setattr(cmd, k, v) for k, v in kwargs.items()] + return(apiclient.updateTemplate(cmd)) + + @classmethod + def copy(cls, apiclient, id, sourcezoneid, destzoneid): + "Copy Template from source Zone to Destination Zone" + + cmd = copyTemplate.copyTemplateCmd() + cmd.id = id + cmd.sourcezoneid = sourcezoneid + cmd.destzoneid = destzoneid + + return apiclient.copyTemplate(cmd) + @classmethod def list(cls, apiclient, **kwargs): """List all templates matching criteria""" cmd = listTemplates.listTemplatesCmd() [setattr(cmd, k, v) for k, v in kwargs.items()] + if 'account' in kwargs.keys() and 'domainid' in kwargs.keys(): + cmd.listall=True return(apiclient.listTemplates(cmd)) class Iso: + """Manage ISO life cycle""" def __init__(self, items): @@ -1078,7 +1219,7 @@ def __init__(self, items): @classmethod def create(cls, apiclient, services, account=None, domainid=None, - projectid=None): + projectid=None): """Create an ISO""" # Create ISO from URL cmd = registerIso.registerIsoCmd() @@ -1095,11 +1236,11 @@ def create(cls, apiclient, services, account=None, domainid=None, if not isinstance(ostypes, list): raise Exception( "Unable to find Ostype id with desc: %s" % - services["ostype"]) + services["ostype"]) cmd.ostypeid = ostypes[0].id else: raise Exception( - "Unable to find Ostype is required for creating ISO") + "Unable to find Ostype is required for creating ISO") cmd.url = services["url"] cmd.zoneid = services["zoneid"] @@ -1149,10 +1290,10 @@ def download(self, apiclient, timeout=5, interval=60): if response.status == 'Successfully Installed': return elif 'Downloaded' not in response.status and \ - 'Installing' not in response.status: + 'Installing' not in response.status: raise Exception( "Error In Downloading ISO: ISO Status - %s" % - response.status) + response.status) elif timeout == 0: raise Exception("ISO download Timeout Exception") @@ -1160,24 +1301,58 @@ def download(self, apiclient, timeout=5, interval=60): timeout = timeout - 1 return + @classmethod + def extract(cls, apiclient, id, mode, zoneid=None): + "Extract ISO " + + cmd = extractIso.extractIsoCmd() + cmd.id = id + cmd.mode = mode + cmd.zoneid = zoneid + + return apiclient.extractIso(cmd) + + def update(self, apiclient, **kwargs): + """Updates the ISO details""" + + cmd = updateIso.updateIsoCmd() + cmd.id = self.id + [setattr(cmd, k, v) for k, v in kwargs.items()] + return(apiclient.updateIso(cmd)) + + @classmethod + def copy(cls, apiclient, id, sourcezoneid, destzoneid): + "Copy ISO from source Zone to Destination Zone" + + cmd = copyIso.copyIsoCmd() + cmd.id = id + cmd.sourcezoneid = sourcezoneid + cmd.destzoneid = destzoneid + + return apiclient.copyIso(cmd) + @classmethod def list(cls, apiclient, **kwargs): """Lists all available ISO files.""" cmd = listIsos.listIsosCmd() [setattr(cmd, k, v) for k, v in kwargs.items()] + if 'account' in kwargs.keys() and 'domainid' in kwargs.keys(): + cmd.listall=True return(apiclient.listIsos(cmd)) class PublicIPAddress: + """Manage Public IP Addresses""" def __init__(self, items): self.__dict__.update(items) @classmethod - def create(cls, apiclient, accountid=None, zoneid=None, domainid=None, services=None, - networkid=None, projectid=None, vpcid=None, isportable=False): + def create(cls, apiclient, accountid=None, zoneid=None, domainid=None, + services=None, networkid=None, projectid=None, vpcid=None, + isportable=False): """Associate Public IP address""" cmd = associateIpAddress.associateIpAddressCmd() @@ -1222,10 +1397,12 @@ def list(cls, apiclient, **kwargs): cmd = listPublicIpAddresses.listPublicIpAddressesCmd() [setattr(cmd, k, v) for k, v in kwargs.items()] + cmd.listall=True return(apiclient.listPublicIpAddresses(cmd)) class NATRule: + """Manage port forwarding rule""" def __init__(self, items): @@ -1233,7 +1410,8 @@ def __init__(self, items): @classmethod def create(cls, apiclient, virtual_machine, services, ipaddressid=None, - projectid=None, openfirewall=False, networkid=None, vpcid=None): + projectid=None, openfirewall=False, networkid=None, vpcid=None, + vmguestip=None): """Create Port forwarding rule""" cmd = createPortForwardingRule.createPortForwardingRuleCmd() @@ -1262,6 +1440,10 @@ def create(cls, apiclient, virtual_machine, services, ipaddressid=None, if vpcid: cmd.vpcid = vpcid + + if vmguestip: + cmd.vmguestip = vmguestip + return NATRule(apiclient.createPortForwardingRule(cmd).__dict__) def delete(self, apiclient): @@ -1277,17 +1459,21 @@ def list(cls, apiclient, **kwargs): cmd = listPortForwardingRules.listPortForwardingRulesCmd() [setattr(cmd, k, v) for k, v in kwargs.items()] + if 'account' in kwargs.keys() and 'domainid' in kwargs.keys(): + cmd.listall=True return(apiclient.listPortForwardingRules(cmd)) class StaticNATRule: + """Manage Static NAT rule""" def __init__(self, items): self.__dict__.update(items) @classmethod - def create(cls, apiclient, services, ipaddressid=None, networkid=None, vpcid=None): + def create(cls, apiclient, services, ipaddressid=None, + networkid=None, vpcid=None): """Creates static ip forwarding rule""" cmd = createFirewallRule.createFirewallRuleCmd() @@ -1325,10 +1511,13 @@ def list(cls, apiclient, **kwargs): cmd = listIpForwardingRules.listIpForwardingRulesCmd() [setattr(cmd, k, v) for k, v in kwargs.items()] + if 'account' in kwargs.keys() and 'domainid' in kwargs.keys(): + cmd.listall=True return(apiclient.listIpForwardingRules(cmd)) @classmethod - def enable(cls, apiclient, ipaddressid, virtualmachineid, networkid=None): + def enable(cls, apiclient, ipaddressid, virtualmachineid, networkid=None, + vmguestip=None): """Enables Static NAT rule""" cmd = enableStaticNat.enableStaticNatCmd() @@ -1336,6 +1525,9 @@ def enable(cls, apiclient, ipaddressid, virtualmachineid, networkid=None): cmd.virtualmachineid = virtualmachineid if networkid: cmd.networkid = networkid + + if vmguestip: + cmd.vmguestip = vmguestip apiclient.enableStaticNat(cmd) return @@ -1350,6 +1542,7 @@ def disable(cls, apiclient, ipaddressid, virtualmachineid): class EgressFireWallRule: + """Manage Egress Firewall rule""" def __init__(self, items): @@ -1369,7 +1562,8 @@ def create(cls, apiclient, networkid, protocol, cidrlist=None, if endport: cmd.endport = endport - return EgressFireWallRule(apiclient.createEgressFirewallRule(cmd).__dict__) + return EgressFireWallRule( + apiclient.createEgressFirewallRule(cmd).__dict__) def delete(self, apiclient): """Delete Egress Firewall rule""" @@ -1384,11 +1578,13 @@ def list(cls, apiclient, **kwargs): cmd = listEgressFirewallRules.listEgressFirewallRulesCmd() [setattr(cmd, k, v) for k, v in kwargs.items()] + if 'account' in kwargs.keys() and 'domainid' in kwargs.keys(): + cmd.listall=True return(apiclient.listEgressFirewallRules(cmd)) - class FireWallRule: + """Manage Firewall rule""" def __init__(self, items): @@ -1429,10 +1625,13 @@ def list(cls, apiclient, **kwargs): cmd = listFirewallRules.listFirewallRulesCmd() [setattr(cmd, k, v) for k, v in kwargs.items()] + if 'account' in kwargs.keys() and 'domainid' in kwargs.keys(): + cmd.listall=True return(apiclient.listFirewallRules(cmd)) class ServiceOffering: + """Manage service offerings cycle""" def __init__(self, items): @@ -1459,15 +1658,22 @@ def create(cls, apiclient, services, domainid=None, **kwargs): if "tags" in services: cmd.tags = services["tags"] + if "hosttags" in services: + cmd.hosttags = services["hosttags"] + if "deploymentplanner" in services: cmd.deploymentplanner = services["deploymentplanner"] if "serviceofferingdetails" in services: - cmd.serviceofferingdetails.append({services['serviceofferingdetails']}) + cmd.serviceofferingdetails.append( + {services['serviceofferingdetails']}) if "isvolatile" in services: cmd.isvolatile = services["isvolatile"] + if "offerha" in services: + cmd.offerha = services["offerha"] + # Service Offering private to that domain if domainid: cmd.domainid = domainid @@ -1488,10 +1694,13 @@ def list(cls, apiclient, **kwargs): cmd = listServiceOfferings.listServiceOfferingsCmd() [setattr(cmd, k, v) for k, v in kwargs.items()] + if 'account' in kwargs.keys() and 'domainid' in kwargs.keys(): + cmd.listall=True return(apiclient.listServiceOfferings(cmd)) class DiskOffering: + """Manage disk offerings cycle""" def __init__(self, items): @@ -1529,10 +1738,13 @@ def list(cls, apiclient, **kwargs): cmd = listDiskOfferings.listDiskOfferingsCmd() [setattr(cmd, k, v) for k, v in kwargs.items()] + if 'account' in kwargs.keys() and 'domainid' in kwargs.keys(): + cmd.listall=True return(apiclient.listDiskOfferings(cmd)) class NetworkOffering: + """Manage network offerings cycle""" def __init__(self, items): @@ -1557,18 +1769,19 @@ def create(cls, apiclient, services, **kwargs): if "serviceProviderList" in services: for service, provider in services["serviceProviderList"].items(): cmd.serviceproviderlist.append({ - 'service': service, - 'provider': provider - }) + 'service': service, + 'provider': provider + }) if "serviceCapabilityList" in services: cmd.servicecapabilitylist = [] - for service, capability in services["serviceCapabilityList"].items(): + for service, capability in services["serviceCapabilityList"].\ + items(): for ctype, value in capability.items(): cmd.servicecapabilitylist.append({ - 'service': service, - 'capabilitytype': ctype, - 'capabilityvalue': value - }) + 'service': service, + 'capabilitytype': ctype, + 'capabilityvalue': value + }) if "specifyVlan" in services: cmd.specifyVlan = services["specifyVlan"] if "specifyIpRanges" in services: @@ -1605,10 +1818,13 @@ def list(cls, apiclient, **kwargs): cmd = listNetworkOfferings.listNetworkOfferingsCmd() [setattr(cmd, k, v) for k, v in kwargs.items()] + if 'account' in kwargs.keys() and 'domainid' in kwargs.keys(): + cmd.listall=True return(apiclient.listNetworkOfferings(cmd)) class SnapshotPolicy: + """Manage snapshot policies""" def __init__(self, items): @@ -1638,10 +1854,31 @@ def list(cls, apiclient, **kwargs): cmd = listSnapshotPolicies.listSnapshotPoliciesCmd() [setattr(cmd, k, v) for k, v in kwargs.items()] + if 'account' in kwargs.keys() and 'domainid' in kwargs.keys(): + cmd.listall=True return(apiclient.listSnapshotPolicies(cmd)) +class Hypervisor: + + """Manage Hypervisor""" + + def __init__(self, items): + self.__dict__.update(items) + + @classmethod + def list(cls, apiclient, **kwargs): + """Lists hypervisors""" + + cmd = listHypervisors.listHypervisorsCmd() + [setattr(cmd, k, v) for k, v in kwargs.items()] + if 'account' in kwargs.keys() and 'domainid' in kwargs.keys(): + cmd.listall=True + return(apiclient.listHypervisors(cmd)) + + class LoadBalancerRule: + """Manage Load Balancer rule""" def __init__(self, items): @@ -1707,7 +1944,8 @@ def remove(self, apiclient, vms): apiclient.removeFromLoadBalancerRule(cmd) return - def update(self, apiclient, algorithm=None, description=None, name=None, **kwargs): + def update(self, apiclient, algorithm=None, + description=None, name=None, **kwargs): """Updates the load balancing rule""" cmd = updateLoadBalancerRule.updateLoadBalancerRuleCmd() cmd.id = self.id @@ -1721,7 +1959,8 @@ def update(self, apiclient, algorithm=None, description=None, name=None, **kwarg [setattr(cmd, k, v) for k, v in kwargs.items()] return apiclient.updateLoadBalancerRule(cmd) - def createSticky(self, apiclient, methodname, name, description=None, param=None): + def createSticky( + self, apiclient, methodname, name, description=None, param=None): """Creates a sticky policy for the LB rule""" cmd = createLBStickinessPolicy.createLBStickinessPolicyCmd() @@ -1750,6 +1989,8 @@ def listStickyPolicies(cls, apiclient, lbruleid, **kwargs): cmd = listLBStickinessPolicies.listLBStickinessPoliciesCmd() cmd.lbruleid = lbruleid [setattr(cmd, k, v) for k, v in kwargs.items()] + if 'account' in kwargs.keys() and 'domainid' in kwargs.keys(): + cmd.listall=True return apiclient.listLBStickinessPolicies(cmd) @classmethod @@ -1758,21 +1999,25 @@ def list(cls, apiclient, **kwargs): cmd = listLoadBalancerRules.listLoadBalancerRulesCmd() [setattr(cmd, k, v) for k, v in kwargs.items()] + if 'account' in kwargs.keys() and 'domainid' in kwargs.keys(): + cmd.listall=True return(apiclient.listLoadBalancerRules(cmd)) class Cluster: + """Manage Cluster life cycle""" def __init__(self, items): self.__dict__.update(items) @classmethod - def create(cls, apiclient, services, zoneid=None, podid=None): + def create(cls, apiclient, services, zoneid=None, podid=None, + hypervisor=None): """Create Cluster""" cmd = addCluster.addClusterCmd() cmd.clustertype = services["clustertype"] - cmd.hypervisor = apiclient.hypervisor + cmd.hypervisor = hypervisor if zoneid: cmd.zoneid = zoneid @@ -1808,46 +2053,75 @@ def list(cls, apiclient, **kwargs): cmd = listClusters.listClustersCmd() [setattr(cmd, k, v) for k, v in kwargs.items()] + if 'account' in kwargs.keys() and 'domainid' in kwargs.keys(): + cmd.listall=True return(apiclient.listClusters(cmd)) class Host: + """Manage Host life cycle""" def __init__(self, items): self.__dict__.update(items) @classmethod - def create(cls, apiclient, cluster, services, zoneid=None, podid=None): - """Create Host in cluster""" - - cmd = addHost.addHostCmd() - cmd.hypervisor = apiclient.hypervisor - cmd.url = services["url"] - cmd.clusterid = cluster.id - - if zoneid: - cmd.zoneid = zoneid - else: - cmd.zoneid = services["zoneid"] - - if podid: - cmd.podid = podid - else: - cmd.podid = services["podid"] - - if "clustertype" in services: - cmd.clustertype = services["clustertype"] - if "username" in services: - cmd.username = services["username"] - if "password" in services: - cmd.password = services["password"] + def create(cls, apiclient, cluster, services, + zoneid=None, podid=None, hypervisor=None): + """ + 1. Creates the host based upon the information provided. + 2. Verifies the output of the adding host and its state post addition + Returns FAILED in case of an issue, else an instance of Host + """ + try: + cmd = addHost.addHostCmd() + cmd.hypervisor = hypervisor + cmd.url = services["url"] + cmd.clusterid = cluster.id - # Add host - host = apiclient.addHost(cmd) + if zoneid: + cmd.zoneid = zoneid + else: + cmd.zoneid = services["zoneid"] - if isinstance(host, list): - return Host(host[0].__dict__) + if podid: + cmd.podid = podid + else: + cmd.podid = services["podid"] + + if "clustertype" in services: + cmd.clustertype = services["clustertype"] + if "username" in services: + cmd.username = services["username"] + if "password" in services: + cmd.password = services["password"] + + ''' + Adds a Host, + If response is valid and host is up return + an instance of Host. + If response is invalid, returns FAILED. + If host state is not up, verify through listHosts call + till host status is up and return accordingly. Max 3 retries + ''' + host = apiclient.addHost(cmd) + ret = validateList(host) + if ret[0] == PASS: + if str(host[0].state).lower() == 'up': + return Host(host[0].__dict__) + retries = 3 + while retries: + lh_resp = apiclient.listHosts(host[0].id) + ret = validateList(lh_resp) + if (ret[0] == PASS) and \ + (str(ret[1].state).lower() == 'up'): + return Host(host[0].__dict__) + retries += -1 + return FAILED + except Exception as e: + print "Exception Occurred Under Host.create : %s" % \ + GetDetailExceptionInfo(e) + return FAILED def delete(self, apiclient): """Delete Host""" @@ -1898,6 +2172,8 @@ def list(cls, apiclient, **kwargs): cmd = listHosts.listHostsCmd() [setattr(cmd, k, v) for k, v in kwargs.items()] + if 'account' in kwargs.keys() and 'domainid' in kwargs.keys(): + cmd.listall=True return(apiclient.listHosts(cmd)) @classmethod @@ -1906,6 +2182,8 @@ def listForMigration(cls, apiclient, **kwargs): cmd = findHostsForMigration.findHostsForMigrationCmd() [setattr(cmd, k, v) for k, v in kwargs.items()] + if 'account' in kwargs.keys() and 'domainid' in kwargs.keys(): + cmd.listall=True return(apiclient.findHostsForMigration(cmd)) @classmethod @@ -1918,6 +2196,7 @@ def update(cls, apiclient, **kwargs): class StoragePool: + """Manage Storage pools (Primary Storage)""" def __init__(self, items): @@ -1925,7 +2204,7 @@ def __init__(self, items): @classmethod def create(cls, apiclient, services, clusterid=None, - zoneid=None, podid=None): + zoneid=None, podid=None): """Create Storage pool (Primary Storage)""" cmd = createStoragePool.createStoragePoolCmd() @@ -1975,6 +2254,8 @@ def list(cls, apiclient, **kwargs): cmd = listStoragePools.listStoragePoolsCmd() [setattr(cmd, k, v) for k, v in kwargs.items()] + if 'account' in kwargs.keys() and 'domainid' in kwargs.keys(): + cmd.listall=True return(apiclient.listStoragePools(cmd)) @classmethod @@ -1983,9 +2264,13 @@ def listForMigration(cls, apiclient, **kwargs): cmd = findStoragePoolsForMigration.findStoragePoolsForMigrationCmd() [setattr(cmd, k, v) for k, v in kwargs.items()] + if 'account' in kwargs.keys() and 'domainid' in kwargs.keys(): + cmd.listall=True return(apiclient.findStoragePoolsForMigration(cmd)) + class Network: + """Manage Network pools""" def __init__(self, items): @@ -2073,10 +2358,13 @@ def list(cls, apiclient, **kwargs): cmd = listNetworks.listNetworksCmd() [setattr(cmd, k, v) for k, v in kwargs.items()] + if 'account' in kwargs.keys() and 'domainid' in kwargs.keys(): + cmd.listall=True return(apiclient.listNetworks(cmd)) class NetworkACL: + """Manage Network ACL lifecycle""" def __init__(self, items): @@ -2084,7 +2372,8 @@ def __init__(self, items): @classmethod def create(cls, apiclient, services, networkid=None, protocol=None, - number=None, aclid=None, action='Allow', traffictype=None, cidrlist=[]): + number=None, aclid=None, action='Allow', + traffictype=None, cidrlist=[]): """Create network ACL rules(Ingress/Egress)""" cmd = createNetworkACL.createNetworkACLCmd() @@ -2147,17 +2436,21 @@ def list(cls, apiclient, **kwargs): cmd = listNetworkACLs.listNetworkACLsCmd() [setattr(cmd, k, v) for k, v in kwargs.items()] + if 'account' in kwargs.keys() and 'domainid' in kwargs.keys(): + cmd.listall=True return(apiclient.listNetworkACLs(cmd)) class NetworkACLList: + """Manage Network ACL lists lifecycle""" def __init__(self, items): self.__dict__.update(items) @classmethod - def create(cls, apiclient, services, name=None, description=None, vpcid=None): + def create( + cls, apiclient, services, name=None, description=None, vpcid=None): """Create network ACL container list""" cmd = createNetworkACLList.createNetworkACLListCmd() @@ -2191,10 +2484,13 @@ def list(cls, apiclient, **kwargs): cmd = listNetworkACLLists.listNetworkACLListsCmd() [setattr(cmd, k, v) for k, v in kwargs.items()] + if 'account' in kwargs.keys() and 'domainid' in kwargs.keys(): + cmd.listall=True return(apiclient.listNetworkACLLists(cmd)) class Vpn: + """Manage VPN life cycle""" def __init__(self, items): @@ -2202,7 +2498,7 @@ def __init__(self, items): @classmethod def create(cls, apiclient, publicipid, account=None, domainid=None, - projectid=None, networkid=None, vpcid=None): + projectid=None, networkid=None, vpcid=None): """Create VPN for Public IP address""" cmd = createRemoteAccessVpn.createRemoteAccessVpnCmd() cmd.publicipid = publicipid @@ -2231,10 +2527,13 @@ def list(cls, apiclient, **kwargs): cmd = listRemoteAccessVpns.listRemoteAccessVpnsCmd() [setattr(cmd, k, v) for k, v in kwargs.items()] + if 'account' in kwargs.keys() and 'domainid' in kwargs.keys(): + cmd.listall=True return(apiclient.listRemoteAccessVpns(cmd)) class VpnUser: + """Manage VPN user""" def __init__(self, items): @@ -2275,10 +2574,13 @@ def list(cls, apiclient, **kwargs): cmd = listVpnUsers.listVpnUsersCmd() [setattr(cmd, k, v) for k, v in kwargs.items()] + if 'account' in kwargs.keys() and 'domainid' in kwargs.keys(): + cmd.listall=True return(apiclient.listVpnUsers(cmd)) class Zone: + """Manage Zone""" def __init__(self, items): @@ -2325,10 +2627,13 @@ def list(cls, apiclient, **kwargs): cmd = listZones.listZonesCmd() [setattr(cmd, k, v) for k, v in kwargs.items()] + if 'account' in kwargs.keys() and 'domainid' in kwargs.keys(): + cmd.listall=True return(apiclient.listZones(cmd)) class Pod: + """Manage Pod""" def __init__(self, items): @@ -2360,10 +2665,13 @@ def list(cls, apiclient, **kwargs): cmd = listPods.listPodsCmd() [setattr(cmd, k, v) for k, v in kwargs.items()] + if 'account' in kwargs.keys() and 'domainid' in kwargs.keys(): + cmd.listall=True return apiclient.listPods(cmd) class PublicIpRange: + """Manage VlanIpRange""" def __init__(self, items): @@ -2380,7 +2688,8 @@ def create(cls, apiclient, services): cmd.startip = services["startip"] cmd.endip = services["endip"] cmd.zoneid = services["zoneid"] - cmd.podid = services["podid"] + if "podid" in services: + cmd.podid = services["podid"] cmd.vlan = services["vlan"] return PublicIpRange(apiclient.createVlanIpRange(cmd).__dict__) @@ -2398,10 +2707,13 @@ def list(cls, apiclient, **kwargs): cmd = listVlanIpRanges.listVlanIpRangesCmd() [setattr(cmd, k, v) for k, v in kwargs.items()] + if 'account' in kwargs.keys() and 'domainid' in kwargs.keys(): + cmd.listall=True return(apiclient.listVlanIpRanges(cmd)) @classmethod - def dedicate(cls, apiclient, id, account=None, domainid=None, projectid=None): + def dedicate( + cls, apiclient, id, account=None, domainid=None, projectid=None): """Dedicate VLAN IP range""" cmd = dedicatePublicIpRange.dedicatePublicIpRangeCmd() @@ -2420,6 +2732,7 @@ def release(self, apiclient): class PortablePublicIpRange: + """Manage portable public Ip Range""" def __init__(self, items): @@ -2439,7 +2752,8 @@ def create(cls, apiclient, services): if "vlan" in services: cmd.vlan = services["vlan"] - return PortablePublicIpRange(apiclient.createPortableIpRange(cmd).__dict__) + return PortablePublicIpRange( + apiclient.createPortableIpRange(cmd).__dict__) def delete(self, apiclient): """Delete portable IpRange""" @@ -2454,9 +2768,13 @@ def list(cls, apiclient, **kwargs): cmd = listPortableIpRanges.listPortableIpRangesCmd() [setattr(cmd, k, v) for k, v in kwargs.items()] + if 'account' in kwargs.keys() and 'domainid' in kwargs.keys(): + cmd.listall=True return(apiclient.listPortableIpRanges(cmd)) + class SecondaryStagingStore: + """Manage Staging Store""" def __init__(self, items): @@ -2476,7 +2794,8 @@ def create(cls, apiclient, url, provider, services=None): if "scope" in services: cmd.scope = services["scope"] - return SecondaryStagingStore(apiclient.createSecondaryStagingStore(cmd).__dict__) + return SecondaryStagingStore( + apiclient.createSecondaryStagingStore(cmd).__dict__) def delete(self, apiclient): """Delete Staging Storage""" @@ -2488,10 +2807,13 @@ def delete(self, apiclient): def list(cls, apiclient, **kwargs): cmd = listSecondaryStagingStores.listSecondaryStagingStoresCmd() [setattr(cmd, k, v) for k, v in kwargs.items()] + if 'account' in kwargs.keys() and 'domainid' in kwargs.keys(): + cmd.listall=True return(apiclient.listSecondaryStagingStores(cmd)) class ImageStore: + """Manage image stores""" def __init__(self, items): @@ -2523,10 +2845,13 @@ def delete(self, apiclient): def list(cls, apiclient, **kwargs): cmd = listImageStores.listImageStoresCmd() [setattr(cmd, k, v) for k, v in kwargs.items()] + if 'account' in kwargs.keys() and 'domainid' in kwargs.keys(): + cmd.listall=True return(apiclient.listImageStores(cmd)) class PhysicalNetwork: + """Manage physical network storage""" def __init__(self, items): @@ -2567,7 +2892,8 @@ def addTrafficType(self, apiclient, type): return apiclient.addTrafficType(cmd) @classmethod - def dedicate(cls, apiclient, vlanrange, physicalnetworkid, account=None, domainid=None, projectid=None): + def dedicate(cls, apiclient, vlanrange, physicalnetworkid, + account=None, domainid=None, projectid=None): """Dedicate guest vlan range""" cmd = dedicateGuestVlanRange.dedicateGuestVlanRangeCmd() @@ -2581,7 +2907,8 @@ def dedicate(cls, apiclient, vlanrange, physicalnetworkid, account=None, domaini def release(self, apiclient): """Release guest vlan range""" - cmd = releaseDedicatedGuestVlanRange.releaseDedicatedGuestVlanRangeCmd() + cmd = releaseDedicatedGuestVlanRange.\ + releaseDedicatedGuestVlanRangeCmd() cmd.id = self.id return apiclient.releaseDedicatedGuestVlanRange(cmd) @@ -2591,6 +2918,8 @@ def listDedicated(cls, apiclient, **kwargs): cmd = listDedicatedGuestVlanRanges.listDedicatedGuestVlanRangesCmd() [setattr(cmd, k, v) for k, v in kwargs.items()] + if 'account' in kwargs.keys() and 'domainid' in kwargs.keys(): + cmd.listall=True return apiclient.listDedicatedGuestVlanRanges(cmd) @classmethod @@ -2599,10 +2928,14 @@ def list(cls, apiclient, **kwargs): cmd = listPhysicalNetworks.listPhysicalNetworksCmd() [setattr(cmd, k, v) for k, v in kwargs.items()] - return map(lambda pn : PhysicalNetwork(pn.__dict__), apiclient.listPhysicalNetworks(cmd)) + if 'account' in kwargs.keys() and 'domainid' in kwargs.keys(): + cmd.listall=True + return map(lambda pn: PhysicalNetwork( + pn.__dict__), apiclient.listPhysicalNetworks(cmd)) class SecurityGroup: + """Manage Security Groups""" def __init__(self, items): @@ -2614,7 +2947,7 @@ def create(cls, apiclient, services, account=None, domainid=None, """Create security group""" cmd = createSecurityGroup.createSecurityGroupCmd() - cmd.name = services["name"] + cmd.name = "-".join([services["name"], random_gen()]) if account: cmd.account = account if domainid: @@ -2694,9 +3027,9 @@ def authorizeEgress(self, apiclient, services, account=None, domainid=None, cmd.usersecuritygrouplist = [] for account, group in user_secgrp_list.items(): cmd.usersecuritygrouplist.append({ - 'account': account, - 'group': group - }) + 'account': account, + 'group': group + }) return (apiclient.authorizeSecurityGroupEgress(cmd).__dict__) @@ -2713,10 +3046,87 @@ def list(cls, apiclient, **kwargs): cmd = listSecurityGroups.listSecurityGroupsCmd() [setattr(cmd, k, v) for k, v in kwargs.items()] + if 'account' in kwargs.keys() and 'domainid' in kwargs.keys(): + cmd.listall=True return(apiclient.listSecurityGroups(cmd)) +class VpnCustomerGateway: + + """Manage VPN Customer Gateway""" + + def __init__(self, items): + self.__dict__.update(items) + + @classmethod + def create(cls, apiclient, services, name, gateway, cidrlist, + account=None, domainid=None): + """Create VPN Customer Gateway""" + cmd = createVpnCustomerGateway.createVpnCustomerGatewayCmd() + cmd.name = name + cmd.gateway = gateway + cmd.cidrlist = cidrlist + if "ipsecpsk" in services: + cmd.ipsecpsk = services["ipsecpsk"] + if "ikepolicy" in services: + cmd.ikepolicy = services["ikepolicy"] + if "ikelifetime" in services: + cmd.ikelifetime = services["ikelifetime"] + if "esppolicy" in services: + cmd.esppolicy = services["esppolicy"] + if "esplifetime" in services: + cmd.esplifetime = services["esplifetime"] + if "dpd" in services: + cmd.dpd = services["dpd"] + if account: + cmd.account = account + if domainid: + cmd.domainid = domainid + return VpnCustomerGateway( + apiclient.createVpnCustomerGateway(cmd).__dict__) + + def update(self, apiclient, services, name, gateway, cidrlist): + """Updates VPN Customer Gateway""" + + cmd = updateVpnCustomerGateway.updateVpnCustomerGatewayCmd() + cmd.id = self.id + cmd.name = name + cmd.gateway = gateway + cmd.cidrlist = cidrlist + if "ipsecpsk" in services: + cmd.ipsecpsk = services["ipsecpsk"] + if "ikepolicy" in services: + cmd.ikepolicy = services["ikepolicy"] + if "ikelifetime" in services: + cmd.ikelifetime = services["ikelifetime"] + if "esppolicy" in services: + cmd.esppolicy = services["esppolicy"] + if "esplifetime" in services: + cmd.esplifetime = services["esplifetime"] + if "dpd" in services: + cmd.dpd = services["dpd"] + return(apiclient.updateVpnCustomerGateway(cmd)) + + def delete(self, apiclient): + """Delete VPN Customer Gateway""" + + cmd = deleteVpnCustomerGateway.deleteVpnCustomerGatewayCmd() + cmd.id = self.id + apiclient.deleteVpnCustomerGateway(cmd) + + @classmethod + def list(cls, apiclient, **kwargs): + """List all VPN customer Gateway""" + + cmd = listVpnCustomerGateways.listVpnCustomerGatewaysCmd() + [setattr(cmd, k, v) for k, v in kwargs.items()] + if 'account' in kwargs.keys() and 'domainid' in kwargs.keys(): + cmd.listall=True + return(apiclient.listVpnCustomerGateways(cmd)) + + class Project: + """Manage Project life cycle""" def __init__(self, items): @@ -2790,6 +3200,8 @@ def listAccounts(cls, apiclient, **kwargs): cmd = listProjectAccounts.listProjectAccountsCmd() [setattr(cmd, k, v) for k, v in kwargs.items()] + if 'account' in kwargs.keys() and 'domainid' in kwargs.keys(): + cmd.listall=True return(apiclient.listProjectAccounts(cmd)) @classmethod @@ -2798,10 +3210,13 @@ def list(cls, apiclient, **kwargs): cmd = listProjects.listProjectsCmd() [setattr(cmd, k, v) for k, v in kwargs.items()] + if 'account' in kwargs.keys() and 'domainid' in kwargs.keys(): + cmd.listall=True return(apiclient.listProjects(cmd)) class ProjectInvitation: + """Manage project invitations""" def __init__(self, items): @@ -2834,10 +3249,13 @@ def list(cls, apiclient, **kwargs): cmd = listProjectInvitations.listProjectInvitationsCmd() [setattr(cmd, k, v) for k, v in kwargs.items()] + if 'account' in kwargs.keys() and 'domainid' in kwargs.keys(): + cmd.listall=True return(apiclient.listProjectInvitations(cmd)) class Configurations: + """Manage Configuration""" @classmethod @@ -2855,17 +3273,21 @@ def list(cls, apiclient, **kwargs): cmd = listConfigurations.listConfigurationsCmd() [setattr(cmd, k, v) for k, v in kwargs.items()] + if 'account' in kwargs.keys() and 'domainid' in kwargs.keys(): + cmd.listall=True return(apiclient.listConfigurations(cmd)) class NetScaler: + """Manage external netscaler device""" def __init__(self, items): self.__dict__.update(items) @classmethod - def add(cls, apiclient, services, physicalnetworkid, username=None, password=None): + def add(cls, apiclient, services, physicalnetworkid, + username=None, password=None): """Add external netscaler device to cloudstack""" cmd = addNetscalerLoadBalancer.addNetscalerLoadBalancerCmd() @@ -2885,11 +3307,14 @@ def add(cls, apiclient, services, physicalnetworkid, username=None, password=Non # Generate the URL url = 'https://' + str(services["ipaddress"]) + '?' url = url + 'publicinterface=' + str(services["publicinterface"]) + '&' - url = url + 'privateinterface=' + str(services["privateinterface"]) + '&' + url = url + 'privateinterface=' + \ + str(services["privateinterface"]) + '&' url = url + 'numretries=' + str(services["numretries"]) + '&' - if not services["lbdevicededicated"] and "lbdevicecapacity" in services: - url = url + 'lbdevicecapacity=' + str(services["lbdevicecapacity"]) + '&' + if not services["lbdevicededicated"] and \ + "lbdevicecapacity" in services: + url = url + 'lbdevicecapacity=' + \ + str(services["lbdevicecapacity"]) + '&' url = url + 'lbdevicededicated=' + str(services["lbdevicededicated"]) @@ -2907,7 +3332,8 @@ def delete(self, apiclient): def configure(self, apiclient, **kwargs): """List already registered netscaler devices""" - cmd = configureNetscalerLoadBalancer.configureNetscalerLoadBalancerCmd() + cmd = configureNetscalerLoadBalancer.\ + configureNetscalerLoadBalancerCmd() cmd.lbdeviceid = self.lbdeviceid [setattr(cmd, k, v) for k, v in kwargs.items()] return(apiclient.configureNetscalerLoadBalancer(cmd)) @@ -2918,10 +3344,13 @@ def list(cls, apiclient, **kwargs): cmd = listNetscalerLoadBalancers.listNetscalerLoadBalancersCmd() [setattr(cmd, k, v) for k, v in kwargs.items()] + if 'account' in kwargs.keys() and 'domainid' in kwargs.keys(): + cmd.listall=True return(apiclient.listNetscalerLoadBalancers(cmd)) class NetworkServiceProvider: + """Manage network serivce providers for CloudStack""" def __init__(self, items): @@ -2935,7 +3364,8 @@ def add(cls, apiclient, name, physicalnetworkid, servicelist): cmd.name = name cmd.physicalnetworkid = physicalnetworkid cmd.servicelist = servicelist - return NetworkServiceProvider(apiclient.addNetworkServiceProvider(cmd).__dict__) + return NetworkServiceProvider( + apiclient.addNetworkServiceProvider(cmd).__dict__) def delete(self, apiclient): """Deletes network service provider""" @@ -2967,10 +3397,13 @@ def list(cls, apiclient, **kwargs): cmd = listNetworkServiceProviders.listNetworkServiceProvidersCmd() [setattr(cmd, k, v) for k, v in kwargs.items()] + if 'account' in kwargs.keys() and 'domainid' in kwargs.keys(): + cmd.listall=True return(apiclient.listNetworkServiceProviders(cmd)) class Router: + """Manage router life cycle""" def __init__(self, items): @@ -3020,10 +3453,13 @@ def list(cls, apiclient, **kwargs): cmd = listRouters.listRoutersCmd() [setattr(cmd, k, v) for k, v in kwargs.items()] + if 'account' in kwargs.keys() and 'domainid' in kwargs.keys(): + cmd.listall=True return(apiclient.listRouters(cmd)) class Tag: + """Manage tags""" def __init__(self, items): @@ -3039,9 +3475,9 @@ def create(cls, apiclient, resourceIds, resourceType, tags): cmd.tags = [] for key, value in tags.items(): cmd.tags.append({ - 'key': key, - 'value': value - }) + 'key': key, + 'value': value + }) return Tag(apiclient.createTags(cmd).__dict__) def delete(self, apiclient, resourceIds, resourceType, tags): @@ -3053,9 +3489,9 @@ def delete(self, apiclient, resourceIds, resourceType, tags): cmd.tags = [] for key, value in tags.items(): cmd.tags.append({ - 'key': key, - 'value': value - }) + 'key': key, + 'value': value + }) apiclient.deleteTags(cmd) @classmethod @@ -3064,10 +3500,13 @@ def list(cls, apiclient, **kwargs): cmd = listTags.listTagsCmd() [setattr(cmd, k, v) for k, v in kwargs.items()] + if 'account' in kwargs.keys() and 'domainid' in kwargs.keys(): + cmd.listall=True return(apiclient.listTags(cmd)) class VpcOffering: + """Manage VPC offerings""" def __init__(self, items): @@ -3084,18 +3523,19 @@ def create(cls, apiclient, services): if "serviceProviderList" in services: for service, provider in services["serviceProviderList"].items(): cmd.serviceproviderlist.append({ - 'service': service, - 'provider': provider - }) + 'service': service, + 'provider': provider + }) if "serviceCapabilityList" in services: cmd.servicecapabilitylist = [] - for service, capability in services["serviceCapabilityList"].items(): + for service, capability in \ + services["serviceCapabilityList"].items(): for ctype, value in capability.items(): cmd.servicecapabilitylist.append({ - 'service': service, - 'capabilitytype': ctype, - 'capabilityvalue': value - }) + 'service': service, + 'capabilitytype': ctype, + 'capabilityvalue': value + }) return VpcOffering(apiclient.createVPCOffering(cmd).__dict__) def update(self, apiclient, name=None, displaytext=None, state=None): @@ -3117,6 +3557,8 @@ def list(cls, apiclient, **kwargs): cmd = listVPCOfferings.listVPCOfferingsCmd() [setattr(cmd, k, v) for k, v in kwargs.items()] + if 'account' in kwargs.keys() and 'domainid' in kwargs.keys(): + cmd.listall=True return(apiclient.listVPCOfferings(cmd)) def delete(self, apiclient): @@ -3128,6 +3570,7 @@ def delete(self, apiclient): class VPC: + """Manage Virtual Private Connection""" def __init__(self, items): @@ -3135,7 +3578,8 @@ def __init__(self, items): @classmethod def create(cls, apiclient, services, vpcofferingid, - zoneid, networkDomain=None, account=None, domainid=None, **kwargs): + zoneid, networkDomain=None, account=None, + domainid=None, **kwargs): """Creates the virtual private connection (VPC)""" cmd = createVPC.createVPCCmd() @@ -3185,10 +3629,13 @@ def list(cls, apiclient, **kwargs): cmd = listVPCs.listVPCsCmd() [setattr(cmd, k, v) for k, v in kwargs.items()] + if 'account' in kwargs.keys() and 'domainid' in kwargs.keys(): + cmd.listall=True return(apiclient.listVPCs(cmd)) class PrivateGateway: + """Manage private gateway lifecycle""" def __init__(self, items): @@ -3196,7 +3643,7 @@ def __init__(self, items): @classmethod def create(cls, apiclient, gateway, ipaddress, netmask, vlan, vpcid, - physicalnetworkid=None): + physicalnetworkid=None): """Create private gateway""" cmd = createPrivateGateway.createPrivateGatewayCmd() @@ -3223,10 +3670,13 @@ def list(cls, apiclient, **kwargs): cmd = listPrivateGateways.listPrivateGatewaysCmd() [setattr(cmd, k, v) for k, v in kwargs.items()] + if 'account' in kwargs.keys() and 'domainid' in kwargs.keys(): + cmd.listall=True return(apiclient.listPrivateGateways(cmd)) class AffinityGroup: + def __init__(self, items): self.__dict__.update(items) @@ -3254,10 +3704,15 @@ def delete(self, apiclient): def list(cls, apiclient, **kwargs): cmd = listAffinityGroups.listAffinityGroupsCmd() [setattr(cmd, k, v) for k, v in kwargs.items()] + if 'account' in kwargs.keys() and 'domainid' in kwargs.keys(): + cmd.listall=True return apiclient.listAffinityGroups(cmd) + class StaticRoute: + """Manage static route lifecycle""" + def __init__(self, items): self.__dict__.update(items) @@ -3283,15 +3738,20 @@ def list(cls, apiclient, **kwargs): cmd = listStaticRoutes.listStaticRoutesCmd() [setattr(cmd, k, v) for k, v in kwargs.items()] + if 'account' in kwargs.keys() and 'domainid' in kwargs.keys(): + cmd.listall=True return(apiclient.listStaticRoutes(cmd)) class VNMC: + """Manage VNMC lifecycle""" + def __init__(self, items): self.__dict__.update(items) - def create(cls, apiclient, hostname, username, password, physicalnetworkid): + def create(cls, apiclient, hostname, username, password, + physicalnetworkid): """Registers VNMC appliance""" cmd = addCiscoVnmcResource.addCiscoVnmcResourceCmd() @@ -3314,10 +3774,13 @@ def list(cls, apiclient, **kwargs): cmd = listCiscoVnmcResources.listCiscoVnmcResourcesCmd() [setattr(cmd, k, v) for k, v in kwargs.items()] + if 'account' in kwargs.keys() and 'domainid' in kwargs.keys(): + cmd.listall=True return(apiclient.listCiscoVnmcResources(cmd)) class SSHKeyPair: + """Manage SSH Key pairs""" def __init__(self, items, services): @@ -3325,7 +3788,7 @@ def __init__(self, items, services): @classmethod def create(cls, apiclient, name=None, account=None, - domainid=None, projectid=None): + domainid=None, projectid=None): """Creates SSH keypair""" cmd = createSSHKeyPair.createSSHKeyPairCmd() cmd.name = name @@ -3337,6 +3800,14 @@ def create(cls, apiclient, name=None, account=None, cmd.projectid = projectid return (apiclient.createSSHKeyPair(cmd)) + @classmethod + def register(cls, apiclient, name, publickey): + """Registers SSH keypair""" + cmd = registerSSHKeyPair.registerSSHKeyPairCmd() + cmd.name = name + cmd.publickey = publickey + return (apiclient.registerSSHKeyPair(cmd)) + def delete(self, apiclient): """Delete SSH key pair""" cmd = deleteSSHKeyPair.deleteSSHKeyPairCmd() @@ -3348,10 +3819,13 @@ def list(cls, apiclient, **kwargs): """List all SSH key pairs""" cmd = listSSHKeyPairs.listSSHKeyPairsCmd() [setattr(cmd, k, v) for k, v in kwargs.items()] + if 'account' in kwargs.keys() and 'domainid' in kwargs.keys(): + cmd.listall=True return(apiclient.listSSHKeyPairs(cmd)) class Capacities: + """Manage Capacities""" @classmethod @@ -3360,10 +3834,13 @@ def list(cls, apiclient, **kwargs): cmd = listCapacity.listCapacityCmd() [setattr(cmd, k, v) for k, v in kwargs.items()] + if 'account' in kwargs.keys() and 'domainid' in kwargs.keys(): + cmd.listall=True return(apiclient.listCapacity(cmd)) class Alert: + """Manage alerts""" @classmethod @@ -3372,10 +3849,13 @@ def list(cls, apiclient, **kwargs): cmd = listAlerts.listAlertsCmd() [setattr(cmd, k, v) for k, v in kwargs.items()] + if 'account' in kwargs.keys() and 'domainid' in kwargs.keys(): + cmd.listall=True return(apiclient.listAlerts(cmd)) class InstanceGroup: + """Manage VM instance groups""" def __init__(self, items): @@ -3416,6 +3896,8 @@ def list(cls, apiclient, **kwargs): """List all instance groups""" cmd = listInstanceGroups.listInstanceGroupsCmd() [setattr(cmd, k, v) for k, v in kwargs.items()] + if 'account' in kwargs.keys() and 'domainid' in kwargs.keys(): + cmd.listall=True return (apiclient.listInstanceGroups(cmd)) def startInstances(self, apiclient): @@ -3449,7 +3931,8 @@ def deleteInstances(self, apiclient): def changeServiceOffering(self, apiclient, serviceOfferingId): """Change service offering of the vm tier""" - cmd = changeServiceForVirtualMachine.changeServiceForVirtualMachineCmd() + cmd = changeServiceForVirtualMachine.\ + changeServiceForVirtualMachineCmd() cmd.group = self.id cmd.serviceofferingid = serviceOfferingId return apiclient.changeServiceForVirtualMachine(cmd) @@ -3462,8 +3945,10 @@ def recoverInstances(self, apiclient): class ASA1000V: + """Manage ASA 1000v lifecycle""" - def create(cls, apiclient, hostname, insideportprofile, clusterid, physicalnetworkid): + def create(cls, apiclient, hostname, insideportprofile, + clusterid, physicalnetworkid): """Registers ASA 1000v appliance""" cmd = addCiscoAsa1000vResource.addCiscoAsa1000vResourceCmd() @@ -3486,14 +3971,21 @@ def list(cls, apiclient, **kwargs): cmd = listCiscoAsa1000vResources.listCiscoAsa1000vResourcesCmd() [setattr(cmd, k, v) for k, v in kwargs.items()] + if 'account' in kwargs.keys() and 'domainid' in kwargs.keys(): + cmd.listall=True return(apiclient.listCiscoAsa1000vResources(cmd)) + class VmSnapshot: + """Manage VM Snapshot life cycle""" + def __init__(self, items): self.__dict__.update(items) + @classmethod - def create(cls,apiclient,vmid,snapshotmemory="false",name=None,description=None): + def create(cls, apiclient, vmid, snapshotmemory="false", + name=None, description=None): cmd = createVMSnapshot.createVMSnapshotCmd() cmd.virtualmachineid = vmid @@ -3504,29 +3996,34 @@ def create(cls,apiclient,vmid,snapshotmemory="false",name=None,description=None) if description: cmd.description = description return VmSnapshot(apiclient.createVMSnapshot(cmd).__dict__) - + @classmethod def list(cls, apiclient, **kwargs): cmd = listVMSnapshot.listVMSnapshotCmd() [setattr(cmd, k, v) for k, v in kwargs.items()] + if 'account' in kwargs.keys() and 'domainid' in kwargs.keys(): + cmd.listall=True return(apiclient.listVMSnapshot(cmd)) - + @classmethod - def revertToSnapshot(cls, apiclient,vmsnapshotid): + def revertToSnapshot(cls, apiclient, vmsnapshotid): cmd = revertToVMSnapshot.revertToVMSnapshotCmd() cmd.vmsnapshotid = vmsnapshotid - + return apiclient.revertToVMSnapshot(cmd) - + @classmethod - def deleteVMSnapshot(cls,apiclient,vmsnapshotid): + def deleteVMSnapshot(cls, apiclient, vmsnapshotid): cmd = deleteVMSnapshot.deleteVMSnapshotCmd() cmd.vmsnapshotid = vmsnapshotid - + return apiclient.deleteVMSnapshot(cmd) + class Region: + """ Regions related Api """ + def __init__(self, items): self.__dict__.update(items) @@ -3547,6 +4044,8 @@ def create(cls, apiclient, services): def list(cls, apiclient, **kwargs): cmd = listRegions.listRegionsCmd() [setattr(cmd, k, v) for k, v in kwargs.items()] + if 'account' in kwargs.keys() and 'domainid' in kwargs.keys(): + cmd.listall=True region = apiclient.listRegions(cmd) return region @@ -3568,14 +4067,16 @@ def delete(self, apiclient): class ApplicationLoadBalancer: + """Manage Application Load Balancers in VPC""" def __init__(self, items): self.__dict__.update(items) @classmethod - def create(cls, apiclient, services, name=None, sourceport=None, instanceport=22, - algorithm="roundrobin", scheme="internal", sourcenetworkid=None, networkid=None): + def create(cls, apiclient, services, name=None, sourceport=None, + instanceport=22, algorithm="roundrobin", scheme="internal", + sourcenetworkid=None, networkid=None): """Create Application Load Balancer""" cmd = createLoadBalancer.createLoadBalancerCmd() @@ -3644,9 +4145,13 @@ def list(cls, apiclient, **kwargs): """List all appln load balancers""" cmd = listLoadBalancers.listLoadBalancersCmd() [setattr(cmd, k, v) for k, v in kwargs.items()] + if 'account' in kwargs.keys() and 'domainid' in kwargs.keys(): + cmd.listall=True return(apiclient.listLoadBalancerRules(cmd)) + class Resources: + """Manage resource limits""" def __init__(self, items, services): @@ -3658,6 +4163,8 @@ def list(cls, apiclient, **kwargs): cmd = listResourceLimits.listResourceLimitsCmd() [setattr(cmd, k, v) for k, v in kwargs.items()] + if 'account' in kwargs.keys() and 'domainid' in kwargs.keys(): + cmd.listall=True return(apiclient.listResourceLimits(cmd)) @classmethod @@ -3675,9 +4182,12 @@ def updateCount(cls, apiclient, **kwargs): cmd = updateResourceCount.updateResourceCountCmd() [setattr(cmd, k, v) for k, v in kwargs.items()] return(apiclient.updateResourceCount(cmd)) - + + class NIC: + """NIC related API""" + def __init__(self, items): self.__dict__.update(items) @@ -3691,7 +4201,7 @@ def addIp(cls, apiclient, id, ipaddress=None): return(apiclient.addIpToNic(cmd)) @classmethod - def removeIp(cls,apiclient,ipaddressid): + def removeIp(cls, apiclient, ipaddressid): """Remove secondary Ip from NIC""" cmd = removeIpFromNic.removeIpFromNicCmd() cmd.id = ipaddressid @@ -3703,9 +4213,13 @@ def list(cls, apiclient, **kwargs): cmd = listNics.listNicsCmd() [setattr(cmd, k, v) for k, v in kwargs.items()] + if 'account' in kwargs.keys() and 'domainid' in kwargs.keys(): + cmd.listall=True return(apiclient.listNics(cmd)) - + + class IAMGroup: + def __init__(self, items): self.__dict__.update(items) @@ -3732,15 +4246,17 @@ def delete(self, apiclient): def list(cls, apiclient, **kwargs): cmd = listIAMGroups.listIAMGroupsCmd() [setattr(cmd, k, v) for k, v in kwargs.items()] - return apiclient.listIAMGroupsCmd(cmd) - + if 'account' in kwargs.keys() and 'domainid' in kwargs.keys(): + cmd.listall=True + return apiclient.listIAMGroups(cmd) + def addAccount(self, apiclient, accts): """Add accounts to iam group""" cmd = addAccountToIAMGroup.addAccountToIAMGroupCmd() cmd.id = self.id cmd.accounts = [str(acct.id) for acct in accts] apiclient.addAccountToIAMGroup(cmd) - return + return def removeAccount(self, apiclient, accts): """ Remove accounts from iam group""" @@ -3748,25 +4264,26 @@ def removeAccount(self, apiclient, accts): cmd.id = self.id cmd.accounts = [str(acct.id) for acct in accts] apiclient.removeAccountFromIAMGroup(cmd) - return - + return + def attachPolicy(self, apiclient, policies): """Add policies to iam group""" cmd = attachIAMPolicyToIAMGroup.attachIAMPolicyToIAMGroupCmd() cmd.id = self.id cmd.policies = [str(policy.id) for policy in policies] apiclient.attachIAMPolicyToIAMGroup(cmd) - return - + return + def detachPolicy(self, apiclient, policies): """Remove policies from iam group""" cmd = removeIAMPolicyFromIAMGroup.removeIAMPolicyFromIAMGroupCmd() cmd.id = self.id cmd.policies = [str(policy.id) for policy in policies] apiclient.removeIAMPolicyFromIAMGroup(cmd) - return - + return + class IAMPolicy: + def __init__(self, items): self.__dict__.update(items) @@ -3793,7 +4310,9 @@ def delete(self, apiclient): def list(cls, apiclient, **kwargs): cmd = listIAMPolicies.listIAMPoliciesCmd() [setattr(cmd, k, v) for k, v in kwargs.items()] - return apiclient.listIAMPoliciesCmd(cmd) + if 'account' in kwargs.keys() and 'domainid' in kwargs.keys(): + cmd.listall=True + return apiclient.listIAMPolicies(cmd) def addPermission(self, apiclient, permission): """Add permission to iam policy""" @@ -3804,31 +4323,81 @@ def addPermission(self, apiclient, permission): cmd.scope = permission['scope'] cmd.scopeid = permission['scopeid'] apiclient.addIAMPermissionToIAMPolicy(cmd) - return + return def removePermission(self, apiclient, permission): """Remove permission from iam policy""" - cmd = removeIAMPermissionFromIAMPolicy.removeIAMPermissionFromIAMPolicyCmd() + cmd = removeIAMPermissionFromIAMPolicy.\ + removeIAMPermissionFromIAMPolicyCmd() cmd.id = self.id cmd.action = permission['action'] cmd.entitytype = permission['entitytype'] cmd.scope = permission['scope'] cmd.scopeid = permission['scopeid'] apiclient.removeIAMPermissionFromIAMPolicy(cmd) - return - + return + def attachAccount(self, apiclient, accts): """Attach iam policy to accounts""" cmd = attachIAMPolicyToAccount.attachIAMPolicyToAccountCmd() cmd.id = self.id cmd.accounts = [str(acct.id) for acct in accts] apiclient.attachIAMPolicyToAccount(cmd) - return - + return + def detachAccount(self, apiclient, accts): """Detach iam policy from accounts""" cmd = removeIAMPolicyFromAccount.removeIAMPolicyFromAccountCmd() cmd.id = self.id cmd.accounts = [str(acct.id) for acct in accts] apiclient.removeIAMPolicyFromAccount(cmd) - return + return + + +class SimulatorMock: + + """Manage simulator mock lifecycle""" + + def __init__(self, items): + self.__dict__.update(items) + + @classmethod + def create(cls, apiclient, command, zoneid=None, podid=None, + clusterid=None, hostid=None, value="result:fail", + count=None, jsonresponse=None): + """Creates simulator mock""" + + cmd = configureSimulator.configureSimulatorCmd() + cmd.zoneid = zoneid + cmd.podid = podid + cmd.clusterid = clusterid + cmd.hostid = hostid + cmd.name = command + cmd.value = value + cmd.count = count + cmd.jsonresponse = jsonresponse + try: + simulatormock = apiclient.configureSimulator(cmd) + if simulatormock is not None: + return SimulatorMock(simulatormock.__dict__) + except Exception as e: + raise e + + def delete(self, apiclient): + """Removes simulator mock""" + + cmd = cleanupSimulatorMock.cleanupSimulatorMockCmd() + cmd.id = self.id + return apiclient.cleanupSimulatorMock(cmd) + + def query(self, apiclient): + """Queries simulator mock""" + + cmd = querySimulatorMock.querySimulatorMockCmd() + cmd.id = self.id + try: + simulatormock = apiclient.querySimulatorMock(cmd) + if simulatormock is not None: + return SimulatorMock(simulatormock.__dict__) + except Exception as e: + raise e diff --git a/tools/marvin/marvin/integration/lib/common.py b/tools/marvin/marvin/lib/common.py similarity index 54% rename from tools/marvin/marvin/integration/lib/common.py rename to tools/marvin/marvin/lib/common.py index 3b292bf920..b946b92f1e 100644 --- a/tools/marvin/marvin/integration/lib/common.py +++ b/tools/marvin/marvin/lib/common.py @@ -5,9 +5,9 @@ # 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 @@ -17,7 +17,7 @@ """Common functions """ -#Import Local Modules +# Import Local Modules from marvin.cloudstackAPI import (listConfigurations, listPhysicalNetworks, listRegions, @@ -57,36 +57,36 @@ listNetworkOfferings, listResourceLimits, listVPCOfferings) -from marvin.integration.lib.base import (Configurations, - NetScaler, - Template, - Resources, - PhysicalNetwork, - Host, - PublicIPAddress, - NetworkOffering, - Network) -from marvin.integration.lib.utils import (get_process_status, - xsplit, - validateList) + from marvin.sshClient import SshClient -from marvin.codes import PASS, ISOLATED_NETWORK, VPC_NETWORK, BASIC_ZONE, FAIL +from marvin.codes import (PASS, ISOLATED_NETWORK, VPC_NETWORK, + BASIC_ZONE, FAIL, NAT_RULE, STATIC_NAT_RULE) import random +from marvin.lib.utils import * +from marvin.lib.base import * +from marvin.codes import PASS + -#Import System modules +# Import System modules import time def is_config_suitable(apiclient, name, value): """ - Ensure if the deployment has the expected `value` for the global setting `name' + Ensure if the deployment has the expected + `value` for the global setting `name' @return: true if value is set, else false """ configs = Configurations.list(apiclient, name=name) - assert(configs is not None and isinstance(configs, list) and len(configs) > 0) + assert( + configs is not None and isinstance( + configs, + list) and len( + configs) > 0) return configs[0].value == value + def wait_for_cleanup(apiclient, configs=None): """Sleeps till the cleanup configs passed""" @@ -110,6 +110,7 @@ def wait_for_cleanup(apiclient, configs=None): time.sleep(int(config_desc.value)) return + def add_netscaler(apiclient, zoneid, NSservice): """ Adds Netscaler device and enables NS provider""" @@ -117,11 +118,11 @@ def add_netscaler(apiclient, zoneid, NSservice): cmd.zoneid = zoneid physical_networks = apiclient.listPhysicalNetworks(cmd) if isinstance(physical_networks, list): - physical_network = physical_networks[0] + physical_network = physical_networks[0] cmd = listNetworkServiceProviders.listNetworkServiceProvidersCmd() cmd.name = 'Netscaler' - cmd.physicalnetworkid=physical_network.id + cmd.physicalnetworkid = physical_network.id nw_service_providers = apiclient.listNetworkServiceProviders(cmd) if isinstance(nw_service_providers, list): @@ -133,111 +134,155 @@ def add_netscaler(apiclient, zoneid, NSservice): netscaler_provider = apiclient.addNetworkServiceProvider(cmd1) netscaler = NetScaler.add( - apiclient, - NSservice, - physicalnetworkid=physical_network.id - ) + apiclient, + NSservice, + physicalnetworkid=physical_network.id + ) if netscaler_provider.state != 'Enabled': - cmd = updateNetworkServiceProvider.updateNetworkServiceProviderCmd() - cmd.id = netscaler_provider.id - cmd.state = 'Enabled' - apiclient.updateNetworkServiceProvider(cmd) + cmd = updateNetworkServiceProvider.updateNetworkServiceProviderCmd() + cmd.id = netscaler_provider.id + cmd.state = 'Enabled' + apiclient.updateNetworkServiceProvider(cmd) return netscaler -def get_region(apiclient, services=None): - "Returns a default region" +def get_region(apiclient, region_id=None, region_name=None): + ''' + @name : get_region + @Desc : Returns the Region Information for a given + region id or region name + @Input : region_name: Name of the Region + region_id : Id of the region + @Output : 1. Region Information for the passed inputs else first Region + 2. FAILED In case the cmd failed + ''' cmd = listRegions.listRegionsCmd() - if services: - if "regionid" in services: - cmd.id = services["regionid"] - - regions = apiclient.listRegions(cmd) - - if isinstance(regions, list): - assert len(regions) > 0 - return regions[0] - else: - raise Exception("Failed to find specified region.") - -def get_domain(apiclient, services=None): - "Returns a default domain" - + if region_name is not None: + cmd.name = region_name + if region_id is not None: + cmd.id = region_id + cmd_out = apiclient.listRegions(cmd) + return FAILED if validateList(cmd_out)[0] != PASS else cmd_out[0] + + +def get_domain(apiclient, domain_id=None, domain_name=None): + ''' + @name : get_domain + @Desc : Returns the Domain Information for a given domain id or domain name + @Input : domain id : Id of the Domain + domain_name : Name of the Domain + @Output : 1. Domain Information for the passed inputs else first Domain + 2. FAILED In case the cmd failed + ''' cmd = listDomains.listDomainsCmd() - if services: - if "domainid" in services: - cmd.id = services["domainid"] - - domains = apiclient.listDomains(cmd) - - if isinstance(domains, list): - assert len(domains) > 0 - return domains[0] - else: - raise Exception("Failed to find specified domain.") - - -def get_zone(apiclient, services=None): - "Returns a default zone" + if domain_name is not None: + cmd.name = domain_name + if domain_id is not None: + cmd.id = domain_id + cmd_out = apiclient.listDomains(cmd) + if validateList(cmd_out)[0] != PASS: + return FAILED + return cmd_out[0] + + +def get_zone(apiclient, zone_name=None, zone_id=None): + ''' + @name : get_zone + @Desc :Returns the Zone Information for a given zone id or Zone Name + @Input : zone_name: Name of the Zone + zone_id : Id of the zone + @Output : 1. Zone Information for the passed inputs else first zone + 2. FAILED In case the cmd failed + ''' cmd = listZones.listZonesCmd() - if services: - if "zoneid" in services: - cmd.id = services["zoneid"] - - zones = apiclient.listZones(cmd) - - if isinstance(zones, list): - assert len(zones) > 0, "There are no available zones in the deployment" - return zones[0] - else: - raise Exception("Failed to find specified zone.") - - -def get_pod(apiclient, zoneid, services=None): - "Returns a default pod for specified zone" - + if zone_name is not None: + cmd.name = zone_name + if zone_id is not None: + cmd.id = zone_id + + cmd_out = apiclient.listZones(cmd) + + if validateList(cmd_out)[0] != PASS: + return FAILED + ''' + Check if input zone name and zone id is None, + then return first element of List Zones command + ''' + return cmd_out[0] + + +def get_pod(apiclient, zone_id=None, pod_id=None, pod_name=None): + ''' + @name : get_pod + @Desc : Returns the Pod Information for a given zone id or Zone Name + @Input : zone_id: Id of the Zone + pod_name : Name of the Pod + pod_id : Id of the Pod + @Output : 1. Pod Information for the pod + 2. FAILED In case the cmd failed + ''' cmd = listPods.listPodsCmd() - cmd.zoneid = zoneid - - if services: - if "podid" in services: - cmd.id = services["podid"] - - pods = apiclient.listPods(cmd) - - if isinstance(pods, list): - assert len(pods) > 0, "No pods found for zone %s"%zoneid - return pods[0] - else: - raise Exception("Exception: Failed to find specified pod.") - - -def get_template(apiclient, zoneid, ostype, services=None, - templatefilter='featured', - templatetype='BUILTIN'): - "Returns a featured built in template in given zone" + if pod_name is not None: + cmd.name = pod_name + if pod_id is not None: + cmd.id = pod_id + if zone_id is not None: + cmd.zoneid = zone_id + + cmd_out = apiclient.listPods(cmd) + + if validateList(cmd_out)[0] != PASS: + return FAILED + return cmd_out[0] + + +def get_template( + apiclient, zone_id=None, ostype_desc=None, template_filter="featured", + template_type='BUILTIN', template_id=None, template_name=None, + account=None, domain_id=None, project_id=None, hypervisor=None): + ''' + @Name : get_template + @Desc : Retrieves the template Information based upon inputs provided + Template is retrieved based upon either of the inputs matched + condition + @Input : returns a template" + @Output : FAILED in case of any failure + template Information matching the inputs + ''' cmd = listTemplates.listTemplatesCmd() - cmd.templatefilter = templatefilter - cmd.zoneid = zoneid - - if services: - if "template" in services: - cmd.id = services["template"] - - list_templates = apiclient.listTemplates(cmd) + cmd.templatefilter = template_filter + if domain_id is not None: + cmd.domainid = domain_id + if zone_id is not None: + cmd.zoneid = zone_id + if template_id is not None: + cmd.id = template_id + if template_name is not None: + cmd.name = template_name + if hypervisor is not None: + cmd.hypervisor = hypervisor + if project_id is not None: + cmd.projectid = project_id + if account is not None: + cmd.account = account - if isinstance(list_templates, list): - assert len(list_templates) > 0, "received empty response on featured templates" - for template in list_templates: - if template.isready and template.templatetype == templatetype: - return template + ''' + Get the Templates pertaining to the inputs provided + ''' + list_templatesout = apiclient.listTemplates(cmd) + if validateList(list_templatesout)[0] != PASS: + return FAILED - raise Exception("Exception: Failed to find built in template which is in " - "ready state: %s" % templatetype) - return + for template in list_templatesout: + if template.isready and template.templatetype == template_type: + return template + ''' + Return default first template, if no template matched + ''' + return list_templatesout[0] def download_systemplates_sec_storage(server, services): @@ -246,29 +291,29 @@ def download_systemplates_sec_storage(server, services): try: # Login to management server ssh = SshClient( - server["ipaddress"], - server["port"], - server["username"], - server["password"] - ) + server["ipaddress"], + server["port"], + server["username"], + server["password"] + ) except Exception: - raise Exception("SSH access failted for server with IP address: %s" % - server["ipaddess"]) + raise Exception("SSH access failed for server with IP address: %s" % + server["ipaddess"]) # Mount Secondary Storage on Management Server cmds = [ - "mkdir -p %s" % services["mnt_dir"], - "mount -t nfs %s:/%s %s" % ( - services["sec_storage"], - services["path"], - services["mnt_dir"] - ), - "%s -m %s -u %s -h %s -F" % ( - services["command"], - services["mnt_dir"], - services["download_url"], - services["hypervisor"] - ) - ] + "mkdir -p %s" % services["mnt_dir"], + "mount -t nfs %s:/%s %s" % ( + services["sec_storage"], + services["path"], + services["mnt_dir"] + ), + "%s -m %s -u %s -h %s -F" % ( + services["command"], + services["mnt_dir"], + services["download_url"], + services["hypervisor"] + ) + ] for c in cmds: result = ssh.execute(c) @@ -290,84 +335,86 @@ def wait_for_ssvms(apiclient, zoneid, podid, interval=60): time.sleep(interval) timeout = 40 while True: - list_ssvm_response = list_ssvms( - apiclient, - systemvmtype='secondarystoragevm', - zoneid=zoneid, - podid=podid - ) - ssvm = list_ssvm_response[0] - if ssvm.state != 'Running': - # Sleep to ensure SSVMs are Up and Running - time.sleep(interval) - timeout = timeout - 1 - elif ssvm.state == 'Running': - break - elif timeout == 0: - raise Exception("SSVM failed to come up") - break + list_ssvm_response = list_ssvms( + apiclient, + systemvmtype='secondarystoragevm', + zoneid=zoneid, + podid=podid + ) + ssvm = list_ssvm_response[0] + if ssvm.state != 'Running': + # Sleep to ensure SSVMs are Up and Running + time.sleep(interval) + timeout = timeout - 1 + elif ssvm.state == 'Running': + break + elif timeout == 0: + raise Exception("SSVM failed to come up") + break timeout = 40 while True: - list_ssvm_response = list_ssvms( - apiclient, - systemvmtype='consoleproxy', - zoneid=zoneid, - podid=podid - ) - cpvm = list_ssvm_response[0] - if cpvm.state != 'Running': - # Sleep to ensure SSVMs are Up and Running - time.sleep(interval) - timeout = timeout - 1 - elif cpvm.state == 'Running': - break - elif timeout == 0: - raise Exception("CPVM failed to come up") - break + list_ssvm_response = list_ssvms( + apiclient, + systemvmtype='consoleproxy', + zoneid=zoneid, + podid=podid + ) + cpvm = list_ssvm_response[0] + if cpvm.state != 'Running': + # Sleep to ensure SSVMs are Up and Running + time.sleep(interval) + timeout = timeout - 1 + elif cpvm.state == 'Running': + break + elif timeout == 0: + raise Exception("CPVM failed to come up") + break return + def get_builtin_template_info(apiclient, zoneid): """Returns hypervisor specific infor for templates""" list_template_response = Template.list( - apiclient, - templatefilter='featured', - zoneid=zoneid, - ) + apiclient, + templatefilter='featured', + zoneid=zoneid, + ) for b_template in list_template_response: - if b_template.templatetype == 'BUILTIN': - break + if b_template.templatetype == 'BUILTIN': + break extract_response = Template.extract(apiclient, - b_template.id, - 'HTTP_DOWNLOAD', - zoneid) + b_template.id, + 'HTTP_DOWNLOAD', + zoneid) return extract_response.url, b_template.hypervisor, b_template.format + def download_builtin_templates(apiclient, zoneid, hypervisor, host, - linklocalip, interval=60): + linklocalip, interval=60): """After setup wait till builtin templates are downloaded""" # Change IPTABLES Rules get_process_status( - host["ipaddress"], - host["port"], - host["username"], - host["password"], - linklocalip, - "iptables -P INPUT ACCEPT" - ) + host["ipaddress"], + host["port"], + host["username"], + host["password"], + linklocalip, + "iptables -P INPUT ACCEPT" + ) time.sleep(interval) # Find the BUILTIN Templates for given Zone, Hypervisor list_template_response = list_templates( - apiclient, - hypervisor=hypervisor, - zoneid=zoneid, - templatefilter='self' - ) + apiclient, + hypervisor=hypervisor, + zoneid=zoneid, + templatefilter='self' + ) if not isinstance(list_template_response, list): raise Exception("Failed to download BUILTIN templates") @@ -376,18 +423,18 @@ def download_builtin_templates(apiclient, zoneid, hypervisor, host, templateid = None for template in list_template_response: if template.templatetype == "BUILTIN": - templateid = template.id + templateid = template.id # Sleep to ensure that template is in downloading state after adding # Sec storage time.sleep(interval) while True: template_response = list_templates( - apiclient, - id=templateid, - zoneid=zoneid, - templatefilter='self' - ) + apiclient, + id=templateid, + zoneid=zoneid, + templatefilter='self' + ) template = template_response[0] # If template is ready, # template.status = Download Complete @@ -406,7 +453,7 @@ def download_builtin_templates(apiclient, zoneid, hypervisor, host, def update_resource_limit(apiclient, resourcetype, account=None, - domainid=None, max=None, projectid=None): + domainid=None, max=None, projectid=None): """Updates the resource limit to 'max' for given account""" cmd = updateResourceLimit.updateResourceLimitCmd() @@ -428,6 +475,8 @@ def list_os_types(apiclient, **kwargs): cmd = listOsTypes.listOsTypesCmd() [setattr(cmd, k, v) for k, v in kwargs.items()] + if 'account' in kwargs.keys() and 'domainid' in kwargs.keys(): + cmd.listall=True return(apiclient.listOsTypes(cmd)) @@ -436,6 +485,8 @@ def list_routers(apiclient, **kwargs): cmd = listRouters.listRoutersCmd() [setattr(cmd, k, v) for k, v in kwargs.items()] + if 'account' in kwargs.keys() and 'domainid' in kwargs.keys(): + cmd.listall=True return(apiclient.listRouters(cmd)) @@ -444,6 +495,8 @@ def list_zones(apiclient, **kwargs): cmd = listZones.listZonesCmd() [setattr(cmd, k, v) for k, v in kwargs.items()] + if 'account' in kwargs.keys() and 'domainid' in kwargs.keys(): + cmd.listall=True return(apiclient.listZones(cmd)) @@ -452,6 +505,8 @@ def list_networks(apiclient, **kwargs): cmd = listNetworks.listNetworksCmd() [setattr(cmd, k, v) for k, v in kwargs.items()] + if 'account' in kwargs.keys() and 'domainid' in kwargs.keys(): + cmd.listall=True return(apiclient.listNetworks(cmd)) @@ -460,6 +515,8 @@ def list_clusters(apiclient, **kwargs): cmd = listClusters.listClustersCmd() [setattr(cmd, k, v) for k, v in kwargs.items()] + if 'account' in kwargs.keys() and 'domainid' in kwargs.keys(): + cmd.listall=True return(apiclient.listClusters(cmd)) @@ -468,6 +525,8 @@ def list_ssvms(apiclient, **kwargs): cmd = listSystemVms.listSystemVmsCmd() [setattr(cmd, k, v) for k, v in kwargs.items()] + if 'account' in kwargs.keys() and 'domainid' in kwargs.keys(): + cmd.listall=True return(apiclient.listSystemVms(cmd)) @@ -476,6 +535,8 @@ def list_storage_pools(apiclient, **kwargs): cmd = listStoragePools.listStoragePoolsCmd() [setattr(cmd, k, v) for k, v in kwargs.items()] + if 'account' in kwargs.keys() and 'domainid' in kwargs.keys(): + cmd.listall=True return(apiclient.listStoragePools(cmd)) @@ -484,6 +545,8 @@ def list_virtual_machines(apiclient, **kwargs): cmd = listVirtualMachines.listVirtualMachinesCmd() [setattr(cmd, k, v) for k, v in kwargs.items()] + if 'account' in kwargs.keys() and 'domainid' in kwargs.keys(): + cmd.listall=True return(apiclient.listVirtualMachines(cmd)) @@ -492,6 +555,8 @@ def list_hosts(apiclient, **kwargs): cmd = listHosts.listHostsCmd() [setattr(cmd, k, v) for k, v in kwargs.items()] + if 'account' in kwargs.keys() and 'domainid' in kwargs.keys(): + cmd.listall=True return(apiclient.listHosts(cmd)) @@ -500,6 +565,8 @@ def list_configurations(apiclient, **kwargs): cmd = listConfigurations.listConfigurationsCmd() [setattr(cmd, k, v) for k, v in kwargs.items()] + if 'account' in kwargs.keys() and 'domainid' in kwargs.keys(): + cmd.listall=True return(apiclient.listConfigurations(cmd)) @@ -508,6 +575,8 @@ def list_publicIP(apiclient, **kwargs): cmd = listPublicIpAddresses.listPublicIpAddressesCmd() [setattr(cmd, k, v) for k, v in kwargs.items()] + if 'account' in kwargs.keys() and 'domainid' in kwargs.keys(): + cmd.listall=True return(apiclient.listPublicIpAddresses(cmd)) @@ -516,6 +585,8 @@ def list_nat_rules(apiclient, **kwargs): cmd = listPortForwardingRules.listPortForwardingRulesCmd() [setattr(cmd, k, v) for k, v in kwargs.items()] + if 'account' in kwargs.keys() and 'domainid' in kwargs.keys(): + cmd.listall=True return(apiclient.listPortForwardingRules(cmd)) @@ -524,6 +595,8 @@ def list_lb_rules(apiclient, **kwargs): cmd = listLoadBalancerRules.listLoadBalancerRulesCmd() [setattr(cmd, k, v) for k, v in kwargs.items()] + if 'account' in kwargs.keys() and 'domainid' in kwargs.keys(): + cmd.listall=True return(apiclient.listLoadBalancerRules(cmd)) @@ -532,6 +605,8 @@ def list_lb_instances(apiclient, **kwargs): cmd = listLoadBalancerRuleInstances.listLoadBalancerRuleInstancesCmd() [setattr(cmd, k, v) for k, v in kwargs.items()] + if 'account' in kwargs.keys() and 'domainid' in kwargs.keys(): + cmd.listall=True return(apiclient.listLoadBalancerRuleInstances(cmd)) @@ -540,6 +615,8 @@ def list_firewall_rules(apiclient, **kwargs): cmd = listFirewallRules.listFirewallRulesCmd() [setattr(cmd, k, v) for k, v in kwargs.items()] + if 'account' in kwargs.keys() and 'domainid' in kwargs.keys(): + cmd.listall=True return(apiclient.listFirewallRules(cmd)) @@ -548,6 +625,8 @@ def list_volumes(apiclient, **kwargs): cmd = listVolumes.listVolumesCmd() [setattr(cmd, k, v) for k, v in kwargs.items()] + if 'account' in kwargs.keys() and 'domainid' in kwargs.keys(): + cmd.listall=True return(apiclient.listVolumes(cmd)) @@ -556,6 +635,8 @@ def list_isos(apiclient, **kwargs): cmd = listIsos.listIsosCmd() [setattr(cmd, k, v) for k, v in kwargs.items()] + if 'account' in kwargs.keys() and 'domainid' in kwargs.keys(): + cmd.listall=True return(apiclient.listIsos(cmd)) @@ -564,6 +645,8 @@ def list_snapshots(apiclient, **kwargs): cmd = listSnapshots.listSnapshotsCmd() [setattr(cmd, k, v) for k, v in kwargs.items()] + if 'account' in kwargs.keys() and 'domainid' in kwargs.keys(): + cmd.listall=True return(apiclient.listSnapshots(cmd)) @@ -572,6 +655,8 @@ def list_templates(apiclient, **kwargs): cmd = listTemplates.listTemplatesCmd() [setattr(cmd, k, v) for k, v in kwargs.items()] + if 'account' in kwargs.keys() and 'domainid' in kwargs.keys(): + cmd.listall=True return(apiclient.listTemplates(cmd)) @@ -580,6 +665,8 @@ def list_domains(apiclient, **kwargs): cmd = listDomains.listDomainsCmd() [setattr(cmd, k, v) for k, v in kwargs.items()] + if 'account' in kwargs.keys() and 'domainid' in kwargs.keys(): + cmd.listall=True return(apiclient.listDomains(cmd)) @@ -589,6 +676,8 @@ def list_accounts(apiclient, **kwargs): cmd = listAccounts.listAccountsCmd() [setattr(cmd, k, v) for k, v in kwargs.items()] + if 'account' in kwargs.keys() and 'domainid' in kwargs.keys(): + cmd.listall=True return(apiclient.listAccounts(cmd)) @@ -598,6 +687,8 @@ def list_users(apiclient, **kwargs): cmd = listUsers.listUsersCmd() [setattr(cmd, k, v) for k, v in kwargs.items()] + if 'account' in kwargs.keys() and 'domainid' in kwargs.keys(): + cmd.listall=True return(apiclient.listUsers(cmd)) @@ -606,6 +697,8 @@ def list_snapshot_policy(apiclient, **kwargs): cmd = listSnapshotPolicies.listSnapshotPoliciesCmd() [setattr(cmd, k, v) for k, v in kwargs.items()] + if 'account' in kwargs.keys() and 'domainid' in kwargs.keys(): + cmd.listall=True return(apiclient.listSnapshotPolicies(cmd)) @@ -614,6 +707,8 @@ def list_events(apiclient, **kwargs): cmd = listEvents.listEventsCmd() [setattr(cmd, k, v) for k, v in kwargs.items()] + if 'account' in kwargs.keys() and 'domainid' in kwargs.keys(): + cmd.listall=True return(apiclient.listEvents(cmd)) @@ -622,6 +717,8 @@ def list_disk_offering(apiclient, **kwargs): cmd = listDiskOfferings.listDiskOfferingsCmd() [setattr(cmd, k, v) for k, v in kwargs.items()] + if 'account' in kwargs.keys() and 'domainid' in kwargs.keys(): + cmd.listall=True return(apiclient.listDiskOfferings(cmd)) @@ -630,6 +727,8 @@ def list_service_offering(apiclient, **kwargs): cmd = listServiceOfferings.listServiceOfferingsCmd() [setattr(cmd, k, v) for k, v in kwargs.items()] + if 'account' in kwargs.keys() and 'domainid' in kwargs.keys(): + cmd.listall=True return(apiclient.listServiceOfferings(cmd)) @@ -638,6 +737,8 @@ def list_vlan_ipranges(apiclient, **kwargs): cmd = listVlanIpRanges.listVlanIpRangesCmd() [setattr(cmd, k, v) for k, v in kwargs.items()] + if 'account' in kwargs.keys() and 'domainid' in kwargs.keys(): + cmd.listall=True return(apiclient.listVlanIpRanges(cmd)) @@ -646,6 +747,8 @@ def list_usage_records(apiclient, **kwargs): cmd = listUsageRecords.listUsageRecordsCmd() [setattr(cmd, k, v) for k, v in kwargs.items()] + if 'account' in kwargs.keys() and 'domainid' in kwargs.keys(): + cmd.listall=True return(apiclient.listUsageRecords(cmd)) @@ -654,6 +757,8 @@ def list_nw_service_prividers(apiclient, **kwargs): cmd = listNetworkServiceProviders.listNetworkServiceProvidersCmd() [setattr(cmd, k, v) for k, v in kwargs.items()] + if 'account' in kwargs.keys() and 'domainid' in kwargs.keys(): + cmd.listall=True return(apiclient.listNetworkServiceProviders(cmd)) @@ -662,6 +767,8 @@ def list_virtual_router_elements(apiclient, **kwargs): cmd = listVirtualRouterElements.listVirtualRouterElementsCmd() [setattr(cmd, k, v) for k, v in kwargs.items()] + if 'account' in kwargs.keys() and 'domainid' in kwargs.keys(): + cmd.listall=True return(apiclient.listVirtualRouterElements(cmd)) @@ -670,6 +777,8 @@ def list_network_offerings(apiclient, **kwargs): cmd = listNetworkOfferings.listNetworkOfferingsCmd() [setattr(cmd, k, v) for k, v in kwargs.items()] + if 'account' in kwargs.keys() and 'domainid' in kwargs.keys(): + cmd.listall=True return(apiclient.listNetworkOfferings(cmd)) @@ -678,138 +787,119 @@ def list_resource_limits(apiclient, **kwargs): cmd = listResourceLimits.listResourceLimitsCmd() [setattr(cmd, k, v) for k, v in kwargs.items()] + if 'account' in kwargs.keys() and 'domainid' in kwargs.keys(): + cmd.listall=True return(apiclient.listResourceLimits(cmd)) + def list_vpc_offerings(apiclient, **kwargs): """ Lists VPC offerings """ cmd = listVPCOfferings.listVPCOfferingsCmd() [setattr(cmd, k, v) for k, v in kwargs.items()] + if 'account' in kwargs.keys() and 'domainid' in kwargs.keys(): + cmd.listall=True return(apiclient.listVPCOfferings(cmd)) + def update_resource_count(apiclient, domainid, accountid=None, projectid=None, rtype=None): - """updates the resource count - 0 - VM - 1 - Public IP - 2 - Volume - 3 - Snapshot - 4 - Template - 5 - Projects - 6 - Network - 7 - VPC - 8 - CPUs - 9 - RAM - 10 - Primary (shared) storage (Volumes) - 11 - Secondary storage (Snapshots, Templates & ISOs) - """ - - Resources.updateCount(apiclient, - domainid=domainid, - account=accountid if accountid else None, - projectid=projectid if projectid else None, - resourcetype=rtype if rtype else None - ) - return + """updates the resource count + 0 - VM + 1 - Public IP + 2 - Volume + 3 - Snapshot + 4 - Template + 5 - Projects + 6 - Network + 7 - VPC + 8 - CPUs + 9 - RAM + 10 - Primary (shared) storage (Volumes) + 11 - Secondary storage (Snapshots, Templates & ISOs) + """ + + Resources.updateCount(apiclient, + domainid=domainid, + account=accountid if accountid else None, + projectid=projectid if projectid else None, + resourcetype=rtype if rtype else None + ) + return + def findSuitableHostForMigration(apiclient, vmid): """Returns a suitable host for VM migration""" suitableHost = None try: hosts = Host.listForMigration(apiclient, virtualmachineid=vmid, - ) + ) except Exception as e: - raise Exception("Exception while getting hosts list suitable for migration: %s" % e) + raise Exception( + "Exception while getting hosts list suitable for migration: %s" % + e) suitablehosts = [] if isinstance(hosts, list) and len(hosts) > 0: - suitablehosts = [host for host in hosts if (str(host.resourcestate).lower() == "enabled"\ - and str(host.state).lower() == "up")] - if len(suitablehosts)>0: + suitablehosts = [host for host in hosts + if (str(host.resourcestate).lower() == "enabled" + and str(host.state).lower() == "up")] + if len(suitablehosts) > 0: suitableHost = suitablehosts[0] return suitableHost -def get_resource_type(resource_id): - """Returns resource type""" - - lookup = { 0: "VM", - 1: "Public IP", - 2: "Volume", - 3: "Snapshot", - 4: "Template", - 5: "Projects", - 6: "Network", - 7: "VPC", - 8: "CPUs", - 9: "RAM", - 10: "Primary (shared) storage (Volumes)", - 11: "Secondary storage (Snapshots, Templates & ISOs)" - } - - return lookup[resource_id] - -def get_portable_ip_range_services(config): - """ Reads config values related to portable ip and fills up - services accordingly""" - - services = {} - attributeError = False - - if config.portableIpRange.startip: - services["startip"] = config.portableIpRange.startip - else: - attributeError = True - - if config.portableIpRange.endip: - services["endip"] = config.portableIpRange.endip - else: - attributeError = True - - if config.portableIpRange.netmask: - services["netmask"] = config.portableIpRange.netmask - else: - attributeError = True - if config.portableIpRange.gateway: - services["gateway"] = config.portableIpRange.gateway - else: - attributeError = True +def get_resource_type(resource_id): + """Returns resource type""" - if config.portableIpRange.vlan: - services["vlan"] = config.portableIpRange.vlan + lookup = {0: "VM", + 1: "Public IP", + 2: "Volume", + 3: "Snapshot", + 4: "Template", + 5: "Projects", + 6: "Network", + 7: "VPC", + 8: "CPUs", + 9: "RAM", + 10: "Primary (shared) storage (Volumes)", + 11: "Secondary storage (Snapshots, Templates & ISOs)" + } - if attributeError: - services = None + return lookup[resource_id] - return services def get_free_vlan(apiclient, zoneid): """ - Find an unallocated VLAN outside the range allocated to the physical network. + Find an unallocated VLAN outside the range + allocated to the physical network. @note: This does not guarantee that the VLAN is available for use in the deployment's network gear @return: physical_network, shared_vlan_tag """ list_physical_networks_response = PhysicalNetwork.list( - apiclient, - zoneid=zoneid - ) + apiclient, + zoneid=zoneid + ) assert isinstance(list_physical_networks_response, list) - assert len(list_physical_networks_response) > 0, "No physical networks found in zone %s" % zoneid + assert len( + list_physical_networks_response) > 0,\ + "No physical networks found in zone %s" % zoneid physical_network = list_physical_networks_response[0] - networks = list_networks(apiclient, zoneid= zoneid, type='Shared') + networks = list_networks(apiclient, zoneid=zoneid, type='Shared') usedVlanIds = [] if isinstance(networks, list) and len(networks) > 0: - usedVlanIds = [int(nw.vlan) for nw in networks if nw.vlan!="untagged"] + usedVlanIds = [int(nw.vlan) + for nw in networks if nw.vlan != "untagged"] if hasattr(physical_network, "vlan") is False: while True: - shared_ntwk_vlan = random.randrange(1,4095) + shared_ntwk_vlan = random.randrange(1, 4095) if shared_ntwk_vlan in usedVlanIds: continue else: @@ -818,9 +908,12 @@ def get_free_vlan(apiclient, zoneid): vlans = xsplit(physical_network.vlan, ['-', ',']) assert len(vlans) > 0 - assert int(vlans[0]) < int(vlans[-1]), "VLAN range %s was improperly split" % physical_network.vlan + assert int(vlans[0]) < int( + vlans[-1]), "VLAN range %s was improperly split"\ + % physical_network.vlan - retriesCount = 20 #Assuming random function will give different integer each time + # Assuming random function will give different integer each time + retriesCount = 20 shared_ntwk_vlan = None @@ -842,9 +935,11 @@ def get_free_vlan(apiclient, zoneid): return physical_network, shared_ntwk_vlan + def setNonContiguousVlanIds(apiclient, zoneid): """ - Form the non contiguous ranges based on currently assigned range in physical network + Form the non contiguous ranges based on currently + assigned range in physical network """ NonContigVlanIdsAcquired = False @@ -854,53 +949,72 @@ def setNonContiguousVlanIds(apiclient, zoneid): zoneid=zoneid ) assert isinstance(list_physical_networks_response, list) - assert len(list_physical_networks_response) > 0, "No physical networks found in zone %s" % zoneid + assert len( + list_physical_networks_response) > 0, \ + "No physical networks found in zone %s" % zoneid for physical_network in list_physical_networks_response: vlans = xsplit(physical_network.vlan, ['-', ',']) assert len(vlans) > 0 - assert int(vlans[0]) < int(vlans[-1]), "VLAN range %s was improperly split" % physical_network.vlan + assert int(vlans[0]) < int( + vlans[-1]), "VLAN range %s was improperly split"\ + % physical_network.vlan - # Keep some gap between existing vlan and the new vlans which we are going to add + # Keep some gap between existing vlan and the new vlans + # which we are going to add # So that they are non contiguous non_contig_end_vlan_id = int(vlans[-1]) + 6 non_contig_start_vlan_id = int(vlans[0]) - 6 - # Form ranges which are consecutive to existing ranges but not immediately contiguous - # There should be gap in between existing range and new non contiguous ranage - - # If you can't add range after existing range, because it's crossing 4095, then - # select VLAN ids before the existing range such that they are greater than 0, and + # Form ranges which are consecutive to existing ranges but + # not immediately contiguous + # There should be gap in between existing range + # and new non contiguous range + # If you can't add range after existing range, + # because it's crossing 4095, then select VLAN ids before + # the existing range such that they are greater than 0, and # then add this non contiguoud range - vlan = { "partial_range": ["",""], "full_range": ""} + vlan = {"partial_range": ["", ""], "full_range": ""} if non_contig_end_vlan_id < 4095: - vlan["partial_range"][0] = str(non_contig_end_vlan_id - 4) + '-' + str(non_contig_end_vlan_id - 3) - vlan["partial_range"][1] = str(non_contig_end_vlan_id - 1) + '-' + str(non_contig_end_vlan_id) - vlan["full_range"] = str(non_contig_end_vlan_id - 4) + '-' + str(non_contig_end_vlan_id) + vlan["partial_range"][0] = str( + non_contig_end_vlan_id - 4) + '-' + str(non_contig_end_vlan_id + - 3) + vlan["partial_range"][1] = str( + non_contig_end_vlan_id - 1) + '-' + str(non_contig_end_vlan_id) + vlan["full_range"] = str( + non_contig_end_vlan_id - 4) + '-' + str(non_contig_end_vlan_id) NonContigVlanIdsAcquired = True elif non_contig_start_vlan_id > 0: - vlan["partial_range"][0] = str(non_contig_start_vlan_id) + '-' + str(non_contig_start_vlan_id + 1) - vlan["partial_range"][1] = str(non_contig_start_vlan_id + 3) + '-' + str(non_contig_start_vlan_id + 4) - vlan["full_range"] = str(non_contig_start_vlan_id) + '-' + str(non_contig_start_vlan_id + 4) + vlan["partial_range"][0] = \ + str(non_contig_start_vlan_id) \ + + '-' + str(non_contig_start_vlan_id + 1) + vlan["partial_range"][1] = \ + str(non_contig_start_vlan_id + 3) \ + + '-' + str(non_contig_start_vlan_id + 4) + vlan["full_range"] = \ + str(non_contig_start_vlan_id) \ + + '-' + str(non_contig_start_vlan_id + 4) NonContigVlanIdsAcquired = True else: NonContigVlanIdsAcquired = False # If failed to get relevant vlan ids, continue to next physical network - # else break from loop as we have hot the non contiguous vlan ids for the test purpose + # else break from loop as we have hot the non contiguous vlan ids for + # the test purpose if not NonContigVlanIdsAcquired: continue else: break - # If even through looping from all existing physical networks, failed to get relevant non + # If even through looping from all existing physical networks, + # failed to get relevant non # contiguous vlan ids, then fail the test case if not NonContigVlanIdsAcquired: @@ -908,83 +1022,116 @@ def setNonContiguousVlanIds(apiclient, zoneid): return physical_network, vlan + def is_public_ip_in_correct_state(apiclient, ipaddressid, state): """ Check if the given IP is in the correct state (given) and return True/False accordingly""" retriesCount = 10 while True: portableips = PublicIPAddress.list(apiclient, id=ipaddressid) - assert validateList(portableips)[0] == PASS, "IPs list validation failed" + assert validateList( + portableips)[0] == PASS, "IPs list validation failed" if str(portableips[0].state).lower() == state: break elif retriesCount == 0: - return False + return False else: retriesCount -= 1 time.sleep(60) continue return True + def setSharedNetworkParams(networkServices, range=20): - """Fill up the services dictionary for shared network using random subnet""" + """Fill up the services dictionary for shared network + using random subnet + """ - # @range: range decides the endip. Pass the range as "x" if you want the difference between the startip + # @range: range decides the endip. Pass the range as "x" + # if you want the difference between the startip # and endip as "x" # Set the subnet number of shared networks randomly prior to execution # of each test case to avoid overlapping of ip addresses - shared_network_subnet_number = random.randrange(1,254) - - networkServices["gateway"] = "172.16."+str(shared_network_subnet_number)+".1" - networkServices["startip"] = "172.16."+str(shared_network_subnet_number)+".2" - networkServices["endip"] = "172.16."+str(shared_network_subnet_number)+"."+str(range+1) + shared_network_subnet_number = random.randrange(1, 254) + + networkServices["gateway"] = "172.16." + \ + str(shared_network_subnet_number) + ".1" + networkServices["startip"] = "172.16." + \ + str(shared_network_subnet_number) + ".2" + networkServices["endip"] = "172.16." + \ + str(shared_network_subnet_number) + "." + str(range + 1) networkServices["netmask"] = "255.255.255.0" return networkServices + def createEnabledNetworkOffering(apiclient, networkServices): """Create and enable network offering according to the type @output: List, containing [ Result,Network Offering,Reason ] - Ist Argument('Result') : FAIL : If exception or assertion error occurs + Ist Argument('Result') : FAIL : If exception or assertion + error occurs PASS : If network offering is created and enabled successfully IInd Argument(Net Off) : Enabled network offering In case of exception or - assertion error, it will be None + assertion error, it will be + None IIIrd Argument(Reason) : Reason for failure, default to None """ try: resultSet = [FAIL, None, None] # Create network offering - network_offering = NetworkOffering.create(apiclient, networkServices, conservemode=False) + network_offering = NetworkOffering.create( + apiclient, + networkServices, + conservemode=False) # Update network offering state from disabled to enabled. - NetworkOffering.update(network_offering, apiclient, id=network_offering.id, + NetworkOffering.update(network_offering, + apiclient, id=network_offering.id, state="enabled") except Exception as e: resultSet[2] = e return resultSet return [PASS, network_offering, None] + def shouldTestBeSkipped(networkType, zoneType): """Decide which test to skip, according to type of network and zone type""" - # If network type is isolated or vpc and zone type is basic, then test should be skipped + # If network type is isolated or vpc and zone type is basic, then test + # should be skipped skipIt = False - if ((networkType.lower() == str(ISOLATED_NETWORK).lower() or networkType.lower() == str(VPC_NETWORK).lower()) - and (zoneType.lower() == BASIC_ZONE)): + if (networkType.lower() == str(ISOLATED_NETWORK).lower() or + networkType.lower() == str(VPC_NETWORK).lower()) and\ + (zoneType.lower() == BASIC_ZONE): skipIt = True return skipIt + def verifyNetworkState(apiclient, networkid, state): """List networks and check if the network state matches the given state""" + retriesCount = 10 + isNetworkInDesiredState = False + exceptionOccured = False + exceptionMessage = "" try: - networks = Network.list(apiclient, id=networkid) + while retriesCount >= 0: + networks = Network.list(apiclient, id=networkid) + assert validateList( + networks)[0] == PASS, "Networks list validation failed" + if str(networks[0].state).lower() == state: + isNetworkInDesiredState = True + break + retriesCount -= 1 + time.sleep(60) except Exception as e: - raise Exception("Failed while fetching network list with error: %s" % e) - assert validateList(networks)[0] == PASS, "Networks list validation failed, list is %s" % networks - assert str(networks[0].state).lower() == state, "network state should be %s, it is %s" % (state, networks[0].state) - return + exceptionOccured = True + exceptionMessage = e + return [exceptionOccured, isNetworkInDesiredState, exceptionMessage] + return [exceptionOccured, isNetworkInDesiredState, exceptionMessage] + def verifyComputeOfferingCreation(apiclient, computeofferingid): """List Compute offerings by ID and verify that the offering exists""" @@ -994,8 +1141,42 @@ def verifyComputeOfferingCreation(apiclient, computeofferingid): serviceOfferings = None try: serviceOfferings = apiclient.listServiceOfferings(cmd) - except Exception as e: - return FAIL + except Exception: + return FAIL if not (isinstance(serviceOfferings, list) and len(serviceOfferings) > 0): - return FAIL + return FAIL return PASS + + +def createNetworkRulesForVM(apiclient, virtualmachine, ruletype, + account, networkruledata): + """Acquire IP, create Firewall and NAT/StaticNAT rule + (associating it with given vm) for that IP""" + + try: + public_ip = PublicIPAddress.create( + apiclient, accountid=account.name, + zoneid=virtualmachine.zoneid, domainid=account.domainid, + networkid=virtualmachine.nic[0].networkid) + + FireWallRule.create( + apiclient, ipaddressid=public_ip.ipaddress.id, + protocol='TCP', cidrlist=[networkruledata["fwrule"]["cidr"]], + startport=networkruledata["fwrule"]["startport"], + endport=networkruledata["fwrule"]["endport"] + ) + + if ruletype == NAT_RULE: + # Create NAT rule + NATRule.create(apiclient, virtualmachine, + networkruledata[ + "natrule"], ipaddressid=public_ip.ipaddress.id, + networkid=virtualmachine.nic[0].networkid) + elif ruletype == STATIC_NAT_RULE: + # Enable Static NAT for VM + StaticNATRule.enable(apiclient, public_ip.ipaddress.id, + virtualmachine.id, + networkid=virtualmachine.nic[0].networkid) + except Exception as e: + [FAIL, e] + return [PASS, public_ip] diff --git a/tools/marvin/marvin/integration/lib/utils.py b/tools/marvin/marvin/lib/utils.py similarity index 63% rename from tools/marvin/marvin/integration/lib/utils.py rename to tools/marvin/marvin/lib/utils.py index 709fddebe7..4194e32da3 100644 --- a/tools/marvin/marvin/integration/lib/utils.py +++ b/tools/marvin/marvin/lib/utils.py @@ -28,13 +28,19 @@ import socket import urlparse import datetime -from marvin.cloudstackAPI import cloudstackAPIClient, listHosts +from marvin.cloudstackAPI import cloudstackAPIClient, listHosts, listRouters +from platform import system +from marvin.cloudstackException import GetDetailExceptionInfo from marvin.sshClient import SshClient -from marvin.codes import (FAIL, - PASS, - MATCH_NOT_FOUND, - INVALID_INPUT, - EMPTY_LIST) +from marvin.codes import ( + SUCCESS, + FAIL, + PASS, + MATCH_NOT_FOUND, + INVALID_INPUT, + EMPTY_LIST, + FAILED) + def restart_mgmt_server(server): """Restarts the management server""" @@ -116,7 +122,9 @@ def cleanup_resources(api_client, resources): obj.delete(api_client) -def is_server_ssh_ready(ipaddress, port, username, password, retries=20, retryinterv=30, timeout=10.0, keyPairFileLocation=None): +def is_server_ssh_ready(ipaddress, port, username, password, + retries=20, retryinterv=30, + timeout=10.0, keyPairFileLocation=None): ''' @Name: is_server_ssh_ready @Input: timeout: tcp connection timeout flag, @@ -136,8 +144,10 @@ def is_server_ssh_ready(ipaddress, port, username, password, retries=20, retryin retries=retries, delay=retryinterv, timeout=timeout) - except Exception, e: - raise Exception("SSH connection has Failed. Waited %ss. Error is %s" % (retries * retryinterv, str(e))) + except Exception as e: + raise Exception( + "SSH connection has Failed. Waited %ss. Error is %s" % + (retries * retryinterv, str(e))) else: return ssh @@ -166,6 +176,7 @@ def fetch_api_client(config_file='datacenterCfg'): ) ) + def get_host_credentials(config, hostip): """Get login information for a host `hostip` (ipv4) from marvin's `config` @@ -181,26 +192,35 @@ def get_host_credentials(config, hostip): try: if socket.getfqdn(hostip) == socket.getfqdn(hostname): return host.username, host.password - except socket.error, e: - raise Exception("Unresolvable host %s error is %s" % (hostip, e)) - raise KeyError("Please provide the marvin configuration file with credentials to your hosts") - - -def get_process_status(hostip, port, username, password, linklocalip, process, hypervisor=None): + except socket.error as e: + raise Exception( + "Unresolvable host %s error is %s" % + (hostip, e)) + raise KeyError( + "Please provide the marvin configuration file " + "with credentials to your hosts") + + +def get_process_status( + hostip, port, username, password, + linklocalip, process, hypervisor=None): """Double hop and returns a process status""" - #SSH to the machine + # SSH to the machine ssh = SshClient(hostip, port, username, password) if (str(hypervisor).lower() == 'vmware' - or str(hypervisor).lower() == 'hyperv'): - ssh_command = "ssh -i /var/cloudstack/management/.ssh/id_rsa -ostricthostkeychecking=no " + or str(hypervisor).lower() == 'hyperv'): + ssh_command =\ + "ssh -i /var/cloudstack/management/" \ + ".ssh/id_rsa -ostricthostkeychecking=no " else: - ssh_command = "ssh -i ~/.ssh/id_rsa.cloud -ostricthostkeychecking=no " + ssh_command = "ssh -i ~/.ssh/id_rsa.cloud " \ + "-ostricthostkeychecking=no " ssh_command = ssh_command +\ - "-oUserKnownHostsFile=/dev/null -p 3922 %s %s" % ( - linklocalip, - process) + "-oUserKnownHostsFile=/dev/null -p 3922 %s %s" % ( + linklocalip, + process) # Double hop into router timeout = 5 @@ -237,12 +257,13 @@ def xsplit(txt, seps): @return: list of split units """ default_sep = seps[0] - for sep in seps[1:]: # we skip seps[0] because that's the default separator + # we skip seps[0] because that's the default separator + for sep in seps[1:]: txt = txt.replace(sep, default_sep) return [i.strip() for i in txt.split(default_sep)] -def get_hypervisor_type(apiclient): +def get_hypervisor_type(apiclient): """Return the hypervisor type of the hosts in setup""" cmd = listHosts.listHostsCmd() @@ -250,61 +271,79 @@ def get_hypervisor_type(apiclient): cmd.listall = True hosts = apiclient.listHosts(cmd) hosts_list_validation_result = validateList(hosts) - assert hosts_list_validation_result[0] == PASS, "host list validation failed" + assert hosts_list_validation_result[ + 0] == PASS, "host list validation failed" return hosts_list_validation_result[1].hypervisor + def is_snapshot_on_nfs(apiclient, dbconn, config, zoneid, snapshotid): """ - Checks whether a snapshot with id (not UUID) `snapshotid` is present on the nfs storage + Checks whether a snapshot with id + (not UUID) `snapshotid` is present on the nfs storage @param apiclient: api client connection @param @dbconn: connection to the cloudstack db @param config: marvin configuration file - @param zoneid: uuid of the zone on which the secondary nfs storage pool is mounted + @param zoneid: uuid of the zone on which the + secondary nfs storage pool is mounted @param snapshotid: uuid of the snapshot @return: True if snapshot is found, False otherwise """ # snapshot extension to be appended to the snapshot path obtained from db snapshot_extensions = {"vmware": ".ovf", - "kvm": "", - "xenserver": ".vhd"} + "kvm": "", + "xenserver": ".vhd", + "simulator": ""} qresultset = dbconn.execute( - "select id from snapshots where uuid = '%s';" \ - % str(snapshotid) - ) + "select id from snapshots where uuid = '%s';" + % str(snapshotid) + ) if len(qresultset) == 0: raise Exception( "No snapshot found in cloudstack with id %s" % snapshotid) - snapshotid = qresultset[0][0] qresultset = dbconn.execute( - "select install_path,store_id from snapshot_store_ref where snapshot_id='%s' and store_role='Image';" % snapshotid + "select install_path,store_id from snapshot_store_ref" + " where snapshot_id='%s' and " + "store_role='Image';" % snapshotid ) - assert isinstance(qresultset, list), "Invalid db query response for snapshot %s" % snapshotid + assert isinstance( + qresultset, list), "Invalid db query " \ + "response for snapshot " \ + "%s" % snapshotid if len(qresultset) == 0: - #Snapshot does not exist + # Snapshot does not exist return False from base import ImageStore - #pass store_id to get the exact storage pool where snapshot is stored - secondaryStores = ImageStore.list(apiclient, zoneid=zoneid, id=int(qresultset[0][1])) - - assert isinstance(secondaryStores, list), "Not a valid response for listImageStores" - assert len(secondaryStores) != 0, "No image stores found in zone %s" % zoneid + # pass store_id to get the exact storage pool where snapshot is stored + secondaryStores = ImageStore.list( + apiclient, + zoneid=zoneid, + id=int( + qresultset[0][1])) + + assert isinstance( + secondaryStores, list), "Not a valid response for listImageStores" + assert len( + secondaryStores) != 0, "No image stores found in zone %s" % zoneid secondaryStore = secondaryStores[0] if str(secondaryStore.providername).lower() != "nfs": raise Exception( - "is_snapshot_on_nfs works only against nfs secondary storage. found %s" % str(secondaryStore.providername)) + "is_snapshot_on_nfs works only " + "against nfs secondary storage." + " found %s" % str(secondaryStore.providername)) hypervisor = get_hypervisor_type(apiclient) # append snapshot extension based on hypervisor, to the snapshot path - snapshotPath = str(qresultset[0][0]) + snapshot_extensions[str(hypervisor).lower()] + snapshotPath = str(qresultset[0][0]) + \ + snapshot_extensions[str(hypervisor).lower()] nfsurl = secondaryStore.url from urllib2 import urlparse @@ -312,8 +351,11 @@ def is_snapshot_on_nfs(apiclient, dbconn, config, zoneid, snapshotid): host, path = parse_url.netloc, parse_url.path if not config.mgtSvr: - raise Exception("Your marvin configuration does not contain mgmt server credentials") - mgtSvr, user, passwd = config.mgtSvr[0].mgtSvrIp, config.mgtSvr[0].user, config.mgtSvr[0].passwd + raise Exception( + "Your marvin configuration does " + "not contain mgmt server credentials") + mgtSvr, user, passwd = config.mgtSvr[ + 0].mgtSvrIp, config.mgtSvr[0].user, config.mgtSvr[0].passwd try: ssh_client = SshClient( @@ -323,32 +365,33 @@ def is_snapshot_on_nfs(apiclient, dbconn, config, zoneid, snapshotid): passwd ) cmds = [ - "mkdir -p %s /mnt/tmp", - "mount -t %s %s%s /mnt/tmp" % ( - 'nfs', - host, - path, - ), - "test -f %s && echo 'snapshot exists'" % ( - os.path.join("/mnt/tmp", snapshotPath) - ), - ] + "mkdir -p %s /mnt/tmp", + "mount -t %s %s:%s /mnt/tmp" % ( + 'nfs', + host, + path, + ), + "test -f %s && echo 'snapshot exists'" % ( + os.path.join("/mnt/tmp", snapshotPath) + ), + ] for c in cmds: result = ssh_client.execute(c) # Unmount the Sec Storage cmds = [ - "cd", - "umount /mnt/tmp", - ] + "cd", + "umount /mnt/tmp", + ] for c in cmds: ssh_client.execute(c) except Exception as e: raise Exception("SSH failed for management server: %s - %s" % - (config.mgtSvr[0].mgtSvrIp, e)) + (config.mgtSvr[0].mgtSvrIp, e)) return 'snapshot exists' in result + def validateList(inp): """ @name: validateList @@ -382,7 +425,8 @@ def validateList(inp): return ret return [PASS, inp[0], None] -def verifyElementInList(inp, toverify, responsevar=None, pos=0): + +def verifyElementInList(inp, toverify, responsevar=None, pos=0): ''' @name: verifyElementInList @Description: @@ -394,9 +438,9 @@ def verifyElementInList(inp, toverify, responsevar=None, pos=0): at a given pos @Input: I : Input to be verified whether its a list or not - II : Element to verify whether it exists in the list - III : variable name in response object to verify - default to None, if None, we will verify for the complete + II : Element to verify whether it exists in the list + III : variable name in response object to verify + default to None, if None, we will verify for the complete first element EX: state of response object object IV : Position in the list at which the input element to verify default to 0 @@ -419,13 +463,78 @@ def verifyElementInList(inp, toverify, responsevar=None, pos=0): return [FAIL, out[2]] if len(inp) > pos: if responsevar is None: - if inp[pos] == toverify: - return [PASS, None] + if inp[pos] == toverify: + return [PASS, None] else: - if responsevar in inp[pos].__dict__ and getattr(inp[pos], responsevar) == toverify: - return [PASS, None] - else: - return [FAIL, MATCH_NOT_FOUND] + if responsevar in inp[pos].\ + __dict__ and getattr(inp[pos], responsevar) == toverify: + return [PASS, None] + else: + return [FAIL, MATCH_NOT_FOUND] else: return [FAIL, MATCH_NOT_FOUND] + +def checkVolumeSize(ssh_handle=None, + volume_name="/dev/sda", + cmd_inp="/sbin/fdisk -l | grep Disk", + size_to_verify=0): + ''' + @Name : getDiskUsage + @Desc : provides facility to verify the + volume size against the size to verify + @Input: 1. ssh_handle : machine against which to execute the disk size cmd + 2. volume_name : The name of the volume + against which to verify the size + 3. cmd_inp : Input command used to veify the size + 4. size_to_verify: size against which to compare. + @Output: Returns FAILED in case of an issue, else SUCCESS + ''' + try: + if ssh_handle is None or cmd_inp is None or volume_name is None: + return INVALID_INPUT + + cmd = cmd_inp + ''' + Retrieve the cmd output + ''' + if system().lower() != "windows": + fdisk_output = ssh_handle.runCommand(cmd_inp) + if fdisk_output["status"] != SUCCESS: + return FAILED + temp_out = fdisk_output["stdout"] + for line in temp_out.split("\n"): + if volume_name in line: + parts = line.split() + if str(parts[-2]) == str(size_to_verify): + return [SUCCESS, str(parts[-2])] + return [FAILED, "Volume Not Found"] + except Exception as e: + print "\n Exception Occurred under getDiskUsage: " \ + "%s" % GetDetailExceptionInfo(e) + return [FAILED, GetDetailExceptionInfo(e)] + + +def verifyRouterState(apiclient, routerid, allowedstates): + """List the router and verify that its state is in allowed states + @output: List, containing [Result, Reason] + Ist Argument ('Result'): FAIL: If router state is not + in allowed states + PASS: If router state is in + allowed states""" + + try: + cmd = listRouters.listRoutersCmd() + cmd.id = routerid + cmd.listall = True + routers = apiclient.listRouters(cmd) + except Exception as e: + return [FAIL, e] + listvalidationresult = validateList(routers) + if listvalidationresult[0] == FAIL: + return [FAIL, listvalidationresult[2]] + if routers[0].redundantstate not in allowedstates: + return [FAIL, "Redundant state of the" + " router should be in %s but is %s" % + (allowedstates, routers[0].redundantstate)] + return [PASS, None] diff --git a/tools/marvin/marvin/marvinInit.py b/tools/marvin/marvin/marvinInit.py index f722058a9f..ce9b43f1ad 100644 --- a/tools/marvin/marvin/marvinInit.py +++ b/tools/marvin/marvin/marvinInit.py @@ -15,56 +15,67 @@ # specific language governing permissions and limitations # under the License. ''' -@Desc: Initializes the marvin and does required prerequisites +Initializes the marvin and does required prerequisites for starting it. -1. Parses the configuration file passed to marvin and creates a - parsed config + 1. Parses the configuration file passed to marvin and creates a + parsed config. 2. Initializes the logging required for marvin.All logs are now made available under a single timestamped folder. - 3. Deploys the Data Center based upon input + 3. Deploys the Data Center based upon input. ''' - -from marvin import configGenerator -from marvin import cloudstackException +from marvin.configGenerator import getSetupConfig from marvin.marvinLog import MarvinLog -from marvin.deployDataCenter import deployDataCenters +from marvin.deployDataCenter import DeployDataCenters +from marvin.cloudstackTestClient import CSTestClient +from marvin.cloudstackException import GetDetailExceptionInfo from marvin.codes import( - YES, - NO, + XEN_SERVER, SUCCESS, FAILED - ) -import sys -import time +) import os -import logging -import string -import random class MarvinInit: - def __init__(self, config_file, load_flag, log_folder_path=None): + + def __init__(self, config_file, + deploy_dc_flag=None, + test_mod_name="deploydc", + zone=None, + hypervisor_type=None, + user_logfolder_path=None): self.__configFile = config_file - self.__loadFlag = load_flag - self.__parsedConfig = None - self.__logFolderPath = log_folder_path + self.__deployFlag = deploy_dc_flag + self.__logFolderPath = None self.__tcRunLogger = None + self.__testModName = test_mod_name self.__testClient = None - self.__tcRunDebugFile = None + self.__tcResultFile = None + self.__testDataFilePath = None + self.__zoneForTests = zone + self.__parsedConfig = None + self.__hypervisorType = hypervisor_type + self.__userLogFolderPath = user_logfolder_path def __parseConfig(self): ''' + @Name: __parseConfig @Desc : Parses the configuration file passed and assigns the parsed configuration + @Output : SUCCESS or FAILED ''' try: - self.__parsedConfig = configGenerator.\ - getSetupConfig(self.__configFile) + if not os.path.isfile(self.__configFile): + print "\n=== Marvin Parse Config Init Failed ===" + return FAILED + self.__parsedConfig = getSetupConfig(self.__configFile) + print "\n=== Marvin Parse Config Successful ===" return SUCCESS - except Exception, e: - print "\n Exception Occurred Under __parseConfig : %s" % str(e) - return None + except Exception as e: + print "\nException Occurred Under __parseConfig : " \ + "%s" % GetDetailExceptionInfo(e) + return FAILED def getParsedConfig(self): return self.__parsedConfig @@ -78,33 +89,67 @@ def getTestClient(self): def getLogger(self): return self.__tcRunLogger - def getDebugFile(self): - return self.__tcRunDebugFile + def getResultFile(self): + ''' + @Name : getDebugFile + @Desc : Creates the result file at a given path. + @Output : Returns the Result file to be used for writing + test outputs + ''' + if self.__logFolderPath is not None: + self.__tcResultFile = open(self.__logFolderPath + + "/results.txt", "w") + return self.__tcResultFile + + def __setHypervisorAndZoneInfo(self): + ''' + @Name : __setHypervisorAndZoneInfo + @Desc: Set the HyperVisor and Zone details; + default to XenServer + ''' + try: + if not self.__hypervisorType: + self.__hypervisorType = XEN_SERVER + if not self.__zoneForTests: + if self.__parsedConfig: + for zone in self.__parsedConfig.zones: + self.__zoneForTests = zone.name + break + return SUCCESS + except Exception as e: + print "\n Exception Occurred Under init " \ + "%s" % GetDetailExceptionInfo(e) + return FAILED def init(self): ''' + @Name : init @Desc :Initializes the marvin by 1. Parsing the configuration and creating a parsed config structure 2. Creates a timestamped log folder and provides all logs to be dumped there 3. Creates the DataCenter based upon configuration provided + @Output : SUCCESS or FAILED ''' try: - if ((self.__parseConfig() is not None) and - (self.__initLogging() is not None) and - (self.__deployDC() is not None)): + if ((self.__parseConfig() != FAILED) and + (self.__setHypervisorAndZoneInfo())and + (self.__setTestDataPath() != FAILED) and + (self.__initLogging() != FAILED) and + (self.__createTestClient() != FAILED) and + (self.__deployDC() != FAILED)): return SUCCESS - else: - return FAILED - except Exception, e: - print "\n Exception Occurred Under init %s" % str(e) + return FAILED + except Exception as e: + print "\n Exception Occurred Under init " \ + "%s" % GetDetailExceptionInfo(e) return FAILED def __initLogging(self): - try: - ''' - @Desc : 1. Initializes the logging for marvin and so provides + ''' + @Name : __initLogging + @Desc : 1. Initializes the logging for marvin and so provides various log features for automation run. 2. Initializes all logs to be available under given Folder Path,where all test run logs @@ -112,58 +157,87 @@ def __initLogging(self): 3. All logging like exception log,results, run info etc for a given test run are available under a given timestamped folder - ''' - temp_path = "".join(str(time.time()).split(".")) - if self.__logFolderPath is None: - log_config = self.__parsedConfig.logger - if log_config is not None: - if log_config.LogFolderPath is not None: - self.logFolderPath = log_config.LogFolderPath + '/' \ - + temp_path - else: - self.logFolderPath = temp_path - else: - self.logFolderPath = temp_path - else: - self.logFolderPath = self.__logFolderPath + '/' + temp_path - if os.path.exists(self.logFolderPath): - self.logFolderPath += ''.join(random.choice( - string.ascii_uppercase + - string.digits for x in range(3))) - os.makedirs(self.logFolderPath) - ''' - Log File Paths - ''' - tc_failed_exceptionlog = self.logFolderPath + "/failed_" \ - "plus_" \ - "exceptions.txt" - tc_run_log = self.logFolderPath + "/runinfo.txt" - self.__tcRunDebugFile = open(self.logFolderPath + - "/results.txt", "w") - + @Output : SUCCESS or FAILED + ''' + try: log_obj = MarvinLog("CSLog") - self.__tcRunLogger = log_obj.setLogHandler(tc_run_log) - log_obj.setLogHandler(tc_failed_exceptionlog, - log_level=logging.FATAL) + if log_obj: + ret = log_obj.\ + createLogs(self.__testModName, + self.__parsedConfig.logger, + self.__userLogFolderPath) + if ret != FAILED: + self.__logFolderPath = log_obj.getLogFolderPath() + self.__tcRunLogger = log_obj.getLogger() + print "\n=== Marvin Init Logging Successful===" + return SUCCESS + return FAILED + except Exception as e: + print "\n Exception Occurred Under __initLogging " \ + ":%s" % GetDetailExceptionInfo(e) + return FAILED + + def __createTestClient(self): + ''' + @Name : __createTestClient + @Desc : Creates the TestClient during init + based upon the parameters provided + @Output: Returns SUCCESS or FAILED + ''' + try: + mgt_details = self.__parsedConfig.mgtSvr[0] + dbsvr_details = self.__parsedConfig.dbSvr + self.__testClient = CSTestClient( + mgt_details, + dbsvr_details, + logger=self.__tcRunLogger, + test_data_filepath=self.__testDataFilePath, + zone=self.__zoneForTests, + hypervisor_type=self.__hypervisorType) + if self.__testClient: + return self.__testClient.createTestClient() + return FAILED + except Exception as e: + print "\n Exception Occurred Under __createTestClient : %s" % \ + GetDetailExceptionInfo(e) + return FAILED + + def __setTestDataPath(self): + ''' + @Name : __setTestDataPath + @Desc : Sets the TestData Path for tests to run + @Output:Returns SUCCESS or FAILED + ''' + try: + if ((self.__parsedConfig.TestData is not None) and + (self.__parsedConfig.TestData.Path is not None)): + self.__testDataFilePath = self.__parsedConfig.TestData.Path + print "\n=== Marvin Setting TestData Successful===" return SUCCESS - except Exception, e: - print "\n Exception Occurred Under __initLogging :%s" % str(e) - return None + except Exception as e: + print "\nException Occurred Under __setTestDataPath : %s" % \ + GetDetailExceptionInfo(e) + return FAILED def __deployDC(self): + ''' + @Name : __deployDC + @Desc : Deploy the DataCenter and returns accordingly. + @Output: SUCCESS or FAILED + ''' try: - ''' - Deploy the DataCenter and retrieves test client. - ''' - deploy_obj = deployDataCenters(self.__parsedConfig, - self.__tcRunLogger) - if self.__loadFlag: - deploy_obj.loadCfg() - else: - deploy_obj.deploy() - - self.__testClient = deploy_obj.testClient - return SUCCESS - except Exception, e: - print "\n Exception Occurred Under __deployDC : %s" % str(e) - return None + ret = SUCCESS + if self.__deployFlag: + deploy_obj = DeployDataCenters(self.__testClient, + self.__parsedConfig, + self.__tcRunLogger) + ret = deploy_obj.deploy() + if ret == SUCCESS: + print "Deploy DC Successful" + else: + print "Deploy DC Failed" + return ret + except Exception as e: + print "\n Exception Occurred Under __deployDC : %s" % \ + GetDetailExceptionInfo(e) + return FAILED diff --git a/tools/marvin/marvin/marvinLog.py b/tools/marvin/marvin/marvinLog.py index 76de185421..ea8eaee7df 100644 --- a/tools/marvin/marvin/marvinLog.py +++ b/tools/marvin/marvin/marvinLog.py @@ -20,17 +20,22 @@ import logging import sys import time -from marvin.codes import (NO, - YES +import os +from marvin.codes import (SUCCESS, + FAILED ) +from marvin.cloudstackException import GetDetailExceptionInfo +from marvin.lib.utils import random_gen class MarvinLog: + ''' + @Name : MarvinLog @Desc : provides interface for logging to marvin @Input : logger_name : name for logger ''' - logFormat = logging.Formatter("%(asctime)s - %(levelname)s - %(name)s - %(message)s") + logFormat = logging.Formatter("%(asctime)s - %(levelname)s - %(message)s") _instance = None def __new__(cls, logger_name): @@ -39,21 +44,39 @@ def __new__(cls, logger_name): return cls._instance def __init__(self, logger_name): - self.loggerName = logger_name - self.logger = None + ''' + @Name: __init__ + @Input: logger_name for logger + ''' + self.__loggerName = logger_name + ''' + Logger for Logging Info + ''' + self.__logger = None + ''' + Log Folder Directory + ''' + self.__logFolderDir = None self.__setLogger() def __setLogger(self): - self.logger = logging.getLogger(self.loggerName) - self.logger.setLevel(logging.DEBUG) + ''' + @Name : __setLogger + @Desc : Sets the Logger and Level + ''' + self.__logger = logging.getLogger(self.__loggerName) + self.__logger.setLevel(logging.DEBUG) - def setLogHandler(self, log_file_path, log_format=None, - log_level=logging.DEBUG): + def __setLogHandler(self, log_file_path, + log_format=None, + log_level=logging.DEBUG): ''' + @Name : __setLogHandler @Desc: Adds the given Log handler to the current logger @Input: log_file_path: Log File Path as where to store the logs log_format : Format of log messages to be dumped log_level : Determines the level of logging for this logger + @Output: SUCCESS if no issues else FAILED ''' try: if log_file_path is not None: @@ -66,8 +89,98 @@ def setLogHandler(self, log_file_path, log_format=None, else: stream.setFormatter(self.__class__.logFormat) stream.setLevel(log_level) - self.logger.addHandler(stream) - except Exception, e: - print "\n Exception Occurred Under setLogHandler %s" % str(e) - finally: - return self.logger + self.__logger.addHandler(stream) + return SUCCESS + except Exception as e: + print "\nException Occurred Under " \ + "__setLogHandler %s" % GetDetailExceptionInfo(e) + return FAILED + + def __cleanPreviousLogs(self, logfolder_to_remove): + ''' + @Name : __cleanPreviousLogs + @Desc : Removes the Previous Logs + @Return: N\A + @Input: logfolder_to_remove: Path of Log to remove + ''' + try: + if os.path.isdir(logfolder_to_remove): + os.rmdir(logfolder_to_remove) + except Exception as e: + print "\n Exception Occurred Under __cleanPreviousLogs :%s" % \ + GetDetailExceptionInfo(e) + return FAILED + + def getLogger(self): + ''' + @Name:getLogger + @Desc : Returns the Logger + ''' + return self.__logger + + def getLogFolderPath(self): + ''' + @Name : getLogFolderPath + @Desc : Returns the final log directory path for marvin run + ''' + return self.__logFolderDir + + def createLogs(self, + test_module_name=None, + log_cfg=None, + user_provided_logpath=None): + ''' + @Name : createLogs + @Desc : Gets the Logger with file paths initialized and created + @Inputs :test_module_name: Test Module Name to use for logs while + creating log folder path + log_cfg: Log Configuration provided inside of + Configuration + user_provided_logpath:LogPath provided by user + If user provided log path + is available, then one in cfg + will not be picked up. + @Output : SUCCESS\FAILED + ''' + try: + temp_ts = time.strftime("%b_%d_%Y_%H_%M_%S", + time.localtime()) + if test_module_name is None: + temp_path = temp_ts + "_" + random_gen() + else: + temp_path = str(test_module_name) + \ + "__" + str(temp_ts) + "_" + random_gen() + + if user_provided_logpath: + temp_dir = user_provided_logpath + "/MarvinLogs" + elif ((log_cfg is not None) and + ('LogFolderPath' in log_cfg.__dict__.keys()) and + (log_cfg.__dict__.get('LogFolderPath') is not None)): + temp_dir = \ + log_cfg.__dict__.get('LogFolderPath') + "/MarvinLogs" + + self.__logFolderDir = temp_dir + "//" + temp_path + print "\n==== Log Folder Path: %s. " \ + "All logs will be available here ====" \ + % str(self.__logFolderDir) + os.makedirs(self.__logFolderDir) + + ''' + Log File Paths + 1. FailedExceptionLog + 2. RunLog contains the complete Run Information for Test Run + 3. ResultFile contains the TC result information for Test Run + ''' + tc_failed_exception_log = \ + self.__logFolderDir + "/failed_plus_exceptions.txt" + tc_run_log = self.__logFolderDir + "/runinfo.txt" + if self.__setLogHandler(tc_run_log, + log_level=logging.DEBUG) != FAILED: + self.__setLogHandler(tc_failed_exception_log, + log_level=logging.FATAL) + return SUCCESS + return FAILED + except Exception as e: + print "\n Exception Occurred Under createLogs :%s" % \ + GetDetailExceptionInfo(e) + return FAILED diff --git a/tools/marvin/marvin/marvinPlugin.py b/tools/marvin/marvin/marvinPlugin.py index df7d7a3123..52a2cdea3d 100644 --- a/tools/marvin/marvin/marvinPlugin.py +++ b/tools/marvin/marvin/marvinPlugin.py @@ -14,25 +14,24 @@ # KIND, either express or implied. See the License for the # specific language governing permissions and limitations # under the License. - import marvin -import sys +from sys import stdout, exit import logging +import time +import os import nose.core from marvin.cloudstackTestCase import cloudstackTestCase from marvin.marvinInit import MarvinInit from nose.plugins.base import Plugin from marvin.codes import (SUCCESS, FAILED, - EXCEPTION, - UNKNOWN_ERROR - ) -import traceback -import time -import os + EXCEPTION) +from marvin.lib.utils import random_gen +from marvin.cloudstackException import GetDetailExceptionInfo class MarvinPlugin(Plugin): + """ Custom plugin for the cloudstackTestCases to be run using nose """ @@ -40,18 +39,35 @@ class MarvinPlugin(Plugin): name = "marvin" def __init__(self): - self.identifier = None - self.testClient = None - self.parsedConfig = None - self.configFile = None - self.loadFlag = None + self.__identifier = None + self.__testClient = None + self.__logFolderPath = None + self.__parsedConfig = None + ''' + Contains Config File + ''' + self.__configFile = None + ''' + Signifies the Zone against which all tests will be Run + ''' + self.__zoneForTests = None + ''' + Signifies the flag whether to deploy the New DC or Not + ''' + self.__deployDcFlag = None self.conf = None - self.debugStream = sys.stdout - self.testRunner = None - self.testResult = SUCCESS - self.startTime = None - self.testName = None - self.tcRunLogger = None + self.__resultStream = stdout + self.__testRunner = None + self.__testResult = SUCCESS + self.__startTime = None + self.__testName = None + self.__tcRunLogger = None + self.__testModName = '' + self.__hypervisorType = None + ''' + The Log Path provided by user where all logs are routed to + ''' + self.__userLogPath = None Plugin.__init__(self) def configure(self, options, conf): @@ -60,20 +76,20 @@ def configure(self, options, conf): self.enabled (True|False) determines whether marvin's tests will run. By default non-default plugins like marvin will be disabled """ + self.enabled = True if hasattr(options, self.enableOpt): if not getattr(options, self.enableOpt): self.enabled = False return - else: - self.enabled = True - self.configFile = options.config_file - self.loadFlag = options.load - self.logFolderPath = options.log_folder_path + self.__configFile = options.configFile + self.__deployDcFlag = options.deployDc + self.__zoneForTests = options.zone + self.__hypervisorType = options.hypervisor_type + self.__userLogPath = options.logFolder self.conf = conf - ''' - Initializes the marvin with required settings - ''' - self.startMarvin() + if self.startMarvin() == FAILED: + print "\nStarting Marvin Failed, exiting. Please Check" + exit(1) def options(self, parser, env): """ @@ -82,20 +98,31 @@ def options(self, parser, env): parser.add_option("--marvin-config", action="store", default=env.get('MARVIN_CONFIG', './datacenter.cfg'), - dest="config_file", - help="Marvin's configuration file where the " + - "datacenter information is specified" + - " [MARVIN_CONFIG]") - parser.add_option("--load", action="store_true", + dest="configFile", + help="Marvin's configuration file is required." + "The config file containing the datacenter and " + "other management server " + "information is specified") + parser.add_option("--deploy", action="store_true", default=False, - dest="load", - help="Only load the deployment configuration given") - parser.add_option("--log-folder-path", - action="store", + dest="deployDc", + help="Deploys the DC with Given Configuration." + "Requires only when DC needs to be deployed") + parser.add_option("--zone", action="store", + default=None, + dest="zone", + help="Runs all tests against this specified zone") + parser.add_option("--hypervisor", action="store", + default=None, + dest="hypervisor_type", + help="Runs all tests against the specified " + "zone and hypervisor Type") + parser.add_option("--log-folder-path", action="store", default=None, - dest="log_folder_path", - help="Path to the folder " - "where log files will be stored") + dest="logFolder", + help="Collects all logs under the user specified" + "folder" + ) Plugin.options(self, parser, env) def wantClass(self, cls): @@ -105,93 +132,124 @@ def wantClass(self, cls): return True return None - def wantFile(self, filename): + def __checkImport(self, filename): ''' - Only python files will be used as test modules + @Name : __checkImport + @Desc : Verifies to run the available test module for any Import + Errors before running and check + whether if it is importable. + This will check for test modules which has some issues to be + getting imported. + Returns False or True based upon the result. ''' - parts = filename.split(os.path.sep) - base, ext = os.path.splitext(parts[-1]) - if ext == '.py': - return True - else: + try: + if os.path.isfile(filename): + ret = os.path.splitext(filename) + if ret[1] == ".py": + os.system("python " + filename) + return True + return False + except ImportError as e: + print "FileName :%s : Error : %s" % \ + (filename, GetDetailExceptionInfo(e)) return False + def wantFile(self, filename): + ''' + @Desc : Only python files will be used as test modules + ''' + return self.__checkImport(filename) + def loadTestsFromTestCase(self, cls): if cls.__name__ != 'cloudstackTestCase': - self.identifier = cls.__name__ + self.__identifier = cls.__name__ self._injectClients(cls) def beforeTest(self, test): - self.testName = test.__str__().split()[0] - self.testClient.identifier = '-'.join([self.identifier, self.testName]) - self.tcRunLogger.name = test.__str__() - - def prepareTestRunner(self, runner): - return self.testRunner + self.__testModName = test.__str__() + self.__testName = test.__str__().split()[0] + self.__testClient.identifier = '-'.\ + join([self.__identifier, self.__testName]) + if self.__tcRunLogger: + self.__tcRunLogger.name = test.__str__() def startTest(self, test): """ Currently used to record start time for tests Dump Start Msg of TestCase to Log """ - self.tcRunLogger.debug("::::::::::::STARTED : TC: " + - str(self.testName) + " :::::::::::") - self.startTime = time.time() + if self.__tcRunLogger: + self.__tcRunLogger.debug("::::::::::::STARTED : TC: " + + str(self.__testName) + " :::::::::::") + self.__startTime = time.time() + + def printMsg(self, status, tname, err): + if status in [FAILED, EXCEPTION] and self.__tcRunLogger: + self.__tcRunLogger.\ + fatal("%s: %s: %s" % (status, + tname, + GetDetailExceptionInfo(err))) + write_str = "=== TestName: %s | Status : %s ===\n" % (tname, status) + self.__resultStream.write(write_str) + print write_str - def getErrorInfo(self, err): + def addSuccess(self, test, capt): ''' - Extracts and returns the sanitized error message + Adds the Success Messages to logs ''' - if err is not None: - return str(traceback.format_exc()) - else: - return UNKNOWN_ERROR + self.printMsg(SUCCESS, self.__testName, "Test Case Passed") + self.__testresult = SUCCESS def handleError(self, test, err): ''' Adds Exception throwing test cases and information to log. ''' - err_msg = self.getErrorInfo(err) - self.tcRunLogger.fatal("%s: %s: %s" % - (EXCEPTION, self.testName, err_msg)) - self.testResult = EXCEPTION + self.printMsg(EXCEPTION, self.__testName, GetDetailExceptionInfo(err)) + self.__testResult = EXCEPTION + + def prepareTestRunner(self, runner): + if self.__testRunner: + return self.__testRunner def handleFailure(self, test, err): ''' Adds Failing test cases and information to log. ''' - err_msg = self.getErrorInfo(err) - self.tcRunLogger.fatal("%s: %s: %s" % - (FAILED, self.testName, err_msg)) - self.testResult = FAILED + self.printMsg(FAILED, self.__testName, GetDetailExceptionInfo(err)) + self.__testResult = FAILED def startMarvin(self): ''' - Initializes the Marvin - creates the test Client - creates the runlogger for logging - Parses the config and creates a parsedconfig - Creates a debugstream for tc debug log + @Name : startMarvin + @Desc : Initializes the Marvin + creates the test Client + creates the runlogger for logging + Parses the config and creates a parsedconfig + Creates a debugstream for tc debug log ''' try: - obj_marvininit = MarvinInit(self.configFile, - self.loadFlag, - self.logFolderPath) - if obj_marvininit.init() == SUCCESS: - self.testClient = obj_marvininit.getTestClient() - self.tcRunLogger = obj_marvininit.getLogger() - self.parsedConfig = obj_marvininit.getParsedConfig() - self.debugStream = obj_marvininit.getDebugFile() - self.testRunner = nose.core.TextTestRunner(stream= - self.debugStream, - descriptions=True, - verbosity=2, - config=self.conf) + obj_marvininit = MarvinInit(self.__configFile, + self.__deployDcFlag, + None, + self.__zoneForTests, + self.__hypervisorType, + self.__userLogPath) + if obj_marvininit and obj_marvininit.init() == SUCCESS: + self.__testClient = obj_marvininit.getTestClient() + self.__tcRunLogger = obj_marvininit.getLogger() + self.__parsedConfig = obj_marvininit.getParsedConfig() + self.__resultStream = obj_marvininit.getResultFile() + self.__logFolderPath = obj_marvininit.getLogFolderPath() + self.__testRunner = nose.core.\ + TextTestRunner(stream=self.__resultStream, + descriptions=True, + verbosity=2, + config=self.conf) return SUCCESS - else: - return FAILED - except Exception, e: - print "Exception Occurred under startMarvin: %s" % str(e) + return FAILED + except Exception as e: + print "Exception Occurred under startMarvin: %s" % \ + GetDetailExceptionInfo(e) return FAILED def stopTest(self, test): @@ -199,27 +257,53 @@ def stopTest(self, test): Currently used to record end time for tests """ endTime = time.time() - if self.startTime is not None: - totTime = int(endTime - self.startTime) - self.tcRunLogger.debug("TestCaseName: %s; Time Taken: " - "%s Seconds; " - "StartTime: %s; EndTime: %s; Result: %s" - % (self.testName, str(totTime), - str(time.ctime(self.startTime)), - str(time.ctime(endTime)), - self.testResult)) + if self.__startTime: + totTime = int(endTime - self.__startTime) + if self.__tcRunLogger: + self.__tcRunLogger.\ + debug("TestCaseName: %s; " + "Time Taken: %s Seconds; StartTime: %s; " + "EndTime: %s; Result: %s" % + (self.__testName, str(totTime), + str(time.ctime(self.__startTime)), + str(time.ctime(endTime)), + self.__testResult)) def _injectClients(self, test): - setattr(test, "debug", self.tcRunLogger.debug) - setattr(test, "info", self.tcRunLogger.info) - setattr(test, "warn", self.tcRunLogger.warning) - setattr(test, "error", self.tcRunLogger.error) - setattr(test, "testClient", self.testClient) - setattr(test, "config", self.parsedConfig) - if self.testClient.identifier is None: - self.testClient.identifier = self.identifier - setattr(test, "clstestclient", self.testClient) + setattr(test, "debug", self.__tcRunLogger.debug) + setattr(test, "info", self.__tcRunLogger.info) + setattr(test, "warn", self.__tcRunLogger.warning) + setattr(test, "error", self.__tcRunLogger.error) + setattr(test, "testClient", self.__testClient) + setattr(test, "config", self.__parsedConfig) + if self.__testClient.identifier is None: + self.__testClient.identifier = self.__identifier + setattr(test, "clstestclient", self.__testClient) if hasattr(test, "user"): # when the class-level attr applied. all test runs as 'user' - self.testClient.createUserApiClient(test.UserName, test.DomainName, - test.AcctType) + self.__testClient.getUserApiClient(test.UserName, + test.DomainName, + test.AcctType) + + def finalize(self, result): + try: + src = self.__logFolderPath + if not self.__userLogPath: + log_cfg = self.__parsedConfig.logger + tmp = log_cfg.__dict__.get('LogFolderPath') + "/MarvinLogs" + else: + tmp = self.__userLogPath + "/MarvinLogs" + dst = tmp + "//" + random_gen() + mod_name = "test_suite" + if self.__testModName: + mod_name = self.__testModName.split(".") + if len(mod_name) > 2: + mod_name = mod_name[-2] + if mod_name: + dst = tmp + "/" + mod_name + "_" + random_gen() + cmd = "mv " + src + " " + dst + os.system(cmd) + print "===final results are now copied to: %s===" % str(dst) + except Exception as e: + print "=== Exception occurred under finalize :%s ===" % \ + str(GetDetailExceptionInfo(e)) diff --git a/tools/marvin/marvin/src/__init__.py b/tools/marvin/marvin/src/__init__.py new file mode 100644 index 0000000000..13a83393a9 --- /dev/null +++ b/tools/marvin/marvin/src/__init__.py @@ -0,0 +1,16 @@ +# 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. diff --git a/tools/marvin/marvin/sshClient.py b/tools/marvin/marvin/sshClient.py index fd8726cee3..76f3b6dd59 100644 --- a/tools/marvin/marvin/sshClient.py +++ b/tools/marvin/marvin/sshClient.py @@ -16,29 +16,49 @@ # under the License. import paramiko +from paramiko import (BadHostKeyException, + AuthenticationException, + SSHException, + SSHClient, + AutoAddPolicy, + Transport, + SFTPClient) +import socket import time -import cloudstackException +from marvin.cloudstackException import ( + internalError, + GetDetailExceptionInfo +) import contextlib import logging from marvin.codes import ( - SUCCESS, FAIL, INVALID_INPUT, EXCEPTION_OCCURRED - ) + SUCCESS, FAILED, INVALID_INPUT, EXCEPTION_OCCURRED +) from contextlib import closing class SshClient(object): + ''' - Added timeout flag for ssh connect calls.Default to 3.0 seconds + @Desc : SSH Library for Marvin. + Facilitates SSH,SCP services to marvin users + @Input: host: Host to connect + port: port on host to connect + user: Username to be used for connecting + passwd: Password for connection + retries and delay applies for establishing connection + timeout : Applies while executing command ''' - def __init__(self, host, port, user, passwd, retries=20, delay=30, - log_lvl=logging.INFO, keyPairFiles=None, timeout=10.0): + + def __init__(self, host, port, user, passwd, retries=60, delay=10, + log_lvl=logging.DEBUG, keyPairFiles=None, timeout=10.0): self.host = None self.port = 22 self.user = user self.passwd = passwd self.keyPairFiles = keyPairFiles - self.ssh = paramiko.SSHClient() - self.ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy()) + self.ssh = SSHClient() + self.ssh.set_missing_host_key_policy(AutoAddPolicy()) self.logger = logging.getLogger('sshClient') self.retryCnt = 0 self.delay = 0 @@ -47,8 +67,8 @@ def __init__(self, host, port, user, passwd, retries=20, delay=30, ch.setLevel(log_lvl) self.logger.addHandler(ch) - #Check invalid host value and raise exception - #Atleast host is required for connection + # Check invalid host value and raise exception + # Atleast host is required for connection if host is not None and host != '': self.host = host if retries is not None and retries > 0: @@ -57,11 +77,10 @@ def __init__(self, host, port, user, passwd, retries=20, delay=30, self.delay = delay if timeout is not None and timeout > 0: self.timeout = timeout - if port is not None or port >= 0: + if port is not None and port >= 0: self.port = port - if self.createConnection() == FAIL: - raise cloudstackException.\ - internalError("Connection Failed") + if self.createConnection() == FAILED: + raise internalError("SSH Connection Failed") def execute(self, command): stdin, stdout, stderr = self.ssh.exec_command(command) @@ -86,15 +105,16 @@ def createConnection(self): @Desc: Creates an ssh connection for retries mentioned,along with sleep mentioned @Output: SUCCESS on successful connection - FAIL If connection through ssh failed + FAILED If connection through ssh failed ''' - ret = FAIL + ret = FAILED + except_msg = '' while self.retryCnt >= 0: try: - self.logger.debug("SSH Connection: Host:%s User:%s\ - Port:%s" % - (self.host, self.user, str(self.port) - )) + self.logger.debug("====Trying SSH Connection: Host:%s User:%s\ + Port:%s RetryCnt:%s===" % + (self.host, self.user, str(self.port), + str(self.retryCnt))) if self.keyPairFiles is None: self.ssh.connect(hostname=self.host, port=self.port, @@ -102,22 +122,39 @@ def createConnection(self): password=self.passwd, timeout=self.timeout) else: + self.ssh.load_host_keys(self.keyPairFiles) self.ssh.connect(hostname=self.host, port=self.port, username=self.user, password=self.passwd, key_filename=self.keyPairFiles, timeout=self.timeout, - look_for_keys=False + look_for_keys=True ) + self.logger.debug("===SSH to Host %s port : %s SUCCESSFUL===" + % (str(self.host), str(self.port))) ret = SUCCESS break - except Exception as se: - self.retryCnt = self.retryCnt - 1 - if self.retryCnt == 0: + except BadHostKeyException as e: + except_msg = GetDetailExceptionInfo(e) + except AuthenticationException as e: + except_msg = GetDetailExceptionInfo(e) + except SSHException as e: + except_msg = GetDetailExceptionInfo(e) + except socket.error as e: + except_msg = GetDetailExceptionInfo(e) + except Exception as e: + except_msg = GetDetailExceptionInfo(e) + finally: + if self.retryCnt == 0 or ret == SUCCESS: break + if except_msg != '': + self.logger.\ + exception("SshClient: Exception under " + "createConnection: %s" % except_msg) + self.retryCnt = self.retryCnt - 1 time.sleep(self.delay) - return ret + return ret def runCommand(self, command): ''' @@ -126,57 +163,54 @@ def runCommand(self, command): returns the result along with status code @Input: command to execute @Output: 1: status of command executed. - Default to None SUCCESS : If command execution is successful - FAIL : If command execution has failed - EXCEPTION_OCCURRED: Exception occurred while executing - command - INVALID_INPUT : If invalid value for command is passed + FAILED : If command execution has failed 2: stdin,stdout,stderr values of command output ''' - excep_msg = '' - ret = {"status": None, "stdin": None, "stdout": None, "stderr": None} + ret = {"status": FAILED, "stdin": None, "stdout": None, + "stderr": INVALID_INPUT} if command is None or command == '': - ret["status"] = INVALID_INPUT return ret try: status_check = 1 - stdin, stdout, stderr = self.ssh.exec_command(command) - output = stdout.readlines() - errors = stderr.readlines() - inp = stdin.readlines() - ret["stdin"] = inp - ret["stdout"] = output - ret["stderr"] = errors + stdin, stdout, stderr = self.ssh.\ + exec_command(command, timeout=self.timeout) if stdout is not None: status_check = stdout.channel.recv_exit_status() - if status_check == 0: - ret["status"] = SUCCESS - else: - ret["status"] = FAIL + if status_check == 0: + ret["status"] = SUCCESS + ret["stdout"] = stdout.readlines() + if stderr is not None: + ret["stderr"] = stderr.readlines() except Exception as e: - excep_msg = str(e) - ret["status"] = EXCEPTION_OCCURRED + ret["stderr"] = GetDetailExceptionInfo(e) + self.logger.exception("SshClient: Exception under runCommand :%s" % + GetDetailExceptionInfo(e)) finally: - self.logger.debug(" Host: %s Cmd: %s Output:%s Exception: %s" % - (self.host, command, str(ret), excep_msg)) + self.logger.debug(" Host: %s Cmd: %s Output:%s" % + (self.host, command, str(ret))) return ret def scp(self, srcFile, destPath): - transport = paramiko.Transport((self.host, int(self.port))) + transport = Transport((self.host, int(self.port))) transport.connect(username=self.user, password=self.passwd) - sftp = paramiko.SFTPClient.from_transport(transport) + sftp = SFTPClient.from_transport(transport) try: sftp.put(srcFile, destPath) - except IOError, e: + except IOError as e: raise e + def __del__(self): + self.close() + def close(self): - if self.ssh is not None: - self.ssh.close() + if self.ssh is not None: + self.ssh.close() + self.ssh = None if __name__ == "__main__": - with contextlib.closing(SshClient("10.223.75.10", 22, "root", - "password")) as ssh: - print ssh.execute("ls -l") + with contextlib.closing(SshClient("127.0.0.1", 22, "root", + "asdf!@34")) as ssh: + ret = ssh.runCommand("ls -l") + print ret diff --git a/tools/marvin/marvin/tcExecuteEngine.py b/tools/marvin/marvin/tcExecuteEngine.py index f959e7e935..e2f4d114b7 100644 --- a/tools/marvin/marvin/tcExecuteEngine.py +++ b/tools/marvin/marvin/tcExecuteEngine.py @@ -23,6 +23,7 @@ class TestCaseExecuteEngine(object): + def __init__(self, testclient, config, tc_logger=None, debug_stream=None): """ Initialize the testcase execution engine, just the basics here @@ -53,7 +54,7 @@ def injectTestCase(self, testSuites): if isinstance(test, unittest.BaseTestSuite): self.injectTestCase(test) else: - #inject testclient and logger into each unittest + # inject testclient and logger into each unittest self.tcRunLogger.name = test.__str__() setattr(test, "testClient", self.testclient) setattr(test, "config", self.config) @@ -61,9 +62,10 @@ def injectTestCase(self, testSuites): setattr(test.__class__, "clstestclient", self.testclient) if hasattr(test, "user"): # attribute when test is entirely executed as user - self.testclient.createUserApiClient(test.UserName, - test.DomainName, - test.AcctType) + self.testclient.\ + getUserApiClient(test.UserName, + test.DomainName, + test.AcctType) def run(self): if self.suite: diff --git a/tools/marvin/marvin/testSetupSuccess.py b/tools/marvin/marvin/testSetupSuccess.py index 1701626a82..8b000f9e97 100644 --- a/tools/marvin/marvin/testSetupSuccess.py +++ b/tools/marvin/marvin/testSetupSuccess.py @@ -23,6 +23,7 @@ class TestSetupSuccess(cloudstackTestCase): + """ Test to verify if the cloudstack is ready to launch tests upon 1. Verify that system VMs are up and running in all zones diff --git a/tools/marvin/setup.py b/tools/marvin/setup.py index 9ce3951fde..4c775ad614 100644 --- a/tools/marvin/setup.py +++ b/tools/marvin/setup.py @@ -6,9 +6,9 @@ # 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 @@ -30,33 +30,37 @@ VERSION = '0.1.0' import os + + def read(fname): return open(os.path.join(os.path.dirname(__file__), fname)).read().strip() setup(name="Marvin", - version=VERSION, - description="Marvin - Python client for Apache CloudStack", - author="Edison Su", - author_email="Edison.Su@citrix.com", - maintainer="Prasanna Santhanam", - maintainer_email="tsp@apache.org", - long_description="Marvin is the Apache CloudStack python client written around the unittest framework", - platforms=("Any",), - url="https://builds.apache.org/job/cloudstack-marvin/", - packages=["marvin", "marvin.cloudstackAPI", "marvin.integration", - "marvin.integration.lib", "marvin.sandbox", - "marvin.sandbox.advanced", "marvin.sandbox.advancedsg", "marvin.sandbox.basic"], - license="LICENSE.txt", - install_requires=[ - "mysql-connector-python", - "requests", - "paramiko", - "nose", - "ddt >= 0.4.0" - ], - py_modules=['marvin.marvinPlugin'], - zip_safe=False, - entry_points={ - 'nose.plugins': ['marvinPlugin = marvin.marvinPlugin:MarvinPlugin'] - }, -) + version=VERSION, + description="Marvin - Python client for Apache CloudStack", + author="Edison Su", + author_email="Edison.Su@citrix.com", + maintainer="Prasanna Santhanam", + maintainer_email="tsp@apache.org", + long_description="Marvin is the Apache CloudStack python " + "client written around the unittest framework", + platforms=("Any",), + url="https://builds.apache.org/job/cloudstack-marvin/", + packages=["marvin", "marvin.cloudstackAPI", + "marvin.lib", "marvin.config", "marvin.sandbox", + "marvin.sandbox.advanced", "marvin.sandbox.advancedsg", + "marvin.sandbox.basic"], + license="LICENSE.txt", + install_requires=[ + "mysql-connector-python", + "requests", + "paramiko", + "nose", + "ddt >= 0.4.0" + ], + py_modules=['marvin.marvinPlugin'], + zip_safe=False, + entry_points={ + 'nose.plugins': ['marvinPlugin = marvin.marvinPlugin:MarvinPlugin'] + }, + ) diff --git a/tools/transifex/.tx/config b/tools/transifex/.tx/config index 5e83db3ef0..a2c1e26289 100644 --- a/tools/transifex/.tx/config +++ b/tools/transifex/.tx/config @@ -15,23 +15,14 @@ source_lang = en [CloudStack_UI.42xmessagesproperties] file_filter = translations/CloudStack_UI.42xmessagesproperties/.properties -source_file = work-dir/messages.properties source_lang = en -trans.ar = work-dir/messages_ar.properties -trans.ca = work-dir/messages_ca.properties -trans.de_DE = work-dir/messages_de_DE.properties -trans.es = work-dir/messages_es.properties -trans.fr_FR = work-dir/messages_fr_FR.properties -trans.it_IT = work-dir/messages_it_IT.properties -trans.ja = work-dir/messages_ja.properties -trans.ko_KR = work-dir/messages_ko_KR.properties -trans.nb_NO = work-dir/messages_nb_NO.properties -trans.pt_BR = work-dir/messages_pt_BR.properties -trans.ru_RU = work-dir/messages_ru_RU.properties -trans.zh_CN = work-dir/messages_zh_CN.properties [CloudStack_UI.43xmessagesproperties] -source_file = work-dir/messages.properties +file_filter = translations/CloudStack_UI.43xmessagesproperties/.properties +source_lang = en + +[CloudStack_UI.44xmessagesproperties] +file_filter = translations/CloudStack_UI.44xmessagesproperties/.properties source_lang = en trans.ar = work-dir/messages_ar.properties trans.ca = work-dir/messages_ca.properties diff --git a/ui/css/cloudstack3.css b/ui/css/cloudstack3.css index 2b88e03366..cb9fa3521f 100644 --- a/ui/css/cloudstack3.css +++ b/ui/css/cloudstack3.css @@ -173,6 +173,13 @@ table tbody td.truncated > span { text-overflow: ellipsis; } +.list-view-select table th.name, +.list-view-select table td.name { + width: 170px; + min-width: 170px; + max-width: 170px; +} + /** Multiselect*/ table thead th.multiselect, table tbody td.multiselect { @@ -210,6 +217,23 @@ table tbody td.actions input { margin: 11px 0 0px; } +.list-view-select table tbody td.actions { + width: 40px !important; + min-width: 40px !important; + max-width: 40px !important; +} + +.list-view-select table tbody td.actions input { + margin: 0 0 0 -7px; +} + +.list-view-select table thead th.actions { + width: 40px !important; + min-width: 40px !important; + max-width: 40px !important; + text-indent: 5px; +} + /** Quick view table cell*/ table tbody td.quick-view, table thead th.quick-view { @@ -1333,7 +1357,7 @@ div.list-view td.first { cursor: pointer; } -div.list-view td.first:hover { +div.list-view tr:not(.multi-edit-selected) td.first:hover { color: #3A82CD; } @@ -1836,6 +1860,58 @@ div.list-view td.state.off span { width: 245px; } +.detail-group .main-groups table td.value > span.copypasteenabledvalue { + text-overflow: ellipsis; + -o-text-overflow: ellipsis; + overflow: hidden; + white-space: nowrap; +} + +.detail-group .main-groups table td.value > .copypasteactive { + display: auto; + white-space: nowrap; + overflow: none; +} + +div.copypasteicon { + background: url("../images/sprites.png") no-repeat -271px -65px; + float: left; + height: 21px; + margin-left: 6px; + margin-top: 0px; + width: 18px; +} + +div.copypasteicon:hover { + background: url("../images/sprites.png") no-repeat -271px -646px; +} + +.detail-group .main-groups table td.value > span.copypasteenabledvalue { + text-overflow: ellipsis; + -o-text-overflow: ellipsis; + overflow: hidden; + white-space: nowrap; +} + +.detail-group .main-groups table td.value > .copypasteactive { + display: auto; + white-space: nowrap; + overflow: none; +} + +div.copypasteicon { + background: url("../images/sprites.png") no-repeat -271px -65px; + float: left; + height: 21px; + margin-left: 6px; + margin-top: 0px; + width: 18px; +} + +div.copypasteicon:hover { + background: url("../images/sprites.png") no-repeat -271px -646px; +} + .detail-group .main-groups table td.value > span select { width: 100% !important; } @@ -1926,6 +2002,11 @@ div.list-view td.state.off span { margin: 4px 0 0 12px; } +.list-view .subselect span.info { + font-size: 10px; + white-space: nowrap; +} + .list-view .subselect select { width: 85%; margin: 5px 0 4px; @@ -3893,7 +3974,7 @@ Dialogs*/ } .ui-dialog.confirm .ui-dialog-title { - background: url(../images/icons.png) no-repeat 0px -225px; + background: url(../images/icons.png) no-repeat 0px -224px; } .ui-dialog.create-form .ui-dialog-title { @@ -5988,7 +6069,7 @@ label.error { } .multi-wizard.instance-wizard .data-disk-offering .select-container { - height: 280px; + height: 300px; margin: -7px 6px 0 8px; /*+border-radius:6px;*/ -moz-border-radius: 6px; @@ -5998,6 +6079,94 @@ label.error { border-radius: 6px 6px 6px 6px; } +.multi-wizard.instance-wizard .data-disk-offering .disk-select-group { + float: left; + margin-top: 12px; + width: 100%; +} + +.multi-wizard.instance-wizard .data-disk-offering .disk-select-header { + border-bottom: 1px solid #D4D4D4; + /*+border-radius:4px;*/ + -moz-border-radius: 4px; + -webkit-border-radius: 4px; + -khtml-border-radius: 4px; + border-radius: 4px; + background: #C2C2C2 0px 4px; + padding: 6px; + height: 17px; +} + +.multi-wizard.instance-wizard .disk-select-group.selected .disk-select-header { + background: #505050; + /*+border-radius:4px 4px 0 0;*/ + -moz-border-radius: 4px 4px 0 0; + -webkit-border-radius: 4px 4px 0 0; + -khtml-border-radius: 4px 4px 0 0; + border-radius: 4px 4px 0 0; +} + +.multi-wizard.instance-wizard .data-disk-offering .disk-select-header input { + float: left; +} + +.multi-wizard.instance-wizard .data-disk-offering .disk-select-header .title { + float: left; + font-size: 14px; + padding: 2px; +} + +.multi-wizard.instance-wizard .disk-select-group.selected .disk-select-header .title { + color: #FFFFFF; + /*+text-shadow:0px -1px #000000;*/ + -moz-text-shadow: 0px -1px #000000; + -webkit-text-shadow: 0px -1px #000000; + -o-text-shadow: 0px -1px #000000; + text-shadow: 0px -1px #000000; +} + +.multi-wizard.instance-wizard .data-disk-offering .multi-disk-select-container { + max-height: 257px; + overflow: auto; + border: 1px solid #DDDBDB; + padding: 13px; + background: #E4E4E4; +} + +.multi-wizard.instance-wizard .data-disk-offering .disk-select-group .select-container { + max-height: 114px; + float: left; + margin: 0; + border: none; + /*+border-radius:0;*/ + -moz-border-radius: 0; + -webkit-border-radius: 0; + -khtml-border-radius: 0; + border-radius: 0; + display: none; +} + +.multi-wizard.instance-wizard .data-disk-offering .disk-select-group.selected .select-container { + display: block; +} + +.multi-wizard.instance-wizard .data-disk-offering .disk-select-group .select { + padding: 0 0 17px; + height: 0; +} + +.multi-wizard.instance-wizard .data-disk-offering .disk-select-group.custom-size .section.custom-size { + display: block !important; +} + +.multi-wizard.instance-wizard .data-disk-offering .disk-select-group .select input { + margin: 13px 12px 12px; +} + +.multi-wizard.instance-wizard .data-disk-offering .disk-select-group .select-desc { + margin: 13px 0 0; +} + .multi-wizard.instance-wizard .data-disk-offering.required .select-container { height: 344px; position: relative; @@ -6057,6 +6226,13 @@ label.error { border-radius: 4px; } +.multi-wizard.instance-wizard .section.custom-iops-do { + position: relative; + background: #F4F4F4; + padding: 7px; + border-radius: 4px; +} + .multi-wizard.instance-wizard .section.custom-size input[type=radio] { float: left; } @@ -6073,6 +6249,12 @@ label.error { margin: 6px -1px 0 8px; } +.multi-wizard.instance-wizard .section.custom-iops-do input[type=text] { + float: left; + width: 28px; + margin: 6px -1px 0 8px; +} + .multi-wizard.instance-wizard .section.custom-size label.error { position: absolute; top: 29px; @@ -6080,6 +6262,53 @@ label.error { font-size: 10px; } +.instance-wizard .step.data-disk-offering.custom-disk-size .select-container { + height: 272px; +} + +.instance-wizard .step.data-disk-offering.custom-iops-do .select-container { + height: 240px; +} + +.instance-wizard .step.data-disk-offering.custom-disk-size.custom-iops-do .select-container { + height: 176px; +} + +.instance-wizard .step.data-disk-offering.required.custom-disk-size .select-container { + height: 315px; +} + +.instance-wizard .step.data-disk-offering.required.custom-iops-do .select-container { + height: 295px; +} + +.instance-wizard .step.data-disk-offering.required.custom-disk-size.custom-iops-do .select-container { + height: 223px; +} + +.instance-wizard .step.data-disk-offering .custom-iops-do { + display: none; +} + +.instance-wizard .step.data-disk-offering.custom-iops-do .custom-iops-do { + display: block; +} + +.instance-wizard .step.data-disk-offering .custom-iops-do .field { + width: 30%; + float: left; + margin-bottom: 5px; +} + +.instance-wizard .step.data-disk-offering .custom-iops-do .field label { + text-indent: 20px; +} + +.instance-wizard .step.data-disk-offering .custom-iops-do .field input { + width: 88%; + margin-left: 26px; +} + /*** Compute offering*/ .instance-wizard .step.service-offering { } @@ -7739,28 +7968,42 @@ div.panel.ui-dialog div.list-view div.fixed-header { /*List-view: subselect dropdown*/ .list-view .subselect { - width: 116px; + width: 173px; + cursor: default; display: block; float: left; - background: url(../images/bg-gradients.png) 0px -42px; + background: #E8E8E8; padding: 0; - margin: 8px 0 1px 7px; + margin: 0 0 0 -3px; clear: both; border: 1px solid #A8A7A7; - /*+border-radius:4px;*/ - -moz-border-radius: 4px; - -webkit-border-radius: 4px; - -khtml-border-radius: 4px; - border-radius: 4px; + /*+border-radius:2px;*/ + -moz-border-radius: 2px; + -webkit-border-radius: 2px; + -khtml-border-radius: 2px; + border-radius: 2px; +} + +.list-view .subselect:hover span { + color: initial; } .list-view .subselect span { margin: 4px 0 0 12px; + cursor: default; +} + +.list-view .subselect span.info { + background: none; +} + +.list-view .subselect span:hover { + color: initial; } .list-view .subselect select { - width: 85%; - margin: 5px 0 4px; + width: 175px; + margin: 0 0 0 -11px; font-size: 10px; } @@ -12374,11 +12617,13 @@ div.ui-dialog div.autoscaler div.field-group div.form-container form div.form-it } .restoreVM .icon, -.restore .icon { +.restore .icon, +.recover .icon { background-position: -168px -31px; } -.reset .icon { +.reset .icon, +.reinstall .icon { background-position: -168px -31px; } @@ -12687,3 +12932,50 @@ div.ui-dialog div.autoscaler div.field-group div.form-container form div.form-it display: inline-block; } +/*GPU*/ +div.gpugroups div.list-view div.fixed-header { + position: relative; + left: 12px !important; + top: 0px !important; +} + +div.gpugroups div.list-view div.fixed-header table { + width: auto; +} + +div.gpugroups div.list-view div.data-table table { + margin-top: 0; +} + +div.gpugroups div.list-view { + position: relative; + height: auto !important; + margin-top: 0 !important; + border: none !important; +} + +.gpugroups { + float: left; + height: 100%; + width: 100%; + overflow-x: hidden; + overflow-y: auto; +} + +.gpugroups .gpugroup-container { + border: 1px solid #C8C2C2; + border-radius: 3px; + height: auto !important; + margin: 12px; + padding: 0; + position: relative; + float: left; + width: auto; +} + +.gpugroups .gpugroup-container .title { + font-size: 13px; + font-weight: 100; + padding: 12px 12px 5px; +} + diff --git a/ui/dictionary.jsp b/ui/dictionary.jsp index 074db7f061..9cc030ad95 100644 --- a/ui/dictionary.jsp +++ b/ui/dictionary.jsp @@ -25,6 +25,12 @@ under the License. <% long now = System.currentTimeMillis(); %> diff --git a/ui/images/sprites.png b/ui/images/sprites.png old mode 100644 new mode 100755 index ab396700f3..1a6eaa577f Binary files a/ui/images/sprites.png and b/ui/images/sprites.png differ diff --git a/ui/index.jsp b/ui/index.jsp index d46c395cd8..5840e7171d 100644 --- a/ui/index.jsp +++ b/ui/index.jsp @@ -206,6 +206,7 @@

@@ -1065,7 +1077,7 @@
-
+
 
diff --git a/ui/scripts/accounts.js b/ui/scripts/accounts.js index aff780ef48..4eaa401113 100644 --- a/ui/scripts/accounts.js +++ b/ui/scripts/accounts.js @@ -17,8 +17,7 @@ (function(cloudStack) { var domainObjs; - var rootDomainId; - + cloudStack.sections.accounts = { title: 'label.accounts', id: 'accounts', @@ -97,6 +96,7 @@ label: 'Add LDAP Account', isHeader: true, preFilter: function(args) { + //if ((isAdmin() || isDomainAdmin()) && true) { //for testing only if ((isAdmin() || isDomainAdmin()) && isLdapEnabled()) { return true; } else { @@ -1374,12 +1374,6 @@ state: { label: 'label.state' }, - apikey: { - label: 'label.api.key' - }, - secretkey: { - label: 'label.secret.key' - }, account: { label: 'label.account.name' }, @@ -1392,6 +1386,14 @@ domain: { label: 'label.domain' }, + apikey: { + label: 'label.api.key', + isCopyPaste: true + }, + secretkey: { + label: 'label.secret.key', + isCopyPaste: true + }, email: { label: 'label.email', isEditable: true, diff --git a/ui/scripts/accountsWizard.js b/ui/scripts/accountsWizard.js index 6b4907c1cb..e02a04eea8 100644 --- a/ui/scripts/accountsWizard.js +++ b/ui/scripts/accountsWizard.js @@ -16,6 +16,8 @@ // under the License. (function(cloudStack, $) { + var rootDomainId; + cloudStack.accountsWizard = { informationWithinLdap: { @@ -75,20 +77,9 @@ validation: { required: true }, - select: function(args) { - var data = {}; - - if (args.context.users) { // In accounts section - data.listAll = true; - } else if (args.context.domains) { // In domain section (use specific domain) - data.id = args.context.domains[0].id; - } - + select: function(args) { $.ajax({ - url: createURL("listDomains"), - data: data, - dataType: "json", - async: false, + url: createURL("listDomains"), success: function(json) { var items = []; domainObjs = json.listdomainsresponse.domain; @@ -198,14 +189,16 @@ array1.push("&domainid=" + args.data.domainid); var account = args.data.account; - if (account === null || account.length === 0) { - account = args.username; + + if (account !== null && account.length > 0) { + array1.push("&account=" + account); } - array1.push("&account=" + account); var accountType = args.data.accounttype; - if (args.data.accounttype == "1" && args.data.domainid != rootDomainId) { //if account type is admin, but domain is not Root domain - accountType = "2"; // Change accounttype from root-domain("1") to domain-admin("2") + if (accountType == "1") { //if "admin" is selected in account type dropdown + if (rootDomainId == undefined || args.data.domainid != rootDomainId ) { //but current login has no visibility to root domain object, or the selected domain is not root domain + accountType = "2"; // change accountType from root-domain("1") to domain-admin("2") + } } array1.push("&accounttype=" + accountType); @@ -268,48 +261,6 @@ } }); } - } - /* - action: function(args) { - var array1 = []; - - var username = args.data.username; - - array1.push("&domainid=" + args.data.domainid); - - if (args.data.account != null && args.data.account.length != 0) { - array1.push("&account=" + args.data.account); - } - - if (args.data.accounttype == "1" && args.data.domainid != rootDomainId) { - args.data.accounttype = "2"; - } - array1.push("&accountType=" + args.data.accounttype); - - if (args.data.timezone != null && args.data.timezone.length != 0) { - array1.push("&timezone=" + args.data.timezone); - } - if (args.data.networkdomain != null && args.data.networkdomain != 0) { - array1.push("&networkDomain=" + args.data.networkdomain); - } - - for (var i = 0; i < username.length; i++) { - $.ajax({ - url: createURL("ldapCreateAccount&username=" + username[i] + array1.join("")), - dataType: "json", - async: false, - success: function(json) { - var item = json.createaccountresponse.account; - args.response.success({ - data: item - }); - }, - error: function(XMLHttpResponse) { - args.response.error(parseXMLHttpResponse(XMLHttpResponse)); - } - }); - } - } - */ + } }; }(cloudStack, jQuery)); \ No newline at end of file diff --git a/ui/scripts/configuration.js b/ui/scripts/configuration.js index 7b2f4e9219..53cd0c3257 100644 --- a/ui/scripts/configuration.js +++ b/ui/scripts/configuration.js @@ -331,8 +331,15 @@ args.response.success({ data: items }); - - + args.$select.change(function() { + var $form = $(this).closest('form'); + var $fields = $form.find('.field'); + if ($(this).val() == "ImplicitDedicationPlanner") { + $form.find('[rel=plannerMode]').css('display', 'block'); + } else { + $form.find('[rel=plannerMode]').hide(); + } + }); } }); } @@ -362,7 +369,7 @@ }, pciDevice: { - label: 'GPU Type', + label: 'GPU', select: function(args) { var items = []; items.push({ @@ -370,40 +377,71 @@ description: '' }); items.push({ - id: 'GPU_Passthrough', - description: 'GPU-Passthrough' + id: 'Group of NVIDIA Corporation GK107GL [GRID K1] GPUs', + description: 'NVIDIA GRID K1' }); items.push({ - id: 'VGPU', - description: 'VGPU' + id: 'Group of NVIDIA Corporation GK104GL [GRID K2] GPUs', + description: 'NVIDIA GRID K2' }); args.response.success({ data: items }); + + var vGpuMap = {}; + vGpuMap['Group of NVIDIA Corporation GK107GL [GRID K1] GPUs'] = ['passthrough', 'GRID K100', 'GRID K120Q', 'GRID K140Q']; + vGpuMap['Group of NVIDIA Corporation GK104GL [GRID K2] GPUs'] = ['passthrough', 'GRID K200', 'GRID K220Q', 'GRID K240Q', 'GRID K260Q']; + args.$select.change(function() { - var $form = $(this).closest('form'); - var $fields = $form.find('.field'); - if (($(this).val() == "") || $(this).val() == "GPU-Passthrough") { - $form.find('[rel=vgpuType]').hide(); - } else if ($(this).val() == "VGPU") { - $form.find('[rel=vgpuType]').css('display', 'block'); + var gpu = $(this).val(); + + if (gpu == '') { + $(this).closest('form').find('.form-item[rel=\"vgpuType\"]').hide(); + } + else { + $(this).closest('form').find('.form-item[rel=\"vgpuType\"]').css('display', 'inline-block'); + + // enable/disable vGPU type options, depending on selected GPU + var $vGpuTypeSelect = $(this).closest('form').find('select[name=vgpuType]'); + var $vGpuTypeOptions = $vGpuTypeSelect.find('option'); + $vGpuTypeOptions.each(function(index) { + var vGpuTypeOption = $(this).val(); + if (vGpuTypeOption == '' || (gpu in vGpuMap && $.inArray(vGpuTypeOption, vGpuMap[gpu]) > -1)) + $(this).attr('disabled', false); + else + $(this).attr('disabled', true); + }); + + //if selected option is disabled, select the first enabled option instead + if ($vGpuTypeSelect.find('option:selected:disabled').length > 0) { + $vGpuTypeSelect.val($vGpuTypeSelect.find('option:enabled:first').val()); + } } }); } }, vgpuType: { - label: 'VGPU Type', + label: 'vGPU Type', + isHidden: true, select: function(args) { var items = []; items.push({ id: '', description: '' }); + items.push({ + id: 'passthrough', + description: 'passthrough' + }); items.push({ id: 'GRID K100', description: 'GRID K100' }); + items.push({ + id: 'GRID K120Q', + description: 'GRID K120Q' + }); items.push({ id: 'GRID K140Q', description: 'GRID K140Q' @@ -412,6 +450,10 @@ id: 'GRID K200', description: 'GRID K200' }); + items.push({ + id: 'GRID K220Q', + description: 'GRID K220Q' + }); items.push({ id: 'GRID K240Q', description: 'GRID K240Q' @@ -467,17 +509,17 @@ //custom fields (begin) if (args.$form.find('.form-item[rel=cpuNumber]').css("display") != "none") { $.extend(data, { - cpuNumber: args.data.cpuNumber + cpuNumber: args.data.cpuNumber }); } if (args.$form.find('.form-item[rel=cpuSpeed]').css("display") != "none") { $.extend(data, { - cpuSpeed: args.data.cpuSpeed + cpuSpeed: args.data.cpuSpeed }); } if (args.$form.find('.form-item[rel=memory]').css("display") != "none") { $.extend(data, { - memory: args.data.memory + memory: args.data.memory }); } //custom fields (end) @@ -499,7 +541,7 @@ array1.push("&serviceofferingdetails[1].value" + "=" + args.data.pciDevice); } - if (args.data.pciDevice == "VGPU") { + if (args.data.vgpuType != "") { array1.push("&serviceofferingdetails[2].key" + "=" + "vgpuType"); array1.push("&serviceofferingdetails[2].value" + "=" + args.data.vgpuType); } @@ -738,9 +780,9 @@ memory: { label: 'label.memory.mb', converter: function(args) { - if (args == undefined) - return ''; - else + if (args == undefined) + return ''; + else return cloudStack.converters.convertBytes(args * 1024 * 1024); } }, @@ -808,6 +850,12 @@ plannerMode: { label: 'Planner Mode' }, + pciDevice: { + label: 'GPU' + }, + vgpuType: { + label: 'vGPU type' + }, tags: { label: 'label.storage.tags' }, @@ -836,11 +884,16 @@ var item = json.listserviceofferingsresponse.serviceoffering[0]; if (item.deploymentplanner != null && item.serviceofferingdetails != null) { - if (item.deploymentplanner == 'ImplicitDedicationPlanner' && item.serviceofferingdetails.ImplicitDedicationMode != null) { - item.plannerMode = item.serviceofferingdetails.ImplicitDedicationMode; - } + if (item.deploymentplanner == 'ImplicitDedicationPlanner' && item.serviceofferingdetails.ImplicitDedicationMode != null) { + item.plannerMode = item.serviceofferingdetails.ImplicitDedicationMode; + } } + if (item.serviceofferingdetails != null) { + item.pciDevice = item.serviceofferingdetails.pciDevice; + item.vgpuType = item.serviceofferingdetails.vgpuType; + } + args.response.success({ actionFitler: serviceOfferingActionfilter, data: item @@ -1288,9 +1341,9 @@ memory: { label: 'label.memory.mb', converter: function(args) { - if (args == undefined) - return ''; - else + if (args == undefined) + return ''; + else return cloudStack.converters.convertBytes(args * 1024 * 1024); } }, @@ -2006,6 +2059,7 @@ var $lbType = args.$form.find('.form-item[rel=lbType]'); var $serviceofferingid = args.$form.find('.form-item[rel=serviceofferingid]'); var $conservemode = args.$form.find('.form-item[rel=conservemode]'); + var $supportsstrechedl2subnet = args.$form.find('.form-item[rel=supportsstrechedl2subnet]'); var $serviceSourceNatRedundantRouterCapabilityCheckbox = args.$form.find('.form-item[rel="service.SourceNat.redundantRouterCapabilityCheckbox"]'); var hasAdvancedZones = false; @@ -2043,7 +2097,7 @@ } else { //Isolated network offering $useVpc.css('display', 'inline-block'); } - var $providers = $useVpcCb.closest('form').find('.dynamic-input select'); + var $providers = $useVpcCb.closest('form').find('.dynamic-input select[name!="service.Connectivity.provider"]'); var $optionsOfProviders = $providers.find('option'); //p.s. Netscaler is supported in both vpc and non-vpc if ($useVpc.is(':visible') && $useVpcCb.is(':checked')) { //*** vpc *** @@ -2153,7 +2207,7 @@ /* - when service(s) has VPC Virtual Router as provider: + when service(s) has VPC Virtual Router as provider: (1) conserve mode is set to unchecked and grayed out. (2) redundant router capability checkbox is set to unchecked and grayed out. (3) remove Firewall service, SecurityGroup service. @@ -2185,43 +2239,43 @@ //CS-16612 show all services regardless of guestIpType(Shared/Isolated) /* - //hide/show service fields ***** (begin) ***** - var serviceFieldsToHide = []; - if($guestTypeField.val() == 'Shared') { //Shared network offering - serviceFieldsToHide = [ - 'service.SourceNat.isEnabled', - 'service.PortForwarding.isEnabled', - 'service.Firewall.isEnabled', - 'service.Vpn.isEnabled' - ]; - if(havingVpcVirtualRouterForAtLeastOneService == true) { //add SecurityGroup to to-hide-list - serviceFieldsToHide.push('service.SecurityGroup.isEnabled'); - } - else { //remove SecurityGroup from to-hide-list - var temp = $.map(serviceFieldsToHide, function(item) { - if (item != 'service.SecurityGroup.isEnabled') { - return item; - } - }); - serviceFieldsToHide = temp; - } - } - else { //Isolated network offering - serviceFieldsToHide = [ - 'service.SecurityGroup.isEnabled' - ]; - if(havingVpcVirtualRouterForAtLeastOneService == true) { //add firewall to to-hide-list - serviceFieldsToHide.push('service.Firewall.isEnabled'); - } - else { //remove firewall from to-hide-list - var temp = $.map(serviceFieldsToHide, function(item) { - if (item != 'service.Firewall.isEnabled') { - return item; - } - }); - serviceFieldsToHide = temp; - } - } + //hide/show service fields ***** (begin) ***** + var serviceFieldsToHide = []; + if($guestTypeField.val() == 'Shared') { //Shared network offering + serviceFieldsToHide = [ + 'service.SourceNat.isEnabled', + 'service.PortForwarding.isEnabled', + 'service.Firewall.isEnabled', + 'service.Vpn.isEnabled' + ]; + if(havingVpcVirtualRouterForAtLeastOneService == true) { //add SecurityGroup to to-hide-list + serviceFieldsToHide.push('service.SecurityGroup.isEnabled'); + } + else { //remove SecurityGroup from to-hide-list + var temp = $.map(serviceFieldsToHide, function(item) { + if (item != 'service.SecurityGroup.isEnabled') { + return item; + } + }); + serviceFieldsToHide = temp; + } + } + else { //Isolated network offering + serviceFieldsToHide = [ + 'service.SecurityGroup.isEnabled' + ]; + if(havingVpcVirtualRouterForAtLeastOneService == true) { //add firewall to to-hide-list + serviceFieldsToHide.push('service.Firewall.isEnabled'); + } + else { //remove firewall from to-hide-list + var temp = $.map(serviceFieldsToHide, function(item) { + if (item != 'service.Firewall.isEnabled') { + return item; + } + }); + serviceFieldsToHide = temp; + } + } */ @@ -2309,6 +2363,13 @@ args.$form.find('.form-item[rel=\"service.StaticNat.associatePublicIP\"]').hide(); args.$form.find('.form-item[rel=\"service.StaticNat.associatePublicIP\"]').find('input[type=checkbox]').attr('checked', false); } + + //StretchedL2Subnet checkbox should be displayed only when 'Connectivity' service is checked + if (args.$form.find('.form-item[rel=\"service.Connectivity.isEnabled\"]').find('input[type=checkbox]').is(':checked')) { + $supportsstrechedl2subnet.css('display', 'inline-block'); + } else { + $supportsstrechedl2subnet.hide(); + } }); args.$form.change(); @@ -2346,7 +2407,7 @@ }); } }, - */ + */ guestIpType: { label: 'label.guest.type', @@ -2682,6 +2743,12 @@ }, //show or hide upon checked services and selected providers above (end) + supportsstrechedl2subnet: { + label: 'label.supportsstrechedl2subnet', + isBoolean: true, + isChecked: false, + isHidden: true + }, conservemode: { label: 'label.conserve.mode', @@ -2784,7 +2851,7 @@ inputData['servicecapabilitylist[' + serviceCapabilityIndex + '].capabilitytype'] = 'lbSchemes'; inputData['servicecapabilitylist[' + serviceCapabilityIndex + '].capabilityvalue'] = 'internal'; serviceCapabilityIndex++; - } + } } else if (value != '') { // Normal data inputData[key] = value; } @@ -2792,7 +2859,7 @@ for (var key1 in inputData) { /* When capability ElasticIp=true is passed to API, if capability associatePublicIP is not passed to API, cloudStack API will assume associatePublicIP=true. - So, UI has to explicitly pass associatePublicIP=false to API if its checkbox is unchecked. */ + So, UI has to explicitly pass associatePublicIP=false to API if its checkbox is unchecked. */ if (inputData[key1] == 'ElasticIp') { //ElasticIp checkbox is checked var associatePublicIPExists = false; for (var key2 in inputData) { @@ -2806,11 +2873,25 @@ inputData['servicecapabilitylist[' + serviceCapabilityIndex + '].service'] = 'StaticNat'; inputData['servicecapabilitylist[' + serviceCapabilityIndex + '].capabilitytype'] = 'associatePublicIP'; inputData['servicecapabilitylist[' + serviceCapabilityIndex + '].capabilityvalue'] = false; //associatePublicIP checkbox is unchecked + serviceCapabilityIndex++; } break; //break key1 for loop } } + //passing supportsstrechedl2subnet's value as capability + for (var k in inputData) { + if (k == 'supportsstrechedl2subnet' && ("Connectivity" in serviceProviderMap)) { + inputData['servicecapabilitylist[' + serviceCapabilityIndex + '].service'] = 'Connectivity'; + inputData['servicecapabilitylist[' + serviceCapabilityIndex + '].capabilitytype'] = 'StretchedL2Subnet'; + inputData['servicecapabilitylist[' + serviceCapabilityIndex + '].capabilityvalue'] = true; + serviceCapabilityIndex++; + break; + } + } + //removing supportsstrechedl2subnet from parameters, it has been set as capability + delete inputData['supportsstrechedl2subnet']; + // Make supported services list inputData['supportedServices'] = $.map(serviceProviderMap, function(value, key) { return key; @@ -3145,6 +3226,10 @@ traffictype: { label: 'label.traffic.type' }, + supportsstrechedl2subnet: { + label: 'label.supportsstrechedl2subnet', + converter: cloudStack.converters.toBooleanText + }, supportedServices: { label: 'label.supported.services' }, @@ -3170,6 +3255,561 @@ return service.name; }).join(', '), + serviceCapabilities: $.map(item.service, function(service) { + return service.provider ? $.map(service.provider, function(capability) { + return service.name + ': ' + capability.name; + }).join(', ') : null; + }).join(', ') + }) + }); + } + }); + } + } + } + } + } + }, + + vpcOfferings: { + type: 'select', + title: 'label.menu.vpc.offerings', + listView: { + id: 'vpcOfferings', + label: 'label.menu.vpc.offerings', + fields: { + name: { + label: 'label.name' + }, + state: { + label: 'label.state', + indicator: { + 'Enabled': 'on', + 'Disabled': 'off', + 'Destroyed': 'off' + } + } + }, + + dataProvider: function(args) { + var data = {}; + listViewDataProvider(args, data); + + $.ajax({ + url: createURL('listVPCOfferings'), + data: data, + success: function(json) { + var items = json.listvpcofferingsresponse.vpcoffering; + args.response.success({ + actionFilter: vpcOfferingActionfilter, + data: items + }); + }, + error: function(data) { + args.response.error(parseXMLHttpResponse(data)); + } + }); + }, + + actions: { + add: { + label: 'label.add.vpc.offering', + + createForm: { + title: 'label.add.vpc.offering', + + preFilter: function(args) { + var hasAdvancedZones = false; + + // Check whether there are any advanced zones + $.ajax({ + url: createURL('listZones'), + data: { + listAll: true + }, + async: false, + success: function(json) { + var zones = json.listzonesresponse.zone; + if (zones != null && zones.length > 0) { + for (var i = 0; i < zones.length; i++) { + if (zones[i].networktype == "Advanced") + hasAdvancedZones = true; + } + } + } + }); + + args.$form.bind('change', function() { //when any field in the dialog is changed + + var $providers = args.$form.find('.dynamic-input select'); + var $optionsOfProviders = $providers.find('option'); + + $providers.each(function() { + //if selected option is disabled, select the first enabled option instead + if ($(this).find('option:selected:disabled').length > 0) { + $(this).val($(this).find('option:first')); + } + }); + }); + + args.$form.change(); + }, + + fields: { + name: { + label: 'label.name', + validation: { + required: true + }, + docID: 'helpVpcOfferingName' + }, + + displayText: { + label: 'label.description', + validation: { + required: true + }, + docID: 'helpVpcOfferingDescription' + }, + + supportedServices: { + label: 'label.supported.services', + + dynamic: function(args) { + var networkServiceObjs = []; + networkServiceObjs.push({ + name: 'Dhcp', + provider: [{name: 'VpcVirtualRouter'}] + }); + networkServiceObjs.push({ + name: 'Dns', + provider: [{name: 'VpcVirtualRouter'}] + }); + networkServiceObjs.push({ + name: 'Lb', + provider: [{name: 'VpcVirtualRouter'}] + }); + networkServiceObjs.push({ + name: 'Gateway', + provider: [{name: 'VpcVirtualRouter'}] + }); + networkServiceObjs.push({ + name: 'StaticNat', + provider: [{name: 'VpcVirtualRouter'}] + }); + networkServiceObjs.push({ + name: 'SourceNat', + provider: [{name: 'VpcVirtualRouter'}] + }); + networkServiceObjs.push({ + name: 'NetworkACL', + provider: [{name: 'VpcVirtualRouter'}] + }); + networkServiceObjs.push({ + name: 'PortForwarding', + provider: [{name: 'VpcVirtualRouter'}] + }); + networkServiceObjs.push({ + name: 'UserData', + provider: [{name: 'VpcVirtualRouter'}] + }); + networkServiceObjs.push({ + name: 'Vpn', + provider: [{name: 'VpcVirtualRouter'}] + }); + + networkServiceObjs.push({ + name: 'Connectivity', + provider: [ + {name: 'NiciraNvp'}, + {name: 'Ovs'}, + {name: 'JuniperContrailVpcRouter'} + ] + }); + + serviceFields = []; + var fields = {}; + $(networkServiceObjs).each(function() { + var serviceName = this.name; + var providerObjs = this.provider; + var serviceDisplayName; + + // Sanitize names + switch (serviceName) { + case 'Vpn': + serviceDisplayName = dictionary['label.vpn']; + break; + case 'Dhcp': + serviceDisplayName = dictionary['label.dhcp']; + break; + case 'Dns': + serviceDisplayName = dictionary['label.dns']; + break; + case 'Lb': + serviceDisplayName = dictionary['label.load.balancer']; + break; + case 'SourceNat': + serviceDisplayName = dictionary['label.source.nat']; + break; + case 'StaticNat': + serviceDisplayName = dictionary['label.static.nat']; + break; + case 'PortForwarding': + serviceDisplayName = dictionary['label.port.forwarding']; + break; + case 'UserData': + serviceDisplayName = dictionary['label.user.data']; + break; + default: + serviceDisplayName = serviceName; + break; + } + + var id = { + isEnabled: 'service' + '.' + serviceName + '.' + 'isEnabled', + capabilities: 'service' + '.' + serviceName + '.' + 'capabilities', + provider: 'service' + '.' + serviceName + '.' + 'provider' + }; + + serviceCheckboxNames.push(id.isEnabled); + + fields[id.isEnabled] = { + label: serviceDisplayName, + isBoolean: true, + }; + + serviceFields.push(id.isEnabled); + + fields[id.provider] = { + label: serviceDisplayName + ' Provider', + isHidden: true, + dependsOn: id.isEnabled, + select: function(args) { + var items = []; + $(providerObjs).each(function() { + items.push({ + id: this.name, + description: this.name + }); + }); + args.response.success({ + data: items + }); + } + } + }); + + args.response.success({ + fields: fields + }); + } + }, //end of supportedservices field + + "service.Connectivity.regionLevelVpcCapabilityCheckbox": { + label: 'label.regionlevelvpc', + isHidden: true, + dependsOn: 'service.Connectivity.isEnabled', + isBoolean: true + }, + + "service.Connectivity.distributedRouterCapabilityCheckbox": { + label: 'label.distributedrouter', + isHidden: true, + dependsOn: 'service.Connectivity.isEnabled', + isBoolean: true + } + },//end of fields + }, //end of createForm + + action: function(args) { + var formData = args.data; + var inputData = {}; + var serviceProviderMap = {}; + var serviceCapabilityIndex = 0; + + $.each(formData, function(key, value) { + var serviceData = key.split('.'); + + if (serviceData.length > 1) { + if (serviceData[0] == 'service' && + serviceData[2] == 'isEnabled' && + value == 'on') { // Services field + + serviceProviderMap[serviceData[1]] = formData[ + 'service.' + serviceData[1] + '.provider' + ]; + } else if ((key == 'service.Connectivity.regionLevelVpcCapabilityCheckbox') && ("Connectivity" in serviceProviderMap)) { + inputData['serviceCapabilityList[' + serviceCapabilityIndex + '].service'] = 'Connectivity'; + inputData['serviceCapabilityList[' + serviceCapabilityIndex + '].capabilitytype'] = "RegionLevelVpc"; + inputData['serviceCapabilityList[' + serviceCapabilityIndex + '].capabilityvalue'] = true; + serviceCapabilityIndex++; + } else if ((key == 'service.Connectivity.distributedRouterCapabilityCheckbox') && ("Connectivity" in serviceProviderMap)) { + inputData['servicecapabilitylist[' + serviceCapabilityIndex + '].service'] = 'Connectivity'; + inputData['servicecapabilitylist[' + serviceCapabilityIndex + '].capabilitytype'] = 'DistributedRouter'; + inputData['servicecapabilitylist[' + serviceCapabilityIndex + '].capabilityvalue'] = true; + serviceCapabilityIndex++; + } + } else if (value != '') { // Normal data + inputData[key] = value; + } + }); + + // Make supported services list + inputData['supportedServices'] = $.map(serviceProviderMap, function(value, key) { + return key; + }).join(','); + + + // Make service provider map + var serviceProviderIndex = 0; + $.each(serviceProviderMap, function(key, value) { + inputData['serviceProviderList[' + serviceProviderIndex + '].service'] = key; + inputData['serviceProviderList[' + serviceProviderIndex + '].provider'] = value; + serviceProviderIndex++; + }); + + $.ajax({ + url: createURL('createVPCOffering'), + data: inputData, + dataType: 'json', + async: true, + success: function(data) { + var item = data.createvpcofferingresponse; + + args.response.success({ + data: item, + actionFilter: vpcOfferingActionfilter + }); + }, + + error: function(data) { + args.response.error(parseXMLHttpResponse(data)); + } + }); + }, + + notification: { + poll: function(args) { + args.complete({ + actionFilter: vpcOfferingActionfilter + }); + } + }, + + messages: { + notification: function(args) { + return 'Added VPC offering'; + } + } + } + }, + + reorder: cloudStack.api.actions.sort('updateVPCOffering', 'vpcOfferings'), + + detailView: { + name: 'label.vpc.offering.details', + actions: { + edit: { + label: 'label.edit', + action: function(args) { + var data = { + id: args.context.vpcOfferings[0].id, + name: args.data.name, + displaytext: args.data.displaytext, + availability: args.data.availability + }; + + $.ajax({ + url: createURL('updateVPCOffering'), + data: data, + success: function(json) { + var item = json.updatevpcofferingresponse.vpcoffering; + args.response.success({ + data: item + }); + }, + error: function(data) { + args.response.error(parseXMLHttpResponse(data)); + } + }); + } + }, + + enable: { + label: 'label.enable.vpc.offering', + messages: { + confirm: function(args) { + return 'message.confirm.enable.vpc.offering'; + }, + notification: function(args) { + return 'message.enabling.vpc.offering'; + } + }, + action: function(args) { + $.ajax({ + url: createURL("updateVPCOffering&id=" + args.context.vpcOfferings[0].id + "&state=Enabled"), + dataType: "json", + async: true, + success: function(json) { + var item = json.updatevpcofferingresponse.vpcoffering; + args.response.success(); + }, + error: function(data) { + args.response.error(parseXMLHttpResponse(data)); + } + }); + }, + notification: { + poll: function(args) { + args.complete({ + data: { + state: 'Enabled' + } + }); + } + } + }, + + disable: { + label: 'label.disable.vpc.offering', + messages: { + confirm: function(args) { + return 'message.confirm.disable.vpc.offering'; + }, + notification: function(args) { + return 'message.disabling.vpc.offering'; + } + }, + action: function(args) { + $.ajax({ + url: createURL("updateVPCOffering&id=" + args.context.vpcOfferings[0].id + "&state=Disabled"), + dataType: "json", + async: true, + success: function(json) { + var item = json.updatevpcofferingresponse.vpcoffering; + args.response.success(); + }, + error: function(data) { + args.response.error(parseXMLHttpResponse(data)); + } + }); + }, + notification: { + poll: function(args) { + args.complete({ + data: { + state: 'Disabled' + } + }); + } + } + }, + + remove: { + label: 'label.remove.vpc.offering', + action: function(args) { + $.ajax({ + url: createURL('deleteVPCOffering'), + data: { + id: args.context.vpcOfferings[0].id + }, + success: function(json) { + args.response.success(); + }, + error: function(data) { + args.response.error(parseXMLHttpResponse(data)); + } + }); + }, + messages: { + confirm: function() { + return 'message.confirm.remove.vpc.offering'; + }, + notification: function() { + return 'label.remove.vpc.offering'; + } + }, + notification: { + poll: function(args) { + args.complete({ + data: { + state: 'Destroyed' + }, + actionFilter: vpcOfferingActionfilter + }); + } + } + } + }, + tabs: { + details: { + title: 'label.details', + + fields: [{ + name: { + label: 'label.name', + isEditable: true, + validation: { + required: true + } + } + }, { + id: { + label: 'label.id' + }, + displaytext: { + label: 'label.description', + isEditable: true, + validation: { + required: true + } + }, + state: { + label: 'label.state' + }, + + isdefault: { //created by system by default + label: 'label.created.by.system', + converter: cloudStack.converters.toBooleanText + }, + + supportedServices: { + label: 'label.supported.services' + }, + serviceCapabilities: { + label: 'label.service.capabilities' + }, + distributedvpcrouter: { + label: 'label.vpc.distributedvpcrouter', + converter: cloudStack.converters.toBooleanText + }, + supportsregionLevelvpc: { + label: 'label.vpc.supportsregionlevelvpc', + converter: cloudStack.converters.toBooleanText + }, + serviceCapabilities: { + label: 'label.service.capabilities' + }, + tags: { + label: 'label.tags' + } + + }], + + dataProvider: function(args) { + $.ajax({ + url: createURL('listVPCOfferings&id=' + args.context.vpcOfferings[0].id), + dataType: "json", + async: true, + success: function(json) { + var item = json.listvpcofferingsresponse.vpcoffering[0]; + args.response.success({ + actionFilter: vpcOfferingActionfilter, + data: $.extend(item, { + supportedServices: $.map(item.service, function(service) { + return service.name; + }).join(', '), + serviceCapabilities: $.map(item.service, function(service) { return service.provider ? $.map(service.provider, function(capability) { return service.name + ': ' + capability.name; @@ -3186,7 +3826,8 @@ } } } - }; +} + var serviceOfferingActionfilter = function(args) { var jsonObj = args.context.item; @@ -3232,4 +3873,24 @@ return allowedActions; }; + var vpcOfferingActionfilter = function(args) { + var jsonObj = args.context.item; + + if (jsonObj.state == 'Destroyed') + return []; + + var allowedActions = []; + allowedActions.push("edit"); + + if (jsonObj.state == "Enabled") + allowedActions.push("disable"); + else if (jsonObj.state == "Disabled") + allowedActions.push("enable"); + + if (jsonObj.isdefault == false) + allowedActions.push("remove"); + + return allowedActions; + }; + })(cloudStack, jQuery); diff --git a/ui/scripts/docs.js b/ui/scripts/docs.js index 32237f318e..abda45b8a2 100755 --- a/ui/scripts/docs.js +++ b/ui/scripts/docs.js @@ -627,7 +627,7 @@ cloudStack.docs = { externalLink: '' }, helpPrimaryStorageProtocol: { - desc: 'For XenServer, choose NFS, iSCSI, or PreSetup. For KVM, choose NFS or SharedMountPoint. For vSphere, choose VMFS (iSCSI or FiberChannel) or NFS.', + desc: 'For XenServer, choose NFS, iSCSI, or PreSetup. For KVM, choose NFS or SharedMountPoint. For vSphere, choose VMFS (iSCSI or FiberChannel) or NFS. For Hyper-V, choose SMB/CIFS', externalLink: '' }, helpPrimaryStorageServer: { @@ -1197,7 +1197,7 @@ cloudStack.docs = { externalLink: '' }, helpUploadVolumeFormat: { - desc: 'The disk image format of the volume. XenServer is VHD, VMware is OVA, and KVM is QCOW2.', + desc: 'The disk image format of the volume. XenServer is VHD, VMware is OVA, and KVM is QCOW2. Hyper-V is VHD.', externalLink: '' }, helpUploadVolumeURL: { @@ -1211,5 +1211,13 @@ cloudStack.docs = { helpLdapGroupName: { desc: 'The group name from which you want to import LDAP users', externalLink: '' + }, + helpVpcOfferingName: { + desc: 'Any desired name for the VPC offering', + externalLink: '' + }, + helpVpcOfferingDescription: { + desc: 'A short description of the offering that can be displayed to users', + externalLink: '' } }; diff --git a/ui/scripts/instanceWizard.js b/ui/scripts/instanceWizard.js index 5c04d0e145..9df6eccdff 100644 --- a/ui/scripts/instanceWizard.js +++ b/ui/scripts/instanceWizard.js @@ -22,6 +22,12 @@ var step6ContainerType = 'nothing-to-select'; //'nothing-to-select', 'select-network', 'select-security-group', 'select-advanced-sg'(advanced sg-enabled zone) cloudStack.instanceWizard = { + //min disk offering size when custom disk size is used + minDiskOfferingSize: function() { + return g_capabilities.customdiskofferingminsize; + }, + + //max disk offering size when custom disk size is used maxDiskOfferingSize: function() { return g_capabilities.customdiskofferingmaxsize; }, @@ -292,6 +298,9 @@ selectedHypervisor = args.currentData.hypervisorid; } + // if the user is leveraging a template, then we can show custom IOPS, if applicable + var canShowCustomIopsForServiceOffering = (args.currentData["select-template"] != "select-iso" ? true : false); + $.ajax({ url: createURL("listServiceOfferings&issystem=false"), dataType: "json", @@ -299,6 +308,7 @@ success: function(json) { serviceOfferingObjs = json.listserviceofferingsresponse.serviceoffering; args.response.success({ + canShowCustomIops: canShowCustomIopsForServiceOffering, customFlag: 'iscustomized', //customFlag: 'offerha', //for testing only customIopsFlag: 'iscustomizediops', @@ -322,9 +332,11 @@ args.response.success({ required: isRequred, customFlag: 'iscustomized', // Field determines if custom slider is shown + customIopsDoFlag: 'iscustomizediops', data: { diskOfferings: diskOfferingObjs - } + }, + multiDisk: false }); } }); @@ -657,6 +669,20 @@ size : args.data.size }); } + + if (selectedDiskOfferingObj.iscustomizediops == true) { + if (args.$wizard.find('input[name=disk-min-iops-do]').val().length > 0) { + $.extend(deployVmData, { + 'details[0].minIopsDo' : args.$wizard.find('input[name=disk-min-iops-do]').val() + }); + } + + if (args.$wizard.find('input[name=disk-max-iops-do]').val().length > 0) { + $.extend(deployVmData, { + 'details[0].maxIopsDo' : args.$wizard.find('input[name=disk-max-iops-do]').val() + }); + } + } } //step 5: select an affinity group diff --git a/ui/scripts/instances.js b/ui/scripts/instances.js index 10d25917f9..d219e6dc04 100644 --- a/ui/scripts/instances.js +++ b/ui/scripts/instances.js @@ -148,13 +148,15 @@ }, fields: { name: { - label: 'label.name' + label: 'label.name', + truncate: true }, instancename: { label: 'label.internal.name' }, displayname: { - label: 'label.display.name' + label: 'label.display.name', + truncate: true }, zonename: { label: 'label.zone.name' @@ -660,15 +662,15 @@ poll: pollAsyncJobResult } }, - restore: { - label: 'label.action.restore.instance', - compactLabel: 'label.restore', + recover: { + label: 'label.recover.vm', + compactLabel: 'label.recover.vm', messages: { confirm: function(args) { - return 'message.action.restore.instance'; + return 'message.recover.vm'; }, notification: function(args) { - return 'label.action.restore.instance'; + return 'label.recover.vm'; } }, action: function(args) { @@ -694,15 +696,14 @@ } } }, - reset: { - label: 'label.resetVM', - textLabel: 'label.resetVM', + reinstall: { + label: 'label.reinstall.vm', messages: { confirm: function(args) { - return 'message.restoreVM'; + return 'message.reinstall.vm'; }, notification: function(args) { - return 'label.resetVM'; + return 'label.reinstall.vm'; }, complete: function(args) { if (args.password != null && args.password.length > 0) @@ -2198,7 +2199,7 @@ if (jsonObj.state == 'Destroyed') { if (isAdmin() || isDomainAdmin()) { - allowedActions.push("restore"); + allowedActions.push("recover"); } if (isAdmin() || isDomainAdmin()) allowedActions.push("expunge"); @@ -2208,7 +2209,7 @@ if (jsonObj.hypervisor != 'KVM' || g_kvmsnapshotenabled == true) allowedActions.push("snapshot"); allowedActions.push("destroy"); - allowedActions.push("reset"); + allowedActions.push("reinstall"); //when userVm is running, scaleUp is not supported for KVM if (jsonObj.hypervisor != 'KVM') { @@ -2234,7 +2235,7 @@ allowedActions.push("edit"); allowedActions.push("start"); allowedActions.push("destroy"); - allowedActions.push("reset"); + allowedActions.push("reinstall"); if (jsonObj.hypervisor != 'KVM' || g_kvmsnapshotenabled == true) allowedActions.push("snapshot"); allowedActions.push("scaleUp"); //when vm is stopped, scaleUp is supported for all hypervisors diff --git a/ui/scripts/network.js b/ui/scripts/network.js index f82a295aee..9d5fb79b3c 100755 --- a/ui/scripts/network.js +++ b/ui/scripts/network.js @@ -40,7 +40,7 @@ var instance = args.context.instances[0]; var network = args.context.networks[0]; - if (args.context.ipAddresses[0].isportable) { + if (args.context.ipAddresses[0].isportable) { //portable IP which has multiple NICs. Each NIC has a different network ID. $.ajax({ url: createURL('listNics'), data: { @@ -49,72 +49,73 @@ success: function(json) { var nics = json.listnicsresponse.nic; var ipSelection = []; - - $(nics).map(function(index, nic) { - var ips = nic.secondaryip ? nic.secondaryip : []; + + $(nics).map(function(index, nic) { + var primaryIp = nic.ipaddress; + var secondaryIps = nic.secondaryip ? nic.secondaryip : []; var prefix = '[NIC ' + (index + 1) + '] '; // Add primary IP as default ipSelection.push({ id: nic.networkid + ',-1', - description: prefix + nic.ipaddress + ' (Primary)' + description: prefix + primaryIp + ' (Primary)' }); // Add secondary IPs - $(ips).map(function(index, ip) { + $(secondaryIps).map(function(index, secondaryIp) { ipSelection.push({ - id: nic.networkid + ',' + ip.ipaddress, - description: prefix + ip.ipaddress + id: nic.networkid + ',' + secondaryIp.ipaddress, + description: prefix + secondaryIp.ipaddress }); }); }); - args.response.success({ data: ipSelection }); } }); - - return; + + } else { //non-portable IP which has only one NIC + /* + var nic = $.grep(instance.nic, function(nic) { + return nic.networkid == network.id; + })[0]; + */ + + // Get NIC IPs + $.ajax({ + url: createURL('listNics'), + data: { + virtualmachineid: instance.id, + nicId: instance.nic[0].id + }, + success: function(json) { + var nic = json.listnicsresponse.nic[0]; + var primaryIp = nic.ipaddress; + var secondaryIps = nic.secondaryip ? nic.secondaryip : []; + var ipSelection = []; + + // Add primary IP as default + ipSelection.push({ + id: -1, + description: primaryIp + ' (Primary)' + }); + + // Add secondary IPs + $(secondaryIps).map(function(index, secondaryIp) { + ipSelection.push({ + id: secondaryIp.ipaddress, + description: secondaryIp.ipaddress + }); + }); + + args.response.success({ + data: ipSelection + }); + } + }); } - - var nic = $.grep(instance.nic, function(nic) { - return nic.networkid == network.id; - })[0]; - - // Get NIC IPs - $.ajax({ - url: createURL('listNics'), - data: { - virtualmachineid: instance.id, - nicId: nic.id - }, - success: function(json) { - var nic = json.listnicsresponse.nic[0]; - var ips = nic.secondaryip ? nic.secondaryip : []; - var ipSelection = []; - - // Add primary IP as default - ipSelection.push({ - id: -1, - description: nic.ipaddress + ' (Primary)' - }); - - // Add secondary IPs - $(ips).map(function(index, ip) { - ipSelection.push({ - id: ip.ipaddress, - description: ip.ipaddress - }); - }); - - - args.response.success({ - data: ipSelection - }); - } - }) }; //value of Primary IP in subselect dropdown is itself (not -1), for multiple VM selection (API parameter vmidipmap), e.g. assignToLoadBalancerRule API. @@ -122,7 +123,7 @@ var instance = args.context.instances[0]; var network = args.context.networks[0]; - if (args.context.ipAddresses[0].isportable) { + if (args.context.ipAddresses[0].isportable) { //portable IP which has multiple NICs. Each NIC has a different network ID. $.ajax({ url: createURL('listNics'), data: { @@ -132,71 +133,80 @@ var nics = json.listnicsresponse.nic; var ipSelection = []; + //portable IP has multiple NICs. Each NIC has a different network ID. $(nics).map(function(index, nic) { - var ips = nic.secondaryip ? nic.secondaryip : []; + var primaryIp = nic.ipaddress; + var secondaryIps = nic.secondaryip ? nic.secondaryip : []; var prefix = '[NIC ' + (index + 1) + '] '; // Add primary IP as default ipSelection.push({ - id: nic.networkid + ',' + nic.ipaddress, - description: prefix + nic.ipaddress + ' (Primary)' + id: nic.networkid + ',' + primaryIp, + description: prefix + primaryIp + ' (Primary)' }); // Add secondary IPs - $(ips).map(function(index, ip) { + $(secondaryIps).map(function(index, secondaryIp) { ipSelection.push({ - id: nic.networkid + ',' + ip.ipaddress, - description: prefix + ip.ipaddress + id: nic.networkid + ',' + secondaryIp.ipaddress, + description: prefix + secondaryIp.ipaddress }); }); - }); - - + }); + args.response.success({ data: ipSelection }); } - }); + }); - return; - } - - var nic = $.grep(instance.nic, function(nic) { - return nic.networkid == network.id; - })[0]; - - // Get NIC IPs - $.ajax({ - url: createURL('listNics'), - data: { - virtualmachineid: instance.id, - nicId: nic.id - }, - success: function(json) { - var nic = json.listnicsresponse.nic[0]; - var ips = nic.secondaryip ? nic.secondaryip : []; - var ipSelection = []; - - // Add primary IP as default - ipSelection.push({ - id: nic.ipaddress, - description: nic.ipaddress + ' (Primary)' - }); + } else { //non-portable IP which has only one NIC + /* + var nic = $.grep(instance.nic, function(nic) { + return nic.networkid == network.id; + })[0]; + */ + + // Get NIC IPs + $.ajax({ + url: createURL('listNics'), + data: { + virtualmachineid: instance.id, + nicId: instance.nic[0].id + }, + success: function(json) { + var nic = json.listnicsresponse.nic[0]; + var primaryIp = nic.ipaddress; + var secondaryIps = nic.secondaryip ? nic.secondaryip : []; + var ipSelection = []; + var existingIps = $(args.context.subItemData).map( + function(index, item) { return item.itemIp; } + ); - // Add secondary IPs - $(ips).map(function(index, ip) { - ipSelection.push({ - id: ip.ipaddress, - description: ip.ipaddress - }); - }); + // Add primary IP as default + if ($.inArray(primaryIp, existingIps) == -1) { + ipSelection.push({ + id: primaryIp, + description: primaryIp + ' (Primary)' + }); + } + // Add secondary IPs + $(secondaryIps).map(function(index, secondaryIp) { + if ($.inArray(secondaryIp.ipaddress, existingIps) == -1) { + ipSelection.push({ + id: secondaryIp.ipaddress, + description: secondaryIp.ipaddress + }); + } + }); - args.response.success({ - data: ipSelection - }); - } - }) + args.response.success({ + data: ipSelection + }); + } + }); + } }; var ipChangeNotice = function() { @@ -2131,12 +2141,15 @@ $.ajax({ url: createURL('listRegions'), success: function(json) { + var selectedRegionName = $(".region-switcher .title").text(); + if ( selectedRegionName == undefined || selectedRegionName.length == 0) { + selectedRegionName = "Local"; + } var items = json.listregionsresponse.region; if(items != null) { - for(var i = 0; i < items.length; i++) { - var region = items[0]; - if(region.name == 'Local') { - if(region.portableipserviceenabled == true) { + for(var i = 0; i < items.length; i++) { + if(items[i].name == selectedRegionName) { + if(items[i].portableipserviceenabled == true) { args.$form.find('.form-item[rel=isportable]').css('display', 'inline-block'); } else { args.$form.find('.form-item[rel=isportable]').hide(); @@ -3317,16 +3330,14 @@ filters: false, //when server-side change of adding new parameter "vmidipmap" to assignToLoadBalancerRule API is in, uncomment the following commented 4 lines. - /* subselect: { - label: 'label.use.vm.ip', + isMultiple: true, + label: 'label.use.vm.ips', dataProvider: multipleVmSecondaryIPSubselect }, - */ - + dataProvider: function(args) { - var itemData = $.isArray(args.context.multiRule) && args.context.multiRule[0]['_itemData'] ? - args.context.multiRule[0]['_itemData'] : []; + var itemData = $.isArray(args.context.multiRule) && args.context.subItemData ? args.context.subItemData : []; var networkid; if ('vpc' in args.context) @@ -3375,6 +3386,42 @@ return item.id == instance.id; }).length; + // Check if there are any remaining IPs + if (!notExisting) { + $.ajax({ + url: createURL('listNics'), + async: false, + data: { + virtualmachineid: instance.id + }, + success: function(json) { + var nics = json.listnicsresponse.nic; + + $(nics).map(function (index, nic) { + if (nic.secondaryip) { + var targetIPs = $(nic.secondaryip).map(function (index, sip) { + return sip.ipaddress; + }); + + var lbIPs = $(itemData).map(function(index, item) { return item.itemIp; }); + + targetIPs.push(nic.ipaddress); + + var matchingIPs = $.grep(targetIPs, function(item) { + return $.inArray(item, lbIPs) > -1; + }); + + if (targetIPs.length - matchingIPs.length) { + notExisting = true; + + return false; + } + } + }); + } + }) + } + return nonAutoScale && isActiveState && notExisting; } ); @@ -3578,6 +3625,7 @@ var stickyData = $.extend(true, {}, args.data.sticky); + //***** create new LB rule > Add VMs ***** $.ajax({ url: createURL('createLoadBalancerRule'), data: data, @@ -3588,40 +3636,48 @@ var jobID = data.createloadbalancerruleresponse.jobid; var lbID = data.createloadbalancerruleresponse.id; + var inputData = { + id: data.createloadbalancerruleresponse.id + }; + /* var inputData = { id: data.createloadbalancerruleresponse.id, virtualmachineids: $.map(itemData, function(elem) { return elem.id; }).join(',') }; - //when server-side change of adding new parameter "vmidipmap" to assignToLoadBalancerRule API is in, remove the above 6 lines and uncomment the commented section below. + */ + //virtualmachineids parameter has been replaced with vmidipmap parameter, so comment out the 6 lines above. - /* - var inputData = { - id: data.createloadbalancerruleresponse.id - }; - if (args.context.ipAddresses[0].isportable) { - if (args.itemData != null) { - for (var k = 0; k < args.itemData.length; k++) { - inputData['vmidipmap[' + k + '].vmid'] = args.itemData[k].id; - inputData['vmidipmap[' + k + '].ip'] = args.itemData[k]._subselect.split(',')[1]; - } - } - - } else { - if (args.itemData != null) { - for (var k = 0; k < args.itemData.length; k++) { - inputData['vmidipmap[' + k + '].vmid'] = args.itemData[k].id; - inputData['vmidipmap[' + k + '].ip'] = args.itemData[k]._subselect; - } - } - } - */ - //http://localhost:8080/client/api?command=assignToLoadBalancerRule&response=json&sessionkey=M6I8h6gBXuEMeBMb4pjSDTjYprc=&id=da97bae5-9389-4bbb-aef3-ccca8408a852&vmidipmap[0].vmid=667d1450-3cd9-4670-b22e-aebb77f521a3&vmidipmap[0].ip=10.1.1.23&vmidipmap[1].vmid=5128d30b-7747-4a05-bdbc-6262191d7642&vmidipmap[1].ip=10.1.1.82&vmidipmap[2].vmid=48c61d00-28d2-4048-aed5-774289470804&vmidipmap[2].ip=10.1.1.5&_=1393451067671 - - + /* + * e.g. first VM(xxx) has two IPs(10.1.1.~), second VM(yyy) has three IPs(10.2.2.~): + * vmidipmap[0].vmid=xxx vmidipmap[0].vmip=10.1.1.11 + * vmidipmap[1].vmid=xxx vmidipmap[1].vmip=10.1.1.12 + * vmidipmap[2].vmid=yyy vmidipmap[2].vmip=10.2.2.77 + * vmidipmap[3].vmid=yyy vmidipmap[3].vmip=10.2.2.78 + * vmidipmap[4].vmid=yyy vmidipmap[4].vmip=10.2.2.79 + */ + var selectedVMs = args.itemData; + if (selectedVMs != null) { + var vmidipmapIndex = 0; + for (var vmIndex = 0; vmIndex < selectedVMs.length; vmIndex++) { + var selectedIPs = selectedVMs[vmIndex]._subselect; + for (var ipIndex = 0; ipIndex < selectedIPs.length; ipIndex++) { + inputData['vmidipmap[' + vmidipmapIndex + '].vmid'] = selectedVMs[vmIndex].id; + + if (args.context.ipAddresses[0].isportable) { + inputData['vmidipmap[' + vmidipmapIndex + '].vmip'] = selectedIPs[ipIndex].split(',')[1]; + } else { + inputData['vmidipmap[' + vmidipmapIndex + '].vmip'] = selectedIPs[ipIndex]; + } + + vmidipmapIndex++; + } + } + } + $.ajax({ url: createURL('assignToLoadBalancerRule'), data: inputData, @@ -3731,17 +3787,44 @@ }, itemActions: { - add: { + //***** update existing LB rule > Add VMs ***** + add: { label: 'label.add.vms.to.lb', action: function(args) { + var inputData = { + id: args.multiRule.id + }; + + /* + * e.g. first VM(xxx) has two IPs(10.1.1.~), second VM(yyy) has three IPs(10.2.2.~): + * vmidipmap[0].vmid=xxx vmidipmap[0].vmip=10.1.1.11 + * vmidipmap[1].vmid=xxx vmidipmap[1].vmip=10.1.1.12 + * vmidipmap[2].vmid=yyy vmidipmap[2].vmip=10.2.2.77 + * vmidipmap[3].vmid=yyy vmidipmap[3].vmip=10.2.2.78 + * vmidipmap[4].vmid=yyy vmidipmap[4].vmip=10.2.2.79 + */ + var selectedVMs = args.data; + if (selectedVMs != null) { + var vmidipmapIndex = 0; + for (var vmIndex = 0; vmIndex < selectedVMs.length; vmIndex++) { + var selectedIPs = selectedVMs[vmIndex]._subselect; + for (var ipIndex = 0; ipIndex < selectedIPs.length; ipIndex++) { + inputData['vmidipmap[' + vmidipmapIndex + '].vmid'] = selectedVMs[vmIndex].id; + + if (args.context.ipAddresses[0].isportable) { + inputData['vmidipmap[' + vmidipmapIndex + '].vmip'] = selectedIPs[ipIndex].split(',')[1]; + } else { + inputData['vmidipmap[' + vmidipmapIndex + '].vmip'] = selectedIPs[ipIndex]; + } + + vmidipmapIndex++; + } + } + } + $.ajax({ url: createURL('assignToLoadBalancerRule'), - data: { - id: args.multiRule.id, - virtualmachineids: $.map(args.data, function(elem) { - return elem.id; - }).join(',') - }, + data: inputData, success: function(json) { args.response.success({ notification: { @@ -3764,13 +3847,24 @@ }, destroy: { label: 'label.remove.vm.from.lb', - action: function(args) { - $.ajax({ - url: createURL('removeFromLoadBalancerRule'), - data: { + action: function(args) { + var inputData; + if (args.item.itemIp == undefined) { + inputData = { id: args.multiRule.id, virtualmachineids: args.item.id - }, + }; + } else { + inputData = { + id: args.multiRule.id, + "vmidipmap[0].vmid": args.item.id, + "vmidipmap[0].vmip": args.item.itemIp + }; + } + + $.ajax({ + url: createURL('removeFromLoadBalancerRule'), + data: inputData, success: function(json) { args.response.success({ notification: { @@ -3804,31 +3898,30 @@ dataType: 'json', async: true, success: function(data) { - var loadBalancerData = data.listloadbalancerrulesresponse.loadbalancerrule; - var loadVMTotal = loadBalancerData ? loadBalancerData.length : 0; - var loadVMCurrent = 0; - - $(loadBalancerData).each(function() { - loadVMCurrent++; - var item = this; + var loadbalancerrules = data.listloadbalancerrulesresponse.loadbalancerrule; + + $(loadbalancerrules).each(function() { + var lbRule = this; var stickyData = {}; - var lbInstances = []; + + //var lbInstances = []; + var itemData = []; // Passing _hideFields array will disable specified fields for this row - //item._hideFields = ['autoScale']; + //lbRule._hideFields = ['autoScale']; $.ajax({ url: createURL('listAutoScaleVmGroups'), data: { listAll: true, - lbruleid: item.id + lbruleid: lbRule.id }, async: false, success: function(json) { if (json.listautoscalevmgroupsresponse.autoscalevmgroup != null && json.listautoscalevmgroupsresponse.autoscalevmgroup.length > 0) { //from 'autoScale' button - item._hideFields = ['add-vm']; + lbRule._hideFields = ['add-vm']; } else { //from 'add-vm' button - item._hideFields = ['autoScale']; + lbRule._hideFields = ['autoScale']; } } }); @@ -3839,7 +3932,7 @@ async: false, data: { listAll: true, - lbruleid: item.id + lbruleid: lbRule.id }, success: function(json) { var stickyPolicy = json.listlbstickinesspoliciesresponse.stickinesspolicies ? @@ -3855,12 +3948,12 @@ methodname: stickyPolicy.methodname, stickyName: stickyPolicy.name, id: stickyPolicy.id, - lbRuleID: item.id + lbRuleID: lbRule.id }; $.extend(stickyData, stickyPolicy.params); } else { stickyData = { - lbRuleID: item.id + lbRuleID: lbRule.id }; } }, @@ -3878,42 +3971,62 @@ async: false, data: { listAll: true, - id: item.id + lbvmips: true, + id: lbRule.id }, success: function(data) { - lbInstances = data.listloadbalancerruleinstancesresponse.loadbalancerruleinstance ? - data.listloadbalancerruleinstancesresponse.loadbalancerruleinstance : []; - - $(lbInstances).each(function() { - if (this.displayname.indexOf('AutoScale-LB-') > -1) //autoscale VM is not allowed to be deleted manually. So, hide destroy button - this._hideActions = ['destroy']; - - if (this.servicestate) { - this._itemStateLabel = 'label.service.state'; - this._itemState = this.servicestate; - } - }); + //when "lbvmips: true" is not passed to API + //lbVMs = data.listloadbalancerruleinstancesresponse.loadbalancerruleinstance; + + //when "lbvmips: true" is passed to API + lbrulevmidips = data.listloadbalancerruleinstancesresponse.lbrulevmidip; + + if (lbrulevmidips != null) { + for (var k = 0; k < lbrulevmidips.length; k++) { + var lbrulevmidip = lbrulevmidips[k]; + var lbVM = lbrulevmidip.loadbalancerruleinstance; + if (lbVM.displayname.indexOf('AutoScale-LB-') > -1) //autoscale VM is not allowed to be deleted manually. So, hide destroy button + lbVM._hideActions = ['destroy']; + + if (lbVM.servicestate) { + lbVM._itemStateLabel = 'label.service.state'; + lbVM._itemState = lbVM.servicestate; + } + + if (lbrulevmidip.lbvmipaddresses != null) { + for (var m = 0 ; m < lbrulevmidip.lbvmipaddresses.length; m++) { + var ip = lbrulevmidip.lbvmipaddresses[m]; + itemData.push($.extend({}, lbVM, { + itemIp: ip + })); + } + } else { + itemData.push(lbVM); + } + } + } }, error: function(data) { args.response.error(parseXMLHttpResponse(data)); } - }); + }); - $.extend(item, { + $.extend(lbRule, { _itemName: 'name', - _itemData: lbInstances, + _itemIp: 'itemIp', + _itemData: itemData, _maxLength: { name: 7 }, sticky: stickyData, autoScale: { - lbRuleID: item.id + lbRuleID: lbRule.id } }); }); args.response.success({ - data: loadBalancerData + data: loadbalancerrules }); } }); @@ -5107,7 +5220,16 @@ url: createURL('listVPCs'), data: data, success: function(json) { - var items = json.listvpcsresponse.vpc; + var items = json.listvpcsresponse.vpc ? json.listvpcsresponse.vpc : { }; + + //If we are coming from Home > Regions, show only regional vpcs + if (args.context.regions) + items = $.grep( + items, + function (vpc, i) { + return vpc.regionlevelvpc; + }); + args.response.success({ data: items }); @@ -5201,30 +5323,49 @@ data: items }); } + }, + vpcoffering: { + label: 'label.vpc.offering', + validation: { + required: true + }, + + select: function(args) { + var data = { + listAll: true + }; + $.ajax({ + url: createURL('listVPCOfferings'), + data: { + listAll: true + }, + success: function(json) { + var offerings = json.listvpcofferingsresponse.vpcoffering ? json.listvpcofferingsresponse.vpcoffering : []; + var filteredofferings = $.grep(offerings, function(offering) { + return offering.state == 'Enabled'; + }); + args.response.success({ + data: $.map(filteredofferings, function(vpco) { + return { + id: vpco.id, + description: vpco.name + }; + }) + }); + } + }); + } } } }, action: function(args) { - var vpcOfferingName; - if (args.data.publicLoadBalancerProvider == 'VpcVirtualRouter') - vpcOfferingName = 'Default VPC offering'; - else if (args.data.publicLoadBalancerProvider == 'Netscaler') - vpcOfferingName = 'Default VPC offering with Netscaler'; - - $.ajax({ - url: createURL('listVPCOfferings'), - data: { - name: vpcOfferingName - }, - success: function(json) { - var vpcofferingid = json.listvpcofferingsresponse.vpcoffering[0].id; - + var vpcOfferingName = args.data.vpcoffering var dataObj = { name: args.data.name, displaytext: args.data.displaytext, zoneid: args.data.zoneid, cidr: args.data.cidr, - vpcofferingid: vpcofferingid + vpcofferingid: args.data.vpcoffering }; if (args.data.networkdomain != null && args.data.networkdomain.length > 0) @@ -5252,8 +5393,6 @@ args.response.error(parseXMLHttpResponse(data)); } }); - } - }); }, notification: { diff --git a/ui/scripts/regions.js b/ui/scripts/regions.js index 66dae8c1a1..368c1bfb2f 100644 --- a/ui/scripts/regions.js +++ b/ui/scripts/regions.js @@ -147,6 +147,9 @@ viewAll: [{ path: 'regions.GSLB', label: 'GSLB' + }, { + path: 'network.vpc', + label: 'label.regionlevelvpc' }, { path: 'regions.portableIpRanges', label: 'Portable IP', diff --git a/ui/scripts/sharedFunctions.js b/ui/scripts/sharedFunctions.js index 9c24f40489..9cb48a20a7 100644 --- a/ui/scripts/sharedFunctions.js +++ b/ui/scripts/sharedFunctions.js @@ -18,6 +18,7 @@ var g_mySession = null; var g_sessionKey = null; var g_role = null; // roles - root, domain-admin, ro-admin, user var g_username = null; +var g_userid = null; var g_account = null; var g_domainid = null; var g_loginCmdText = null; @@ -919,11 +920,18 @@ cloudStack.converters = { var disconnected = new Date(); disconnected.setISO8601(UtcDate); - if (g_timezoneoffset != null) + if (g_timezoneoffset != null) { localDate = disconnected.getTimePlusTimezoneOffset(g_timezoneoffset); - else - localDate = disconnected.toUTCString(); - // localDate = disconnected.getTimePlusTimezoneOffset(0); + } else { + var browserDate = new Date(); + var browserTimezoneoffset = browserDate.getTimezoneOffset(); + if (browserTimezoneoffset == undefined || isNaN(browserTimezoneoffset) ) { + localDate = disconnected.toUTCString(); + } else { + g_timezoneoffset = (browserTimezoneoffset/60) * (-1); + localDate = disconnected.getTimePlusTimezoneOffset(g_timezoneoffset); + } + } } return localDate; }, @@ -1096,6 +1104,8 @@ cloudStack.converters = { return "VLAN"; case 18: return "Secondary Storage VM"; + case 19: + return "GPU"; } }, diff --git a/ui/scripts/storage.js b/ui/scripts/storage.js index e69a07e115..2660aa5549 100644 --- a/ui/scripts/storage.js +++ b/ui/scripts/storage.js @@ -975,7 +975,7 @@ getUpdatedItem: function(json) { return { virtualmachineid: null, - vmname: null + vmdisplayname: null }; }, getActionFilter: function() { diff --git a/ui/scripts/system.js b/ui/scripts/system.js index cdd02b29fd..67e01f1cc9 100644 --- a/ui/scripts/system.js +++ b/ui/scripts/system.js @@ -14755,6 +14755,74 @@ } }, + enable: { + label: 'Enable Host', + action: function (args) { + var data = { + id: args.context.hosts[0].id, + allocationstate: "Enable" + }; + $.ajax({ + url: createURL("updateHost"), + data: data, + success: function (json) { + var item = json.updatehostresponse.host; + args.response.success({ + actionFilter: hostActionfilter, + data: item + }); + } + }); + }, + messages: { + confirm: function (args) { + return 'Please confirm that you want to enable the host'; + }, + notification: function (args) { + return 'Enable Host'; + } + }, + notification: { + poll: function (args) { + args.complete(); + } + } + }, + + disable: { + label: 'Disable Host', + action: function (args) { + var data = { + id: args.context.hosts[0].id, + allocationstate: "Disable" + }; + $.ajax({ + url: createURL("updateHost"), + data: data, + success: function (json) { + var item = json.updatehostresponse.host; + args.response.success({ + actionFilter: hostActionfilter, + data: item + }); + } + }); + }, + messages: { + confirm: function (args) { + return 'Please confirm that you want to disable the host'; + }, + notification: function (args) { + return 'Disable Host'; + } + }, + notification: { + poll: function (args) { + args.complete(); + } + } + }, + 'remove': { label: 'label.action.remove.host', messages: { @@ -14811,6 +14879,13 @@ } } }, + tabFilter: function (args) { + var hiddenTabs =[]; + if (args.context.hosts[0].gpugroup == null) { + hiddenTabs.push("gpu"); + } + return hiddenTabs; + }, tabs: { details: { title: 'label.details', @@ -15004,6 +15079,81 @@ } }); } + }, + gpu: { + title: 'label.gpu', + custom: function (args) { + var gpugroups = null; + $.ajax({ + url: createURL("listHosts&id=" + args.context.hosts[0].id), + dataType: "json", + async: false, + success: function (json) { + var item = json.listhostsresponse.host[0]; + if (item != null && item.gpugroup != null) + gpugroups = item.gpugroup; + } + }); + + var $tabcontent = $('
').addClass('gpugroups'); + + $(gpugroups).each(function() { + var gpugroupObj = this; + + var $groupcontainer = $('
').addClass('gpugroup-container'); + + //group name + $groupcontainer.append($('
').addClass('title') + .append($('').html(gpugroupObj.gpugroupname))); + //vgpu details + var $groupdetails = $('
').listView({ + context: args.context, + listView: { + id: 'gputypes', + hideToolbar: true, + fields: { + vgputype: { + label: 'label.vgpu.type' + }, + maxvgpuperpgpu: { + label: 'label.vgpu.max.vgpu.per.gpu', + converter: function (args) { + return (args == null || args == 0) ? "" : args; + } + }, + videoram: { + label: 'label.vgpu.video.ram', + converter: function (args) { + return (args == null || args == 0) ? "" : cloudStack.converters.convertBytes(args); + } + }, + maxresolution: { + label: 'label.vgpu.max.resolution' + }, + remainingcapacity: { + label: 'label.vgpu.remaining.capacity' + } + }, + dataProvider: function (args) { + var items = gpugroupObj.vgpu.sort(function(a, b) { + return a.maxvgpuperpgpu >= b.maxvgpuperpgpu; + }); + $(items).each(function () { + this.maxresolution = (this.maxresolutionx == null || this.maxresolutionx == 0 + || this.maxresolutiony == null || this.maxresolutiony == 0) + ? "" : this.maxresolutionx + " x " + this.maxresolutiony; + }); + args.response.success({ + data: items + }); + } + } + }); + $groupcontainer.append($groupdetails); + $tabcontent.append($groupcontainer); + }); + return $tabcontent; + } } } } @@ -15131,7 +15281,11 @@ id: 'VMware', description: _l('VMware') }); - + items.push({ + id: 'Hyperv', + description: _l('Hyperv') + }); + args.response.success({ data: items }); @@ -18907,6 +19061,7 @@ if (jsonObj.resourcestate == "Enabled") { allowedActions.push("edit"); allowedActions.push("enableMaintenanceMode"); + allowedActions.push("disable"); if (jsonObj.state != "Disconnected") allowedActions.push("forceReconnect"); @@ -18923,6 +19078,7 @@ allowedActions.push("remove"); } else if (jsonObj.resourcestate == "Disabled") { allowedActions.push("edit"); + allowedActions.push("enable"); allowedActions.push("remove"); } diff --git a/ui/scripts/templates.js b/ui/scripts/templates.js index 7a45463d8a..67cc2fb99e 100644 --- a/ui/scripts/templates.js +++ b/ui/scripts/templates.js @@ -396,6 +396,10 @@ id: 'VHD', description: 'VHD' }); + items.push({ + id: 'VHDX', + description: 'VHDX' + }); } args.response.success({ data: items diff --git a/ui/scripts/ui-custom/accountsWizard.js b/ui/scripts/ui-custom/accountsWizard.js index 5ef0fa96b3..3259227d13 100644 --- a/ui/scripts/ui-custom/accountsWizard.js +++ b/ui/scripts/ui-custom/accountsWizard.js @@ -130,6 +130,89 @@ dataType: "json", async: false, success: function(json) { + //for testing only (begin) + /* + json = { + "ldapuserresponse": { + "count": 11, + "LdapUser": [ + { + "email": "test@test.com", + "principal": "CN=Administrator,CN=Users,DC=hyd-qa,DC=com", + "username": "Administrator", + "domain": "CN=Administrator" + }, + { + "email": "test@test.com", + "principal": "CN=Guest,CN=Users,DC=hyd-qa,DC=com", + "username": "Guest", + "domain": "CN=Guest" + }, + { + "email": "test@test.com", + "principal": "CN=IUSR_HYD-QA12,CN=Users,DC=hyd-qa,DC=com", + "username": "IUSR_HYD-QA12", + "domain": "CN=IUSR_HYD-QA12" + }, + { + "email": "test@test.com", + "principal": "CN=IWAM_HYD-QA12,CN=Users,DC=hyd-qa,DC=com", + "username": "IWAM_HYD-QA12", + "domain": "CN=IWAM_HYD-QA12" + }, + { + "email": "test@test.com", + "principal": "CN=SUPPORT_388945a0,CN=Users,DC=hyd-qa,DC=com", + "username": "SUPPORT_388945a0", + "domain": "CN=SUPPORT_388945a0" + }, + { + "principal": "CN=jessica j,CN=Users,DC=hyd-qa,DC=com", + "firstname": "jessica", + "lastname": "j", + "username": "jessica", + "domain": "CN=jessica j" + }, + { + "principal": "CN=krbtgt,CN=Users,DC=hyd-qa,DC=com", + "username": "krbtgt", + "domain": "CN=krbtgt" + }, + { + "email": "sadhu@sadhu.com", + "principal": "CN=sadhu,CN=Users,DC=hyd-qa,DC=com", + "firstname": "sadhu", + "username": "sadhu", + "domain": "CN=sadhu" + }, + { + "email": "test@test.com", + "principal": "CN=sangee1 hariharan,CN=Users,DC=hyd-qa,DC=com", + "firstname": "sangee1", + "lastname": "hariharan", + "username": "sangee1", + "domain": "CN=sangee1 hariharan" + }, + { + "email": "test@test.com", + "principal": "CN=sanjeev n.,CN=Users,DC=hyd-qa,DC=com", + "firstname": "sanjeev", + "username": "sanjeev", + "domain": "CN=sanjeev n." + }, + { + "email": "test@test.com", + "principal": "CN=test1dddd,CN=Users,DC=hyd-qa,DC=com", + "firstname": "test1", + "username": "test1dddd", + "domain": "CN=test1dddd" + } + ] + } + }; + */ + //for testing only (end) + if (json.ldapuserresponse.count > 0) { $(json.ldapuserresponse.LdapUser).each(function() { var $result = $(''); @@ -137,15 +220,15 @@ $result.append( $('').addClass('select').append( $('').attr({ - type: 'checkbox', name: 'username', value: this.username + type: 'checkbox', name: 'username', value: _s(this.username) }) ), - $('').addClass('name').html(this.firstname + ' ' + this.lastname) - .attr('title', this.firstname + ' ' + this.lastname), - $('').addClass('username').html(this.username) + $('').addClass('name').html(_s(this.firstname) + ' ' + _s(this.lastname)) + .attr('title', _s(this.firstname) + ' ' + _s(this.lastname)), + $('').addClass('username').html(_s(this.username)) .attr('title', this.username), - $('').addClass('email').html(this.email) - .attr('title', this.email) + $('').addClass('email').html(_s(this.email)) + .attr('title', _s(this.email)) ) $table.append($result); diff --git a/ui/scripts/ui-custom/instanceWizard.js b/ui/scripts/ui-custom/instanceWizard.js index f5f7b10cfa..527dc10547 100644 --- a/ui/scripts/ui-custom/instanceWizard.js +++ b/ui/scripts/ui-custom/instanceWizard.js @@ -59,6 +59,24 @@ }); data['new-network-ip'] = $form.find('.new-network .select.advanced .specify-ip input[type=text]').val(); + // Handle multi-disk service offerings + if ($form.find('.multi-disk-select-container').size()) { + data['disk-offerings-multi'] = []; + + var $diskGroups = $form.find('.disk-select-group'); + var $selectedDisks = $.grep($diskGroups, function (diskGroup) { + return $(diskGroup).find('input[type=checkbox]:checked').size(); + }); + + $selectedDisks.map(function (disk) { + data['disk-offerings-multi'].push( + $.extend($(disk).data('json-obj'), { + _diskOfferingId: $(disk).find('input[type=radio]:checked').val() + }) + ); + }); + } + args.action({ // Populate data context: context, @@ -460,7 +478,7 @@ var customIops = item[args.customIopsFlag]; - if (customIops) { + if (customIops && args.canShowCustomIops) { $step.addClass('custom-iops'); } else { $step.removeClass('custom-iops'); @@ -491,7 +509,11 @@ return { response: { success: function(args) { + var multiDisk = args.multiDisk; + + $step.find('.multi-disk-select-container').remove(); $step.removeClass('custom-disk-size'); + if (args.required) { $step.find('.section.no-thanks').hide(); $step.addClass('required'); @@ -500,15 +522,68 @@ $step.removeClass('required'); } - $step.find('.content .select-container').append( - makeSelects('diskofferingid', args.data.diskOfferings, { - id: 'id', - name: 'name', - desc: 'displaytext' - }, { - 'wizard-field': 'disk-offering' - }) - ); + var $selectContainer = $step.find('.content .select-container:not(.multi-disk)'); + + if (multiDisk) { // Render as multiple groups for each disk + var $multiDiskSelect = $('
').addClass('multi-disk-select-container'); + + $(multiDisk).map(function(index, disk) { + var $group = $('
').addClass('disk-select-group'); + var $header = $('
').addClass('disk-select-header').append( + $('
').addClass('title').html(disk.label) + ).appendTo($group); + var $checkbox = $('').addClass('multi-disk-select') + .attr({ + type: 'checkbox', + 'disk-id': disk.id + }) + .prependTo($header); + var $multiSelectContainer = $selectContainer.clone().append( + makeSelects('diskofferingid.' + disk.id, args.data.diskOfferings, { + id: 'id', + name: 'name', + desc: 'displaytext' + }, { + 'wizard-field': 'disk-offering' + }) + ).appendTo($group).addClass('multi-disk'); + + $group.appendTo($multiDiskSelect); + $group.data('json-obj', disk); + + // Show-hide disk group selects + $checkbox.click(function() { + $group.toggleClass('selected'); + $group.find('.select:first input[type=radio]').click(); + + if (!$multiDiskSelect.find('input[type=checkbox]:checked').size()) { + $step.find('.no-thanks input[type=radio]').click(); + } else { + $step.find('.no-thanks input[type=radio]').attr('checked', false); + } + }); + + // Add custom disk size box + $step.find('.section.custom-size').clone().hide().appendTo($group); + }); + + $multiDiskSelect.insertAfter($selectContainer); + $selectContainer.hide(); + + // Fix issue with containers always showing after reload + $multiDiskSelect.find('.select-container').attr('style', null); + } else { + $selectContainer.show(); + $step.find('.content .select-container').append( + makeSelects('diskofferingid', args.data.diskOfferings, { + id: 'id', + name: 'name', + desc: 'displaytext' + }, { + 'wizard-field': 'disk-offering' + }) + ); + } $step.find('input[type=radio]').bind('change', function() { var $target = $(this); @@ -516,44 +591,81 @@ var item = $.grep(args.data.diskOfferings, function(elem) { return elem.id == val; })[0]; + var isMultiDisk = $step.find('.multi-disk-select').size(); - if (!item) return true; + // Uncheck any multi-select groups + if ($target.closest('.no-thanks').size() && isMultiDisk) { + $step.find('.disk-select-group input[type=checkbox]:checked').click(); + $(this).attr('checked', true); + + return true; + } + + if (!item) { + if (isMultiDisk) { + $(this).closest('.disk-select-group .section.custom-size').hide(); + $(this).closest('.disk-select-group').removeClass('custom-size'); + } else { + // handle removal of custom size controls + $step.find('.section.custom-size').hide(); + $step.removeClass('custom-disk-size'); + + // handle removal of custom IOPS controls + $step.removeClass('custom-iops-do'); + } + + return true; + } var custom = item[args.customFlag]; - $step.find('.custom-size-label').remove(); + if (!isMultiDisk) $step.find('.custom-size-label').remove(); - if (custom) { + if (custom && !isMultiDisk) { $target.parent().find('.name') + .append( + $('').addClass('custom-size-label') + .append(': ') .append( - $('').addClass('custom-size-label') - .append(': ') - .append( - $('').addClass('custom-disk-size').html( - $step.find('.custom-size input[name=size]').val() - ) - ) - .append(' GB') + $('').addClass('custom-disk-size').html( + $step.find('.custom-size input[name=size]').val() + ) + ) + .append(' GB') ); $target.parent().find('.select-desc .desc') + .append( + $('').addClass('custom-size-label') + .append(', ') .append( - $('').addClass('custom-size-label') - .append(', ') - .append( - $('').addClass('custom-disk-size').html( - $step.find('.custom-size input[name=size]').val() - ) - ) - .append(' GB') + $('').addClass('custom-disk-size').html( + $step.find('.custom-size input[name=size]').val() + ) + ) + .append(' GB') ); $step.find('.section.custom-size').show(); $step.addClass('custom-disk-size'); $target.closest('.select-container').scrollTop( $target.position().top ); + } else if (custom && isMultiDisk) { + $(this).closest('.disk-select-group').addClass('custom-size'); } else { - $step.find('.section.custom-size').hide(); - $step.removeClass('custom-disk-size'); + if (isMultiDisk) { + $(this).closest('.disk-select-group').removeClass('custom-size'); + } else { + $step.find('.section.custom-size').hide(); + $step.removeClass('custom-disk-size'); + } + } + + var customIops = item[args.customIopsDoFlag]; + + if (customIops) { + $step.addClass('custom-iops-do'); + } else { + $step.removeClass('custom-iops-do'); } return true; @@ -1088,17 +1200,22 @@ $futureSteps.removeClass('loaded'); }); + var minCustomDiskSize = args.minDiskOfferingSize ? + args.minDiskOfferingSize() : 1; + var maxCustomDiskSize = args.maxDiskOfferingSize ? args.maxDiskOfferingSize() : 100; // Setup tabs and slider + $wizard.find('.section.custom-size .size.min span').html(minCustomDiskSize); + $wizard.find('.section.custom-size input[type=text]').val(minCustomDiskSize); $wizard.find('.section.custom-size .size.max span').html(maxCustomDiskSize); $wizard.find('.tab-view').tabs(); $wizard.find('.slider').each(function() { var $slider = $(this); - + $slider.slider({ - min: 1, + min: minCustomDiskSize, max: maxCustomDiskSize, start: function(event) { $slider.closest('.section.custom-size').find('input[type=radio]').click(); diff --git a/ui/scripts/ui-custom/physicalResources.js b/ui/scripts/ui-custom/physicalResources.js index fcc2f6ab5b..ac379b462f 100644 --- a/ui/scripts/ui-custom/physicalResources.js +++ b/ui/scripts/ui-custom/physicalResources.js @@ -117,8 +117,8 @@ type: "POST", url: createURL('uploadCustomCertificate'), data: { - certificate: encodeURIComponent(args.data.certificate), - privatekey: encodeURIComponent(args.data.privatekey), + certificate: args.data.certificate, + privatekey: args.data.privatekey, domainsuffix: args.data.domainsuffix }, dataType: 'json', @@ -136,7 +136,7 @@ clearInterval(uploadCustomCertificateIntervalID); if (result.jobstatus == 1) { cloudStack.dialog.notice({ - message: 'Update SSL Certiciate succeeded' + message: 'Update SSL Certificate succeeded' }); } else if (result.jobstatus == 2) { cloudStack.dialog.notice({ diff --git a/ui/scripts/ui-custom/zoneChart.js b/ui/scripts/ui-custom/zoneChart.js index bc30d51053..ac3c0e475a 100644 --- a/ui/scripts/ui-custom/zoneChart.js +++ b/ui/scripts/ui-custom/zoneChart.js @@ -24,7 +24,7 @@ */ var viewAllButton = function(args) { var $viewAll = $('
').addClass('button view-all'); - var $label = $('').addClass('view-all-label').html(args.label ? args.label : 'label.view.all'); + var $label = $('').addClass('view-all-label').html(args.label ? args.label : _l('label.view.all')); var $browser = args.$browser; var action = args.action; // Launch a list view @@ -166,13 +166,13 @@ var $label = $('').addClass('label'); $li.addClass(id); - $label.html(resource.label); + $label.html(_l(resource.label)); $label.appendTo($li); // View all if (resource.viewAll) { viewAllButton($.extend(resource.viewAll, { - title: resource.label, + title: _l(resource.label), $browser: $browser, context: context })).appendTo($li); @@ -383,6 +383,9 @@ }, 7: { name: _l('label.vlan') + }, + 19: { + name: _l('GPU') } }; diff --git a/ui/scripts/ui/dialog.js b/ui/scripts/ui/dialog.js index 82e7fd428c..7a903fdca0 100644 --- a/ui/scripts/ui/dialog.js +++ b/ui/scripts/ui/dialog.js @@ -223,7 +223,10 @@ }); if ($dependsOn.is('[type=checkbox]')) { - var isReverse = args.form.fields[dependsOn].isReverse; + + var isReverse = false; + if (args.form.fields[dependsOn]) + isReverse = args.form.fields[dependsOn].isReverse; // Checkbox $dependsOn.bind('click', function(event) { @@ -274,17 +277,18 @@ id = this[field.valueField]; else id = this.id !== undefined ? this.id : this.name; - var description = this.description; + var desc; if (args.descriptionField) - description = this[args.descriptionField]; + desc = this[args.descriptionField]; else - description = this.description; + desc = _l(this.description); var $option = $('