You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@cloudstack.apache.org by mc...@apache.org on 2014/02/22 00:36:01 UTC

git commit: updated refs/heads/rbac to b78cb22

Repository: cloudstack
Updated Branches:
  refs/heads/rbac 42a7d41c5 -> b78cb2284


Add marvin integration test for list VM.


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

Branch: refs/heads/rbac
Commit: b78cb2284aae8fa340d0ae719d4a45c67046900e
Parents: 42a7d41
Author: Min Chen <mi...@citrix.com>
Authored: Fri Feb 21 15:33:41 2014 -0800
Committer: Min Chen <mi...@citrix.com>
Committed: Fri Feb 21 15:35:48 2014 -0800

----------------------------------------------------------------------
 test/integration/smoke/test_vm_iam.py       | 713 +++++++++++++++++++++++
 tools/marvin/marvin/integration/lib/base.py | 128 ++++
 2 files changed, 841 insertions(+)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/cloudstack/blob/b78cb228/test/integration/smoke/test_vm_iam.py
----------------------------------------------------------------------
diff --git a/test/integration/smoke/test_vm_iam.py b/test/integration/smoke/test_vm_iam.py
new file mode 100644
index 0000000..062c030
--- /dev/null
+++ b/test/integration/smoke/test_vm_iam.py
@@ -0,0 +1,713 @@
+# 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.
+""" BVT tests for Virtual Machine IAM effect
+"""
+#Import Local Modules
+import marvin
+from marvin.cloudstackTestCase import *
+from marvin.cloudstackAPI import *
+from marvin.integration.lib.utils import *
+from marvin.integration.lib.base import *
+from marvin.integration.lib.common import *
+from nose.plugins.attrib import attr
+#Import System modules
+import time
+
+_multiprocess_shared_ = True
+class Services:
+    """Test VM Life Cycle Services
+    """
+
+    def __init__(self):
+        self.services = {
+            #data for domains and accounts
+            "domain1": {
+                "name": "Domain1",
+             },
+            "account1A": {
+                "email": "test1A@test.com",
+                "firstname": "test1A",
+                "lastname": "User",
+                "username": "test1A",
+                "password": "password",
+            },
+            "account1B": {
+                "email": "test1B@test.com",
+                "firstname": "test1B",
+                "lastname": "User",
+                "username": "test1B",
+                "password": "password",
+            },                         
+            "domain2": {
+                "name": "Domain2",
+             },
+            "account2A": {
+                "email": "test2A@test.com",
+                "firstname": "test2A",
+                "lastname": "User",
+                "username": "test2A",
+                "password": "password",
+            },
+            #data reqd for virtual machine creation
+            "virtual_machine1A" : {
+                "name" : "test1Avm",
+                "displayname" : "Test1A  VM",
+            },
+            "virtual_machine1B" : {
+                "name" : "test1Bvm",
+                "displayname" : "Test1B  VM",
+            }, 
+            "virtual_machine2A" : {
+                "name" : "test2Avm",
+                "displayname" : "Test2A  VM",
+            },                                                 
+            #small service offering
+            "service_offering": {
+                "small": {
+                    "name": "Small Instance",
+                    "displaytext": "Small Instance",
+                    "cpunumber": 1,
+                    "cpuspeed": 100,
+                    "memory": 128,
+                },
+            },
+            "ostype": 'CentOS 5.3 (64-bit)',
+            # iam group and policy information
+            "service_desk_iam_grp" : {
+                "name" : "Service Desk",
+                "description" : "Service Desk IAM Group"
+            },
+            "vm_readonly_iam_policy" : {
+                "name" : "VM Read Only Access",
+                "description" : "VM read only access iam policy"
+            },
+        }
+
+
+
+class TestVMIam(cloudstackTestCase):
+
+    @classmethod
+    def setUpClass(self):
+        self.apiclient = super(TestVMIam, self).getClsTestClient().getApiClient()
+        self.services = Services().services
+        
+        # backup default apikey and secretkey
+        self.default_apikey = self.apiclient.connection.apiKey
+        self.default_secretkey = self.apiclient.connection.securityKey
+
+        # Create domains and accounts etc
+        self.domain_1 = Domain.create(
+                                   self.apiclient,
+                                   self.services["domain1"]
+                                   )
+        self.domain_2 = Domain.create(
+                                   self.apiclient,
+                                   self.services["domain2"]
+                                   )
+        # Create two accounts for doamin_1
+        self.account_1A = Account.create(
+                            self.apiclient,
+                            self.services["account1A"],
+                            admin=False,
+                            domainid=self.domain_1.id
+                            )
+        
+        self.account_1B = Account.create(
+                            self.apiclient,
+                            self.services["account1B"],
+                            admin=False,
+                            domainid=self.domain_1.id
+                            )        
+
+        # Create an account for domain_2
+        self.account_2A = Account.create(
+                            self.apiclient,
+                            self.services["account2A"],
+                            admin=False,
+                            domainid=self.domain_2.id
+                            )
+        
+        # Fetch user details to register apiKey for them
+        self.user_1A = User.list(
+                          self.apiclient,
+                          account=self.account_1A.name,
+                          domainid=self.account_1A.domainid
+                          )[0]
+       
+        user_1A_key = User.registerUserKeys(
+                        self.apiclient,
+                        self.user_1A.id
+                      )  
+        self.user_1A_apikey = user_1A_key.apikey
+        self.user_1A_secretkey = user_1A_key.secretkey
+        
+                         
+        self.user_1B = User.list(
+                          self.apiclient,
+                          account=self.account_1B.name,
+                          domainid=self.account_1B.domainid
+                          )[0]
+       
+        user_1B_key = User.registerUserKeys(
+                        self.apiclient,
+                        self.user_1B.id
+                      )  
+       
+        self.user_1B_apikey = user_1B_key.apikey
+        self.user_1B_secretkey = user_1B_key.secretkey                    
+
+ 
+        self.user_2A = User.list(
+                          self.apiclient,
+                          account=self.account_2A.name,
+                          domainid=self.account_2A.domainid
+                          )[0]
+       
+        user_2A_key = User.registerUserKeys(
+                        self.apiclient,
+                        self.user_2A.id
+                      )  
+        self.user_2A_apikey = user_2A_key.apikey
+        self.user_2A_secretkey = user_2A_key.secretkey
+                
+        # create service offering
+        self.service_offering = ServiceOffering.create(
+                                self.apiclient,
+                                self.services["service_offering"]["small"]
+                                )
+        
+        self.zone = get_zone(self.apiclient, self.services)
+        self.services['mode'] = self.zone.networktype
+        self.template = get_template(self.apiclient, self.zone.id, self.services["ostype"])
+
+        # deploy 3 VMs for three accounts
+        self.virtual_machine_1A = VirtualMachine.create(
+            self.apiclient,
+            self.services["virtual_machine1A"],
+            accountid=self.account_1A.name,
+            zoneid=self.zone.id,
+            domainid=self.account_1A.domainid,
+            serviceofferingid=self.service_offering.id,
+            templateid=self.template.id
+        )  
+        
+        self.virtual_machine_1B = VirtualMachine.create(
+            self.apiclient,
+            self.services["virtual_machine1B"],
+            accountid=self.account_1B.name,
+            zoneid=self.zone.id,
+            domainid=self.account_1B.domainid,
+            serviceofferingid=self.service_offering.id,
+            templateid=self.template.id
+        )  
+        
+        self.virtual_machine_2A = VirtualMachine.create(
+            self.apiclient,
+            self.services["virtual_machine2A"],
+            accountid=self.account_2A.name,
+            zoneid=self.zone.id,
+            domainid=self.account_2A.domainid,
+            serviceofferingid=self.service_offering.id,
+            templateid=self.template.id
+        )   
+        
+        self.srv_desk_grp = AclGroup.create(
+            self.apiclient, 
+            self.services["service_desk_iam_grp"]
+        )                             
+ 
+        self.vm_read_policy = AclPolicy.create(
+            self.apiclient, 
+            self.services["vm_readonly_iam_policy"]
+        )
+        
+        vm_grant_policy_params = {}
+        vm_grant_policy_params['name'] = "policyGrantVirtualMachine" + self.virtual_machine_1A.id
+        vm_grant_policy_params['description'] = "Policy to grant permission to VirtualMachine " + self.virtual_machine_1A.id
+        self.vm_grant_policy = AclPolicy.create(
+            self.apiclient, 
+            vm_grant_policy_params
+        )   
+        
+        self._cleanup = [
+                        self.account_1A,
+                        self.account_1B,
+                        self.domain_1,
+                        self.account_2A,
+                        self.domain_2,
+                        self.service_offering,
+                        self.vm_read_policy,
+                        self.srv_desk_grp,
+                        self.vm_grant_policy
+                        ]
+
+    @classmethod
+    def tearDownClass(self):
+        self.apiclient = super(TestVMIAM, self).getClsTestClient().getApiClient()
+        cleanup_resources(self.apiclient, self._cleanup)
+        return
+
+    def setUp(self):
+        self.apiclient = self.testClient.getApiClient()
+        self.dbclient = self.testClient.getDbConnection()
+        self.cleanup = []
+
+    def tearDown(self):
+        # restore back default apikey and secretkey
+        self.apiclient.connection.apiKey = self.default_apikey
+        self.apiclient.connection.secretKey = self.default_secretkey
+        cleanup_resources(self.apiclient, self.cleanup)
+        return
+
+    
+    @attr(tags = ["devcloud", "advanced", "advancedns", "smoke", "basic", "sg"])
+    def test_01_list_own_vm(self):
+        #  listVM command should return owne's VM
+
+        self.debug("Listing VM for account: %s" % self.account_1A.name)
+
+        self.apiclient.connection.apiKey = self.user_1A_apikey
+        self.apiclient.connection.secretKey = self.user_1A_secretkey
+        list_vm_response = list_virtual_machines(
+                                            self.apiclient
+                                            )
+        self.assertEqual(
+                            isinstance(list_vm_response, list),
+                            True,
+                            "Check list response returns a valid list"
+                        )
+        self.assertNotEqual(
+                            len(list_vm_response),
+                            0,
+                            "Check VM available in List Virtual Machines"
+                        )
+
+        self.assertEqual(
+            list_vm_response[0].name,
+            self.virtual_machine_1A.name,
+            "Virtual Machine names do not match"
+        )
+
+        self.debug("Listing VM for account: %s" % self.account_1B.id)
+        self.apiclient.connection.apiKey = self.user_1B_apikey
+        self.apiclient.connection.secretKey = self.user_1B_secretkey
+        list_vm_response = list_virtual_machines(
+                                            self.apiclient
+                                            )
+        self.assertEqual(
+                            isinstance(list_vm_response, list),
+                            True,
+                            "Check list response returns a valid list"
+                        )
+        self.assertNotEqual(
+                            len(list_vm_response),
+                            0,
+                            "Check VM available in List Virtual Machines"
+                        )
+
+        self.assertEqual(
+            list_vm_response[0].name,
+            self.virtual_machine_1B.name,
+            "Virtual Machine names do not match"
+        )
+        
+        self.debug("Listing VM for account: %s" % self.account_2A.id)
+
+        self.apiclient.connection.apiKey = self.user_2A_apikey
+        self.apiclient.connection.secretKey = self.user_2A_secretkey
+        list_vm_response = list_virtual_machines(
+                                            self.apiclient
+                                            )
+        self.assertEqual(
+                            isinstance(list_vm_response, list),
+                            True,
+                            "Check list response returns a valid list"
+                        )
+        self.assertNotEqual(
+                            len(list_vm_response),
+                            0,
+                            "Check VM available in List Virtual Machines"
+                        )
+
+        self.assertEqual(
+            list_vm_response[0].name,
+            self.virtual_machine_2A.name,
+            "Virtual Machine names do not match"
+        )
+                
+        return
+
+        
+    @attr(tags = ["devcloud", "advanced", "advancedns", "smoke", "basic", "sg"])
+    def test_02_grant_domain_vm(self):
+ 
+        # Validate the following
+        # 1. Grant domain2 VM access to account_1B
+        # 2. listVM command should return account_1B and domain_2 VMs.
+
+        self.debug("Granting Domain %s VM read only access to account: %s" % (self.domain_2.name, self.account_1B.name))
+        
+        self.srv_desk_grp.addAccount(self.apiclient, [self.account_1B.id])
+        domain_permission = {}
+        domain_permission['action'] = "listVirtualMachines"
+        domain_permission['entitytype'] = "VirtualMachine"
+        domain_permission['scope'] = "DOMAIN"
+        domain_permission['scopeid'] = self.domain_2.id
+        self.vm_read_policy.addPermission(self.apiclient, domain_permission)
+        
+        self.debug("Listing VM for account: %s" % self.account_1B.id)
+        self.apiclient.connection.apiKey = self.user_1B_apikey
+        self.apiclient.connection.secretKey = self.user_1B_secretkey
+        list_vm_response = list_virtual_machines(
+                                            self.apiclient
+                                            )
+        self.assertEqual(
+                            isinstance(list_vm_response, list),
+                            True,
+                            "Check list response returns a valid list"
+                        )
+        self.assertNotEqual(
+                            len(list_vm_response),
+                            2,
+                            "Check VM available in List Virtual Machines"
+                        )
+
+        list_vm_names = [list_vm_response[0].name, list_vm_response[1].name]
+        
+        self.assertEqual( self.virtual_machine_1B.name in list_vm_names,
+                          True,
+                          "Accessible Virtual Machine names do not match"
+                          )
+        
+        self.assertEqual( self.virtual_machine_2A.name in list_vm_names,
+                          True,
+                          "Accessible Virtual Machine names do not match"
+                          )        
+        
+        return
+
+
+    @attr(tags = ["devcloud", "advanced", "advancedns", "smoke", "basic", "sg"])
+    def test_03_grant_account_vm(self):
+ 
+        # Validate the following
+        # 1. Grant account_1A VM access to account_1B
+        # 2. listVM command should return account_1A and account_1B VMs.
+
+        self.debug("Granting Account %s VM read only access to account: %s" % (self.account_1A.name, self.account_1B.name))
+        
+        account_permission = {}
+        account_permission['action'] = "listVirtualMachines"
+        account_permission['entitytype'] = "VirtualMachine"
+        account_permission['scope'] = "ACCOUNT"
+        account_permission['scopeid'] = self.account_1A.id
+        self.vm_read_policy.addPermission(self.apiclient, account_permission)
+        
+        self.debug("Listing VM for account: %s" % self.account_1B.id)
+        self.apiclient.connection.apiKey = self.user_1B_apikey
+        self.apiclient.connection.secretKey = self.user_1B_secretkey
+        list_vm_response = list_virtual_machines(
+                                            self.apiclient
+                                            )
+        self.assertEqual(
+                            isinstance(list_vm_response, list),
+                            True,
+                            "Check list response returns a valid list"
+                        )
+        self.assertNotEqual(
+                            len(list_vm_response),
+                            3,
+                            "Check VM available in List Virtual Machines"
+                        )
+
+        list_vm_names = [list_vm_response[0].name, list_vm_response[1].name, list_vm_response[2].name]
+        
+        self.assertEqual( self.virtual_machine_1B.name in list_vm_names,
+                          True,
+                          "Accessible Virtual Machine names do not match"
+                          )
+        
+        self.assertEqual( self.virtual_machine_1A.name in list_vm_names,
+                          True,
+                          "Accessible Virtual Machine names do not match"
+                          )    
+                
+        self.assertEqual( self.virtual_machine_2A.name in list_vm_names,
+                          True,
+                          "Accessible Virtual Machine names do not match"
+                          )        
+        
+        return
+
+
+    @attr(tags = ["devcloud", "advanced", "advancedns", "smoke", "basic", "sg"])
+    def test_04_revoke_account_vm(self):
+ 
+        # Validate the following
+        # 1. Revoke account_1A VM access from account_1B
+        # 2. listVM command should not return account_1A VMs.
+
+        self.debug("Revoking Account %s VM read only access from account: %s" % (self.account_1A.name, self.account_1B.name))
+        
+        account_permission = {}
+        account_permission['action'] = "listVirtualMachines"
+        account_permission['entitytype'] = "VirtualMachine"
+        account_permission['scope'] = "ACCOUNT"
+        account_permission['scopeid'] = self.account_1A.id
+        self.vm_read_policy.removePermission(self.apiclient, account_permission)
+        
+        self.debug("Listing VM for account: %s" % self.account_1B.id)
+        self.apiclient.connection.apiKey = self.user_1B_apikey
+        self.apiclient.connection.secretKey = self.user_1B_secretkey
+        list_vm_response = list_virtual_machines(
+                                            self.apiclient
+                                            )
+        self.assertEqual(
+                            isinstance(list_vm_response, list),
+                            True,
+                            "Check list response returns a valid list"
+                        )
+        self.assertNotEqual(
+                            len(list_vm_response),
+                            2,
+                            "Check VM available in List Virtual Machines"
+                        )
+
+        list_vm_names = [list_vm_response[0].name, list_vm_response[1].name]
+        
+       
+        self.assertEqual( self.virtual_machine_1A.name in list_vm_names,
+                          False,
+                          "Accessible Virtual Machine names do not match"
+                          )    
+        return
+    
+    
+    @attr(tags = ["devcloud", "advanced", "advancedns", "smoke", "basic", "sg"])
+    def test_05_revoke_domain_vm(self):
+ 
+        # Validate the following
+        # 1. Revoke account_1A VM access from account_1B
+        # 2. listVM command should not return account_1A VMs.
+
+        self.debug("Revoking Domain %s VM read only access from account: %s" % (self.domain_1.name, self.account_1B.name))
+        
+        domain_permission = {}
+        domain_permission['action'] = "listVirtualMachines"
+        domain_permission['entitytype'] = "VirtualMachine"
+        domain_permission['scope'] = "DOMAIN"
+        domain_permission['scopeid'] = self.domain_2.id
+        self.vm_read_policy.removePermission(self.apiclient, domain_permission)
+        
+        self.debug("Listing VM for account: %s" % self.account_1B.id)
+        self.apiclient.connection.apiKey = self.user_1B_apikey
+        self.apiclient.connection.secretKey = self.user_1B_secretkey
+        list_vm_response = list_virtual_machines(
+                                            self.apiclient
+                                            )
+        self.assertEqual(
+                            isinstance(list_vm_response, list),
+                            True,
+                            "Check list response returns a valid list"
+                        )
+        self.assertNotEqual(
+                            len(list_vm_response),
+                            1,
+                            "Check VM available in List Virtual Machines"
+                        )
+
+        self.assertEqual(
+            list_vm_response[0].name,
+            self.virtual_machine_2A.name,
+            "Virtual Machine names do not match"
+        )
+         
+        return    
+    
+    @attr(tags = ["devcloud", "advanced", "advancedns", "smoke", "basic", "sg"])
+    def test_06_grant_resource_vm(self):
+ 
+        # Validate the following
+        # 1. Grant a particular vm access to account_1B
+        # 2. listVM command should return account_1B VMs and granted VM.
+
+        self.debug("Granting VM %s read only access to account: %s" % (self.virtual_machine_1A.name, self.account_1B.name))
+        
+        res_permission = {}
+        res_permission['action'] = "listVirtualMachines"
+        res_permission['entitytype'] = "VirtualMachine"
+        res_permission['scope'] = "RESOURCE"
+        res_permission['scopeid'] = self.virtual_machine_1A.id
+        self.vm_read_policy.addPermission(self.apiclient, res_permission)
+        
+        self.debug("Listing VM for account: %s" % self.account_1B.id)
+        self.apiclient.connection.apiKey = self.user_1B_apikey
+        self.apiclient.connection.secretKey = self.user_1B_secretkey
+        list_vm_response = list_virtual_machines(
+                                            self.apiclient
+                                            )
+        self.assertEqual(
+                            isinstance(list_vm_response, list),
+                            True,
+                            "Check list response returns a valid list"
+                        )
+        self.assertNotEqual(
+                            len(list_vm_response),
+                            2,
+                            "Check VM available in List Virtual Machines"
+                        )
+
+        list_vm_names = [list_vm_response[0].name, list_vm_response[1].name]
+        
+        self.assertEqual( self.virtual_machine_1B.name in list_vm_names,
+                          True,
+                          "Accessible Virtual Machine names do not match"
+                          )
+        
+        self.assertEqual( self.virtual_machine_1A.name in list_vm_names,
+                          True,
+                          "Accessible Virtual Machine names do not match"
+                          )    
+                
+        return    
+    
+    @attr(tags = ["devcloud", "advanced", "advancedns", "smoke", "basic", "sg"])
+    def test_07_revoke_resource_vm(self):
+ 
+        # Validate the following
+        # 1. Grant a particular vm access to account_1B
+        # 2. listVM command should return account_1B VMs and granted VM.
+
+        self.debug("Revoking VM %s read only access from account: %s" % (self.virtual_machine_1A.name, self.account_1B.name))
+        
+        res_permission = {}
+        res_permission['action'] = "listVirtualMachines"
+        res_permission['entitytype'] = "VirtualMachine"
+        res_permission['scope'] = "RESOURCE"
+        res_permission['scopeid'] = self.virtual_machine_1A.id
+        self.vm_read_policy.removePermission(self.apiclient, res_permission)
+        
+        self.debug("Listing VM for account: %s" % self.account_1B.id)
+        self.apiclient.connection.apiKey = self.user_1B_apikey
+        self.apiclient.connection.secretKey = self.user_1B_secretkey
+        list_vm_response = list_virtual_machines(
+                                            self.apiclient
+                                            )
+        self.assertEqual(
+                            isinstance(list_vm_response, list),
+                            True,
+                            "Check list response returns a valid list"
+                        )
+        self.assertNotEqual(
+                            len(list_vm_response),
+                            1,
+                            "Check VM available in List Virtual Machines"
+                        )
+
+        self.assertEqual(
+            list_vm_response[0].name,
+            self.virtual_machine_2A.name,
+            "Virtual Machine names do not match"
+        )
+        
+        return      
+    
+    
+    @attr(tags = ["devcloud", "advanced", "advancedns", "smoke", "basic", "sg"])
+    def test_08_policy_attach_account(self):
+ 
+        # Validate the following
+        # 1. Grant a particular vm access to account_1B by directly attaching policy to account
+        # 2. listVM command should return account_1B VMs and granted VM.
+
+        self.debug("Granting VM %s read only access to account: %s by attaching policy to account" % (self.virtual_machine_1A.name, self.account_1B.name))
+        
+        res_permission = {}
+        res_permission['action'] = "listVirtualMachines"
+        res_permission['entitytype'] = "VirtualMachine"
+        res_permission['scope'] = "RESOURCE"
+        res_permission['scopeid'] = self.virtual_machine_1A.id
+        self.vm_grant_policy.addPermission(self.apiclient, res_permission)
+        self.vm_grant_policy.attachAccount(self.apiclient, [self.account_1B.id])
+        
+        self.debug("Listing VM for account: %s" % self.account_1B.id)
+        self.apiclient.connection.apiKey = self.user_1B_apikey
+        self.apiclient.connection.secretKey = self.user_1B_secretkey
+        list_vm_response = list_virtual_machines(
+                                            self.apiclient
+                                            )
+        self.assertEqual(
+                            isinstance(list_vm_response, list),
+                            True,
+                            "Check list response returns a valid list"
+                        )
+        self.assertNotEqual(
+                            len(list_vm_response),
+                            2,
+                            "Check VM available in List Virtual Machines"
+                        )
+
+        list_vm_names = [list_vm_response[0].name, list_vm_response[1].name]
+        
+        self.assertEqual( self.virtual_machine_1B.name in list_vm_names,
+                          True,
+                          "Accessible Virtual Machine names do not match"
+                          )
+        
+        self.assertEqual( self.virtual_machine_1A.name in list_vm_names,
+                          True,
+                          "Accessible Virtual Machine names do not match"
+                          )    
+                
+        return     
+    
+    @attr(tags = ["devcloud", "advanced", "advancedns", "smoke", "basic", "sg"])
+    def test_09_policy_detach_account(self):
+ 
+        # Validate the following
+        # 1. Revoking a particular vm access from account_1B by detaching policy from account
+        # 2. listVM command should return account_1B VMs.
+
+        self.debug("Revoking VM %s read only access from account: %s by attaching policy to account" % (self.virtual_machine_1A.name, self.account_1B.name))
+        
+        self.vm_grant_policy.detachAccount(self.apiclient, [self.account_1B.id])
+        
+        self.debug("Listing VM for account: %s" % self.account_1B.id)
+        self.apiclient.connection.apiKey = self.user_1B_apikey
+        self.apiclient.connection.secretKey = self.user_1B_secretkey
+        list_vm_response = list_virtual_machines(
+                                            self.apiclient
+                                            )
+        self.assertEqual(
+                            isinstance(list_vm_response, list),
+                            True,
+                            "Check list response returns a valid list"
+                        )
+        self.assertNotEqual(
+                            len(list_vm_response),
+                            1,
+                            "Check VM available in List Virtual Machines"
+                        )
+
+        self.assertEqual(
+            list_vm_response[0].name,
+            self.virtual_machine_2A.name,
+            "Virtual Machine names do not match"
+        )
+        
+        return         
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/b78cb228/tools/marvin/marvin/integration/lib/base.py
----------------------------------------------------------------------
diff --git a/tools/marvin/marvin/integration/lib/base.py b/tools/marvin/marvin/integration/lib/base.py
index aa23029..0058834 100755
--- a/tools/marvin/marvin/integration/lib/base.py
+++ b/tools/marvin/marvin/integration/lib/base.py
@@ -3623,3 +3623,131 @@ class Resources:
         cmd = updateResourceCount.updateResourceCountCmd()
         [setattr(cmd, k, v) for k, v in kwargs.items()]
         return(apiclient.updateResourceCount(cmd))
+    
+class AclGroup:
+    def __init__(self, items):
+        self.__dict__.update(items)
+
+    @classmethod
+    def create(cls, apiclient, iam_grp, account=None, domainid=None):
+        cmd = createAclGroup.createAclGroupCmd()
+        cmd.name = iam_grp['name']
+        cmd.description = iam_grp['description']
+        if account:
+            cmd.account = account
+        if domainid:
+            cmd.domainid = domainid
+        return AclGroup(apiclient.createAclGroup(cmd).__dict__)
+
+    def update(self, apiclient):
+        pass
+
+    def delete(self, apiclient):
+        cmd = deleteAclGroup.deleteAclGroupCmd()
+        cmd.id = self.id
+        return apiclient.deleteAclGroup(cmd)
+
+    @classmethod
+    def list(cls, apiclient, **kwargs):
+        cmd = listAclGroups.listAclGroupsCmd()
+        [setattr(cmd, k, v) for k, v in kwargs.items()]
+        return apiclient.listAclGroupsCmd(cmd)  
+    
+    def addAccount(self, apiclient, accts):
+        """Add accounts to acl group"""
+        cmd = addAccountToAclGroup.addAccountToAclGroupCmd()
+        cmd.id = self.id
+        cmd.accounts = [str(acct.id) for acct in accts]
+        apiclient.addAccountToAclGroup(cmd)
+        return  
+
+    def removeAccount(self, apiclient, accts):
+        """ Remove accounts from acl group"""
+        cmd = removeAccountFromAclGroup.removeAccountFromAclGroupCmd()
+        cmd.id = self.id
+        cmd.accounts = [str(acct.id) for acct in accts]
+        apiclient.removeAccountFromAclGroup(cmd)
+        return  
+    
+    def attachPolicy(self, apiclient, policies):
+        """Add policies to acl group"""
+        cmd = attachAclPolicyToAclGroup.attachAclPolicyToAclGroupCmd()
+        cmd.id = self.id
+        cmd.policies = [str(policy.id) for policy in policies]
+        apiclient.attachAclPolicyToAclGroup(cmd)
+        return   
+    
+    def detachPolicy(self, apiclient, policies):
+        """Remove policies from acl group"""
+        cmd = removeAclPolicyFromAclGroup.removeAclPolicyFromAclGroupCmd()
+        cmd.id = self.id
+        cmd.policies = [str(policy.id) for policy in policies]
+        apiclient.removeAclPolicyFromAclGroup(cmd)
+        return         
+    
+class AclPolicy:
+    def __init__(self, items):
+        self.__dict__.update(items)
+
+    @classmethod
+    def create(cls, apiclient, iam_policy, account=None, domainid=None):
+        cmd = createAclPolicy.createAclPolicyCmd()
+        cmd.name = iam_policy['name']
+        cmd.description = iam_policy['description']
+        if account:
+            cmd.account = account
+        if domainid:
+            cmd.domainid = domainid
+        return AclGroup(apiclient.createAclPolicy(cmd).__dict__)
+
+    def update(self, apiclient):
+        pass
+
+    def delete(self, apiclient):
+        cmd = deleteAclPolicy.deleteAclPolicyCmd()
+        cmd.id = self.id
+        return apiclient.deleteAclPolicy(cmd)
+
+    @classmethod
+    def list(cls, apiclient, **kwargs):
+        cmd = listAclPolicies.listAclPoliciesCmd()
+        [setattr(cmd, k, v) for k, v in kwargs.items()]
+        return apiclient.listAclPoliciesCmd(cmd)  
+
+    def addPermission(self, apiclient, permission):
+        """Add permission to acl policy"""
+        cmd = addAclPermissionToAclPolicy.addAclPermissionToAclPolicyCmd()
+        cmd.id = self.id
+        cmd.action = permission['action']
+        cmd.entitytype = permission['entitytype']
+        cmd.scope = permission['scope']
+        cmd.scopeid = permission['scopeid']
+        apiclient.addAclPermissionToAclPolicy(cmd)
+        return       
+
+    def removePermission(self, apiclient, permission):
+        """Remove permission from acl policy"""
+        cmd = removeAclPermissionFromAclPolicy.removeAclPermissionFromAclPolicyCmd()
+        cmd.id = self.id
+        cmd.action = permission['action']
+        cmd.entitytype = permission['entitytype']
+        cmd.scope = permission['scope']
+        cmd.scopeid = permission['scopeid']
+        apiclient.addAclPermissionToAclPolicy(cmd)
+        return  
+    
+    def attachAccount(self, apiclient, accts):
+        """Attach policy to accounts"""
+        cmd = attachAclPolicyToAccount.attachAclPolicyToAccountCmd()
+        cmd.id = self.id
+        cmd.accounts = [str(acct.id) for acct in accts]
+        apiclient.attachAclPolicyToAccount(cmd)
+        return  
+    
+    def detachAccount(self, apiclient, accts):
+        """Detach policy from accounts"""
+        cmd = removeAclPolicyFromAccount.removeAclPolicyFromAccountCmd()
+        cmd.id = self.id
+        cmd.accounts = [str(acct.id) for acct in accts]
+        apiclient.removeAclPolicyFromAccount(cmd)
+        return           
\ No newline at end of file