You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@cloudstack.apache.org by gi...@apache.org on 2014/06/18 09:45:56 UTC
[1/2] CLOUDSTACK-1466: Automatiion - Primary Storage Limits test cases
Repository: cloudstack
Updated Branches:
refs/heads/master 942fc9884 -> e7fe391be
http://git-wip-us.apache.org/repos/asf/cloudstack/blob/e7fe391b/test/integration/component/test_ps_resize_volume.py
----------------------------------------------------------------------
diff --git a/test/integration/component/test_ps_resize_volume.py b/test/integration/component/test_ps_resize_volume.py
new file mode 100644
index 0000000..737f910
--- /dev/null
+++ b/test/integration/component/test_ps_resize_volume.py
@@ -0,0 +1,339 @@
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements. See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership. The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied. See the License for the
+# specific language governing permissions and limitations
+# under the License.
+
+""" P1 tests for testing resize volume functionality with primary storage limit constraints on
+ account/domain
+
+ Test Plan: https://cwiki.apache.org/confluence/display/CLOUDSTACK/Limit+Resources+to+domain+or+accounts
+
+ Issue Link: https://issues.apache.org/jira/browse/CLOUDSTACK-1466
+
+ Feature Specifications: https://cwiki.apache.org/confluence/display/CLOUDSTACK/Limit+Resources+to+domains+and+accounts
+"""
+# Import Local Modules
+from nose.plugins.attrib import attr
+from marvin.cloudstackTestCase import cloudstackTestCase, unittest
+from marvin.lib.base import (Account,
+ ServiceOffering,
+ VirtualMachine,
+ Resources,
+ Domain,
+ DiskOffering,
+ Volume)
+from marvin.lib.common import (get_domain,
+ get_zone,
+ get_template,
+ matchResourceCount,
+ isDomainResourceCountEqualToExpectedCount)
+from marvin.lib.utils import (cleanup_resources,
+ get_hypervisor_type)
+from marvin.codes import (PASS,
+ FAIL,
+ FAILED,
+ RESOURCE_PRIMARY_STORAGE,
+ RESOURCE_SECONDARY_STORAGE,
+ XEN_SERVER)
+
+class TestResizeVolume(cloudstackTestCase):
+
+ @classmethod
+ def setUpClass(cls):
+ cloudstackTestClient = super(TestResizeVolume,
+ 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.services["mode"] = cls.zone.networktype
+ cls.resourcetypemapping = {RESOURCE_PRIMARY_STORAGE: 10,
+ RESOURCE_SECONDARY_STORAGE: 11}
+
+ 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.services["volume"]["zoneid"] = cls.zone.id
+
+ cls._cleanup = []
+ try:
+ cls.hypervisor = str(get_hypervisor_type(cls.api_client)).lower()
+
+ # Creating service offering with normal config
+ cls.service_offering = ServiceOffering.create(cls.api_client,
+ cls.services["service_offering"])
+ cls._cleanup.append(cls.service_offering)
+
+ cls.services["disk_offering"]["disksize"] = 5
+ cls.disk_offering_5_GB = DiskOffering.create(
+ cls.api_client,
+ cls.services["disk_offering"]
+ )
+ cls._cleanup.append(cls.disk_offering_5_GB)
+
+ cls.services["disk_offering"]["disksize"] = 20
+ cls.disk_offering_20_GB = DiskOffering.create(
+ cls.api_client,
+ cls.services["disk_offering"]
+ )
+ cls._cleanup.append(cls.disk_offering_20_GB)
+ except Exception as e:
+ cls.tearDownClass()
+ raise unittest.SkipTest("Failure while creating disk offering: %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 = []
+ return
+
+ def tearDown(self):
+ try:
+ # Clean up, terminate the created instance, volumes and snapshots
+ cleanup_resources(self.apiclient, self.cleanup)
+ pass
+ except Exception as e:
+ raise Exception("Warning: Exception during cleanup : %s" % e)
+ return
+
+ def updateResourceLimits(self, accountLimit=None, domainLimit=None):
+ """Update primary storage limits of the parent domain and its
+ child domains"""
+
+ try:
+ if domainLimit:
+ #Update resource limit for domain
+ Resources.updateLimit(self.apiclient, resourcetype=10,
+ max=domainLimit,
+ domainid=self.parent_domain.id)
+ if accountLimit:
+ #Update resource limit for domain
+ Resources.updateLimit(self.apiclient, resourcetype=10,
+ max=accountLimit, account=self.parentd_admin.name,
+ domainid=self.parent_domain.id)
+ except Exception as e:
+ return [FAIL, e]
+ return [PASS, None]
+
+ def setupAccounts(self):
+ try:
+ self.parent_domain = Domain.create(self.apiclient,
+ services=self.services["domain"],
+ parentdomainid=self.domain.id)
+ self.parentd_admin = Account.create(self.apiclient, self.services["account"],
+ admin=True, domainid=self.parent_domain.id)
+
+ # Cleanup the resources created at end of test
+ self.cleanup.append(self.parentd_admin)
+ self.cleanup.append(self.parent_domain)
+ except Exception as e:
+ return [FAIL, e]
+ return [PASS, None]
+
+ @attr(tags=["advanced", "selfservice"])
+ def test_01_increase_volume_size_within_account_limit(self):
+ """Test increasing volume size within the account limit and verify primary storage usage
+
+ # Validate the following
+ # 1. Create a domain and its admin account
+ # 2. Set account primary storage limit well beyond (20 GB volume + template size of VM)
+ # 3. Deploy a VM without any disk offering (only root disk)
+ # 4. Create a volume of 5 GB in the account and attach it to the VM
+ # 5. Increase (resize) the volume to 20 GB
+ # 6. Resize opearation should be successful and primary storage counnt for
+ # account should be updated successfully"""
+
+ # Setting up account and domain hierarchy
+ result = self.setupAccounts()
+ self.assertEqual(result[0], PASS, result[1])
+
+ apiclient = self.testClient.getUserApiClient(
+ UserName=self.parentd_admin.name,
+ DomainName=self.parentd_admin.domain)
+ self.assertNotEqual(apiclient, FAILED, "Failed to get api client\
+ of account: %s" % self.parentd_admin.name)
+
+ templateSize = (self.template.size / (1024**3))
+ accountLimit = (templateSize + self.disk_offering_20_GB.disksize)
+ response = self.updateResourceLimits(accountLimit=accountLimit)
+ self.assertEqual(response[0], PASS, response[1])
+ try:
+ virtualMachine = VirtualMachine.create(
+ apiclient, self.services["virtual_machine"],
+ accountid=self.parentd_admin.name, domainid=self.parent_domain.id,
+ serviceofferingid=self.service_offering.id
+ )
+
+ volume = Volume.create(
+ apiclient,self.services["volume"],zoneid=self.zone.id,
+ account=self.parentd_admin.name,domainid=self.parent_domain.id,
+ diskofferingid=self.disk_offering_5_GB.id)
+
+ virtualMachine.attach_volume(apiclient, volume=volume)
+
+ expectedCount = (templateSize + self.disk_offering_5_GB.disksize)
+ response = matchResourceCount(
+ self.apiclient, expectedCount,
+ RESOURCE_PRIMARY_STORAGE,
+ accountid=self.parentd_admin.id)
+ if response[0] == FAIL:
+ raise Exception(response[1])
+
+ if self.hypervisor == str(XEN_SERVER).lower():
+ virtualMachine.stop(self.apiclient)
+ volume.resize(apiclient, diskofferingid=self.disk_offering_20_GB.id)
+
+ expectedCount = (templateSize + self.disk_offering_20_GB.disksize)
+ response = matchResourceCount(
+ self.apiclient, expectedCount,
+ RESOURCE_PRIMARY_STORAGE,
+ accountid=self.parentd_admin.id)
+ if response[0] == FAIL:
+ raise Exception(response[1])
+ except Exception as e:
+ self.fail("Failed with exception: %s" % e)
+ return
+
+ @attr(tags=["advanced", "selfservice"])
+ def test_02_increase_volume_size_above_account_limit(self):
+ """Test increasing volume size above the account limit
+
+ # Validate the following
+ # 1. Create a domain and its admin account
+ # 2. Set account primary storage limit more than (5 GB volume + template size of VM)
+ # and less than (20 GB volume+ template size of VM)
+ # 3. Deploy a VM without any disk offering (only root disk)
+ # 4. Create a volume of 5 GB in the account and attach it to the VM
+ # 5. Try to (resize) the volume to 20 GB
+ # 6. Resize opearation should fail"""
+
+ # Setting up account and domain hierarchy
+ result = self.setupAccounts()
+ self.assertEqual(result[0], PASS, result[1])
+
+ templateSize = (self.template.size / (1024**3))
+ accountLimit = ((templateSize + self.disk_offering_20_GB.disksize) - 1)
+ response = self.updateResourceLimits(accountLimit=accountLimit)
+ self.assertEqual(response[0], PASS, response[1])
+
+ apiclient = self.testClient.getUserApiClient(
+ UserName=self.parentd_admin.name,
+ DomainName=self.parentd_admin.domain)
+ self.assertNotEqual(apiclient, FAILED, "Failed to get api client\
+ of account: %s" % self.parentd_admin.name)
+
+ try:
+ virtualMachine = VirtualMachine.create(
+ apiclient, self.services["virtual_machine"],
+ accountid=self.parentd_admin.name, domainid=self.parent_domain.id,
+ serviceofferingid=self.service_offering.id
+ )
+
+ volume = Volume.create(
+ apiclient,self.services["volume"],zoneid=self.zone.id,
+ account=self.parentd_admin.name,domainid=self.parent_domain.id,
+ diskofferingid=self.disk_offering_5_GB.id)
+
+ virtualMachine.attach_volume(apiclient, volume=volume)
+
+ expectedCount = (templateSize + self.disk_offering_5_GB.disksize)
+ response = matchResourceCount(
+ self.apiclient, expectedCount,
+ RESOURCE_PRIMARY_STORAGE,
+ accountid=self.parentd_admin.id)
+ if response[0] == FAIL:
+ raise Exception(response[1])
+ except Exception as e:
+ self.fail("Failed with exception: %s" % e)
+
+ if self.hypervisor == str(XEN_SERVER).lower():
+ virtualMachine.stop(self.apiclient)
+ with self.assertRaises(Exception):
+ volume.resize(apiclient, diskofferingid=self.disk_offering_20_GB.id)
+ return
+
+ @attr(tags=["advanced", "selfservice"])
+ def test_03_increase_volume_size_above_domain_limit(self):
+ """Test increasing volume size above the domain limit
+
+ # Validate the following
+ # 1. Create a domain and its admin account
+ # 2. Set domain primary storage limit more than (5 GB volume + template size of VM)
+ # and less than (20 GB volume+ template size of VM)
+ # 3. Deploy a VM without any disk offering (only root disk)
+ # 4. Create a volume of 5 GB in the account and attach it to the VM
+ # 5. Try to (resize) the volume to 20 GB
+ # 6. Resize opearation should fail"""
+
+ # Setting up account and domain hierarchy
+ result = self.setupAccounts()
+ self.assertEqual(result[0], PASS, result[1])
+
+ templateSize = (self.template.size / (1024**3))
+ domainLimit = ((templateSize + self.disk_offering_20_GB.disksize) - 1)
+ response = self.updateResourceLimits(domainLimit=domainLimit)
+ self.assertEqual(response[0], PASS, response[1])
+
+ apiclient = self.testClient.getUserApiClient(
+ UserName=self.parentd_admin.name,
+ DomainName=self.parentd_admin.domain)
+ self.assertNotEqual(apiclient, FAILED, "Failed to get api client\
+ of account: %s" % self.parentd_admin.name)
+
+ try:
+ virtualMachine = VirtualMachine.create(
+ apiclient, self.services["virtual_machine"],
+ accountid=self.parentd_admin.name, domainid=self.parent_domain.id,
+ serviceofferingid=self.service_offering.id
+ )
+
+ volume = Volume.create(
+ apiclient,self.services["volume"],zoneid=self.zone.id,
+ account=self.parentd_admin.name,domainid=self.parent_domain.id,
+ diskofferingid=self.disk_offering_5_GB.id)
+
+ virtualMachine.attach_volume(apiclient, volume=volume)
+
+ expectedCount = (templateSize + self.disk_offering_5_GB.disksize)
+ result = isDomainResourceCountEqualToExpectedCount(
+ self.apiclient, self.parent_domain.id,
+ expectedCount, RESOURCE_PRIMARY_STORAGE)
+ self.assertFalse(result[0], result[1])
+ self.assertTrue(result[2], "Resource count does not match")
+ except Exception as e:
+ self.fail("Failed with exception: %s" % e)
+
+ if self.hypervisor == str(XEN_SERVER).lower():
+ virtualMachine.stop(self.apiclient)
+ with self.assertRaises(Exception):
+ volume.resize(apiclient, diskofferingid=self.disk_offering_20_GB.id)
+ return
http://git-wip-us.apache.org/repos/asf/cloudstack/blob/e7fe391b/tools/marvin/marvin/codes.py
----------------------------------------------------------------------
diff --git a/tools/marvin/marvin/codes.py b/tools/marvin/marvin/codes.py
index ef49c0c..a1e7085 100644
--- a/tools/marvin/marvin/codes.py
+++ b/tools/marvin/marvin/codes.py
@@ -30,12 +30,28 @@
@DateAdded: 20th October 2013
"""
+'''
+VM STATES - START
+'''
RUNNING = "Running"
STOPPED = "Stopped"
STOPPING = "Stopping"
STARTING = "Starting"
DESTROYED = "Destroyed"
EXPUNGING = "Expunging"
+'''
+VM STATES - END
+'''
+
+'''
+Snapshot States - START
+'''
+BACKED_UP = "backedup"
+BACKING_UP = "backingup"
+'''
+Snapshot States - END
+'''
+
RECURRING = "RECURRING"
ENABLED = "Enabled"
NETWORK_OFFERING = "network_offering"
@@ -81,3 +97,11 @@ USER = 0
XEN_SERVER = "XenServer"
ADMIN_ACCOUNT = 'ADMIN_ACCOUNT'
USER_ACCOUNT = 'USER_ACCOUNT'
+RESOURCE_CPU = 8
+RESOURCE_MEMORY = 9
+RESOURCE_PRIMARY_STORAGE = 10
+RESOURCE_SECONDARY_STORAGE = 11
+KVM = "kvm"
+VMWARE = "vmware"
+ROOT_DOMAIN_ADMIN="root domain admin"
+CHILD_DOMAIN_ADMIN="child domain admin"
http://git-wip-us.apache.org/repos/asf/cloudstack/blob/e7fe391b/tools/marvin/marvin/lib/base.py
----------------------------------------------------------------------
diff --git a/tools/marvin/marvin/lib/base.py b/tools/marvin/marvin/lib/base.py
index 94606df..ad2b875 100755
--- a/tools/marvin/marvin/lib/base.py
+++ b/tools/marvin/marvin/lib/base.py
@@ -20,11 +20,10 @@
"""
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)
+ STOPPING, BACKED_UP, BACKING_UP)
from marvin.cloudstackException import GetDetailExceptionInfo
from marvin.lib.utils import validateList, is_server_ssh_ready, random_gen
# Import System modules
@@ -946,6 +945,12 @@ class Volume:
class Snapshot:
"""Manage Snapshot Lifecycle
"""
+ '''Class level variables'''
+ # Variables denoting possible Snapshot states - start
+ BACKED_UP = BACKED_UP
+ BACKING_UP = BACKING_UP
+ # Variables denoting possible Snapshot states - end
+
def __init__(self, items):
self.__dict__.update(items)
@@ -979,6 +984,31 @@ class Snapshot:
cmd.listall = True
return(apiclient.listSnapshots(cmd))
+ def validateState(self, apiclient, snapshotstate, timeout=600):
+ """Check if snapshot is in required state
+ returnValue: List[Result, Reason]
+ @Result: PASS if snapshot is in required state,
+ else FAIL
+ @Reason: Reason for failure in case Result is FAIL
+ """
+ isSnapshotInRequiredState = False
+ try:
+ while timeout >= 0:
+ snapshots = Snapshot.list(apiclient, id=self.id)
+ assert validateList(snapshots)[0] == PASS, "snapshots list\
+ validation failed"
+ if str(snapshots[0].state).lower() == snapshotstate:
+ isSnapshotInRequiredState = True
+ break
+ timeout -= 60
+ time.sleep(60)
+ #end while
+ if isSnapshotInRequiredState:
+ return[PASS, None]
+ else:
+ raise Exception("Snapshot not in required state")
+ except Exception as e:
+ return [FAIL, e]
class Template:
"""Manage template life cycle"""
http://git-wip-us.apache.org/repos/asf/cloudstack/blob/e7fe391b/tools/marvin/marvin/lib/common.py
----------------------------------------------------------------------
diff --git a/tools/marvin/marvin/lib/common.py b/tools/marvin/marvin/lib/common.py
index a2cb959..29677d3 100644
--- a/tools/marvin/marvin/lib/common.py
+++ b/tools/marvin/marvin/lib/common.py
@@ -62,12 +62,29 @@ from marvin.cloudstackAPI import (listConfigurations,
from marvin.sshClient import SshClient
-from marvin.codes import (PASS, ISOLATED_NETWORK, VPC_NETWORK,
- BASIC_ZONE, FAIL, NAT_RULE, STATIC_NAT_RULE, FAILED)
+from marvin.codes import (PASS, FAILED, ISOLATED_NETWORK, VPC_NETWORK,
+ BASIC_ZONE, FAIL, NAT_RULE, STATIC_NAT_RULE,
+ RESOURCE_PRIMARY_STORAGE, RESOURCE_SECONDARY_STORAGE,
+ RESOURCE_CPU, RESOURCE_MEMORY)
+from marvin.lib.utils import (validateList, xsplit, get_process_status)
+from marvin.lib.base import (PhysicalNetwork,
+ PublicIPAddress,
+ NetworkOffering,
+ NATRule,
+ StaticNATRule,
+ Volume,
+ Account,
+ Project,
+ Snapshot,
+ NetScaler,
+ VirtualMachine,
+ FireWallRule,
+ Template,
+ Network,
+ Host,
+ Resources,
+ Configurations)
import random
-from marvin.lib.utils import *
-from marvin.lib.base import *
-from marvin.codes import PASS
# Import System modules
@@ -1182,3 +1199,111 @@ def getPortableIpRangeServices(config):
services = FAILED
return services
+
+
+def uploadVolume(apiclient, zoneid, account, services):
+ try:
+ # Upload the volume
+ volume = Volume.upload(apiclient, services["volume"],
+ zoneid=zoneid, account=account.name,
+ domainid=account.domainid, url=services["url"])
+
+ volume.wait_for_upload(apiclient)
+
+ # Check List Volume response for newly created volume
+ volumes = Volume.list(apiclient, id=volume.id,
+ zoneid=zoneid, listall=True)
+ validationresult = validateList(volumes)
+ assert validationresult[0] == PASS,\
+ "volumes list validation failed: %s" % validationresult[2]
+ assert str(volumes[0].state).lower() == "uploaded",\
+ "Volume state should be 'uploaded' but it is %s" % volumes[0].state
+ except Exception as e:
+ return [FAIL, e]
+ return [PASS, volume]
+
+def matchResourceCount(apiclient, expectedCount, resourceType,
+ accountid=None, projectid=None):
+ """Match the resource count of account/project with the expected
+ resource count"""
+ try:
+ resourceholderlist = None
+ if accountid:
+ resourceholderlist = Account.list(apiclient, id=accountid)
+ elif projectid:
+ resourceholderlist = Project.list(apiclient, id=projectid, listall=True)
+ validationresult = validateList(resourceholderlist)
+ assert validationresult[0] == PASS,\
+ "accounts list validation failed"
+ if resourceType == RESOURCE_PRIMARY_STORAGE:
+ resourceCount = resourceholderlist[0].primarystoragetotal
+ elif resourceType == RESOURCE_SECONDARY_STORAGE:
+ resourceCount = resourceholderlist[0].secondarystoragetotal
+ elif resourceType == RESOURCE_CPU:
+ resourceCount = resourceholderlist[0].cputotal
+ elif resourceType == RESOURCE_MEMORY:
+ resourceCount = resourceholderlist[0].memorytotal
+ assert str(resourceCount) == str(expectedCount),\
+ "Resource count %s should match with the expected resource count %s" %\
+ (resourceCount, expectedCount)
+ except Exception as e:
+ return [FAIL, e]
+ return [PASS, None]
+
+def createSnapshotFromVirtualMachineVolume(apiclient, account, vmid):
+ """Create snapshot from volume"""
+
+ try:
+ volumes = Volume.list(apiclient, account=account.name,
+ domainid=account.domainid, virtualmachineid=vmid)
+ validationresult = validateList(volumes)
+ assert validateList(volumes)[0] == PASS,\
+ "List volumes should return a valid response"
+ snapshot = Snapshot.create(apiclient, volume_id=volumes[0].id,
+ account=account.name, domainid=account.domainid)
+ snapshots = Snapshot.list(apiclient, id=snapshot.id,
+ listall=True)
+ validationresult = validateList(snapshots)
+ assert validationresult[0] == PASS,\
+ "List snapshot should return a valid list"
+ except Exception as e:
+ return[FAIL, e]
+ return [PASS, snapshot]
+
+def isVmExpunged(apiclient, vmid, projectid=None, timeout=600):
+ """Verify if VM is expunged or not"""
+ vmExpunged= False
+ while timeout>=0:
+ try:
+ vms = VirtualMachine.list(apiclient, id=vmid, projectid=projectid)
+ if vms is None:
+ vmExpunged = True
+ break
+ timeout -= 60
+ time.sleep(60)
+ except Exception:
+ vmExpunged = True
+ break
+ #end while
+ return vmExpunged
+
+def isDomainResourceCountEqualToExpectedCount(apiclient, domainid, expectedcount,
+ resourcetype):
+ """Get the resource count of specific domain and match
+ it with the expected count
+ Return list [isExceptionOccured, reasonForException, isResourceCountEqual]"""
+ isResourceCountEqual = False
+ isExceptionOccured = False
+ reasonForException = None
+ try:
+ response = Resources.updateCount(apiclient, domainid=domainid,
+ resourcetype=resourcetype)
+ except Exception as e:
+ reasonForException = "Failed while updating resource count: %s" % e
+ isExceptionOccured = True
+ return [isExceptionOccured, reasonForException, isResourceCountEqual]
+
+ resourcecount = (response[0].resourcecount / (1024**3))
+ if resourcecount == expectedcount:
+ isResourceCountEqual = True
+ return [isExceptionOccured, reasonForException, isResourceCountEqual]
[2/2] git commit: updated refs/heads/master to e7fe391
Posted by gi...@apache.org.
CLOUDSTACK-1466: Automatiion - Primary Storage Limits test cases
Project: http://git-wip-us.apache.org/repos/asf/cloudstack/repo
Commit: http://git-wip-us.apache.org/repos/asf/cloudstack/commit/e7fe391b
Tree: http://git-wip-us.apache.org/repos/asf/cloudstack/tree/e7fe391b
Diff: http://git-wip-us.apache.org/repos/asf/cloudstack/diff/e7fe391b
Branch: refs/heads/master
Commit: e7fe391be4076309a9dc9a0f9bf8ea58181dfa12
Parents: 942fc98
Author: Gaurav Aradhye <ga...@clogeny.com>
Authored: Wed Jun 18 12:09:58 2014 +0530
Committer: Girish Shilamkar <gi...@clogeny.com>
Committed: Wed Jun 18 13:15:21 2014 +0530
----------------------------------------------------------------------
.../component/test_ps_domain_limits.py | 690 +++++++++++++++++++
test/integration/component/test_ps_limits.py | 588 ++++++++++++++++
.../integration/component/test_ps_max_limits.py | 300 ++++++++
.../component/test_ps_project_limits.py | 238 +++++++
.../component/test_ps_resize_volume.py | 339 +++++++++
tools/marvin/marvin/codes.py | 24 +
tools/marvin/marvin/lib/base.py | 34 +-
tools/marvin/marvin/lib/common.py | 135 +++-
8 files changed, 2341 insertions(+), 7 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/cloudstack/blob/e7fe391b/test/integration/component/test_ps_domain_limits.py
----------------------------------------------------------------------
diff --git a/test/integration/component/test_ps_domain_limits.py b/test/integration/component/test_ps_domain_limits.py
new file mode 100644
index 0000000..afb0955
--- /dev/null
+++ b/test/integration/component/test_ps_domain_limits.py
@@ -0,0 +1,690 @@
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements. See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership. The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied. See the License for the
+# specific language governing permissions and limitations
+# under the License.
+
+""" P1 tests for primary storage domain limits
+
+ Test Plan: https://cwiki.apache.org/confluence/display/CLOUDSTACK/Limit+Resources+to+domain+or+accounts
+
+ Issue Link: https://issues.apache.org/jira/browse/CLOUDSTACK-1466
+
+ Feature Specifications: https://cwiki.apache.org/confluence/display/CLOUDSTACK/Limit+Resources+to+domains+and+accounts
+"""
+# Import Local Modules
+from nose.plugins.attrib import attr
+from marvin.cloudstackTestCase import cloudstackTestCase, unittest
+from marvin.lib.base import (Account,
+ ServiceOffering,
+ VirtualMachine,
+ Resources,
+ Domain,
+ Volume,
+ DiskOffering,
+ Snapshot)
+from marvin.lib.common import (get_domain,
+ get_zone,
+ get_template,
+ createSnapshotFromVirtualMachineVolume,
+ isVmExpunged,
+ isDomainResourceCountEqualToExpectedCount)
+from marvin.lib.utils import (cleanup_resources)
+from marvin.codes import (PASS,
+ FAIL,
+ FAILED,
+ RESOURCE_PRIMARY_STORAGE)
+
+class TestMultipleChildDomain(cloudstackTestCase):
+
+ @classmethod
+ def setUpClass(cls):
+ cloudstackTestClient = super(TestMultipleChildDomain,
+ 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.services["mode"] = cls.zone.networktype
+
+ 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.services["volume"]["zoneid"] = cls.zone.id
+
+ cls._cleanup = []
+ try:
+ cls.service_offering = ServiceOffering.create(cls.api_client,
+ cls.services["service_offering"])
+ cls._cleanup.append(cls.service_offering)
+ except Exception as e:
+ cls.tearDownClass()
+ raise unittest.SkipTest("Exception 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 = []
+ self.services["disk_offering"]["disksize"] = 5
+ try:
+ self.disk_offering = DiskOffering.create(
+ self.apiclient,
+ self.services["disk_offering"]
+ )
+ self.assertNotEqual(self.disk_offering, None, \
+ "Disk offering is None")
+ self.cleanup.append(self.disk_offering)
+ except Exception as e:
+ self.tearDown()
+ self.skipTest("Failure while creating disk offering: %s" % e)
+ return
+
+ def tearDown(self):
+ try:
+ # Clean up, terminate the created instance, volumes and snapshots
+ cleanup_resources(self.apiclient, self.cleanup)
+ pass
+ except Exception as e:
+ raise Exception("Warning: Exception during cleanup : %s" % e)
+ return
+
+ def updateDomainResourceLimits(self, parentdomainlimit, subdomainlimit):
+ """Update primary storage limits of the parent domain and its
+ child domains"""
+
+ try:
+ #Update resource limit for domain
+ Resources.updateLimit(self.apiclient, resourcetype=10,
+ max=parentdomainlimit,
+ domainid=self.parent_domain.id)
+
+ # Update Resource limit for sub-domains
+ Resources.updateLimit(self.apiclient, resourcetype=10,
+ max=subdomainlimit,
+ domainid=self.cadmin_1.domainid)
+
+ Resources.updateLimit(self.apiclient, resourcetype=10,
+ max=subdomainlimit,
+ domainid=self.cadmin_2.domainid)
+ except Exception as e:
+ return [FAIL, e]
+ return [PASS, None]
+
+ def setupAccounts(self):
+ try:
+ self.parent_domain = Domain.create(self.apiclient,
+ services=self.services["domain"],
+ parentdomainid=self.domain.id)
+ self.parentd_admin = Account.create(self.apiclient, self.services["account"],
+ admin=True, domainid=self.parent_domain.id)
+
+ # Create sub-domains and their admin accounts
+ self.cdomain_1 = Domain.create(self.apiclient,
+ services=self.services["domain"],
+ parentdomainid=self.parent_domain.id)
+ self.cdomain_2 = Domain.create(self.apiclient,
+ services=self.services["domain"],
+ parentdomainid=self.parent_domain.id)
+
+ self.cadmin_1 = Account.create(self.apiclient, self.services["account"],
+ admin=True, domainid=self.cdomain_1.id)
+
+ self.cadmin_2 = Account.create(self.apiclient, self.services["account"],
+ admin=True, domainid=self.cdomain_2.id)
+
+ # Cleanup the resources created at end of test
+ self.cleanup.append(self.cadmin_1)
+ self.cleanup.append(self.cadmin_2)
+ self.cleanup.append(self.cdomain_1)
+ self.cleanup.append(self.cdomain_2)
+ self.cleanup.append(self.parentd_admin)
+ self.cleanup.append(self.parent_domain)
+
+ users = {
+ self.cdomain_1: self.cadmin_1,
+ self.cdomain_2: self.cadmin_2
+ }
+ except Exception as e:
+ return [FAIL, e, None]
+ return [PASS, None, users]
+
+ @attr(tags=["advanced","selfservice"])
+ def test_01_multiple_domains_primary_storage_limits(self):
+ """Test primary storage limit of domain and its sub-domains
+
+ # Steps
+ 1. Create a parent domain and two sub-domains in it (also admin accounts
+ of each domain)
+ 2. Update primary storage limits of the parent domain and child domains
+ 3. Deploy VM in child domain 1 so that total primary storage
+ is less than the limit of child domain
+ 4. Repeat step 3 for child domain 2
+ 5. Try to deploy VM in parent domain now so that the total primary storage in
+ parent domain (including that in sub-domains is more than the primary
+ storage limit of the parent domain
+ 6. Delete the admin account of child domain 1 and check resource count
+ of the parent domain
+ 7. Delete VM deployed in account 2 and check primary storage count
+ of parent domain
+
+ # Validations:
+ 1. Step 3 and 4 should succeed
+ 2. Step 5 should fail as the resource limit exceeds in parent domain
+ 3. After step 6, resource count in parent domain should decrease by equivalent
+ quantity
+ 4. After step 7, resource count in parent domain should be 0"""
+
+ # Setting up account and domain hierarchy
+ result = self.setupAccounts()
+ self.assertEqual(result[0], PASS,\
+ "Failure while setting up accounts and domains: %s" % result[1])
+
+ templatesize = (self.template.size / (1024**3))
+ disksize = 10
+ subdomainlimit = (templatesize + disksize)
+
+ result = self.updateDomainResourceLimits(((subdomainlimit*3)- 1), subdomainlimit)
+ self.assertEqual(result[0], PASS,\
+ "Failure while updating resource limits: %s" % result[1])
+
+ try:
+ self.services["disk_offering"]["disksize"] = disksize
+ disk_offering_custom = DiskOffering.create(self.apiclient,
+ services=self.services["disk_offering"])
+ self.cleanup.append(disk_offering_custom)
+ except Exception as e:
+ self.fail("Failed to create disk offering")
+
+ # Get API clients of parent and child domain admin accounts
+ api_client_admin = self.testClient.getUserApiClient(
+ UserName=self.parentd_admin.name,
+ DomainName=self.parentd_admin.domain)
+ self.assertNotEqual(api_client_admin, FAILED,\
+ "Failed to create api client for account: %s" % self.parentd_admin.name)
+
+ api_client_cadmin_1 = self.testClient.getUserApiClient(
+ UserName=self.cadmin_1.name,
+ DomainName=self.cadmin_1.domain)
+ self.assertNotEqual(api_client_cadmin_1, FAILED,\
+ "Failed to create api client for account: %s" % self.cadmin_1.name)
+
+ api_client_cadmin_2 = self.testClient.getUserApiClient(
+ UserName=self.cadmin_2.name,
+ DomainName=self.cadmin_2.domain)
+ self.assertNotEqual(api_client_cadmin_2, FAILED,\
+ "Failed to create api client for account: %s" % self.cadmin_2.name)
+
+ VirtualMachine.create(
+ api_client_cadmin_1, self.services["virtual_machine"],
+ accountid=self.cadmin_1.name, domainid=self.cadmin_1.domainid,
+ diskofferingid=disk_offering_custom.id, serviceofferingid=self.service_offering.id
+ )
+
+ self.initialResourceCount = (templatesize + disksize)
+ result = isDomainResourceCountEqualToExpectedCount(
+ self.apiclient, self.parent_domain.id,
+ self.initialResourceCount, RESOURCE_PRIMARY_STORAGE)
+ self.assertFalse(result[0], result[1])
+ self.assertTrue(result[2], "Resource count does not match")
+
+ # Create VM in second child domain
+ vm_2 = VirtualMachine.create(
+ api_client_cadmin_2, self.services["virtual_machine"],
+ accountid=self.cadmin_2.name, domainid=self.cadmin_2.domainid,
+ diskofferingid=disk_offering_custom.id, serviceofferingid=self.service_offering.id
+ )
+
+ # Now the VMs in two child domains have exhausted the primary storage limit
+ # of parent domain, hence VM creation in parent domain with custom disk offering
+ # should fail
+ with self.assertRaises(Exception):
+ VirtualMachine.create(
+ api_client_admin, self.services["virtual_machine"],
+ accountid=self.parentd_admin.name, domainid=self.parentd_admin.domainid,
+ diskofferingid=disk_offering_custom.id, serviceofferingid=self.service_offering.id
+ )
+
+ # Deleting user account
+ self.cadmin_1.delete(self.apiclient)
+ self.cleanup.remove(self.cadmin_1)
+
+ expectedCount = self.initialResourceCount
+ result = isDomainResourceCountEqualToExpectedCount(
+ self.apiclient, self.parent_domain.id,
+ expectedCount, RESOURCE_PRIMARY_STORAGE)
+ self.assertFalse(result[0], result[1])
+ self.assertTrue(result[2], "Resource count does not match")
+
+ try:
+ vm_2.delete(self.apiclient)
+ except Exception as e:
+ self.fail("Failed to delete instance: %s" % e)
+
+ self.assertTrue(isVmExpunged(self.apiclient, vm_2.id), "VM not expunged \
+ in allotted time")
+
+ expectedCount = 0
+ result = isDomainResourceCountEqualToExpectedCount(
+ self.apiclient, self.parent_domain.id,
+ expectedCount, RESOURCE_PRIMARY_STORAGE)
+ self.assertFalse(result[0], result[1])
+ self.assertTrue(result[2], "Resource count does not match")
+ return
+
+ @attr(tags=["advanced", "selfservice"])
+ def test_02_multiple_domains_primary_storage_limits(self):
+ """Test primary storage counts in multiple child domains
+ # Steps
+ 1. Create a parent domain and two sub-domains in it (also admin accounts
+ of each domain)
+ Repeat following steps for both the child domains
+ 2. Deploy VM in child domain
+ 3. Check if the resource count for domain is updated correctly
+ 4. Create a volume and attach it to the VM
+ 5. Check if the primary storage resource count is updated correctly
+
+ """
+
+ # Setting up account and domain hierarchy
+ result = self.setupAccounts()
+ self.assertEqual(result[0], PASS,\
+ "Failure while setting up accounts and domains: %s" % result[1])
+ users = result[2]
+
+ templatesize = (self.template.size / (1024**3))
+
+ for domain, admin in users.items():
+ self.account = admin
+ self.domain = domain
+
+ apiclient = self.testClient.getUserApiClient(
+ UserName=self.account.name,
+ DomainName=self.account.domain)
+ self.assertNotEqual(apiclient, FAILED,\
+ "Failed to create api client for account: %s" % self.account.name)
+ try:
+ vm = VirtualMachine.create(
+ apiclient, self.services["virtual_machine"],
+ accountid=self.account.name, domainid=self.account.domainid,
+ diskofferingid=self.disk_offering.id, serviceofferingid=self.service_offering.id
+ )
+
+ expectedCount = templatesize + self.disk_offering.disksize
+ result = isDomainResourceCountEqualToExpectedCount(
+ self.apiclient, self.domain.id,
+ expectedCount, RESOURCE_PRIMARY_STORAGE)
+ self.assertFalse(result[0], result[1])
+ self.assertTrue(result[2], "Resource count does not match")
+
+ # Creating service offering with 10 GB volume
+ self.services["disk_offering"]["disksize"] = 10
+ disk_offering_10_GB = DiskOffering.create(self.apiclient,
+ services=self.services["disk_offering"])
+
+ self.cleanup.append(disk_offering_10_GB)
+
+ volume = Volume.create(
+ apiclient, self.services["volume"],
+ zoneid=self.zone.id, account=self.account.name,
+ domainid=self.account.domainid, diskofferingid=disk_offering_10_GB.id
+ )
+
+ volumeSize = (volume.size / (1024**3))
+ expectedCount += volumeSize
+
+ vm.attach_volume(apiclient, volume=volume)
+ result = isDomainResourceCountEqualToExpectedCount(
+ self.apiclient, self.domain.id,
+ expectedCount, RESOURCE_PRIMARY_STORAGE)
+ self.assertFalse(result[0], result[1])
+ self.assertTrue(result[2], "Resource count does not match")
+
+ expectedCount -= volumeSize
+ vm.detach_volume(apiclient, volume=volume)
+ result = isDomainResourceCountEqualToExpectedCount(
+ self.apiclient, self.domain.id,
+ expectedCount, RESOURCE_PRIMARY_STORAGE)
+ self.assertFalse(result[0], result[1])
+ self.assertTrue(result[2], "Resource count does not match")
+ except Exception as e:
+ self.fail("Failure: %s" % e)
+ return
+
+ @attr(tags=["advanced", "selfservice"])
+ def test_03_multiple_domains_multiple_volumes(self):
+ """Test primary storage counts in multiple child domains
+ # Steps
+ 1. Create a parent domain and two sub-domains in it (also admin accounts
+ of each domain)
+ Repeat following steps for both the child domains
+ 2. Deploy VM in child domain
+ 3. Check if the resource count for domain is updated correctly
+ 4. Create multiple volumes and attach it to the VM
+ 5. Check if the primary storage resource count is updated correctly
+ 6. Delete one of the volumes and check if the primary storage resource count
+ reduced by equivalent number
+ 7. Detach other volume and check primary storage resource count remains the same
+
+ """
+ # Setting up account and domain hierarchy
+ result = self.setupAccounts()
+ if result[0] == FAIL:
+ self.fail("Failure while setting up accounts and domains: %s" % result[1])
+ else:
+ users = result[2]
+
+ templatesize = (self.template.size / (1024**3))
+
+ for domain, admin in users.items():
+ self.account = admin
+ self.domain = domain
+
+ apiclient = self.testClient.getUserApiClient(
+ UserName=self.account.name,
+ DomainName=self.account.domain)
+ self.assertNotEqual(apiclient, FAILED,\
+ "Failed to create api client for account: %s" % self.account.name)
+
+ try:
+ vm = VirtualMachine.create(
+ apiclient, self.services["virtual_machine"],
+ accountid=self.account.name, domainid=self.account.domainid,
+ diskofferingid=self.disk_offering.id, serviceofferingid=self.service_offering.id
+ )
+
+ expectedCount = templatesize + self.disk_offering.disksize
+ result = isDomainResourceCountEqualToExpectedCount(
+ self.apiclient, self.domain.id,
+ expectedCount, RESOURCE_PRIMARY_STORAGE)
+ self.assertFalse(result[0], result[1])
+ self.assertTrue(result[2], "Resource count does not match")
+
+ volume1size = self.services["disk_offering"]["disksize"] = 15
+ disk_offering_15_GB = DiskOffering.create(self.apiclient,
+ services=self.services["disk_offering"])
+
+ self.cleanup.append(disk_offering_15_GB)
+
+ volume2size = self.services["disk_offering"]["disksize"] = 20
+ disk_offering_20_GB = DiskOffering.create(self.apiclient,
+ services=self.services["disk_offering"])
+
+ self.cleanup.append(disk_offering_20_GB)
+
+ volume_1 = Volume.create(
+ apiclient, self.services["volume"],
+ zoneid=self.zone.id, account=self.account.name,
+ domainid=self.account.domainid, diskofferingid=disk_offering_15_GB.id
+ )
+
+ volume_2 = Volume.create(
+ apiclient, self.services["volume"],
+ zoneid=self.zone.id, account=self.account.name,
+ domainid=self.account.domainid, diskofferingid=disk_offering_20_GB.id
+ )
+
+ vm.attach_volume(apiclient, volume=volume_1)
+ vm.attach_volume(apiclient, volume=volume_2)
+
+ expectedCount += volume1size + volume2size
+ result = isDomainResourceCountEqualToExpectedCount(
+ self.apiclient, self.domain.id,
+ expectedCount, RESOURCE_PRIMARY_STORAGE)
+ self.assertFalse(result[0], result[1])
+ self.assertTrue(result[2], "Resource count does not match")
+
+ vm.detach_volume(apiclient, volume=volume_1)
+ volume_1.delete(apiclient)
+
+ expectedCount -= volume1size
+ result = isDomainResourceCountEqualToExpectedCount(
+ self.apiclient, self.domain.id,
+ expectedCount, RESOURCE_PRIMARY_STORAGE)
+ self.assertFalse(result[0], result[1])
+ self.assertTrue(result[2], "Resource count does not match")
+
+ expectedCount -= volume2size
+ vm.detach_volume(apiclient, volume=volume_2)
+ result = isDomainResourceCountEqualToExpectedCount(
+ self.apiclient, self.domain.id,
+ expectedCount, RESOURCE_PRIMARY_STORAGE)
+ self.assertFalse(result[0], result[1])
+ self.assertTrue(result[2], "Resource count does not match")
+ except Exception as e:
+ self.fail("Failure: %s" % e)
+ return
+
+ @attr(tags=["advanced", "selfservice"])
+ def test_04_create_template_snapshot(self):
+ """Test create snapshot and templates from volume
+
+ # Validate the following
+ 1. Create parent domain with two child sub-domains (and their admin accounts)
+ Follow these steps for both the domains
+ # 1. Create template from snapshot and verify secondary storage resource count
+ # 2. Create Volume from Snapshot and verify primary storage resource count
+ # 3. Attach volume to instance which was created from snapshot and
+ # verify primary storage resource count
+ # 4. Detach volume from instance which was created from snapshot and
+ # verify the primary storage resource count
+ # 5. Delete volume which was created from snapshot and verify primary storage
+ resource count"""
+
+ result = self.setupAccounts()
+ if result[0] == FAIL:
+ self.fail("Failure while setting up accounts and domains: %s" % result[1])
+ users = result[2]
+
+ for domain, admin in users.items():
+ self.account = admin
+ self.domain = domain
+
+ try:
+ apiclient = self.testClient.getUserApiClient(
+ UserName=self.account.name,
+ DomainName=self.account.domain)
+ self.assertNotEqual(apiclient, FAILED,\
+ "Failed to create api client for account: %s" % self.account.name)
+
+ vm = VirtualMachine.create(
+ apiclient, self.services["virtual_machine"],
+ accountid=self.account.name, domainid=self.account.domainid,
+ diskofferingid=self.disk_offering.id, serviceofferingid=self.service_offering.id
+ )
+
+ templatesize = (self.template.size / (1024**3))
+
+ initialResourceCount = expectedCount = templatesize + self.disk_offering.disksize
+ result = isDomainResourceCountEqualToExpectedCount(
+ self.apiclient, self.domain.id,
+ initialResourceCount, RESOURCE_PRIMARY_STORAGE)
+ self.assertFalse(result[0], result[1])
+ self.assertTrue(result[2], "Resource count does not match")
+
+ vm.stop(self.apiclient)
+
+ response = createSnapshotFromVirtualMachineVolume(apiclient, self.account, vm.id)
+ self.assertEqual(response[0], PASS, response[1])
+ snapshot = response[1]
+
+ response = snapshot.validateState(apiclient, Snapshot.BACKED_UP)
+ self.assertEqual(response[0], PASS, response[1])
+
+ self.services["volume"]["size"] = self.services["disk_offering"]["disksize"]
+ volume = Volume.create_from_snapshot(apiclient,
+ snapshot_id=snapshot.id,
+ services=self.services["volume"],
+ account=self.account.name,
+ domainid=self.account.domainid)
+ volumeSize = (volume.size / (1024**3))
+ vm.attach_volume(apiclient, volume)
+ expectedCount = initialResourceCount + (volumeSize)
+ result = isDomainResourceCountEqualToExpectedCount(
+ self.apiclient, self.domain.id,
+ expectedCount, RESOURCE_PRIMARY_STORAGE)
+ self.assertFalse(result[0], result[1])
+ self.assertTrue(result[2], "Resource count does not match")
+
+ expectedCount -= volumeSize
+ vm.detach_volume(apiclient, volume)
+ result = isDomainResourceCountEqualToExpectedCount(
+ self.apiclient, self.domain.id,
+ expectedCount, RESOURCE_PRIMARY_STORAGE)
+ self.assertFalse(result[0], result[1])
+ self.assertTrue(result[2], "Resource count does not match")
+
+ volume.delete(apiclient)
+ result = isDomainResourceCountEqualToExpectedCount(
+ self.apiclient, self.domain.id,
+ expectedCount, RESOURCE_PRIMARY_STORAGE)
+ self.assertFalse(result[0], result[1])
+ self.assertTrue(result[2], "Resource count does not match")
+ except Exception as e:
+ self.fail("Failed with exception : %s" % e)
+ return
+
+ @attr(tags=["advanced", "selfservice"])
+ def test_05_assign_virtual_machine_different_domain(self):
+ """Test assign virtual machine to account belonging to different domain
+
+ # Steps
+ 1. Create a parent domain and two sub-domains in it (also admin accounts
+ of each domain)
+ 2. Deploy VM in child domain 1
+ 3. Check if the resource count for domain 1 is updated correctly
+ 4. Assign this virtual machine to account 2 in domain 2
+ 5. Verify that primaru storage resource count of domain 1 is now 0 and
+ primary storage resource count of domain 2 is increased by equivalent number
+ """
+
+ # Setting up account and domain hierarchy
+ result = self.setupAccounts()
+ self.assertEqual(result[0], PASS, result[1])
+
+ apiclient = self.testClient.getUserApiClient(
+ UserName=self.cadmin_1.name,
+ DomainName=self.cadmin_1.domain)
+ self.assertNotEqual(apiclient, FAILED,\
+ "Failed to create api client for account: %s" % self.cadmin_1.name)
+
+ try:
+ vm_1 = VirtualMachine.create(
+ apiclient, self.services["virtual_machine"],
+ accountid=self.cadmin_1.name, domainid=self.cadmin_1.domainid,
+ diskofferingid=self.disk_offering.id, serviceofferingid=self.service_offering.id
+ )
+
+ templatesize = (self.template.size / (1024**3))
+
+ expectedCount = templatesize + self.disk_offering.disksize
+ result = isDomainResourceCountEqualToExpectedCount(
+ self.apiclient, self.cadmin_1.domainid,
+ expectedCount, RESOURCE_PRIMARY_STORAGE)
+ self.assertFalse(result[0], result[1])
+ self.assertTrue(result[2], "Resource count does not match")
+
+ vm_1.stop(apiclient)
+ vm_1.assign_virtual_machine(self.apiclient, account=self.cadmin_2.name,
+ domainid=self.cadmin_2.domainid)
+
+ result = isDomainResourceCountEqualToExpectedCount(
+ self.apiclient, self.cadmin_2.domainid,
+ expectedCount, RESOURCE_PRIMARY_STORAGE)
+ self.assertFalse(result[0], result[1])
+ self.assertTrue(result[2], "Resource count does not match")
+
+ expectedCount = 0
+ result = isDomainResourceCountEqualToExpectedCount(
+ self.apiclient, self.cadmin_1.domainid,
+ expectedCount, RESOURCE_PRIMARY_STORAGE)
+ self.assertFalse(result[0], result[1])
+ self.assertTrue(result[2], "Resource count does not match")
+ except Exception as e:
+ self.fail("Failed with exception: %s" % e)
+ return
+
+ @attr(tags=["advanced", "selfservice"])
+ def test_06_destroy_recover_vm(self):
+ """Test primary storage counts while destroying and recovering VM
+ # Steps
+ 1. Create a parent domain and two sub-domains in it (also admin accounts
+ of each domain)
+ Repeat following steps for both the child domains
+ 2. Deploy VM in child domain
+ 3. Check if the resource count for domain is updated correctly
+ 4. Destroy the VM
+ 5. Verify that the primary storage resource count remains the same
+ 6. Recover the VM
+ 7. Verify that the primary storage resource count remains the same
+ """
+
+ # Setting up account and domain hierarchy
+ result = self.setupAccounts()
+ self.assertEqual(result[0], PASS, result[1])
+ users = result[2]
+
+ for domain, admin in users.items():
+ self.account = admin
+ self.domain = domain
+ try:
+ vm_1 = VirtualMachine.create(
+ self.apiclient, self.services["virtual_machine"],
+ accountid=self.account.name, domainid=self.account.domainid,
+ diskofferingid=self.disk_offering.id, serviceofferingid=self.service_offering.id
+ )
+
+ templatesize = (self.template.size / (1024**3))
+
+ expectedCount = templatesize + self.disk_offering.disksize
+ result = isDomainResourceCountEqualToExpectedCount(
+ self.apiclient, self.account.domainid,
+ expectedCount, RESOURCE_PRIMARY_STORAGE)
+ self.assertFalse(result[0], result[1])
+ self.assertTrue(result[2], "Resource count does not match")
+
+ vm_1.delete(self.apiclient)
+
+ result = isDomainResourceCountEqualToExpectedCount(
+ self.apiclient, self.account.domainid,
+ expectedCount, RESOURCE_PRIMARY_STORAGE)
+ self.assertFalse(result[0], result[1])
+ self.assertTrue(result[2], "Resource count does not match")
+
+ vm_1.recover(self.apiclient)
+
+ result = isDomainResourceCountEqualToExpectedCount(
+ self.apiclient, self.account.domainid,
+ expectedCount, RESOURCE_PRIMARY_STORAGE)
+ self.assertFalse(result[0], result[1])
+ self.assertTrue(result[2], "Resource count does not match")
+ except Exception as e:
+ self.fail("Failed with exception: %s" % e)
+ return
http://git-wip-us.apache.org/repos/asf/cloudstack/blob/e7fe391b/test/integration/component/test_ps_limits.py
----------------------------------------------------------------------
diff --git a/test/integration/component/test_ps_limits.py b/test/integration/component/test_ps_limits.py
new file mode 100644
index 0000000..1993e93
--- /dev/null
+++ b/test/integration/component/test_ps_limits.py
@@ -0,0 +1,588 @@
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements. See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership. The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied. See the License for the
+# specific language governing permissions and limitations
+# under the License.
+
+""" P1 tests for primary storage limits
+
+ Test Plan: https://cwiki.apache.org/confluence/display/CLOUDSTACK/Limit+Resources+to+domain+or+accounts
+
+ Issue Link: https://issues.apache.org/jira/browse/CLOUDSTACK-1466
+
+ Feature Specifications: https://cwiki.apache.org/confluence/display/CLOUDSTACK/Limit+Resources+to+domains+and+accounts
+"""
+# Import Local Modules
+from nose.plugins.attrib import attr
+from marvin.cloudstackTestCase import cloudstackTestCase, unittest
+from marvin.lib.base import (
+ Account,
+ ServiceOffering,
+ VirtualMachine,
+ Domain,
+ Volume,
+ DiskOffering)
+from marvin.lib.common import (get_domain,
+ get_zone,
+ get_template,
+ matchResourceCount,
+ createSnapshotFromVirtualMachineVolume,
+ isVmExpunged)
+from marvin.lib.utils import (cleanup_resources,
+ validateList)
+from marvin.codes import (PASS,
+ FAIL,
+ RESOURCE_PRIMARY_STORAGE,
+ CHILD_DOMAIN_ADMIN,
+ ROOT_DOMAIN_ADMIN)
+from ddt import ddt, data
+
+@ddt
+class TestVolumeLimits(cloudstackTestCase):
+
+ @classmethod
+ def setUpClass(cls):
+ cloudstackTestClient = super(TestVolumeLimits,
+ 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.services["mode"] = cls.zone.networktype
+
+ 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.services["volume"]["zoneid"] = cls.zone.id
+ cls._cleanup = []
+ try:
+ cls.service_offering = ServiceOffering.create(cls.api_client, cls.services["service_offering"])
+ cls._cleanup.append(cls.service_offering)
+ except Exception as e:
+ cls.tearDownClass()
+ raise unittest.SkipTest("Exception 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.services["disk_offering"]["disksize"] = 2
+ self.disk_offering = DiskOffering.create(self.apiclient, self.services["disk_offering"])
+ self.assertNotEqual(self.disk_offering, None,\
+ "Disk offering is None")
+ self.cleanup.append(self.disk_offering)
+ except Exception as e:
+ self.tearDown()
+ self.skipTest("Failure in setup: %s" % e)
+ return
+
+ def tearDown(self):
+ try:
+ # Clean up, terminate the created instance, volumes and snapshots
+ cleanup_resources(self.apiclient, self.cleanup)
+ pass
+ except Exception as e:
+ raise Exception("Warning: Exception during cleanup : %s" % e)
+ return
+
+ def setupAccount(self, accountType):
+ """Setup the account required for the test"""
+
+ try:
+ if accountType == CHILD_DOMAIN_ADMIN:
+ self.domain = Domain.create(self.apiclient,
+ services=self.services["domain"],
+ parentdomainid=self.domain.id)
+
+ self.account = Account.create(self.apiclient, self.services["account"],
+ domainid=self.domain.id, admin=True)
+ self.cleanup.append(self.account)
+ if accountType == CHILD_DOMAIN_ADMIN:
+ self.cleanup.append(self.domain)
+
+ self.virtualMachine = VirtualMachine.create(self.api_client, self.services["virtual_machine"],
+ accountid=self.account.name, domainid=self.account.domainid,
+ diskofferingid=self.disk_offering.id,
+ serviceofferingid=self.service_offering.id)
+
+ accounts = Account.list(self.apiclient, id=self.account.id)
+
+ self.assertEqual(validateList(accounts)[0], PASS,
+ "accounts list validation failed")
+
+ self.initialResourceCount = int(accounts[0].primarystoragetotal)
+ except Exception as e:
+ return [FAIL, e]
+ return [PASS, None]
+
+ @data(ROOT_DOMAIN_ADMIN, CHILD_DOMAIN_ADMIN)
+ @attr(tags=["advanced", "selfservice"])
+ def test_stop_start_vm(self, value):
+ """Test Deploy VM with 5 GB volume & verify the usage
+
+ # Validate the following
+ # 1. Create a VM with custom disk offering and check the primary storage count
+ # 2. Stop VM and verify the resource count remains same
+ # 3. Start VM and verify resource count remains same"""
+
+ response = self.setupAccount(value)
+ self.assertEqual(response[0], PASS, response[1])
+
+ expectedCount = self.initialResourceCount
+ # Stopping instance
+ try:
+ self.virtualMachine.stop(self.apiclient)
+ except Exception as e:
+ self.fail("Failed to stop instance: %s" % e)
+ response = matchResourceCount(
+ self.apiclient, expectedCount,
+ RESOURCE_PRIMARY_STORAGE,
+ accountid=self.account.id)
+ self.assertEqual(response[0], PASS, response[1])
+
+ # Starting instance
+ try:
+ self.virtualMachine.start(self.apiclient)
+ except Exception as e:
+ self.fail("Failed to start instance: %s" % e)
+
+ response = matchResourceCount(
+ self.apiclient, expectedCount,
+ RESOURCE_PRIMARY_STORAGE,
+ accountid=self.account.id)
+ self.assertEqual(response[0], PASS, response[1])
+ return
+
+ @unittest.skip("skip")
+ @data(ROOT_DOMAIN_ADMIN, CHILD_DOMAIN_ADMIN)
+ @attr(tags=["advanced", "selfservice"])
+ def test_destroy_recover_vm(self, value):
+ """Test delete and recover instance
+
+ # Validate the following
+ # 1. Create a VM with custom disk offering and check the primary storage count
+ # 2. Destroy VM and verify the resource count remains same
+ # 3. Recover VM and verify resource count remains same"""
+
+ response = self.setupAccount(value)
+ self.assertEqual(response[0], PASS, response[1])
+
+ expectedCount = self.initialResourceCount
+ # Stopping instance
+ try:
+ self.virtualMachine.delete(self.apiclient)
+ except Exception as e:
+ self.fail("Failed to destroy instance: %s" % e)
+ response = matchResourceCount(
+ self.apiclient, expectedCount,
+ RESOURCE_PRIMARY_STORAGE,
+ accountid=self.account.id)
+ self.assertEqual(response[0], PASS, response[1])
+
+ # Recovering instance
+ try:
+ self.virtualMachine.recover(self.apiclient)
+ except Exception as e:
+ self.fail("Failed to start instance: %s" % e)
+
+ response = matchResourceCount(
+ self.apiclient, expectedCount,
+ RESOURCE_PRIMARY_STORAGE,
+ accountid=self.account.id)
+ self.assertEqual(response[0], PASS, response[1])
+ return
+
+ @data(ROOT_DOMAIN_ADMIN, CHILD_DOMAIN_ADMIN)
+ @attr(tags=["advanced", "selfservice"])
+ def test_attach_detach_volume(self, value):
+ """Stop attach and detach volume from VM
+
+ # Validate the following
+ # 1. Create a VM with custom disk offering and check the primary storage count
+ # of account
+ # 2. Create custom volume in account
+ # 3. Verify that primary storage count increases by same amount
+ # 4. Attach volume to VM and verify resource count remains the same
+ # 5. Detach volume and verify resource count remains the same"""
+
+ response = self.setupAccount(value)
+ self.assertEqual(response[0], PASS, response[1])
+
+ apiclient = self.apiclient
+ if value == CHILD_DOMAIN_ADMIN:
+ apiclient = self.testClient.getUserApiClient(
+ UserName=self.account.name,
+ DomainName=self.account.domain
+ )
+ self.assertNotEqual(apiclient, FAIL, "Failure while getting\
+ api client of account: %s" % self.account.name)
+
+ try:
+ self.services["disk_offering"]["disksize"] = 4
+ expectedCount = self.initialResourceCount + int(self.services["disk_offering"]["disksize"])
+ disk_offering = DiskOffering.create(self.apiclient,
+ services=self.services["disk_offering"])
+
+ self.cleanup.append(disk_offering)
+
+ volume = Volume.create(
+ apiclient,self.services["volume"],zoneid=self.zone.id,
+ account=self.account.name,domainid=self.account.domainid,
+ diskofferingid=disk_offering.id)
+ except Exception as e:
+ self.fail("Failure: %s" % e)
+
+ response = matchResourceCount(
+ self.apiclient, expectedCount,
+ RESOURCE_PRIMARY_STORAGE,
+ accountid=self.account.id)
+ self.assertEqual(response[0], PASS, response[1])
+
+ try:
+ self.virtualMachine.attach_volume(apiclient, volume=volume)
+ except Exception as e:
+ self.fail("Failed while attaching volume to VM: %s" % e)
+
+ response = matchResourceCount(
+ self.apiclient, expectedCount,
+ RESOURCE_PRIMARY_STORAGE,
+ accountid=self.account.id)
+ self.assertEqual(response[0], PASS, response[1])
+
+ try:
+ self.virtualMachine.detach_volume(apiclient, volume=volume)
+ except Exception as e:
+ self.fail("Failure while detaching volume: %s" % e)
+
+ response = matchResourceCount(
+ self.apiclient, expectedCount,
+ RESOURCE_PRIMARY_STORAGE,
+ accountid=self.account.id)
+ self.assertEqual(response[0], PASS, response[1])
+ return
+
+ @data(ROOT_DOMAIN_ADMIN, CHILD_DOMAIN_ADMIN)
+ @attr(tags=["advanced", "selfservice"])
+ def test_create_multiple_volumes(self, value):
+ """Test create multiple volumes
+
+ # Validate the following
+ # 1. Create a VM with custom disk offering and check the primary storage count
+ # of account
+ # 2. Create multiple volumes in account
+ # 3. Verify that primary storage count increases by same amount
+ # 4. Attach volumes to VM and verify resource count remains the same
+ # 5. Detach and delete both volumes one by one and verify resource count decreases
+ # proportionately"""
+
+ # Creating service offering with 10 GB volume
+
+ response = self.setupAccount(value)
+ self.assertEqual(response[0], PASS, response[1])
+
+ apiclient = self.apiclient
+ if value == CHILD_DOMAIN_ADMIN:
+ apiclient = self.testClient.getUserApiClient(
+ UserName=self.account.name,
+ DomainName=self.account.domain
+ )
+ self.assertNotEqual(apiclient, FAIL, "Failure while getting\
+ api client of account %s" % self.account.name)
+
+ try:
+ self.services["disk_offering"]["disksize"] = 5
+ disk_offering_5_GB = DiskOffering.create(self.apiclient,
+ services=self.services["disk_offering"])
+ self.cleanup.append(disk_offering_5_GB)
+
+ self.services["disk_offering"]["disksize"] = 10
+ disk_offering_10_GB = DiskOffering.create(self.apiclient,
+ services=self.services["disk_offering"])
+
+ self.cleanup.append(disk_offering_10_GB)
+
+ volume_1 = Volume.create(
+ apiclient,self.services["volume"],zoneid=self.zone.id,
+ account=self.account.name,domainid=self.account.domainid,
+ diskofferingid=disk_offering_5_GB.id)
+
+ volume_2 = Volume.create(
+ apiclient,self.services["volume"],zoneid=self.zone.id,
+ account=self.account.name,domainid=self.account.domainid,
+ diskofferingid=disk_offering_10_GB.id)
+
+ self.debug("Attaching volume %s to vm %s" % (volume_1.name, self.virtualMachine.name))
+ self.virtualMachine.attach_volume(apiclient, volume=volume_1)
+
+ self.debug("Attaching volume %s to vm %s" % (volume_2.name, self.virtualMachine.name))
+ self.virtualMachine.attach_volume(apiclient, volume=volume_2)
+ except Exception as e:
+ self.fail("Failure: %s" % e)
+
+ expectedCount = self.initialResourceCount + 15 # (5 + 10)
+ response = matchResourceCount(
+ self.apiclient, expectedCount,
+ RESOURCE_PRIMARY_STORAGE,
+ accountid=self.account.id)
+ self.assertEqual(response[0], PASS, response[1])
+
+ try:
+ # Detaching and deleting volume 1
+ self.virtualMachine.detach_volume(apiclient, volume=volume_1)
+ volume_1.delete(apiclient)
+ except Exception as e:
+ self.fail("Failure while volume operation: %s" % e)
+
+ expectedCount -= 5 #After deleting first volume
+ response = matchResourceCount(
+ self.apiclient, expectedCount,
+ RESOURCE_PRIMARY_STORAGE,
+ accountid=self.account.id)
+ self.assertEqual(response[0], PASS, response[1])
+
+ try:
+ # Detaching and deleting volume 2
+ self.virtualMachine.detach_volume(apiclient, volume=volume_2)
+ volume_2.delete(apiclient)
+ except Exception as e:
+ self.fail("Failure while volume operation: %s" % e)
+
+ expectedCount -= 10
+ response = matchResourceCount(
+ self.apiclient, expectedCount,
+ RESOURCE_PRIMARY_STORAGE,
+ accountid=self.account.id)
+ self.assertEqual(response[0], PASS, response[1])
+ return
+
+ @data(ROOT_DOMAIN_ADMIN, CHILD_DOMAIN_ADMIN)
+ @attr(tags=["advanced", "selfservice"])
+ def test_deploy_multiple_vm(self, value):
+ """Test Deploy multiple VMs with & verify the usage
+ # Validate the following
+ # 1. Deploy multiple VMs with this service offering
+ # 2. Update Resource count for the root admin Primary Storage usage
+ # 3. Primary Storage usage should list properly
+ # 4. Destroy one VM among multiple VM's and verify that primary storage count
+ # decreases by equivalent amount
+ """
+
+ response = self.setupAccount(value)
+ self.assertEqual(response[0], PASS, response[1])
+
+ self.virtualMachine_2 = VirtualMachine.create(self.api_client, self.services["virtual_machine"],
+ accountid=self.account.name, domainid=self.account.domainid,
+ diskofferingid=self.disk_offering.id,
+ serviceofferingid=self.service_offering.id)
+
+ expectedCount = (self.initialResourceCount * 2) #Total 2 vms
+ response = matchResourceCount(
+ self.apiclient, expectedCount,
+ RESOURCE_PRIMARY_STORAGE,
+ accountid=self.account.id)
+ self.assertEqual(response[0], PASS, response[1])
+
+ self.virtualMachine_3 = VirtualMachine.create(self.api_client, self.services["virtual_machine"],
+ accountid=self.account.name, domainid=self.account.domainid,
+ diskofferingid=self.disk_offering.id,
+ serviceofferingid=self.service_offering.id)
+
+ expectedCount = (self.initialResourceCount * 3) #Total 3 vms
+ response = matchResourceCount(
+ self.apiclient, expectedCount,
+ RESOURCE_PRIMARY_STORAGE,
+ accountid=self.account.id)
+ self.assertEqual(response[0], PASS, response[1])
+
+ self.debug("Destroying instance: %s" % self.virtualMachine_2.name)
+ try:
+ self.virtualMachine_2.delete(self.apiclient)
+ except Exception as e:
+ self.fail("Failed to delete instance: %s" % e)
+
+ self.assertTrue(isVmExpunged(self.apiclient, self.virtualMachine_2.id), "VM not expunged \
+ in allotted time")
+
+ expectedCount = (self.initialResourceCount * 2) #Total 2 vms
+ response = matchResourceCount(
+ self.apiclient, expectedCount,
+ RESOURCE_PRIMARY_STORAGE,
+ accountid=self.account.id)
+ self.assertEqual(response[0], PASS, response[1])
+ return
+
+ @data(ROOT_DOMAIN_ADMIN, CHILD_DOMAIN_ADMIN)
+ @attr(tags=["advanced","selfservice"])
+ def test_assign_vm_different_account(self, value):
+ """Test assign Vm to different account
+ # Validate the following
+ # 1. Deploy VM in account and check the primary storage resource count
+ # 2. Assign VM to another account
+ # 3. Resource count for first account should now equal to 0
+ # 4. Resource count for the account to which VM is assigned should
+ # increase to that of initial resource count of first account
+ """
+
+ response = self.setupAccount(value)
+ self.assertEqual(response[0], PASS, response[1])
+
+ try:
+ account_2 = Account.create(self.apiclient, self.services["account"],
+ domainid=self.domain.id, admin=True)
+ self.cleanup.insert(0, account_2)
+ except Exception as e:
+ self.fail("Failed to create account: %s" % e)
+
+ expectedCount = self.initialResourceCount
+ response = matchResourceCount(
+ self.apiclient, expectedCount,
+ RESOURCE_PRIMARY_STORAGE,
+ accountid=self.account.id)
+ self.assertEqual(response[0], PASS, response[1])
+
+ try:
+ self.virtualMachine.stop(self.apiclient)
+ self.virtualMachine.assign_virtual_machine(self.apiclient,
+ account_2.name ,account_2.domainid)
+ except Exception as e:
+ self.fail("Failed to assign virtual machine to account %s: %s" %
+ (account_2.name,e))
+
+ # Checking resource count for account 2
+ response = matchResourceCount(
+ self.apiclient, expectedCount,
+ RESOURCE_PRIMARY_STORAGE,
+ accountid=account_2.id)
+ self.assertEqual(response[0], PASS, response[1])
+
+ expectedCount = 0
+ # Checking resource count for original account
+ response = matchResourceCount(
+ self.apiclient, expectedCount,
+ RESOURCE_PRIMARY_STORAGE,
+ accountid=self.account.id)
+ self.assertEqual(response[0], PASS, response[1])
+ return
+
+ @data(ROOT_DOMAIN_ADMIN, CHILD_DOMAIN_ADMIN)
+ @attr(tags=["advanced", "selfservice"])
+ def test_create_template_snapshot(self, value):
+ """Test create snapshot and templates from volume
+
+ # Validate the following
+ # 1. Deploy VM with custoom disk offering and check the
+ # primary storage resource count
+ # 2. Stop the VM and create Snapshot from VM's volume
+ # 3. Create volume againt from this snapshto and attach to VM
+ # 4. Verify that primary storage count increases by the volume size
+ # 5. Detach and delete volume, verify primary storage count decreaes by volume size"""
+
+ response = self.setupAccount(value)
+ self.debug(response[0])
+ self.debug(response[1])
+ self.assertEqual(response[0], PASS, response[1])
+
+ apiclient = self.apiclient
+ if value == CHILD_DOMAIN_ADMIN:
+ apiclient = self.testClient.getUserApiClient(
+ UserName=self.account.name,
+ DomainName=self.account.domain
+ )
+ self.assertNotEqual(apiclient, FAIL, "Failure while getting api\
+ client of account: %s" % self.account.name)
+
+ try:
+ self.virtualMachine.stop(apiclient)
+ except Exception as e:
+ self.fail("Failed to stop instance: %s" % e)
+ expectedCount = self.initialResourceCount
+ response = matchResourceCount(
+ self.apiclient, expectedCount,
+ RESOURCE_PRIMARY_STORAGE,
+ accountid=self.account.id)
+ self.assertEqual(response[0], PASS, response[1])
+
+ self.debug("Creating snapshot from ROOT volume: %s" % self.virtualMachine.name)
+ snapshot = None
+ response = createSnapshotFromVirtualMachineVolume(apiclient, self.account, self.virtualMachine.id)
+ self.assertEqual(response[0], PASS, response[1])
+ snapshot = response[1]
+ response = matchResourceCount(
+ self.apiclient, expectedCount,
+ RESOURCE_PRIMARY_STORAGE,
+ accountid=self.account.id)
+ self.assertEqual(response[0], PASS, response[1])
+
+ try:
+ self.services["volume"]["size"] = self.services["disk_offering"]["disksize"]
+ volume = Volume.create_from_snapshot(apiclient,
+ snapshot_id=snapshot.id,
+ services=self.services["volume"],
+ account=self.account.name,
+ domainid=self.account.domainid)
+
+ self.debug("Attaching the volume to vm: %s" % self.virtualMachine.name)
+ self.virtualMachine.attach_volume(apiclient, volume)
+ except Exception as e:
+ self.fail("Failure in volume operation: %s" % e)
+
+ expectedCount += int(self.services["volume"]["size"])
+ response = matchResourceCount(
+ self.apiclient, expectedCount,
+ RESOURCE_PRIMARY_STORAGE,
+ accountid=self.account.id)
+ self.assertEqual(response[0], PASS, response[1])
+
+ try:
+ self.virtualMachine.detach_volume(apiclient, volume)
+ except Exception as e:
+ self.fail("Failure in detach volume operation: %s" % e)
+
+ response = matchResourceCount(
+ self.apiclient, expectedCount,
+ RESOURCE_PRIMARY_STORAGE,
+ accountid=self.account.id)
+ self.assertEqual(response[0], PASS, response[1])
+
+ try:
+ self.debug("deleting the volume: %s" % volume.name)
+ volume.delete(apiclient)
+ except Exception as e:
+ self.fail("Failure while deleting volume: %s" % e)
+
+ expectedCount -= int(self.services["volume"]["size"])
+ response = matchResourceCount(
+ self.apiclient, expectedCount,
+ RESOURCE_PRIMARY_STORAGE,
+ accountid=self.account.id)
+ self.assertEqual(response[0], PASS, response[1])
+ return
http://git-wip-us.apache.org/repos/asf/cloudstack/blob/e7fe391b/test/integration/component/test_ps_max_limits.py
----------------------------------------------------------------------
diff --git a/test/integration/component/test_ps_max_limits.py b/test/integration/component/test_ps_max_limits.py
new file mode 100644
index 0000000..8d047ef
--- /dev/null
+++ b/test/integration/component/test_ps_max_limits.py
@@ -0,0 +1,300 @@
+# 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.
+
+""" Tests for praimary storage - Maximum Limits
+
+ Test Plan: https://cwiki.apache.org/confluence/display/CLOUDSTACK/Limit+Resources+to+domain+or+accounts
+
+ Issue Link: https://issues.apache.org/jira/browse/CLOUDSTACK-1466
+
+ Feature Specifications: https://cwiki.apache.org/confluence/display/CLOUDSTACK/Limit+Resources+to+domains+and+accounts
+"""
+# Import Local Modules
+from nose.plugins.attrib import attr
+from marvin.cloudstackTestCase import cloudstackTestCase, unittest
+from marvin.lib.base import (Account,
+ ServiceOffering,
+ VirtualMachine,
+ Resources,
+ Domain,
+ Project,
+ Volume,
+ DiskOffering)
+from marvin.lib.common import (get_domain,
+ get_zone,
+ get_template)
+from marvin.lib.utils import (cleanup_resources,
+ validateList)
+from marvin.codes import PASS, FAIL
+
+class TestMaxPrimaryStorageLimits(cloudstackTestCase):
+
+ @classmethod
+ def setUpClass(cls):
+ cloudstackTestClient = super(TestMaxPrimaryStorageLimits,
+ 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.services["mode"] = cls.zone.networktype
+
+ 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.services["volume"]["zoneid"] = cls.zone.id
+ cls._cleanup = []
+ try:
+ cls.service_offering = ServiceOffering.create(cls.api_client, cls.services["service_offering"])
+ cls._cleanup.append(cls.service_offering)
+ except Exception as e:
+ cls.tearDownClass()
+ raise unittest.SkipTest("Exception 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:
+ response = self.setupAccounts()
+ if response[0] == FAIL:
+ self.skipTest("Failure while setting up accounts: %s" % response[1])
+ self.services["disk_offering"]["disksize"] = 2
+ self.disk_offering = DiskOffering.create(self.apiclient, self.services["disk_offering"])
+ self.cleanup.append(self.disk_offering)
+ except Exception as e:
+ self.tearDown()
+ self.skipTest("Failure in setup: %s" % e)
+ return
+
+ def tearDown(self):
+ try:
+ # Clean up, terminate the created instance, volumes and snapshots
+ cleanup_resources(self.apiclient, self.cleanup)
+ except Exception as e:
+ raise Exception("Warning: Exception during cleanup : %s" % e)
+ return
+
+ def setupAccounts(self):
+
+ try:
+ self.child_domain = Domain.create(self.apiclient,services=self.services["domain"],
+ parentdomainid=self.domain.id)
+
+ self.child_do_admin = Account.create(self.apiclient, self.services["account"], admin=True,
+ domainid=self.child_domain.id)
+
+ # Create project as a domain admin
+ self.project = Project.create(self.apiclient, self.services["project"],
+ account=self.child_do_admin.name,
+ domainid=self.child_do_admin.domainid)
+
+ # Cleanup created project at end of test
+ self.cleanup.append(self.project)
+
+ # Cleanup accounts created
+ self.cleanup.append(self.child_do_admin)
+ self.cleanup.append(self.child_domain)
+ except Exception as e:
+ return [FAIL, e]
+ return [PASS, None]
+
+ def updatePrimaryStorageLimits(self, accountLimit=None, domainLimit=None,
+ projectLimit=None):
+
+ try:
+ # Update resource limits for account
+ if accountLimit:
+ Resources.updateLimit(self.apiclient, resourcetype=10,
+ max=accountLimit, account=self.child_do_admin.name,
+ domainid=self.child_do_admin.domainid)
+
+ if projectLimit:
+ Resources.updateLimit(self.apiclient, resourcetype=10,
+ max=projectLimit, projectid=self.project.id)
+
+ if domainLimit:
+ Resources.updateLimit(self.apiclient, resourcetype=10,
+ max=domainLimit, domainid=self.child_domain.id)
+ except Exception as e:
+ return [FAIL, e]
+ return [PASS, None]
+
+ @attr(tags=["advanced","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
+
+ # Validate the following
+ # 1. Try to deploy VM with admin account where account has not used the
+ # resources but @ domain they are not available
+ # 2. Deploy VM should error out saying ResourceAllocationException
+ # with "resource limit exceeds"""
+
+ self.virtualMachine = VirtualMachine.create(self.api_client, self.services["virtual_machine"],
+ accountid=self.child_do_admin.name, domainid=self.child_do_admin.domainid,
+ serviceofferingid=self.service_offering.id)
+
+ accounts = Account.list(self.apiclient, id=self.child_do_admin.id)
+ self.assertEqual(validateList(accounts)[0], PASS,
+ "accounts list validation failed")
+
+ self.initialResourceCount = int(accounts[0].primarystoragetotal)
+ domainLimit = self.initialResourceCount + 3
+
+ self.debug("Setting up account and domain hierarchy")
+ response = self.updatePrimaryStorageLimits(domainLimit=domainLimit)
+ self.assertEqual(response[0], PASS, response[1])
+
+ self.services["volume"]["size"] = self.services["disk_offering"]["disksize"] = 2
+
+ try:
+ disk_offering = DiskOffering.create(self.apiclient,
+ services=self.services["disk_offering"])
+ self.cleanup.append(disk_offering)
+ Volume.create(self.apiclient,
+ self.services["volume"],
+ zoneid=self.zone.id,
+ account=self.child_do_admin.name,
+ domainid=self.child_do_admin.domainid,
+ diskofferingid=disk_offering.id)
+ except Exception as e:
+ self.fail("Exception occured: %s" % e)
+
+ with self.assertRaises(Exception):
+ Volume.create(self.apiclient,
+ self.services["volume"],
+ zoneid=self.zone.id,
+ account=self.child_do_admin.name,
+ domainid=self.child_do_admin.domainid,
+ diskofferingid=disk_offering.id)
+ return
+
+ @attr(tags=["advanced","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"""
+
+ self.virtualMachine = VirtualMachine.create(self.api_client, self.services["virtual_machine"],
+ accountid=self.child_do_admin.name, domainid=self.child_do_admin.domainid,
+ diskofferingid=self.disk_offering.id,
+ serviceofferingid=self.service_offering.id)
+
+ accounts = Account.list(self.apiclient, id=self.child_do_admin.id)
+ self.assertEqual(validateList(accounts)[0], PASS,
+ "accounts list validation failed")
+
+ self.initialResourceCount = int(accounts[0].primarystoragetotal)
+ accountLimit = self.initialResourceCount + 3
+
+ self.debug("Setting up account and domain hierarchy")
+ response = self.updatePrimaryStorageLimits(accountLimit=accountLimit)
+ self.assertEqual(response[0], PASS, response[1])
+
+ self.services["volume"]["size"] = self.services["disk_offering"]["disksize"] = 2
+
+ try:
+ disk_offering = DiskOffering.create(self.apiclient,
+ services=self.services["disk_offering"])
+ self.cleanup.append(disk_offering)
+ Volume.create(self.apiclient,
+ self.services["volume"],
+ zoneid=self.zone.id,
+ account=self.child_do_admin.name,
+ domainid=self.child_do_admin.domainid,
+ diskofferingid=disk_offering.id)
+ except Exception as e:
+ self.fail("failed to create volume: %s" % e)
+
+ with self.assertRaises(Exception):
+ Volume.create(self.apiclient,
+ self.services["volume"],
+ zoneid=self.zone.id,
+ account=self.child_do_admin.name,
+ domainid=self.child_do_admin.domainid,
+ diskofferingid=disk_offering.id)
+ return
+
+ @attr(tags=["advanced","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
+
+ # Validate the following
+ # 1. Try to deploy VM with admin account where account has not used the
+ # resources but @ project they are not available
+ # 2. Deploy VM should error out saying ResourceAllocationException
+ # with "resource limit exceeds"""
+
+ self.virtualMachine = VirtualMachine.create(self.api_client, self.services["virtual_machine"],
+ projectid=self.project.id,
+ diskofferingid=self.disk_offering.id,
+ serviceofferingid=self.service_offering.id)
+
+ try:
+ projects = Project.list(self.apiclient, id=self.project.id, listall=True)
+ except Exception as e:
+ self.fail("failed to get projects list: %s" % e)
+
+ self.assertEqual(validateList(projects)[0], PASS,
+ "projects list validation failed")
+ self.initialResourceCount = int(projects[0].primarystoragetotal)
+
+ projectLimit = self.initialResourceCount + 3
+
+ self.debug("Setting up account and domain hierarchy")
+ response = self.updatePrimaryStorageLimits(projectLimit=projectLimit)
+ self.assertEqual(response[0], PASS, response[1])
+
+ self.services["volume"]["size"] = self.services["disk_offering"]["disksize"] = 2
+
+ try:
+ disk_offering = DiskOffering.create(self.apiclient,
+ services=self.services["disk_offering"])
+ self.cleanup.append(disk_offering)
+ Volume.create(self.apiclient,
+ self.services["volume"],
+ zoneid=self.zone.id,
+ projectid=self.project.id,
+ diskofferingid=disk_offering.id)
+ except Exception as e:
+ self.fail("Exception occured: %s" % e)
+
+ with self.assertRaises(Exception):
+ Volume.create(self.apiclient,
+ self.services["volume"],
+ zoneid=self.zone.id,
+ projectid=self.project.id,
+ diskofferingid=disk_offering.id)
+ return
http://git-wip-us.apache.org/repos/asf/cloudstack/blob/e7fe391b/test/integration/component/test_ps_project_limits.py
----------------------------------------------------------------------
diff --git a/test/integration/component/test_ps_project_limits.py b/test/integration/component/test_ps_project_limits.py
new file mode 100644
index 0000000..471b4a1
--- /dev/null
+++ b/test/integration/component/test_ps_project_limits.py
@@ -0,0 +1,238 @@
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements. See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership. The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied. See the License for the
+# specific language governing permissions and limitations
+# under the License.
+
+""" P1 tests for primary storage Project limits
+
+ Test Plan: https://cwiki.apache.org/confluence/display/CLOUDSTACK/Limit+Resources+to+domain+or+accounts
+
+ Issue Link: https://issues.apache.org/jira/browse/CLOUDSTACK-1466
+
+ Feature Specifications: https://cwiki.apache.org/confluence/display/CLOUDSTACK/Limit+Resources+to+domains+and+accounts
+"""
+# Import Local Modules
+from nose.plugins.attrib import attr
+from marvin.cloudstackTestCase import cloudstackTestCase, unittest
+from marvin.lib.base import (Account,
+ ServiceOffering,
+ VirtualMachine,
+ Host,
+ Domain,
+ Project,
+ Volume)
+from marvin.lib.common import (get_domain,
+ get_zone,
+ get_template,
+ matchResourceCount,
+ isVmExpunged)
+from marvin.lib.utils import (cleanup_resources,
+ validateList)
+from marvin.codes import (PASS,
+ FAIL,
+ RESOURCE_PRIMARY_STORAGE)
+import time
+
+class TestProjectsVolumeLimits(cloudstackTestCase):
+
+ @classmethod
+ def setUpClass(cls):
+ cloudstackTestClient = super(TestProjectsVolumeLimits,
+ 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.services["mode"] = cls.zone.networktype
+
+ cls.template = get_template(
+ cls.api_client,
+ cls.zone.id,
+ cls.services["ostype"]
+ )
+
+ cls.services["virtual_machine"]["zoneid"] = cls.zone.id
+ cls.services["volume"]["zoneid"] = cls.zone.id
+ cls._cleanup = []
+ try:
+ cls.service_offering = ServiceOffering.create(cls.api_client, cls.services["service_offering"])
+ cls._cleanup.append(cls.service_offering)
+ except Exception as e:
+ cls.tearDownClass()
+ raise unittest.SkipTest("Exception 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 = []
+ response = self.setupProjectAccounts()
+ self.assertEqual(response[0], PASS, response[1])
+
+ try:
+ self.vm = VirtualMachine.create(
+ self.apiclient,self.services["virtual_machine"],
+ templateid=self.template.id,projectid=self.project.id,
+ serviceofferingid=self.service_offering.id)
+ projects = Project.list(self.apiclient,id=self.project.id, listall=True)
+ self.assertEqual(validateList(projects)[0], PASS,\
+ "projects list validation failed")
+ self.initialResourceCount = projects[0].primarystoragetotal
+ except Exception as e:
+ self.tearDown()
+ self.skipTest("Exception occured in setup: %s" % e)
+ return
+
+ def tearDown(self):
+ try:
+ # Clean up, terminate the created instance, volumes and snapshots
+ cleanup_resources(self.apiclient, self.cleanup)
+ pass
+ except Exception as e:
+ raise Exception("Warning: Exception during cleanup : %s" % e)
+ return
+
+ def setupProjectAccounts(self):
+
+ try:
+ self.domain = Domain.create(self.apiclient,
+ services=self.services["domain"],
+ parentdomainid=self.domain.id)
+ self.admin = Account.create(
+ self.apiclient, self.services["account"],
+ admin=True, domainid=self.domain.id)
+
+ # Create project as a domain admin
+ self.project = Project.create(
+ self.apiclient,self.services["project"],
+ account=self.admin.name,domainid=self.admin.domainid)
+ # Cleanup created project at end of test
+ self.cleanup.append(self.project)
+ self.cleanup.append(self.admin)
+ self.cleanup.append(self.domain)
+ except Exception as e:
+ return [FAIL, e]
+ return [PASS, None]
+
+ @attr(tags=["advanced", "selfservice"])
+ def test_01_VM_start_stop(self):
+ """Test project primary storage count with VM stop/start operation
+
+ # Validate the following
+ # 1. Create VM with custom disk offering in a project and check
+ # initial primary storage count
+ # 2. Stop the VM and verify primary storage count remains the same
+ # 3. Start the VM and verify priamay storage count remains the same
+ """
+
+ try:
+ self.vm.stop(self.apiclient)
+ except Exception as e:
+ self.fail("Faield to stop VM: %s" % e)
+
+ expectedCount = self.initialResourceCount
+ response = matchResourceCount(
+ self.apiclient, expectedCount,
+ RESOURCE_PRIMARY_STORAGE,
+ projectid=self.project.id)
+ self.assertEqual(response[0], PASS, response[1])
+
+ try:
+ self.vm.start(self.apiclient)
+ except Exception as e:
+ self.fail("Failed to start VM: %s" % e)
+
+ response = matchResourceCount(
+ self.apiclient, expectedCount,
+ RESOURCE_PRIMARY_STORAGE,
+ projectid=self.project.id)
+ self.assertEqual(response[0], PASS, response[1])
+ return
+
+ @attr(tags=["advanced", "selfservice"])
+ def test_02_migrate_vm(self):
+ """Test migrate VM in project
+
+ # Validate the following
+ # 1. Create VM with custom disk offering in a project and check
+ # initial primary storage count
+ # 2. List the hosts suitable for migrating the VM
+ # 3. Migrate the VM and verify that primary storage count of project remains same"""
+
+ try:
+ hosts = Host.list(self.apiclient,virtualmachineid=self.vm.id,
+ listall=True)
+ self.assertEqual(validateList(hosts)[0], PASS, "hosts list validation failed")
+ host = hosts[0]
+ self.vm.migrate(self.apiclient, host.id)
+ except Exception as e:
+ self.fail("Exception occured" % e)
+
+ expectedCount = self.initialResourceCount
+ response = matchResourceCount(
+ self.apiclient, expectedCount,
+ RESOURCE_PRIMARY_STORAGE,
+ projectid=self.project.id)
+ self.assertEqual(response[0], PASS, response[1])
+ return
+
+ @attr(tags=["advanced", "selfservice"])
+ def test_03_delete_vm(self):
+ """Test delete VM belonging to project
+
+ # Validate the following
+ # 1. Create VM with custom disk offering in a project and check
+ # initial primary storage count
+ # 2. Delete VM and verify that it's expunged
+ # 3. Verify that primary storage count of project equals 0"""
+
+ try:
+ self.vm.delete(self.apiclient)
+ except Exception as e:
+ self.fail("Failed to detroy VM: %s" % e)
+
+ self.assertTrue(isVmExpunged(self.apiclient, self.vm.id, self.project.id),\
+ "VM not expunged")
+
+ totalallottedtime = timeout = 600
+ while timeout >= 0:
+ volumes = Volume.list(self.apiclient, projectid=self.project.id, listall=True)
+ if volumes is None:
+ break
+ if timeout == 0:
+ self.fail("Volume attached to VM not cleaned up even\
+ after %s seconds" % totalallottedtime)
+ timeout -= 60
+ time.sleep(60)
+
+ expectedCount = 0
+ response = matchResourceCount(
+ self.apiclient, expectedCount,
+ RESOURCE_PRIMARY_STORAGE,
+ projectid=self.project.id)
+ self.assertEqual(response[0], PASS, response[1])
+ return