You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@cloudstack.apache.org by sw...@apache.org on 2016/04/01 04:25:40 UTC

[2/4] git commit: updated refs/heads/master to 419f8fb

CLOUDSTACK-9298: Improve ListTemplatesCmd, ListVolumesCmd and ListVMsCmd performance


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

Branch: refs/heads/master
Commit: db54b26fed51d55879f2f704bcfbc25e52e15461
Parents: 9a9136e
Author: nvazquez <ni...@gmail.com>
Authored: Mon Feb 29 07:37:12 2016 -0800
Committer: nvazquez <ni...@gmail.com>
Committed: Thu Mar 10 06:07:29 2016 -0800

----------------------------------------------------------------------
 .../api/BaseResponseWithTagInformation.java     |  40 ++
 .../api/response/ResourceTagResponse.java       |   4 +
 .../api/response/TemplateResponse.java          |  13 +-
 .../cloudstack/api/response/UserVmResponse.java |  16 +-
 .../cloudstack/api/response/VolumeResponse.java |  20 +-
 .../dao/GenericDaoBaseWithTagInformation.java   |  51 +++
 .../api/query/dao/TemplateJoinDaoImpl.java      |  13 +-
 .../cloud/api/query/dao/UserVmJoinDaoImpl.java  |  14 +-
 .../cloud/api/query/dao/VolumeJoinDaoImpl.java  |  14 +-
 .../query/vo/BaseViewWithTagInformationVO.java  | 171 ++++++++
 .../cloud/api/query/vo/ResourceTagJoinVO.java   |  52 +++
 .../com/cloud/api/query/vo/TemplateJoinVO.java  |  79 +---
 .../com/cloud/api/query/vo/UserVmJoinVO.java    |  75 +---
 .../com/cloud/api/query/vo/VolumeJoinVO.java    |  75 +---
 ...enericDaoBaseWithTagInformationBaseTest.java |  90 +++++
 .../api/query/dao/TemplateJoinDaoImplTest.java  |  50 +++
 .../api/query/dao/UserVmJoinDaoImplTest.java    |  50 +++
 .../api/query/dao/VolumeJoinDaoImplTest.java    |  50 +++
 setup/db/db/schema-481to490.sql                 | 399 +++++++++++++++++++
 19 files changed, 987 insertions(+), 289 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/cloudstack/blob/db54b26f/api/src/org/apache/cloudstack/api/BaseResponseWithTagInformation.java
----------------------------------------------------------------------
diff --git a/api/src/org/apache/cloudstack/api/BaseResponseWithTagInformation.java b/api/src/org/apache/cloudstack/api/BaseResponseWithTagInformation.java
new file mode 100755
index 0000000..3d694a3
--- /dev/null
+++ b/api/src/org/apache/cloudstack/api/BaseResponseWithTagInformation.java
@@ -0,0 +1,40 @@
+// 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.api;
+
+import java.util.Set;
+
+import org.apache.cloudstack.api.response.ResourceTagResponse;
+
+import com.cloud.serializer.Param;
+import com.google.gson.annotations.SerializedName;
+
+public abstract class BaseResponseWithTagInformation extends BaseResponse {
+
+    @SerializedName(ApiConstants.TAGS)
+    @Param(description = "the list of resource tags associated", responseObject = ResourceTagResponse.class)
+    protected Set<ResourceTagResponse> tags;
+
+    public void addTag(ResourceTagResponse tag) {
+        this.tags.add(tag);
+    }
+
+    public Set<ResourceTagResponse> getTags(){
+        return this.tags;
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/db54b26f/api/src/org/apache/cloudstack/api/response/ResourceTagResponse.java
----------------------------------------------------------------------
diff --git a/api/src/org/apache/cloudstack/api/response/ResourceTagResponse.java b/api/src/org/apache/cloudstack/api/response/ResourceTagResponse.java
index ae61347..4432556 100644
--- a/api/src/org/apache/cloudstack/api/response/ResourceTagResponse.java
+++ b/api/src/org/apache/cloudstack/api/response/ResourceTagResponse.java
@@ -114,6 +114,10 @@ public class ResourceTagResponse extends BaseResponse implements ControlledViewE
         return this.key;
     }
 
+    public String getValue() {
+        return this.value;
+    }
+
     @Override
     public int hashCode() {
         final int prime = 31;

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/db54b26f/api/src/org/apache/cloudstack/api/response/TemplateResponse.java
----------------------------------------------------------------------
diff --git a/api/src/org/apache/cloudstack/api/response/TemplateResponse.java b/api/src/org/apache/cloudstack/api/response/TemplateResponse.java
index 3e21043..4986f2f 100644
--- a/api/src/org/apache/cloudstack/api/response/TemplateResponse.java
+++ b/api/src/org/apache/cloudstack/api/response/TemplateResponse.java
@@ -24,7 +24,7 @@ import java.util.Set;
 import com.google.gson.annotations.SerializedName;
 
 import org.apache.cloudstack.api.ApiConstants;
-import org.apache.cloudstack.api.BaseResponse;
+import org.apache.cloudstack.api.BaseResponseWithTagInformation;
 import org.apache.cloudstack.api.EntityReference;
 
 import com.cloud.serializer.Param;
@@ -33,7 +33,7 @@ import com.cloud.template.VirtualMachineTemplate;
 
 @EntityReference(value = VirtualMachineTemplate.class)
 @SuppressWarnings("unused")
-public class TemplateResponse extends BaseResponse implements ControlledViewEntityResponse {
+public class TemplateResponse extends BaseResponseWithTagInformation implements ControlledViewEntityResponse {
     @SerializedName(ApiConstants.ID)
     @Param(description = "the template ID")
     private String id;
@@ -175,10 +175,6 @@ public class TemplateResponse extends BaseResponse implements ControlledViewEnti
     //    @SerializedName("zones")  @Param(description="list of zones associated with tempate", responseObject = TemplateZoneResponse.class)
     //    private Set<TemplateZoneResponse> zones;
 
-    @SerializedName(ApiConstants.TAGS)
-    @Param(description = "the list of resource tags associated with tempate", responseObject = ResourceTagResponse.class)
-    private Set<ResourceTagResponse> tags;
-
     @SerializedName(ApiConstants.SSHKEY_ENABLED)
     @Param(description = "true if template is sshkey enabled, false otherwise")
     private Boolean sshKeyEnabled;
@@ -346,10 +342,6 @@ public class TemplateResponse extends BaseResponse implements ControlledViewEnti
         this.tags = tags;
     }
 
-    public void addTag(ResourceTagResponse tag) {
-        this.tags.add(tag);
-    }
-
     public void setSshKeyEnabled(boolean sshKeyEnabled) {
         this.sshKeyEnabled = sshKeyEnabled;
     }
@@ -361,4 +353,5 @@ public class TemplateResponse extends BaseResponse implements ControlledViewEnti
     public String getZoneId() {
         return zoneId;
     }
+
 }

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/db54b26f/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 e8d1a9e..d4e612b 100644
--- a/api/src/org/apache/cloudstack/api/response/UserVmResponse.java
+++ b/api/src/org/apache/cloudstack/api/response/UserVmResponse.java
@@ -24,7 +24,7 @@ import java.util.Set;
 import org.apache.cloudstack.acl.RoleType;
 import org.apache.cloudstack.affinity.AffinityGroupResponse;
 import org.apache.cloudstack.api.ApiConstants;
-import org.apache.cloudstack.api.BaseResponse;
+import org.apache.cloudstack.api.BaseResponseWithTagInformation;
 import org.apache.cloudstack.api.EntityReference;
 
 import com.cloud.network.router.VirtualRouter;
@@ -35,7 +35,7 @@ import com.google.gson.annotations.SerializedName;
 
 @SuppressWarnings("unused")
 @EntityReference(value = {VirtualMachine.class, UserVm.class, VirtualRouter.class})
-public class UserVmResponse extends BaseResponse implements ControlledEntityResponse {
+public class UserVmResponse extends BaseResponseWithTagInformation implements ControlledEntityResponse {
     @SerializedName(ApiConstants.ID)
     @Param(description = "the ID of the virtual machine")
     private String id;
@@ -244,10 +244,6 @@ public class UserVmResponse extends BaseResponse implements ControlledEntityResp
     @Param(description = "instance name of the user vm; this parameter is returned to the ROOT admin only", since = "3.0.1")
     private String instanceName;
 
-    @SerializedName(ApiConstants.TAGS)
-    @Param(description = "the list of resource tags associated with vm", responseObject = ResourceTagResponse.class)
-    private Set<ResourceTagResponse> tags;
-
     transient Set<Long> tagIds;
 
     @SerializedName(ApiConstants.DETAILS)
@@ -514,10 +510,6 @@ public class UserVmResponse extends BaseResponse implements ControlledEntityResp
         return instanceName;
     }
 
-    public Set<ResourceTagResponse> getTags() {
-        return tags;
-    }
-
     public String getKeyPairName() {
         return keyPairName;
     }
@@ -758,10 +750,6 @@ public class UserVmResponse extends BaseResponse implements ControlledEntityResp
         this.tags = tags;
     }
 
-    public void addTag(ResourceTagResponse tag) {
-        this.tags.add(tag);
-    }
-
     public void setKeyPairName(String keyPairName) {
         this.keyPairName = keyPairName;
     }

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/db54b26f/api/src/org/apache/cloudstack/api/response/VolumeResponse.java
----------------------------------------------------------------------
diff --git a/api/src/org/apache/cloudstack/api/response/VolumeResponse.java b/api/src/org/apache/cloudstack/api/response/VolumeResponse.java
index eeb4af9..a934563 100644
--- a/api/src/org/apache/cloudstack/api/response/VolumeResponse.java
+++ b/api/src/org/apache/cloudstack/api/response/VolumeResponse.java
@@ -22,7 +22,7 @@ import java.util.Set;
 
 import org.apache.cloudstack.acl.RoleType;
 import org.apache.cloudstack.api.ApiConstants;
-import org.apache.cloudstack.api.BaseResponse;
+import org.apache.cloudstack.api.BaseResponseWithTagInformation;
 import org.apache.cloudstack.api.EntityReference;
 
 import com.cloud.serializer.Param;
@@ -31,7 +31,7 @@ import com.google.gson.annotations.SerializedName;
 
 @EntityReference(value = Volume.class)
 @SuppressWarnings("unused")
-public class VolumeResponse extends BaseResponse implements ControlledViewEntityResponse {
+public class VolumeResponse extends BaseResponseWithTagInformation implements ControlledViewEntityResponse {
     @SerializedName(ApiConstants.ID)
     @Param(description = "ID of the disk volume")
     private String id;
@@ -212,10 +212,6 @@ public class VolumeResponse extends BaseResponse implements ControlledViewEntity
     @Param(description = "the status of the volume")
     private String status;
 
-    @SerializedName(ApiConstants.TAGS)
-    @Param(description = "the list of resource tags associated with volume", responseObject = ResourceTagResponse.class)
-    private Set<ResourceTagResponse> tags;
-
     @SerializedName(ApiConstants.DISPLAY_VOLUME)
     @Param(description = "an optional field whether to the display the volume to the end user or not.", authorized = {RoleType.Admin})
     private Boolean displayVolume;
@@ -439,14 +435,6 @@ public class VolumeResponse extends BaseResponse implements ControlledViewEntity
         this.projectName = projectName;
     }
 
-    public void setTags(Set<ResourceTagResponse> tags) {
-        this.tags = tags;
-    }
-
-    public void addTag(ResourceTagResponse tag) {
-        this.tags.add(tag);
-    }
-
     public void setDisplayVolume(Boolean displayVm) {
         this.displayVolume = displayVm;
     }
@@ -522,4 +510,8 @@ public class VolumeResponse extends BaseResponse implements ControlledViewEntity
     public void setTemplateDisplayText(String templateDisplayText) {
         this.templateDisplayText = templateDisplayText;
     }
+
+    public void setTags(Set<ResourceTagResponse> tags) {
+        this.tags = tags;
+    }
 }

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/db54b26f/server/src/com/cloud/api/query/dao/GenericDaoBaseWithTagInformation.java
----------------------------------------------------------------------
diff --git a/server/src/com/cloud/api/query/dao/GenericDaoBaseWithTagInformation.java b/server/src/com/cloud/api/query/dao/GenericDaoBaseWithTagInformation.java
new file mode 100755
index 0000000..e6760d8
--- /dev/null
+++ b/server/src/com/cloud/api/query/dao/GenericDaoBaseWithTagInformation.java
@@ -0,0 +1,51 @@
+// 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 org.apache.cloudstack.api.BaseResponseWithTagInformation;
+
+import com.cloud.api.ApiDBUtils;
+import com.cloud.api.query.vo.BaseViewWithTagInformationVO;
+import com.cloud.api.query.vo.ResourceTagJoinVO;
+import com.cloud.utils.db.GenericDaoBase;
+
+public abstract class GenericDaoBaseWithTagInformation<T extends BaseViewWithTagInformationVO, Z extends BaseResponseWithTagInformation> extends GenericDaoBase<T, Long> {
+
+    /**
+     * Update tag information on baseResponse
+     * @param baseView base view containing tag information
+     * @param baseResponse response to update
+     */
+    protected void addTagInformation(T baseView, Z baseResponse) {
+        ResourceTagJoinVO vtag = new ResourceTagJoinVO();
+        vtag.setId(baseView.getTagId());
+        vtag.setUuid(baseView.getTagUuid());
+        vtag.setKey(baseView.getTagKey());
+        vtag.setValue(baseView.getTagValue());
+        vtag.setDomainId(baseView.getTagDomainId());
+        vtag.setAccountId(baseView.getTagAccountId());
+        vtag.setResourceId(baseView.getTagResourceId());
+        vtag.setResourceUuid(baseView.getTagResourceUuid());
+        vtag.setResourceType(baseView.getTagResourceType());
+        vtag.setCustomer(baseView.getTagCustomer());
+        vtag.setAccountName(baseView.getTagAccountName());
+        vtag.setDomainName(baseView.getTagDomainName());
+        vtag.setDomainUuid(baseView.getTagDomainUuid());
+        baseResponse.addTag(ApiDBUtils.newResourceTagResponse(vtag, false));
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/db54b26f/server/src/com/cloud/api/query/dao/TemplateJoinDaoImpl.java
----------------------------------------------------------------------
diff --git a/server/src/com/cloud/api/query/dao/TemplateJoinDaoImpl.java b/server/src/com/cloud/api/query/dao/TemplateJoinDaoImpl.java
index 5444eca..38120af 100644
--- a/server/src/com/cloud/api/query/dao/TemplateJoinDaoImpl.java
+++ b/server/src/com/cloud/api/query/dao/TemplateJoinDaoImpl.java
@@ -46,13 +46,12 @@ import com.cloud.user.Account;
 import com.cloud.user.AccountService;
 import com.cloud.utils.Pair;
 import com.cloud.utils.db.Filter;
-import com.cloud.utils.db.GenericDaoBase;
 import com.cloud.utils.db.SearchBuilder;
 import com.cloud.utils.db.SearchCriteria;
 
 
 @Component
-public class TemplateJoinDaoImpl extends GenericDaoBase<TemplateJoinVO, Long> implements TemplateJoinDao {
+public class TemplateJoinDaoImpl extends GenericDaoBaseWithTagInformation<TemplateJoinVO, TemplateResponse> implements TemplateJoinDao {
 
     public static final Logger s_logger = Logger.getLogger(TemplateJoinDaoImpl.class);
 
@@ -188,10 +187,7 @@ public class TemplateJoinDaoImpl extends GenericDaoBase<TemplateJoinVO, Long> im
         // update tag information
         long tag_id = template.getTagId();
         if (tag_id > 0) {
-            ResourceTagJoinVO vtag = ApiDBUtils.findResourceTagViewById(tag_id);
-            if (vtag != null) {
-                templateResponse.addTag(ApiDBUtils.newResourceTagResponse(vtag, false));
-            }
+            addTagInformation(template, templateResponse);
         }
 
         templateResponse.setObjectName("template");
@@ -257,10 +253,7 @@ public class TemplateJoinDaoImpl extends GenericDaoBase<TemplateJoinVO, Long> im
         // update tag information
         long tag_id = template.getTagId();
         if (tag_id > 0) {
-            ResourceTagJoinVO vtag = ApiDBUtils.findResourceTagViewById(tag_id);
-            if (vtag != null) {
-                templateResponse.addTag(ApiDBUtils.newResourceTagResponse(vtag, false));
-            }
+            addTagInformation(template, templateResponse);
         }
 
         return templateResponse;

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/db54b26f/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 7983065..079da57 100644
--- a/server/src/com/cloud/api/query/dao/UserVmJoinDaoImpl.java
+++ b/server/src/com/cloud/api/query/dao/UserVmJoinDaoImpl.java
@@ -40,7 +40,6 @@ import org.apache.cloudstack.api.response.UserVmResponse;
 import org.apache.cloudstack.framework.config.dao.ConfigurationDao;
 
 import com.cloud.api.ApiDBUtils;
-import com.cloud.api.query.vo.ResourceTagJoinVO;
 import com.cloud.api.query.vo.UserVmJoinVO;
 import com.cloud.gpu.GPU;
 import com.cloud.hypervisor.Hypervisor.HypervisorType;
@@ -50,7 +49,6 @@ import com.cloud.user.AccountManager;
 import com.cloud.user.User;
 import com.cloud.user.dao.UserDao;
 import com.cloud.uservm.UserVm;
-import com.cloud.utils.db.GenericDaoBase;
 import com.cloud.utils.db.SearchBuilder;
 import com.cloud.utils.db.SearchCriteria;
 import com.cloud.vm.UserVmDetailVO;
@@ -61,7 +59,7 @@ import com.cloud.vm.dao.NicSecondaryIpVO;
 import com.cloud.vm.dao.UserVmDetailsDao;
 
 @Component
-public class UserVmJoinDaoImpl extends GenericDaoBase<UserVmJoinVO, Long> implements UserVmJoinDao {
+public class UserVmJoinDaoImpl extends GenericDaoBaseWithTagInformation<UserVmJoinVO, UserVmResponse> implements UserVmJoinDao {
     public static final Logger s_logger = Logger.getLogger(UserVmJoinDaoImpl.class);
 
     @Inject
@@ -283,10 +281,7 @@ public class UserVmJoinDaoImpl extends GenericDaoBase<UserVmJoinVO, Long> implem
         // update tag information
         long tag_id = userVm.getTagId();
         if (tag_id > 0 && !userVmResponse.containTag(tag_id)) {
-            ResourceTagJoinVO vtag = ApiDBUtils.findResourceTagViewById(tag_id);
-            if (vtag != null) {
-                userVmResponse.addTag(ApiDBUtils.newResourceTagResponse(vtag, false));
-            }
+            addTagInformation(userVm, userVmResponse);
         }
 
         if (details.contains(VMDetails.all) || details.contains(VMDetails.affgrp)) {
@@ -383,10 +378,7 @@ public class UserVmJoinDaoImpl extends GenericDaoBase<UserVmJoinVO, Long> implem
 
         long tag_id = uvo.getTagId();
         if (tag_id > 0 && !userVmData.containTag(tag_id)) {
-            ResourceTagJoinVO vtag = ApiDBUtils.findResourceTagViewById(tag_id);
-            if (vtag != null) {
-                userVmData.addTag(ApiDBUtils.newResourceTagResponse(vtag, false));
-            }
+            addTagInformation(uvo, userVmData);
         }
 
         Long affinityGroupId = uvo.getAffinityGroupId();

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/db54b26f/server/src/com/cloud/api/query/dao/VolumeJoinDaoImpl.java
----------------------------------------------------------------------
diff --git a/server/src/com/cloud/api/query/dao/VolumeJoinDaoImpl.java b/server/src/com/cloud/api/query/dao/VolumeJoinDaoImpl.java
index 54d1ca1..73e0c6d 100644
--- a/server/src/com/cloud/api/query/dao/VolumeJoinDaoImpl.java
+++ b/server/src/com/cloud/api/query/dao/VolumeJoinDaoImpl.java
@@ -29,7 +29,6 @@ import org.springframework.stereotype.Component;
 
 import com.cloud.api.ApiDBUtils;
 import com.cloud.api.ApiResponseHelper;
-import com.cloud.api.query.vo.ResourceTagJoinVO;
 import com.cloud.api.query.vo.VolumeJoinVO;
 import com.cloud.offering.ServiceOffering;
 import com.cloud.storage.Storage;
@@ -37,12 +36,11 @@ import com.cloud.storage.VMTemplateHostVO;
 import com.cloud.storage.VMTemplateStorageResourceAssoc.Status;
 import com.cloud.storage.Volume;
 import com.cloud.user.AccountManager;
-import com.cloud.utils.db.GenericDaoBase;
 import com.cloud.utils.db.SearchBuilder;
 import com.cloud.utils.db.SearchCriteria;
 
 @Component
-public class VolumeJoinDaoImpl extends GenericDaoBase<VolumeJoinVO, Long> implements VolumeJoinDao {
+public class VolumeJoinDaoImpl extends GenericDaoBaseWithTagInformation<VolumeJoinVO, VolumeResponse> implements VolumeJoinDao {
     public static final Logger s_logger = Logger.getLogger(VolumeJoinDaoImpl.class);
 
     @Inject
@@ -221,10 +219,7 @@ public class VolumeJoinDaoImpl extends GenericDaoBase<VolumeJoinVO, Long> implem
         // update tag information
         long tag_id = volume.getTagId();
         if (tag_id > 0) {
-            ResourceTagJoinVO vtag = ApiDBUtils.findResourceTagViewById(tag_id);
-            if (vtag != null) {
-                volResponse.addTag(ApiDBUtils.newResourceTagResponse(vtag, false));
-            }
+            addTagInformation(volume, volResponse);
         }
 
         volResponse.setExtractable(isExtractable);
@@ -253,10 +248,7 @@ public class VolumeJoinDaoImpl extends GenericDaoBase<VolumeJoinVO, Long> implem
     public VolumeResponse setVolumeResponse(ResponseView view, VolumeResponse volData, VolumeJoinVO vol) {
         long tag_id = vol.getTagId();
         if (tag_id > 0) {
-            ResourceTagJoinVO vtag = ApiDBUtils.findResourceTagViewById(tag_id);
-            if (vtag != null) {
-                volData.addTag(ApiDBUtils.newResourceTagResponse(vtag, false));
-            }
+            addTagInformation(vol, volData);
         }
         return volData;
     }

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/db54b26f/server/src/com/cloud/api/query/vo/BaseViewWithTagInformationVO.java
----------------------------------------------------------------------
diff --git a/server/src/com/cloud/api/query/vo/BaseViewWithTagInformationVO.java b/server/src/com/cloud/api/query/vo/BaseViewWithTagInformationVO.java
new file mode 100755
index 0000000..075cde2
--- /dev/null
+++ b/server/src/com/cloud/api/query/vo/BaseViewWithTagInformationVO.java
@@ -0,0 +1,171 @@
+// 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.EnumType;
+import javax.persistence.Enumerated;
+
+import com.cloud.server.ResourceTag.ResourceObjectType;
+
+public abstract class BaseViewWithTagInformationVO extends BaseViewVO {
+
+    @Column(name = "tag_id")
+    private long tagId;
+
+    @Column(name = "tag_uuid")
+    private String tagUuid;
+
+    @Column(name = "tag_key")
+    private String tagKey;
+
+    @Column(name = "tag_value")
+    private String tagValue;
+
+    @Column(name = "tag_domain_id")
+    private long tagDomainId;
+
+    @Column(name = "tag_account_id")
+    private long tagAccountId;
+
+    @Column(name = "tag_resource_id")
+    private long tagResourceId;
+
+    @Column(name = "tag_resource_uuid")
+    private String tagResourceUuid;
+
+    @Column(name = "tag_resource_type")
+    @Enumerated(value = EnumType.STRING)
+    private ResourceObjectType tagResourceType;
+
+    @Column(name = "tag_customer")
+    private String tagCustomer;
+
+    @Column(name = "tag_account_name")
+    private String tagAccountName;
+
+    @Column(name = "tag_domain_uuid")
+    private String tagDomainUuid;
+
+    @Column(name = "tag_domain_name")
+    private String tagDomainName;
+
+    public long getTagId() {
+        return tagId;
+    }
+
+    public void setTagId(long tagId) {
+        this.tagId = tagId;
+    }
+
+    public String getTagUuid() {
+        return tagUuid;
+    }
+
+    public void setTagUuid(String tagUuid) {
+        this.tagUuid = tagUuid;
+    }
+
+    public String getTagKey() {
+        return tagKey;
+    }
+
+    public void setTagKey(String tagKey) {
+        this.tagKey = tagKey;
+    }
+
+    public String getTagValue() {
+        return tagValue;
+    }
+
+    public void setTagValue(String tagValue) {
+        this.tagValue = tagValue;
+    }
+
+    public long getTagDomainId() {
+        return tagDomainId;
+    }
+
+    public void setTagDomainId(long tagDomainId) {
+        this.tagDomainId = tagDomainId;
+    }
+
+    public long getTagAccountId() {
+        return tagAccountId;
+    }
+
+    public void setTagAccountId(long tagAccountId) {
+        this.tagAccountId = tagAccountId;
+    }
+
+    public long getTagResourceId() {
+        return tagResourceId;
+    }
+
+    public void setTagResourceId(long tagResourceId) {
+        this.tagResourceId = tagResourceId;
+    }
+
+    public String getTagResourceUuid() {
+        return tagResourceUuid;
+    }
+
+    public void setTagResourceUuid(String tagResourceUuid) {
+        this.tagResourceUuid = tagResourceUuid;
+    }
+
+    public ResourceObjectType getTagResourceType() {
+        return tagResourceType;
+    }
+
+    public void setTagResourceType(ResourceObjectType tagResourceType) {
+        this.tagResourceType = tagResourceType;
+    }
+
+    public String getTagCustomer() {
+        return tagCustomer;
+    }
+
+    public void setTagCustomer(String tagCustomer) {
+        this.tagCustomer = tagCustomer;
+    }
+
+    public String getTagAccountName() {
+        return tagAccountName;
+    }
+
+    public void setTagAccountName(String tagAccountName) {
+        this.tagAccountName = tagAccountName;
+    }
+
+    public String getTagDomainUuid() {
+        return tagDomainUuid;
+    }
+
+    public void setTagDomainUuid(String tagDomainUuid) {
+        this.tagDomainUuid = tagDomainUuid;
+    }
+
+    public String getTagDomainName() {
+        return tagDomainName;
+    }
+
+    public void setTagDomainName(String tagDomainName) {
+        this.tagDomainName = tagDomainName;
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/db54b26f/server/src/com/cloud/api/query/vo/ResourceTagJoinVO.java
----------------------------------------------------------------------
diff --git a/server/src/com/cloud/api/query/vo/ResourceTagJoinVO.java b/server/src/com/cloud/api/query/vo/ResourceTagJoinVO.java
index 2c1ff47..6758552 100644
--- a/server/src/com/cloud/api/query/vo/ResourceTagJoinVO.java
+++ b/server/src/com/cloud/api/query/vo/ResourceTagJoinVO.java
@@ -184,4 +184,56 @@ public class ResourceTagJoinVO extends BaseViewVO implements ControlledViewEntit
     public Class<?> getEntityType() {
         return ResourceTag.class;
     }
+
+    public void setId(long id) {
+        this.id = id;
+    }
+
+    public void setUuid(String uuid) {
+        this.uuid = uuid;
+    }
+
+    public void setKey(String key) {
+        this.key = key;
+    }
+
+    public void setValue(String value) {
+        this.value = value;
+    }
+
+    public void setResourceId(long resourceId) {
+        this.resourceId = resourceId;
+    }
+
+    public void setResourceUuid(String resourceUuid) {
+        this.resourceUuid = resourceUuid;
+    }
+
+    public void setResourceType(ResourceObjectType resourceType) {
+        this.resourceType = resourceType;
+    }
+
+    public void setAccountId(long accountId) {
+        this.accountId = accountId;
+    }
+
+    public void setAccountName(String accountName) {
+        this.accountName = accountName;
+    }
+
+    public void setDomainId(long domainId) {
+        this.domainId = domainId;
+    }
+
+    public void setDomainUuid(String domainUuid) {
+        this.domainUuid = domainUuid;
+    }
+
+    public void setDomainName(String domainName) {
+        this.domainName = domainName;
+    }
+
+    public void setCustomer(String customer) {
+        this.customer = customer;
+    }
 }

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/db54b26f/server/src/com/cloud/api/query/vo/TemplateJoinVO.java
----------------------------------------------------------------------
diff --git a/server/src/com/cloud/api/query/vo/TemplateJoinVO.java b/server/src/com/cloud/api/query/vo/TemplateJoinVO.java
index 834a9ce..c8eed0a 100644
--- a/server/src/com/cloud/api/query/vo/TemplateJoinVO.java
+++ b/server/src/com/cloud/api/query/vo/TemplateJoinVO.java
@@ -30,7 +30,6 @@ import javax.persistence.TemporalType;
 import org.apache.cloudstack.engine.subsystem.api.storage.ObjectInDataStoreStateMachine;
 
 import com.cloud.hypervisor.Hypervisor.HypervisorType;
-import com.cloud.server.ResourceTag.ResourceObjectType;
 import com.cloud.storage.ScopeType;
 import com.cloud.storage.Storage;
 import com.cloud.storage.VMTemplateStorageResourceAssoc.Status;
@@ -40,7 +39,7 @@ import com.cloud.utils.db.GenericDao;
 
 @Entity
 @Table(name = "template_view")
-public class TemplateJoinVO extends BaseViewVO implements ControlledViewEntity {
+public class TemplateJoinVO extends BaseViewWithTagInformationVO implements ControlledViewEntity {
 
     @Id
     @Column(name = "id")
@@ -218,37 +217,6 @@ public class TemplateJoinVO extends BaseViewVO implements ControlledViewEntity {
     @Column(name = "detail_value")
     private String detailValue;
 
-    @Column(name = "tag_id")
-    private long tagId;
-
-    @Column(name = "tag_uuid")
-    private String tagUuid;
-
-    @Column(name = "tag_key")
-    private String tagKey;
-
-    @Column(name = "tag_value")
-    private String tagValue;
-
-    @Column(name = "tag_domain_id")
-    private long tagDomainId;
-
-    @Column(name = "tag_account_id")
-    private long tagAccountId;
-
-    @Column(name = "tag_resource_id")
-    private long tagResourceId;
-
-    @Column(name = "tag_resource_uuid")
-    private String tagResourceUuid;
-
-    @Column(name = "tag_resource_type")
-    @Enumerated(value = EnumType.STRING)
-    private ResourceObjectType tagResourceType;
-
-    @Column(name = "tag_customer")
-    private String tagCustomer;
-
     @Column(name = "state")
     @Enumerated(EnumType.STRING)
     ObjectInDataStoreStateMachine.State state;
@@ -343,46 +311,6 @@ public class TemplateJoinVO extends BaseViewVO implements ControlledViewEntity {
         return templateType;
     }
 
-    public long getTagId() {
-        return tagId;
-    }
-
-    public String getTagUuid() {
-        return tagUuid;
-    }
-
-    public String getTagKey() {
-        return tagKey;
-    }
-
-    public String getTagValue() {
-        return tagValue;
-    }
-
-    public long getTagDomainId() {
-        return tagDomainId;
-    }
-
-    public long getTagAccountId() {
-        return tagAccountId;
-    }
-
-    public long getTagResourceId() {
-        return tagResourceId;
-    }
-
-    public String getTagResourceUuid() {
-        return tagResourceUuid;
-    }
-
-    public ResourceObjectType getTagResourceType() {
-        return tagResourceType;
-    }
-
-    public String getTagCustomer() {
-        return tagCustomer;
-    }
-
     public long getDataCenterId() {
         return dataCenterId;
     }
@@ -547,4 +475,9 @@ public class TemplateJoinVO extends BaseViewVO implements ControlledViewEntity {
     public Class<?> getEntityType() {
         return VirtualMachineTemplate.class;
     }
+
+    public void setAccountId(long accountId) {
+        this.accountId = accountId;
+    }
+
 }

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/db54b26f/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 54a48fb..2847c6b 100644
--- a/server/src/com/cloud/api/query/vo/UserVmJoinVO.java
+++ b/server/src/com/cloud/api/query/vo/UserVmJoinVO.java
@@ -31,7 +31,6 @@ import javax.persistence.Transient;
 import com.cloud.hypervisor.Hypervisor.HypervisorType;
 import com.cloud.network.Network.GuestType;
 import com.cloud.network.Networks.TrafficType;
-import com.cloud.server.ResourceTag.ResourceObjectType;
 import com.cloud.storage.Storage.StoragePoolType;
 import com.cloud.storage.Volume;
 import com.cloud.utils.db.GenericDao;
@@ -40,7 +39,7 @@ import com.cloud.vm.VirtualMachine.State;
 
 @Entity
 @Table(name = "user_vm_view")
-public class UserVmJoinVO extends BaseViewVO implements ControlledViewEntity {
+public class UserVmJoinVO extends BaseViewWithTagInformationVO implements ControlledViewEntity {
 
     @Id
     @Column(name = "id", updatable = false, nullable = false)
@@ -346,37 +345,6 @@ public class UserVmJoinVO extends BaseViewVO implements ControlledViewEntity {
     @Column(name = "job_status")
     private int jobStatus;
 
-    @Column(name = "tag_id")
-    private long tagId;
-
-    @Column(name = "tag_uuid")
-    private String tagUuid;
-
-    @Column(name = "tag_key")
-    private String tagKey;
-
-    @Column(name = "tag_value")
-    private String tagValue;
-
-    @Column(name = "tag_domain_id")
-    private long tagDomainId;
-
-    @Column(name = "tag_account_id")
-    private long tagAccountId;
-
-    @Column(name = "tag_resource_id")
-    private long tagResourceId;
-
-    @Column(name = "tag_resource_uuid")
-    private String tagResourceUuid;
-
-    @Column(name = "tag_resource_type")
-    @Enumerated(value = EnumType.STRING)
-    private ResourceObjectType tagResourceType;
-
-    @Column(name = "tag_customer")
-    private String tagCustomer;
-
     @Column(name = "affinity_group_id")
     private long affinityGroupId;
 
@@ -776,46 +744,6 @@ public class UserVmJoinVO extends BaseViewVO implements ControlledViewEntity {
         return keypairName;
     }
 
-    public long getTagId() {
-        return tagId;
-    }
-
-    public String getTagUuid() {
-        return tagUuid;
-    }
-
-    public String getTagKey() {
-        return tagKey;
-    }
-
-    public String getTagValue() {
-        return tagValue;
-    }
-
-    public long getTagDomainId() {
-        return tagDomainId;
-    }
-
-    public long getTagAccountId() {
-        return tagAccountId;
-    }
-
-    public long getTagResourceId() {
-        return tagResourceId;
-    }
-
-    public String getTagResourceUuid() {
-        return tagResourceUuid;
-    }
-
-    public ResourceObjectType getTagResourceType() {
-        return tagResourceType;
-    }
-
-    public String getTagCustomer() {
-        return tagCustomer;
-    }
-
     public boolean isLimitCpuUse() {
         return limitCpuUse;
     }
@@ -907,4 +835,5 @@ public class UserVmJoinVO extends BaseViewVO implements ControlledViewEntity {
     public Class<?> getEntityType() {
         return VirtualMachine.class;
     }
+
 }

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/db54b26f/server/src/com/cloud/api/query/vo/VolumeJoinVO.java
----------------------------------------------------------------------
diff --git a/server/src/com/cloud/api/query/vo/VolumeJoinVO.java b/server/src/com/cloud/api/query/vo/VolumeJoinVO.java
index d9c482c..e39b1b1 100644
--- a/server/src/com/cloud/api/query/vo/VolumeJoinVO.java
+++ b/server/src/com/cloud/api/query/vo/VolumeJoinVO.java
@@ -28,7 +28,6 @@ import javax.persistence.Temporal;
 import javax.persistence.TemporalType;
 
 import com.cloud.hypervisor.Hypervisor.HypervisorType;
-import com.cloud.server.ResourceTag.ResourceObjectType;
 import com.cloud.storage.Storage;
 import com.cloud.storage.VMTemplateStorageResourceAssoc.Status;
 import com.cloud.storage.Volume;
@@ -37,7 +36,7 @@ import com.cloud.vm.VirtualMachine;
 
 @Entity
 @Table(name = "volume_view")
-public class VolumeJoinVO extends BaseViewVO implements ControlledViewEntity {
+public class VolumeJoinVO extends BaseViewWithTagInformationVO implements ControlledViewEntity {
 
     @Id
     @Column(name = "id")
@@ -252,37 +251,6 @@ public class VolumeJoinVO extends BaseViewVO implements ControlledViewEntity {
     @Column(name = "job_status")
     private int jobStatus;
 
-    @Column(name = "tag_id")
-    private long tagId;
-
-    @Column(name = "tag_uuid")
-    private String tagUuid;
-
-    @Column(name = "tag_key")
-    private String tagKey;
-
-    @Column(name = "tag_value")
-    private String tagValue;
-
-    @Column(name = "tag_domain_id")
-    private long tagDomainId;
-
-    @Column(name = "tag_account_id")
-    private long tagAccountId;
-
-    @Column(name = "tag_resource_id")
-    private long tagResourceId;
-
-    @Column(name = "tag_resource_uuid")
-    private String tagResourceUuid;
-
-    @Column(name = "tag_resource_type")
-    @Enumerated(value = EnumType.STRING)
-    private ResourceObjectType tagResourceType;
-
-    @Column(name = "tag_customer")
-    private String tagCustomer;
-
     @Column(name = "display_volume", updatable = true, nullable = false)
     protected boolean displayVolume;
 
@@ -563,46 +531,6 @@ public class VolumeJoinVO extends BaseViewVO implements ControlledViewEntity {
         return jobStatus;
     }
 
-    public long getTagId() {
-        return tagId;
-    }
-
-    public String getTagUuid() {
-        return tagUuid;
-    }
-
-    public String getTagKey() {
-        return tagKey;
-    }
-
-    public String getTagValue() {
-        return tagValue;
-    }
-
-    public long getTagDomainId() {
-        return tagDomainId;
-    }
-
-    public long getTagAccountId() {
-        return tagAccountId;
-    }
-
-    public long getTagResourceId() {
-        return tagResourceId;
-    }
-
-    public String getTagResourceUuid() {
-        return tagResourceUuid;
-    }
-
-    public ResourceObjectType getTagResourceType() {
-        return tagResourceType;
-    }
-
-    public String getTagCustomer() {
-        return tagCustomer;
-    }
-
     public long getDataCenterId() {
         return dataCenterId;
     }
@@ -636,4 +564,5 @@ public class VolumeJoinVO extends BaseViewVO implements ControlledViewEntity {
     public Class<?> getEntityType() {
         return Volume.class;
     }
+
 }

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/db54b26f/server/test/com/cloud/api/query/dao/GenericDaoBaseWithTagInformationBaseTest.java
----------------------------------------------------------------------
diff --git a/server/test/com/cloud/api/query/dao/GenericDaoBaseWithTagInformationBaseTest.java b/server/test/com/cloud/api/query/dao/GenericDaoBaseWithTagInformationBaseTest.java
new file mode 100755
index 0000000..c7c65f8
--- /dev/null
+++ b/server/test/com/cloud/api/query/dao/GenericDaoBaseWithTagInformationBaseTest.java
@@ -0,0 +1,90 @@
+// 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 static org.junit.Assert.assertEquals;
+
+import org.apache.cloudstack.api.BaseResponseWithTagInformation;
+import org.apache.cloudstack.api.response.ResourceTagResponse;
+import org.powermock.api.mockito.PowerMockito;
+
+import com.cloud.api.ApiDBUtils;
+import com.cloud.api.query.vo.BaseViewWithTagInformationVO;
+import com.cloud.server.ResourceTag.ResourceObjectType;
+
+public abstract class GenericDaoBaseWithTagInformationBaseTest<T extends BaseViewWithTagInformationVO,
+                                                                Z extends BaseResponseWithTagInformation> {
+
+    private final static long TAG_ID = 1l;
+    private final static String TAG_KEY = "type";
+    private final static String TAG_VALUE = "supported";
+    private final static String TAG_UUID = "aaaa-aaaa-aaaa-aaaa";
+    private final static ResourceObjectType TAG_RESOURCE_TYPE = ResourceObjectType.Template;
+    private final static String TAG_RESOURCE_TYPE_STR = "Template";
+    private final static String TAG_RESOURCE_UUID = "aaaa-aaaa-aaaa-aaaa";
+    private final static long TAG_DOMAIN_ID = 123l;
+    private final static String TAG_DOMAIN_ID_STR = "123";
+    private final static String TAG_DOMAIN_NAME = "aaaa-aaaa-aaaa-aaaa";
+    private final static String TAG_CUSTOMER = "aaaa-aaaa-aaaa-aaaa";
+    private final static String TAG_ACCOUNT_NAME = "admin";
+
+    private final static String RESPONSE_OBJECT_NAME = "tag";
+
+    public void prepareSetup(){
+        PowerMockito.spy(ApiDBUtils.class);
+        PowerMockito.stub(PowerMockito.method(ApiDBUtils.class, "newResourceTagResponse")).toReturn(getResourceTagResponse());
+    }
+
+    private ResourceTagResponse getResourceTagResponse(){
+        ResourceTagResponse tagResponse = new ResourceTagResponse();
+        tagResponse.setKey(TAG_KEY);
+        tagResponse.setValue(TAG_VALUE);
+        tagResponse.setObjectName(RESPONSE_OBJECT_NAME);
+        tagResponse.setResourceType(TAG_RESOURCE_TYPE_STR);
+        tagResponse.setResourceId(TAG_RESOURCE_UUID);
+        tagResponse.setDomainId(TAG_DOMAIN_ID_STR);
+        tagResponse.setDomainName(TAG_DOMAIN_NAME);
+        tagResponse.setCustomer(TAG_CUSTOMER);
+        tagResponse.setAccountName(TAG_ACCOUNT_NAME);
+        return tagResponse;
+    }
+
+    private void prepareBaseView(long tagId, T baseView){
+        baseView.setTagId(tagId);
+        baseView.setTagKey(TAG_KEY);
+        baseView.setTagValue(TAG_VALUE);
+        baseView.setTagUuid(TAG_UUID);
+        baseView.setTagResourceType(TAG_RESOURCE_TYPE);
+        baseView.setTagAccountName(TAG_ACCOUNT_NAME);
+        baseView.setTagDomainId(TAG_DOMAIN_ID);
+        baseView.setTagDomainName(TAG_DOMAIN_NAME);
+        baseView.setTagCustomer(TAG_CUSTOMER);
+        baseView.setTagAccountName(TAG_ACCOUNT_NAME);
+    }
+
+    public void testUpdateTagInformation(GenericDaoBaseWithTagInformation<T, Z> dao, T baseView, Z baseResponse){
+        prepareBaseView(TAG_ID, baseView);
+        dao.addTagInformation(baseView, baseResponse);
+        ResourceTagResponse[] responseArray = new ResourceTagResponse[baseResponse.getTags().size()];
+        baseResponse.getTags().toArray(responseArray);
+        assertEquals(1, responseArray.length);
+        assertEquals(TAG_KEY, responseArray[0].getKey());
+        assertEquals(TAG_VALUE, responseArray[0].getValue());
+        assertEquals(RESPONSE_OBJECT_NAME, responseArray[0].getObjectName());
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/db54b26f/server/test/com/cloud/api/query/dao/TemplateJoinDaoImplTest.java
----------------------------------------------------------------------
diff --git a/server/test/com/cloud/api/query/dao/TemplateJoinDaoImplTest.java b/server/test/com/cloud/api/query/dao/TemplateJoinDaoImplTest.java
new file mode 100755
index 0000000..d194e32
--- /dev/null
+++ b/server/test/com/cloud/api/query/dao/TemplateJoinDaoImplTest.java
@@ -0,0 +1,50 @@
+// 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 org.apache.cloudstack.api.response.TemplateResponse;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.InjectMocks;
+import org.powermock.core.classloader.annotations.PrepareForTest;
+import org.powermock.modules.junit4.PowerMockRunner;
+
+import com.cloud.api.ApiDBUtils;
+import com.cloud.api.query.vo.TemplateJoinVO;
+
+@RunWith(PowerMockRunner.class)
+@PrepareForTest(ApiDBUtils.class)
+public class TemplateJoinDaoImplTest extends GenericDaoBaseWithTagInformationBaseTest<TemplateJoinVO, TemplateResponse> {
+
+    @InjectMocks
+    private TemplateJoinDaoImpl _templateJoinDaoImpl;
+
+    private TemplateJoinVO template = new TemplateJoinVO();
+    private TemplateResponse templateResponse = new TemplateResponse();
+
+    @Before
+    public void setup() {
+        prepareSetup();
+    }
+
+    @Test
+    public void testUpdateTemplateTagInfo(){
+        testUpdateTagInformation(_templateJoinDaoImpl, template, templateResponse);
+    }
+
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/db54b26f/server/test/com/cloud/api/query/dao/UserVmJoinDaoImplTest.java
----------------------------------------------------------------------
diff --git a/server/test/com/cloud/api/query/dao/UserVmJoinDaoImplTest.java b/server/test/com/cloud/api/query/dao/UserVmJoinDaoImplTest.java
new file mode 100755
index 0000000..669143e
--- /dev/null
+++ b/server/test/com/cloud/api/query/dao/UserVmJoinDaoImplTest.java
@@ -0,0 +1,50 @@
+// 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 org.apache.cloudstack.api.response.UserVmResponse;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.InjectMocks;
+import org.powermock.core.classloader.annotations.PrepareForTest;
+import org.powermock.modules.junit4.PowerMockRunner;
+
+import com.cloud.api.ApiDBUtils;
+import com.cloud.api.query.vo.UserVmJoinVO;
+
+@RunWith(PowerMockRunner.class)
+@PrepareForTest(ApiDBUtils.class)
+public class UserVmJoinDaoImplTest extends GenericDaoBaseWithTagInformationBaseTest<UserVmJoinVO, UserVmResponse> {
+
+    @InjectMocks
+    private UserVmJoinDaoImpl _userVmJoinDaoImpl;
+
+    private UserVmJoinVO userVm = new UserVmJoinVO();
+    private UserVmResponse userVmResponse = new UserVmResponse();
+
+    @Before
+    public void setup() {
+        prepareSetup();
+    }
+
+    @Test
+    public void testUpdateUserVmTagInfo(){
+        testUpdateTagInformation(_userVmJoinDaoImpl, userVm, userVmResponse);
+    }
+
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/db54b26f/server/test/com/cloud/api/query/dao/VolumeJoinDaoImplTest.java
----------------------------------------------------------------------
diff --git a/server/test/com/cloud/api/query/dao/VolumeJoinDaoImplTest.java b/server/test/com/cloud/api/query/dao/VolumeJoinDaoImplTest.java
new file mode 100755
index 0000000..b0b0ad2
--- /dev/null
+++ b/server/test/com/cloud/api/query/dao/VolumeJoinDaoImplTest.java
@@ -0,0 +1,50 @@
+// 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 org.apache.cloudstack.api.response.VolumeResponse;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.InjectMocks;
+import org.powermock.core.classloader.annotations.PrepareForTest;
+import org.powermock.modules.junit4.PowerMockRunner;
+
+import com.cloud.api.ApiDBUtils;
+import com.cloud.api.query.vo.VolumeJoinVO;
+
+@RunWith(PowerMockRunner.class)
+@PrepareForTest(ApiDBUtils.class)
+public class VolumeJoinDaoImplTest extends GenericDaoBaseWithTagInformationBaseTest<VolumeJoinVO, VolumeResponse> {
+
+    @InjectMocks
+    private VolumeJoinDaoImpl _volumeJoinDaoImpl;
+
+    private VolumeJoinVO volume = new VolumeJoinVO();
+    private VolumeResponse volumeResponse = new VolumeResponse();
+
+    @Before
+    public void setup() {
+        prepareSetup();
+    }
+
+    @Test
+    public void testUpdateVolumeTagInfo(){
+        testUpdateTagInformation(_volumeJoinDaoImpl, volume, volumeResponse);
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/db54b26f/setup/db/db/schema-481to490.sql
----------------------------------------------------------------------
diff --git a/setup/db/db/schema-481to490.sql b/setup/db/db/schema-481to490.sql
index 0f27e45..cebe605 100644
--- a/setup/db/db/schema-481to490.sql
+++ b/setup/db/db/schema-481to490.sql
@@ -21,3 +21,402 @@
 
 ALTER TABLE `event` ADD INDEX `archived` (`archived`);
 ALTER TABLE `event` ADD INDEX `state` (`state`);
+
+DROP VIEW IF EXISTS `cloud`.`template_view`;
+CREATE 
+    ALGORITHM = UNDEFINED 
+    DEFINER = `cloud`@`%` 
+    SQL SECURITY DEFINER
+VIEW `template_view` AS
+    SELECT 
+        `vm_template`.`id` AS `id`,
+        `vm_template`.`uuid` AS `uuid`,
+        `vm_template`.`unique_name` AS `unique_name`,
+        `vm_template`.`name` AS `name`,
+        `vm_template`.`public` AS `public`,
+        `vm_template`.`featured` AS `featured`,
+        `vm_template`.`type` AS `type`,
+        `vm_template`.`hvm` AS `hvm`,
+        `vm_template`.`bits` AS `bits`,
+        `vm_template`.`url` AS `url`,
+        `vm_template`.`format` AS `format`,
+        `vm_template`.`created` AS `created`,
+        `vm_template`.`checksum` AS `checksum`,
+        `vm_template`.`display_text` AS `display_text`,
+        `vm_template`.`enable_password` AS `enable_password`,
+        `vm_template`.`dynamically_scalable` AS `dynamically_scalable`,
+        `vm_template`.`state` AS `template_state`,
+        `vm_template`.`guest_os_id` AS `guest_os_id`,
+        `guest_os`.`uuid` AS `guest_os_uuid`,
+        `guest_os`.`display_name` AS `guest_os_name`,
+        `vm_template`.`bootable` AS `bootable`,
+        `vm_template`.`prepopulate` AS `prepopulate`,
+        `vm_template`.`cross_zones` AS `cross_zones`,
+        `vm_template`.`hypervisor_type` AS `hypervisor_type`,
+        `vm_template`.`extractable` AS `extractable`,
+        `vm_template`.`template_tag` AS `template_tag`,
+        `vm_template`.`sort_key` AS `sort_key`,
+        `vm_template`.`removed` AS `removed`,
+        `vm_template`.`enable_sshkey` AS `enable_sshkey`,
+        `source_template`.`id` AS `source_template_id`,
+        `source_template`.`uuid` AS `source_template_uuid`,
+        `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`,
+        `data_center`.`id` AS `data_center_id`,
+        `data_center`.`uuid` AS `data_center_uuid`,
+        `data_center`.`name` AS `data_center_name`,
+        `launch_permission`.`account_id` AS `lp_account_id`,
+        `template_store_ref`.`store_id` AS `store_id`,
+        `image_store`.`scope` AS `store_scope`,
+        `template_store_ref`.`state` AS `state`,
+        `template_store_ref`.`download_state` AS `download_state`,
+        `template_store_ref`.`download_pct` AS `download_pct`,
+        `template_store_ref`.`error_str` AS `error_str`,
+        `template_store_ref`.`size` AS `size`,
+        `template_store_ref`.`destroyed` AS `destroyed`,
+        `template_store_ref`.`created` AS `created_on_store`,
+        `vm_template_details`.`name` AS `detail_name`,
+        `vm_template_details`.`value` AS `detail_value`,
+        `resource_tags`.`id` AS `tag_id`,
+        `resource_tags`.`uuid` AS `tag_uuid`,
+        `resource_tags`.`key` AS `tag_key`,
+        `resource_tags`.`value` AS `tag_value`,
+        `resource_tags`.`domain_id` AS `tag_domain_id`,
+        `domain`.`uuid` AS `tag_domain_uuid`,
+        `domain`.`name` AS `tag_domain_name`,
+        `resource_tags`.`account_id` AS `tag_account_id`,
+        `account`.`account_name` AS `tag_account_name`,
+        `resource_tags`.`resource_id` AS `tag_resource_id`,
+        `resource_tags`.`resource_uuid` AS `tag_resource_uuid`,
+        `resource_tags`.`resource_type` AS `tag_resource_type`,
+        `resource_tags`.`customer` AS `tag_customer`,
+        CONCAT(`vm_template`.`id`,
+                '_',
+                IFNULL(`data_center`.`id`, 0)) AS `temp_zone_pair`
+    FROM
+        ((((((((((((`vm_template`
+        JOIN `guest_os` ON ((`guest_os`.`id` = `vm_template`.`guest_os_id`)))
+        JOIN `account` ON ((`account`.`id` = `vm_template`.`account_id`)))
+        JOIN `domain` ON ((`domain`.`id` = `account`.`domain_id`)))
+        LEFT JOIN `projects` ON ((`projects`.`project_account_id` = `account`.`id`)))
+        LEFT JOIN `vm_template_details` ON ((`vm_template_details`.`template_id` = `vm_template`.`id`)))
+        LEFT JOIN `vm_template` `source_template` ON ((`source_template`.`id` = `vm_template`.`source_template_id`)))
+        LEFT JOIN `template_store_ref` ON (((`template_store_ref`.`template_id` = `vm_template`.`id`)
+            AND (`template_store_ref`.`store_role` = 'Image')
+            AND (`template_store_ref`.`destroyed` = 0))))
+        LEFT JOIN `image_store` ON ((ISNULL(`image_store`.`removed`)
+            AND (`template_store_ref`.`store_id` IS NOT NULL)
+            AND (`image_store`.`id` = `template_store_ref`.`store_id`))))
+        LEFT JOIN `template_zone_ref` ON (((`template_zone_ref`.`template_id` = `vm_template`.`id`)
+            AND ISNULL(`template_store_ref`.`store_id`)
+            AND ISNULL(`template_zone_ref`.`removed`))))
+        LEFT JOIN `data_center` ON (((`image_store`.`data_center_id` = `data_center`.`id`)
+            OR (`template_zone_ref`.`zone_id` = `data_center`.`id`))))
+        LEFT JOIN `launch_permission` ON ((`launch_permission`.`template_id` = `vm_template`.`id`)))
+        LEFT JOIN `resource_tags` ON (((`resource_tags`.`resource_id` = `vm_template`.`id`)
+            AND ((`resource_tags`.`resource_type` = 'Template')
+            OR (`resource_tags`.`resource_type` = 'ISO')))));
+
+DROP VIEW IF EXISTS `cloud`.`volume_view`;
+CREATE 
+    ALGORITHM = UNDEFINED 
+    DEFINER = `cloud`@`%` 
+    SQL SECURITY DEFINER
+VIEW `volume_view` AS
+    SELECT 
+        `volumes`.`id` AS `id`,
+        `volumes`.`uuid` AS `uuid`,
+        `volumes`.`name` AS `name`,
+        `volumes`.`device_id` AS `device_id`,
+        `volumes`.`volume_type` AS `volume_type`,
+        `volumes`.`provisioning_type` AS `provisioning_type`,
+        `volumes`.`size` AS `size`,
+        `volumes`.`min_iops` AS `min_iops`,
+        `volumes`.`max_iops` AS `max_iops`,
+        `volumes`.`created` AS `created`,
+        `volumes`.`state` AS `state`,
+        `volumes`.`attached` AS `attached`,
+        `volumes`.`removed` AS `removed`,
+        `volumes`.`pod_id` AS `pod_id`,
+        `volumes`.`display_volume` AS `display_volume`,
+        `volumes`.`format` AS `format`,
+        `volumes`.`path` AS `path`,
+        `volumes`.`chain_info` AS `chain_info`,
+        `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`,
+        `data_center`.`id` AS `data_center_id`,
+        `data_center`.`uuid` AS `data_center_uuid`,
+        `data_center`.`name` AS `data_center_name`,
+        `data_center`.`networktype` AS `data_center_type`,
+        `vm_instance`.`id` AS `vm_id`,
+        `vm_instance`.`uuid` AS `vm_uuid`,
+        `vm_instance`.`name` AS `vm_name`,
+        `vm_instance`.`state` AS `vm_state`,
+        `vm_instance`.`vm_type` AS `vm_type`,
+        `user_vm`.`display_name` AS `vm_display_name`,
+        `volume_store_ref`.`size` AS `volume_store_size`,
+        `volume_store_ref`.`download_pct` AS `download_pct`,
+        `volume_store_ref`.`download_state` AS `download_state`,
+        `volume_store_ref`.`error_str` AS `error_str`,
+        `volume_store_ref`.`created` AS `created_on_store`,
+        `disk_offering`.`id` AS `disk_offering_id`,
+        `disk_offering`.`uuid` AS `disk_offering_uuid`,
+        `disk_offering`.`name` AS `disk_offering_name`,
+        `disk_offering`.`display_text` AS `disk_offering_display_text`,
+        `disk_offering`.`use_local_storage` AS `use_local_storage`,
+        `disk_offering`.`system_use` AS `system_use`,
+        `disk_offering`.`bytes_read_rate` AS `bytes_read_rate`,
+        `disk_offering`.`bytes_write_rate` AS `bytes_write_rate`,
+        `disk_offering`.`iops_read_rate` AS `iops_read_rate`,
+        `disk_offering`.`iops_write_rate` AS `iops_write_rate`,
+        `disk_offering`.`cache_mode` AS `cache_mode`,
+        `storage_pool`.`id` AS `pool_id`,
+        `storage_pool`.`uuid` AS `pool_uuid`,
+        `storage_pool`.`name` AS `pool_name`,
+        `cluster`.`hypervisor_type` AS `hypervisor_type`,
+        `vm_template`.`id` AS `template_id`,
+        `vm_template`.`uuid` AS `template_uuid`,
+        `vm_template`.`extractable` AS `extractable`,
+        `vm_template`.`type` AS `template_type`,
+        `vm_template`.`name` AS `template_name`,
+        `vm_template`.`display_text` AS `template_display_text`,
+        `iso`.`id` AS `iso_id`,
+        `iso`.`uuid` AS `iso_uuid`,
+        `iso`.`name` AS `iso_name`,
+        `iso`.`display_text` AS `iso_display_text`,
+        `resource_tags`.`id` AS `tag_id`,
+        `resource_tags`.`uuid` AS `tag_uuid`,
+        `resource_tags`.`key` AS `tag_key`,
+        `resource_tags`.`value` AS `tag_value`,
+        `resource_tags`.`domain_id` AS `tag_domain_id`,
+        `domain`.`uuid` AS `tag_domain_uuid`,
+        `domain`.`name` AS `tag_domain_name`,
+        `resource_tags`.`account_id` AS `tag_account_id`,
+        `account`.`account_name` AS `tag_account_name`,
+        `resource_tags`.`resource_id` AS `tag_resource_id`,
+        `resource_tags`.`resource_uuid` AS `tag_resource_uuid`,
+        `resource_tags`.`resource_type` AS `tag_resource_type`,
+        `resource_tags`.`customer` AS `tag_customer`,
+        `async_job`.`id` AS `job_id`,
+        `async_job`.`uuid` AS `job_uuid`,
+        `async_job`.`job_status` AS `job_status`,
+        `async_job`.`account_id` AS `job_account_id`
+    FROM
+        ((((((((((((((`volumes`
+        JOIN `account` ON ((`volumes`.`account_id` = `account`.`id`)))
+        JOIN `domain` ON ((`volumes`.`domain_id` = `domain`.`id`)))
+        LEFT JOIN `projects` ON ((`projects`.`project_account_id` = `account`.`id`)))
+        LEFT JOIN `data_center` ON ((`volumes`.`data_center_id` = `data_center`.`id`)))
+        LEFT JOIN `vm_instance` ON ((`volumes`.`instance_id` = `vm_instance`.`id`)))
+        LEFT JOIN `user_vm` ON ((`user_vm`.`id` = `vm_instance`.`id`)))
+        LEFT JOIN `volume_store_ref` ON ((`volumes`.`id` = `volume_store_ref`.`volume_id`)))
+        LEFT JOIN `disk_offering` ON ((`volumes`.`disk_offering_id` = `disk_offering`.`id`)))
+        LEFT JOIN `storage_pool` ON ((`volumes`.`pool_id` = `storage_pool`.`id`)))
+        LEFT JOIN `cluster` ON ((`storage_pool`.`cluster_id` = `cluster`.`id`)))
+        LEFT JOIN `vm_template` ON ((`volumes`.`template_id` = `vm_template`.`id`)))
+        LEFT JOIN `vm_template` `iso` ON ((`iso`.`id` = `volumes`.`iso_id`)))
+        LEFT JOIN `resource_tags` ON (((`resource_tags`.`resource_id` = `volumes`.`id`)
+            AND (`resource_tags`.`resource_type` = 'Volume'))))
+        LEFT JOIN `async_job` ON (((`async_job`.`instance_id` = `volumes`.`id`)
+            AND (`async_job`.`instance_type` = 'Volume')
+            AND (`async_job`.`job_status` = 0))));
+
+DROP VIEW IF EXISTS `cloud`.`user_vm__view`;
+
+CREATE 
+    ALGORITHM = UNDEFINED 
+    DEFINER = `cloud`@`%` 
+    SQL SECURITY DEFINER
+VIEW `user_vm_view` AS
+    SELECT 
+        `vm_instance`.`id` AS `id`,
+        `vm_instance`.`name` AS `name`,
+        `user_vm`.`display_name` AS `display_name`,
+        `user_vm`.`user_data` AS `user_data`,
+        `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`,
+        `instance_group`.`id` AS `instance_group_id`,
+        `instance_group`.`uuid` AS `instance_group_uuid`,
+        `instance_group`.`name` AS `instance_group_name`,
+        `vm_instance`.`uuid` AS `uuid`,
+        `vm_instance`.`user_id` AS `user_id`,
+        `vm_instance`.`last_host_id` AS `last_host_id`,
+        `vm_instance`.`vm_type` AS `type`,
+        `vm_instance`.`limit_cpu_use` AS `limit_cpu_use`,
+        `vm_instance`.`created` AS `created`,
+        `vm_instance`.`state` AS `state`,
+        `vm_instance`.`removed` AS `removed`,
+        `vm_instance`.`ha_enabled` AS `ha_enabled`,
+        `vm_instance`.`hypervisor_type` AS `hypervisor_type`,
+        `vm_instance`.`instance_name` AS `instance_name`,
+        `vm_instance`.`guest_os_id` AS `guest_os_id`,
+        `vm_instance`.`display_vm` AS `display_vm`,
+        `guest_os`.`uuid` AS `guest_os_uuid`,
+        `vm_instance`.`pod_id` AS `pod_id`,
+        `host_pod_ref`.`uuid` AS `pod_uuid`,
+        `vm_instance`.`private_ip_address` AS `private_ip_address`,
+        `vm_instance`.`private_mac_address` AS `private_mac_address`,
+        `vm_instance`.`vm_type` AS `vm_type`,
+        `data_center`.`id` AS `data_center_id`,
+        `data_center`.`uuid` AS `data_center_uuid`,
+        `data_center`.`name` AS `data_center_name`,
+        `data_center`.`is_security_group_enabled` AS `security_group_enabled`,
+        `data_center`.`networktype` AS `data_center_type`,
+        `host`.`id` AS `host_id`,
+        `host`.`uuid` AS `host_uuid`,
+        `host`.`name` AS `host_name`,
+        `vm_template`.`id` AS `template_id`,
+        `vm_template`.`uuid` AS `template_uuid`,
+        `vm_template`.`name` AS `template_name`,
+        `vm_template`.`display_text` AS `template_display_text`,
+        `vm_template`.`enable_password` AS `password_enabled`,
+        `iso`.`id` AS `iso_id`,
+        `iso`.`uuid` AS `iso_uuid`,
+        `iso`.`name` AS `iso_name`,
+        `iso`.`display_text` AS `iso_display_text`,
+        `service_offering`.`id` AS `service_offering_id`,
+        `svc_disk_offering`.`uuid` AS `service_offering_uuid`,
+        `disk_offering`.`uuid` AS `disk_offering_uuid`,
+        `disk_offering`.`id` AS `disk_offering_id`,
+        (CASE
+            WHEN ISNULL(`service_offering`.`cpu`) THEN `custom_cpu`.`value`
+            ELSE `service_offering`.`cpu`
+        END) AS `cpu`,
+        (CASE
+            WHEN ISNULL(`service_offering`.`speed`) THEN `custom_speed`.`value`
+            ELSE `service_offering`.`speed`
+        END) AS `speed`,
+        (CASE
+            WHEN ISNULL(`service_offering`.`ram_size`) THEN `custom_ram_size`.`value`
+            ELSE `service_offering`.`ram_size`
+        END) AS `ram_size`,
+        `svc_disk_offering`.`name` AS `service_offering_name`,
+        `disk_offering`.`name` AS `disk_offering_name`,
+        `storage_pool`.`id` AS `pool_id`,
+        `storage_pool`.`uuid` AS `pool_uuid`,
+        `storage_pool`.`pool_type` AS `pool_type`,
+        `volumes`.`id` AS `volume_id`,
+        `volumes`.`uuid` AS `volume_uuid`,
+        `volumes`.`device_id` AS `volume_device_id`,
+        `volumes`.`volume_type` AS `volume_type`,
+        `security_group`.`id` AS `security_group_id`,
+        `security_group`.`uuid` AS `security_group_uuid`,
+        `security_group`.`name` AS `security_group_name`,
+        `security_group`.`description` AS `security_group_description`,
+        `nics`.`id` AS `nic_id`,
+        `nics`.`uuid` AS `nic_uuid`,
+        `nics`.`network_id` AS `network_id`,
+        `nics`.`ip4_address` AS `ip_address`,
+        `nics`.`ip6_address` AS `ip6_address`,
+        `nics`.`ip6_gateway` AS `ip6_gateway`,
+        `nics`.`ip6_cidr` AS `ip6_cidr`,
+        `nics`.`default_nic` AS `is_default_nic`,
+        `nics`.`gateway` AS `gateway`,
+        `nics`.`netmask` AS `netmask`,
+        `nics`.`mac_address` AS `mac_address`,
+        `nics`.`broadcast_uri` AS `broadcast_uri`,
+        `nics`.`isolation_uri` AS `isolation_uri`,
+        `vpc`.`id` AS `vpc_id`,
+        `vpc`.`uuid` AS `vpc_uuid`,
+        `networks`.`uuid` AS `network_uuid`,
+        `networks`.`name` AS `network_name`,
+        `networks`.`traffic_type` AS `traffic_type`,
+        `networks`.`guest_type` AS `guest_type`,
+        `user_ip_address`.`id` AS `public_ip_id`,
+        `user_ip_address`.`uuid` AS `public_ip_uuid`,
+        `user_ip_address`.`public_ip_address` AS `public_ip_address`,
+        `ssh_keypairs`.`keypair_name` AS `keypair_name`,
+        `resource_tags`.`id` AS `tag_id`,
+        `resource_tags`.`uuid` AS `tag_uuid`,
+        `resource_tags`.`key` AS `tag_key`,
+        `resource_tags`.`value` AS `tag_value`,
+        `resource_tags`.`domain_id` AS `tag_domain_id`,
+        `domain`.`uuid` AS `tag_domain_uuid`,
+        `domain`.`name` AS `tag_domain_name`,
+        `resource_tags`.`account_id` AS `tag_account_id`,
+        `account`.`account_name` AS `tag_account_name`,
+        `resource_tags`.`resource_id` AS `tag_resource_id`,
+        `resource_tags`.`resource_uuid` AS `tag_resource_uuid`,
+        `resource_tags`.`resource_type` AS `tag_resource_type`,
+        `resource_tags`.`customer` AS `tag_customer`,
+        `async_job`.`id` AS `job_id`,
+        `async_job`.`uuid` AS `job_uuid`,
+        `async_job`.`job_status` AS `job_status`,
+        `async_job`.`account_id` AS `job_account_id`,
+        `affinity_group`.`id` AS `affinity_group_id`,
+        `affinity_group`.`uuid` AS `affinity_group_uuid`,
+        `affinity_group`.`name` AS `affinity_group_name`,
+        `affinity_group`.`description` AS `affinity_group_description`,
+        `vm_instance`.`dynamically_scalable` AS `dynamically_scalable`
+    FROM
+        ((((((((((((((((((((((((((((((((`user_vm`
+        JOIN `vm_instance` ON (((`vm_instance`.`id` = `user_vm`.`id`)
+            AND ISNULL(`vm_instance`.`removed`))))
+        JOIN `account` ON ((`vm_instance`.`account_id` = `account`.`id`)))
+        JOIN `domain` ON ((`vm_instance`.`domain_id` = `domain`.`id`)))
+        LEFT JOIN `guest_os` ON ((`vm_instance`.`guest_os_id` = `guest_os`.`id`)))
+        LEFT JOIN `host_pod_ref` ON ((`vm_instance`.`pod_id` = `host_pod_ref`.`id`)))
+        LEFT JOIN `projects` ON ((`projects`.`project_account_id` = `account`.`id`)))
+        LEFT JOIN `instance_group_vm_map` ON ((`vm_instance`.`id` = `instance_group_vm_map`.`instance_id`)))
+        LEFT JOIN `instance_group` ON ((`instance_group_vm_map`.`group_id` = `instance_group`.`id`)))
+        LEFT JOIN `data_center` ON ((`vm_instance`.`data_center_id` = `data_center`.`id`)))
+        LEFT JOIN `host` ON ((`vm_instance`.`host_id` = `host`.`id`)))
+        LEFT JOIN `vm_template` ON ((`vm_instance`.`vm_template_id` = `vm_template`.`id`)))
+        LEFT JOIN `vm_template` `iso` ON ((`iso`.`id` = `user_vm`.`iso_id`)))
+        LEFT JOIN `service_offering` ON ((`vm_instance`.`service_offering_id` = `service_offering`.`id`)))
+        LEFT JOIN `disk_offering` `svc_disk_offering` ON ((`vm_instance`.`service_offering_id` = `svc_disk_offering`.`id`)))
+        LEFT JOIN `disk_offering` ON ((`vm_instance`.`disk_offering_id` = `disk_offering`.`id`)))
+        LEFT JOIN `volumes` ON ((`vm_instance`.`id` = `volumes`.`instance_id`)))
+        LEFT JOIN `storage_pool` ON ((`volumes`.`pool_id` = `storage_pool`.`id`)))
+        LEFT JOIN `security_group_vm_map` ON ((`vm_instance`.`id` = `security_group_vm_map`.`instance_id`)))
+        LEFT JOIN `security_group` ON ((`security_group_vm_map`.`security_group_id` = `security_group`.`id`)))
+        LEFT JOIN `nics` ON (((`vm_instance`.`id` = `nics`.`instance_id`)
+            AND ISNULL(`nics`.`removed`))))
+        LEFT JOIN `networks` ON ((`nics`.`network_id` = `networks`.`id`)))
+        LEFT JOIN `vpc` ON (((`networks`.`vpc_id` = `vpc`.`id`)
+            AND ISNULL(`vpc`.`removed`))))
+        LEFT JOIN `user_ip_address` ON ((`user_ip_address`.`vm_id` = `vm_instance`.`id`)))
+        LEFT JOIN `user_vm_details` `ssh_details` ON (((`ssh_details`.`vm_id` = `vm_instance`.`id`)
+            AND (`ssh_details`.`name` = 'SSH.PublicKey'))))
+        LEFT JOIN `ssh_keypairs` ON (((`ssh_keypairs`.`public_key` = `ssh_details`.`value`)
+            AND (`ssh_keypairs`.`account_id` = `account`.`id`))))
+        LEFT JOIN `resource_tags` ON (((`resource_tags`.`resource_id` = `vm_instance`.`id`)
+            AND (`resource_tags`.`resource_type` = 'UserVm'))))
+        LEFT JOIN `async_job` ON (((`async_job`.`instance_id` = `vm_instance`.`id`)
+            AND (`async_job`.`instance_type` = 'VirtualMachine')
+            AND (`async_job`.`job_status` = 0))))
+        LEFT JOIN `affinity_group_vm_map` ON ((`vm_instance`.`id` = `affinity_group_vm_map`.`instance_id`)))
+        LEFT JOIN `affinity_group` ON ((`affinity_group_vm_map`.`affinity_group_id` = `affinity_group`.`id`)))
+        LEFT JOIN `user_vm_details` `custom_cpu` ON (((`custom_cpu`.`vm_id` = `vm_instance`.`id`)
+            AND (`custom_cpu`.`name` = 'CpuNumber'))))
+        LEFT JOIN `user_vm_details` `custom_speed` ON (((`custom_speed`.`vm_id` = `vm_instance`.`id`)
+            AND (`custom_speed`.`name` = 'CpuSpeed'))))
+        LEFT JOIN `user_vm_details` `custom_ram_size` ON (((`custom_ram_size`.`vm_id` = `vm_instance`.`id`)
+            AND (`custom_ram_size`.`name` = 'memory'))));