cloudstack-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From r...@apache.org
Subject [1/2] git commit: updated refs/heads/master to 4ffad54
Date Thu, 03 Dec 2015 08:43:56 GMT
Repository: cloudstack
Updated Branches:
  refs/heads/master df6343452 -> 4ffad548a


CLOUDSTACK-9080: Resource limits for Primary arent respected during attach.

primary store resource limit check is not performed while attaching a
volume to a vm. Added them same.
Also added a marvin test case to verify the same.


Project: http://git-wip-us.apache.org/repos/asf/cloudstack/repo
Commit: http://git-wip-us.apache.org/repos/asf/cloudstack/commit/25626349
Tree: http://git-wip-us.apache.org/repos/asf/cloudstack/tree/25626349
Diff: http://git-wip-us.apache.org/repos/asf/cloudstack/diff/25626349

Branch: refs/heads/master
Commit: 256263492f10643a77d0f50ec8ec38d81a253e49
Parents: 8afda59
Author: Rajani Karuturi <rajanikaruturi@gmail.com>
Authored: Thu May 21 16:50:39 2015 +0530
Committer: Rajani Karuturi <rajani.karuturi@citrix.com>
Committed: Tue Nov 24 11:59:31 2015 +0530

----------------------------------------------------------------------
 .../com/cloud/storage/VolumeApiServiceImpl.java |   9 +
 .../component/test_ps_resource_limits_volume.py | 172 +++++++++++++++++++
 2 files changed, 181 insertions(+)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/cloudstack/blob/25626349/server/src/com/cloud/storage/VolumeApiServiceImpl.java
----------------------------------------------------------------------
diff --git a/server/src/com/cloud/storage/VolumeApiServiceImpl.java b/server/src/com/cloud/storage/VolumeApiServiceImpl.java
index 8f29167..8a77629 100644
--- a/server/src/com/cloud/storage/VolumeApiServiceImpl.java
+++ b/server/src/com/cloud/storage/VolumeApiServiceImpl.java
@@ -1443,6 +1443,15 @@ public class VolumeApiServiceImpl extends ManagerBase implements VolumeApiServic
             throw new InvalidParameterValueException("Volume state must be in Allocated,
Ready or in Uploaded state");
         }
 
+        Account owner = _accountDao.findById(volumeToAttach.getAccountId());
+
+        try {
+            _resourceLimitMgr.checkResourceLimit(owner, ResourceType.primary_storage, volumeToAttach.getSize());
+        } catch (ResourceAllocationException e) {
+            s_logger.error("primary storage resource limit check failed", e);
+            throw new InvalidParameterValueException(e.getMessage());
+        }
+
         HypervisorType rootDiskHyperType = vm.getHypervisorType();
         HypervisorType volumeToAttachHyperType = _volsDao.getHypervisorType(volumeToAttach.getId());
 

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/25626349/test/integration/component/test_ps_resource_limits_volume.py
----------------------------------------------------------------------
diff --git a/test/integration/component/test_ps_resource_limits_volume.py b/test/integration/component/test_ps_resource_limits_volume.py
new file mode 100644
index 0000000..1e86557
--- /dev/null
+++ b/test/integration/component/test_ps_resource_limits_volume.py
@@ -0,0 +1,172 @@
+# 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 primary storage limits during upload volume
+"""
+import unittest
+
+from ddt import ddt, data
+from marvin.cloudstackTestCase import cloudstackTestCase
+from marvin.codes import PASS, RESOURCE_PRIMARY_STORAGE, FAIL, USER_ACCOUNT
+from marvin.lib.base import Domain, Account, VirtualMachine, DiskOffering, ServiceOffering,
Volume
+from marvin.lib.common import get_domain, get_zone, update_resource_limit, uploadVolume,
matchResourceCount, get_template
+from marvin.lib.utils import cleanup_resources, validateList
+from nose.plugins.attrib import attr
+
+
+@ddt
+class TestPrimaryResourceLimitsVolume(cloudstackTestCase):
+    @classmethod
+    def setUpClass(cls):
+        cloudstacktestclient = super(TestPrimaryResourceLimitsVolume,
+                                     cls).getClsTestClient()
+        cls.api_client = cloudstacktestclient.getApiClient()
+        cls.hypervisor = cloudstacktestclient.getHypervisorInfo()
+        # 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._cleanup = []
+        cls.unsupportedStorageType = False
+        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
+        try:
+            cls.service_offering = ServiceOffering.create(cls.api_client, cls.services["service_offering"])
+            cls.services["disk_offering"]["disksize"] = 2
+            cls.disk_offering = DiskOffering.create(cls.api_client, cls.services["disk_offering"])
+            cls._cleanup.append(cls.service_offering)
+            cls._cleanup.append(cls.disk_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 = []
+        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 setupNormalAccount(self):
+        """Setup the account required for the test"""
+
+        try:
+            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=False)
+            self.cleanup.append(self.account)
+            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)
+
+            primarystoragelimit = self.initialResourceCount
+            update_resource_limit(self.api_client, RESOURCE_PRIMARY_STORAGE, account=self.account.name,
domainid=self.account.domainid, max=primarystoragelimit)
+
+        except Exception as e:
+            return [FAIL, e]
+        return [PASS, None]
+
+    # @data(USER_ACCOUNT)
+    @attr(tags=["advanced","basic"], required_hardware="true")
+    def test_attach_volume_exceeding_primary_limits(self):
+        """
+        # do
+        # 1. create a normal user account and update primary store limits to the current
resource count
+        # 2. Upload a volume of any size
+        # 3. Verify that upload volume succeeds
+        # 4. Verify that primary storage count doesnt change
+        # 6. Try attaching volume to VM and verify that the attach fails (as the resource
limits exceed)
+        # 7. Verify that primary storage count doesnt change
+        # done
+        """
+        # create an account, launch a vm with default template and custom disk offering,
update the primary store limits to the current primary store resource count
+        response = self.setupNormalAccount()
+        self.assertEqual(response[0], PASS, response[1])
+
+        # upload volume and verify that the volume is uploaded
+        volume = Volume.upload(self.apiclient, self.services["configurableData"]["upload_volume"],
+                               zoneid=self.zone.id, account=self.account.name,
+                               domainid=self.account.domainid, url="http://people.apache.org/~sanjeev/rajani-thin-volume.vhd")
+
+        volume.wait_for_upload(self.apiclient)
+        volumes = Volume.list(self.apiclient, id=volume.id,
+                              zoneid=self.zone.id, 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
+
+        # verify that the resource count didnt change due to upload volume
+        response = matchResourceCount(
+            self.apiclient, self.initialResourceCount,
+            RESOURCE_PRIMARY_STORAGE,
+            accountid=self.account.id)
+        self.assertEqual(response[0], PASS, response[1])
+
+        # attach the above volume to the vm
+        try:
+            self.virtualMachine.attach_volume(self.apiclient, volume=volume)
+        except Exception as e:
+            if "Maximum number of resources of type \'primary_storage\' for account name="+self.account.name
in e.message:
+                self.assertTrue(True, "there should be primary store resource limit reached
exception")
+            else:
+                self.fail("only resource limit reached exception is expected. some other
exception occurred. Failing the test case.")
+
+        # resource count should match as the attach should fail due to reaching resource
limits
+        response = matchResourceCount(
+                self.apiclient, self.initialResourceCount,
+                RESOURCE_PRIMARY_STORAGE,
+                accountid=self.account.id)
+        self.assertEqual(response[0], PASS, response[1])
+
+        return
+


Mime
View raw message