You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@cloudstack.apache.org by pr...@apache.org on 2013/04/05 07:47:49 UTC

[1/2] git commit: updated refs/heads/affinity_groups to 1b60135

Updated Branches:
  refs/heads/affinity_groups d68856a2f -> 1b60135fb


Changes to return affinity groups information during listVMsCmd


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

Branch: refs/heads/affinity_groups
Commit: 68b74a1eafd4305e6e4ca412965790da49449333
Parents: d68856a
Author: Prachi Damle <pr...@cloud.com>
Authored: Thu Apr 4 14:40:05 2013 -0700
Committer: Prachi Damle <pr...@cloud.com>
Committed: Thu Apr 4 14:40:05 2013 -0700

----------------------------------------------------------------------
 .../org/apache/cloudstack/api/ApiConstants.java    |    2 +-
 .../cloudstack/api/response/UserVmResponse.java    |   14 ++
 .../com/cloud/api/query/ViewResponseHelper.java    |    2 +-
 .../com/cloud/api/query/dao/UserVmJoinDaoImpl.java |   27 +++
 .../src/com/cloud/api/query/vo/UserVmJoinVO.java   |   37 +++
 setup/db/db/schema-410to420.sql                    |  179 +++++++++++++++
 6 files changed, 259 insertions(+), 2 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/cloudstack/blob/68b74a1e/api/src/org/apache/cloudstack/api/ApiConstants.java
----------------------------------------------------------------------
diff --git a/api/src/org/apache/cloudstack/api/ApiConstants.java b/api/src/org/apache/cloudstack/api/ApiConstants.java
index dd8bfcd..b08e992 100755
--- a/api/src/org/apache/cloudstack/api/ApiConstants.java
+++ b/api/src/org/apache/cloudstack/api/ApiConstants.java
@@ -482,7 +482,7 @@ public class ApiConstants {
     }
 
     public enum VMDetails {
-        all, group, nics, stats, secgrp, tmpl, servoff, iso, volume, min;
+        all, group, nics, stats, secgrp, tmpl, servoff, iso, volume, min, affgrp;
     }
 
     public enum LDAPParams {

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/68b74a1e/api/src/org/apache/cloudstack/api/response/UserVmResponse.java
----------------------------------------------------------------------
diff --git a/api/src/org/apache/cloudstack/api/response/UserVmResponse.java b/api/src/org/apache/cloudstack/api/response/UserVmResponse.java
index 71d1b82..212601c 100644
--- a/api/src/org/apache/cloudstack/api/response/UserVmResponse.java
+++ b/api/src/org/apache/cloudstack/api/response/UserVmResponse.java
@@ -21,6 +21,7 @@ import java.util.HashSet;
 import java.util.LinkedHashSet;
 import java.util.Set;
 
+import org.apache.cloudstack.affinity.AffinityGroupResponse;
 import org.apache.cloudstack.api.ApiConstants;
 import org.apache.cloudstack.api.BaseResponse;
 import org.apache.cloudstack.api.EntityReference;
@@ -169,10 +170,15 @@ public class UserVmResponse extends BaseResponse implements ControlledEntityResp
     @SerializedName(ApiConstants.SSH_KEYPAIR) @Param(description="ssh key-pair")
     private String keyPairName;
 
+    @SerializedName("affinitygroup")
+    @Param(description = "list of affinity groups associated with the virtual machine", responseObject = AffinityGroupResponse.class)
+    private Set<AffinityGroupResponse> affinityGroupList;
+
     public UserVmResponse(){
         securityGroupList = new LinkedHashSet<SecurityGroupResponse>();
         nics = new LinkedHashSet<NicResponse>();
         tags = new LinkedHashSet<ResourceTagResponse>();
+        affinityGroupList = new LinkedHashSet<AffinityGroupResponse>();
     }
 
     public void setHypervisor(String hypervisor) {
@@ -381,4 +387,12 @@ public class UserVmResponse extends BaseResponse implements ControlledEntityResp
         this.keyPairName = keyPairName;
     }
 
+    public void setAffinityGroupList(Set<AffinityGroupResponse> affinityGroups) {
+        this.affinityGroupList = affinityGroups;
+    }
+
+    public void addAffinityGroup(AffinityGroupResponse affinityGroup) {
+        this.affinityGroupList.add(affinityGroup);
+    }
+
 }

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/68b74a1e/server/src/com/cloud/api/query/ViewResponseHelper.java
----------------------------------------------------------------------
diff --git a/server/src/com/cloud/api/query/ViewResponseHelper.java b/server/src/com/cloud/api/query/ViewResponseHelper.java
index 9e612b0..931327a 100644
--- a/server/src/com/cloud/api/query/ViewResponseHelper.java
+++ b/server/src/com/cloud/api/query/ViewResponseHelper.java
@@ -123,7 +123,7 @@ public class ViewResponseHelper {
                 // first time encountering this vm
                 userVmData = ApiDBUtils.newUserVmResponse(objectName, userVm, details, caller);
             } else{
-                // update nics, securitygroups, tags for 1 to many mapping fields
+                // update nics, securitygroups, tags, affinitygroups for 1 to many mapping fields
                 userVmData = ApiDBUtils.fillVmDetails(userVmData, userVm);
             }
             vmDataList.put(userVm.getId(), userVmData);

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/68b74a1e/server/src/com/cloud/api/query/dao/UserVmJoinDaoImpl.java
----------------------------------------------------------------------
diff --git a/server/src/com/cloud/api/query/dao/UserVmJoinDaoImpl.java b/server/src/com/cloud/api/query/dao/UserVmJoinDaoImpl.java
index 8b6abf8..4ed6226 100644
--- a/server/src/com/cloud/api/query/dao/UserVmJoinDaoImpl.java
+++ b/server/src/com/cloud/api/query/dao/UserVmJoinDaoImpl.java
@@ -26,6 +26,7 @@ import java.util.Set;
 import javax.ejb.Local;
 import javax.inject.Inject;
 
+import org.apache.cloudstack.affinity.AffinityGroupResponse;
 import org.apache.cloudstack.api.ApiConstants.VMDetails;
 import org.apache.cloudstack.api.response.NicResponse;
 import org.apache.cloudstack.api.response.SecurityGroupResponse;
@@ -216,6 +217,20 @@ public class UserVmJoinDaoImpl extends GenericDaoBase<UserVmJoinVO, Long> implem
                 userVmResponse.addTag(ApiDBUtils.newResourceTagResponse(vtag, false));
             }
         }
+
+        if (details.contains(VMDetails.all) || details.contains(VMDetails.affgrp)) {
+            Long affinityGroupId = userVm.getAffinityGroupId();
+            if (affinityGroupId != null && affinityGroupId.longValue() != 0) {
+                AffinityGroupResponse resp = new AffinityGroupResponse();
+                resp.setId(userVm.getAffinityGroupUuid());
+                resp.setName(userVm.getAffinityGroupName());
+                resp.setDescription(userVm.getAffinityGroupDescription());
+                resp.setObjectName("affinitygroup");
+                resp.setAccountName(userVm.getAccountName());
+                userVmResponse.addAffinityGroup(resp);
+            }
+        }
+
         userVmResponse.setObjectName(objectName);
 
         return userVmResponse;
@@ -276,6 +291,18 @@ public class UserVmJoinDaoImpl extends GenericDaoBase<UserVmJoinVO, Long> implem
                 userVmData.addTag(ApiDBUtils.newResourceTagResponse(vtag, false));
             }
         }
+
+        Long affinityGroupId = uvo.getAffinityGroupId();
+        if (affinityGroupId != null && affinityGroupId.longValue() != 0) {
+            AffinityGroupResponse resp = new AffinityGroupResponse();
+            resp.setId(uvo.getAffinityGroupUuid());
+            resp.setName(uvo.getAffinityGroupName());
+            resp.setDescription(uvo.getAffinityGroupDescription());
+            resp.setObjectName("affinitygroup");
+            resp.setAccountName(uvo.getAccountName());
+            userVmData.addAffinityGroup(resp);
+        }
+
         return userVmData;
     }
 

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/68b74a1e/server/src/com/cloud/api/query/vo/UserVmJoinVO.java
----------------------------------------------------------------------
diff --git a/server/src/com/cloud/api/query/vo/UserVmJoinVO.java b/server/src/com/cloud/api/query/vo/UserVmJoinVO.java
index 33c49cd..8d1314e 100644
--- a/server/src/com/cloud/api/query/vo/UserVmJoinVO.java
+++ b/server/src/com/cloud/api/query/vo/UserVmJoinVO.java
@@ -368,6 +368,18 @@ public class UserVmJoinVO extends BaseViewVO implements ControlledViewEntity {
     @Column(name="tag_customer")
     private String tagCustomer;
 
+    @Column(name = "affinity_group_id")
+    private long affinityGroupId;
+
+    @Column(name = "affinity_group_uuid")
+    private String affinityGroupUuid;
+
+    @Column(name = "affinity_group_name")
+    private String affinityGroupName;
+
+    @Column(name = "affinity_group_description")
+    private String affinityGroupDescription;
+
     transient String password;
 
     @Transient
@@ -1671,4 +1683,29 @@ public class UserVmJoinVO extends BaseViewVO implements ControlledViewEntity {
 	public void setIp6Cidr(String ip6Cidr) {
 		this.ip6Cidr = ip6Cidr;
 	}
+
+
+    public long getAffinityGroupId() {
+        return affinityGroupId;
+    }
+
+
+
+    public String getAffinityGroupUuid() {
+        return affinityGroupUuid;
+    }
+
+
+
+    public String getAffinityGroupName() {
+        return affinityGroupName;
+    }
+
+
+
+    public String getAffinityGroupDescription() {
+        return affinityGroupDescription;
+    }
+
+
 }

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/68b74a1e/setup/db/db/schema-410to420.sql
----------------------------------------------------------------------
diff --git a/setup/db/db/schema-410to420.sql b/setup/db/db/schema-410to420.sql
index f24fbb0..fc0a718 100644
--- a/setup/db/db/schema-410to420.sql
+++ b/setup/db/db/schema-410to420.sql
@@ -413,5 +413,184 @@ CREATE VIEW `cloud`.`account_view` AS
             and async_job.instance_type = 'Account'
             and async_job.job_status = 0;
 
+			
+DROP VIEW IF EXISTS `cloud`.`user_vm_view`;
+CREATE VIEW `cloud`.`user_vm_view` AS
+    select 
+        vm_instance.id id,
+        vm_instance.name name,
+        user_vm.display_name display_name,
+        user_vm.user_data user_data,
+        account.id account_id,
+        account.uuid account_uuid,
+        account.account_name account_name,
+        account.type account_type,
+        domain.id domain_id,
+        domain.uuid domain_uuid,
+        domain.name domain_name,
+        domain.path domain_path,
+        projects.id project_id,
+        projects.uuid project_uuid,
+        projects.name project_name,
+        instance_group.id instance_group_id,
+        instance_group.uuid instance_group_uuid,
+        instance_group.name instance_group_name,
+        vm_instance.uuid uuid,
+        vm_instance.last_host_id last_host_id,
+        vm_instance.vm_type type,
+        vm_instance.vnc_password vnc_password,
+        vm_instance.limit_cpu_use limit_cpu_use,
+        vm_instance.created created,
+        vm_instance.state state,
+        vm_instance.removed removed,
+        vm_instance.ha_enabled ha_enabled,
+        vm_instance.hypervisor_type hypervisor_type,
+        vm_instance.instance_name instance_name,
+        vm_instance.guest_os_id guest_os_id,
+        guest_os.uuid guest_os_uuid,
+        vm_instance.pod_id pod_id,
+        host_pod_ref.uuid pod_uuid,
+        vm_instance.private_ip_address private_ip_address,
+        vm_instance.private_mac_address private_mac_address,
+        vm_instance.vm_type vm_type,
+        data_center.id data_center_id,
+        data_center.uuid data_center_uuid,
+        data_center.name data_center_name,
+        data_center.is_security_group_enabled security_group_enabled,
+        host.id host_id,
+        host.uuid host_uuid,
+        host.name host_name,
+        vm_template.id template_id,
+        vm_template.uuid template_uuid,
+        vm_template.name template_name,
+        vm_template.display_text template_display_text,
+        vm_template.enable_password password_enabled,
+        iso.id iso_id,
+        iso.uuid iso_uuid,
+        iso.name iso_name,
+        iso.display_text iso_display_text,
+        service_offering.id service_offering_id,
+        disk_offering.uuid service_offering_uuid,
+        service_offering.cpu cpu,
+        service_offering.speed speed,
+        service_offering.ram_size ram_size,
+        disk_offering.name service_offering_name,
+        storage_pool.id pool_id,
+        storage_pool.uuid pool_uuid,
+        storage_pool.pool_type pool_type,
+        volumes.id volume_id,
+        volumes.uuid volume_uuid,
+        volumes.device_id volume_device_id,
+        volumes.volume_type volume_type,
+        security_group.id security_group_id,
+        security_group.uuid security_group_uuid,
+        security_group.name security_group_name,
+        security_group.description security_group_description,
+        nics.id nic_id,
+        nics.uuid nic_uuid,
+        nics.network_id network_id,
+        nics.ip4_address ip_address,
+        nics.ip6_address ip6_address,
+        nics.ip6_gateway ip6_gateway,
+        nics.ip6_cidr ip6_cidr,
+        nics.default_nic is_default_nic,
+        nics.gateway gateway,
+        nics.netmask netmask,
+        nics.mac_address mac_address,
+        nics.broadcast_uri broadcast_uri,
+        nics.isolation_uri isolation_uri,
+        vpc.id vpc_id,
+        vpc.uuid vpc_uuid,
+        networks.uuid network_uuid,
+        networks.name network_name,
+        networks.traffic_type traffic_type,
+        networks.guest_type guest_type,
+        user_ip_address.id public_ip_id,
+        user_ip_address.uuid public_ip_uuid,
+        user_ip_address.public_ip_address public_ip_address,
+        ssh_keypairs.keypair_name keypair_name,
+        resource_tags.id tag_id,
+        resource_tags.uuid tag_uuid,
+        resource_tags.key tag_key,
+        resource_tags.value tag_value,
+        resource_tags.domain_id tag_domain_id,
+        resource_tags.account_id tag_account_id,
+        resource_tags.resource_id tag_resource_id,
+        resource_tags.resource_uuid tag_resource_uuid,
+        resource_tags.resource_type tag_resource_type,
+        resource_tags.customer tag_customer,
+        async_job.id job_id,
+        async_job.uuid job_uuid,
+        async_job.job_status job_status,
+        async_job.account_id job_account_id,
+		affinity_group.id affinity_group_id,
+        affinity_group.uuid affinity_group_uuid,
+        affinity_group.name affinity_group_name,
+        affinity_group.description affinity_group_description
+    from
+        `cloud`.`user_vm`
+            inner join
+        `cloud`.`vm_instance` ON vm_instance.id = user_vm.id
+            and vm_instance.removed is NULL
+            inner join
+        `cloud`.`account` ON vm_instance.account_id = account.id
+            inner join
+        `cloud`.`domain` ON vm_instance.domain_id = domain.id
+            left join
+        `cloud`.`guest_os` ON vm_instance.guest_os_id = guest_os.id
+            left join
+        `cloud`.`host_pod_ref` ON vm_instance.pod_id = host_pod_ref.id
+            left join
+        `cloud`.`projects` ON projects.project_account_id = account.id
+            left join
+        `cloud`.`instance_group_vm_map` ON vm_instance.id = instance_group_vm_map.instance_id
+            left join
+        `cloud`.`instance_group` ON instance_group_vm_map.group_id = instance_group.id
+            left join
+        `cloud`.`data_center` ON vm_instance.data_center_id = data_center.id
+            left join
+        `cloud`.`host` ON vm_instance.host_id = host.id
+            left join
+        `cloud`.`vm_template` ON vm_instance.vm_template_id = vm_template.id
+            left join
+        `cloud`.`vm_template` iso ON iso.id = user_vm.iso_id
+            left join
+        `cloud`.`service_offering` ON vm_instance.service_offering_id = service_offering.id
+            left join
+        `cloud`.`disk_offering` ON vm_instance.service_offering_id = disk_offering.id
+            left join
+        `cloud`.`volumes` ON vm_instance.id = volumes.instance_id
+            left join
+        `cloud`.`storage_pool` ON volumes.pool_id = storage_pool.id
+            left join
+        `cloud`.`security_group_vm_map` ON vm_instance.id = security_group_vm_map.instance_id
+            left join
+        `cloud`.`security_group` ON security_group_vm_map.security_group_id = security_group.id
+            left join
+        `cloud`.`nics` ON vm_instance.id = nics.instance_id
+            left join
+        `cloud`.`networks` ON nics.network_id = networks.id
+            left join
+        `cloud`.`vpc` ON networks.vpc_id = vpc.id
+            left join
+        `cloud`.`user_ip_address` ON user_ip_address.vm_id = vm_instance.id
+            left join
+        `cloud`.`user_vm_details` ON user_vm_details.vm_id = vm_instance.id
+            and user_vm_details.name = 'SSH.PublicKey'
+            left join
+        `cloud`.`ssh_keypairs` ON ssh_keypairs.public_key = user_vm_details.value
+            left join
+        `cloud`.`resource_tags` ON resource_tags.resource_id = vm_instance.id
+            and resource_tags.resource_type = 'UserVm'
+            left join
+        `cloud`.`async_job` ON async_job.instance_id = vm_instance.id
+            and async_job.instance_type = 'VirtualMachine'
+            and async_job.job_status = 0
+            left join
+        `cloud`.`affinity_group_vm_map` ON vm_instance.id = affinity_group_vm_map.instance_id
+			left join
+        `cloud`.`affinity_group` ON affinity_group_vm_map.affinity_group_id = affinity_group.id;
+
+			
 -- Re-enable foreign key checking, at the end of the upgrade path
 SET foreign_key_checks = 1;			
\ No newline at end of file


[2/2] git commit: updated refs/heads/affinity_groups to 1b60135

Posted by pr...@apache.org.
Added AffinityGroup View in order to include VM details while listing AffinityGroups.


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

Branch: refs/heads/affinity_groups
Commit: 1b60135fbca6a4c1ce39ad1717411777a812c1ad
Parents: 68b74a1
Author: Prachi Damle <pr...@cloud.com>
Authored: Thu Apr 4 22:46:11 2013 -0700
Committer: Prachi Damle <pr...@cloud.com>
Committed: Thu Apr 4 22:46:11 2013 -0700

----------------------------------------------------------------------
 .../cloudstack/affinity/AffinityGroupResponse.java |   16 +-
 .../user/affinitygroup/ListAffinityGroupsCmd.java  |   26 +--
 .../affinitygroup/UpdateVMAffinityGroupCmd.java    |    8 +-
 .../org/apache/cloudstack/query/QueryService.java  |    4 +
 client/tomcatconf/applicationContext.xml.in        |   10 +
 client/tomcatconf/componentContext.xml.in          |    3 -
 .../affinity/HostAntiAffinityProcessor.java        |    9 +-
 server/src/com/cloud/api/ApiDBUtils.java           |   14 +
 .../src/com/cloud/api/query/QueryManagerImpl.java  |  108 +++++++
 .../com/cloud/api/query/ViewResponseHelper.java    |   18 +
 .../cloud/api/query/dao/AffinityGroupJoinDao.java  |   37 +++
 .../api/query/dao/AffinityGroupJoinDaoImpl.java    |  155 +++++++++
 .../cloud/api/query/vo/AffinityGroupJoinVO.java    |  248 +++++++++++++++
 .../affinity/dao/AffinityGroupDaoImpl.java         |    1 -
 .../affinity/dao/AffinityGroupVMMapDaoImpl.java    |    1 -
 setup/db/db/schema-410to420.sql                    |   34 ++-
 16 files changed, 660 insertions(+), 32 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/cloudstack/blob/1b60135f/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 073a82c..1ae7c59 100644
--- a/api/src/org/apache/cloudstack/affinity/AffinityGroupResponse.java
+++ b/api/src/org/apache/cloudstack/affinity/AffinityGroupResponse.java
@@ -17,6 +17,7 @@
 package org.apache.cloudstack.affinity;
 
 import java.util.HashSet;
+import java.util.LinkedHashSet;
 import java.util.Set;
 
 import org.apache.cloudstack.api.ApiConstants;
@@ -24,6 +25,7 @@ import org.apache.cloudstack.api.BaseResponse;
 import org.apache.cloudstack.api.EntityReference;
 import org.apache.cloudstack.api.response.ControlledEntityResponse;
 import org.apache.cloudstack.api.response.ControlledViewEntityResponse;
+import org.apache.cloudstack.api.response.UserVmResponse;
 
 import com.cloud.network.security.SecurityGroup;
 import com.cloud.serializer.Param;
@@ -31,7 +33,7 @@ import com.google.gson.annotations.SerializedName;
 
 @SuppressWarnings("unused")
 @EntityReference(value = AffinityGroup.class)
-public class AffinityGroupResponse extends BaseResponse implements ControlledEntityResponse {
+public class AffinityGroupResponse extends BaseResponse implements ControlledViewEntityResponse {
 
     @SerializedName(ApiConstants.ID) @Param(description="the ID of the affinity group")
     private String id;
@@ -55,8 +57,12 @@ public class AffinityGroupResponse extends BaseResponse implements ControlledEnt
     @Param(description = "the type of the affinity group")
     private String type;
 
+    @SerializedName("virtualmachine")
+    @Param(description = "virtual machines associated with this affinity group ", responseObject = UserVmResponse.class)
+    private Set<UserVmResponse> vmList;
 
     public AffinityGroupResponse() {
+        this.vmList = new LinkedHashSet<UserVmResponse>();
     }
 
     @Override
@@ -136,4 +142,12 @@ public class AffinityGroupResponse extends BaseResponse implements ControlledEnt
 
     }
 
+    public void setVMList(Set<UserVmResponse> vmList) {
+        this.vmList = vmList;
+    }
+
+    public void addVM(UserVmResponse vm) {
+        this.vmList.add(vm);
+    }
+
 }

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/1b60135f/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 effbd86..9310fb9 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
@@ -16,23 +16,16 @@
 // under the License.
 package org.apache.cloudstack.api.command.user.affinitygroup;
 
-import java.util.ArrayList;
-import java.util.List;
-
-import org.apache.cloudstack.affinity.AffinityGroup;
 import org.apache.cloudstack.affinity.AffinityGroupResponse;
 import org.apache.cloudstack.api.APICommand;
 import org.apache.cloudstack.api.ApiConstants;
-import org.apache.cloudstack.api.ApiErrorCode;
 import org.apache.cloudstack.api.BaseListCmd;
 import org.apache.cloudstack.api.Parameter;
-import org.apache.cloudstack.api.ServerApiException;
 import org.apache.cloudstack.api.response.ListResponse;
 import org.apache.cloudstack.api.response.UserVmResponse;
 import org.apache.log4j.Logger;
 
 import com.cloud.async.AsyncJob;
-import com.cloud.utils.Pair;
 
 @APICommand(name = "listAffinityGroups", description = "Lists affinity groups", responseObject = AffinityGroupResponse.class)
 public class ListAffinityGroupsCmd extends BaseListCmd {
@@ -83,22 +76,11 @@ public class ListAffinityGroupsCmd extends BaseListCmd {
     @Override
     public void execute(){
 
-        Pair<List<? extends AffinityGroup>, Integer> result = _affinityGroupService.listAffinityGroups(id,
-                affinityGroupName,
+        ListResponse<AffinityGroupResponse> response = _queryService.listAffinityGroups(id, affinityGroupName,
                 affinityGroupType, virtualMachineId, this.getStartIndex(), this.getPageSizeVal());
-        if (result != null) {
-            ListResponse<AffinityGroupResponse> response = new ListResponse<AffinityGroupResponse>();
-            List<AffinityGroupResponse> groupResponses = new ArrayList<AffinityGroupResponse>();
-            for (AffinityGroup group : result.first()) {
-                AffinityGroupResponse groupResponse = _responseGenerator.createAffinityGroupResponse(group);
-                groupResponses.add(groupResponse);
-            }
-            response.setResponses(groupResponses, result.second());
-            response.setResponseName(getCommandName());
-            this.setResponseObject(response);
-        } else {
-            throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, "Failed to search for affinity groups");
-        }
+        response.setResponseName(getCommandName());
+        this.setResponseObject(response);
+
     }
 
     @Override

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/1b60135f/api/src/org/apache/cloudstack/api/command/user/affinitygroup/UpdateVMAffinityGroupCmd.java
----------------------------------------------------------------------
diff --git a/api/src/org/apache/cloudstack/api/command/user/affinitygroup/UpdateVMAffinityGroupCmd.java b/api/src/org/apache/cloudstack/api/command/user/affinitygroup/UpdateVMAffinityGroupCmd.java
index 94f8446..44d017b 100644
--- a/api/src/org/apache/cloudstack/api/command/user/affinitygroup/UpdateVMAffinityGroupCmd.java
+++ b/api/src/org/apache/cloudstack/api/command/user/affinitygroup/UpdateVMAffinityGroupCmd.java
@@ -17,6 +17,7 @@
 package org.apache.cloudstack.api.command.user.affinitygroup;
 
 import java.util.ArrayList;
+import java.util.EnumSet;
 import java.util.List;
 
 import org.apache.cloudstack.affinity.AffinityGroupResponse;
@@ -27,6 +28,7 @@ import org.apache.cloudstack.api.ApiErrorCode;
 import org.apache.cloudstack.api.BaseAsyncCmd;
 import org.apache.cloudstack.api.Parameter;
 import org.apache.cloudstack.api.ServerApiException;
+import org.apache.cloudstack.api.ApiConstants.VMDetails;
 import org.apache.cloudstack.api.response.UserVmResponse;
 import org.apache.log4j.Logger;
 
@@ -131,8 +133,12 @@ public class UpdateVMAffinityGroupCmd extends BaseAsyncCmd {
             InsufficientCapacityException, ServerApiException {
         UserContext.current().setEventDetails("Vm Id: "+getId());
         UserVm result = _affinityGroupService.updateVMAffinityGroups(getId(), getAffinityGroupIdList());
+        ArrayList<VMDetails> dc = new ArrayList<VMDetails>();
+        dc.add(VMDetails.valueOf("affgrp"));
+        EnumSet<VMDetails> details = EnumSet.copyOf(dc);
+
         if (result != null){
-            UserVmResponse response = _responseGenerator.createUserVmResponse("virtualmachine", result).get(0);
+            UserVmResponse response = _responseGenerator.createUserVmResponse("virtualmachine", details, result).get(0);
             response.setResponseName(getCommandName());
             this.setResponseObject(response);
         } else {

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/1b60135f/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 c3f86aa..443c5df 100644
--- a/api/src/org/apache/cloudstack/query/QueryService.java
+++ b/api/src/org/apache/cloudstack/query/QueryService.java
@@ -16,6 +16,7 @@
 // under the License.
 package org.apache.cloudstack.query;
 
+import org.apache.cloudstack.affinity.AffinityGroupResponse;
 import org.apache.cloudstack.api.command.admin.host.ListHostsCmd;
 import org.apache.cloudstack.api.command.admin.router.ListRoutersCmd;
 import org.apache.cloudstack.api.command.admin.storage.ListStoragePoolsCmd;
@@ -97,4 +98,7 @@ public interface QueryService {
     public ListResponse<ServiceOfferingResponse>  searchForServiceOfferings(ListServiceOfferingsCmd cmd);
 
     public ListResponse<ZoneResponse>  listDataCenters(ListZonesByCmd cmd);
+
+    public ListResponse<AffinityGroupResponse> listAffinityGroups(Long affinityGroupId, String affinityGroupName,
+            String affinityGroupType, Long vmId, Long startIndex, Long pageSize);
 }

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/1b60135f/client/tomcatconf/applicationContext.xml.in
----------------------------------------------------------------------
diff --git a/client/tomcatconf/applicationContext.xml.in b/client/tomcatconf/applicationContext.xml.in
index 6cec8b3..ebce0e3 100644
--- a/client/tomcatconf/applicationContext.xml.in
+++ b/client/tomcatconf/applicationContext.xml.in
@@ -166,4 +166,14 @@
     </property>  
   </bean>
  
+  <bean id="AffinityGroupServiceImpl" class="org.apache.cloudstack.affinity.AffinityGroupServiceImpl"/>
+  <bean id="DeploymentPlanningManager" class="com.cloud.deploy.DeploymentPlanningManagerImpl" />
+  
+  <bean id="AffinityGroupJoinDaoImpl" class="com.cloud.api.query.dao.AffinityGroupJoinDaoImpl">
+  </bean>
+  <bean id="AffinityGroupDaoImpl" class="org.apache.cloudstack.affinity.dao.AffinityGroupDaoImpl">
+  </bean>
+  <bean id="AffinityGroupVMMapDaoImpl" class="org.apache.cloudstack.affinity.dao.AffinityGroupVMMapDaoImpl">
+  </bean>
+  
 </beans>

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/1b60135f/client/tomcatconf/componentContext.xml.in
----------------------------------------------------------------------
diff --git a/client/tomcatconf/componentContext.xml.in b/client/tomcatconf/componentContext.xml.in
index 2cfdada..fac17f0 100644
--- a/client/tomcatconf/componentContext.xml.in
+++ b/client/tomcatconf/componentContext.xml.in
@@ -77,9 +77,6 @@
   <bean id="UcsBladeDao" class="com.cloud.ucs.database.UcsBladeDaoImpl" />
   <bean id="UcsManagerDao" class="com.cloud.ucs.database.UcsManagerDaoImpl" />
 
-  <bean id="affinityGroupServiceImpl" class="org.apache.cloudstack.affinity.AffinityGroupServiceImpl"/>
-  <bean id="DeploymentPlanningManager" class="com.cloud.deploy.DeploymentPlanningManagerImpl" />
-   
   <!--
       Network Elements
   -->

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/1b60135f/plugins/affinity-group-processors/host-anti-affinity/src/org/apache/cloudstack/affinity/HostAntiAffinityProcessor.java
----------------------------------------------------------------------
diff --git a/plugins/affinity-group-processors/host-anti-affinity/src/org/apache/cloudstack/affinity/HostAntiAffinityProcessor.java b/plugins/affinity-group-processors/host-anti-affinity/src/org/apache/cloudstack/affinity/HostAntiAffinityProcessor.java
index 88030f2..4049571 100644
--- a/plugins/affinity-group-processors/host-anti-affinity/src/org/apache/cloudstack/affinity/HostAntiAffinityProcessor.java
+++ b/plugins/affinity-group-processors/host-anti-affinity/src/org/apache/cloudstack/affinity/HostAntiAffinityProcessor.java
@@ -65,8 +65,13 @@ public class HostAntiAffinityProcessor extends AffinityProcessorBase implements
 
             for (Long groupVMId : groupVMIds) {
                 VMInstanceVO groupVM = _vmInstanceDao.findById(groupVMId);
-                if (groupVM != null && !groupVM.isRemoved() && groupVM.getHostId() != null) {
-                    avoid.addHost(groupVM.getHostId());
+                if (groupVM != null && !groupVM.isRemoved()) {
+                    if (groupVM.getHostId() != null) {
+                        avoid.addHost(groupVM.getHostId());
+                    } else if (VirtualMachine.State.Stopped.equals(groupVM.getState())
+                            && groupVM.getLastHostId() != null) {
+                        avoid.addHost(groupVM.getLastHostId());
+                    }
                 }
             }
         }

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/1b60135f/server/src/com/cloud/api/ApiDBUtils.java
----------------------------------------------------------------------
diff --git a/server/src/com/cloud/api/ApiDBUtils.java b/server/src/com/cloud/api/ApiDBUtils.java
index 2823c61..332157a 100755
--- a/server/src/com/cloud/api/ApiDBUtils.java
+++ b/server/src/com/cloud/api/ApiDBUtils.java
@@ -26,6 +26,7 @@ import javax.annotation.PostConstruct;
 import javax.inject.Inject;
 
 import org.apache.cloudstack.affinity.AffinityGroup;
+import org.apache.cloudstack.affinity.AffinityGroupResponse;
 import org.apache.cloudstack.affinity.dao.AffinityGroupDao;
 import org.apache.cloudstack.api.ApiConstants.HostDetails;
 import org.apache.cloudstack.api.ApiConstants.VMDetails;
@@ -52,6 +53,7 @@ import org.apache.cloudstack.storage.datastore.db.StoragePoolVO;
 import org.springframework.stereotype.Component;
 
 import com.cloud.api.query.dao.AccountJoinDao;
+import com.cloud.api.query.dao.AffinityGroupJoinDao;
 import com.cloud.api.query.dao.AsyncJobJoinDao;
 import com.cloud.api.query.dao.DataCenterJoinDao;
 import com.cloud.api.query.dao.DiskOfferingJoinDao;
@@ -69,6 +71,7 @@ import com.cloud.api.query.dao.UserAccountJoinDao;
 import com.cloud.api.query.dao.UserVmJoinDao;
 import com.cloud.api.query.dao.VolumeJoinDao;
 import com.cloud.api.query.vo.AccountJoinVO;
+import com.cloud.api.query.vo.AffinityGroupJoinVO;
 import com.cloud.api.query.vo.AsyncJobJoinVO;
 import com.cloud.api.query.vo.DataCenterJoinVO;
 import com.cloud.api.query.vo.DiskOfferingJoinVO;
@@ -327,6 +330,7 @@ public class ApiDBUtils {
     static ClusterDetailsDao _clusterDetailsDao;
     static NicSecondaryIpDao _nicSecondaryIpDao;
     static AffinityGroupDao _affinityGroupDao;
+    static AffinityGroupJoinDao _affinityGroupJoinDao;
 
     @Inject private ManagementServer ms;
     @Inject public AsyncJobManager asyncMgr;
@@ -431,6 +435,7 @@ public class ApiDBUtils {
     @Inject private VMSnapshotDao vmSnapshotDao;
     @Inject private NicSecondaryIpDao nicSecondaryIpDao;
     @Inject private AffinityGroupDao affinityGroupDao;
+    @Inject private AffinityGroupJoinDao affinityGroupJoinDao;
 
     @PostConstruct
     void init() {
@@ -534,6 +539,7 @@ public class ApiDBUtils {
         _vmSnapshotDao = vmSnapshotDao;
         _nicSecondaryIpDao = nicSecondaryIpDao;
         _affinityGroupDao = affinityGroupDao;
+        _affinityGroupJoinDao = affinityGroupJoinDao;
         // Note: stats collector should already have been initialized by this time, otherwise a null instance is returned
         _statsCollector = StatsCollector.getInstance();
     }
@@ -1540,4 +1546,12 @@ public class ApiDBUtils {
     public static AffinityGroup getAffinityGroup(String groupName, long accountId) {
         return _affinityGroupDao.findByAccountAndName(accountId, groupName);
     }
+
+    public static AffinityGroupResponse newAffinityGroupResponse(AffinityGroupJoinVO group) {
+        return _affinityGroupJoinDao.newAffinityGroupResponse(group);
+    }
+
+    public static AffinityGroupResponse fillAffinityGroupDetails(AffinityGroupResponse resp, AffinityGroupJoinVO group) {
+        return _affinityGroupJoinDao.setAffinityGroupResponse(resp, group);
+    }
 }

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/1b60135f/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 951d09e..a498c18 100644
--- a/server/src/com/cloud/api/query/QueryManagerImpl.java
+++ b/server/src/com/cloud/api/query/QueryManagerImpl.java
@@ -27,6 +27,11 @@ import javax.ejb.Local;
 import javax.inject.Inject;
 import javax.naming.ConfigurationException;
 
+import org.apache.cloudstack.affinity.AffinityGroup;
+import org.apache.cloudstack.affinity.AffinityGroupResponse;
+import org.apache.cloudstack.affinity.AffinityGroupVMMapVO;
+import org.apache.cloudstack.affinity.AffinityGroupVO;
+import org.apache.cloudstack.affinity.dao.AffinityGroupVMMapDao;
 import org.apache.cloudstack.api.command.admin.host.ListHostsCmd;
 import org.apache.cloudstack.api.command.admin.router.ListRoutersCmd;
 import org.apache.cloudstack.api.command.admin.storage.ListStoragePoolsCmd;
@@ -69,6 +74,7 @@ import org.apache.log4j.Logger;
 import org.springframework.stereotype.Component;
 
 import com.cloud.api.query.dao.AccountJoinDao;
+import com.cloud.api.query.dao.AffinityGroupJoinDao;
 import com.cloud.api.query.dao.AsyncJobJoinDao;
 import com.cloud.api.query.dao.DataCenterJoinDao;
 import com.cloud.api.query.dao.DiskOfferingJoinDao;
@@ -86,6 +92,7 @@ import com.cloud.api.query.dao.UserAccountJoinDao;
 import com.cloud.api.query.dao.UserVmJoinDao;
 import com.cloud.api.query.dao.VolumeJoinDao;
 import com.cloud.api.query.vo.AccountJoinVO;
+import com.cloud.api.query.vo.AffinityGroupJoinVO;
 import com.cloud.api.query.vo.AsyncJobJoinVO;
 import com.cloud.api.query.vo.DataCenterJoinVO;
 import com.cloud.api.query.vo.DiskOfferingJoinVO;
@@ -138,6 +145,7 @@ import com.cloud.utils.Ternary;
 import com.cloud.utils.component.Manager;
 import com.cloud.utils.component.ManagerBase;
 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.SearchCriteria.Func;
@@ -246,6 +254,12 @@ public class QueryManagerImpl extends ManagerBase implements QueryService {
     @Inject
     private HighAvailabilityManager _haMgr;
 
+    @Inject
+    AffinityGroupVMMapDao _affinityGroupVMMapDao;
+
+    @Inject
+    private AffinityGroupJoinDao _affinityGroupJoinDao;
+
     /* (non-Javadoc)
      * @see com.cloud.api.query.QueryService#searchForUsers(org.apache.cloudstack.api.command.admin.user.ListUsersCmd)
      */
@@ -2328,5 +2342,99 @@ public class QueryManagerImpl extends ManagerBase implements QueryService {
         return false;
     }
 
+    @Override
+    public ListResponse<AffinityGroupResponse> listAffinityGroups(Long affinityGroupId, String affinityGroupName,
+            String affinityGroupType, Long vmId, Long startIndex, Long pageSize) {
+        Pair<List<AffinityGroupJoinVO>, Integer> result = listAffinityGroupsInternal(affinityGroupId,
+                affinityGroupName, affinityGroupType, vmId, startIndex, pageSize);
+        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, Long startIndex, Long pageSize) {
+
+        Account caller = UserContext.current().getCaller();
+
+        Long accountId = caller.getAccountId();
+        Long domainId = caller.getDomainId();
+
+        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);
+            return listAffinityGroupsByVM(vmId.longValue(), startIndex, pageSize);
+        }
+
+        Filter searchFilter = new Filter(AffinityGroupJoinVO.class, "id", true, startIndex, pageSize);
+        SearchBuilder<AffinityGroupJoinVO> groupSearch = _affinityGroupJoinDao.createSearchBuilder();
+        groupSearch.select(null, Func.DISTINCT, groupSearch.entity().getId()); // select
+                                                                               // distinct
+
+        SearchCriteria<AffinityGroupJoinVO> 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);
+        }
+
+
+        Pair<List<AffinityGroupJoinVO>, Integer> uniqueGroupsPair = _affinityGroupJoinDao.searchAndCount(sc,
+                searchFilter);
+        // search group details by ids
+        Integer count = uniqueGroupsPair.second();
+        if (count.intValue() == 0) {
+            // empty result
+            return uniqueGroupsPair;
+        }
+        List<AffinityGroupJoinVO> uniqueGroups = uniqueGroupsPair.first();
+        Long[] vrIds = new Long[uniqueGroups.size()];
+        int i = 0;
+        for (AffinityGroupJoinVO v : uniqueGroups) {
+            vrIds[i++] = v.getId();
+        }
+        List<AffinityGroupJoinVO> vrs = _affinityGroupJoinDao.searchByIds(vrIds);
+        return new Pair<List<AffinityGroupJoinVO>, Integer>(vrs, count);
+
+    }
+
+    private Pair<List<AffinityGroupJoinVO>, Integer> listAffinityGroupsByVM(long vmId, long pageInd, long pageSize) {
+        Filter sf = new Filter(SecurityGroupVMMapVO.class, null, true, pageInd, pageSize);
+        Pair<List<AffinityGroupVMMapVO>, Integer> agVmMappingPair = _affinityGroupVMMapDao.listByInstanceId(vmId, sf);
+        Integer count = agVmMappingPair.second();
+        if (count.intValue() == 0) {
+            // handle empty result cases
+            return new Pair<List<AffinityGroupJoinVO>, Integer>(new ArrayList<AffinityGroupJoinVO>(), count);
+        }
+        List<AffinityGroupVMMapVO> agVmMappings = agVmMappingPair.first();
+        Long[] agIds = new Long[agVmMappings.size()];
+        int i = 0;
+        for (AffinityGroupVMMapVO agVm : agVmMappings) {
+            agIds[i++] = agVm.getAffinityGroupId();
+        }
+        List<AffinityGroupJoinVO> ags = _affinityGroupJoinDao.searchByIds(agIds);
+        return new Pair<List<AffinityGroupJoinVO>, Integer>(ags, count);
+    }
 
 }

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/1b60135f/server/src/com/cloud/api/query/ViewResponseHelper.java
----------------------------------------------------------------------
diff --git a/server/src/com/cloud/api/query/ViewResponseHelper.java b/server/src/com/cloud/api/query/ViewResponseHelper.java
index 931327a..dc2727e 100644
--- a/server/src/com/cloud/api/query/ViewResponseHelper.java
+++ b/server/src/com/cloud/api/query/ViewResponseHelper.java
@@ -21,6 +21,7 @@ import java.util.EnumSet;
 import java.util.Hashtable;
 import java.util.List;
 
+import org.apache.cloudstack.affinity.AffinityGroupResponse;
 import org.apache.cloudstack.api.ApiConstants.HostDetails;
 import org.apache.cloudstack.api.ApiConstants.VMDetails;
 import org.apache.cloudstack.api.response.AccountResponse;
@@ -45,6 +46,7 @@ import org.apache.log4j.Logger;
 
 import com.cloud.api.ApiDBUtils;
 import com.cloud.api.query.vo.AccountJoinVO;
+import com.cloud.api.query.vo.AffinityGroupJoinVO;
 import com.cloud.api.query.vo.AsyncJobJoinVO;
 import com.cloud.api.query.vo.DataCenterJoinVO;
 import com.cloud.api.query.vo.DiskOfferingJoinVO;
@@ -303,4 +305,20 @@ public class ViewResponseHelper {
         }
         return respList;
     }
+
+    public static List<AffinityGroupResponse> createAffinityGroupResponses(List<AffinityGroupJoinVO> groups) {
+        Hashtable<Long, AffinityGroupResponse> vrDataList = new Hashtable<Long, AffinityGroupResponse>();
+        for (AffinityGroupJoinVO vr : groups) {
+            AffinityGroupResponse vrData = vrDataList.get(vr.getId());
+            if (vrData == null) {
+                // first time encountering this AffinityGroup
+                vrData = ApiDBUtils.newAffinityGroupResponse(vr);
+            } else {
+                // update vms
+                vrData = ApiDBUtils.fillAffinityGroupDetails(vrData, vr);
+            }
+            vrDataList.put(vr.getId(), vrData);
+        }
+        return new ArrayList<AffinityGroupResponse>(vrDataList.values());
+    }
 }

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/1b60135f/server/src/com/cloud/api/query/dao/AffinityGroupJoinDao.java
----------------------------------------------------------------------
diff --git a/server/src/com/cloud/api/query/dao/AffinityGroupJoinDao.java b/server/src/com/cloud/api/query/dao/AffinityGroupJoinDao.java
new file mode 100644
index 0000000..c029b3f
--- /dev/null
+++ b/server/src/com/cloud/api/query/dao/AffinityGroupJoinDao.java
@@ -0,0 +1,37 @@
+// 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 com.cloud.api.query.dao;
+
+import java.util.List;
+
+import org.apache.cloudstack.affinity.AffinityGroup;
+import org.apache.cloudstack.affinity.AffinityGroupResponse;
+import com.cloud.api.query.vo.AffinityGroupJoinVO;
+import com.cloud.user.Account;
+import com.cloud.utils.db.GenericDao;
+
+public interface AffinityGroupJoinDao extends GenericDao<AffinityGroupJoinVO, Long> {
+
+    AffinityGroupResponse newAffinityGroupResponse(AffinityGroupJoinVO vsg);
+
+    AffinityGroupResponse setAffinityGroupResponse(AffinityGroupResponse vsgData, AffinityGroupJoinVO vsg);
+
+    List<AffinityGroupJoinVO> newAffinityGroupView(AffinityGroup ag);
+
+    List<AffinityGroupJoinVO> searchByIds(Long... ids);
+}
+

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/1b60135f/server/src/com/cloud/api/query/dao/AffinityGroupJoinDaoImpl.java
----------------------------------------------------------------------
diff --git a/server/src/com/cloud/api/query/dao/AffinityGroupJoinDaoImpl.java b/server/src/com/cloud/api/query/dao/AffinityGroupJoinDaoImpl.java
new file mode 100644
index 0000000..98c6440
--- /dev/null
+++ b/server/src/com/cloud/api/query/dao/AffinityGroupJoinDaoImpl.java
@@ -0,0 +1,155 @@
+// 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 com.cloud.api.query.dao;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import javax.ejb.Local;
+import javax.inject.Inject;
+
+
+import org.apache.cloudstack.affinity.AffinityGroup;
+import org.apache.cloudstack.affinity.AffinityGroupResponse;
+import org.apache.cloudstack.api.response.UserVmResponse;
+import org.apache.log4j.Logger;
+import org.springframework.stereotype.Component;
+import com.cloud.api.ApiResponseHelper;
+import com.cloud.api.query.vo.AffinityGroupJoinVO;
+import com.cloud.configuration.dao.ConfigurationDao;
+import com.cloud.user.Account;
+import com.cloud.utils.db.GenericDaoBase;
+import com.cloud.utils.db.SearchBuilder;
+import com.cloud.utils.db.SearchCriteria;
+
+@Local(value = { AffinityGroupJoinDao.class })
+public class AffinityGroupJoinDaoImpl extends GenericDaoBase<AffinityGroupJoinVO, Long> implements AffinityGroupJoinDao {
+    public static final Logger s_logger = Logger.getLogger(AffinityGroupJoinDaoImpl.class);
+
+    @Inject
+    private ConfigurationDao  _configDao;
+
+    private final SearchBuilder<AffinityGroupJoinVO> agSearch;
+
+    private final SearchBuilder<AffinityGroupJoinVO> agIdSearch;
+
+    protected AffinityGroupJoinDaoImpl() {
+
+        agSearch = createSearchBuilder();
+        agSearch.and("idIN", agSearch.entity().getId(), SearchCriteria.Op.IN);
+        agSearch.done();
+
+        agIdSearch = createSearchBuilder();
+        agIdSearch.and("id", agIdSearch.entity().getId(), SearchCriteria.Op.EQ);
+        agIdSearch.done();
+
+        this._count = "select count(distinct id) from affinity_group_view WHERE ";
+    }
+
+    @Override
+    public AffinityGroupResponse newAffinityGroupResponse(AffinityGroupJoinVO vag) {
+        AffinityGroupResponse agResponse = new AffinityGroupResponse();
+        agResponse.setId(vag.getUuid());
+        agResponse.setName(vag.getName());
+        agResponse.setDescription(vag.getDescription());
+
+        ApiResponseHelper.populateOwner(agResponse, vag);
+
+        // update vm information
+        long instanceId = vag.getVmId();
+        if (instanceId > 0) {
+            UserVmResponse resp = new UserVmResponse();
+            resp.setObjectName("virtualmachine");
+            resp.setId(vag.getVmUuid());
+            resp.setName(vag.getVmName());
+            resp.setDisplayName(vag.getVmDisplayName());
+            resp.setState(vag.getVmState().toString());
+            agResponse.addVM(resp);
+        }
+
+        agResponse.setObjectName("affinitygroup");
+        return agResponse;
+    }
+
+    @Override
+    public AffinityGroupResponse setAffinityGroupResponse(AffinityGroupResponse vagData, AffinityGroupJoinVO vag) {
+        // update vm information
+        long instanceId = vag.getVmId();
+        if (instanceId > 0) {
+            UserVmResponse resp = new UserVmResponse();
+            resp.setObjectName("virtualmachine");
+            resp.setId(vag.getVmUuid());
+            resp.setName(vag.getVmName());
+            resp.setDisplayName(vag.getVmDisplayName());
+            resp.setState(vag.getVmState().toString());
+            vagData.addVM(resp);
+        }
+        return vagData;
+    }
+
+    @Override
+    public List<AffinityGroupJoinVO> newAffinityGroupView(AffinityGroup ag) {
+
+        SearchCriteria<AffinityGroupJoinVO> sc = agIdSearch.create();
+        sc.setParameters("id", ag.getId());
+        return searchIncludingRemoved(sc, null, null, false);
+    }
+
+    @Override
+    public List<AffinityGroupJoinVO> searchByIds(Long... agIds) {
+        // set detail batch query size
+        int DETAILS_BATCH_SIZE = 2000;
+        String batchCfg = _configDao.getValue("detail.batch.query.size");
+        if ( batchCfg != null ){
+            DETAILS_BATCH_SIZE = Integer.parseInt(batchCfg);
+        }
+        // query details by batches
+        List<AffinityGroupJoinVO> uvList = new ArrayList<AffinityGroupJoinVO>();
+        // query details by batches
+        int curr_index = 0;
+        if (agIds.length > DETAILS_BATCH_SIZE) {
+            while ((curr_index + DETAILS_BATCH_SIZE) <= agIds.length) {
+                Long[] ids = new Long[DETAILS_BATCH_SIZE];
+                for (int k = 0, j = curr_index; j < curr_index + DETAILS_BATCH_SIZE; j++, k++) {
+                    ids[k] = agIds[j];
+                }
+                SearchCriteria<AffinityGroupJoinVO> sc = agSearch.create();
+                sc.setParameters("idIN", ids);
+                List<AffinityGroupJoinVO> vms = searchIncludingRemoved(sc, null, null, false);
+                if (vms != null) {
+                    uvList.addAll(vms);
+                }
+                curr_index += DETAILS_BATCH_SIZE;
+            }
+        }
+        if (curr_index < agIds.length) {
+            int batch_size = (agIds.length - curr_index);
+            // set the ids value
+            Long[] ids = new Long[batch_size];
+            for (int k = 0, j = curr_index; j < curr_index + batch_size; j++, k++) {
+                ids[k] = agIds[j];
+            }
+            SearchCriteria<AffinityGroupJoinVO> sc = agSearch.create();
+            sc.setParameters("idIN", ids);
+            List<AffinityGroupJoinVO> vms = searchIncludingRemoved(sc, null, null, false);
+            if (vms != null) {
+                uvList.addAll(vms);
+            }
+        }
+        return uvList;
+    }
+}

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/1b60135f/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
new file mode 100644
index 0000000..e68996c
--- /dev/null
+++ b/server/src/com/cloud/api/query/vo/AffinityGroupJoinVO.java
@@ -0,0 +1,248 @@
+// 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 com.cloud.api.query.vo;
+
+import javax.persistence.Column;
+import javax.persistence.Entity;
+import javax.persistence.EnumType;
+import javax.persistence.Enumerated;
+import javax.persistence.Id;
+import javax.persistence.Table;
+
+import com.cloud.vm.VirtualMachine;
+
+@Entity
+@Table(name = "affinity_group_view")
+public class AffinityGroupJoinVO extends BaseViewVO implements ControlledViewEntity {
+
+    @Id
+    @Column(name="id", updatable=false, nullable = false)
+    private long id;
+
+    @Column(name="name")
+    private String name;
+
+    @Column(name = "description")
+    private String description;
+
+    @Column(name = "uuid")
+    private String uuid;
+
+    @Column(name="account_id")
+    private long accountId;
+
+    @Column(name="account_uuid")
+    private String accountUuid;
+
+    @Column(name="account_name")
+    private String accountName = null;
+
+    @Column(name="account_type")
+    private short accountType;
+
+    @Column(name="domain_id")
+    private long domainId;
+
+    @Column(name="domain_uuid")
+    private String domainUuid;
+
+    @Column(name="domain_name")
+    private String domainName = null;
+
+    @Column(name="domain_path")
+    private String domainPath = null;
+
+    @Column(name = "vm_id")
+    private long vmId;
+
+    @Column(name = "vm_uuid")
+    private String vmUuid;
+
+    @Column(name = "vm_name")
+    private String vmName;
+
+    @Column(name = "vm_display_name")
+    private String vmDisplayName;
+
+    @Column(name = "vm_state")
+    @Enumerated(value = EnumType.STRING)
+    protected VirtualMachine.State vmState = null;
+
+
+    public AffinityGroupJoinVO() {
+    }
+
+    @Override
+    public long getId() {
+        return id;
+    }
+
+    @Override
+    public void setId(long id) {
+        this.id = id;
+    }
+
+    @Override
+    public String getUuid() {
+        return uuid;
+    }
+
+    public void setUuid(String uuid) {
+        this.uuid = uuid;
+    }
+
+
+    public String getName() {
+        return name;
+    }
+
+    public void setName(String name) {
+        this.name = name;
+    }
+
+    @Override
+    public long getAccountId() {
+        return accountId;
+    }
+
+    public void setAccountId(long accountId) {
+        this.accountId = accountId;
+    }
+
+    @Override
+    public String getAccountUuid() {
+        return accountUuid;
+    }
+
+    public void setAccountUuid(String accountUuid) {
+        this.accountUuid = accountUuid;
+    }
+
+    @Override
+    public String getAccountName() {
+        return accountName;
+    }
+
+    public void setAccountName(String accountName) {
+        this.accountName = accountName;
+    }
+
+    @Override
+    public short getAccountType() {
+        return accountType;
+    }
+
+    public void setAccountType(short accountType) {
+        this.accountType = accountType;
+    }
+
+    @Override
+    public long getDomainId() {
+        return domainId;
+    }
+
+    public void setDomainId(long domainId) {
+        this.domainId = domainId;
+    }
+
+    @Override
+    public String getDomainUuid() {
+        return domainUuid;
+    }
+
+    public void setDomainUuid(String domainUuid) {
+        this.domainUuid = domainUuid;
+    }
+
+    @Override
+    public String getDomainName() {
+        return domainName;
+    }
+
+    public void setDomainName(String domainName) {
+        this.domainName = domainName;
+    }
+
+    @Override
+    public String getDomainPath() {
+        return domainPath;
+    }
+
+    public void setDomainPath(String domainPath) {
+        this.domainPath = domainPath;
+    }
+
+    public String getDescription() {
+        return description;
+    }
+
+    public void setDescription(String description) {
+        this.description = description;
+    }
+
+    public long getVmId() {
+        return vmId;
+    }
+
+    public void setVmId(long vmId) {
+        this.vmId = vmId;
+    }
+
+    public String getVmUuid() {
+        return vmUuid;
+    }
+
+    public void setVmUuid(String vmUuid) {
+        this.vmUuid = vmUuid;
+    }
+
+    public String getVmName() {
+        return vmName;
+    }
+
+    public void setVmName(String vmName) {
+        this.vmName = vmName;
+    }
+
+    public String getVmDisplayName() {
+        return vmDisplayName;
+    }
+
+    public void setVmDisplayName(String vmDisplayName) {
+        this.vmDisplayName = vmDisplayName;
+    }
+
+    public VirtualMachine.State getVmState() {
+        return vmState;
+    }
+
+    public void setVmState(VirtualMachine.State vmState) {
+        this.vmState = vmState;
+    }
+
+    @Override
+    public String getProjectUuid() {
+        // TODO Auto-generated method stub
+        return null;
+    }
+
+    @Override
+    public String getProjectName() {
+        // TODO Auto-generated method stub
+        return null;
+    }
+}

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/1b60135f/server/src/org/apache/cloudstack/affinity/dao/AffinityGroupDaoImpl.java
----------------------------------------------------------------------
diff --git a/server/src/org/apache/cloudstack/affinity/dao/AffinityGroupDaoImpl.java b/server/src/org/apache/cloudstack/affinity/dao/AffinityGroupDaoImpl.java
index f7db418..d189d60 100644
--- a/server/src/org/apache/cloudstack/affinity/dao/AffinityGroupDaoImpl.java
+++ b/server/src/org/apache/cloudstack/affinity/dao/AffinityGroupDaoImpl.java
@@ -26,7 +26,6 @@ import com.cloud.utils.db.GenericDaoBase;
 import com.cloud.utils.db.SearchBuilder;
 import com.cloud.utils.db.SearchCriteria;
 
-@Component
 @Local(value = { AffinityGroupDao.class })
 public class AffinityGroupDaoImpl extends GenericDaoBase<AffinityGroupVO, Long> implements AffinityGroupDao {
     private SearchBuilder<AffinityGroupVO> AccountIdSearch;

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/1b60135f/server/src/org/apache/cloudstack/affinity/dao/AffinityGroupVMMapDaoImpl.java
----------------------------------------------------------------------
diff --git a/server/src/org/apache/cloudstack/affinity/dao/AffinityGroupVMMapDaoImpl.java b/server/src/org/apache/cloudstack/affinity/dao/AffinityGroupVMMapDaoImpl.java
index b17d0b3..abc2a2b 100644
--- a/server/src/org/apache/cloudstack/affinity/dao/AffinityGroupVMMapDaoImpl.java
+++ b/server/src/org/apache/cloudstack/affinity/dao/AffinityGroupVMMapDaoImpl.java
@@ -37,7 +37,6 @@ import com.cloud.utils.db.SearchCriteria;
 import com.cloud.utils.db.SearchCriteria.Func;
 import com.cloud.utils.db.Transaction;
 
-@Component
 @Local(value = { AffinityGroupVMMapDao.class })
 public class AffinityGroupVMMapDaoImpl extends GenericDaoBase<AffinityGroupVMMapVO, Long> implements
         AffinityGroupVMMapDao {

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/1b60135f/setup/db/db/schema-410to420.sql
----------------------------------------------------------------------
diff --git a/setup/db/db/schema-410to420.sql b/setup/db/db/schema-410to420.sql
index fc0a718..cc759b8 100644
--- a/setup/db/db/schema-410to420.sql
+++ b/setup/db/db/schema-410to420.sql
@@ -591,6 +591,38 @@ CREATE VIEW `cloud`.`user_vm_view` AS
 			left join
         `cloud`.`affinity_group` ON affinity_group_vm_map.affinity_group_id = affinity_group.id;
 
-			
+DROP VIEW IF EXISTS `cloud`.`affinity_group_view`;
+CREATE VIEW `cloud`.`affinity_group_view` AS
+    select 
+        affinity_group.id id,
+        affinity_group.name name,
+        affinity_group.description description,
+        affinity_group.uuid uuid,
+        account.id account_id,
+        account.uuid account_uuid,
+        account.account_name account_name,
+        account.type account_type,
+        domain.id domain_id,
+        domain.uuid domain_uuid,
+        domain.name domain_name,
+        domain.path domain_path,
+        vm_instance.id vm_id,
+        vm_instance.uuid vm_uuid,
+        vm_instance.name vm_name,
+        vm_instance.state vm_state,
+        user_vm.display_name vm_display_name
+    from
+        `cloud`.`affinity_group`
+            inner join
+        `cloud`.`account` ON affinity_group.account_id = account.id
+            inner join
+        `cloud`.`domain` ON affinity_group.domain_id = domain.id
+            left join
+        `cloud`.`affinity_group_vm_map` ON affinity_group.id = affinity_group_vm_map.affinity_group_id
+            left join
+        `cloud`.`vm_instance` ON vm_instance.id = affinity_group_vm_map.instance_id
+            left join
+		`cloud`.`user_vm` ON user_vm.id = vm_instance.id;
+		
 -- Re-enable foreign key checking, at the end of the upgrade path
 SET foreign_key_checks = 1;			
\ No newline at end of file