You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@cloudstack.apache.org by GitBox <gi...@apache.org> on 2021/09/20 09:26:24 UTC

[GitHub] [cloudstack] shwstppr opened a new pull request #5473: api,server: add params for updatehypervisorcapabilities API

shwstppr opened a new pull request #5473:
URL: https://github.com/apache/cloudstack/pull/5473


   ### Description
   
   Allows updating following capabilities for a hypervisor, version:
   - Max DATA volumes limit
   - Storage motion supported
   - Max hosts per cluster
   - VM snapshot enabled
   
   ### Types of changes
   
   - [ ] Breaking change (fix or feature that would cause existing functionality to change)
   - [ ] New feature (non-breaking change which adds functionality)
   - [ ] Bug fix (non-breaking change which fixes an issue)
   - [x] Enhancement (improves an existing feature and functionality)
   - [ ] Cleanup (Code refactoring and cleanup, that may add test cases)
   
   ### Feature/Enhancement Scale or Bug Severity
   
   #### Feature/Enhancement Scale
   
   - [ ] Major
   - [ ] Minor
   
   #### Bug Severity
   
   - [ ] BLOCKER
   - [ ] Critical
   - [ ] Major
   - [ ] Minor
   - [ ] Trivial
   
   
   ### Screenshots (if appropriate):
   
   
   ### How Has This Been Tested?
   Using cmk:
   
   ```
   (local) 🦌 > list hypervisorcapabilities id=7e83442b-19ed-11ec-93bc-645d8651f45a
   {
     "count": 1,
     "hypervisorCapabilities": [
       {
         "hypervisor": "Simulator",
         "hypervisorversion": "default",
         "id": "7e83442b-19ed-11ec-93bc-645d8651f45a",
         "maxdatavolumeslimit": 6,
         "maxguestslimit": 50,
         "securitygroupenabled": true,
         "storagemotionenabled": true,
         "vmsnapshotenabled": false
       }
     ]
   }
   (local) 🦅 > update hypervisorcapabilities id=7e83442b-19ed-11ec-93bc-645d8651f45a maxdatavolumeslimit=32 maxguestslimit=64 securitygroupenabled=false storagemotionenabled=false vmsnapshotenabled=true maxhostspercluster=10
   {
     "null": {
       "hypervisor": "Simulator",
       "hypervisorversion": "default",
       "id": "7e83442b-19ed-11ec-93bc-645d8651f45a",
       "maxdatavolumeslimit": 32,
       "maxguestslimit": 64,
       "maxhostspercluster": 10,
       "securitygroupenabled": false,
       "storagemotionenabled": false,
       "vmsnapshotenabled": true
     }
   }
   ```
   


-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: commits-unsubscribe@cloudstack.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org



[GitHub] [cloudstack] sureshanaparti commented on pull request #5473: api,server: add params for updatehypervisorcapabilities API

Posted by GitBox <gi...@apache.org>.
sureshanaparti commented on pull request #5473:
URL: https://github.com/apache/cloudstack/pull/5473#issuecomment-1027870604


   @blueorangutan test


-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: commits-unsubscribe@cloudstack.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org



[GitHub] [cloudstack] sureshanaparti commented on pull request #5473: api,server: add params for updatehypervisorcapabilities API

Posted by GitBox <gi...@apache.org>.
sureshanaparti commented on pull request #5473:
URL: https://github.com/apache/cloudstack/pull/5473#issuecomment-1012103206


   @shwstppr Is this PR ready?


-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: commits-unsubscribe@cloudstack.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org



[GitHub] [cloudstack] shwstppr commented on pull request #5473: api,server: add params for updatehypervisorcapabilities API

Posted by GitBox <gi...@apache.org>.
shwstppr commented on pull request #5473:
URL: https://github.com/apache/cloudstack/pull/5473#issuecomment-1024175813


   @DaanHoogland can you please have a look at the integration test added in the last commit. Should it be under components or smoke?


-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: commits-unsubscribe@cloudstack.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org



[GitHub] [cloudstack] blueorangutan commented on pull request #5473: api,server: add params for updatehypervisorcapabilities API

Posted by GitBox <gi...@apache.org>.
blueorangutan commented on pull request #5473:
URL: https://github.com/apache/cloudstack/pull/5473#issuecomment-1027833722


   @sureshanaparti a Jenkins job has been kicked to build packages. I'll keep you posted as I make progress.


-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: commits-unsubscribe@cloudstack.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org



[GitHub] [cloudstack] shwstppr commented on pull request #5473: api,server: add params for updatehypervisorcapabilities API

Posted by GitBox <gi...@apache.org>.
shwstppr commented on pull request #5473:
URL: https://github.com/apache/cloudstack/pull/5473#issuecomment-922764388


   @blueorangutan package


-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: commits-unsubscribe@cloudstack.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org



[GitHub] [cloudstack] shwstppr commented on a change in pull request #5473: api,server: add params for updatehypervisorcapabilities API

Posted by GitBox <gi...@apache.org>.
shwstppr commented on a change in pull request #5473:
URL: https://github.com/apache/cloudstack/pull/5473#discussion_r794721757



##########
File path: test/integration/smoke/test_hypervisor_capabilities.py
##########
@@ -0,0 +1,291 @@
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements.  See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership.  The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License.  You may obtain a copy of the License at
+#
+#   http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied.  See the License for the
+# specific language governing permissions and limitations
+# under the License.
+""" Test cases for Testing Hypervisor Capabilities
+"""
+from nose.plugins.attrib import attr
+from marvin.cloudstackTestCase import cloudstackTestCase
+from marvin.lib.utils import (cleanup_resources,
+                              validateList)
+from marvin.lib.base import (Account,
+                             ServiceOffering,
+                             DiskOffering,
+                             VirtualMachine,
+                             Volume,
+                             Host,
+                             VmSnapshot)
+from marvin.lib.common import (get_domain,
+                               get_zone,
+                               get_template,
+                               list_virtual_machines,
+                               list_ssvms,
+                               list_routers)
+from marvin.lib.decoratorGenerators import skipTestIf
+
+
+from marvin.cloudstackAPI import (updateHypervisorCapabilities,
+                                  listHypervisorCapabilities)
+
+from marvin.codes import PASS
+
+
+class TestHypervisorCapabilities(cloudstackTestCase):
+
+    @classmethod
+    def setUpClass(cls):
+        testClient = super(TestHypervisorCapabilities, cls).getClsTestClient()
+        cls.apiclient = testClient.getApiClient()
+        cls.services = testClient.getParsedTestDataConfig()
+        cls.zone = get_zone(cls.apiclient, testClient.getZoneForTests())
+        cls.domain = get_domain(cls.apiclient)
+
+        cls.hypervisor = cls.testClient.getHypervisorInfo()
+        # Get Zone, Domain and templates
+
+        cls.notSupported = True
+        cls._cleanup = []
+        cls.hosts = Host.list(cls.apiclient, zoneid=cls.zone.id, type='Routing')
+        if isinstance(cls.hosts, list) and len(cls.hosts) > 0:
+            cls.host = cls.hosts[0]
+            cls.notSupported = False
+
+        cls.hypervisorversion = "default"
+        if hasattr(cls.host, 'hypervisorversion'):
+            cls.hypervisorversion = cls.host.hypervisorversion
+
+        if cls.notSupported == False:
+            cls.notSupported = True
+            cmdList = listHypervisorCapabilities.listHypervisorCapabilitiesCmd()
+            cmdList.hypervisor = cls.hypervisor
+            capabilities = cls.apiclient.listHypervisorCapabilities(cmdList)
+            for capability in capabilities:
+                if capability.hypervisorversion == cls.hypervisorversion:
+                   cls.hostCapability = capability
+                   cls.notSupported = False
+                   break
+
+            if cls.notSupported == True:
+                cls.hypervisorversion = "default"
+                for capability in capabilities:
+                    if capability.hypervisorversion == cls.hypervisorversion:
+                       cls.hostCapability = capability
+                       cls.notSupported = False
+                       break
+
+        print("Test-- %s, %s, %s" % (cls.notSupported, cls.hostCapability.id, cls.hostCapability.maxdatavolumeslimit))
+        if cls.notSupported == False:
+            cls.template = get_template(
+                cls.apiclient,
+                cls.zone.id,
+                cls.services["ostype"])
+
+            # Create an account
+            cls.account = Account.create(
+                cls.apiclient,
+                cls.services["account"],
+                domainid=cls.domain.id
+            )
+            cls._cleanup.append(cls.account)
+
+            # Create user api client of the account
+            cls.userapiclient = testClient.getUserApiClient(
+                UserName=cls.account.name,
+                DomainName=cls.account.domain
+            )
+            # Create Service offering
+            cls.service_offering = ServiceOffering.create(
+                cls.apiclient,
+                cls.services["service_offering"],
+                hosttags="host1"
+            )
+            cls._cleanup.append(cls.service_offering)
+
+            cls.disk_offering = DiskOffering.create(
+                cls.apiclient,
+                cls.services["disk_offering"]
+            )
+            cls._cleanup.append(cls.disk_offering)
+
+        return
+
+    @classmethod
+    def tearDownClass(cls):
+        try:
+            cleanup_resources(cls.apiclient, cls._cleanup)
+        except Exception as e:
+            raise Exception("Warning: Exception during cleanup : %s" % e)
+
+    def setUp(self):
+        self.cleanup = []
+
+        self.apiclient = self.testClient.getApiClient()
+        self.dbclient = self.testClient.getDbConnection()
+
+    def tearDown(self):
+        try:
+            if self.notSupported == False:
+                Host.update(self.apiclient, id=self.host.id, hosttags="")
+                self.updateHostHypervisorCapability(self.hostCapability.id,
+                    self.hostCapability.maxdatavolumeslimit,
+                    self.hostCapability.vmsnapshotenabled)
+
+            cleanup_resources(self.apiclient, self.cleanup)
+        except Exception as e:
+            raise Exception("Warning: Exception during cleanup : %s" % e)
+        return
+
+    @skipTestIf("notSupported")
+    @attr(tags=["advanced", "basic"], required_hardware="false")
+    def test_01_check_hypervisor_max_data_volume_limit(self):
+        """ Test hypervisor maxdatavolumeslimit effect
+
+        # 1. Set maxdatavolumeslimit to 1 for hypervisor
+        # 2. List capabilities and verify value
+        # 3. Deploy a VM and attach a volume to it
+        # 4. Try attach another volume, it should fail
+        # 5. Set maxdatavolumeslimit to 32 for hypervisor
+        # 6. Try attach second volume, it should succeed
+        """
+        self.updateHostHypervisorCapability(self.hostCapability.id, 1)
+        capabilities = self.listHostHypervisorCapabilities(self.hostCapability.id)
+        self.assertTrue(isinstance(capabilities, list), "listHypervisorCapabilities response not a valid list")
+        self.assertEqual(len(capabilities), 1, "listHypervisorCapabilities response not valid")
+        self.assertEqual(capabilities[0].maxdatavolumeslimit,
+            1,
+            "listHypervisorCapabilities response maxdatavolumeslimit value not 1")
+
+        Host.update(self.apiclient, id=self.host.id, hosttags="host1")
+        vm = VirtualMachine.create(
+            self.userapiclient,
+            self.services["small"],
+            templateid=self.template.id,
+            accountid=self.account.name,
+            domainid=self.account.domainid,
+            serviceofferingid=self.service_offering.id,
+            zoneid=self.zone.id
+        )
+        volume_created1 = Volume.create(
+            self.userapiclient,
+            self.services["volume"],
+            zoneid=self.zone.id,
+            diskofferingid=self.disk_offering.id
+        )
+        volume_created2 = Volume.create(
+            self.userapiclient,
+            self.services["volume"],
+            zoneid=self.zone.id,
+            diskofferingid=self.disk_offering.id
+        )
+        self.cleanup.append(volume_created1)
+        self.cleanup.append(volume_created2)
+        self.cleanup.append(vm)
+
+        vm.attach_volume(
+            self.userapiclient,
+            volume_created1
+        )
+
+        try:
+            vm.attach_volume(
+                self.userapiclient,
+                volume_created2
+            )
+            vm.detach_volume(self.userapiclient, volume_created1)
+            vm.detach_volume(self.userapiclient, volume_created2)
+            self.fail("Successful to attach 2 DATA disks when max DATA disk limit was set to 1")
+        except Exception as e:
+            self.debug("Failed to attach 2nd DATA disk when max DATA disk limit was set to 1: %s" % e)
+
+        self.updateHostHypervisorCapability(self.hostCapability.id, 32)
+
+        vm.attach_volume(
+            self.userapiclient,
+            volume_created2
+        )
+        vm.detach_volume(self.userapiclient, volume_created1)
+        vm.detach_volume(self.userapiclient, volume_created2)
+
+    @skipTestIf("notSupported")
+    @attr(tags=["advanced", "basic"], required_hardware="false")
+    def test_01_check_hypervisor_vm_snapshot(self):
+        """ Test hypervisor vmsnapshotenabled effect
+
+        # 1. Set vmsnapshotenabled to false for hypervisor
+        # 2. List capabilities and verify value
+        # 3. Deploy a VM
+        # 4. Try VM snapshot, it should fail
+        # 5. Set vmsnapshotenabled to true for hypervisor
+        # 6. Try VM snapshot again, it should succeed
+        """
+        self.updateHostHypervisorCapability(self.hostCapability.id, None, False)
+        capabilities = self.listHostHypervisorCapabilities(self.hostCapability.id)
+        self.assertTrue(isinstance(capabilities, list), "listHypervisorCapabilities response not a valid list")
+        self.assertEqual(len(capabilities), 1, "listHypervisorCapabilities response not valid")
+        self.assertEqual(capabilities[0].vmsnapshotenabled,
+            False,
+            "listHypervisorCapabilities response vmsnapshotenabled value not False")
+
+        Host.update(self.apiclient, id=self.host.id, hosttags="host1")
+        vm = VirtualMachine.create(
+            self.userapiclient,
+            self.services["small"],
+            templateid=self.template.id,
+            accountid=self.account.name,
+            domainid=self.account.domainid,
+            serviceofferingid=self.service_offering.id,
+            zoneid=self.zone.id
+        )
+
+        try:
+            fail_snapshot = VmSnapshot.create(
+                self.userapiclient,
+                vmid=vm.id,
+                snapshotmemory="false",
+                name="Test Snapshot",
+                description="Test Snapshot Desc"
+            )
+            if vm_snapshot:
+                VmSnapshot.deleteVMSnapshot(self.userapiclient, fail_snapshot.id)
+            self.fail("Successful to take VM snapshot even when vmsnapshotenabled was set to False")
+        except Exception as e:
+            self.debug("Failed to take VM snapshot even vmsnapshotenabled was set to False: %s" % e)
+
+        self.updateHostHypervisorCapability(self.hostCapability.id, None, True)
+
+        vm_snapshot = VmSnapshot.create(
+            self.userapiclient,
+            vmid=vm.id,
+            snapshotmemory="false",
+            name="Test Snapshot",
+            description="Test Snapshot Desc"
+        )
+        if vm_snapshot:
+            VmSnapshot.deleteVMSnapshot(self.userapiclient, vm_snapshot.id)

Review comment:
       @DaanHoogland this doesn't work




-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: commits-unsubscribe@cloudstack.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org



[GitHub] [cloudstack] blueorangutan commented on pull request #5473: api,server: add params for updatehypervisorcapabilities API

Posted by GitBox <gi...@apache.org>.
blueorangutan commented on pull request #5473:
URL: https://github.com/apache/cloudstack/pull/5473#issuecomment-1025446563


   <b>Trillian test result (tid-3063)</b>
   Environment: kvm-centos7 (x2), Advanced Networking with Mgmt server 7
   Total time taken: 36361 seconds
   Marvin logs: https://github.com/blueorangutan/acs-prs/releases/download/trillian/pr5473-t3063-kvm-centos7.zip
   Smoke tests completed. 92 look OK, 1 have errors
   Only failed tests results shown below:
   
   
   Test | Result | Time (s) | Test File
   --- | --- | --- | ---
   test_01_check_hypervisor_max_data_volume_limit | `Error` | 89.58 | test_hypervisor_capabilities.py
   test_01_check_hypervisor_vm_snapshot | `Error` | 43.71 | test_hypervisor_capabilities.py
   


-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: commits-unsubscribe@cloudstack.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org



[GitHub] [cloudstack] sureshanaparti commented on pull request #5473: api,server: add params for updatehypervisorcapabilities API

Posted by GitBox <gi...@apache.org>.
sureshanaparti commented on pull request #5473:
URL: https://github.com/apache/cloudstack/pull/5473#issuecomment-1025227597


   @blueorangutan test


-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: commits-unsubscribe@cloudstack.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org



[GitHub] [cloudstack] shwstppr commented on a change in pull request #5473: api,server: add params for updatehypervisorcapabilities API

Posted by GitBox <gi...@apache.org>.
shwstppr commented on a change in pull request #5473:
URL: https://github.com/apache/cloudstack/pull/5473#discussion_r794774410



##########
File path: test/integration/smoke/test_hypervisor_capabilities.py
##########
@@ -0,0 +1,291 @@
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements.  See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership.  The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License.  You may obtain a copy of the License at
+#
+#   http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied.  See the License for the
+# specific language governing permissions and limitations
+# under the License.
+""" Test cases for Testing Hypervisor Capabilities
+"""
+from nose.plugins.attrib import attr
+from marvin.cloudstackTestCase import cloudstackTestCase
+from marvin.lib.utils import (cleanup_resources,
+                              validateList)
+from marvin.lib.base import (Account,
+                             ServiceOffering,
+                             DiskOffering,
+                             VirtualMachine,
+                             Volume,
+                             Host,
+                             VmSnapshot)
+from marvin.lib.common import (get_domain,
+                               get_zone,
+                               get_template,
+                               list_virtual_machines,
+                               list_ssvms,
+                               list_routers)
+from marvin.lib.decoratorGenerators import skipTestIf
+
+
+from marvin.cloudstackAPI import (updateHypervisorCapabilities,
+                                  listHypervisorCapabilities)
+
+from marvin.codes import PASS
+
+
+class TestHypervisorCapabilities(cloudstackTestCase):
+
+    @classmethod
+    def setUpClass(cls):
+        testClient = super(TestHypervisorCapabilities, cls).getClsTestClient()
+        cls.apiclient = testClient.getApiClient()
+        cls.services = testClient.getParsedTestDataConfig()
+        cls.zone = get_zone(cls.apiclient, testClient.getZoneForTests())
+        cls.domain = get_domain(cls.apiclient)
+
+        cls.hypervisor = cls.testClient.getHypervisorInfo()
+        # Get Zone, Domain and templates
+
+        cls.notSupported = True
+        cls._cleanup = []
+        cls.hosts = Host.list(cls.apiclient, zoneid=cls.zone.id, type='Routing')
+        if isinstance(cls.hosts, list) and len(cls.hosts) > 0:
+            cls.host = cls.hosts[0]
+            cls.notSupported = False
+
+        cls.hypervisorversion = "default"
+        if hasattr(cls.host, 'hypervisorversion'):
+            cls.hypervisorversion = cls.host.hypervisorversion
+
+        if cls.notSupported == False:
+            cls.notSupported = True
+            cmdList = listHypervisorCapabilities.listHypervisorCapabilitiesCmd()
+            cmdList.hypervisor = cls.hypervisor
+            capabilities = cls.apiclient.listHypervisorCapabilities(cmdList)
+            for capability in capabilities:
+                if capability.hypervisorversion == cls.hypervisorversion:
+                   cls.hostCapability = capability
+                   cls.notSupported = False
+                   break
+
+            if cls.notSupported == True:
+                cls.hypervisorversion = "default"
+                for capability in capabilities:
+                    if capability.hypervisorversion == cls.hypervisorversion:
+                       cls.hostCapability = capability
+                       cls.notSupported = False
+                       break
+
+        print("Test-- %s, %s, %s" % (cls.notSupported, cls.hostCapability.id, cls.hostCapability.maxdatavolumeslimit))
+        if cls.notSupported == False:
+            cls.template = get_template(
+                cls.apiclient,
+                cls.zone.id,
+                cls.services["ostype"])
+
+            # Create an account
+            cls.account = Account.create(
+                cls.apiclient,
+                cls.services["account"],
+                domainid=cls.domain.id
+            )
+            cls._cleanup.append(cls.account)
+
+            # Create user api client of the account
+            cls.userapiclient = testClient.getUserApiClient(
+                UserName=cls.account.name,
+                DomainName=cls.account.domain
+            )
+            # Create Service offering
+            cls.service_offering = ServiceOffering.create(
+                cls.apiclient,
+                cls.services["service_offering"],
+                hosttags="host1"
+            )
+            cls._cleanup.append(cls.service_offering)
+
+            cls.disk_offering = DiskOffering.create(
+                cls.apiclient,
+                cls.services["disk_offering"]
+            )
+            cls._cleanup.append(cls.disk_offering)
+
+        return
+
+    @classmethod
+    def tearDownClass(cls):
+        try:
+            cleanup_resources(cls.apiclient, cls._cleanup)
+        except Exception as e:
+            raise Exception("Warning: Exception during cleanup : %s" % e)
+
+    def setUp(self):
+        self.cleanup = []
+
+        self.apiclient = self.testClient.getApiClient()
+        self.dbclient = self.testClient.getDbConnection()
+
+    def tearDown(self):
+        try:
+            if self.notSupported == False:
+                Host.update(self.apiclient, id=self.host.id, hosttags="")
+                self.updateHostHypervisorCapability(self.hostCapability.id,
+                    self.hostCapability.maxdatavolumeslimit,
+                    self.hostCapability.vmsnapshotenabled)
+
+            cleanup_resources(self.apiclient, self.cleanup)
+        except Exception as e:
+            raise Exception("Warning: Exception during cleanup : %s" % e)
+        return
+
+    @skipTestIf("notSupported")
+    @attr(tags=["advanced", "basic"], required_hardware="false")
+    def test_01_check_hypervisor_max_data_volume_limit(self):
+        """ Test hypervisor maxdatavolumeslimit effect
+
+        # 1. Set maxdatavolumeslimit to 1 for hypervisor
+        # 2. List capabilities and verify value
+        # 3. Deploy a VM and attach a volume to it
+        # 4. Try attach another volume, it should fail
+        # 5. Set maxdatavolumeslimit to 32 for hypervisor
+        # 6. Try attach second volume, it should succeed
+        """
+        self.updateHostHypervisorCapability(self.hostCapability.id, 1)
+        capabilities = self.listHostHypervisorCapabilities(self.hostCapability.id)
+        self.assertTrue(isinstance(capabilities, list), "listHypervisorCapabilities response not a valid list")
+        self.assertEqual(len(capabilities), 1, "listHypervisorCapabilities response not valid")
+        self.assertEqual(capabilities[0].maxdatavolumeslimit,
+            1,
+            "listHypervisorCapabilities response maxdatavolumeslimit value not 1")
+
+        Host.update(self.apiclient, id=self.host.id, hosttags="host1")
+        vm = VirtualMachine.create(
+            self.userapiclient,
+            self.services["small"],
+            templateid=self.template.id,
+            accountid=self.account.name,
+            domainid=self.account.domainid,
+            serviceofferingid=self.service_offering.id,
+            zoneid=self.zone.id
+        )
+        volume_created1 = Volume.create(
+            self.userapiclient,
+            self.services["volume"],
+            zoneid=self.zone.id,
+            diskofferingid=self.disk_offering.id
+        )
+        volume_created2 = Volume.create(
+            self.userapiclient,
+            self.services["volume"],
+            zoneid=self.zone.id,
+            diskofferingid=self.disk_offering.id
+        )
+        self.cleanup.append(volume_created1)
+        self.cleanup.append(volume_created2)
+        self.cleanup.append(vm)
+
+        vm.attach_volume(
+            self.userapiclient,
+            volume_created1
+        )
+
+        try:
+            vm.attach_volume(
+                self.userapiclient,
+                volume_created2
+            )
+            vm.detach_volume(self.userapiclient, volume_created1)
+            vm.detach_volume(self.userapiclient, volume_created2)
+            self.fail("Successful to attach 2 DATA disks when max DATA disk limit was set to 1")
+        except Exception as e:
+            self.debug("Failed to attach 2nd DATA disk when max DATA disk limit was set to 1: %s" % e)
+
+        self.updateHostHypervisorCapability(self.hostCapability.id, 32)
+
+        vm.attach_volume(
+            self.userapiclient,
+            volume_created2
+        )
+        vm.detach_volume(self.userapiclient, volume_created1)
+        vm.detach_volume(self.userapiclient, volume_created2)
+
+    @skipTestIf("notSupported")
+    @attr(tags=["advanced", "basic"], required_hardware="false")
+    def test_01_check_hypervisor_vm_snapshot(self):
+        """ Test hypervisor vmsnapshotenabled effect
+
+        # 1. Set vmsnapshotenabled to false for hypervisor
+        # 2. List capabilities and verify value
+        # 3. Deploy a VM
+        # 4. Try VM snapshot, it should fail
+        # 5. Set vmsnapshotenabled to true for hypervisor
+        # 6. Try VM snapshot again, it should succeed
+        """
+        self.updateHostHypervisorCapability(self.hostCapability.id, None, False)
+        capabilities = self.listHostHypervisorCapabilities(self.hostCapability.id)
+        self.assertTrue(isinstance(capabilities, list), "listHypervisorCapabilities response not a valid list")
+        self.assertEqual(len(capabilities), 1, "listHypervisorCapabilities response not valid")
+        self.assertEqual(capabilities[0].vmsnapshotenabled,
+            False,
+            "listHypervisorCapabilities response vmsnapshotenabled value not False")
+
+        Host.update(self.apiclient, id=self.host.id, hosttags="host1")
+        vm = VirtualMachine.create(
+            self.userapiclient,
+            self.services["small"],
+            templateid=self.template.id,
+            accountid=self.account.name,
+            domainid=self.account.domainid,
+            serviceofferingid=self.service_offering.id,
+            zoneid=self.zone.id
+        )
+
+        try:
+            fail_snapshot = VmSnapshot.create(
+                self.userapiclient,
+                vmid=vm.id,
+                snapshotmemory="false",
+                name="Test Snapshot",
+                description="Test Snapshot Desc"
+            )
+            if vm_snapshot:
+                VmSnapshot.deleteVMSnapshot(self.userapiclient, fail_snapshot.id)

Review comment:
       my bad




-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: commits-unsubscribe@cloudstack.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org



[GitHub] [cloudstack] blueorangutan commented on pull request #5473: api,server: add params for updatehypervisorcapabilities API

Posted by GitBox <gi...@apache.org>.
blueorangutan commented on pull request #5473:
URL: https://github.com/apache/cloudstack/pull/5473#issuecomment-923676815


   <b>Trillian test result (tid-2137)</b>
   Environment: kvm-centos7 (x2), Advanced Networking with Mgmt server 7
   Total time taken: 34595 seconds
   Marvin logs: https://github.com/blueorangutan/acs-prs/releases/download/trillian/pr5473-t2137-kvm-centos7.zip
   Smoke tests completed. 89 look OK, 0 have errors
   Only failed tests results shown below:
   
   
   Test | Result | Time (s) | Test File
   --- | --- | --- | ---
   


-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: commits-unsubscribe@cloudstack.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org



[GitHub] [cloudstack] sureshanaparti commented on pull request #5473: api,server: add params for updatehypervisorcapabilities API

Posted by GitBox <gi...@apache.org>.
sureshanaparti commented on pull request #5473:
URL: https://github.com/apache/cloudstack/pull/5473#issuecomment-1027832670


   @blueorangutan package


-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: commits-unsubscribe@cloudstack.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org



[GitHub] [cloudstack] DaanHoogland commented on a change in pull request #5473: api,server: add params for updatehypervisorcapabilities API

Posted by GitBox <gi...@apache.org>.
DaanHoogland commented on a change in pull request #5473:
URL: https://github.com/apache/cloudstack/pull/5473#discussion_r794479429



##########
File path: test/integration/smoke/test_hypervisor_capabilities.py
##########
@@ -0,0 +1,291 @@
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements.  See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership.  The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License.  You may obtain a copy of the License at
+#
+#   http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied.  See the License for the
+# specific language governing permissions and limitations
+# under the License.
+""" Test cases for Testing Hypervisor Capabilities
+"""
+from nose.plugins.attrib import attr
+from marvin.cloudstackTestCase import cloudstackTestCase
+from marvin.lib.utils import (cleanup_resources,
+                              validateList)
+from marvin.lib.base import (Account,
+                             ServiceOffering,
+                             DiskOffering,
+                             VirtualMachine,
+                             Volume,
+                             Host,
+                             VmSnapshot)
+from marvin.lib.common import (get_domain,
+                               get_zone,
+                               get_template,
+                               list_virtual_machines,
+                               list_ssvms,
+                               list_routers)
+from marvin.lib.decoratorGenerators import skipTestIf
+
+
+from marvin.cloudstackAPI import (updateHypervisorCapabilities,
+                                  listHypervisorCapabilities)
+
+from marvin.codes import PASS
+
+
+class TestHypervisorCapabilities(cloudstackTestCase):
+
+    @classmethod
+    def setUpClass(cls):
+        testClient = super(TestHypervisorCapabilities, cls).getClsTestClient()
+        cls.apiclient = testClient.getApiClient()
+        cls.services = testClient.getParsedTestDataConfig()
+        cls.zone = get_zone(cls.apiclient, testClient.getZoneForTests())
+        cls.domain = get_domain(cls.apiclient)
+
+        cls.hypervisor = cls.testClient.getHypervisorInfo()
+        # Get Zone, Domain and templates
+
+        cls.notSupported = True
+        cls._cleanup = []
+        cls.hosts = Host.list(cls.apiclient, zoneid=cls.zone.id, type='Routing')
+        if isinstance(cls.hosts, list) and len(cls.hosts) > 0:
+            cls.host = cls.hosts[0]
+            cls.notSupported = False
+
+        cls.hypervisorversion = "default"
+        if hasattr(cls.host, 'hypervisorversion'):
+            cls.hypervisorversion = cls.host.hypervisorversion
+
+        if cls.notSupported == False:
+            cls.notSupported = True
+            cmdList = listHypervisorCapabilities.listHypervisorCapabilitiesCmd()
+            cmdList.hypervisor = cls.hypervisor
+            capabilities = cls.apiclient.listHypervisorCapabilities(cmdList)
+            for capability in capabilities:
+                if capability.hypervisorversion == cls.hypervisorversion:
+                   cls.hostCapability = capability
+                   cls.notSupported = False
+                   break
+
+            if cls.notSupported == True:
+                cls.hypervisorversion = "default"
+                for capability in capabilities:
+                    if capability.hypervisorversion == cls.hypervisorversion:
+                       cls.hostCapability = capability
+                       cls.notSupported = False
+                       break
+
+        print("Test-- %s, %s, %s" % (cls.notSupported, cls.hostCapability.id, cls.hostCapability.maxdatavolumeslimit))
+        if cls.notSupported == False:
+            cls.template = get_template(
+                cls.apiclient,
+                cls.zone.id,
+                cls.services["ostype"])
+
+            # Create an account
+            cls.account = Account.create(
+                cls.apiclient,
+                cls.services["account"],
+                domainid=cls.domain.id
+            )
+            cls._cleanup.append(cls.account)
+
+            # Create user api client of the account
+            cls.userapiclient = testClient.getUserApiClient(
+                UserName=cls.account.name,
+                DomainName=cls.account.domain
+            )
+            # Create Service offering
+            cls.service_offering = ServiceOffering.create(
+                cls.apiclient,
+                cls.services["service_offering"],
+                hosttags="host1"
+            )
+            cls._cleanup.append(cls.service_offering)
+
+            cls.disk_offering = DiskOffering.create(
+                cls.apiclient,
+                cls.services["disk_offering"]
+            )
+            cls._cleanup.append(cls.disk_offering)
+
+        return
+
+    @classmethod
+    def tearDownClass(cls):
+        try:
+            cleanup_resources(cls.apiclient, cls._cleanup)
+        except Exception as e:
+            raise Exception("Warning: Exception during cleanup : %s" % e)
+
+    def setUp(self):
+        self.cleanup = []
+
+        self.apiclient = self.testClient.getApiClient()
+        self.dbclient = self.testClient.getDbConnection()
+
+    def tearDown(self):
+        try:
+            if self.notSupported == False:
+                Host.update(self.apiclient, id=self.host.id, hosttags="")
+                self.updateHostHypervisorCapability(self.hostCapability.id,
+                    self.hostCapability.maxdatavolumeslimit,
+                    self.hostCapability.vmsnapshotenabled)
+
+            cleanup_resources(self.apiclient, self.cleanup)
+        except Exception as e:
+            raise Exception("Warning: Exception during cleanup : %s" % e)
+        return
+
+    @skipTestIf("notSupported")
+    @attr(tags=["advanced", "basic"], required_hardware="false")
+    def test_01_check_hypervisor_max_data_volume_limit(self):
+        """ Test hypervisor maxdatavolumeslimit effect
+
+        # 1. Set maxdatavolumeslimit to 1 for hypervisor
+        # 2. List capabilities and verify value
+        # 3. Deploy a VM and attach a volume to it
+        # 4. Try attach another volume, it should fail
+        # 5. Set maxdatavolumeslimit to 32 for hypervisor
+        # 6. Try attach second volume, it should succeed
+        """
+        self.updateHostHypervisorCapability(self.hostCapability.id, 1)
+        capabilities = self.listHostHypervisorCapabilities(self.hostCapability.id)
+        self.assertTrue(isinstance(capabilities, list), "listHypervisorCapabilities response not a valid list")
+        self.assertEqual(len(capabilities), 1, "listHypervisorCapabilities response not valid")
+        self.assertEqual(capabilities[0].maxdatavolumeslimit,
+            1,
+            "listHypervisorCapabilities response maxdatavolumeslimit value not 1")
+
+        Host.update(self.apiclient, id=self.host.id, hosttags="host1")
+        vm = VirtualMachine.create(
+            self.userapiclient,
+            self.services["small"],
+            templateid=self.template.id,
+            accountid=self.account.name,
+            domainid=self.account.domainid,
+            serviceofferingid=self.service_offering.id,
+            zoneid=self.zone.id
+        )
+        volume_created1 = Volume.create(
+            self.userapiclient,
+            self.services["volume"],
+            zoneid=self.zone.id,
+            diskofferingid=self.disk_offering.id
+        )
+        volume_created2 = Volume.create(
+            self.userapiclient,
+            self.services["volume"],
+            zoneid=self.zone.id,
+            diskofferingid=self.disk_offering.id
+        )
+        self.cleanup.append(volume_created1)
+        self.cleanup.append(volume_created2)
+        self.cleanup.append(vm)
+
+        vm.attach_volume(
+            self.userapiclient,
+            volume_created1
+        )
+
+        try:
+            vm.attach_volume(
+                self.userapiclient,
+                volume_created2
+            )
+            vm.detach_volume(self.userapiclient, volume_created1)
+            vm.detach_volume(self.userapiclient, volume_created2)
+            self.fail("Successful to attach 2 DATA disks when max DATA disk limit was set to 1")
+        except Exception as e:
+            self.debug("Failed to attach 2nd DATA disk when max DATA disk limit was set to 1: %s" % e)
+
+        self.updateHostHypervisorCapability(self.hostCapability.id, 32)
+
+        vm.attach_volume(
+            self.userapiclient,
+            volume_created2
+        )
+        vm.detach_volume(self.userapiclient, volume_created1)
+        vm.detach_volume(self.userapiclient, volume_created2)
+
+    @skipTestIf("notSupported")
+    @attr(tags=["advanced", "basic"], required_hardware="false")
+    def test_01_check_hypervisor_vm_snapshot(self):
+        """ Test hypervisor vmsnapshotenabled effect
+
+        # 1. Set vmsnapshotenabled to false for hypervisor
+        # 2. List capabilities and verify value
+        # 3. Deploy a VM
+        # 4. Try VM snapshot, it should fail
+        # 5. Set vmsnapshotenabled to true for hypervisor
+        # 6. Try VM snapshot again, it should succeed
+        """
+        self.updateHostHypervisorCapability(self.hostCapability.id, None, False)
+        capabilities = self.listHostHypervisorCapabilities(self.hostCapability.id)
+        self.assertTrue(isinstance(capabilities, list), "listHypervisorCapabilities response not a valid list")
+        self.assertEqual(len(capabilities), 1, "listHypervisorCapabilities response not valid")
+        self.assertEqual(capabilities[0].vmsnapshotenabled,
+            False,
+            "listHypervisorCapabilities response vmsnapshotenabled value not False")
+
+        Host.update(self.apiclient, id=self.host.id, hosttags="host1")
+        vm = VirtualMachine.create(
+            self.userapiclient,
+            self.services["small"],
+            templateid=self.template.id,
+            accountid=self.account.name,
+            domainid=self.account.domainid,
+            serviceofferingid=self.service_offering.id,
+            zoneid=self.zone.id
+        )

Review comment:
       ```suggestion
           vm = VirtualMachine.create(
               self.userapiclient,
               self.services["small"],
               templateid=self.template.id,
               accountid=self.account.name,
               domainid=self.account.domainid,
               serviceofferingid=self.service_offering.id,
               zoneid=self.zone.id
           )
           self.cleanup.append(vm)
   ```

##########
File path: test/integration/smoke/test_hypervisor_capabilities.py
##########
@@ -0,0 +1,291 @@
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements.  See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership.  The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License.  You may obtain a copy of the License at
+#
+#   http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied.  See the License for the
+# specific language governing permissions and limitations
+# under the License.
+""" Test cases for Testing Hypervisor Capabilities
+"""
+from nose.plugins.attrib import attr
+from marvin.cloudstackTestCase import cloudstackTestCase
+from marvin.lib.utils import (cleanup_resources,
+                              validateList)
+from marvin.lib.base import (Account,
+                             ServiceOffering,
+                             DiskOffering,
+                             VirtualMachine,
+                             Volume,
+                             Host,
+                             VmSnapshot)
+from marvin.lib.common import (get_domain,
+                               get_zone,
+                               get_template,
+                               list_virtual_machines,
+                               list_ssvms,
+                               list_routers)
+from marvin.lib.decoratorGenerators import skipTestIf
+
+
+from marvin.cloudstackAPI import (updateHypervisorCapabilities,
+                                  listHypervisorCapabilities)
+
+from marvin.codes import PASS
+
+
+class TestHypervisorCapabilities(cloudstackTestCase):
+
+    @classmethod
+    def setUpClass(cls):
+        testClient = super(TestHypervisorCapabilities, cls).getClsTestClient()
+        cls.apiclient = testClient.getApiClient()
+        cls.services = testClient.getParsedTestDataConfig()
+        cls.zone = get_zone(cls.apiclient, testClient.getZoneForTests())
+        cls.domain = get_domain(cls.apiclient)
+
+        cls.hypervisor = cls.testClient.getHypervisorInfo()
+        # Get Zone, Domain and templates
+
+        cls.notSupported = True
+        cls._cleanup = []
+        cls.hosts = Host.list(cls.apiclient, zoneid=cls.zone.id, type='Routing')
+        if isinstance(cls.hosts, list) and len(cls.hosts) > 0:
+            cls.host = cls.hosts[0]
+            cls.notSupported = False
+
+        cls.hypervisorversion = "default"
+        if hasattr(cls.host, 'hypervisorversion'):
+            cls.hypervisorversion = cls.host.hypervisorversion
+
+        if cls.notSupported == False:
+            cls.notSupported = True
+            cmdList = listHypervisorCapabilities.listHypervisorCapabilitiesCmd()
+            cmdList.hypervisor = cls.hypervisor
+            capabilities = cls.apiclient.listHypervisorCapabilities(cmdList)
+            for capability in capabilities:
+                if capability.hypervisorversion == cls.hypervisorversion:
+                   cls.hostCapability = capability
+                   cls.notSupported = False
+                   break
+
+            if cls.notSupported == True:
+                cls.hypervisorversion = "default"
+                for capability in capabilities:
+                    if capability.hypervisorversion == cls.hypervisorversion:
+                       cls.hostCapability = capability
+                       cls.notSupported = False
+                       break
+
+        print("Test-- %s, %s, %s" % (cls.notSupported, cls.hostCapability.id, cls.hostCapability.maxdatavolumeslimit))
+        if cls.notSupported == False:
+            cls.template = get_template(
+                cls.apiclient,
+                cls.zone.id,
+                cls.services["ostype"])
+
+            # Create an account
+            cls.account = Account.create(
+                cls.apiclient,
+                cls.services["account"],
+                domainid=cls.domain.id
+            )
+            cls._cleanup.append(cls.account)
+
+            # Create user api client of the account
+            cls.userapiclient = testClient.getUserApiClient(
+                UserName=cls.account.name,
+                DomainName=cls.account.domain
+            )
+            # Create Service offering
+            cls.service_offering = ServiceOffering.create(
+                cls.apiclient,
+                cls.services["service_offering"],
+                hosttags="host1"
+            )
+            cls._cleanup.append(cls.service_offering)
+
+            cls.disk_offering = DiskOffering.create(
+                cls.apiclient,
+                cls.services["disk_offering"]
+            )
+            cls._cleanup.append(cls.disk_offering)
+
+        return
+
+    @classmethod
+    def tearDownClass(cls):
+        try:
+            cleanup_resources(cls.apiclient, cls._cleanup)
+        except Exception as e:
+            raise Exception("Warning: Exception during cleanup : %s" % e)

Review comment:
       ```suggestion
           super(TestHypervisorCapabilities, cls).tearDownClass()
   ```

##########
File path: test/integration/smoke/test_hypervisor_capabilities.py
##########
@@ -0,0 +1,291 @@
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements.  See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership.  The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License.  You may obtain a copy of the License at
+#
+#   http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied.  See the License for the
+# specific language governing permissions and limitations
+# under the License.
+""" Test cases for Testing Hypervisor Capabilities
+"""
+from nose.plugins.attrib import attr
+from marvin.cloudstackTestCase import cloudstackTestCase
+from marvin.lib.utils import (cleanup_resources,
+                              validateList)
+from marvin.lib.base import (Account,
+                             ServiceOffering,
+                             DiskOffering,
+                             VirtualMachine,
+                             Volume,
+                             Host,
+                             VmSnapshot)
+from marvin.lib.common import (get_domain,
+                               get_zone,
+                               get_template,
+                               list_virtual_machines,
+                               list_ssvms,
+                               list_routers)
+from marvin.lib.decoratorGenerators import skipTestIf
+
+
+from marvin.cloudstackAPI import (updateHypervisorCapabilities,
+                                  listHypervisorCapabilities)
+
+from marvin.codes import PASS
+
+
+class TestHypervisorCapabilities(cloudstackTestCase):
+
+    @classmethod
+    def setUpClass(cls):
+        testClient = super(TestHypervisorCapabilities, cls).getClsTestClient()
+        cls.apiclient = testClient.getApiClient()
+        cls.services = testClient.getParsedTestDataConfig()
+        cls.zone = get_zone(cls.apiclient, testClient.getZoneForTests())
+        cls.domain = get_domain(cls.apiclient)
+
+        cls.hypervisor = cls.testClient.getHypervisorInfo()
+        # Get Zone, Domain and templates
+
+        cls.notSupported = True
+        cls._cleanup = []
+        cls.hosts = Host.list(cls.apiclient, zoneid=cls.zone.id, type='Routing')
+        if isinstance(cls.hosts, list) and len(cls.hosts) > 0:
+            cls.host = cls.hosts[0]
+            cls.notSupported = False
+
+        cls.hypervisorversion = "default"
+        if hasattr(cls.host, 'hypervisorversion'):
+            cls.hypervisorversion = cls.host.hypervisorversion
+
+        if cls.notSupported == False:
+            cls.notSupported = True
+            cmdList = listHypervisorCapabilities.listHypervisorCapabilitiesCmd()
+            cmdList.hypervisor = cls.hypervisor
+            capabilities = cls.apiclient.listHypervisorCapabilities(cmdList)
+            for capability in capabilities:
+                if capability.hypervisorversion == cls.hypervisorversion:
+                   cls.hostCapability = capability
+                   cls.notSupported = False
+                   break
+
+            if cls.notSupported == True:
+                cls.hypervisorversion = "default"
+                for capability in capabilities:
+                    if capability.hypervisorversion == cls.hypervisorversion:
+                       cls.hostCapability = capability
+                       cls.notSupported = False
+                       break
+
+        print("Test-- %s, %s, %s" % (cls.notSupported, cls.hostCapability.id, cls.hostCapability.maxdatavolumeslimit))
+        if cls.notSupported == False:
+            cls.template = get_template(
+                cls.apiclient,
+                cls.zone.id,
+                cls.services["ostype"])
+
+            # Create an account
+            cls.account = Account.create(
+                cls.apiclient,
+                cls.services["account"],
+                domainid=cls.domain.id
+            )
+            cls._cleanup.append(cls.account)
+
+            # Create user api client of the account
+            cls.userapiclient = testClient.getUserApiClient(
+                UserName=cls.account.name,
+                DomainName=cls.account.domain
+            )
+            # Create Service offering
+            cls.service_offering = ServiceOffering.create(
+                cls.apiclient,
+                cls.services["service_offering"],
+                hosttags="host1"
+            )
+            cls._cleanup.append(cls.service_offering)
+
+            cls.disk_offering = DiskOffering.create(
+                cls.apiclient,
+                cls.services["disk_offering"]
+            )
+            cls._cleanup.append(cls.disk_offering)
+
+        return
+
+    @classmethod
+    def tearDownClass(cls):
+        try:
+            cleanup_resources(cls.apiclient, cls._cleanup)
+        except Exception as e:
+            raise Exception("Warning: Exception during cleanup : %s" % e)
+
+    def setUp(self):
+        self.cleanup = []
+
+        self.apiclient = self.testClient.getApiClient()
+        self.dbclient = self.testClient.getDbConnection()
+
+    def tearDown(self):
+        try:
+            if self.notSupported == False:
+                Host.update(self.apiclient, id=self.host.id, hosttags="")
+                self.updateHostHypervisorCapability(self.hostCapability.id,
+                    self.hostCapability.maxdatavolumeslimit,
+                    self.hostCapability.vmsnapshotenabled)
+
+            cleanup_resources(self.apiclient, self.cleanup)

Review comment:
       ```suggestion
               super(TestHypervisorCapabilities, self).tearDown()
   ```

##########
File path: test/integration/smoke/test_hypervisor_capabilities.py
##########
@@ -0,0 +1,291 @@
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements.  See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership.  The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License.  You may obtain a copy of the License at
+#
+#   http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied.  See the License for the
+# specific language governing permissions and limitations
+# under the License.
+""" Test cases for Testing Hypervisor Capabilities
+"""
+from nose.plugins.attrib import attr
+from marvin.cloudstackTestCase import cloudstackTestCase
+from marvin.lib.utils import (cleanup_resources,
+                              validateList)
+from marvin.lib.base import (Account,
+                             ServiceOffering,
+                             DiskOffering,
+                             VirtualMachine,
+                             Volume,
+                             Host,
+                             VmSnapshot)
+from marvin.lib.common import (get_domain,
+                               get_zone,
+                               get_template,
+                               list_virtual_machines,
+                               list_ssvms,
+                               list_routers)
+from marvin.lib.decoratorGenerators import skipTestIf
+
+
+from marvin.cloudstackAPI import (updateHypervisorCapabilities,
+                                  listHypervisorCapabilities)
+
+from marvin.codes import PASS
+
+
+class TestHypervisorCapabilities(cloudstackTestCase):
+
+    @classmethod
+    def setUpClass(cls):
+        testClient = super(TestHypervisorCapabilities, cls).getClsTestClient()
+        cls.apiclient = testClient.getApiClient()
+        cls.services = testClient.getParsedTestDataConfig()
+        cls.zone = get_zone(cls.apiclient, testClient.getZoneForTests())
+        cls.domain = get_domain(cls.apiclient)
+
+        cls.hypervisor = cls.testClient.getHypervisorInfo()
+        # Get Zone, Domain and templates
+
+        cls.notSupported = True
+        cls._cleanup = []
+        cls.hosts = Host.list(cls.apiclient, zoneid=cls.zone.id, type='Routing')
+        if isinstance(cls.hosts, list) and len(cls.hosts) > 0:
+            cls.host = cls.hosts[0]
+            cls.notSupported = False
+
+        cls.hypervisorversion = "default"
+        if hasattr(cls.host, 'hypervisorversion'):
+            cls.hypervisorversion = cls.host.hypervisorversion
+
+        if cls.notSupported == False:
+            cls.notSupported = True
+            cmdList = listHypervisorCapabilities.listHypervisorCapabilitiesCmd()
+            cmdList.hypervisor = cls.hypervisor
+            capabilities = cls.apiclient.listHypervisorCapabilities(cmdList)
+            for capability in capabilities:
+                if capability.hypervisorversion == cls.hypervisorversion:
+                   cls.hostCapability = capability
+                   cls.notSupported = False
+                   break
+
+            if cls.notSupported == True:
+                cls.hypervisorversion = "default"
+                for capability in capabilities:
+                    if capability.hypervisorversion == cls.hypervisorversion:
+                       cls.hostCapability = capability
+                       cls.notSupported = False
+                       break
+
+        print("Test-- %s, %s, %s" % (cls.notSupported, cls.hostCapability.id, cls.hostCapability.maxdatavolumeslimit))
+        if cls.notSupported == False:
+            cls.template = get_template(
+                cls.apiclient,
+                cls.zone.id,
+                cls.services["ostype"])
+
+            # Create an account
+            cls.account = Account.create(
+                cls.apiclient,
+                cls.services["account"],
+                domainid=cls.domain.id
+            )
+            cls._cleanup.append(cls.account)
+
+            # Create user api client of the account
+            cls.userapiclient = testClient.getUserApiClient(
+                UserName=cls.account.name,
+                DomainName=cls.account.domain
+            )
+            # Create Service offering
+            cls.service_offering = ServiceOffering.create(
+                cls.apiclient,
+                cls.services["service_offering"],
+                hosttags="host1"
+            )
+            cls._cleanup.append(cls.service_offering)
+
+            cls.disk_offering = DiskOffering.create(
+                cls.apiclient,
+                cls.services["disk_offering"]
+            )
+            cls._cleanup.append(cls.disk_offering)
+
+        return
+
+    @classmethod
+    def tearDownClass(cls):
+        try:
+            cleanup_resources(cls.apiclient, cls._cleanup)
+        except Exception as e:
+            raise Exception("Warning: Exception during cleanup : %s" % e)
+
+    def setUp(self):
+        self.cleanup = []
+
+        self.apiclient = self.testClient.getApiClient()
+        self.dbclient = self.testClient.getDbConnection()
+
+    def tearDown(self):
+        try:
+            if self.notSupported == False:
+                Host.update(self.apiclient, id=self.host.id, hosttags="")
+                self.updateHostHypervisorCapability(self.hostCapability.id,
+                    self.hostCapability.maxdatavolumeslimit,
+                    self.hostCapability.vmsnapshotenabled)
+
+            cleanup_resources(self.apiclient, self.cleanup)
+        except Exception as e:
+            raise Exception("Warning: Exception during cleanup : %s" % e)
+        return
+
+    @skipTestIf("notSupported")
+    @attr(tags=["advanced", "basic"], required_hardware="false")
+    def test_01_check_hypervisor_max_data_volume_limit(self):
+        """ Test hypervisor maxdatavolumeslimit effect
+
+        # 1. Set maxdatavolumeslimit to 1 for hypervisor
+        # 2. List capabilities and verify value
+        # 3. Deploy a VM and attach a volume to it
+        # 4. Try attach another volume, it should fail
+        # 5. Set maxdatavolumeslimit to 32 for hypervisor
+        # 6. Try attach second volume, it should succeed
+        """
+        self.updateHostHypervisorCapability(self.hostCapability.id, 1)
+        capabilities = self.listHostHypervisorCapabilities(self.hostCapability.id)
+        self.assertTrue(isinstance(capabilities, list), "listHypervisorCapabilities response not a valid list")
+        self.assertEqual(len(capabilities), 1, "listHypervisorCapabilities response not valid")
+        self.assertEqual(capabilities[0].maxdatavolumeslimit,
+            1,
+            "listHypervisorCapabilities response maxdatavolumeslimit value not 1")
+
+        Host.update(self.apiclient, id=self.host.id, hosttags="host1")
+        vm = VirtualMachine.create(
+            self.userapiclient,
+            self.services["small"],
+            templateid=self.template.id,
+            accountid=self.account.name,
+            domainid=self.account.domainid,
+            serviceofferingid=self.service_offering.id,
+            zoneid=self.zone.id
+        )
+        volume_created1 = Volume.create(
+            self.userapiclient,
+            self.services["volume"],
+            zoneid=self.zone.id,
+            diskofferingid=self.disk_offering.id
+        )
+        volume_created2 = Volume.create(
+            self.userapiclient,
+            self.services["volume"],
+            zoneid=self.zone.id,
+            diskofferingid=self.disk_offering.id
+        )
+        self.cleanup.append(volume_created1)
+        self.cleanup.append(volume_created2)
+        self.cleanup.append(vm)
+
+        vm.attach_volume(
+            self.userapiclient,
+            volume_created1
+        )
+
+        try:
+            vm.attach_volume(
+                self.userapiclient,
+                volume_created2
+            )
+            vm.detach_volume(self.userapiclient, volume_created1)
+            vm.detach_volume(self.userapiclient, volume_created2)
+            self.fail("Successful to attach 2 DATA disks when max DATA disk limit was set to 1")
+        except Exception as e:
+            self.debug("Failed to attach 2nd DATA disk when max DATA disk limit was set to 1: %s" % e)
+
+        self.updateHostHypervisorCapability(self.hostCapability.id, 32)
+
+        vm.attach_volume(
+            self.userapiclient,
+            volume_created2
+        )
+        vm.detach_volume(self.userapiclient, volume_created1)
+        vm.detach_volume(self.userapiclient, volume_created2)
+
+    @skipTestIf("notSupported")
+    @attr(tags=["advanced", "basic"], required_hardware="false")
+    def test_01_check_hypervisor_vm_snapshot(self):
+        """ Test hypervisor vmsnapshotenabled effect
+
+        # 1. Set vmsnapshotenabled to false for hypervisor
+        # 2. List capabilities and verify value
+        # 3. Deploy a VM
+        # 4. Try VM snapshot, it should fail
+        # 5. Set vmsnapshotenabled to true for hypervisor
+        # 6. Try VM snapshot again, it should succeed
+        """
+        self.updateHostHypervisorCapability(self.hostCapability.id, None, False)
+        capabilities = self.listHostHypervisorCapabilities(self.hostCapability.id)
+        self.assertTrue(isinstance(capabilities, list), "listHypervisorCapabilities response not a valid list")
+        self.assertEqual(len(capabilities), 1, "listHypervisorCapabilities response not valid")
+        self.assertEqual(capabilities[0].vmsnapshotenabled,
+            False,
+            "listHypervisorCapabilities response vmsnapshotenabled value not False")
+
+        Host.update(self.apiclient, id=self.host.id, hosttags="host1")
+        vm = VirtualMachine.create(
+            self.userapiclient,
+            self.services["small"],
+            templateid=self.template.id,
+            accountid=self.account.name,
+            domainid=self.account.domainid,
+            serviceofferingid=self.service_offering.id,
+            zoneid=self.zone.id
+        )
+
+        try:
+            fail_snapshot = VmSnapshot.create(
+                self.userapiclient,
+                vmid=vm.id,
+                snapshotmemory="false",
+                name="Test Snapshot",
+                description="Test Snapshot Desc"
+            )
+            if vm_snapshot:
+                VmSnapshot.deleteVMSnapshot(self.userapiclient, fail_snapshot.id)

Review comment:
       what is this trying to do @shwstppr ? I think it would be enough to add fail_snapshot to the cleanup list if it exists.
   Also `vm_snapshot` has not been i nitialised at this moment. It is created below, after the `updateHostHypervisorCapability(..)`-call

##########
File path: test/integration/smoke/test_hypervisor_capabilities.py
##########
@@ -0,0 +1,291 @@
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements.  See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership.  The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License.  You may obtain a copy of the License at
+#
+#   http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied.  See the License for the
+# specific language governing permissions and limitations
+# under the License.
+""" Test cases for Testing Hypervisor Capabilities
+"""
+from nose.plugins.attrib import attr
+from marvin.cloudstackTestCase import cloudstackTestCase
+from marvin.lib.utils import (cleanup_resources,
+                              validateList)
+from marvin.lib.base import (Account,
+                             ServiceOffering,
+                             DiskOffering,
+                             VirtualMachine,
+                             Volume,
+                             Host,
+                             VmSnapshot)
+from marvin.lib.common import (get_domain,
+                               get_zone,
+                               get_template,
+                               list_virtual_machines,
+                               list_ssvms,
+                               list_routers)
+from marvin.lib.decoratorGenerators import skipTestIf
+
+
+from marvin.cloudstackAPI import (updateHypervisorCapabilities,
+                                  listHypervisorCapabilities)
+
+from marvin.codes import PASS
+
+
+class TestHypervisorCapabilities(cloudstackTestCase):
+
+    @classmethod
+    def setUpClass(cls):
+        testClient = super(TestHypervisorCapabilities, cls).getClsTestClient()
+        cls.apiclient = testClient.getApiClient()
+        cls.services = testClient.getParsedTestDataConfig()
+        cls.zone = get_zone(cls.apiclient, testClient.getZoneForTests())
+        cls.domain = get_domain(cls.apiclient)
+
+        cls.hypervisor = cls.testClient.getHypervisorInfo()
+        # Get Zone, Domain and templates
+
+        cls.notSupported = True
+        cls._cleanup = []
+        cls.hosts = Host.list(cls.apiclient, zoneid=cls.zone.id, type='Routing')
+        if isinstance(cls.hosts, list) and len(cls.hosts) > 0:
+            cls.host = cls.hosts[0]
+            cls.notSupported = False
+
+        cls.hypervisorversion = "default"
+        if hasattr(cls.host, 'hypervisorversion'):
+            cls.hypervisorversion = cls.host.hypervisorversion
+
+        if cls.notSupported == False:
+            cls.notSupported = True
+            cmdList = listHypervisorCapabilities.listHypervisorCapabilitiesCmd()
+            cmdList.hypervisor = cls.hypervisor
+            capabilities = cls.apiclient.listHypervisorCapabilities(cmdList)
+            for capability in capabilities:
+                if capability.hypervisorversion == cls.hypervisorversion:
+                   cls.hostCapability = capability
+                   cls.notSupported = False
+                   break
+
+            if cls.notSupported == True:
+                cls.hypervisorversion = "default"
+                for capability in capabilities:
+                    if capability.hypervisorversion == cls.hypervisorversion:
+                       cls.hostCapability = capability
+                       cls.notSupported = False
+                       break
+
+        print("Test-- %s, %s, %s" % (cls.notSupported, cls.hostCapability.id, cls.hostCapability.maxdatavolumeslimit))
+        if cls.notSupported == False:
+            cls.template = get_template(
+                cls.apiclient,
+                cls.zone.id,
+                cls.services["ostype"])
+
+            # Create an account
+            cls.account = Account.create(
+                cls.apiclient,
+                cls.services["account"],
+                domainid=cls.domain.id
+            )
+            cls._cleanup.append(cls.account)
+
+            # Create user api client of the account
+            cls.userapiclient = testClient.getUserApiClient(
+                UserName=cls.account.name,
+                DomainName=cls.account.domain
+            )
+            # Create Service offering
+            cls.service_offering = ServiceOffering.create(
+                cls.apiclient,
+                cls.services["service_offering"],
+                hosttags="host1"
+            )
+            cls._cleanup.append(cls.service_offering)
+
+            cls.disk_offering = DiskOffering.create(
+                cls.apiclient,
+                cls.services["disk_offering"]
+            )
+            cls._cleanup.append(cls.disk_offering)
+
+        return
+
+    @classmethod
+    def tearDownClass(cls):
+        try:
+            cleanup_resources(cls.apiclient, cls._cleanup)
+        except Exception as e:
+            raise Exception("Warning: Exception during cleanup : %s" % e)
+
+    def setUp(self):
+        self.cleanup = []
+
+        self.apiclient = self.testClient.getApiClient()
+        self.dbclient = self.testClient.getDbConnection()
+
+    def tearDown(self):
+        try:
+            if self.notSupported == False:
+                Host.update(self.apiclient, id=self.host.id, hosttags="")
+                self.updateHostHypervisorCapability(self.hostCapability.id,
+                    self.hostCapability.maxdatavolumeslimit,
+                    self.hostCapability.vmsnapshotenabled)
+
+            cleanup_resources(self.apiclient, self.cleanup)
+        except Exception as e:
+            raise Exception("Warning: Exception during cleanup : %s" % e)
+        return
+
+    @skipTestIf("notSupported")
+    @attr(tags=["advanced", "basic"], required_hardware="false")
+    def test_01_check_hypervisor_max_data_volume_limit(self):
+        """ Test hypervisor maxdatavolumeslimit effect
+
+        # 1. Set maxdatavolumeslimit to 1 for hypervisor
+        # 2. List capabilities and verify value
+        # 3. Deploy a VM and attach a volume to it
+        # 4. Try attach another volume, it should fail
+        # 5. Set maxdatavolumeslimit to 32 for hypervisor
+        # 6. Try attach second volume, it should succeed
+        """
+        self.updateHostHypervisorCapability(self.hostCapability.id, 1)
+        capabilities = self.listHostHypervisorCapabilities(self.hostCapability.id)
+        self.assertTrue(isinstance(capabilities, list), "listHypervisorCapabilities response not a valid list")
+        self.assertEqual(len(capabilities), 1, "listHypervisorCapabilities response not valid")
+        self.assertEqual(capabilities[0].maxdatavolumeslimit,
+            1,
+            "listHypervisorCapabilities response maxdatavolumeslimit value not 1")
+
+        Host.update(self.apiclient, id=self.host.id, hosttags="host1")
+        vm = VirtualMachine.create(
+            self.userapiclient,
+            self.services["small"],
+            templateid=self.template.id,
+            accountid=self.account.name,
+            domainid=self.account.domainid,
+            serviceofferingid=self.service_offering.id,
+            zoneid=self.zone.id
+        )
+        volume_created1 = Volume.create(
+            self.userapiclient,
+            self.services["volume"],
+            zoneid=self.zone.id,
+            diskofferingid=self.disk_offering.id
+        )
+        volume_created2 = Volume.create(
+            self.userapiclient,
+            self.services["volume"],
+            zoneid=self.zone.id,
+            diskofferingid=self.disk_offering.id
+        )
+        self.cleanup.append(volume_created1)
+        self.cleanup.append(volume_created2)
+        self.cleanup.append(vm)

Review comment:
       ```suggestion
           vm = VirtualMachine.create(
               self.userapiclient,
               self.services["small"],
               templateid=self.template.id,
               accountid=self.account.name,
               domainid=self.account.domainid,
               serviceofferingid=self.service_offering.id,
               zoneid=self.zone.id
           )
           self.cleanup.append(vm)
           volume_created1 = Volume.create(
               self.userapiclient,
               self.services["volume"],
               zoneid=self.zone.id,
               diskofferingid=self.disk_offering.id
           )
           self.cleanup.append(volume_created1)
           volume_created2 = Volume.create(
               self.userapiclient,
               self.services["volume"],
               zoneid=self.zone.id,
               diskofferingid=self.disk_offering.id
           )
           self.cleanup.append(volume_created2)
   ```

##########
File path: test/integration/smoke/test_hypervisor_capabilities.py
##########
@@ -0,0 +1,291 @@
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements.  See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership.  The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License.  You may obtain a copy of the License at
+#
+#   http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied.  See the License for the
+# specific language governing permissions and limitations
+# under the License.
+""" Test cases for Testing Hypervisor Capabilities
+"""
+from nose.plugins.attrib import attr
+from marvin.cloudstackTestCase import cloudstackTestCase
+from marvin.lib.utils import (cleanup_resources,
+                              validateList)
+from marvin.lib.base import (Account,
+                             ServiceOffering,
+                             DiskOffering,
+                             VirtualMachine,
+                             Volume,
+                             Host,
+                             VmSnapshot)
+from marvin.lib.common import (get_domain,
+                               get_zone,
+                               get_template,
+                               list_virtual_machines,
+                               list_ssvms,
+                               list_routers)
+from marvin.lib.decoratorGenerators import skipTestIf
+
+
+from marvin.cloudstackAPI import (updateHypervisorCapabilities,
+                                  listHypervisorCapabilities)
+
+from marvin.codes import PASS
+
+
+class TestHypervisorCapabilities(cloudstackTestCase):
+
+    @classmethod
+    def setUpClass(cls):
+        testClient = super(TestHypervisorCapabilities, cls).getClsTestClient()
+        cls.apiclient = testClient.getApiClient()
+        cls.services = testClient.getParsedTestDataConfig()
+        cls.zone = get_zone(cls.apiclient, testClient.getZoneForTests())
+        cls.domain = get_domain(cls.apiclient)
+
+        cls.hypervisor = cls.testClient.getHypervisorInfo()
+        # Get Zone, Domain and templates
+
+        cls.notSupported = True
+        cls._cleanup = []
+        cls.hosts = Host.list(cls.apiclient, zoneid=cls.zone.id, type='Routing')
+        if isinstance(cls.hosts, list) and len(cls.hosts) > 0:
+            cls.host = cls.hosts[0]
+            cls.notSupported = False
+
+        cls.hypervisorversion = "default"
+        if hasattr(cls.host, 'hypervisorversion'):
+            cls.hypervisorversion = cls.host.hypervisorversion
+
+        if cls.notSupported == False:
+            cls.notSupported = True
+            cmdList = listHypervisorCapabilities.listHypervisorCapabilitiesCmd()
+            cmdList.hypervisor = cls.hypervisor
+            capabilities = cls.apiclient.listHypervisorCapabilities(cmdList)
+            for capability in capabilities:
+                if capability.hypervisorversion == cls.hypervisorversion:
+                   cls.hostCapability = capability
+                   cls.notSupported = False
+                   break
+
+            if cls.notSupported == True:
+                cls.hypervisorversion = "default"
+                for capability in capabilities:
+                    if capability.hypervisorversion == cls.hypervisorversion:
+                       cls.hostCapability = capability
+                       cls.notSupported = False
+                       break
+
+        print("Test-- %s, %s, %s" % (cls.notSupported, cls.hostCapability.id, cls.hostCapability.maxdatavolumeslimit))
+        if cls.notSupported == False:
+            cls.template = get_template(
+                cls.apiclient,
+                cls.zone.id,
+                cls.services["ostype"])
+
+            # Create an account
+            cls.account = Account.create(
+                cls.apiclient,
+                cls.services["account"],
+                domainid=cls.domain.id
+            )
+            cls._cleanup.append(cls.account)
+
+            # Create user api client of the account
+            cls.userapiclient = testClient.getUserApiClient(
+                UserName=cls.account.name,
+                DomainName=cls.account.domain
+            )
+            # Create Service offering
+            cls.service_offering = ServiceOffering.create(
+                cls.apiclient,
+                cls.services["service_offering"],
+                hosttags="host1"
+            )
+            cls._cleanup.append(cls.service_offering)
+
+            cls.disk_offering = DiskOffering.create(
+                cls.apiclient,
+                cls.services["disk_offering"]
+            )
+            cls._cleanup.append(cls.disk_offering)
+
+        return
+
+    @classmethod
+    def tearDownClass(cls):
+        try:
+            cleanup_resources(cls.apiclient, cls._cleanup)
+        except Exception as e:
+            raise Exception("Warning: Exception during cleanup : %s" % e)
+
+    def setUp(self):
+        self.cleanup = []
+
+        self.apiclient = self.testClient.getApiClient()
+        self.dbclient = self.testClient.getDbConnection()
+
+    def tearDown(self):
+        try:
+            if self.notSupported == False:
+                Host.update(self.apiclient, id=self.host.id, hosttags="")
+                self.updateHostHypervisorCapability(self.hostCapability.id,
+                    self.hostCapability.maxdatavolumeslimit,
+                    self.hostCapability.vmsnapshotenabled)
+
+            cleanup_resources(self.apiclient, self.cleanup)
+        except Exception as e:
+            raise Exception("Warning: Exception during cleanup : %s" % e)
+        return
+
+    @skipTestIf("notSupported")
+    @attr(tags=["advanced", "basic"], required_hardware="false")
+    def test_01_check_hypervisor_max_data_volume_limit(self):
+        """ Test hypervisor maxdatavolumeslimit effect
+
+        # 1. Set maxdatavolumeslimit to 1 for hypervisor
+        # 2. List capabilities and verify value
+        # 3. Deploy a VM and attach a volume to it
+        # 4. Try attach another volume, it should fail
+        # 5. Set maxdatavolumeslimit to 32 for hypervisor
+        # 6. Try attach second volume, it should succeed
+        """
+        self.updateHostHypervisorCapability(self.hostCapability.id, 1)
+        capabilities = self.listHostHypervisorCapabilities(self.hostCapability.id)
+        self.assertTrue(isinstance(capabilities, list), "listHypervisorCapabilities response not a valid list")
+        self.assertEqual(len(capabilities), 1, "listHypervisorCapabilities response not valid")
+        self.assertEqual(capabilities[0].maxdatavolumeslimit,
+            1,
+            "listHypervisorCapabilities response maxdatavolumeslimit value not 1")
+
+        Host.update(self.apiclient, id=self.host.id, hosttags="host1")
+        vm = VirtualMachine.create(
+            self.userapiclient,
+            self.services["small"],
+            templateid=self.template.id,
+            accountid=self.account.name,
+            domainid=self.account.domainid,
+            serviceofferingid=self.service_offering.id,
+            zoneid=self.zone.id
+        )
+        volume_created1 = Volume.create(
+            self.userapiclient,
+            self.services["volume"],
+            zoneid=self.zone.id,
+            diskofferingid=self.disk_offering.id
+        )
+        volume_created2 = Volume.create(
+            self.userapiclient,
+            self.services["volume"],
+            zoneid=self.zone.id,
+            diskofferingid=self.disk_offering.id
+        )
+        self.cleanup.append(volume_created1)
+        self.cleanup.append(volume_created2)
+        self.cleanup.append(vm)
+
+        vm.attach_volume(
+            self.userapiclient,
+            volume_created1
+        )
+
+        try:
+            vm.attach_volume(
+                self.userapiclient,
+                volume_created2
+            )
+            vm.detach_volume(self.userapiclient, volume_created1)
+            vm.detach_volume(self.userapiclient, volume_created2)
+            self.fail("Successful to attach 2 DATA disks when max DATA disk limit was set to 1")
+        except Exception as e:
+            self.debug("Failed to attach 2nd DATA disk when max DATA disk limit was set to 1: %s" % e)
+
+        self.updateHostHypervisorCapability(self.hostCapability.id, 32)
+
+        vm.attach_volume(
+            self.userapiclient,
+            volume_created2
+        )
+        vm.detach_volume(self.userapiclient, volume_created1)
+        vm.detach_volume(self.userapiclient, volume_created2)
+
+    @skipTestIf("notSupported")
+    @attr(tags=["advanced", "basic"], required_hardware="false")
+    def test_01_check_hypervisor_vm_snapshot(self):
+        """ Test hypervisor vmsnapshotenabled effect
+
+        # 1. Set vmsnapshotenabled to false for hypervisor
+        # 2. List capabilities and verify value
+        # 3. Deploy a VM
+        # 4. Try VM snapshot, it should fail
+        # 5. Set vmsnapshotenabled to true for hypervisor
+        # 6. Try VM snapshot again, it should succeed
+        """
+        self.updateHostHypervisorCapability(self.hostCapability.id, None, False)
+        capabilities = self.listHostHypervisorCapabilities(self.hostCapability.id)
+        self.assertTrue(isinstance(capabilities, list), "listHypervisorCapabilities response not a valid list")
+        self.assertEqual(len(capabilities), 1, "listHypervisorCapabilities response not valid")
+        self.assertEqual(capabilities[0].vmsnapshotenabled,
+            False,
+            "listHypervisorCapabilities response vmsnapshotenabled value not False")
+
+        Host.update(self.apiclient, id=self.host.id, hosttags="host1")
+        vm = VirtualMachine.create(
+            self.userapiclient,
+            self.services["small"],
+            templateid=self.template.id,
+            accountid=self.account.name,
+            domainid=self.account.domainid,
+            serviceofferingid=self.service_offering.id,
+            zoneid=self.zone.id
+        )
+
+        try:
+            fail_snapshot = VmSnapshot.create(
+                self.userapiclient,
+                vmid=vm.id,
+                snapshotmemory="false",
+                name="Test Snapshot",
+                description="Test Snapshot Desc"
+            )
+            if vm_snapshot:
+                VmSnapshot.deleteVMSnapshot(self.userapiclient, fail_snapshot.id)
+            self.fail("Successful to take VM snapshot even when vmsnapshotenabled was set to False")
+        except Exception as e:
+            self.debug("Failed to take VM snapshot even vmsnapshotenabled was set to False: %s" % e)
+
+        self.updateHostHypervisorCapability(self.hostCapability.id, None, True)
+
+        vm_snapshot = VmSnapshot.create(
+            self.userapiclient,
+            vmid=vm.id,
+            snapshotmemory="false",
+            name="Test Snapshot",
+            description="Test Snapshot Desc"
+        )
+        if vm_snapshot:
+            VmSnapshot.deleteVMSnapshot(self.userapiclient, vm_snapshot.id)

Review comment:
       ```suggestion
           self.cleanup.append(vm_snapshot)
   ```




-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: commits-unsubscribe@cloudstack.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org



[GitHub] [cloudstack] shwstppr closed pull request #5473: api,server: add params for updatehypervisorcapabilities API

Posted by GitBox <gi...@apache.org>.
shwstppr closed pull request #5473:
URL: https://github.com/apache/cloudstack/pull/5473


   


-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: commits-unsubscribe@cloudstack.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org



[GitHub] [cloudstack] DaanHoogland commented on a change in pull request #5473: api,server: add params for updatehypervisorcapabilities API

Posted by GitBox <gi...@apache.org>.
DaanHoogland commented on a change in pull request #5473:
URL: https://github.com/apache/cloudstack/pull/5473#discussion_r795028029



##########
File path: test/integration/smoke/test_hypervisor_capabilities.py
##########
@@ -0,0 +1,291 @@
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements.  See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership.  The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License.  You may obtain a copy of the License at
+#
+#   http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied.  See the License for the
+# specific language governing permissions and limitations
+# under the License.
+""" Test cases for Testing Hypervisor Capabilities
+"""
+from nose.plugins.attrib import attr
+from marvin.cloudstackTestCase import cloudstackTestCase
+from marvin.lib.utils import (cleanup_resources,
+                              validateList)
+from marvin.lib.base import (Account,
+                             ServiceOffering,
+                             DiskOffering,
+                             VirtualMachine,
+                             Volume,
+                             Host,
+                             VmSnapshot)
+from marvin.lib.common import (get_domain,
+                               get_zone,
+                               get_template,
+                               list_virtual_machines,
+                               list_ssvms,
+                               list_routers)
+from marvin.lib.decoratorGenerators import skipTestIf
+
+
+from marvin.cloudstackAPI import (updateHypervisorCapabilities,
+                                  listHypervisorCapabilities)
+
+from marvin.codes import PASS
+
+
+class TestHypervisorCapabilities(cloudstackTestCase):
+
+    @classmethod
+    def setUpClass(cls):
+        testClient = super(TestHypervisorCapabilities, cls).getClsTestClient()
+        cls.apiclient = testClient.getApiClient()
+        cls.services = testClient.getParsedTestDataConfig()
+        cls.zone = get_zone(cls.apiclient, testClient.getZoneForTests())
+        cls.domain = get_domain(cls.apiclient)
+
+        cls.hypervisor = cls.testClient.getHypervisorInfo()
+        # Get Zone, Domain and templates
+
+        cls.notSupported = True
+        cls._cleanup = []
+        cls.hosts = Host.list(cls.apiclient, zoneid=cls.zone.id, type='Routing')
+        if isinstance(cls.hosts, list) and len(cls.hosts) > 0:
+            cls.host = cls.hosts[0]
+            cls.notSupported = False
+
+        cls.hypervisorversion = "default"
+        if hasattr(cls.host, 'hypervisorversion'):
+            cls.hypervisorversion = cls.host.hypervisorversion
+
+        if cls.notSupported == False:
+            cls.notSupported = True
+            cmdList = listHypervisorCapabilities.listHypervisorCapabilitiesCmd()
+            cmdList.hypervisor = cls.hypervisor
+            capabilities = cls.apiclient.listHypervisorCapabilities(cmdList)
+            for capability in capabilities:
+                if capability.hypervisorversion == cls.hypervisorversion:
+                   cls.hostCapability = capability
+                   cls.notSupported = False
+                   break
+
+            if cls.notSupported == True:
+                cls.hypervisorversion = "default"
+                for capability in capabilities:
+                    if capability.hypervisorversion == cls.hypervisorversion:
+                       cls.hostCapability = capability
+                       cls.notSupported = False
+                       break
+
+        print("Test-- %s, %s, %s" % (cls.notSupported, cls.hostCapability.id, cls.hostCapability.maxdatavolumeslimit))
+        if cls.notSupported == False:
+            cls.template = get_template(
+                cls.apiclient,
+                cls.zone.id,
+                cls.services["ostype"])
+
+            # Create an account
+            cls.account = Account.create(
+                cls.apiclient,
+                cls.services["account"],
+                domainid=cls.domain.id
+            )
+            cls._cleanup.append(cls.account)
+
+            # Create user api client of the account
+            cls.userapiclient = testClient.getUserApiClient(
+                UserName=cls.account.name,
+                DomainName=cls.account.domain
+            )
+            # Create Service offering
+            cls.service_offering = ServiceOffering.create(
+                cls.apiclient,
+                cls.services["service_offering"],
+                hosttags="host1"
+            )
+            cls._cleanup.append(cls.service_offering)
+
+            cls.disk_offering = DiskOffering.create(
+                cls.apiclient,
+                cls.services["disk_offering"]
+            )
+            cls._cleanup.append(cls.disk_offering)
+
+        return
+
+    @classmethod
+    def tearDownClass(cls):
+        try:
+            cleanup_resources(cls.apiclient, cls._cleanup)
+        except Exception as e:
+            raise Exception("Warning: Exception during cleanup : %s" % e)
+
+    def setUp(self):
+        self.cleanup = []
+
+        self.apiclient = self.testClient.getApiClient()
+        self.dbclient = self.testClient.getDbConnection()
+
+    def tearDown(self):
+        try:
+            if self.notSupported == False:
+                Host.update(self.apiclient, id=self.host.id, hosttags="")
+                self.updateHostHypervisorCapability(self.hostCapability.id,
+                    self.hostCapability.maxdatavolumeslimit,
+                    self.hostCapability.vmsnapshotenabled)
+
+            cleanup_resources(self.apiclient, self.cleanup)
+        except Exception as e:
+            raise Exception("Warning: Exception during cleanup : %s" % e)
+        return
+
+    @skipTestIf("notSupported")
+    @attr(tags=["advanced", "basic"], required_hardware="false")
+    def test_01_check_hypervisor_max_data_volume_limit(self):
+        """ Test hypervisor maxdatavolumeslimit effect
+
+        # 1. Set maxdatavolumeslimit to 1 for hypervisor
+        # 2. List capabilities and verify value
+        # 3. Deploy a VM and attach a volume to it
+        # 4. Try attach another volume, it should fail
+        # 5. Set maxdatavolumeslimit to 32 for hypervisor
+        # 6. Try attach second volume, it should succeed
+        """
+        self.updateHostHypervisorCapability(self.hostCapability.id, 1)
+        capabilities = self.listHostHypervisorCapabilities(self.hostCapability.id)
+        self.assertTrue(isinstance(capabilities, list), "listHypervisorCapabilities response not a valid list")
+        self.assertEqual(len(capabilities), 1, "listHypervisorCapabilities response not valid")
+        self.assertEqual(capabilities[0].maxdatavolumeslimit,
+            1,
+            "listHypervisorCapabilities response maxdatavolumeslimit value not 1")
+
+        Host.update(self.apiclient, id=self.host.id, hosttags="host1")
+        vm = VirtualMachine.create(
+            self.userapiclient,
+            self.services["small"],
+            templateid=self.template.id,
+            accountid=self.account.name,
+            domainid=self.account.domainid,
+            serviceofferingid=self.service_offering.id,
+            zoneid=self.zone.id
+        )
+        volume_created1 = Volume.create(
+            self.userapiclient,
+            self.services["volume"],
+            zoneid=self.zone.id,
+            diskofferingid=self.disk_offering.id
+        )
+        volume_created2 = Volume.create(
+            self.userapiclient,
+            self.services["volume"],
+            zoneid=self.zone.id,
+            diskofferingid=self.disk_offering.id
+        )
+        self.cleanup.append(volume_created1)
+        self.cleanup.append(volume_created2)
+        self.cleanup.append(vm)
+
+        vm.attach_volume(
+            self.userapiclient,
+            volume_created1
+        )
+
+        try:
+            vm.attach_volume(
+                self.userapiclient,
+                volume_created2
+            )
+            vm.detach_volume(self.userapiclient, volume_created1)
+            vm.detach_volume(self.userapiclient, volume_created2)
+            self.fail("Successful to attach 2 DATA disks when max DATA disk limit was set to 1")
+        except Exception as e:
+            self.debug("Failed to attach 2nd DATA disk when max DATA disk limit was set to 1: %s" % e)
+
+        self.updateHostHypervisorCapability(self.hostCapability.id, 32)
+
+        vm.attach_volume(
+            self.userapiclient,
+            volume_created2
+        )
+        vm.detach_volume(self.userapiclient, volume_created1)
+        vm.detach_volume(self.userapiclient, volume_created2)
+
+    @skipTestIf("notSupported")
+    @attr(tags=["advanced", "basic"], required_hardware="false")
+    def test_01_check_hypervisor_vm_snapshot(self):
+        """ Test hypervisor vmsnapshotenabled effect
+
+        # 1. Set vmsnapshotenabled to false for hypervisor
+        # 2. List capabilities and verify value
+        # 3. Deploy a VM
+        # 4. Try VM snapshot, it should fail
+        # 5. Set vmsnapshotenabled to true for hypervisor
+        # 6. Try VM snapshot again, it should succeed
+        """
+        self.updateHostHypervisorCapability(self.hostCapability.id, None, False)
+        capabilities = self.listHostHypervisorCapabilities(self.hostCapability.id)
+        self.assertTrue(isinstance(capabilities, list), "listHypervisorCapabilities response not a valid list")
+        self.assertEqual(len(capabilities), 1, "listHypervisorCapabilities response not valid")
+        self.assertEqual(capabilities[0].vmsnapshotenabled,
+            False,
+            "listHypervisorCapabilities response vmsnapshotenabled value not False")
+
+        Host.update(self.apiclient, id=self.host.id, hosttags="host1")
+        vm = VirtualMachine.create(
+            self.userapiclient,
+            self.services["small"],
+            templateid=self.template.id,
+            accountid=self.account.name,
+            domainid=self.account.domainid,
+            serviceofferingid=self.service_offering.id,
+            zoneid=self.zone.id
+        )
+
+        try:
+            fail_snapshot = VmSnapshot.create(
+                self.userapiclient,
+                vmid=vm.id,
+                snapshotmemory="false",
+                name="Test Snapshot",
+                description="Test Snapshot Desc"
+            )
+            if vm_snapshot:
+                VmSnapshot.deleteVMSnapshot(self.userapiclient, fail_snapshot.id)
+            self.fail("Successful to take VM snapshot even when vmsnapshotenabled was set to False")
+        except Exception as e:
+            self.debug("Failed to take VM snapshot even vmsnapshotenabled was set to False: %s" % e)
+
+        self.updateHostHypervisorCapability(self.hostCapability.id, None, True)
+
+        vm_snapshot = VmSnapshot.create(
+            self.userapiclient,
+            vmid=vm.id,
+            snapshotmemory="false",
+            name="Test Snapshot",
+            description="Test Snapshot Desc"
+        )
+        if vm_snapshot:
+            VmSnapshot.deleteVMSnapshot(self.userapiclient, vm_snapshot.id)

Review comment:
       ok, hadn't realised that, but good solution :+1: 




-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: commits-unsubscribe@cloudstack.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org



[GitHub] [cloudstack] blueorangutan commented on pull request #5473: api,server: add params for updatehypervisorcapabilities API

Posted by GitBox <gi...@apache.org>.
blueorangutan commented on pull request #5473:
URL: https://github.com/apache/cloudstack/pull/5473#issuecomment-1025213326


   Packaging result: :heavy_check_mark: el7 :heavy_check_mark: el8 :heavy_check_mark: debian :heavy_check_mark: suse15. SL-JID 2386


-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: commits-unsubscribe@cloudstack.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org



[GitHub] [cloudstack] blueorangutan commented on pull request #5473: api,server: add params for updatehypervisorcapabilities API

Posted by GitBox <gi...@apache.org>.
blueorangutan commented on pull request #5473:
URL: https://github.com/apache/cloudstack/pull/5473#issuecomment-1028469201


   <b>Trillian test result (tid-3124)</b>
   Environment: kvm-centos7 (x2), Advanced Networking with Mgmt server 7
   Total time taken: 41197 seconds
   Marvin logs: https://github.com/blueorangutan/acs-prs/releases/download/trillian/pr5473-t3124-kvm-centos7.zip
   Smoke tests completed. 92 look OK, 0 have errors
   Only failed tests results shown below:
   
   
   Test | Result | Time (s) | Test File
   --- | --- | --- | ---
   


-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: commits-unsubscribe@cloudstack.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org



[GitHub] [cloudstack] shwstppr commented on pull request #5473: api,server: add params for updatehypervisorcapabilities API

Posted by GitBox <gi...@apache.org>.
shwstppr commented on pull request #5473:
URL: https://github.com/apache/cloudstack/pull/5473#issuecomment-923267473


   @blueorangutan test


-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: commits-unsubscribe@cloudstack.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org



[GitHub] [cloudstack] blueorangutan commented on pull request #5473: api,server: add params for updatehypervisorcapabilities API

Posted by GitBox <gi...@apache.org>.
blueorangutan commented on pull request #5473:
URL: https://github.com/apache/cloudstack/pull/5473#issuecomment-1027860427


   Packaging result: :heavy_check_mark: el7 :heavy_check_mark: el8 :heavy_check_mark: debian :heavy_check_mark: suse15. SL-JID 2427


-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: commits-unsubscribe@cloudstack.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org



[GitHub] [cloudstack] blueorangutan commented on pull request #5473: api,server: add params for updatehypervisorcapabilities API

Posted by GitBox <gi...@apache.org>.
blueorangutan commented on pull request #5473:
URL: https://github.com/apache/cloudstack/pull/5473#issuecomment-1025227849


   @sureshanaparti a Trillian-Jenkins test job (centos7 mgmt + kvm-centos7) has been kicked to run smoke tests


-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: commits-unsubscribe@cloudstack.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org



[GitHub] [cloudstack] DaanHoogland commented on pull request #5473: api,server: add params for updatehypervisorcapabilities API

Posted by GitBox <gi...@apache.org>.
DaanHoogland commented on pull request #5473:
URL: https://github.com/apache/cloudstack/pull/5473#issuecomment-1025603242


   @shwstppr , these trillian failures seem related to the changes, can you have a look?


-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: commits-unsubscribe@cloudstack.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org



[GitHub] [cloudstack] blueorangutan commented on pull request #5473: api,server: add params for updatehypervisorcapabilities API

Posted by GitBox <gi...@apache.org>.
blueorangutan commented on pull request #5473:
URL: https://github.com/apache/cloudstack/pull/5473#issuecomment-923268183


   @shwstppr a Trillian-Jenkins test job (centos7 mgmt + kvm-centos7) has been kicked to run smoke tests


-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: commits-unsubscribe@cloudstack.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org



[GitHub] [cloudstack] shwstppr commented on pull request #5473: api,server: add params for updatehypervisorcapabilities API

Posted by GitBox <gi...@apache.org>.
shwstppr commented on pull request #5473:
URL: https://github.com/apache/cloudstack/pull/5473#issuecomment-1027632128


   @DaanHoogland as discussed, moved test to component and made fixes.
   - Detach volume was failing intermittently for multiple disks so added a stop VM statement
   - VM snapshots for a running VM is not supported on KVM so skipped that test for KVM.
   
   Tested VMware and KVM. KVM logs below:
   
   ```
   [root@pr5473-t3104-kvm-centos7-marvin marvin]# nosetests --with-xunit --xunit-file=results.xml --with-marvin --marvin-config=./pr5473-t3104-kvm-centos7-advanced-cfg -s -a tags=advanced --hypervisor=KVM tests/component/test_hypervisor_capabilities.py 
   
   ==== Marvin Init Started ====
   
   === Marvin Parse Config Successful ===
   
   === Marvin Setting TestData Successful===
   
   ==== Log Folder Path: /marvin/MarvinLogs/Feb_02_2022_06_34_09_97PJFK All logs will be available here ====
   
   === Marvin Init Logging Successful===
   
   ==== Marvin Init Successful ====
   === TestName: test_01_check_hypervisor_max_data_volume_limit | Status : SUCCESS ===
   
   === Final results are now copied to: /marvin//MarvinLogs/test_hypervisor_capabilities_1R6CDP ===
   [root@pr5473-t3104-kvm-centos7-marvin marvin]# cat /marvin//MarvinLogs/test_hypervisor_capabilities_1R6CDP/results.txt 
   Test hypervisor maxdatavolumeslimit effect ... === TestName: test_01_check_hypervisor_max_data_volume_limit | Status : SUCCESS ===
   ok
   Test hypervisor vmsnapshotenabled effect ... SKIP: Skipping test: Reason -  VM Snapshot of running VM is not supported for KVM
   
   ----------------------------------------------------------------------
   Ran 2 tests in 90.896s
   
   OK (SKIP=1)
   ```


-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: commits-unsubscribe@cloudstack.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org



[GitHub] [cloudstack] blueorangutan commented on pull request #5473: api,server: add params for updatehypervisorcapabilities API

Posted by GitBox <gi...@apache.org>.
blueorangutan commented on pull request #5473:
URL: https://github.com/apache/cloudstack/pull/5473#issuecomment-1027872001


   @sureshanaparti a Trillian-Jenkins test job (centos7 mgmt + kvm-centos7) has been kicked to run smoke tests


-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: commits-unsubscribe@cloudstack.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org



[GitHub] [cloudstack] blueorangutan commented on pull request #5473: api,server: add params for updatehypervisorcapabilities API

Posted by GitBox <gi...@apache.org>.
blueorangutan commented on pull request #5473:
URL: https://github.com/apache/cloudstack/pull/5473#issuecomment-922764928


   @shwstppr a Jenkins job has been kicked to build packages. I'll keep you posted as I make progress.


-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: commits-unsubscribe@cloudstack.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org



[GitHub] [cloudstack] shwstppr commented on pull request #5473: api,server: add params for updatehypervisorcapabilities API

Posted by GitBox <gi...@apache.org>.
shwstppr commented on pull request #5473:
URL: https://github.com/apache/cloudstack/pull/5473#issuecomment-1025649682


   @DaanHoogland will check and update


-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: commits-unsubscribe@cloudstack.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org



[GitHub] [cloudstack] sureshanaparti commented on pull request #5473: api,server: add params for updatehypervisorcapabilities API

Posted by GitBox <gi...@apache.org>.
sureshanaparti commented on pull request #5473:
URL: https://github.com/apache/cloudstack/pull/5473#issuecomment-1025199504


   @blueorangutan package


-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: commits-unsubscribe@cloudstack.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org



[GitHub] [cloudstack] blueorangutan commented on pull request #5473: api,server: add params for updatehypervisorcapabilities API

Posted by GitBox <gi...@apache.org>.
blueorangutan commented on pull request #5473:
URL: https://github.com/apache/cloudstack/pull/5473#issuecomment-1025199662


   @sureshanaparti a Jenkins job has been kicked to build packages. I'll keep you posted as I make progress.


-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: commits-unsubscribe@cloudstack.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org



[GitHub] [cloudstack] DaanHoogland commented on a change in pull request #5473: api,server: add params for updatehypervisorcapabilities API

Posted by GitBox <gi...@apache.org>.
DaanHoogland commented on a change in pull request #5473:
URL: https://github.com/apache/cloudstack/pull/5473#discussion_r795027950



##########
File path: tools/marvin/marvin/lib/base.py
##########
@@ -5097,6 +5097,11 @@ def deleteVMSnapshot(cls, apiclient, vmsnapshotid):
         cmd.vmsnapshotid = vmsnapshotid
         return apiclient.deleteVMSnapshot(cmd)
 
+    def delete(self, apiclient):

Review comment:
       :+1: 




-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: commits-unsubscribe@cloudstack.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org



[GitHub] [cloudstack] blueorangutan commented on pull request #5473: api,server: add params for updatehypervisorcapabilities API

Posted by GitBox <gi...@apache.org>.
blueorangutan commented on pull request #5473:
URL: https://github.com/apache/cloudstack/pull/5473#issuecomment-922779203


   Packaging result: :heavy_check_mark: el7 :heavy_check_mark: el8 :heavy_check_mark: debian :heavy_check_mark: suse15. SL-JID 1323


-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: commits-unsubscribe@cloudstack.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org



[GitHub] [cloudstack] sureshanaparti merged pull request #5473: api,server: add params for updatehypervisorcapabilities API

Posted by GitBox <gi...@apache.org>.
sureshanaparti merged pull request #5473:
URL: https://github.com/apache/cloudstack/pull/5473


   


-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: commits-unsubscribe@cloudstack.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org



[GitHub] [cloudstack] shwstppr commented on a change in pull request #5473: api,server: add params for updatehypervisorcapabilities API

Posted by GitBox <gi...@apache.org>.
shwstppr commented on a change in pull request #5473:
URL: https://github.com/apache/cloudstack/pull/5473#discussion_r794774224



##########
File path: test/integration/smoke/test_hypervisor_capabilities.py
##########
@@ -0,0 +1,291 @@
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements.  See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership.  The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License.  You may obtain a copy of the License at
+#
+#   http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied.  See the License for the
+# specific language governing permissions and limitations
+# under the License.
+""" Test cases for Testing Hypervisor Capabilities
+"""
+from nose.plugins.attrib import attr
+from marvin.cloudstackTestCase import cloudstackTestCase
+from marvin.lib.utils import (cleanup_resources,
+                              validateList)
+from marvin.lib.base import (Account,
+                             ServiceOffering,
+                             DiskOffering,
+                             VirtualMachine,
+                             Volume,
+                             Host,
+                             VmSnapshot)
+from marvin.lib.common import (get_domain,
+                               get_zone,
+                               get_template,
+                               list_virtual_machines,
+                               list_ssvms,
+                               list_routers)
+from marvin.lib.decoratorGenerators import skipTestIf
+
+
+from marvin.cloudstackAPI import (updateHypervisorCapabilities,
+                                  listHypervisorCapabilities)
+
+from marvin.codes import PASS
+
+
+class TestHypervisorCapabilities(cloudstackTestCase):
+
+    @classmethod
+    def setUpClass(cls):
+        testClient = super(TestHypervisorCapabilities, cls).getClsTestClient()
+        cls.apiclient = testClient.getApiClient()
+        cls.services = testClient.getParsedTestDataConfig()
+        cls.zone = get_zone(cls.apiclient, testClient.getZoneForTests())
+        cls.domain = get_domain(cls.apiclient)
+
+        cls.hypervisor = cls.testClient.getHypervisorInfo()
+        # Get Zone, Domain and templates
+
+        cls.notSupported = True
+        cls._cleanup = []
+        cls.hosts = Host.list(cls.apiclient, zoneid=cls.zone.id, type='Routing')
+        if isinstance(cls.hosts, list) and len(cls.hosts) > 0:
+            cls.host = cls.hosts[0]
+            cls.notSupported = False
+
+        cls.hypervisorversion = "default"
+        if hasattr(cls.host, 'hypervisorversion'):
+            cls.hypervisorversion = cls.host.hypervisorversion
+
+        if cls.notSupported == False:
+            cls.notSupported = True
+            cmdList = listHypervisorCapabilities.listHypervisorCapabilitiesCmd()
+            cmdList.hypervisor = cls.hypervisor
+            capabilities = cls.apiclient.listHypervisorCapabilities(cmdList)
+            for capability in capabilities:
+                if capability.hypervisorversion == cls.hypervisorversion:
+                   cls.hostCapability = capability
+                   cls.notSupported = False
+                   break
+
+            if cls.notSupported == True:
+                cls.hypervisorversion = "default"
+                for capability in capabilities:
+                    if capability.hypervisorversion == cls.hypervisorversion:
+                       cls.hostCapability = capability
+                       cls.notSupported = False
+                       break
+
+        print("Test-- %s, %s, %s" % (cls.notSupported, cls.hostCapability.id, cls.hostCapability.maxdatavolumeslimit))
+        if cls.notSupported == False:
+            cls.template = get_template(
+                cls.apiclient,
+                cls.zone.id,
+                cls.services["ostype"])
+
+            # Create an account
+            cls.account = Account.create(
+                cls.apiclient,
+                cls.services["account"],
+                domainid=cls.domain.id
+            )
+            cls._cleanup.append(cls.account)
+
+            # Create user api client of the account
+            cls.userapiclient = testClient.getUserApiClient(
+                UserName=cls.account.name,
+                DomainName=cls.account.domain
+            )
+            # Create Service offering
+            cls.service_offering = ServiceOffering.create(
+                cls.apiclient,
+                cls.services["service_offering"],
+                hosttags="host1"
+            )
+            cls._cleanup.append(cls.service_offering)
+
+            cls.disk_offering = DiskOffering.create(
+                cls.apiclient,
+                cls.services["disk_offering"]
+            )
+            cls._cleanup.append(cls.disk_offering)
+
+        return
+
+    @classmethod
+    def tearDownClass(cls):
+        try:
+            cleanup_resources(cls.apiclient, cls._cleanup)
+        except Exception as e:
+            raise Exception("Warning: Exception during cleanup : %s" % e)
+
+    def setUp(self):
+        self.cleanup = []
+
+        self.apiclient = self.testClient.getApiClient()
+        self.dbclient = self.testClient.getDbConnection()
+
+    def tearDown(self):
+        try:
+            if self.notSupported == False:
+                Host.update(self.apiclient, id=self.host.id, hosttags="")
+                self.updateHostHypervisorCapability(self.hostCapability.id,
+                    self.hostCapability.maxdatavolumeslimit,
+                    self.hostCapability.vmsnapshotenabled)
+
+            cleanup_resources(self.apiclient, self.cleanup)
+        except Exception as e:
+            raise Exception("Warning: Exception during cleanup : %s" % e)
+        return
+
+    @skipTestIf("notSupported")
+    @attr(tags=["advanced", "basic"], required_hardware="false")
+    def test_01_check_hypervisor_max_data_volume_limit(self):
+        """ Test hypervisor maxdatavolumeslimit effect
+
+        # 1. Set maxdatavolumeslimit to 1 for hypervisor
+        # 2. List capabilities and verify value
+        # 3. Deploy a VM and attach a volume to it
+        # 4. Try attach another volume, it should fail
+        # 5. Set maxdatavolumeslimit to 32 for hypervisor
+        # 6. Try attach second volume, it should succeed
+        """
+        self.updateHostHypervisorCapability(self.hostCapability.id, 1)
+        capabilities = self.listHostHypervisorCapabilities(self.hostCapability.id)
+        self.assertTrue(isinstance(capabilities, list), "listHypervisorCapabilities response not a valid list")
+        self.assertEqual(len(capabilities), 1, "listHypervisorCapabilities response not valid")
+        self.assertEqual(capabilities[0].maxdatavolumeslimit,
+            1,
+            "listHypervisorCapabilities response maxdatavolumeslimit value not 1")
+
+        Host.update(self.apiclient, id=self.host.id, hosttags="host1")
+        vm = VirtualMachine.create(
+            self.userapiclient,
+            self.services["small"],
+            templateid=self.template.id,
+            accountid=self.account.name,
+            domainid=self.account.domainid,
+            serviceofferingid=self.service_offering.id,
+            zoneid=self.zone.id
+        )
+        volume_created1 = Volume.create(
+            self.userapiclient,
+            self.services["volume"],
+            zoneid=self.zone.id,
+            diskofferingid=self.disk_offering.id
+        )
+        volume_created2 = Volume.create(
+            self.userapiclient,
+            self.services["volume"],
+            zoneid=self.zone.id,
+            diskofferingid=self.disk_offering.id
+        )
+        self.cleanup.append(volume_created1)
+        self.cleanup.append(volume_created2)
+        self.cleanup.append(vm)
+
+        vm.attach_volume(
+            self.userapiclient,
+            volume_created1
+        )
+
+        try:
+            vm.attach_volume(
+                self.userapiclient,
+                volume_created2
+            )
+            vm.detach_volume(self.userapiclient, volume_created1)
+            vm.detach_volume(self.userapiclient, volume_created2)
+            self.fail("Successful to attach 2 DATA disks when max DATA disk limit was set to 1")
+        except Exception as e:
+            self.debug("Failed to attach 2nd DATA disk when max DATA disk limit was set to 1: %s" % e)
+
+        self.updateHostHypervisorCapability(self.hostCapability.id, 32)
+
+        vm.attach_volume(
+            self.userapiclient,
+            volume_created2
+        )
+        vm.detach_volume(self.userapiclient, volume_created1)
+        vm.detach_volume(self.userapiclient, volume_created2)
+
+    @skipTestIf("notSupported")
+    @attr(tags=["advanced", "basic"], required_hardware="false")
+    def test_01_check_hypervisor_vm_snapshot(self):
+        """ Test hypervisor vmsnapshotenabled effect
+
+        # 1. Set vmsnapshotenabled to false for hypervisor
+        # 2. List capabilities and verify value
+        # 3. Deploy a VM
+        # 4. Try VM snapshot, it should fail
+        # 5. Set vmsnapshotenabled to true for hypervisor
+        # 6. Try VM snapshot again, it should succeed
+        """
+        self.updateHostHypervisorCapability(self.hostCapability.id, None, False)
+        capabilities = self.listHostHypervisorCapabilities(self.hostCapability.id)
+        self.assertTrue(isinstance(capabilities, list), "listHypervisorCapabilities response not a valid list")
+        self.assertEqual(len(capabilities), 1, "listHypervisorCapabilities response not valid")
+        self.assertEqual(capabilities[0].vmsnapshotenabled,
+            False,
+            "listHypervisorCapabilities response vmsnapshotenabled value not False")
+
+        Host.update(self.apiclient, id=self.host.id, hosttags="host1")
+        vm = VirtualMachine.create(
+            self.userapiclient,
+            self.services["small"],
+            templateid=self.template.id,
+            accountid=self.account.name,
+            domainid=self.account.domainid,
+            serviceofferingid=self.service_offering.id,
+            zoneid=self.zone.id
+        )
+
+        try:
+            fail_snapshot = VmSnapshot.create(
+                self.userapiclient,
+                vmid=vm.id,
+                snapshotmemory="false",
+                name="Test Snapshot",
+                description="Test Snapshot Desc"
+            )
+            if vm_snapshot:
+                VmSnapshot.deleteVMSnapshot(self.userapiclient, fail_snapshot.id)
+            self.fail("Successful to take VM snapshot even when vmsnapshotenabled was set to False")
+        except Exception as e:
+            self.debug("Failed to take VM snapshot even vmsnapshotenabled was set to False: %s" % e)
+
+        self.updateHostHypervisorCapability(self.hostCapability.id, None, True)
+
+        vm_snapshot = VmSnapshot.create(
+            self.userapiclient,
+            vmid=vm.id,
+            snapshotmemory="false",
+            name="Test Snapshot",
+            description="Test Snapshot Desc"
+        )
+        if vm_snapshot:
+            VmSnapshot.deleteVMSnapshot(self.userapiclient, vm_snapshot.id)

Review comment:
       had to make change to `lib/base.py`




-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: commits-unsubscribe@cloudstack.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org



[GitHub] [cloudstack] DaanHoogland commented on a change in pull request #5473: api,server: add params for updatehypervisorcapabilities API

Posted by GitBox <gi...@apache.org>.
DaanHoogland commented on a change in pull request #5473:
URL: https://github.com/apache/cloudstack/pull/5473#discussion_r795028029



##########
File path: test/integration/smoke/test_hypervisor_capabilities.py
##########
@@ -0,0 +1,291 @@
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements.  See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership.  The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License.  You may obtain a copy of the License at
+#
+#   http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied.  See the License for the
+# specific language governing permissions and limitations
+# under the License.
+""" Test cases for Testing Hypervisor Capabilities
+"""
+from nose.plugins.attrib import attr
+from marvin.cloudstackTestCase import cloudstackTestCase
+from marvin.lib.utils import (cleanup_resources,
+                              validateList)
+from marvin.lib.base import (Account,
+                             ServiceOffering,
+                             DiskOffering,
+                             VirtualMachine,
+                             Volume,
+                             Host,
+                             VmSnapshot)
+from marvin.lib.common import (get_domain,
+                               get_zone,
+                               get_template,
+                               list_virtual_machines,
+                               list_ssvms,
+                               list_routers)
+from marvin.lib.decoratorGenerators import skipTestIf
+
+
+from marvin.cloudstackAPI import (updateHypervisorCapabilities,
+                                  listHypervisorCapabilities)
+
+from marvin.codes import PASS
+
+
+class TestHypervisorCapabilities(cloudstackTestCase):
+
+    @classmethod
+    def setUpClass(cls):
+        testClient = super(TestHypervisorCapabilities, cls).getClsTestClient()
+        cls.apiclient = testClient.getApiClient()
+        cls.services = testClient.getParsedTestDataConfig()
+        cls.zone = get_zone(cls.apiclient, testClient.getZoneForTests())
+        cls.domain = get_domain(cls.apiclient)
+
+        cls.hypervisor = cls.testClient.getHypervisorInfo()
+        # Get Zone, Domain and templates
+
+        cls.notSupported = True
+        cls._cleanup = []
+        cls.hosts = Host.list(cls.apiclient, zoneid=cls.zone.id, type='Routing')
+        if isinstance(cls.hosts, list) and len(cls.hosts) > 0:
+            cls.host = cls.hosts[0]
+            cls.notSupported = False
+
+        cls.hypervisorversion = "default"
+        if hasattr(cls.host, 'hypervisorversion'):
+            cls.hypervisorversion = cls.host.hypervisorversion
+
+        if cls.notSupported == False:
+            cls.notSupported = True
+            cmdList = listHypervisorCapabilities.listHypervisorCapabilitiesCmd()
+            cmdList.hypervisor = cls.hypervisor
+            capabilities = cls.apiclient.listHypervisorCapabilities(cmdList)
+            for capability in capabilities:
+                if capability.hypervisorversion == cls.hypervisorversion:
+                   cls.hostCapability = capability
+                   cls.notSupported = False
+                   break
+
+            if cls.notSupported == True:
+                cls.hypervisorversion = "default"
+                for capability in capabilities:
+                    if capability.hypervisorversion == cls.hypervisorversion:
+                       cls.hostCapability = capability
+                       cls.notSupported = False
+                       break
+
+        print("Test-- %s, %s, %s" % (cls.notSupported, cls.hostCapability.id, cls.hostCapability.maxdatavolumeslimit))
+        if cls.notSupported == False:
+            cls.template = get_template(
+                cls.apiclient,
+                cls.zone.id,
+                cls.services["ostype"])
+
+            # Create an account
+            cls.account = Account.create(
+                cls.apiclient,
+                cls.services["account"],
+                domainid=cls.domain.id
+            )
+            cls._cleanup.append(cls.account)
+
+            # Create user api client of the account
+            cls.userapiclient = testClient.getUserApiClient(
+                UserName=cls.account.name,
+                DomainName=cls.account.domain
+            )
+            # Create Service offering
+            cls.service_offering = ServiceOffering.create(
+                cls.apiclient,
+                cls.services["service_offering"],
+                hosttags="host1"
+            )
+            cls._cleanup.append(cls.service_offering)
+
+            cls.disk_offering = DiskOffering.create(
+                cls.apiclient,
+                cls.services["disk_offering"]
+            )
+            cls._cleanup.append(cls.disk_offering)
+
+        return
+
+    @classmethod
+    def tearDownClass(cls):
+        try:
+            cleanup_resources(cls.apiclient, cls._cleanup)
+        except Exception as e:
+            raise Exception("Warning: Exception during cleanup : %s" % e)
+
+    def setUp(self):
+        self.cleanup = []
+
+        self.apiclient = self.testClient.getApiClient()
+        self.dbclient = self.testClient.getDbConnection()
+
+    def tearDown(self):
+        try:
+            if self.notSupported == False:
+                Host.update(self.apiclient, id=self.host.id, hosttags="")
+                self.updateHostHypervisorCapability(self.hostCapability.id,
+                    self.hostCapability.maxdatavolumeslimit,
+                    self.hostCapability.vmsnapshotenabled)
+
+            cleanup_resources(self.apiclient, self.cleanup)
+        except Exception as e:
+            raise Exception("Warning: Exception during cleanup : %s" % e)
+        return
+
+    @skipTestIf("notSupported")
+    @attr(tags=["advanced", "basic"], required_hardware="false")
+    def test_01_check_hypervisor_max_data_volume_limit(self):
+        """ Test hypervisor maxdatavolumeslimit effect
+
+        # 1. Set maxdatavolumeslimit to 1 for hypervisor
+        # 2. List capabilities and verify value
+        # 3. Deploy a VM and attach a volume to it
+        # 4. Try attach another volume, it should fail
+        # 5. Set maxdatavolumeslimit to 32 for hypervisor
+        # 6. Try attach second volume, it should succeed
+        """
+        self.updateHostHypervisorCapability(self.hostCapability.id, 1)
+        capabilities = self.listHostHypervisorCapabilities(self.hostCapability.id)
+        self.assertTrue(isinstance(capabilities, list), "listHypervisorCapabilities response not a valid list")
+        self.assertEqual(len(capabilities), 1, "listHypervisorCapabilities response not valid")
+        self.assertEqual(capabilities[0].maxdatavolumeslimit,
+            1,
+            "listHypervisorCapabilities response maxdatavolumeslimit value not 1")
+
+        Host.update(self.apiclient, id=self.host.id, hosttags="host1")
+        vm = VirtualMachine.create(
+            self.userapiclient,
+            self.services["small"],
+            templateid=self.template.id,
+            accountid=self.account.name,
+            domainid=self.account.domainid,
+            serviceofferingid=self.service_offering.id,
+            zoneid=self.zone.id
+        )
+        volume_created1 = Volume.create(
+            self.userapiclient,
+            self.services["volume"],
+            zoneid=self.zone.id,
+            diskofferingid=self.disk_offering.id
+        )
+        volume_created2 = Volume.create(
+            self.userapiclient,
+            self.services["volume"],
+            zoneid=self.zone.id,
+            diskofferingid=self.disk_offering.id
+        )
+        self.cleanup.append(volume_created1)
+        self.cleanup.append(volume_created2)
+        self.cleanup.append(vm)
+
+        vm.attach_volume(
+            self.userapiclient,
+            volume_created1
+        )
+
+        try:
+            vm.attach_volume(
+                self.userapiclient,
+                volume_created2
+            )
+            vm.detach_volume(self.userapiclient, volume_created1)
+            vm.detach_volume(self.userapiclient, volume_created2)
+            self.fail("Successful to attach 2 DATA disks when max DATA disk limit was set to 1")
+        except Exception as e:
+            self.debug("Failed to attach 2nd DATA disk when max DATA disk limit was set to 1: %s" % e)
+
+        self.updateHostHypervisorCapability(self.hostCapability.id, 32)
+
+        vm.attach_volume(
+            self.userapiclient,
+            volume_created2
+        )
+        vm.detach_volume(self.userapiclient, volume_created1)
+        vm.detach_volume(self.userapiclient, volume_created2)
+
+    @skipTestIf("notSupported")
+    @attr(tags=["advanced", "basic"], required_hardware="false")
+    def test_01_check_hypervisor_vm_snapshot(self):
+        """ Test hypervisor vmsnapshotenabled effect
+
+        # 1. Set vmsnapshotenabled to false for hypervisor
+        # 2. List capabilities and verify value
+        # 3. Deploy a VM
+        # 4. Try VM snapshot, it should fail
+        # 5. Set vmsnapshotenabled to true for hypervisor
+        # 6. Try VM snapshot again, it should succeed
+        """
+        self.updateHostHypervisorCapability(self.hostCapability.id, None, False)
+        capabilities = self.listHostHypervisorCapabilities(self.hostCapability.id)
+        self.assertTrue(isinstance(capabilities, list), "listHypervisorCapabilities response not a valid list")
+        self.assertEqual(len(capabilities), 1, "listHypervisorCapabilities response not valid")
+        self.assertEqual(capabilities[0].vmsnapshotenabled,
+            False,
+            "listHypervisorCapabilities response vmsnapshotenabled value not False")
+
+        Host.update(self.apiclient, id=self.host.id, hosttags="host1")
+        vm = VirtualMachine.create(
+            self.userapiclient,
+            self.services["small"],
+            templateid=self.template.id,
+            accountid=self.account.name,
+            domainid=self.account.domainid,
+            serviceofferingid=self.service_offering.id,
+            zoneid=self.zone.id
+        )
+
+        try:
+            fail_snapshot = VmSnapshot.create(
+                self.userapiclient,
+                vmid=vm.id,
+                snapshotmemory="false",
+                name="Test Snapshot",
+                description="Test Snapshot Desc"
+            )
+            if vm_snapshot:
+                VmSnapshot.deleteVMSnapshot(self.userapiclient, fail_snapshot.id)
+            self.fail("Successful to take VM snapshot even when vmsnapshotenabled was set to False")
+        except Exception as e:
+            self.debug("Failed to take VM snapshot even vmsnapshotenabled was set to False: %s" % e)
+
+        self.updateHostHypervisorCapability(self.hostCapability.id, None, True)
+
+        vm_snapshot = VmSnapshot.create(
+            self.userapiclient,
+            vmid=vm.id,
+            snapshotmemory="false",
+            name="Test Snapshot",
+            description="Test Snapshot Desc"
+        )
+        if vm_snapshot:
+            VmSnapshot.deleteVMSnapshot(self.userapiclient, vm_snapshot.id)

Review comment:
       ok, hadn;t realised that, but good solution :+1: 




-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: commits-unsubscribe@cloudstack.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org