You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@cloudstack.apache.org by re...@apache.org on 2015/12/03 20:11:04 UTC

[1/5] git commit: updated refs/heads/4.6 to 9a21873

Repository: cloudstack
Updated Branches:
  refs/heads/4.6 519ce868a -> 9a21873c4


http://git-wip-us.apache.org/repos/asf/cloudstack/blob/c76d3171/server/test/org/apache/cloudstack/affinity/AffinityGroupServiceImplTest.java
----------------------------------------------------------------------
diff --git a/server/test/org/apache/cloudstack/affinity/AffinityGroupServiceImplTest.java b/server/test/org/apache/cloudstack/affinity/AffinityGroupServiceImplTest.java
new file mode 100644
index 0000000..4484247
--- /dev/null
+++ b/server/test/org/apache/cloudstack/affinity/AffinityGroupServiceImplTest.java
@@ -0,0 +1,358 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements.  See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership.  The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License.  You may obtain a copy of the License at
+//
+//   http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied.  See the License for the
+// specific language governing permissions and limitations
+// under the License.
+package org.apache.cloudstack.affinity;
+
+import static org.junit.Assert.assertNotNull;
+import static org.mockito.Matchers.anyBoolean;
+import static org.mockito.Matchers.anyLong;
+import static org.mockito.Matchers.anyObject;
+import static org.mockito.Matchers.anyString;
+import static org.mockito.Matchers.eq;
+import static org.mockito.Mockito.when;
+
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.UUID;
+
+import javax.inject.Inject;
+import javax.naming.ConfigurationException;
+
+import com.cloud.utils.db.EntityManager;
+import com.cloud.event.ActionEventUtils;
+import com.cloud.user.User;
+
+import org.apache.cloudstack.affinity.dao.AffinityGroupDao;
+import org.apache.cloudstack.affinity.dao.AffinityGroupVMMapDao;
+import org.apache.cloudstack.test.utils.SpringUtils;
+import org.junit.After;
+import org.junit.Before;
+import org.junit.BeforeClass;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Matchers;
+import org.mockito.Mockito;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.ComponentScan;
+import org.springframework.context.annotation.ComponentScan.Filter;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.context.annotation.FilterType;
+import org.springframework.core.type.classreading.MetadataReader;
+import org.springframework.core.type.classreading.MetadataReaderFactory;
+import org.springframework.core.type.filter.TypeFilter;
+import org.springframework.test.context.ContextConfiguration;
+import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
+import org.springframework.test.context.support.AnnotationConfigContextLoader;
+import org.apache.cloudstack.acl.ControlledEntity;
+import org.apache.cloudstack.affinity.dao.AffinityGroupDomainMapDao;
+import org.apache.cloudstack.api.command.user.affinitygroup.CreateAffinityGroupCmd;
+import org.apache.cloudstack.context.CallContext;
+import org.apache.cloudstack.framework.config.dao.ConfigurationDao;
+import org.apache.cloudstack.framework.messagebus.MessageBus;
+
+import com.cloud.dc.dao.DedicatedResourceDao;
+import com.cloud.domain.dao.DomainDao;
+import com.cloud.event.EventVO;
+import com.cloud.event.dao.EventDao;
+import com.cloud.exception.InvalidParameterValueException;
+import com.cloud.exception.ResourceInUseException;
+import com.cloud.hypervisor.Hypervisor.HypervisorType;
+import com.cloud.user.Account;
+import com.cloud.user.AccountManager;
+import com.cloud.user.AccountService;
+import com.cloud.user.AccountVO;
+import com.cloud.user.DomainManager;
+import com.cloud.user.UserVO;
+import com.cloud.user.dao.AccountDao;
+import com.cloud.user.dao.UserDao;
+import com.cloud.utils.component.ComponentContext;
+import com.cloud.vm.UserVmVO;
+import com.cloud.vm.VirtualMachine;
+import com.cloud.vm.dao.UserVmDao;
+import com.cloud.projects.dao.ProjectDao;
+
+@RunWith(SpringJUnit4ClassRunner.class)
+@ContextConfiguration(loader = AnnotationConfigContextLoader.class)
+public class AffinityGroupServiceImplTest {
+
+    @Inject
+    AffinityGroupServiceImpl _affinityService;
+
+    @Inject
+    AccountManager _acctMgr;
+
+    @Inject
+    AffinityGroupProcessor _processor;
+
+    @Inject
+    AffinityGroupDao _groupDao;
+
+    @Inject
+    UserVmDao _vmDao;
+
+    @Inject
+    AffinityGroupVMMapDao _affinityGroupVMMapDao;
+
+    @Inject
+    AffinityGroupDao _affinityGroupDao;
+
+    @Inject
+    ActionEventUtils _eventUtils;
+
+    @Inject
+    AccountDao _accountDao;
+
+    @Inject
+    ProjectDao _projectDao;
+
+    @Inject
+    EventDao _eventDao;
+
+    @Inject
+    DedicatedResourceDao _dedicatedDao;
+
+    private static final long DOMAIN_ID = 5L;
+    private static final long PROJECT_ID = 10L;
+    private static final String ACCOUNT_NAME = "user";
+    private static final String AFFINITY_GROUP_NAME = "group1";
+
+    private AccountVO acct;
+
+    @BeforeClass
+    public static void setUpClass() throws ConfigurationException {
+    }
+
+    @Before
+    public void setUp() {
+        ComponentContext.initComponentsLifeCycle();
+        acct = new AccountVO(200L);
+        acct.setType(Account.ACCOUNT_TYPE_NORMAL);
+        acct.setAccountName(ACCOUNT_NAME);
+        acct.setDomainId(DOMAIN_ID);
+
+        UserVO user = new UserVO(1, "testuser", "password", "firstname", "lastName", "email", "timezone", UUID.randomUUID().toString(), User.Source.UNKNOWN);
+
+        CallContext.register(user, acct);
+
+        when(_processor.getType()).thenReturn("mock");
+        when(_accountDao.findByIdIncludingRemoved(0L)).thenReturn(acct);
+
+        List<AffinityGroupProcessor> affinityProcessors = new ArrayList<AffinityGroupProcessor>();
+        affinityProcessors.add(_processor);
+        _affinityService.setAffinityGroupProcessors(affinityProcessors);
+
+        AffinityGroupVO group = new AffinityGroupVO(AFFINITY_GROUP_NAME, "mock", "mock group", DOMAIN_ID, 200L, ControlledEntity.ACLType.Account);
+        Mockito.when(_affinityGroupDao.persist(Matchers.any(AffinityGroupVO.class))).thenReturn(group);
+        Mockito.when(_affinityGroupDao.findById(Matchers.anyLong())).thenReturn(group);
+        Mockito.when(_affinityGroupDao.findByAccountAndName(Matchers.anyLong(), Matchers.anyString())).thenReturn(group);
+        Mockito.when(_affinityGroupDao.lockRow(Matchers.anyLong(), anyBoolean())).thenReturn(group);
+        Mockito.when(_affinityGroupDao.expunge(Matchers.anyLong())).thenReturn(true);
+        Mockito.when(_eventDao.persist(Matchers.any(EventVO.class))).thenReturn(new EventVO());
+    }
+
+    @After
+    public void tearDown() {
+        CallContext.unregister();
+    }
+
+    @Test
+    public void createAffinityGroupFromCmdTest() {
+        when(_acctMgr.finalizeOwner((Account)anyObject(), anyString(), anyLong(), anyLong())).thenReturn(acct);
+        when(_groupDao.isNameInUse(anyLong(), anyLong(), eq(AFFINITY_GROUP_NAME))).thenReturn(false);
+        CreateAffinityGroupCmd mockCreateAffinityGroupCmd = Mockito.mock(CreateAffinityGroupCmd.class);
+        when(mockCreateAffinityGroupCmd.getProjectId()).thenReturn(PROJECT_ID);
+        when(mockCreateAffinityGroupCmd.getAffinityGroupName()).thenReturn(AFFINITY_GROUP_NAME);
+        when(mockCreateAffinityGroupCmd.getAffinityGroupType()).thenReturn("mock");
+        when(mockCreateAffinityGroupCmd.getDescription()).thenReturn("affinity group one");
+        AffinityGroup group = _affinityService.createAffinityGroup(mockCreateAffinityGroupCmd);
+        assertNotNull("Affinity group 'group1' of type 'mock' failed to create ", group);
+    }
+
+    @Test
+    public void createAffinityGroupTest() {
+        when(_acctMgr.finalizeOwner((Account)anyObject(), anyString(), anyLong(), anyLong())).thenReturn(acct);
+        when(_groupDao.isNameInUse(anyLong(), anyLong(), eq(AFFINITY_GROUP_NAME))).thenReturn(false);
+        AffinityGroup group = _affinityService.createAffinityGroup(ACCOUNT_NAME, null, DOMAIN_ID, AFFINITY_GROUP_NAME, "mock", "affinity group one");
+        assertNotNull("Affinity group 'group1' of type 'mock' failed to create ", group);
+
+    }
+
+    @Test
+    public void shouldDeleteDomainLevelAffinityGroup() {
+        AffinityGroupVO mockGroup = Mockito.mock(AffinityGroupVO.class);
+        when(mockGroup.getId()).thenReturn(2L);
+        when(_affinityGroupDao.findById(Matchers.anyLong())).thenReturn(mockGroup);
+        _affinityService.deleteAffinityGroup(2L, null, null, DOMAIN_ID, null);
+        Mockito.verify(_affinityGroupDao).expunge(2L);
+    }
+
+    @Test
+    public void shouldDeleteAffintyGroupById() {
+        AffinityGroupVO mockGroup = Mockito.mock(AffinityGroupVO.class);
+        when(mockGroup.getId()).thenReturn(1L);
+        when(_affinityGroupDao.findById(Matchers.anyLong())).thenReturn(mockGroup);
+        _affinityService.deleteAffinityGroup(1L, ACCOUNT_NAME, null, DOMAIN_ID, null);
+        Mockito.verify(_affinityGroupDao).expunge(1L);
+    }
+
+    @Test(expected = InvalidParameterValueException.class)
+    public void invalidAffinityTypeTest() {
+        when(_acctMgr.finalizeOwner((Account)anyObject(), anyString(), anyLong(), anyLong())).thenReturn(acct);
+        _affinityService.createAffinityGroup(ACCOUNT_NAME, null, DOMAIN_ID, AFFINITY_GROUP_NAME, "invalid", "affinity group one");
+
+    }
+
+    @Test(expected = InvalidParameterValueException.class)
+    public void uniqueAffinityNameTest() {
+        when(_acctMgr.finalizeOwner((Account)anyObject(), anyString(), anyLong(), anyLong())).thenReturn(acct);
+        when(_groupDao.isNameInUse(anyLong(), anyLong(), eq(AFFINITY_GROUP_NAME))).thenReturn(true);
+        _affinityService.createAffinityGroup(ACCOUNT_NAME, null, DOMAIN_ID, AFFINITY_GROUP_NAME, "mock", "affinity group two");
+    }
+
+    @Test(expected = InvalidParameterValueException.class)
+    public void deleteAffinityGroupInvalidIdTest() throws ResourceInUseException {
+        when(_acctMgr.finalizeOwner((Account)anyObject(), anyString(), anyLong(), anyLong())).thenReturn(acct);
+        when(_groupDao.findById(20L)).thenReturn(null);
+        _affinityService.deleteAffinityGroup(20L, ACCOUNT_NAME, null, DOMAIN_ID, AFFINITY_GROUP_NAME);
+    }
+
+    @Test(expected = InvalidParameterValueException.class)
+    public void deleteAffinityGroupInvalidIdName() throws ResourceInUseException {
+        when(_acctMgr.finalizeOwner((Account)anyObject(), anyString(), anyLong(), anyLong())).thenReturn(acct);
+        when(_acctMgr.finalyzeAccountId(ACCOUNT_NAME, DOMAIN_ID, null, true)).thenReturn(200L);
+        when(_groupDao.findByAccountAndName(200L, AFFINITY_GROUP_NAME)).thenReturn(null);
+        _affinityService.deleteAffinityGroup(null, ACCOUNT_NAME, null, DOMAIN_ID, AFFINITY_GROUP_NAME);
+    }
+
+    @Test(expected = InvalidParameterValueException.class)
+    public void deleteAffinityGroupNullIdName() throws ResourceInUseException {
+        when(_acctMgr.finalizeOwner((Account)anyObject(), anyString(), anyLong(), anyLong())).thenReturn(acct);
+        _affinityService.deleteAffinityGroup(null, ACCOUNT_NAME, null, DOMAIN_ID, null);
+    }
+
+    @Test(expected = InvalidParameterValueException.class)
+    public void updateAffinityGroupVMRunning() throws ResourceInUseException {
+        when(_acctMgr.finalizeOwner((Account)anyObject(), anyString(), anyLong(), anyLong())).thenReturn(acct);
+        UserVmVO vm = new UserVmVO(10L, "test", "test", 101L, HypervisorType.Any, 21L, false, false, DOMAIN_ID, 200L, 1, 5L, "", "test", 1L);
+        vm.setState(VirtualMachine.State.Running);
+        when(_vmDao.findById(10L)).thenReturn(vm);
+
+        List<Long> affinityGroupIds = new ArrayList<Long>();
+        affinityGroupIds.add(20L);
+
+        _affinityService.updateVMAffinityGroups(10L, affinityGroupIds);
+    }
+
+    @Configuration
+    @ComponentScan(basePackageClasses = {AffinityGroupServiceImpl.class, ActionEventUtils.class}, includeFilters = {@Filter(value = TestConfiguration.Library.class, type = FilterType.CUSTOM)}, useDefaultFilters = false)
+    public static class TestConfiguration extends SpringUtils.CloudStackTestConfiguration {
+
+        @Bean
+        public AccountDao accountDao() {
+            return Mockito.mock(AccountDao.class);
+        }
+
+        @Bean
+        public ProjectDao projectDao() {
+            return Mockito.mock(ProjectDao.class);
+        }
+
+        @Bean
+        public AccountService accountService() {
+            return Mockito.mock(AccountService.class);
+        }
+
+        @Bean
+        public AffinityGroupProcessor affinityGroupProcessor() {
+            return Mockito.mock(AffinityGroupProcessor.class);
+        }
+
+        @Bean
+        public AffinityGroupDao affinityGroupDao() {
+            return Mockito.mock(AffinityGroupDao.class);
+        }
+
+        @Bean
+        public AffinityGroupVMMapDao affinityGroupVMMapDao() {
+            return Mockito.mock(AffinityGroupVMMapDao.class);
+        }
+
+        @Bean
+        public DedicatedResourceDao dedicatedResourceDao() {
+            return Mockito.mock(DedicatedResourceDao.class);
+        }
+
+        @Bean
+        public AccountManager accountManager() {
+            return Mockito.mock(AccountManager.class);
+        }
+
+        @Bean
+        public DomainManager domainManager() {
+            return Mockito.mock(DomainManager.class);
+        }
+
+        @Bean
+        public EventDao eventDao() {
+            return Mockito.mock(EventDao.class);
+        }
+
+        @Bean
+        public UserVmDao userVMDao() {
+            return Mockito.mock(UserVmDao.class);
+        }
+
+        @Bean
+        public UserDao userDao() {
+            return Mockito.mock(UserDao.class);
+        }
+
+        @Bean
+        public AffinityGroupDomainMapDao affinityGroupDomainMapDao() {
+            return Mockito.mock(AffinityGroupDomainMapDao.class);
+        }
+
+        @Bean
+        public EntityManager entityManager() {
+            return Mockito.mock(EntityManager.class);
+        }
+
+        @Bean
+        public DomainDao domainDao() {
+            return Mockito.mock(DomainDao.class);
+        }
+
+        @Bean
+        public MessageBus messageBus() {
+            return Mockito.mock(MessageBus.class);
+        }
+
+        @Bean
+        public ConfigurationDao configDao() {
+            return Mockito.mock(ConfigurationDao.class);
+        }
+
+        public static class Library implements TypeFilter {
+
+            @Override
+            public boolean match(MetadataReader mdr, MetadataReaderFactory arg1) throws IOException {
+                ComponentScan cs = TestConfiguration.class.getAnnotation(ComponentScan.class);
+                return SpringUtils.includedInBasePackageClasses(mdr.getClassMetadata().getClassName(), cs);
+            }
+        }
+    }
+}

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/c76d3171/setup/db/db/schema-460to461.sql
----------------------------------------------------------------------
diff --git a/setup/db/db/schema-460to461.sql b/setup/db/db/schema-460to461.sql
index e42d0b2..4e07344 100644
--- a/setup/db/db/schema-460to461.sql
+++ b/setup/db/db/schema-460to461.sql
@@ -18,3 +18,35 @@
 --;
 -- Schema upgrade from 4.6.0 to 4.6.1;
 --;
+DROP VIEW IF EXISTS `cloud`.`affinity_group_view`;
+CREATE VIEW `affinity_group_view`
+	AS SELECT
+	   `affinity_group`.`id` AS `id`,
+	   `affinity_group`.`name` AS `name`,
+	   `affinity_group`.`type` AS `type`,
+	   `affinity_group`.`description` AS `description`,
+	   `affinity_group`.`uuid` AS `uuid`,
+	   `affinity_group`.`acl_type` AS `acl_type`,
+	   `account`.`id` AS `account_id`,
+	   `account`.`uuid` AS `account_uuid`,
+	   `account`.`account_name` AS `account_name`,
+	   `account`.`type` AS `account_type`,
+	   `domain`.`id` AS `domain_id`,
+	   `domain`.`uuid` AS `domain_uuid`,
+	   `domain`.`name` AS `domain_name`,
+	   `domain`.`path` AS `domain_path`,
+	   `projects`.`id` AS `project_id`,
+	   `projects`.`uuid` AS `project_uuid`,
+	   `projects`.`name` AS `project_name`,
+	   `vm_instance`.`id` AS `vm_id`,
+	   `vm_instance`.`uuid` AS `vm_uuid`,
+	   `vm_instance`.`name` AS `vm_name`,
+	   `vm_instance`.`state` AS `vm_state`,
+	   `user_vm`.`display_name` AS `vm_display_name`
+FROM `affinity_group`
+	JOIN `account` ON`affinity_group`.`account_id` = `account`.`id`
+	JOIN `domain` ON`affinity_group`.`domain_id` = `domain`.`id`
+	LEFT JOIN `projects` ON`projects`.`project_account_id` = `account`.`id`
+	LEFT JOIN `affinity_group_vm_map` ON`affinity_group`.`id` = `affinity_group_vm_map`.`affinity_group_id`
+	LEFT JOIN `vm_instance` ON`vm_instance`.`id` = `affinity_group_vm_map`.`instance_id`
+	LEFT JOIN `user_vm` ON`user_vm`.`id` = `vm_instance`.`id`;

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/c76d3171/test/integration/component/test_affinity_groups_projects.py
----------------------------------------------------------------------
diff --git a/test/integration/component/test_affinity_groups_projects.py b/test/integration/component/test_affinity_groups_projects.py
new file mode 100644
index 0000000..ffd10ef
--- /dev/null
+++ b/test/integration/component/test_affinity_groups_projects.py
@@ -0,0 +1,1083 @@
+#!/usr/bin/env python
+#  Licensed to the Apache Software Foundation (ASF) under one
+#  or more contributor license agreements.  See the NOTICE file
+#  distributed with this work for additional information
+#  regarding copyright ownership.  The ASF licenses this file
+#  to you under the Apache License, Version 2.0 (the
+#  "License"); you may not use this file except in compliance
+#  with the License.  You may obtain a copy of the License at
+# 
+#    http://www.apache.org/licenses/LICENSE-2.0
+# 
+#  Unless required by applicable law or agreed to in writing,
+#  software distributed under the License is distributed on an
+#  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+#  KIND, either express or implied.  See the License for the
+#  specific language governing permissions and limitations
+#  under the License.
+from marvin.cloudstackTestCase import cloudstackTestCase, unittest
+from marvin.cloudstackAPI import deleteAffinityGroup
+from marvin.lib.utils import (cleanup_resources,
+                        random_gen)
+from marvin.lib.base import (Account,
+                        Project,
+                        ServiceOffering,
+                        VirtualMachine,
+                        AffinityGroup,
+                        Domain)
+from marvin.lib.common import (get_zone,
+                         get_domain,
+                         get_template,
+                         list_hosts,
+                         list_virtual_machines,
+                         wait_for_cleanup)
+from nose.plugins.attrib import attr
+
+class Services:
+    """Test Account Services
+    """
+
+    def __init__(self):
+       self.services = {
+          "domain": {
+             "name": "NonRootDomain"
+          },
+          "domain_admin_account": {
+             "email": "newtest@test.com",
+             "firstname": "Test",
+             "lastname": "User",
+             "username": "doadmintest",
+             "password": "password"
+          },
+          "account": {
+             "email": "newtest@test.com",
+             "firstname": "Test",
+             "lastname": "User",
+             "username": "acc",
+             "password": "password"
+          },
+          "account_not_in_project": {
+             "email": "newtest@test.com",
+             "firstname": "Test",
+             "lastname": "User",
+             "username": "account_not_in_project",
+             "password": "password"
+          },
+          "project": {
+             "name": "Project",
+             "displaytext": "Project"
+          },
+          "project2": {
+             "name": "Project2",
+             "displaytext": "Project2"
+          },
+          "service_offering": {
+             "name": "Tiny Instance",
+             "displaytext": "Tiny Instance",
+             "cpunumber": 1,
+             "cpuspeed": 100,
+             "memory": 64
+          },
+          "ostype": 'CentOS 5.3 (64-bit)',
+          "host_anti_affinity": {
+                "name": "",
+                "type": "host anti-affinity"
+             },
+          "virtual_machine" : {
+             "hypervisor" : "KVM"
+          }
+       }
+
+class TestCreateAffinityGroup(cloudstackTestCase):
+    """
+    Test various scenarios for Create Affinity Group API for projects
+    """
+
+    @classmethod
+    def setUpClass(cls):
+       cls.testClient = super(TestCreateAffinityGroup, cls).getClsTestClient()
+       cls.api_client = cls.testClient.getApiClient()
+       cls.services = Services().services
+
+       #Get Zone, Domain and templates
+       cls.rootdomain = get_domain(cls.api_client)
+       cls.domain = Domain.create(cls.api_client, cls.services["domain"])
+
+       cls.zone = get_zone(cls.api_client, cls.testClient.getZoneForTests())
+       cls.template = get_template(
+          cls.api_client,
+          cls.zone.id,
+          cls.services["ostype"]
+       )
+       
+       cls.services["virtual_machine"]["zoneid"] = cls.zone.id
+       cls.services["template"] = cls.template.id
+       cls.services["zoneid"] = cls.zone.id
+       
+       cls.domain_admin_account = Account.create(
+          cls.api_client,
+          cls.services["domain_admin_account"],
+          domainid=cls.domain.id,
+          admin=True
+       )
+
+       cls.domain_api_client = cls.testClient.getUserApiClient(cls.domain_admin_account.name, cls.domain.name, 2)
+
+       cls.account = Account.create(
+          cls.api_client,
+          cls.services["account"],
+          domainid=cls.domain.id
+       )       
+
+       cls.account_api_client = cls.testClient.getUserApiClient(cls.account.name, cls.domain.name, 0)
+
+       cls.account_not_in_project = Account.create(
+          cls.api_client,
+          cls.services["account_not_in_project"],
+          domainid=cls.domain.id
+       )
+
+       cls.account_not_in_project_api_client = cls.testClient.getUserApiClient(cls.account_not_in_project.name, cls.domain.name, 0)
+
+       cls.project = Project.create(
+          cls.api_client,
+          cls.services["project"],
+          account=cls.domain_admin_account.name,
+          domainid=cls.domain_admin_account.domainid
+       )
+       
+       cls.project2 = Project.create(
+          cls.api_client,
+          cls.services["project2"],
+          account=cls.domain_admin_account.name,
+          domainid=cls.domain_admin_account.domainid
+       )
+
+       cls.debug("Created project with ID: %s" % cls.project.id)
+       cls.debug("Created project2 with ID: %s" % cls.project2.id)
+
+       # Add user to the project
+       cls.project.addAccount(
+          cls.api_client,
+          cls.account.name
+       )
+
+       cls.service_offering = ServiceOffering.create(
+          cls.api_client,
+          cls.services["service_offering"],
+          domainid=cls.account.domainid
+       )
+       
+       cls._cleanup = []
+       return
+
+    def setUp(self):
+       self.apiclient = self.testClient.getApiClient()
+       self.dbclient = self.testClient.getDbConnection()
+       self.cleanup = []
+
+    def tearDown(self):
+       try:
+#            #Clean up, terminate the created instance, volumes and snapshots
+          cleanup_resources(self.apiclient, self.cleanup)
+       except Exception as e:
+          raise Exception("Warning: Exception during cleanup : %s" % e)
+       return
+
+    @classmethod
+    def tearDownClass(cls):
+       try:
+          #Clean up, terminate the created templates
+          cls.domain.delete(cls.api_client, cleanup=True)
+          cleanup_resources(cls.api_client, cls._cleanup)
+       except Exception as e:
+          raise Exception("Warning: Exception during cleanup : %s" % e)
+
+    def create_aff_grp(self, api_client=None, aff_grp=None, aff_grp_name=None, projectid=None):
+
+       if not api_client:
+          api_client = self.api_client
+       if aff_grp is None:
+          aff_grp = self.services["host_anti_affinity"]
+       if aff_grp_name is None:
+          aff_grp["name"] = "aff_grp_" + random_gen(size=6)
+       else:
+          aff_grp["name"] = aff_grp_name
+       if projectid is None:
+          projectid = self.project.id
+       try:
+          return AffinityGroup.create(api_client, aff_grp, None, None, projectid)
+       except Exception as e:
+          raise Exception("Error: Creation of Affinity Group failed : %s" % e)
+   
+    @attr(tags=["simulator", "basic", "advanced"], required_hardware="false")
+    def test_01_admin_create_aff_grp_for_project(self):
+       """
+       Test create affinity group as admin in project
+       @return:
+       """
+       aff_grp = self.create_aff_grp()
+       self.debug("Created Affinity Group: %s" % aff_grp.name)
+       list_aff_grps = AffinityGroup.list(self.api_client, id=aff_grp.id)
+       self.assert_(isinstance(list_aff_grps, list) and len(list_aff_grps) > 0)
+       self.assert_(list_aff_grps[0].id == aff_grp.id)
+       self.assert_(list_aff_grps[0].projectid == self.project.id)
+       self.cleanup.append(aff_grp)
+ 
+    @attr(tags=["simulator", "basic", "advanced"], required_hardware="false")
+    def test_02_doadmin_create_aff_grp_for_project(self):
+        """
+        Test create affinity group as domain admin for projects
+        @return:
+        """
+        aff_grp = self.create_aff_grp(api_client=self.domain_api_client)
+        list_aff_grps = AffinityGroup.list(self.domain_api_client, id=aff_grp.id)
+        self.assert_(isinstance(list_aff_grps, list) and len(list_aff_grps) > 0)
+        self.assert_(list_aff_grps[0].id == aff_grp.id)
+        self.assert_(list_aff_grps[0].projectid == self.project.id)
+        self.cleanup.append(aff_grp)
+ 
+    @attr(tags=["vogxn", "simulator", "basic", "advanced"], required_hardware="false")
+    def test_03_user_create_aff_grp_for_project(self):
+        """
+        Test create affinity group as user for projects
+        @return:
+        """
+        aff_grp = self.create_aff_grp(api_client=self.account_api_client)
+        list_aff_grps = AffinityGroup.list(self.api_client, id=aff_grp.id)
+        self.assert_(isinstance(list_aff_grps, list) and len(list_aff_grps) > 0)
+        self.assert_(list_aff_grps[0].id == aff_grp.id)
+        self.assert_(list_aff_grps[0].projectid == self.project.id)
+        self.cleanup.append(aff_grp)
+  
+    @attr(tags=["simulator", "basic", "advanced"], required_hardware="false")
+    def test_4_user_create_aff_grp_existing_name_for_project(self):
+        """
+        Test create affinity group that exists (same name) for projects
+        @return:
+        """
+        
+        failed_aff_grp = None
+        aff_grp = self.create_aff_grp(api_client=self.account_api_client)
+        with self.assertRaises(Exception):
+           failed_aff_grp = self.create_aff_grp(api_client=self.account_api_client,aff_grp_name = aff_grp.name)
+        
+        if failed_aff_grp:
+            self.cleanup.append(failed_aff_grp)
+        self.cleanup.append(aff_grp)
+
+class TestListAffinityGroups(cloudstackTestCase):
+
+    @classmethod
+    def setUpClass(cls):
+       cls.testClient = super(TestListAffinityGroups, cls).getClsTestClient()
+       cls.api_client = cls.testClient.getApiClient()
+       cls.services = Services().services
+
+       #Get Zone, Domain and templates
+       cls.rootdomain = get_domain(cls.api_client)
+       cls.domain = Domain.create(cls.api_client, cls.services["domain"])
+
+       cls.zone = get_zone(cls.api_client, cls.testClient.getZoneForTests())
+       cls.template = get_template(
+          cls.api_client,
+          cls.zone.id,
+          cls.services["ostype"]
+       )
+       
+       cls.services["virtual_machine"]["zoneid"] = cls.zone.id
+       cls.services["template"] = cls.template.id
+       cls.services["zoneid"] = cls.zone.id
+       
+       cls.domain_admin_account = Account.create(
+          cls.api_client,
+          cls.services["domain_admin_account"],
+          domainid=cls.domain.id,
+          admin=True
+       )
+
+       cls.domain_api_client = cls.testClient.getUserApiClient(cls.domain_admin_account.name, cls.domain.name, 2)
+
+       cls.account = Account.create(
+          cls.api_client,
+          cls.services["account"],
+          domainid=cls.domain.id
+       )       
+
+       cls.account_api_client = cls.testClient.getUserApiClient(cls.account.name, cls.domain.name, 0)
+
+       cls.account_not_in_project = Account.create(
+          cls.api_client,
+          cls.services["account_not_in_project"],
+          domainid=cls.domain.id
+       )
+
+       cls.account_not_in_project_api_client = cls.testClient.getUserApiClient(cls.account_not_in_project.name, cls.domain.name, 0)
+
+       cls.project = Project.create(
+          cls.api_client,
+          cls.services["project"],
+          account=cls.domain_admin_account.name,
+          domainid=cls.domain_admin_account.domainid
+       )
+       
+       cls.project2 = Project.create(
+          cls.api_client,
+          cls.services["project2"],
+          account=cls.domain_admin_account.name,
+          domainid=cls.domain_admin_account.domainid
+       )
+
+       cls.debug("Created project with ID: %s" % cls.project.id)
+       cls.debug("Created project2 with ID: %s" % cls.project2.id)
+
+       # Add user to the project
+       cls.project.addAccount(
+          cls.api_client,
+          cls.account.name
+       )
+
+       cls.service_offering = ServiceOffering.create(
+          cls.api_client,
+          cls.services["service_offering"],
+          domainid=cls.account.domainid
+       )
+       
+       cls._cleanup = []
+       return
+
+    def setUp(self):
+       self.apiclient = self.testClient.getApiClient()
+       self.dbclient = self.testClient.getDbConnection()
+       self.cleanup = []
+
+    def tearDown(self):
+       try:
+#            #Clean up, terminate the created instance, volumes and snapshots
+          cleanup_resources(self.api_client, self.cleanup)
+       except Exception as e:
+          raise Exception("Warning: Exception during cleanup : %s" % e)
+       return
+
+    @classmethod
+    def tearDownClass(cls):
+       try:
+          cls.domain.delete(cls.api_client, cleanup=True)
+          cleanup_resources(cls.api_client, cls._cleanup)
+       except Exception as e:
+          raise Exception("Warning: Exception during cleanup : %s" % e)
+
+    def create_aff_grp(self, api_client=None, aff_grp=None, aff_grp_name=None, projectid=None):
+
+       if not api_client:
+          api_client = self.api_client
+       if aff_grp is None:
+          aff_grp = self.services["host_anti_affinity"]
+       if aff_grp_name is None:
+          aff_grp["name"] = "aff_grp_" + random_gen(size=6)
+       else:
+          aff_grp["name"] = aff_grp_name
+       if projectid is None:
+          projectid = self.project.id
+       try:
+          return AffinityGroup.create(api_client, aff_grp, None, None, projectid)
+       except Exception as e:
+          raise Exception("Error: Creation of Affinity Group failed : %s" % e)
+
+    def create_vm_in_aff_grps(self, api_client=None, ag_list=[], projectid=None):
+        self.debug('Creating VM in AffinityGroups=%s' % ag_list)
+
+        if api_client is None:
+           api_client = self.api_client
+        if projectid is None:
+           projectid = self.project.id
+
+        vm = VirtualMachine.create(
+                api_client,
+                self.services["virtual_machine"],
+                projectid=projectid,
+                templateid=self.template.id,
+                serviceofferingid=self.service_offering.id,
+                affinitygroupnames=ag_list
+              )
+        self.debug('Created VM=%s in Affinity Group=%s' % (vm.id, tuple(ag_list)))
+
+        list_vm = list_virtual_machines(api_client, id=vm.id, projectid=projectid)
+        self.assertEqual(isinstance(list_vm, list), True,"Check list response returns a valid list")
+        self.assertNotEqual(len(list_vm),0, "Check VM available in List Virtual Machines")
+        vm_response = list_vm[0]
+        self.assertEqual(vm_response.state, 'Running',msg="VM is not in Running state")
+        self.assertEqual(vm_response.projectid, projectid,msg="VM is not in project")
+        return vm, vm_response.hostid
+
+    @attr(tags=["simulator", "basic", "advanced"], required_hardware="false")
+    def test_01_list_aff_grps_for_vm(self):
+        """
+          List affinity group for a vm for projects
+        """
+        aff_grps = []
+        aff_grps.append(self.create_aff_grp(self.domain_api_client, projectid=self.project.id))
+
+        vm, hostid = self.create_vm_in_aff_grps(self.account_api_client,ag_list=[aff_grps[0].name])
+        list_aff_grps = AffinityGroup.list(self.api_client,virtualmachineid=vm.id)
+
+        self.assertEqual(list_aff_grps[0].name, aff_grps[0].name,"Listing Affinity Group by VM id failed")
+        self.assertEqual(list_aff_grps[0].projectid, self.project.id,"Listing Affinity Group by VM id failed, vm was not in project")
+
+        vm.delete(self.api_client)
+        #Wait for expunge interval to cleanup VM
+        wait_for_cleanup(self.apiclient, ["expunge.delay", "expunge.interval"])
+        self.cleanup.append(aff_grps[0])
+
+    @attr(tags=["simulator", "basic", "advanced"], required_hardware="false")
+    def test_02_list_multiple_aff_grps_for_vm(self):
+        """
+          List multiple affinity groups associated with a vm for projects
+        """
+
+        aff_grp_01 = self.create_aff_grp(self.account_api_client)
+        aff_grp_02 = self.create_aff_grp(self.account_api_client)
+
+        aff_grps_names = [aff_grp_01.name, aff_grp_02.name]
+        vm, hostid = self.create_vm_in_aff_grps(ag_list=aff_grps_names)
+        list_aff_grps = AffinityGroup.list(self.api_client,
+                                    virtualmachineid=vm.id)
+
+        list_aff_grps_names = [list_aff_grps[0].name, list_aff_grps[1].name]
+
+        aff_grps_names.sort()
+        list_aff_grps_names.sort()
+        self.assertEqual(aff_grps_names, list_aff_grps_names,"One of the Affinity Groups is missing %s" % list_aff_grps_names)
+
+        vm.delete(self.api_client)
+        #Wait for expunge interval to cleanup VM
+        wait_for_cleanup(self.apiclient, ["expunge.delay", "expunge.interval"])
+        self.cleanup.append(aff_grp_01)
+        self.cleanup.append(aff_grp_02)
+
+    @attr(tags=["simulator", "basic", "advanced"], required_hardware="false")
+    def test_03_list_aff_grps_by_id(self):
+        """
+          List affinity groups by id for projects
+        """
+        aff_grp = self.create_aff_grp(self.account_api_client)
+        list_aff_grps = AffinityGroup.list(self.account_api_client, id=aff_grp.id, projectid=self.project.id)
+        self.assertEqual(list_aff_grps[0].id, aff_grp.id,"Listing Affinity Group by id failed")
+        with self.assertRaises(Exception):
+           AffinityGroup.list(self.account_not_in_project_api_client, id=aff_grp.id, projectid=self.project.id)
+        self.cleanup.append(aff_grp)
+
+    @attr(tags=["simulator", "basic", "advanced"], required_hardware="false")
+    def test_04_list_aff_grps_by_name(self):
+        """
+           List Affinity Groups by name for projects
+        """
+        aff_grp = self.create_aff_grp(self.account_api_client)
+        list_aff_grps = AffinityGroup.list(self.account_api_client, name=aff_grp.name, projectid=self.project.id)
+        self.assertEqual(list_aff_grps[0].name, aff_grp.name,"Listing Affinity Group by name failed")
+        with self.assertRaises(Exception):
+           AffinityGroup.list(self.account_not_in_project_api_client, id=aff_grp.id, projectid=self.project.id)
+        self.cleanup.append(aff_grp)
+
+    @attr(tags=["simulator", "basic", "advanced"], required_hardware="false")
+    def test_05_list_aff_grps_by_non_existing_id(self):
+        """
+           List Affinity Groups by non-existing id for projects
+        """
+        aff_grp = self.create_aff_grp(self.account_api_client)
+        list_aff_grps = AffinityGroup.list(self.account_api_client, id=1234, projectid=self.project.id)
+        self.assertEqual(list_aff_grps, None, "Listing Affinity Group by non-existing id succeeded.")
+        self.cleanup.append(aff_grp)
+
+    @attr(tags=["simulator", "basic", "advanced"], required_hardware="false")
+    def test_06_list_aff_grps_by_non_existing_name(self):
+        """
+           List Affinity Groups by non-existing name for projects
+        """
+
+        aff_grp = self.create_aff_grp(self.account_api_client)
+        list_aff_grps = AffinityGroup.list(self.account_api_client, name="inexistantName", projectid=self.project.id)
+        self.assertEqual(list_aff_grps, None, "Listing Affinity Group by non-existing name succeeded.")
+        self.cleanup.append(aff_grp)
+
+    @attr(tags=["simulator", "basic", "advanced"], required_hardware="false")
+    def test_07_list_all_vms_in_aff_grp(self):
+        """
+          List affinity group should list all for a vms associated with that group for projects
+        """
+
+        aff_grp = self.create_aff_grp(self.account_api_client)
+
+        vm1, hostid1 = self.create_vm_in_aff_grps(ag_list=[aff_grp.name])
+        vm2, hostid2 = self.create_vm_in_aff_grps(ag_list=[aff_grp.name])
+        list_aff_grps = AffinityGroup.list(self.api_client, id=aff_grp.id, projectid=self.project.id)
+
+        self.assertEqual(list_aff_grps[0].name, aff_grp.name, "Listing Affinity Group by id failed")
+
+        self.assertEqual(list_aff_grps[0].virtualmachineIds[0], vm1.id, "List affinity group response.virtualmachineIds for group: %s doesn't contain vmid : %s" % (aff_grp.name, vm1.id))
+        self.assertEqual(list_aff_grps[0].virtualmachineIds[1], vm2.id, "List affinity group response.virtualmachineIds for group: %s doesn't contain vmid : %s" % (aff_grp.name, vm2.id))
+
+
+        vm1.delete(self.api_client)
+        vm2.delete(self.api_client)
+        #Wait for expunge interval to cleanup VM
+        wait_for_cleanup(self.apiclient, ["expunge.delay", "expunge.interval"])
+        self.cleanup.append(aff_grp)
+ 
+class TestDeleteAffinityGroups(cloudstackTestCase):
+
+    @classmethod
+    def setUpClass(cls):
+       cls.testClient = super(TestDeleteAffinityGroups, cls).getClsTestClient()
+       cls.api_client = cls.testClient.getApiClient()
+       cls.services = Services().services
+
+       #Get Zone, Domain and templates
+       cls.rootdomain = get_domain(cls.api_client)
+       cls.domain = Domain.create(cls.api_client, cls.services["domain"])
+
+       cls.zone = get_zone(cls.api_client, cls.testClient.getZoneForTests())
+       cls.template = get_template(
+          cls.api_client,
+          cls.zone.id,
+          cls.services["ostype"]
+       )
+       
+       cls.services["virtual_machine"]["zoneid"] = cls.zone.id
+       cls.services["template"] = cls.template.id
+       cls.services["zoneid"] = cls.zone.id
+       
+       cls.domain_admin_account = Account.create(
+          cls.api_client,
+          cls.services["domain_admin_account"],
+          domainid=cls.domain.id,
+          admin=True
+       )
+
+       cls.domain_api_client = cls.testClient.getUserApiClient(cls.domain_admin_account.name, cls.domain.name, 2)
+
+       cls.account = Account.create(
+          cls.api_client,
+          cls.services["account"],
+          domainid=cls.domain.id
+       )       
+
+       cls.account_api_client = cls.testClient.getUserApiClient(cls.account.name, cls.domain.name, 0)
+
+       cls.account_not_in_project = Account.create(
+          cls.api_client,
+          cls.services["account_not_in_project"],
+          domainid=cls.domain.id
+       )
+
+       cls.account_not_in_project_api_client = cls.testClient.getUserApiClient(cls.account_not_in_project.name, cls.domain.name, 0)
+
+       cls.project = Project.create(
+          cls.api_client,
+          cls.services["project"],
+          account=cls.domain_admin_account.name,
+          domainid=cls.domain_admin_account.domainid
+       )
+       
+       cls.project2 = Project.create(
+          cls.api_client,
+          cls.services["project2"],
+          account=cls.domain_admin_account.name,
+          domainid=cls.domain_admin_account.domainid
+       )
+
+       cls.debug("Created project with ID: %s" % cls.project.id)
+       cls.debug("Created project2 with ID: %s" % cls.project2.id)
+
+       # Add user to the project
+       cls.project.addAccount(
+          cls.api_client,
+          cls.account.name
+       )
+
+       cls.service_offering = ServiceOffering.create(
+          cls.api_client,
+          cls.services["service_offering"],
+          domainid=cls.account.domainid
+       )
+       
+       cls._cleanup = []
+       return
+
+    def setUp(self):
+       self.apiclient = self.testClient.getApiClient()
+       self.dbclient = self.testClient.getDbConnection()
+       self.cleanup = []
+
+    def tearDown(self):
+       try:
+#            #Clean up, terminate the created instance, volumes and snapshots
+          cleanup_resources(self.api_client, self.cleanup)
+       except Exception as e:
+          raise Exception("Warning: Exception during cleanup : %s" % e)
+       return
+
+    @classmethod
+    def tearDownClass(cls):
+       try:
+          cls.domain.delete(cls.api_client, cleanup=True)
+          cleanup_resources(cls.api_client, cls._cleanup)
+       except Exception as e:
+          raise Exception("Warning: Exception during cleanup : %s" % e)
+
+    def create_aff_grp(self, api_client=None, aff_grp=None, aff_grp_name=None, projectid=None):
+
+       if not api_client:
+          api_client = self.api_client
+       if aff_grp is None:
+          aff_grp = self.services["host_anti_affinity"]
+       if aff_grp_name is None:
+          aff_grp["name"] = "aff_grp_" + random_gen(size=6)
+       else:
+          aff_grp["name"] = aff_grp_name
+       if projectid is None:
+          projectid = self.project.id
+       try:
+          return AffinityGroup.create(api_client, aff_grp, None, None, projectid)
+       except Exception as e:
+          raise Exception("Error: Creation of Affinity Group failed : %s" % e)
+
+    def create_vm_in_aff_grps(self, api_client=None, ag_list=[], projectid=None):
+        self.debug('Creating VM in AffinityGroups=%s' % ag_list)
+
+        if api_client is None:
+           api_client = self.api_client
+        if projectid is None:
+           projectid = self.project.id
+
+        vm = VirtualMachine.create(
+                api_client,
+                self.services["virtual_machine"],
+                projectid=projectid,
+                templateid=self.template.id,
+                serviceofferingid=self.service_offering.id,
+                affinitygroupnames=ag_list
+              )
+        self.debug('Created VM=%s in Affinity Group=%s' % (vm.id, tuple(ag_list)))
+        list_vm = list_virtual_machines(self.api_client, id=vm.id, projectid=projectid)
+        self.assertEqual(isinstance(list_vm, list), True,"Check list response returns an invalid list %s" % list_vm)
+        self.assertNotEqual(len(list_vm),0, "Check VM available in TestDeployVMAffinityGroups")
+        self.assertEqual(list_vm[0].id, vm.id,"Listed vm does not have the same ids")
+        vm_response = list_vm[0]
+        self.assertEqual(vm.state, 'Running',msg="VM is not in Running state")
+        self.assertEqual(vm.projectid, projectid,msg="VM is not in project")
+        self.assertNotEqual(vm_response.hostid, None, "Host id was null for vm %s" % vm_response)
+        return vm, vm_response.hostid
+
+    def delete_aff_group(self, apiclient, **kwargs):
+        cmd = deleteAffinityGroup.deleteAffinityGroupCmd()
+        [setattr(cmd, k, v) for k, v in kwargs.items()]
+        return apiclient.deleteAffinityGroup(cmd)
+
+
+    @attr(tags=["simulator", "basic", "advanced"], required_hardware="false")
+    def test_01_delete_aff_grp_by_id(self):
+        """
+           #Delete Affinity Group by id.
+        """
+
+        aff_grp1 = self.create_aff_grp(self.account_api_client)
+        aff_grp2 = self.create_aff_grp(self.account_api_client)
+
+        aff_grp1.delete(self.account_api_client)
+        
+        with self.assertRaises(Exception):
+           list_aff_grps = AffinityGroup.list(self.api_client, id=aff_grp1.id)
+        
+        self.cleanup.append(aff_grp2)
+
+    @attr(tags=["simulator", "basic", "advanced"], required_hardware="false")
+    def test_02_delete_aff_grp_by_id_another_user(self):
+        """
+           #Delete Affinity Group by id should fail for user not in project
+        """
+
+        aff_grp1 = self.create_aff_grp(self.account_api_client)
+        aff_grp2 = self.create_aff_grp(self.account_api_client)
+
+        with self.assertRaises(Exception):
+           aff_grp1.delete(self.account_not_in_project_api_client)
+
+        self.cleanup.append(aff_grp1)
+        self.cleanup.append(aff_grp2)
+
+class TestUpdateVMAffinityGroups(cloudstackTestCase):
+
+    @classmethod
+    def setUpClass(cls):
+       cls.testClient = super(TestUpdateVMAffinityGroups, cls).getClsTestClient()
+       cls.api_client = cls.testClient.getApiClient()
+       cls.services = Services().services
+
+       #Get Zone, Domain and templates
+       cls.rootdomain = get_domain(cls.api_client)
+       cls.domain = Domain.create(cls.api_client, cls.services["domain"])
+
+       cls.zone = get_zone(cls.api_client, cls.testClient.getZoneForTests())
+       cls.template = get_template(
+          cls.api_client,
+          cls.zone.id,
+          cls.services["ostype"]
+       )
+       
+       cls.services["virtual_machine"]["zoneid"] = cls.zone.id
+       cls.services["template"] = cls.template.id
+       cls.services["zoneid"] = cls.zone.id
+       
+       cls.domain_admin_account = Account.create(
+          cls.api_client,
+          cls.services["domain_admin_account"],
+          domainid=cls.domain.id,
+          admin=True
+       )
+
+       cls.domain_api_client = cls.testClient.getUserApiClient(cls.domain_admin_account.name, cls.domain.name, 2)
+
+       cls.account = Account.create(
+          cls.api_client,
+          cls.services["account"],
+          domainid=cls.domain.id
+       )       
+
+       cls.account_api_client = cls.testClient.getUserApiClient(cls.account.name, cls.domain.name, 0)
+
+       cls.account_not_in_project = Account.create(
+          cls.api_client,
+          cls.services["account_not_in_project"],
+          domainid=cls.domain.id
+       )
+
+       cls.account_not_in_project_api_client = cls.testClient.getUserApiClient(cls.account_not_in_project.name, cls.domain.name, 0)
+
+       cls.project = Project.create(
+          cls.api_client,
+          cls.services["project"],
+          account=cls.domain_admin_account.name,
+          domainid=cls.domain_admin_account.domainid
+       )
+       
+       cls.project2 = Project.create(
+          cls.api_client,
+          cls.services["project2"],
+          account=cls.domain_admin_account.name,
+          domainid=cls.domain_admin_account.domainid
+       )
+
+       cls.debug("Created project with ID: %s" % cls.project.id)
+       cls.debug("Created project2 with ID: %s" % cls.project2.id)
+
+       # Add user to the project
+       cls.project.addAccount(
+          cls.api_client,
+          cls.account.name
+       )
+
+       cls.service_offering = ServiceOffering.create(
+          cls.api_client,
+          cls.services["service_offering"],
+          domainid=cls.account.domainid
+       )
+       
+       cls._cleanup = []
+       return
+
+    def setUp(self):
+       self.apiclient = self.testClient.getApiClient()
+       self.dbclient = self.testClient.getDbConnection()
+       self.cleanup = []
+
+    def tearDown(self):
+       try:
+#            #Clean up, terminate the created instance, volumes and snapshots
+          cleanup_resources(self.api_client, self.cleanup)
+       except Exception as e:
+          raise Exception("Warning: Exception during cleanup : %s" % e)
+       return
+
+    @classmethod
+    def tearDownClass(cls):
+       try:
+          cls.domain.delete(cls.api_client, cleanup=True)
+          cleanup_resources(cls.api_client, cls._cleanup)
+       except Exception as e:
+          raise Exception("Warning: Exception during cleanup : %s" % e)
+
+    def create_aff_grp(self, api_client=None, aff_grp=None, aff_grp_name=None, projectid=None):
+
+       if not api_client:
+          api_client = self.api_client
+       if aff_grp is None:
+          aff_grp = self.services["host_anti_affinity"]
+       if aff_grp_name is None:
+          aff_grp["name"] = "aff_grp_" + random_gen(size=6)
+       else:
+          aff_grp["name"] = aff_grp_name
+       if projectid is None:
+          projectid = self.project.id
+       try:
+          return AffinityGroup.create(api_client, aff_grp, None, None, projectid)
+       except Exception as e:
+          raise Exception("Error: Creation of Affinity Group failed : %s" % e)
+
+    def create_vm_in_aff_grps(self, api_client=None, ag_list=[], projectid=None):
+        self.debug('Creating VM in AffinityGroups=%s' % ag_list)
+
+        if api_client is None:
+           api_client = self.api_client
+        if projectid is None:
+           projectid = self.project.id
+
+        vm = VirtualMachine.create(
+                api_client,
+                self.services["virtual_machine"],
+                projectid=projectid,
+                templateid=self.template.id,
+                serviceofferingid=self.service_offering.id,
+                affinitygroupnames=ag_list
+              )
+        self.debug('Created VM=%s in Affinity Group=%s' % (vm.id, tuple(ag_list)))
+        list_vm = list_virtual_machines(self.api_client, id=vm.id, projectid=projectid)
+        self.assertEqual(isinstance(list_vm, list), True,"Check list response returns an invalid list %s" % list_vm)
+        self.assertNotEqual(len(list_vm),0, "Check VM available in TestDeployVMAffinityGroups")
+        self.assertEqual(list_vm[0].id, vm.id,"Listed vm does not have the same ids")
+        vm_response = list_vm[0]
+        self.assertEqual(vm.state, 'Running',msg="VM is not in Running state")
+        self.assertEqual(vm.projectid, projectid,msg="VM is not in project")
+        self.assertNotEqual(vm_response.hostid, None, "Host id was null for vm %s" % vm_response)
+        return vm, vm_response.hostid
+
+    @attr(tags=["simulator", "basic", "advanced", "multihost"], required_hardware="false")
+    def test_01_update_aff_grp_by_ids(self):
+        """
+           Update the list of affinityGroups by using affinity groupids
+
+        """
+        aff_grp1 = self.create_aff_grp(self.account_api_client)
+        aff_grp2 = self.create_aff_grp(self.account_api_client)
+
+        vm1, hostid1 = self.create_vm_in_aff_grps(ag_list=[aff_grp1.name])
+        vm2, hostid2 = self.create_vm_in_aff_grps(ag_list=[aff_grp1.name])
+
+        vm1.stop(self.api_client)
+
+        list_aff_grps = AffinityGroup.list(self.api_client, projectid=self.project.id)
+
+        self.assertEqual(len(list_aff_grps), 2 , "2 affinity groups should be present")
+
+        vm1.update_affinity_group(self.api_client,affinitygroupids=[list_aff_grps[0].id,list_aff_grps[1].id])
+
+        list_aff_grps = AffinityGroup.list(self.api_client,virtualmachineid=vm1.id)
+
+        list_aff_grps_names = [list_aff_grps[0].name, list_aff_grps[1].name]
+
+        aff_grps_names = [aff_grp1.name, aff_grp2.name]
+        aff_grps_names.sort()
+        list_aff_grps_names.sort()
+        self.assertEqual(aff_grps_names, list_aff_grps_names,"One of the Affinity Groups is missing %s" % list_aff_grps_names)
+
+        vm1.start(self.api_client)
+
+        vm_status = VirtualMachine.list(self.api_client, id=vm1.id)
+        self.assertNotEqual(vm_status[0].hostid, hostid2, "The virtual machine started on host %s violating the host anti-affinity rule" %vm_status[0].hostid)
+
+        vm1.delete(self.api_client)
+        vm2.delete(self.api_client)
+        #Wait for expunge interval to cleanup VM
+        wait_for_cleanup(self.apiclient, ["expunge.delay", "expunge.interval"])
+        aff_grp1.delete(self.api_client)
+        aff_grp2.delete(self.api_client)
+           
+
+class TestDeployVMAffinityGroups(cloudstackTestCase):
+
+    @classmethod
+    def setUpClass(cls):
+       cls.testClient = super(TestDeployVMAffinityGroups, cls).getClsTestClient()
+       cls.api_client = cls.testClient.getApiClient()
+       cls.services = Services().services
+
+       #Get Zone, Domain and templates
+       cls.rootdomain = get_domain(cls.api_client)
+       cls.domain = Domain.create(cls.api_client, cls.services["domain"])
+
+       cls.zone = get_zone(cls.api_client, cls.testClient.getZoneForTests())
+       cls.template = get_template(
+          cls.api_client,
+          cls.zone.id,
+          cls.services["ostype"]
+       )
+       
+       cls.services["virtual_machine"]["zoneid"] = cls.zone.id
+       cls.services["template"] = cls.template.id
+       cls.services["zoneid"] = cls.zone.id
+       
+       cls.domain_admin_account = Account.create(
+          cls.api_client,
+          cls.services["domain_admin_account"],
+          domainid=cls.domain.id,
+          admin=True
+       )
+
+       cls.domain_api_client = cls.testClient.getUserApiClient(cls.domain_admin_account.name, cls.domain.name, 2)
+
+       cls.account = Account.create(
+          cls.api_client,
+          cls.services["account"],
+          domainid=cls.domain.id
+       )       
+
+       cls.account_api_client = cls.testClient.getUserApiClient(cls.account.name, cls.domain.name, 0)
+
+       cls.account_not_in_project = Account.create(
+          cls.api_client,
+          cls.services["account_not_in_project"],
+          domainid=cls.domain.id
+       )
+
+       cls.account_not_in_project_api_client = cls.testClient.getUserApiClient(cls.account_not_in_project.name, cls.domain.name, 0)
+
+       cls.project = Project.create(
+          cls.api_client,
+          cls.services["project"],
+          account=cls.domain_admin_account.name,
+          domainid=cls.domain_admin_account.domainid
+       )
+       
+       cls.project2 = Project.create(
+          cls.api_client,
+          cls.services["project2"],
+          account=cls.domain_admin_account.name,
+          domainid=cls.domain_admin_account.domainid
+       )
+
+       cls.debug("Created project with ID: %s" % cls.project.id)
+       cls.debug("Created project2 with ID: %s" % cls.project2.id)
+
+       # Add user to the project
+       cls.project.addAccount(
+          cls.api_client,
+          cls.account.name
+       )
+
+       cls.service_offering = ServiceOffering.create(
+          cls.api_client,
+          cls.services["service_offering"],
+          domainid=cls.account.domainid
+       )
+       
+       cls._cleanup = []
+       return
+
+    def setUp(self):
+       self.apiclient = self.testClient.getApiClient()
+       self.dbclient = self.testClient.getDbConnection()
+       self.cleanup = []
+
+    def tearDown(self):
+       try:
+#            #Clean up, terminate the created instance, volumes and snapshots
+          cleanup_resources(self.api_client, self.cleanup)
+       except Exception as e:
+          raise Exception("Warning: Exception during cleanup : %s" % e)
+       return
+
+    @classmethod
+    def tearDownClass(cls):
+       try:
+          cls.domain.delete(cls.api_client, cleanup=True)
+          cleanup_resources(cls.api_client, cls._cleanup)
+       except Exception as e:
+          raise Exception("Warning: Exception during cleanup : %s" % e)
+
+    def create_aff_grp(self, api_client=None, aff_grp=None, aff_grp_name=None, projectid=None):
+
+       if not api_client:
+          api_client = self.api_client
+       if aff_grp is None:
+          aff_grp = self.services["host_anti_affinity"]
+       if aff_grp_name is None:
+          aff_grp["name"] = "aff_grp_" + random_gen(size=6)
+       else:
+          aff_grp["name"] = aff_grp_name
+       if projectid is None:
+          projectid = self.project.id
+       try:
+          return AffinityGroup.create(api_client, aff_grp, None, None, projectid)
+       except Exception as e:
+          raise Exception("Error: Creation of Affinity Group failed : %s" % e)
+
+    def create_vm_in_aff_grps(self, api_client=None, ag_list=[], projectid=None):
+        self.debug('Creating VM in AffinityGroups=%s' % ag_list)
+
+        if api_client is None:
+           api_client = self.api_client
+        if projectid is None:
+           projectid = self.project.id
+
+        vm = VirtualMachine.create(
+                api_client,
+                self.services["virtual_machine"],
+                projectid=projectid,
+                templateid=self.template.id,
+                serviceofferingid=self.service_offering.id,
+                affinitygroupnames=ag_list
+              )
+        self.debug('Created VM=%s in Affinity Group=%s' % (vm.id, tuple(ag_list)))
+        list_vm = list_virtual_machines(self.api_client, id=vm.id, projectid=projectid)
+        self.assertEqual(isinstance(list_vm, list), True,"Check list response returns an invalid list %s" % list_vm)
+        self.assertNotEqual(len(list_vm),0, "Check VM available in TestDeployVMAffinityGroups")
+        self.assertEqual(list_vm[0].id, vm.id,"Listed vm does not have the same ids")
+        vm_response = list_vm[0]
+        self.assertEqual(vm.state, 'Running',msg="VM is not in Running state")
+        self.assertEqual(vm.projectid, projectid,msg="VM is not in project")
+        self.assertNotEqual(vm_response.hostid, None, "Host id was null for vm %s" % vm_response)
+        return vm, vm_response.hostid
+
+    @attr(tags=["simulator", "basic", "advanced", "multihost"], required_hardware="false")
+    def test_01_deploy_vm_anti_affinity_group(self):
+        """
+        test DeployVM in anti-affinity groups
+
+        deploy VM1 and VM2 in the same host-anti-affinity groups
+        Verify that the vms are deployed on separate hosts
+        """
+        aff_grp = self.create_aff_grp(self.account_api_client)
+        vm1, hostid1 = self.create_vm_in_aff_grps(self.account_api_client,ag_list=[aff_grp.name])
+        vm2, hostid2 = self.create_vm_in_aff_grps(self.account_api_client, ag_list=[aff_grp.name])
+
+        self.assertNotEqual(hostid1, hostid2, msg="Both VMs of affinity group %s are on the same host: %s , %s, %s, %s" % (aff_grp.name, vm1, hostid1, vm2, hostid2))
+
+        vm1.delete(self.api_client)
+        vm2.delete(self.api_client)
+        wait_for_cleanup(self.api_client, ["expunge.delay", "expunge.interval"])
+        self.cleanup.append(aff_grp)
+
+    @attr(tags=["simulator", "basic", "advanced", "multihost"], required_hardware="false")
+    def test_02_deploy_vm_anti_affinity_group_fail_on_not_enough_hosts(self):
+        """
+        test DeployVM in anti-affinity groups with more vms than hosts.
+        """
+        hosts = list_hosts(self.api_client, type="routing")
+        aff_grp = self.create_aff_grp(self.account_api_client)
+        vms = []
+        for host in hosts:
+           vms.append(self.create_vm_in_aff_grps(self.account_api_client,ag_list=[aff_grp.name]))
+
+        vm_failed = None
+        with self.assertRaises(Exception):
+           vm_failed = self.create_vm_in_aff_grps(self.account_api_client,ag_list=[aff_grp.name])
+        
+        self.assertEqual(len(hosts), len(vms), "Received %s and %s " % (hosts, vms))
+        
+        if vm_failed:
+           vm_failed.expunge(self.api_client)
+
+        self.cleanup.append(aff_grp)
+
+
+

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/c76d3171/test/integration/smoke/test_affinity_groups_projects.py
----------------------------------------------------------------------
diff --git a/test/integration/smoke/test_affinity_groups_projects.py b/test/integration/smoke/test_affinity_groups_projects.py
new file mode 100644
index 0000000..2e971c5
--- /dev/null
+++ b/test/integration/smoke/test_affinity_groups_projects.py
@@ -0,0 +1,188 @@
+#!/usr/bin/env python
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements.  See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership.  The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License.  You may obtain a copy of the License at
+#
+#   http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied.  See the License for the
+# specific language governing permissions and limitations
+# under the License.
+
+from marvin.codes import FAILED
+from marvin.cloudstackTestCase import *
+from marvin.cloudstackAPI import *
+from marvin.lib.utils import *
+from marvin.lib.base import *
+from marvin.lib.common import *
+from marvin.sshClient import SshClient
+from nose.plugins.attrib import attr
+
+class TestDeployVmWithAffinityGroup(cloudstackTestCase):
+    """
+    This test deploys a virtual machine for a project
+    using the small service offering and builtin template
+    """
+
+    @classmethod
+    def setUpClass(cls):
+        cls.testClient = super(TestDeployVmWithAffinityGroup, cls).getClsTestClient()
+        zone_name = cls.testClient.getZoneForTests()
+        cls.apiclient = cls.testClient.getApiClient()
+        cls.domain = get_domain(cls.apiclient) 
+        cls.services = cls.testClient.getParsedTestDataConfig()
+        # Get Zone, Domain and templates
+        cls.zone = get_zone(cls.apiclient, cls.testClient.getZoneForTests())
+                            
+        cls.template = get_template(
+            cls.apiclient,
+            cls.zone.id,
+            cls.services["ostype"]
+        )
+        
+        if cls.template == FAILED:
+            assert False, "get_template() failed to return template with description %s" % cls.services["ostype"]
+            
+        cls.services["virtual_machine"]["zoneid"] = cls.zone.id
+
+        cls.services["template"] = cls.template.id
+        cls.services["zoneid"] = cls.zone.id
+
+        cls.account = Account.create(
+            cls.apiclient,
+            cls.services["account"],
+            domainid=cls.domain.id
+        )
+
+        projectData = {
+            "name": "Project",
+            "displaytext": "Test project",
+        }
+
+        cls.project = Project.create(
+            cls.apiclient,
+            projectData,
+            account=cls.account.name,
+            domainid=cls.account.domainid
+        )
+
+        # Add user to the project
+        cls.project.addAccount(
+            cls.apiclient,
+            cls.account.name
+        )
+
+        cls.service_offering = ServiceOffering.create(
+            cls.apiclient,
+            cls.services["service_offerings"]["tiny"]
+        )
+
+        cls.ag = AffinityGroup.create(cls.apiclient, cls.services["virtual_machine"]["affinity"],projectid=cls.project.id)
+
+        cls._cleanup = [
+            cls.service_offering,
+            cls.ag,
+            cls.project,
+            cls.account,
+        ]
+        return
+
+    @attr(tags=["basic", "advanced", "multihost"], required_hardware="false")
+    def test_DeployVmAntiAffinityGroup_in_project(self):
+        """
+        test DeployVM in anti-affinity groups for project
+
+        deploy VM1 and VM2 in the same host-anti-affinity groups
+        Verify that the vms are deployed on separate hosts
+        """
+        #deploy VM1 in affinity group created in setUp
+        vm1 = VirtualMachine.create(
+            self.apiclient,
+            self.services["virtual_machine"],
+            templateid=self.template.id,
+            projectid=self.project.id,
+            serviceofferingid=self.service_offering.id,
+            affinitygroupnames=[self.ag.name]
+        )
+
+        list_vm1 = list_virtual_machines(
+            self.apiclient,
+            id=vm1.id
+        )
+        self.assertEqual(
+            isinstance(list_vm1, list),
+            True,
+            "Check list response returns a valid list"
+        )
+        self.assertNotEqual(
+            len(list_vm1),
+            0,
+            "Check VM available in List Virtual Machines"
+        )
+        vm1_response = list_vm1[0]
+        self.assertEqual(
+            vm1_response.state,
+            'Running',
+            msg="VM is not in Running state"
+        )
+        self.assertEqual(
+            vm1_response.projectid,
+            self.project.id,
+            msg="VM1 is not deployed in project"
+        )
+        host_of_vm1 = vm1_response.hostid
+
+        #deploy VM2 in affinity group created in setUp
+        vm2 = VirtualMachine.create(
+            self.apiclient,
+            self.services["virtual_machine"],
+            templateid=self.template.id,
+            projectid=self.project.id,
+            serviceofferingid=self.service_offering.id,
+            affinitygroupnames=[self.ag.name]
+        )
+        list_vm2 = list_virtual_machines(
+            self.apiclient,
+            id=vm2.id
+        )
+        self.assertEqual(
+            isinstance(list_vm2, list),
+            True,
+            "Check list response returns a valid list"
+        )
+        self.assertNotEqual(
+            len(list_vm2),
+            0,
+            "Check VM available in List Virtual Machines"
+        )
+        vm2_response = list_vm2[0]
+        self.assertEqual(
+            vm2_response.state,
+            'Running',
+            msg="VM is not in Running state"
+        )
+        self.assertEqual(
+            vm2_response.projectid,
+            self.project.id,
+            msg="VM2 is not deployed in project"
+        )
+        host_of_vm2 = vm2_response.hostid
+
+        self.assertNotEqual(host_of_vm1, host_of_vm2,
+            msg="Both VMs of affinity group %s are on the same host" % self.ag.name)
+
+
+    @classmethod
+    def tearDownClass(cls):
+        try:
+            #Clean up, terminate the created templates
+            cleanup_resources(cls.apiclient, cls._cleanup)
+        except Exception as e:
+            raise Exception("Warning: Exception during cleanup : %s" % e)

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/c76d3171/tools/marvin/marvin/lib/base.py
----------------------------------------------------------------------
diff --git a/tools/marvin/marvin/lib/base.py b/tools/marvin/marvin/lib/base.py
index 32e2d59..4b04e77 100755
--- a/tools/marvin/marvin/lib/base.py
+++ b/tools/marvin/marvin/lib/base.py
@@ -4220,7 +4220,7 @@ class AffinityGroup:
         self.__dict__.update(items)
 
     @classmethod
-    def create(cls, apiclient, aff_grp, account=None, domainid=None):
+    def create(cls, apiclient, aff_grp, account=None, domainid=None, projectid=None):
         cmd = createAffinityGroup.createAffinityGroupCmd()
         cmd.name = aff_grp['name']
         cmd.displayText = aff_grp['name']
@@ -4229,6 +4229,8 @@ class AffinityGroup:
             cmd.account = account
         if domainid:
             cmd.domainid = domainid
+        if projectid:
+            cmd.projectid = projectid
         return AffinityGroup(apiclient.createAffinityGroup(cmd).__dict__)
 
     def update(self, apiclient):


[4/5] git commit: updated refs/heads/4.6 to 9a21873

Posted by re...@apache.org.
CLOUDSTACK-6276 Removing unused parameter in integration test for projects


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

Branch: refs/heads/4.6
Commit: 091bb79669045c9cd91342ecc27d7f93f8ce7eba
Parents: a1db428
Author: Patrick Dube <pd...@cloudops.com>
Authored: Sat Nov 28 20:46:24 2015 -0500
Committer: Patrick Dube <pd...@cloudops.com>
Committed: Sat Nov 28 20:46:24 2015 -0500

----------------------------------------------------------------------
 test/integration/component/test_affinity_groups_projects.py | 1 -
 1 file changed, 1 deletion(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/cloudstack/blob/091bb796/test/integration/component/test_affinity_groups_projects.py
----------------------------------------------------------------------
diff --git a/test/integration/component/test_affinity_groups_projects.py b/test/integration/component/test_affinity_groups_projects.py
index ffd10ef..dbcc92b 100644
--- a/test/integration/component/test_affinity_groups_projects.py
+++ b/test/integration/component/test_affinity_groups_projects.py
@@ -84,7 +84,6 @@ class Services:
                 "type": "host anti-affinity"
              },
           "virtual_machine" : {
-             "hypervisor" : "KVM"
           }
        }
 


[3/5] git commit: updated refs/heads/4.6 to 9a21873

Posted by re...@apache.org.
CLOUDSTACK-6276 Removing unused parameter in integration test


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

Branch: refs/heads/4.6
Commit: a1db428e08a9dd4564c0b45579670b4f579b223b
Parents: c76d317
Author: Patrick Dube <pd...@cloudops.com>
Authored: Sat Nov 28 20:44:56 2015 -0500
Committer: Patrick Dube <pd...@cloudops.com>
Committed: Sat Nov 28 20:44:56 2015 -0500

----------------------------------------------------------------------
 test/integration/component/test_affinity_groups.py | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/cloudstack/blob/a1db428e/test/integration/component/test_affinity_groups.py
----------------------------------------------------------------------
diff --git a/test/integration/component/test_affinity_groups.py b/test/integration/component/test_affinity_groups.py
index b071e04..c0c5529 100644
--- a/test/integration/component/test_affinity_groups.py
+++ b/test/integration/component/test_affinity_groups.py
@@ -64,7 +64,7 @@ class Services:
                     "type": "host anti-affinity",
                 },
             "virtual_machine" : {
-                "hypervisor" : "KVM",
+                
             },
             "new_domain": {
                 "name": "New Domain",


[5/5] git commit: updated refs/heads/4.6 to 9a21873

Posted by re...@apache.org.
Merge pull request #1134 from pdube/CLOUDSTACK-6276

CLOUDSTACK-6276 Fixing affinity groups for projectsWith some contributions from @resmo and @ustcweizhou.
This closes https://github.com/apache/cloudstack/pull/508

To test manually (need at least 2 hosts):
Create a project
Create an affinity group in that project
Deploy a vm with that affinity group
Deploy a second vm with that affinity group
They should be on different hosts

Ran old and new tests for affinity groups on the simulator

Test create affinity group as admin in project ... === TestName: test_01_admin_create_aff_grp_for_project | Status : SUCCESS ===
ok
Test create affinity group as domain admin for projects ... === TestName: test_02_doadmin_create_aff_grp_for_project | Status : SUCCESS ===
ok
Test create affinity group as user for projects ... === TestName: test_03_user_create_aff_grp_for_project | Status : SUCCESS ===
ok
Test create affinity group that exists (same name) for projects ... === TestName: test_4_user_create_aff_grp_existing_name_for_project | Status : SUCCESS ===
ok
#Delete Affinity Group by id. ... === TestName: test_01_delete_aff_grp_by_id | Status : SUCCESS ===
ok
#Delete Affinity Group by id should fail for user not in project ... === TestName: test_02_delete_aff_grp_by_id_another_user | Status : SUCCESS ===
ok
test DeployVM in anti-affinity groups ... === TestName: test_01_deploy_vm_anti_affinity_group | Status : SUCCESS ===
ok
test DeployVM in anti-affinity groups with more vms than hosts. ... === TestName: test_02_deploy_vm_anti_affinity_group_fail_on_not_enough_hosts | Status : SUCCESS ===
ok
List affinity group for a vm for projects ... === TestName: test_01_list_aff_grps_for_vm | Status : SUCCESS ===
ok
List multiple affinity groups associated with a vm for projects ... === TestName: test_02_list_multiple_aff_grps_for_vm | Status : SUCCESS ===
ok
List affinity groups by id for projects ... === TestName: test_03_list_aff_grps_by_id | Status : SUCCESS ===
ok
List Affinity Groups by name for projects ... === TestName: test_04_list_aff_grps_by_name | Status : SUCCESS ===
ok
List Affinity Groups by non-existing id for projects ... === TestName: test_05_list_aff_grps_by_non_existing_id | Status : SUCCESS ===
ok
List Affinity Groups by non-existing name for projects ... === TestName: test_06_list_aff_grps_by_non_existing_name | Status : SUCCESS ===
ok
List affinity group should list all for a vms associated with that group for projects ... === TestName: test_07_list_all_vms_in_aff_grp | Status : SUCCESS ===
ok
Update the list of affinityGroups by using affinity groupids ... === TestName: test_01_update_aff_grp_by_ids | Status : SUCCESS ===
ok

----------------------------------------------------------------------
Ran 16 tests in 581.706s

OK

Deploy vm as Admin in Affinity Group belonging to regular user (should fail) ... === TestName: test_01_deploy_vm_another_user | Status : SUCCESS ===
ok
Create Affinity Group as admin for regular user ... === TestName: test_02_create_aff_grp_user | Status : SUCCESS ===
ok
List Affinity Groups as admin for all the users ... === TestName: test_03_list_aff_grp_all_users | Status : SUCCESS ===
ok
List Affinity Groups belonging to admin user ... === TestName: test_04_list_all_admin_aff_grp | Status : SUCCESS ===
ok
List Affinity Groups belonging to regular user passing account id and domain id ... === TestName: test_05_list_all_users_aff_grp | Status : SUCCESS ===
ok
List Affinity Groups belonging to regular user passing group id ... === TestName: test_06_list_all_users_aff_grp_by_id | Status : SUCCESS ===
ok
Delete Affinity Group belonging to regular user ... === TestName: test_07_delete_aff_grp_of_other_user | Status : SUCCESS ===
ok
Test create affinity group as admin ... === TestName: test_01_admin_create_aff_grp | Status : SUCCESS ===
ok
Test create affinity group as domain admin ... === TestName: test_02_doadmin_create_aff_grp | Status : SUCCESS ===
ok
Test create affinity group as user ... === TestName: test_03_user_create_aff_grp | Status : SUCCESS ===
ok
Test create affinity group that exists (same name) ... === TestName: test_04_user_create_aff_grp_existing_name | Status : SUCCESS ===
ok
Test create affinity group with existing name but within different account ... === TestName: test_05_create_aff_grp_same_name_diff_acc | Status : SUCCESS ===
ok
Test create affinity group of non-existing type ... === TestName: test_06_create_aff_grp_nonexisting_type | Status : SUCCESS ===
ok
Delete Affinity Group by name ... === TestName: test_01_delete_aff_grp_by_name | Status : SUCCESS ===
ok
Delete Affinity Group as admin for an account ... === TestName: test_02_delete_aff_grp_for_acc | Status : SUCCESS ===
ok
Delete Affinity Group which has vms in it ... === TestName: test_03_delete_aff_grp_with_vms | Status : SUCCESS ===
ok
Delete Affinity Group with id which does not belong to this user ... === TestName: test_05_delete_aff_grp_id | Status : SUCCESS ===
ok
Delete Affinity Group by name which does not belong to this user ... === TestName: test_06_delete_aff_grp_name | Status : SUCCESS ===
ok
Delete Affinity Group by id. ... === TestName: test_08_delete_aff_grp_by_id | Status : SUCCESS ===
ok
Root admin should be able to delete affinity group of other users ... === TestName: test_09_delete_aff_grp_root_admin | Status : SUCCESS ===
ok
Deploy VM without affinity group ... === TestName: test_01_deploy_vm_without_aff_grp | Status : SUCCESS ===
ok
Deploy VM by aff grp name ... === TestName: test_02_deploy_vm_by_aff_grp_name | Status : SUCCESS ===
ok
Deploy VM by aff grp id ... === TestName: test_03_deploy_vm_by_aff_grp_id | Status : SUCCESS ===
ok
test DeployVM in anti-affinity groups ... === TestName: test_04_deploy_vm_anti_affinity_group | Status : SUCCESS ===
ok
Deploy vms by affinity group id ... === TestName: test_05_deploy_vm_by_id | Status : SUCCESS ===
ok
Deploy vm in affinity group of another user by name ... === TestName: test_06_deploy_vm_aff_grp_of_other_user_by_name | Status : SUCCESS ===
ok
Deploy vm in affinity group of another user by id ... === TestName: test_07_deploy_vm_aff_grp_of_other_user_by_id | Status : SUCCESS ===
ok
Deploy vm in multiple affinity groups ... === TestName: test_08_deploy_vm_multiple_aff_grps | Status : SUCCESS ===
ok
Deploy multiple vms in multiple affinity groups ... === TestName: test_09_deploy_vm_multiple_aff_grps | Status : SUCCESS ===
ok
Deploy VM by aff grp name and id ... === TestName: test_10_deploy_vm_by_aff_grp_name_and_id | Status : SUCCESS ===
ok
List affinity group for a vm ... === TestName: test_01_list_aff_grps_for_vm | Status : SUCCESS ===
ok
List multiple affinity groups associated with a vm ... === TestName: test_02_list_multiple_aff_grps_for_vm | Status : SUCCESS ===
ok
List affinity groups by id ... === TestName: test_03_list_aff_grps_by_id | Status : SUCCESS ===
ok
List Affinity Groups by name ... === TestName: test_04_list_aff_grps_by_name | Status : SUCCESS ===
ok
List Affinity Groups by non-existing id ... === TestName: test_05_list_aff_grps_by_non_existing_id | Status : SUCCESS ===
ok
List Affinity Groups by non-existing name ... === TestName: test_06_list_aff_grps_by_non_existing_name | Status : SUCCESS ===
ok
List affinity group should list all for a vms associated with that group ... === TestName: test_07_list_all_vms_in_aff_grp | Status : SUCCESS ===
ok
Update the list of affinityGroups by using affinity groupids ... === TestName: test_01_update_aff_grp_by_ids | Status : SUCCESS ===
ok
Update the list of affinityGroups by using affinity groupnames ... === TestName: test_02_update_aff_grp_by_names | Status : SUCCESS ===
ok
Update the list of affinityGroups for vm which is not associated ... === TestName: test_03_update_aff_grp_for_vm_with_no_aff_grp | Status : SUCCESS ===
ok
Update the list of Affinity Groups to empty list ... SKIP: Skip - Failing - work in progress
Update the list of Affinity Groups on running vm ... === TestName: test_05_update_aff_grp_on_running_vm | Status : SUCCESS ===
ok

----------------------------------------------------------------------
Ran 42 tests in 976.432s

OK (SKIP=1)

* pr/1134:
  CLOUDSTACK-6276 Removing unused parameter in integration test for projects
  CLOUDSTACK-6276 Removing unused parameter in integration test
  CLOUDSTACK-6276 Fixing affinity groups for projects

Signed-off-by: Remi Bergsma <gi...@remi.nl>


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

Branch: refs/heads/4.6
Commit: 9a21873c4a4c68afed47a6fd89ce192f6ec77cfb
Parents: 519ce86 091bb79
Author: Remi Bergsma <gi...@remi.nl>
Authored: Thu Dec 3 20:10:15 2015 +0100
Committer: Remi Bergsma <gi...@remi.nl>
Committed: Thu Dec 3 20:10:16 2015 +0100

----------------------------------------------------------------------
 .../affinity/AffinityGroupResponse.java         |   16 +-
 .../affinity/AffinityGroupService.java          |   32 +-
 .../affinitygroup/CreateAffinityGroupCmd.java   |   38 +-
 .../affinitygroup/DeleteAffinityGroupCmd.java   |   52 +-
 .../affinitygroup/ListAffinityGroupsCmd.java    |   14 +-
 .../apache/cloudstack/query/QueryService.java   |    6 +-
 .../cloud/entity/api/VMEntityManagerImpl.java   |    2 +-
 .../affinity/dao/AffinityGroupDao.java          |    7 +-
 .../affinity/dao/AffinityGroupDaoImpl.java      |    7 +-
 .../dedicated/DedicatedResourceManagerImpl.java |    4 +-
 .../IntegrationTestConfiguration.java           |    2 +-
 .../cloud/acl/AffinityGroupAccessChecker.java   |   22 +-
 .../com/cloud/api/query/QueryManagerImpl.java   |  111 +-
 .../cloud/api/query/vo/AffinityGroupJoinVO.java |   35 +-
 .../configuration/ConfigurationManagerImpl.java |    6 +-
 .../src/com/cloud/user/AccountManagerImpl.java  |   92 +-
 .../affinity/AffinityGroupServiceImpl.java      |  258 ++---
 .../affinity/AffinityApiUnitTest.java           |   13 +-
 .../affinity/AffinityGroupServiceImplTest.java  |  358 ++++++
 setup/db/db/schema-460to461.sql                 |   32 +
 .../component/test_affinity_groups.py           |    2 +-
 .../component/test_affinity_groups_projects.py  | 1082 ++++++++++++++++++
 .../smoke/test_affinity_groups_projects.py      |  188 +++
 tools/marvin/marvin/lib/base.py                 |    4 +-
 24 files changed, 1955 insertions(+), 428 deletions(-)
----------------------------------------------------------------------



[2/5] git commit: updated refs/heads/4.6 to 9a21873

Posted by re...@apache.org.
CLOUDSTACK-6276 Fixing affinity groups for projects


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

Branch: refs/heads/4.6
Commit: c76d31715023070165b30c9c76300c4fdc3da15d
Parents: 92913a1
Author: Patrick Dube <pd...@cloudops.com>
Authored: Fri Nov 27 14:12:28 2015 -0500
Committer: Patrick Dube <pd...@cloudops.com>
Committed: Fri Nov 27 14:43:02 2015 -0500

----------------------------------------------------------------------
 .../affinity/AffinityGroupResponse.java         |   16 +-
 .../affinity/AffinityGroupService.java          |   32 +-
 .../affinitygroup/CreateAffinityGroupCmd.java   |   38 +-
 .../affinitygroup/DeleteAffinityGroupCmd.java   |   52 +-
 .../affinitygroup/ListAffinityGroupsCmd.java    |   14 +-
 .../apache/cloudstack/query/QueryService.java   |    6 +-
 .../cloud/entity/api/VMEntityManagerImpl.java   |    2 +-
 .../affinity/dao/AffinityGroupDao.java          |    7 +-
 .../affinity/dao/AffinityGroupDaoImpl.java      |    7 +-
 .../dedicated/DedicatedResourceManagerImpl.java |    4 +-
 .../IntegrationTestConfiguration.java           |    2 +-
 .../cloud/acl/AffinityGroupAccessChecker.java   |   22 +-
 .../com/cloud/api/query/QueryManagerImpl.java   |  111 +-
 .../cloud/api/query/vo/AffinityGroupJoinVO.java |   35 +-
 .../configuration/ConfigurationManagerImpl.java |    6 +-
 .../src/com/cloud/user/AccountManagerImpl.java  |   92 +-
 .../affinity/AffinityGroupServiceImpl.java      |  258 ++---
 .../affinity/AffinityApiUnitTest.java           |   13 +-
 .../affinity/AffinityGroupServiceImplTest.java  |  358 ++++++
 setup/db/db/schema-460to461.sql                 |   32 +
 .../component/test_affinity_groups_projects.py  | 1083 ++++++++++++++++++
 .../smoke/test_affinity_groups_projects.py      |  188 +++
 tools/marvin/marvin/lib/base.py                 |    4 +-
 23 files changed, 1955 insertions(+), 427 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/cloudstack/blob/c76d3171/api/src/org/apache/cloudstack/affinity/AffinityGroupResponse.java
----------------------------------------------------------------------
diff --git a/api/src/org/apache/cloudstack/affinity/AffinityGroupResponse.java b/api/src/org/apache/cloudstack/affinity/AffinityGroupResponse.java
index aa0b4e6..22842b8 100644
--- a/api/src/org/apache/cloudstack/affinity/AffinityGroupResponse.java
+++ b/api/src/org/apache/cloudstack/affinity/AffinityGroupResponse.java
@@ -56,12 +56,20 @@ public class AffinityGroupResponse extends BaseResponse implements ControlledVie
     @Param(description = "the domain name of the affinity group")
     private String domainName;
 
+    @SerializedName(ApiConstants.PROJECT_ID)
+    @Param(description = "the project ID of the affinity group")
+    private String projectId;
+
+    @SerializedName(ApiConstants.PROJECT)
+    @Param(description = "the project name of the affinity group")
+    private String projectName;
+
     @SerializedName(ApiConstants.TYPE)
     @Param(description = "the type of the affinity group")
     private String type;
 
     @SerializedName("virtualmachineIds")
-    @Param(description = "virtual machine Ids associated with this affinity group ")
+    @Param(description = "virtual machine IDs associated with this affinity group")
     private List<String> vmIdList;
 
     public AffinityGroupResponse() {
@@ -134,14 +142,12 @@ public class AffinityGroupResponse extends BaseResponse implements ControlledVie
 
     @Override
     public void setProjectId(String projectId) {
-        // TODO Auto-generated method stub
-
+        this.projectId = projectId;
     }
 
     @Override
     public void setProjectName(String projectName) {
-        // TODO Auto-generated method stub
-
+        this.projectName = projectName;
     }
 
     public void setVMIdList(List<String> vmIdList) {

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/c76d3171/api/src/org/apache/cloudstack/affinity/AffinityGroupService.java
----------------------------------------------------------------------
diff --git a/api/src/org/apache/cloudstack/affinity/AffinityGroupService.java b/api/src/org/apache/cloudstack/affinity/AffinityGroupService.java
index 8ffc3b2..018e5f5 100644
--- a/api/src/org/apache/cloudstack/affinity/AffinityGroupService.java
+++ b/api/src/org/apache/cloudstack/affinity/AffinityGroupService.java
@@ -18,47 +18,36 @@ package org.apache.cloudstack.affinity;
 
 import java.util.List;
 
+import org.apache.cloudstack.api.command.user.affinitygroup.CreateAffinityGroupCmd;
+
 import com.cloud.uservm.UserVm;
-import com.cloud.utils.Pair;
 
 public interface AffinityGroupService {
 
     /**
      * Creates an affinity/anti-affinity group for the given account/domain.
      *
-     * @param account
+     * @param accountName
+     * @param projectId
      * @param domainId
-     * @param name
-     * @param type
+     * @param affinityGroupName
+     * @param affinityGroupType
      * @param description
      * @return AffinityGroup
      */
+    AffinityGroup createAffinityGroup(String accountName, Long projectId, Long domainId, String affinityGroupName, String affinityGroupType, String description);
 
-    AffinityGroup createAffinityGroup(String account, Long domainId, String affinityGroupName, String affinityGroupType, String description);
+    AffinityGroup createAffinityGroup(CreateAffinityGroupCmd createAffinityGroupCmd);
 
     /**
      * Creates an affinity/anti-affinity group.
      *
      * @param affinityGroupId
-     * @param account
-     * @param domainId
-     * @param affinityGroupName
-     */
-    boolean deleteAffinityGroup(Long affinityGroupId, String account, Long domainId, String affinityGroupName);
-
-    /** Lists Affinity Groups in your account
-     * @param account
+     * @param accountName
      * @param domainId
-     * @param affinityGroupId
      * @param affinityGroupName
-     * @param affinityGroupType
-     * @param vmId
-     * @param startIndex
-     * @param pageSize
-     * @return
      */
-    Pair<List<? extends AffinityGroup>, Integer> listAffinityGroups(Long affinityGroupId, String affinityGroupName, String affinityGroupType, Long vmId, Long startIndex,
-        Long pageSize);
+    boolean deleteAffinityGroup(Long affinityGroupId, String accountName, Long projectId, Long domainId, String affinityGroupName);
 
     /**
      * List group types available in deployment
@@ -77,6 +66,5 @@ public interface AffinityGroupService {
 
     boolean isAffinityGroupAvailableInDomain(long affinityGroupId, long domainId);
 
-    AffinityGroup createAffinityGroupInternal(String account, Long domainId, String affinityGroupName, String affinityGroupType, String description);
 
 }

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/c76d3171/api/src/org/apache/cloudstack/api/command/user/affinitygroup/CreateAffinityGroupCmd.java
----------------------------------------------------------------------
diff --git a/api/src/org/apache/cloudstack/api/command/user/affinitygroup/CreateAffinityGroupCmd.java b/api/src/org/apache/cloudstack/api/command/user/affinitygroup/CreateAffinityGroupCmd.java
index 96d8bec..8cc3d69 100644
--- a/api/src/org/apache/cloudstack/api/command/user/affinitygroup/CreateAffinityGroupCmd.java
+++ b/api/src/org/apache/cloudstack/api/command/user/affinitygroup/CreateAffinityGroupCmd.java
@@ -17,7 +17,6 @@
 package org.apache.cloudstack.api.command.user.affinitygroup;
 
 import org.apache.log4j.Logger;
-
 import org.apache.cloudstack.affinity.AffinityGroup;
 import org.apache.cloudstack.affinity.AffinityGroupResponse;
 import org.apache.cloudstack.api.APICommand;
@@ -28,6 +27,7 @@ import org.apache.cloudstack.api.BaseAsyncCreateCmd;
 import org.apache.cloudstack.api.Parameter;
 import org.apache.cloudstack.api.ServerApiException;
 import org.apache.cloudstack.api.response.DomainResponse;
+import org.apache.cloudstack.api.response.ProjectResponse;
 import org.apache.cloudstack.context.CallContext;
 
 import com.cloud.event.EventTypes;
@@ -54,6 +54,12 @@ public class CreateAffinityGroupCmd extends BaseAsyncCreateCmd {
                entityType = DomainResponse.class)
     private Long domainId;
 
+    @Parameter(name = ApiConstants.PROJECT_ID,
+               type = CommandType.UUID,
+               entityType = ProjectResponse.class,
+               description = "create affinity group for project")
+    private Long projectId;
+
     @Parameter(name = ApiConstants.DESCRIPTION, type = CommandType.STRING, description = "optional description of the affinity group")
     private String description;
 
@@ -90,6 +96,10 @@ public class CreateAffinityGroupCmd extends BaseAsyncCreateCmd {
         return affinityGroupType;
     }
 
+    public Long getProjectId() {
+        return projectId;
+    }
+
     // ///////////////////////////////////////////////////
     // ///////////// API Implementation///////////////////
     // ///////////////////////////////////////////////////
@@ -101,23 +111,17 @@ public class CreateAffinityGroupCmd extends BaseAsyncCreateCmd {
 
     @Override
     public long getEntityOwnerId() {
-        Account account = CallContext.current().getCallingAccount();
-        if ((account == null) || _accountService.isAdmin(account.getId())) {
-            if ((domainId != null) && (accountName != null)) {
-                Account userAccount = _responseGenerator.findAccountByNameDomain(accountName, domainId);
-                if (userAccount != null) {
-                    return userAccount.getId();
-                }
-            }
-        }
+        Account caller = CallContext.current().getCallingAccount();
 
-        if (account != null) {
-            return account.getId();
+        //For domain wide affinity groups (if the affinity group processor type allows it)
+        if(projectId == null && domainId != null && accountName == null && _accountService.isRootAdmin(caller.getId())){
+            return Account.ACCOUNT_ID_SYSTEM;
         }
-
-        return Account.ACCOUNT_ID_SYSTEM; // no account info given, parent this
-                                          // command to SYSTEM so ERROR events
-                                          // are tracked
+        Account owner = _accountService.finalizeOwner(caller, accountName, domainId, projectId);
+        if(owner == null){
+            return caller.getAccountId();
+        }
+        return owner.getAccountId();
     }
 
     @Override
@@ -134,7 +138,7 @@ public class CreateAffinityGroupCmd extends BaseAsyncCreateCmd {
 
     @Override
     public void create() throws ResourceAllocationException {
-        AffinityGroup result = _affinityGroupService.createAffinityGroup(accountName, domainId, affinityGroupName, affinityGroupType, description);
+        AffinityGroup result = _affinityGroupService.createAffinityGroup(this);
         if (result != null) {
             setEntityId(result.getId());
             setEntityUuid(result.getUuid());

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/c76d3171/api/src/org/apache/cloudstack/api/command/user/affinitygroup/DeleteAffinityGroupCmd.java
----------------------------------------------------------------------
diff --git a/api/src/org/apache/cloudstack/api/command/user/affinitygroup/DeleteAffinityGroupCmd.java b/api/src/org/apache/cloudstack/api/command/user/affinitygroup/DeleteAffinityGroupCmd.java
index 4eeff06..e8884b4 100644
--- a/api/src/org/apache/cloudstack/api/command/user/affinitygroup/DeleteAffinityGroupCmd.java
+++ b/api/src/org/apache/cloudstack/api/command/user/affinitygroup/DeleteAffinityGroupCmd.java
@@ -17,8 +17,8 @@
 package org.apache.cloudstack.api.command.user.affinitygroup;
 
 
+import org.apache.cloudstack.api.response.ProjectResponse;
 import org.apache.log4j.Logger;
-
 import org.apache.cloudstack.acl.SecurityChecker.AccessType;
 import org.apache.cloudstack.affinity.AffinityGroup;
 import org.apache.cloudstack.affinity.AffinityGroupResponse;
@@ -35,7 +35,6 @@ import org.apache.cloudstack.api.response.SuccessResponse;
 import org.apache.cloudstack.context.CallContext;
 
 import com.cloud.event.EventTypes;
-import com.cloud.exception.InvalidParameterValueException;
 import com.cloud.user.Account;
 
 @APICommand(name = "deleteAffinityGroup", description = "Deletes affinity group", responseObject = SuccessResponse.class, entityType = {AffinityGroup.class},
@@ -67,6 +66,9 @@ public class DeleteAffinityGroupCmd extends BaseAsyncCmd {
     @Parameter(name = ApiConstants.NAME, type = CommandType.STRING, description = "The name of the affinity group. Mutually exclusive with ID parameter")
     private String name;
 
+    @Parameter(name = ApiConstants.PROJECT_ID, type = CommandType.UUID, description = "the project of the affinity group", entityType = ProjectResponse.class)
+    private Long projectId;
+
     /////////////////////////////////////////////////////
     /////////////////// Accessors ///////////////////////
     /////////////////////////////////////////////////////
@@ -79,22 +81,11 @@ public class DeleteAffinityGroupCmd extends BaseAsyncCmd {
         return domainId;
     }
 
-    public Long getId() {
-        if (id != null && name != null) {
-            throw new InvalidParameterValueException("name and id parameters are mutually exclusive");
-        }
-
-        if (name != null) {
-            id = _responseGenerator.getAffinityGroupId(name, getEntityOwnerId());
-            if (id == null) {
-                throw new InvalidParameterValueException("Unable to find affinity group by name " + name + " for the account ID=" + getEntityOwnerId());
-            }
-        }
-
-        if (id == null) {
-            throw new InvalidParameterValueException("Either ID or name parameter is required by deleteAffinityGroup command");
-        }
+    public Long getProjectId() {
+        return projectId;
+    }
 
+    public Long getId() {
         return id;
     }
 
@@ -109,29 +100,22 @@ public class DeleteAffinityGroupCmd extends BaseAsyncCmd {
 
     @Override
     public long getEntityOwnerId() {
-        Account account = CallContext.current().getCallingAccount();
-        if ((account == null) || _accountService.isAdmin(account.getId())) {
-            if ((domainId != null) && (accountName != null)) {
-                Account userAccount = _responseGenerator.findAccountByNameDomain(accountName, domainId);
-                if (userAccount != null) {
-                    return userAccount.getId();
-                }
-            }
-        }
+        Account caller = CallContext.current().getCallingAccount();
 
-        if (account != null) {
-            return account.getId();
+        //For domain wide affinity groups (if the affinity group processor type allows it)
+        if(projectId == null && domainId != null && accountName == null && _accountService.isRootAdmin(caller.getId())){
+            return Account.ACCOUNT_ID_SYSTEM;
         }
-
-        return Account.ACCOUNT_ID_SYSTEM; // no account info given, parent this
-                                          // command to SYSTEM so ERROR events
-                                          // are tracked
-
+        Account owner = _accountService.finalizeOwner(caller, accountName, domainId, projectId);
+        if(owner == null){
+            return caller.getAccountId();
+        }
+        return owner.getAccountId();
     }
 
     @Override
     public void execute() {
-        boolean result = _affinityGroupService.deleteAffinityGroup(id, accountName, domainId, name);
+        boolean result = _affinityGroupService.deleteAffinityGroup(id, accountName, projectId, domainId, name);
         if (result) {
             SuccessResponse response = new SuccessResponse(getCommandName());
             setResponseObject(response);

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/c76d3171/api/src/org/apache/cloudstack/api/command/user/affinitygroup/ListAffinityGroupsCmd.java
----------------------------------------------------------------------
diff --git a/api/src/org/apache/cloudstack/api/command/user/affinitygroup/ListAffinityGroupsCmd.java b/api/src/org/apache/cloudstack/api/command/user/affinitygroup/ListAffinityGroupsCmd.java
index 41ed6fb..fa7935b 100644
--- a/api/src/org/apache/cloudstack/api/command/user/affinitygroup/ListAffinityGroupsCmd.java
+++ b/api/src/org/apache/cloudstack/api/command/user/affinitygroup/ListAffinityGroupsCmd.java
@@ -23,14 +23,14 @@ import org.apache.cloudstack.affinity.AffinityGroupResponse;
 import org.apache.cloudstack.api.APICommand;
 import org.apache.cloudstack.api.ApiCommandJobType;
 import org.apache.cloudstack.api.ApiConstants;
-import org.apache.cloudstack.api.BaseListAccountResourcesCmd;
+import org.apache.cloudstack.api.BaseListProjectAndAccountResourcesCmd;
 import org.apache.cloudstack.api.Parameter;
 import org.apache.cloudstack.api.response.ListResponse;
 import org.apache.cloudstack.api.response.UserVmResponse;
 
 @APICommand(name = "listAffinityGroups", description = "Lists affinity groups", responseObject = AffinityGroupResponse.class, entityType = {AffinityGroup.class},
         requestHasSensitiveInfo = false, responseHasSensitiveInfo = false)
-public class ListAffinityGroupsCmd extends BaseListAccountResourcesCmd {
+public class ListAffinityGroupsCmd extends BaseListProjectAndAccountResourcesCmd {
     public static final Logger s_logger = Logger.getLogger(ListAffinityGroupsCmd.class.getName());
 
     private static final String s_name = "listaffinitygroupsresponse";
@@ -69,6 +69,10 @@ public class ListAffinityGroupsCmd extends BaseListAccountResourcesCmd {
         return id;
     }
 
+    public String getAffinityGroupType() {
+        return affinityGroupType;
+    }
+
     /////////////////////////////////////////////////////
     /////////////// API Implementation///////////////////
     /////////////////////////////////////////////////////
@@ -80,13 +84,9 @@ public class ListAffinityGroupsCmd extends BaseListAccountResourcesCmd {
 
     @Override
     public void execute() {
-
-        ListResponse<AffinityGroupResponse> response = _queryService.listAffinityGroups(id, affinityGroupName,
-                affinityGroupType, virtualMachineId, getAccountName(), getDomainId(), isRecursive(),
-                listAll(), getStartIndex(), getPageSizeVal(), getKeyword());
+        ListResponse<AffinityGroupResponse> response = _queryService.searchForAffinityGroups(this);
         response.setResponseName(getCommandName());
         setResponseObject(response);
-
     }
 
     @Override

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/c76d3171/api/src/org/apache/cloudstack/query/QueryService.java
----------------------------------------------------------------------
diff --git a/api/src/org/apache/cloudstack/query/QueryService.java b/api/src/org/apache/cloudstack/query/QueryService.java
index 1a5ac11..de9fbb5 100644
--- a/api/src/org/apache/cloudstack/query/QueryService.java
+++ b/api/src/org/apache/cloudstack/query/QueryService.java
@@ -31,6 +31,7 @@ import org.apache.cloudstack.api.command.admin.storage.ListStorageTagsCmd;
 import org.apache.cloudstack.api.command.admin.user.ListUsersCmd;
 import org.apache.cloudstack.api.command.user.account.ListAccountsCmd;
 import org.apache.cloudstack.api.command.user.account.ListProjectAccountsCmd;
+import org.apache.cloudstack.api.command.user.affinitygroup.ListAffinityGroupsCmd;
 import org.apache.cloudstack.api.command.user.event.ListEventsCmd;
 import org.apache.cloudstack.api.command.user.iso.ListIsosCmd;
 import org.apache.cloudstack.api.command.user.job.ListAsyncJobsCmd;
@@ -131,9 +132,7 @@ public interface QueryService {
 
     ListResponse<TemplateResponse> listIsos(ListIsosCmd cmd);
 
-    ListResponse<AffinityGroupResponse> listAffinityGroups(Long affinityGroupId, String affinityGroupName,
-            String affinityGroupType, Long vmId, String accountName, Long domainId, boolean isRecursive,
-            boolean listAll, Long startIndex, Long pageSize, String keyword);
+    ListResponse<AffinityGroupResponse> searchForAffinityGroups(ListAffinityGroupsCmd cmd);
 
     List<ResourceDetailResponse> listResourceDetails(ListResourceDetailsCmd cmd);
 
@@ -142,5 +141,4 @@ public interface QueryService {
     ListResponse<StorageTagResponse> searchForStorageTags(ListStorageTagsCmd cmd);
 
     ListResponse<HostTagResponse> searchForHostTags(ListHostTagsCmd cmd);
-
 }

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/c76d3171/engine/orchestration/src/org/apache/cloudstack/engine/cloud/entity/api/VMEntityManagerImpl.java
----------------------------------------------------------------------
diff --git a/engine/orchestration/src/org/apache/cloudstack/engine/cloud/entity/api/VMEntityManagerImpl.java b/engine/orchestration/src/org/apache/cloudstack/engine/cloud/entity/api/VMEntityManagerImpl.java
index b1ac2f8..829ed10 100644
--- a/engine/orchestration/src/org/apache/cloudstack/engine/cloud/entity/api/VMEntityManagerImpl.java
+++ b/engine/orchestration/src/org/apache/cloudstack/engine/cloud/entity/api/VMEntityManagerImpl.java
@@ -192,7 +192,7 @@ public class VMEntityManagerImpl implements VMEntityManager {
             try {
                 dest = _dpMgr.planDeployment(vmProfile, plan, exclude, plannerToUse);
             } catch (AffinityConflictException e) {
-                throw new CloudRuntimeException("Unable to create deployment, affinity rules associted to the VM conflict");
+                throw new CloudRuntimeException("Unable to create deployment, affinity rules associated to the VM conflict");
             }
 
             if (dest != null) {

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/c76d3171/engine/schema/src/org/apache/cloudstack/affinity/dao/AffinityGroupDao.java
----------------------------------------------------------------------
diff --git a/engine/schema/src/org/apache/cloudstack/affinity/dao/AffinityGroupDao.java b/engine/schema/src/org/apache/cloudstack/affinity/dao/AffinityGroupDao.java
index 76a8144..010720b 100644
--- a/engine/schema/src/org/apache/cloudstack/affinity/dao/AffinityGroupDao.java
+++ b/engine/schema/src/org/apache/cloudstack/affinity/dao/AffinityGroupDao.java
@@ -18,7 +18,6 @@ package org.apache.cloudstack.affinity.dao;
 
 import java.util.List;
 
-import org.apache.cloudstack.affinity.AffinityGroup;
 import org.apache.cloudstack.affinity.AffinityGroupVO;
 
 import com.cloud.utils.db.GenericDao;
@@ -34,9 +33,9 @@ public interface AffinityGroupDao extends GenericDao<AffinityGroupVO, Long> {
 
     int removeByAccountId(long accountId);
 
-    AffinityGroup findDomainLevelGroupByName(Long domainId, String affinityGroupName);
+    AffinityGroupVO findDomainLevelGroupByName(Long domainId, String affinityGroupName);
 
-    AffinityGroup findByAccountAndType(Long accountId, String string);
+    AffinityGroupVO findByAccountAndType(Long accountId, String string);
 
-    AffinityGroup findDomainLevelGroupByType(Long domainId, String string);
+    AffinityGroupVO findDomainLevelGroupByType(Long domainId, String string);
 }

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/c76d3171/engine/schema/src/org/apache/cloudstack/affinity/dao/AffinityGroupDaoImpl.java
----------------------------------------------------------------------
diff --git a/engine/schema/src/org/apache/cloudstack/affinity/dao/AffinityGroupDaoImpl.java b/engine/schema/src/org/apache/cloudstack/affinity/dao/AffinityGroupDaoImpl.java
index c63b04b..1fda52e 100644
--- a/engine/schema/src/org/apache/cloudstack/affinity/dao/AffinityGroupDaoImpl.java
+++ b/engine/schema/src/org/apache/cloudstack/affinity/dao/AffinityGroupDaoImpl.java
@@ -23,7 +23,6 @@ import javax.ejb.Local;
 import javax.inject.Inject;
 
 import org.apache.cloudstack.acl.ControlledEntity;
-import org.apache.cloudstack.affinity.AffinityGroup;
 import org.apache.cloudstack.affinity.AffinityGroupDomainMapVO;
 import org.apache.cloudstack.affinity.AffinityGroupVO;
 
@@ -136,7 +135,7 @@ public class AffinityGroupDaoImpl extends GenericDaoBase<AffinityGroupVO, Long>
     }
 
     @Override
-    public AffinityGroup findDomainLevelGroupByName(Long domainId, String affinityGroupName) {
+    public AffinityGroupVO findDomainLevelGroupByName(Long domainId, String affinityGroupName) {
         SearchCriteria<AffinityGroupVO> sc = DomainLevelNameSearch.create();
         sc.setParameters("aclType", ControlledEntity.ACLType.Domain);
         sc.setParameters("name", affinityGroupName);
@@ -145,7 +144,7 @@ public class AffinityGroupDaoImpl extends GenericDaoBase<AffinityGroupVO, Long>
     }
 
     @Override
-    public AffinityGroup findByAccountAndType(Long accountId, String type) {
+    public AffinityGroupVO findByAccountAndType(Long accountId, String type) {
         SearchCriteria<AffinityGroupVO> sc = AccountIdTypeSearch.create();
         sc.setParameters("accountId", accountId);
         sc.setParameters("type", type);
@@ -154,7 +153,7 @@ public class AffinityGroupDaoImpl extends GenericDaoBase<AffinityGroupVO, Long>
     }
 
     @Override
-    public AffinityGroup findDomainLevelGroupByType(Long domainId, String type) {
+    public AffinityGroupVO findDomainLevelGroupByType(Long domainId, String type) {
         SearchCriteria<AffinityGroupVO> sc = DomainLevelTypeSearch.create();
         sc.setParameters("aclType", ControlledEntity.ACLType.Domain);
         sc.setParameters("type", type);

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/c76d3171/plugins/dedicated-resources/src/org/apache/cloudstack/dedicated/DedicatedResourceManagerImpl.java
----------------------------------------------------------------------
diff --git a/plugins/dedicated-resources/src/org/apache/cloudstack/dedicated/DedicatedResourceManagerImpl.java b/plugins/dedicated-resources/src/org/apache/cloudstack/dedicated/DedicatedResourceManagerImpl.java
index 1e584c3..35bcfc6 100644
--- a/plugins/dedicated-resources/src/org/apache/cloudstack/dedicated/DedicatedResourceManagerImpl.java
+++ b/plugins/dedicated-resources/src/org/apache/cloudstack/dedicated/DedicatedResourceManagerImpl.java
@@ -639,7 +639,7 @@ public class DedicatedResourceManagerImpl implements DedicatedService {
             affinityGroupName = "DedicatedGrp-domain-" + domainName;
         }
 
-        group = _affinityGroupService.createAffinityGroupInternal(accountName, domainId, affinityGroupName, "ExplicitDedication", "dedicated resources group");
+        group = _affinityGroupService.createAffinityGroup(accountName, null, domainId, affinityGroupName, "ExplicitDedication", "dedicated resources group");
 
         return group;
 
@@ -948,7 +948,7 @@ public class DedicatedResourceManagerImpl implements DedicatedService {
             List<DedicatedResourceVO> resourcesInGroup = _dedicatedDao.listByAffinityGroupId(resource.getAffinityGroupId());
             if (resourcesInGroup.isEmpty()) {
                 // delete the group
-                _affinityGroupService.deleteAffinityGroup(resource.getAffinityGroupId(), null, null, null);
+                _affinityGroupService.deleteAffinityGroup(resource.getAffinityGroupId(), null, null, null, null);
             }
 
         }

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/c76d3171/plugins/network-elements/juniper-contrail/test/org/apache/cloudstack/network/contrail/management/IntegrationTestConfiguration.java
----------------------------------------------------------------------
diff --git a/plugins/network-elements/juniper-contrail/test/org/apache/cloudstack/network/contrail/management/IntegrationTestConfiguration.java b/plugins/network-elements/juniper-contrail/test/org/apache/cloudstack/network/contrail/management/IntegrationTestConfiguration.java
index 954a37e..77abb65 100644
--- a/plugins/network-elements/juniper-contrail/test/org/apache/cloudstack/network/contrail/management/IntegrationTestConfiguration.java
+++ b/plugins/network-elements/juniper-contrail/test/org/apache/cloudstack/network/contrail/management/IntegrationTestConfiguration.java
@@ -389,7 +389,7 @@ public class IntegrationTestConfiguration {
                 }
             });
             Mockito.when(
-                mock.createAffinityGroupInternal(Matchers.any(String.class), Matchers.any(Long.class), Matchers.any(String.class), Matchers.any(String.class),
+                mock.createAffinityGroup(Matchers.any(String.class), Matchers.any(Long.class), Matchers.any(Long.class), Matchers.any(String.class), Matchers.any(String.class),
                     Matchers.any(String.class))).thenReturn(gmock);
         } catch (Exception e) {
             e.printStackTrace();

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/c76d3171/server/src/com/cloud/acl/AffinityGroupAccessChecker.java
----------------------------------------------------------------------
diff --git a/server/src/com/cloud/acl/AffinityGroupAccessChecker.java b/server/src/com/cloud/acl/AffinityGroupAccessChecker.java
index 57f7b37..c836aea 100644
--- a/server/src/com/cloud/acl/AffinityGroupAccessChecker.java
+++ b/server/src/com/cloud/acl/AffinityGroupAccessChecker.java
@@ -19,17 +19,19 @@ package com.cloud.acl;
 import javax.ejb.Local;
 import javax.inject.Inject;
 
-import org.springframework.stereotype.Component;
-
 import org.apache.cloudstack.acl.ControlledEntity;
 import org.apache.cloudstack.acl.ControlledEntity.ACLType;
 import org.apache.cloudstack.acl.SecurityChecker;
 import org.apache.cloudstack.affinity.AffinityGroup;
 import org.apache.cloudstack.affinity.AffinityGroupService;
 import org.apache.cloudstack.affinity.dao.AffinityGroupDomainMapDao;
+import org.springframework.stereotype.Component;
 
 import com.cloud.domain.DomainVO;
 import com.cloud.exception.PermissionDeniedException;
+import com.cloud.projects.ProjectVO;
+import com.cloud.projects.dao.ProjectAccountDao;
+import com.cloud.projects.dao.ProjectDao;
 import com.cloud.user.Account;
 import com.cloud.user.AccountManager;
 import com.cloud.utils.exception.CloudRuntimeException;
@@ -44,6 +46,10 @@ public class AffinityGroupAccessChecker extends DomainChecker {
     AccountManager _accountMgr;
     @Inject
     AffinityGroupDomainMapDao _affinityGroupDomainMapDao;
+    @Inject
+    ProjectDao _projectDao;
+    @Inject
+    ProjectAccountDao _projectAccountDao;
 
     @Override
     public boolean checkAccess(Account caller, ControlledEntity entity, AccessType accessType) throws PermissionDeniedException {
@@ -51,8 +57,7 @@ public class AffinityGroupAccessChecker extends DomainChecker {
             AffinityGroup group = (AffinityGroup)entity;
 
             if (_affinityGroupService.isAdminControlledGroup(group)) {
-                if (accessType != null && accessType == AccessType.OperateEntry
-                        && !_accountMgr.isRootAdmin(caller.getId())) {
+                if (accessType == AccessType.OperateEntry && !_accountMgr.isRootAdmin(caller.getId())) {
                     throw new PermissionDeniedException(caller + " does not have permission to operate with resource "
                             + entity);
                 }
@@ -72,6 +77,15 @@ public class AffinityGroupAccessChecker extends DomainChecker {
             } else {
                 //acl_type account
                 if (caller.getId() != group.getAccountId()) {
+                  //check if the group belongs to a project
+                    ProjectVO project = _projectDao.findByProjectAccountId(group.getAccountId());
+                    if (project != null) {
+                        if (AccessType.ModifyProject.equals(accessType) && _projectAccountDao.canModifyProjectAccount(caller.getId(), group.getAccountId())) {
+                            return true;
+                        } else if (!AccessType.ModifyProject.equals(accessType) && _projectAccountDao.canAccessProjectAccount(caller.getId(), group.getAccountId())) {
+                            return true;
+                        }
+                    }
                     throw new PermissionDeniedException(caller + " does not have permission to operate with resource " + entity);
                 } else {
                     return true;

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/c76d3171/server/src/com/cloud/api/query/QueryManagerImpl.java
----------------------------------------------------------------------
diff --git a/server/src/com/cloud/api/query/QueryManagerImpl.java b/server/src/com/cloud/api/query/QueryManagerImpl.java
index f853b67..d64b2ac 100644
--- a/server/src/com/cloud/api/query/QueryManagerImpl.java
+++ b/server/src/com/cloud/api/query/QueryManagerImpl.java
@@ -26,9 +26,6 @@ import java.util.Set;
 import javax.ejb.Local;
 import javax.inject.Inject;
 
-import com.cloud.utils.StringUtils;
-import com.cloud.vm.VMInstanceVO;
-import com.cloud.vm.dao.VMInstanceDao;
 import org.apache.cloudstack.acl.ControlledEntity.ACLType;
 import org.apache.cloudstack.affinity.AffinityGroupDomainMapVO;
 import org.apache.cloudstack.affinity.AffinityGroupResponse;
@@ -57,6 +54,7 @@ import org.apache.cloudstack.api.command.admin.volume.ListVolumesCmdByAdmin;
 import org.apache.cloudstack.api.command.admin.zone.ListZonesCmdByAdmin;
 import org.apache.cloudstack.api.command.user.account.ListAccountsCmd;
 import org.apache.cloudstack.api.command.user.account.ListProjectAccountsCmd;
+import org.apache.cloudstack.api.command.user.affinitygroup.ListAffinityGroupsCmd;
 import org.apache.cloudstack.api.command.user.event.ListEventsCmd;
 import org.apache.cloudstack.api.command.user.iso.ListIsosCmd;
 import org.apache.cloudstack.api.command.user.job.ListAsyncJobsCmd;
@@ -196,7 +194,6 @@ import com.cloud.storage.Storage.TemplateType;
 import com.cloud.storage.VMTemplateVO;
 import com.cloud.storage.Volume;
 import com.cloud.storage.dao.VMTemplateDao;
-import com.cloud.storage.dao.VolumeDetailsDao;
 import com.cloud.tags.ResourceTagVO;
 import com.cloud.tags.dao.ResourceTagDao;
 import com.cloud.template.VirtualMachineTemplate.State;
@@ -207,6 +204,7 @@ import com.cloud.user.DomainManager;
 import com.cloud.user.dao.AccountDao;
 import com.cloud.utils.DateUtil;
 import com.cloud.utils.Pair;
+import com.cloud.utils.StringUtils;
 import com.cloud.utils.Ternary;
 import com.cloud.utils.component.ManagerBase;
 import com.cloud.utils.db.Filter;
@@ -217,11 +215,12 @@ import com.cloud.utils.db.SearchCriteria.Func;
 import com.cloud.utils.db.SearchCriteria.Op;
 import com.cloud.vm.DomainRouterVO;
 import com.cloud.vm.UserVmVO;
+import com.cloud.vm.VMInstanceVO;
 import com.cloud.vm.VirtualMachine;
 import com.cloud.vm.dao.DomainRouterDao;
-import com.cloud.vm.dao.NicDetailsDao;
 import com.cloud.vm.dao.UserVmDao;
 import com.cloud.vm.dao.UserVmDetailsDao;
+import com.cloud.vm.dao.VMInstanceDao;
 
 @Component
 @Local(value = {QueryService.class})
@@ -229,6 +228,8 @@ public class QueryManagerImpl extends ManagerBase implements QueryService, Confi
 
     public static final Logger s_logger = Logger.getLogger(QueryManagerImpl.class);
 
+    private static final String ID_FIELD = "id";
+
     @Inject
     private AccountManager _accountMgr;
 
@@ -332,12 +333,6 @@ public class QueryManagerImpl extends ManagerBase implements QueryService, Confi
     private DomainRouterDao _routerDao;
 
     @Inject
-    private VolumeDetailsDao _volumeDetailDao;
-
-    @Inject
-    private NicDetailsDao _nicDetailDao;
-
-    @Inject
     UserVmDetailsDao _userVmDetailDao;
 
     @Inject
@@ -375,11 +370,11 @@ public class QueryManagerImpl extends ManagerBase implements QueryService, Confi
     @Inject
     AffinityGroupDomainMapDao _affinityGroupDomainMapDao;
 
-
     @Inject NetworkDetailsDao _networkDetailsDao;
 
     @Inject
     ResourceTagDao _resourceTagDao;
+
     @Inject
     DataStoreManager dataStoreManager;
 
@@ -3395,55 +3390,60 @@ public class QueryManagerImpl extends ManagerBase implements QueryService, Confi
                 cmd.listInReadyState(), permittedAccounts, caller, listProjectResourcesCriteria, tags, showRemovedISO);
     }
 
-
     @Override
-    public ListResponse<AffinityGroupResponse> listAffinityGroups(Long affinityGroupId, String affinityGroupName,
-            String affinityGroupType, Long vmId, String accountName, Long domainId, boolean isRecursive,
-            boolean listAll, Long startIndex, Long pageSize, String keyword) {
-        Pair<List<AffinityGroupJoinVO>, Integer> result = listAffinityGroupsInternal(affinityGroupId,
-                affinityGroupName, affinityGroupType, vmId, accountName, domainId, isRecursive, listAll, startIndex,
-                pageSize, keyword);
+    public ListResponse<AffinityGroupResponse> searchForAffinityGroups(ListAffinityGroupsCmd cmd) {
+        Pair<List<AffinityGroupJoinVO>, Integer> result = searchForAffinityGroupsInternal(cmd);
         ListResponse<AffinityGroupResponse> response = new ListResponse<AffinityGroupResponse>();
         List<AffinityGroupResponse> agResponses = ViewResponseHelper.createAffinityGroupResponses(result.first());
         response.setResponses(agResponses, result.second());
         return response;
     }
 
-    public Pair<List<AffinityGroupJoinVO>, Integer> listAffinityGroupsInternal(Long affinityGroupId,
-            String affinityGroupName, String affinityGroupType, Long vmId, String accountName, Long domainId,
-            boolean isRecursive, boolean listAll, Long startIndex, Long pageSize, String keyword) {
+    public Pair<List<AffinityGroupJoinVO>, Integer> searchForAffinityGroupsInternal(ListAffinityGroupsCmd cmd) {
 
-        Account caller = CallContext.current().getCallingAccount();
+        final Long affinityGroupId = cmd.getId();
+        final String affinityGroupName = cmd.getAffinityGroupName();
+        final String affinityGroupType = cmd.getAffinityGroupType();
+        final Long vmId = cmd.getVirtualMachineId();
+        final String accountName = cmd.getAccountName();
+        Long domainId = cmd.getDomainId();
+        final Long projectId = cmd.getProjectId();
+        Boolean isRecursive = cmd.isRecursive();
+        final Boolean listAll = cmd.listAll();
+        final Long startIndex = cmd.getStartIndex();
+        final Long pageSize = cmd.getPageSizeVal();
+        final String keyword = cmd.getKeyword();
 
-        caller.getAccountId();
+        Account caller = CallContext.current().getCallingAccount();
 
         if (vmId != null) {
             UserVmVO userVM = _userVmDao.findById(vmId);
             if (userVM == null) {
-                throw new InvalidParameterValueException("Unable to list affinity groups for virtual machine instance "
-                        + vmId + "; instance not found.");
+                throw new InvalidParameterValueException("Unable to list affinity groups for virtual machine instance " + vmId + "; instance not found.");
             }
             _accountMgr.checkAccess(caller, null, true, userVM);
             return listAffinityGroupsByVM(vmId.longValue(), startIndex, pageSize);
         }
 
         List<Long> permittedAccounts = new ArrayList<Long>();
-        Ternary<Long, Boolean, ListProjectResourcesCriteria> domainIdRecursiveListProject = new Ternary<Long, Boolean, ListProjectResourcesCriteria>(
-                domainId, isRecursive, null);
-        _accountMgr.buildACLSearchParameters(caller, affinityGroupId, accountName, null, permittedAccounts,
-                domainIdRecursiveListProject, listAll, true);
-        domainId = domainIdRecursiveListProject.first();
-        isRecursive = domainIdRecursiveListProject.second();
-        ListProjectResourcesCriteria listProjectResourcesCriteria = domainIdRecursiveListProject.third();
+        Ternary<Long, Boolean, ListProjectResourcesCriteria> ternary = new Ternary<Long, Boolean, ListProjectResourcesCriteria>(domainId, isRecursive, null);
+
+        _accountMgr.buildACLSearchParameters(caller, affinityGroupId, accountName, projectId, permittedAccounts, ternary, listAll, false);
+
+        domainId = ternary.first();
+        isRecursive = ternary.second();
+        ListProjectResourcesCriteria listProjectResourcesCriteria = ternary.third();
+
+        Filter searchFilter = new Filter(AffinityGroupJoinVO.class, ID_FIELD, true, startIndex, pageSize);
 
-        Filter searchFilter = new Filter(AffinityGroupJoinVO.class, "id", true, startIndex, pageSize);
-        SearchCriteria<AffinityGroupJoinVO> sc = buildAffinityGroupSearchCriteria(domainId, isRecursive,
-                permittedAccounts, listProjectResourcesCriteria, affinityGroupId, affinityGroupName, affinityGroupType, keyword);
+        SearchCriteria<AffinityGroupJoinVO> sc = buildAffinityGroupSearchCriteria(domainId, isRecursive, permittedAccounts, listProjectResourcesCriteria, affinityGroupId,
+                affinityGroupName, affinityGroupType, keyword);
+
+        Pair<List<AffinityGroupJoinVO>, Integer> uniqueGroupsPair = _affinityGroupJoinDao.searchAndCount(sc, searchFilter);
 
-        Pair<List<AffinityGroupJoinVO>, Integer> uniqueGroupsPair = _affinityGroupJoinDao.searchAndCount(sc,
-                searchFilter);
         // search group details by ids
-        List<AffinityGroupJoinVO> vrs = new ArrayList<AffinityGroupJoinVO>();
+        List<AffinityGroupJoinVO> affinityGroups = new ArrayList<AffinityGroupJoinVO>();
+
         Integer count = uniqueGroupsPair.second();
         if (count.intValue() != 0) {
             List<AffinityGroupJoinVO> uniqueGroups = uniqueGroupsPair.first();
@@ -3452,36 +3452,33 @@ public class QueryManagerImpl extends ManagerBase implements QueryService, Confi
             for (AffinityGroupJoinVO v : uniqueGroups) {
                 vrIds[i++] = v.getId();
             }
-            vrs = _affinityGroupJoinDao.searchByIds(vrIds);
+            affinityGroups = _affinityGroupJoinDao.searchByIds(vrIds);
         }
 
         if (!permittedAccounts.isEmpty()) {
             // add domain level affinity groups
             if (domainId != null) {
-                SearchCriteria<AffinityGroupJoinVO> scDomain = buildAffinityGroupSearchCriteria(null, isRecursive,
-                        new ArrayList<Long>(), listProjectResourcesCriteria, affinityGroupId, affinityGroupName,
-                        affinityGroupType, keyword);
-                vrs.addAll(listDomainLevelAffinityGroups(scDomain, searchFilter, domainId));
+                SearchCriteria<AffinityGroupJoinVO> scDomain = buildAffinityGroupSearchCriteria(null, isRecursive, new ArrayList<Long>(), listProjectResourcesCriteria,
+                        affinityGroupId, affinityGroupName, affinityGroupType, keyword);
+                affinityGroups.addAll(listDomainLevelAffinityGroups(scDomain, searchFilter, domainId));
             } else {
 
                 for (Long permAcctId : permittedAccounts) {
                     Account permittedAcct = _accountDao.findById(permAcctId);
-                    SearchCriteria<AffinityGroupJoinVO> scDomain = buildAffinityGroupSearchCriteria(
-                            null, isRecursive, new ArrayList<Long>(),
-                            listProjectResourcesCriteria, affinityGroupId, affinityGroupName, affinityGroupType, keyword);
+                    SearchCriteria<AffinityGroupJoinVO> scDomain = buildAffinityGroupSearchCriteria(null, isRecursive, new ArrayList<Long>(), listProjectResourcesCriteria,
+                            affinityGroupId, affinityGroupName, affinityGroupType, keyword);
 
-                    vrs.addAll(listDomainLevelAffinityGroups(scDomain, searchFilter, permittedAcct.getDomainId()));
+                    affinityGroups.addAll(listDomainLevelAffinityGroups(scDomain, searchFilter, permittedAcct.getDomainId()));
                 }
             }
         } else if (((permittedAccounts.isEmpty()) && (domainId != null) && isRecursive)) {
             // list all domain level affinity groups for the domain admin case
-            SearchCriteria<AffinityGroupJoinVO> scDomain = buildAffinityGroupSearchCriteria(null, isRecursive,
-                    new ArrayList<Long>(), listProjectResourcesCriteria, affinityGroupId, affinityGroupName,
-                    affinityGroupType, keyword);
-            vrs.addAll(listDomainLevelAffinityGroups(scDomain, searchFilter, domainId));
+            SearchCriteria<AffinityGroupJoinVO> scDomain = buildAffinityGroupSearchCriteria(null, isRecursive, new ArrayList<Long>(), listProjectResourcesCriteria,
+                    affinityGroupId, affinityGroupName, affinityGroupType, keyword);
+            affinityGroups.addAll(listDomainLevelAffinityGroups(scDomain, searchFilter, domainId));
         }
 
-        return new Pair<List<AffinityGroupJoinVO>, Integer>(vrs, vrs.size());
+        return new Pair<List<AffinityGroupJoinVO>, Integer>(affinityGroups, affinityGroups.size());
 
     }
 
@@ -3526,9 +3523,8 @@ public class QueryManagerImpl extends ManagerBase implements QueryService, Confi
         }
     }
 
-    private SearchCriteria<AffinityGroupJoinVO> buildAffinityGroupSearchCriteria(Long domainId, boolean isRecursive,
-            List<Long> permittedAccounts, ListProjectResourcesCriteria listProjectResourcesCriteria,
-            Long affinityGroupId, String affinityGroupName, String affinityGroupType, String keyword) {
+    private SearchCriteria<AffinityGroupJoinVO> buildAffinityGroupSearchCriteria(Long domainId, boolean isRecursive, List<Long> permittedAccounts,
+            ListProjectResourcesCriteria listProjectResourcesCriteria, Long affinityGroupId, String affinityGroupName, String affinityGroupType, String keyword) {
 
         SearchBuilder<AffinityGroupJoinVO> groupSearch = _affinityGroupJoinDao.createSearchBuilder();
         buildAffinityGroupViewSearchBuilder(groupSearch, domainId, isRecursive, permittedAccounts,
@@ -3538,8 +3534,7 @@ public class QueryManagerImpl extends ManagerBase implements QueryService, Confi
         // distinct
 
         SearchCriteria<AffinityGroupJoinVO> sc = groupSearch.create();
-        buildAffinityGroupViewSearchCriteria(sc, domainId, isRecursive, permittedAccounts,
-                listProjectResourcesCriteria);
+        buildAffinityGroupViewSearchCriteria(sc, domainId, isRecursive, permittedAccounts, listProjectResourcesCriteria);
 
         if (affinityGroupId != null) {
             sc.addAnd("id", SearchCriteria.Op.EQ, affinityGroupId);

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/c76d3171/server/src/com/cloud/api/query/vo/AffinityGroupJoinVO.java
----------------------------------------------------------------------
diff --git a/server/src/com/cloud/api/query/vo/AffinityGroupJoinVO.java b/server/src/com/cloud/api/query/vo/AffinityGroupJoinVO.java
index bcd0fdc..380ad66 100644
--- a/server/src/com/cloud/api/query/vo/AffinityGroupJoinVO.java
+++ b/server/src/com/cloud/api/query/vo/AffinityGroupJoinVO.java
@@ -72,6 +72,15 @@ public class AffinityGroupJoinVO extends BaseViewVO implements ControlledViewEnt
     @Column(name = "domain_path")
     private String domainPath = null;
 
+    @Column(name = "project_id")
+    private long projectId;
+
+    @Column(name = "project_uuid")
+    private String projectUuid;
+
+    @Column(name = "project_name")
+    private String projectName;
+
     @Column(name = "vm_id")
     private long vmId;
 
@@ -153,6 +162,20 @@ public class AffinityGroupJoinVO extends BaseViewVO implements ControlledViewEnt
         return domainPath;
     }
 
+    public long getProjectId() {
+        return projectId;
+    }
+
+    @Override
+    public String getProjectUuid() {
+        return projectUuid;
+    }
+
+    @Override
+    public String getProjectName() {
+        return projectName;
+    }
+
     public String getDescription() {
         return description;
     }
@@ -177,18 +200,6 @@ public class AffinityGroupJoinVO extends BaseViewVO implements ControlledViewEnt
         return vmState;
     }
 
-    @Override
-    public String getProjectUuid() {
-        // TODO Auto-generated method stub
-        return null;
-    }
-
-    @Override
-    public String getProjectName() {
-        // TODO Auto-generated method stub
-        return null;
-    }
-
     public ControlledEntity.ACLType getAclType() {
         return aclType;
     }

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/c76d3171/server/src/com/cloud/configuration/ConfigurationManagerImpl.java
----------------------------------------------------------------------
diff --git a/server/src/com/cloud/configuration/ConfigurationManagerImpl.java b/server/src/com/cloud/configuration/ConfigurationManagerImpl.java
index 69e70e6..3a8c77d 100644
--- a/server/src/com/cloud/configuration/ConfigurationManagerImpl.java
+++ b/server/src/com/cloud/configuration/ConfigurationManagerImpl.java
@@ -1484,7 +1484,7 @@ public class ConfigurationManagerImpl extends ManagerBase implements Configurati
                         final List<DedicatedResourceVO> resourcesInGroup = _dedicatedDao.listByAffinityGroupId(dr.getAffinityGroupId());
                         if (resourcesInGroup.isEmpty()) {
                             // delete the group
-                            _affinityGroupService.deleteAffinityGroup(dr.getAffinityGroupId(), null, null, null);
+                            _affinityGroupService.deleteAffinityGroup(dr.getAffinityGroupId(), null, null, null, null);
                         }
                     }
                 }
@@ -1702,7 +1702,7 @@ public class ConfigurationManagerImpl extends ManagerBase implements Configurati
                         final List<DedicatedResourceVO> resourcesInGroup = _dedicatedDao.listByAffinityGroupId(resource.getAffinityGroupId());
                         if (resourcesInGroup.isEmpty()) {
                             // delete the group
-                            _affinityGroupService.deleteAffinityGroup(resource.getAffinityGroupId(), null, null, null);
+                            _affinityGroupService.deleteAffinityGroup(resource.getAffinityGroupId(), null, null, null, null);
                         }
                     }
                 }
@@ -1800,7 +1800,7 @@ public class ConfigurationManagerImpl extends ManagerBase implements Configurati
             }
         }
 
-        group = _affinityGroupService.createAffinityGroupInternal(accountName, domainId, affinityGroupName, "ExplicitDedication", "dedicated resources group");
+        group = _affinityGroupService.createAffinityGroup(accountName, null, domainId, affinityGroupName, "ExplicitDedication", "dedicated resources group");
 
         return group;
 

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/c76d3171/server/src/com/cloud/user/AccountManagerImpl.java
----------------------------------------------------------------------
diff --git a/server/src/com/cloud/user/AccountManagerImpl.java b/server/src/com/cloud/user/AccountManagerImpl.java
index 8f3a1b2..ead7735 100644
--- a/server/src/com/cloud/user/AccountManagerImpl.java
+++ b/server/src/com/cloud/user/AccountManagerImpl.java
@@ -2406,98 +2406,10 @@ public class AccountManagerImpl extends ManagerBase implements AccountManager, M
         }
     }
 
-//    @Override
-//    public void buildACLSearchParameters(Account caller, Long id, String accountName, Long projectId, List<Long>
-//    permittedAccounts, Ternary<Long, Boolean, ListProjectResourcesCriteria> domainIdRecursiveListProject,
-//            boolean listAll, boolean forProjectInvitation) {
-//        Long domainId = domainIdRecursiveListProject.first();
-//        if (domainId != null) {
-//            Domain domain = _domainDao.findById(domainId);
-//            if (domain == null) {
-//                throw new InvalidParameterValueException("Unable to find domain by id " + domainId);
-//            }
-//            // check permissions
-//            checkAccess(caller, domain);
-//        }
-//
-//        if (accountName != null) {
-//            if (projectId != null) {
-//                throw new InvalidParameterValueException("Account and projectId can't be specified together");
-//            }
-//
-//            Account userAccount = null;
-//            Domain domain = null;
-//            if (domainId != null) {
-//                userAccount = _accountDao.findActiveAccount(accountName, domainId);
-//                domain = _domainDao.findById(domainId);
-//            } else {
-//                userAccount = _accountDao.findActiveAccount(accountName, caller.getDomainId());
-//                domain = _domainDao.findById(caller.getDomainId());
-//            }
-//
-//            if (userAccount != null) {
-//                checkAccess(caller, null, false, userAccount);
-//                //check permissions
-//                permittedAccounts.add(userAccount.getId());
-//            } else {
-//                throw new InvalidParameterValueException("could not find account " + accountName + " in domain " + domain.getUuid());
-//            }
-//        }
-//
-//        // set project information
-//        if (projectId != null) {
-//            if (!forProjectInvitation) {
-//                if (projectId.longValue() == -1) {
-//                    if (caller.getType() == Account.ACCOUNT_TYPE_NORMAL) {
-//                        permittedAccounts.addAll(_projectMgr.listPermittedProjectAccounts(caller.getId()));
-//                    } else {
-//                        domainIdRecursiveListProject.third(Project.ListProjectResourcesCriteria.ListProjectResourcesOnly);
-//                    }
-//                } else {
-//                    Project project = _projectMgr.getProject(projectId);
-//                    if (project == null) {
-//                        throw new InvalidParameterValueException("Unable to find project by id " + projectId);
-//                    }
-//                    if (!_projectMgr.canAccessProjectAccount(caller, project.getProjectAccountId())) {
-//                        throw new PermissionDeniedException("Account " + caller + " can't access project id=" + projectId);
-//                    }
-//                    permittedAccounts.add(project.getProjectAccountId());
-//                }
-//            }
-//        } else {
-//            if (id == null) {
-//                domainIdRecursiveListProject.third(Project.ListProjectResourcesCriteria.SkipProjectResources);
-//            }
-//            if (permittedAccounts.isEmpty() && domainId == null) {
-//                if (caller.getType() == Account.ACCOUNT_TYPE_NORMAL) {
-//                    permittedAccounts.add(caller.getId());
-//                } else if (!listAll) {
-//                    if (id == null) {
-//                        permittedAccounts.add(caller.getId());
-//                    } else if (!isRootAdmin(caller.getId())) {
-//                        domainIdRecursiveListProject.first(caller.getDomainId());
-//                        domainIdRecursiveListProject.second(true);
-//                    }
-//                } else if (domainId == null) {
-//                    if (caller.getType() == Account.ACCOUNT_TYPE_DOMAIN_ADMIN) {
-//                        domainIdRecursiveListProject.first(caller.getDomainId());
-//                        domainIdRecursiveListProject.second(true);
-//                    }
-//                }
-//            } else if (domainId != null) {
-//                if (caller.getType() == Account.ACCOUNT_TYPE_NORMAL) {
-//                    permittedAccounts.add(caller.getId());
-//                }
-//            }
-//
-//        }
-//    }
-
     //TODO: deprecate this to use the new buildACLSearchParameters with permittedDomains, permittedAccounts, and permittedResources as return
     @Override
-    public void buildACLSearchParameters(Account caller, Long id, String accountName, Long projectId, List<Long>
-    permittedAccounts, Ternary<Long, Boolean, ListProjectResourcesCriteria> domainIdRecursiveListProject,
-            boolean listAll, boolean forProjectInvitation) {
+    public void buildACLSearchParameters(Account caller, Long id, String accountName, Long projectId, List<Long> permittedAccounts,
+            Ternary<Long, Boolean, ListProjectResourcesCriteria> domainIdRecursiveListProject, boolean listAll, boolean forProjectInvitation) {
         Long domainId = domainIdRecursiveListProject.first();
         if (domainId != null) {
             Domain domain = _domainDao.findById(domainId);

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/c76d3171/server/src/org/apache/cloudstack/affinity/AffinityGroupServiceImpl.java
----------------------------------------------------------------------
diff --git a/server/src/org/apache/cloudstack/affinity/AffinityGroupServiceImpl.java b/server/src/org/apache/cloudstack/affinity/AffinityGroupServiceImpl.java
index d25bddb..5da1f88 100644
--- a/server/src/org/apache/cloudstack/affinity/AffinityGroupServiceImpl.java
+++ b/server/src/org/apache/cloudstack/affinity/AffinityGroupServiceImpl.java
@@ -27,8 +27,8 @@ import javax.inject.Inject;
 import javax.naming.ConfigurationException;
 
 import com.cloud.utils.fsm.StateMachine2;
-import org.apache.log4j.Logger;
 
+import org.apache.log4j.Logger;
 import org.apache.cloudstack.acl.ControlledEntity;
 import org.apache.cloudstack.acl.ControlledEntity.ACLType;
 import org.apache.cloudstack.acl.SecurityChecker.AccessType;
@@ -36,6 +36,7 @@ import org.apache.cloudstack.affinity.dao.AffinityGroupDao;
 import org.apache.cloudstack.affinity.dao.AffinityGroupDomainMapDao;
 import org.apache.cloudstack.affinity.dao.AffinityGroupVMMapDao;
 import org.apache.cloudstack.api.ApiConstants;
+import org.apache.cloudstack.api.command.user.affinitygroup.CreateAffinityGroupCmd;
 import org.apache.cloudstack.context.CallContext;
 import org.apache.cloudstack.framework.messagebus.MessageBus;
 import org.apache.cloudstack.framework.messagebus.PublishScope;
@@ -55,8 +56,6 @@ import com.cloud.utils.component.Manager;
 import com.cloud.utils.component.ManagerBase;
 import com.cloud.utils.db.DB;
 import com.cloud.utils.db.EntityManager;
-import com.cloud.utils.db.Filter;
-import com.cloud.utils.db.JoinBuilder;
 import com.cloud.utils.db.SearchBuilder;
 import com.cloud.utils.db.SearchCriteria;
 import com.cloud.utils.db.Transaction;
@@ -113,48 +112,29 @@ public class AffinityGroupServiceImpl extends ManagerBase implements AffinityGro
     @DB
     @Override
     @ActionEvent(eventType = EventTypes.EVENT_AFFINITY_GROUP_CREATE, eventDescription = "Creating Affinity Group", create = true)
-    public AffinityGroup createAffinityGroup(String account, Long domainId, String affinityGroupName, String affinityGroupType, String description) {
-
-        Account caller = CallContext.current().getCallingAccount();
-
-        //validate the affinityGroupType
-        Map<String, AffinityGroupProcessor> typeProcessorMap = getAffinityTypeToProcessorMap();
-        if (typeProcessorMap != null && !typeProcessorMap.isEmpty()) {
-            if (!typeProcessorMap.containsKey(affinityGroupType)) {
-                throw new InvalidParameterValueException("Unable to create affinity group, invalid affinity group type" + affinityGroupType);
-            }
-        } else {
-            throw new InvalidParameterValueException("Unable to create affinity group, no Affinity Group Types configured");
-        }
-
-        AffinityGroupProcessor processor = typeProcessorMap.get(affinityGroupType);
-
-        if (processor.isAdminControlledGroup()) {
-            throw new PermissionDeniedException("Cannot create the affinity group");
-        }
-
-        return createAffinityGroupInternal(account, domainId, affinityGroupName, affinityGroupType, description);
+    public AffinityGroup createAffinityGroup(CreateAffinityGroupCmd createAffinityGroupCmd) {
+        return createAffinityGroup(createAffinityGroupCmd.getAccountName(), createAffinityGroupCmd.getProjectId(), createAffinityGroupCmd.getDomainId(), createAffinityGroupCmd.getAffinityGroupName(), createAffinityGroupCmd.getAffinityGroupType(), createAffinityGroupCmd.getDescription());
     }
 
     @DB
     @Override
-    public AffinityGroup createAffinityGroupInternal(String account, final Long domainId, final String affinityGroupName, final String affinityGroupType,
+    public AffinityGroup createAffinityGroup(final String accountName, final Long projectId, final Long domainId, final String affinityGroupName, final String affinityGroupType,
         final String description) {
 
-        Account caller = CallContext.current().getCallingAccount();
-
         // validate the affinityGroupType
         Map<String, AffinityGroupProcessor> typeProcessorMap = getAffinityTypeToProcessorMap();
-        if (typeProcessorMap != null && !typeProcessorMap.isEmpty()) {
-            if (!typeProcessorMap.containsKey(affinityGroupType)) {
-                throw new InvalidParameterValueException("Unable to create affinity group, invalid affinity group type" + affinityGroupType);
-            }
-        } else {
+
+        if (typeProcessorMap == null || typeProcessorMap.isEmpty()) {
             throw new InvalidParameterValueException("Unable to create affinity group, no Affinity Group Types configured");
         }
 
-        final AffinityGroupProcessor processor = typeProcessorMap.get(affinityGroupType);
+        AffinityGroupProcessor processor = typeProcessorMap.get(affinityGroupType);
+
+        if(processor == null){
+            throw new InvalidParameterValueException("Unable to create affinity group, invalid affinity group type" + affinityGroupType);
+        }
 
+        Account caller = CallContext.current().getCallingAccount();
         if (processor.isAdminControlledGroup() && !_accountMgr.isRootAdmin(caller.getId())) {
             throw new PermissionDeniedException("Cannot create the affinity group");
         }
@@ -163,64 +143,60 @@ public class AffinityGroupServiceImpl extends ManagerBase implements AffinityGro
         Account owner = null;
         boolean domainLevel = false;
 
-        if (account != null && domainId != null) {
-
-            owner = _accountMgr.finalizeOwner(caller, account, domainId, null);
-            aclType = ControlledEntity.ACLType.Account;
-
-        } else if (domainId != null && account == null) {
-
-            if (!_accountMgr.isRootAdmin(caller.getId())) {
-                // non root admin need to pass both account and domain
-                throw new InvalidParameterValueException("Unable to create affinity group, account name must be passed with the domainId");
-            } else if (!processor.canBeSharedDomainWide()) {
-                // cannot be domain level
-                throw new InvalidParameterValueException("Unable to create affinity group, account name is needed");
-            }
-
-            DomainVO domain = _domainDao.findById(domainId);
-            if (domain == null) {
-                throw new InvalidParameterValueException("Unable to find domain by specified id");
-            }
+        if (projectId == null && domainId != null && accountName == null) {
+            verifyAccessToDomainWideProcessor(caller, processor);
+            DomainVO domain = getDomain(domainId);
             _accountMgr.checkAccess(caller, domain);
 
             // domain level group, owner is SYSTEM.
             owner = _accountMgr.getAccount(Account.ACCOUNT_ID_SYSTEM);
             aclType = ControlledEntity.ACLType.Domain;
             domainLevel = true;
-
         } else {
-            owner = caller;
+            owner = _accountMgr.finalizeOwner(caller, accountName, domainId, projectId);
             aclType = ControlledEntity.ACLType.Account;
         }
 
-        if (_affinityGroupDao.isNameInUse(owner.getAccountId(), owner.getDomainId(), affinityGroupName)) {
-            throw new InvalidParameterValueException("Unable to create affinity group, a group with name " + affinityGroupName + " already exists.");
+        verifyAffinityGroupNameInUse(owner.getAccountId(), owner.getDomainId(), affinityGroupName);
+        verifyDomainLevelAffinityGroupName(domainLevel, owner.getDomainId(), affinityGroupName);
+
+        AffinityGroupVO group = createAffinityGroup(processor, owner, aclType, affinityGroupName, affinityGroupType, description);
+
+        if (s_logger.isDebugEnabled()) {
+            s_logger.debug("Created affinity group =" + affinityGroupName);
         }
-        if (domainLevel && _affinityGroupDao.findDomainLevelGroupByName(domainId, affinityGroupName) != null) {
-            throw new InvalidParameterValueException("Unable to create affinity group, a group with name " + affinityGroupName + " already exists under the domain.");
+
+        return group;
+    }
+
+    private void verifyAccessToDomainWideProcessor(Account caller, AffinityGroupProcessor processor) {
+        if (!_accountMgr.isRootAdmin(caller.getId())) {
+            throw new InvalidParameterValueException("Unable to create affinity group, account name must be passed with the domainId");
         }
+        if (!processor.canBeSharedDomainWide()) {
+            throw new InvalidParameterValueException("Unable to create affinity group, account name is needed. Affinity group type "+ processor.getType() +" cannot be shared domain wide");
+        }
+    }
 
-        final Account ownerFinal = owner;
-        final ControlledEntity.ACLType aclTypeFinal = aclType;
-        AffinityGroupVO group = Transaction.execute(new TransactionCallback<AffinityGroupVO>() {
+    private AffinityGroupVO createAffinityGroup(final AffinityGroupProcessor processor, final Account owner, final ACLType aclType, final String affinityGroupName, final String affinityGroupType, final String description) {
+        return Transaction.execute(new TransactionCallback<AffinityGroupVO>() {
             @Override
             public AffinityGroupVO doInTransaction(TransactionStatus status) {
                 AffinityGroupVO group =
-                    new AffinityGroupVO(affinityGroupName, affinityGroupType, description, ownerFinal.getDomainId(), ownerFinal.getId(), aclTypeFinal);
+                    new AffinityGroupVO(affinityGroupName, affinityGroupType, description, owner.getDomainId(), owner.getId(), aclType);
                 _affinityGroupDao.persist(group);
 
-                if (domainId != null && aclTypeFinal == ACLType.Domain) {
+                if (aclType == ACLType.Domain) {
                     boolean subDomainAccess = false;
                     subDomainAccess = processor.subDomainAccess();
-                    AffinityGroupDomainMapVO domainMap = new AffinityGroupDomainMapVO(group.getId(), domainId,
+                    AffinityGroupDomainMapVO domainMap = new AffinityGroupDomainMapVO(group.getId(), owner.getDomainId(),
                             subDomainAccess);
                     _affinityGroupDomainMapDao.persist(domainMap);
                     //send event for storing the domain wide resource access
                     Map<String, Object> params = new HashMap<String, Object>();
                     params.put(ApiConstants.ENTITY_TYPE, AffinityGroup.class);
                     params.put(ApiConstants.ENTITY_ID, group.getId());
-                    params.put(ApiConstants.DOMAIN_ID, domainId);
+                    params.put(ApiConstants.DOMAIN_ID, owner.getDomainId());
                     params.put(ApiConstants.SUBDOMAIN_ACCESS, subDomainAccess);
                     _messageBus.publish(_name, EntityManager.MESSAGE_ADD_DOMAIN_WIDE_ENTITY_EVENT, PublishScope.LOCAL,
                             params);
@@ -229,59 +205,99 @@ public class AffinityGroupServiceImpl extends ManagerBase implements AffinityGro
                 return group;
             }
         });
+    }
 
-        if (s_logger.isDebugEnabled()) {
-            s_logger.debug("Created affinity group =" + affinityGroupName);
+    private DomainVO getDomain(Long domainId) {
+        DomainVO domain = _domainDao.findById(domainId);
+        if (domain == null) {
+            throw new InvalidParameterValueException("Unable to find domain by specified id");
         }
+        return domain;
+    }
 
-        return group;
+    private void verifyAffinityGroupNameInUse(long accountId, long domainId, String affinityGroupName) {
+        if (_affinityGroupDao.isNameInUse(accountId, domainId, affinityGroupName)) {
+            throw new InvalidParameterValueException("Unable to create affinity group, a group with name " + affinityGroupName + " already exists.");
+        }
+    }
+
+    private void verifyDomainLevelAffinityGroupName(boolean domainLevel, long domainId, String affinityGroupName) {
+        if (domainLevel && _affinityGroupDao.findDomainLevelGroupByName(domainId, affinityGroupName) != null) {
+            throw new InvalidParameterValueException("Unable to create affinity group, a group with name " + affinityGroupName + " already exists under the domain.");
+        }
     }
 
     @DB
-    @Override
     @ActionEvent(eventType = EventTypes.EVENT_AFFINITY_GROUP_DELETE, eventDescription = "Deleting affinity group")
-    public boolean deleteAffinityGroup(Long affinityGroupId, String account, Long domainId, String affinityGroupName) {
+    public boolean deleteAffinityGroup(Long affinityGroupId, String account, Long projectId, Long domainId, String affinityGroupName) {
+
+        AffinityGroupVO group = getAffinityGroup(affinityGroupId, account, projectId, domainId, affinityGroupName);
 
+        // check permissions
         Account caller = CallContext.current().getCallingAccount();
-        Account owner = _accountMgr.finalizeOwner(caller, account, domainId, null);
+        _accountMgr.checkAccess(caller, AccessType.OperateEntry, true, group);
 
+        final Long affinityGroupIdFinal = group.getId();
+        deleteAffinityGroup(affinityGroupIdFinal);
+
+        // remove its related ACL permission
+        Pair<Class<?>, Long> params = new Pair<Class<?>, Long>(AffinityGroup.class, affinityGroupIdFinal);
+        _messageBus.publish(_name, EntityManager.MESSAGE_REMOVE_ENTITY_EVENT, PublishScope.LOCAL, params);
+
+        if (s_logger.isDebugEnabled()) {
+            s_logger.debug("Deleted affinity group id=" + affinityGroupIdFinal);
+        }
+        return true;
+    }
+
+    private AffinityGroupVO getAffinityGroup(Long affinityGroupId, String account, Long projectId, Long domainId, String affinityGroupName) {
         AffinityGroupVO group = null;
         if (affinityGroupId != null) {
             group = _affinityGroupDao.findById(affinityGroupId);
-            if (group == null) {
-                throw new InvalidParameterValueException("Unable to find affinity group: " + affinityGroupId + "; failed to delete group.");
-            }
         } else if (affinityGroupName != null) {
-            group = _affinityGroupDao.findByAccountAndName(owner.getAccountId(), affinityGroupName);
-            if (group == null) {
-                throw new InvalidParameterValueException("Unable to find affinity group: " + affinityGroupName + "; failed to delete group.");
-            }
+            group = getAffinityGroupByName(account, projectId, domainId, affinityGroupName);
         } else {
             throw new InvalidParameterValueException("Either the affinity group Id or group name must be specified to delete the group");
         }
-        if (affinityGroupId == null) {
-            affinityGroupId = group.getId();
+        if (group == null) {
+                throw new InvalidParameterValueException("Unable to find affinity group " + (affinityGroupId == null ? affinityGroupName : affinityGroupId));
         }
-        // check permissions
-        _accountMgr.checkAccess(caller, AccessType.OperateEntry, true, group);
+        return group;
+    }
+
+    private AffinityGroupVO getAffinityGroupByName(String account, Long projectId, Long domainId, String affinityGroupName) {
+        AffinityGroupVO group = null;
+        if(account == null && domainId != null){
+            group = _affinityGroupDao.findDomainLevelGroupByName(domainId, affinityGroupName);
+        }else{
+            Long accountId = _accountMgr.finalyzeAccountId(account, domainId, projectId, true);
+            if(accountId == null){
+                Account caller = CallContext.current().getCallingAccount();
+                group = _affinityGroupDao.findByAccountAndName(caller.getAccountId(), affinityGroupName);
+            }else{
+                group = _affinityGroupDao.findByAccountAndName(accountId, affinityGroupName);
+            }
+        }
+        return group;
+    }
 
-        final Long affinityGroupIdFinal = affinityGroupId;
+    private void deleteAffinityGroup(final Long affinityGroupId) {
         Transaction.execute(new TransactionCallbackNoReturn() {
             @Override
             public void doInTransactionWithoutResult(TransactionStatus status) {
 
-                AffinityGroupVO group = _affinityGroupDao.lockRow(affinityGroupIdFinal, true);
+                AffinityGroupVO group = _affinityGroupDao.lockRow(affinityGroupId, true);
                 if (group == null) {
-                            throw new InvalidParameterValueException("Unable to find affinity group by id " + affinityGroupIdFinal);
+                    throw new InvalidParameterValueException("Unable to find affinity group by id " + affinityGroupId);
                 }
 
-                List<AffinityGroupVMMapVO> affinityGroupVmMap = _affinityGroupVMMapDao.listByAffinityGroup(affinityGroupIdFinal);
+                List<AffinityGroupVMMapVO> affinityGroupVmMap = _affinityGroupVMMapDao.listByAffinityGroup(affinityGroupId);
                 if (!affinityGroupVmMap.isEmpty()) {
                     SearchBuilder<AffinityGroupVMMapVO> listByAffinityGroup = _affinityGroupVMMapDao.createSearchBuilder();
                             listByAffinityGroup.and("affinityGroupId", listByAffinityGroup.entity().getAffinityGroupId(), SearchCriteria.Op.EQ);
                     listByAffinityGroup.done();
                     SearchCriteria<AffinityGroupVMMapVO> sc = listByAffinityGroup.create();
-                            sc.setParameters("affinityGroupId", affinityGroupIdFinal);
+                            sc.setParameters("affinityGroupId", affinityGroupId);
 
                     _affinityGroupVMMapDao.lockRows(sc, null, true);
                     _affinityGroupVMMapDao.remove(sc);
@@ -293,77 +309,15 @@ public class AffinityGroupServiceImpl extends ManagerBase implements AffinityGro
                     processor.handleDeleteGroup(group);
                 }
 
-                if(_affinityGroupDao.expunge(affinityGroupIdFinal)){
+                if(_affinityGroupDao.expunge(affinityGroupId)){
                     AffinityGroupDomainMapVO groupDomain = _affinityGroupDomainMapDao
-                            .findByAffinityGroup(affinityGroupIdFinal);
+                            .findByAffinityGroup(affinityGroupId);
                     if (groupDomain != null) {
                         _affinityGroupDomainMapDao.remove(groupDomain.getId());
                     }
                 }
             }
         });
-
-        // remove its related ACL permission
-        Pair<Class<?>, Long> params = new Pair<Class<?>, Long>(AffinityGroup.class, affinityGroupIdFinal);
-        _messageBus.publish(_name, EntityManager.MESSAGE_REMOVE_ENTITY_EVENT, PublishScope.LOCAL, params);
-
-        if (s_logger.isDebugEnabled()) {
-            s_logger.debug("Deleted affinity group id=" + affinityGroupId);
-        }
-        return true;
-    }
-
-    @Override
-    public Pair<List<? extends AffinityGroup>, Integer> listAffinityGroups(Long affinityGroupId, String affinityGroupName, String affinityGroupType, Long vmId,
-        Long startIndex, Long pageSize) {
-        Filter searchFilter = new Filter(AffinityGroupVO.class, "id", Boolean.TRUE, startIndex, pageSize);
-
-        Account caller = CallContext.current().getCallingAccount();
-
-        Long accountId = caller.getAccountId();
-        Long domainId = caller.getDomainId();
-
-        SearchBuilder<AffinityGroupVMMapVO> vmInstanceSearch = _affinityGroupVMMapDao.createSearchBuilder();
-        vmInstanceSearch.and("instanceId", vmInstanceSearch.entity().getInstanceId(), SearchCriteria.Op.EQ);
-
-        SearchBuilder<AffinityGroupVO> groupSearch = _affinityGroupDao.createSearchBuilder();
-
-        SearchCriteria<AffinityGroupVO> sc = groupSearch.create();
-
-        if (accountId != null) {
-            sc.addAnd("accountId", SearchCriteria.Op.EQ, accountId);
-        }
-
-        if (domainId != null) {
-            sc.addAnd("domainId", SearchCriteria.Op.EQ, domainId);
-        }
-
-        if (affinityGroupId != null) {
-            sc.addAnd("id", SearchCriteria.Op.EQ, affinityGroupId);
-        }
-
-        if (affinityGroupName != null) {
-            sc.addAnd("name", SearchCriteria.Op.EQ, affinityGroupName);
-        }
-
-        if (affinityGroupType != null) {
-            sc.addAnd("type", SearchCriteria.Op.EQ, affinityGroupType);
-        }
-
-        if (vmId != null) {
-            UserVmVO userVM = _userVmDao.findById(vmId);
-            if (userVM == null) {
-                throw new InvalidParameterValueException("Unable to list affinity groups for virtual machine instance " + vmId + "; instance not found.");
-            }
-            _accountMgr.checkAccess(caller, null, true, userVM);
-            // add join to affinity_groups_vm_map
-            groupSearch.join("vmInstanceSearch", vmInstanceSearch, groupSearch.entity().getId(), vmInstanceSearch.entity().getAffinityGroupId(),
-                JoinBuilder.JoinType.INNER);
-            sc.setJoinParameters("vmInstanceSearch", "instanceId", vmId);
-        }
-
-        Pair<List<AffinityGroupVO>, Integer> result =  _affinityGroupDao.searchAndCount(sc, searchFilter);
-        return new Pair<List<? extends AffinityGroup>, Integer>(result.first(), result.second());
     }
 
     @Override
@@ -460,7 +414,7 @@ public class AffinityGroupServiceImpl extends ManagerBase implements AffinityGro
         // Verify input parameters
         UserVmVO vmInstance = _userVmDao.findById(vmId);
         if (vmInstance == null) {
-            throw new InvalidParameterValueException("unable to find a virtual machine with id " + vmId);
+            throw new InvalidParameterValueException("Unable to find a virtual machine with id " + vmId);
         }
 
         // Check that the VM is stopped

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/c76d3171/server/test/org/apache/cloudstack/affinity/AffinityApiUnitTest.java
----------------------------------------------------------------------
diff --git a/server/test/org/apache/cloudstack/affinity/AffinityApiUnitTest.java b/server/test/org/apache/cloudstack/affinity/AffinityApiUnitTest.java
index 8cf4cdc..354054a 100644
--- a/server/test/org/apache/cloudstack/affinity/AffinityApiUnitTest.java
+++ b/server/test/org/apache/cloudstack/affinity/AffinityApiUnitTest.java
@@ -167,38 +167,39 @@ public class AffinityApiUnitTest {
     @Test
     public void createAffinityGroupTest() {
         when(_groupDao.isNameInUse(anyLong(), anyLong(), eq("group1"))).thenReturn(false);
-        AffinityGroup group = _affinityService.createAffinityGroup("user", domainId, "group1", "mock", "affinity group one");
+        AffinityGroup group = _affinityService.createAffinityGroup("user", null, domainId, "group1", "mock", "affinity group one");
         assertNotNull("Affinity group 'group1' of type 'mock' failed to create ", group);
 
     }
 
     @Test(expected = InvalidParameterValueException.class)
     public void invalidAffinityTypeTest() {
-        AffinityGroup group = _affinityService.createAffinityGroup("user", domainId, "group1", "invalid", "affinity group one");
+        AffinityGroup group = _affinityService.createAffinityGroup("user", null, domainId, "group1", "invalid", "affinity group one");
 
     }
 
     @Test(expected = InvalidParameterValueException.class)
     public void uniqueAffinityNameTest() {
         when(_groupDao.isNameInUse(anyLong(), anyLong(), eq("group1"))).thenReturn(true);
-        AffinityGroup group2 = _affinityService.createAffinityGroup("user", domainId, "group1", "mock", "affinity group two");
+        AffinityGroup group2 = _affinityService.createAffinityGroup("user", null, domainId, "group1", "mock", "affinity group two");
     }
 
     @Test(expected = InvalidParameterValueException.class)
     public void deleteAffinityGroupInvalidIdTest() throws ResourceInUseException {
         when(_groupDao.findById(20L)).thenReturn(null);
-        _affinityService.deleteAffinityGroup(20L, "user", domainId, "group1");
+        _affinityService.deleteAffinityGroup(20L, "user", null, domainId, "group1");
     }
 
     @Test(expected = InvalidParameterValueException.class)
     public void deleteAffinityGroupInvalidIdName() throws ResourceInUseException {
+        when(_acctMgr.finalyzeAccountId("user", domainId, null, true)).thenReturn(200L);
         when(_groupDao.findByAccountAndName(200L, "group1")).thenReturn(null);
-        _affinityService.deleteAffinityGroup(null, "user", domainId, "group1");
+        _affinityService.deleteAffinityGroup(null, "user", null, domainId, "group1");
     }
 
     @Test(expected = InvalidParameterValueException.class)
     public void deleteAffinityGroupNullIdName() throws ResourceInUseException {
-        _affinityService.deleteAffinityGroup(null, "user", domainId, null);
+        _affinityService.deleteAffinityGroup(null, "user", null, domainId, null);
     }
 
     @Test(expected = InvalidParameterValueException.class)