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

git commit: Create DB views for AsyncJobResponse to speed up listAsyncJobsCmd.

Updated Branches:
  refs/heads/api_refactoring ff8fdbd19 -> daeb4abcc


Create DB views for AsyncJobResponse to speed up listAsyncJobsCmd.

Signed-off-by: Min Chen <mi...@citrix.com>


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

Branch: refs/heads/api_refactoring
Commit: daeb4abcca6f6f97d64bd560ce9087d4c92ca4a2
Parents: ff8fdbd
Author: Min Chen <mi...@citrix.com>
Authored: Thu Jan 3 15:35:26 2013 -0800
Committer: Min Chen <mi...@citrix.com>
Committed: Thu Jan 3 15:35:26 2013 -0800

----------------------------------------------------------------------
 api/src/com/cloud/server/ManagementService.java    |   15 -
 .../api/command/user/job/ListAsyncJobsCmd.java     |   10 +-
 .../org/apache/cloudstack/query/QueryService.java  |    8 +
 server/src/com/cloud/api/ApiDBUtils.java           |   13 +
 server/src/com/cloud/api/ApiResponseHelper.java    |   46 +--
 .../src/com/cloud/api/query/QueryManagerImpl.java  |   88 ++++-
 .../com/cloud/api/query/ViewResponseHelper.java    |   10 +
 .../com/cloud/api/query/dao/AsyncJobJoinDao.java   |   34 ++
 .../cloud/api/query/dao/AsyncJobJoinDaoImpl.java   |  161 +++++++
 .../src/com/cloud/api/query/vo/AsyncJobJoinVO.java |  333 +++++++++++++++
 .../configuration/DefaultComponentLibrary.java     |    2 +
 .../src/com/cloud/server/ManagementServerImpl.java |   84 +----
 setup/db/create-schema.sql                         |   77 ++++-
 setup/db/db/schema-40to410.sql                     |   76 ++++
 14 files changed, 808 insertions(+), 149 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-cloudstack/blob/daeb4abc/api/src/com/cloud/server/ManagementService.java
----------------------------------------------------------------------
diff --git a/api/src/com/cloud/server/ManagementService.java b/api/src/com/cloud/server/ManagementService.java
index ccccb90..cacf5cf 100755
--- a/api/src/com/cloud/server/ManagementService.java
+++ b/api/src/com/cloud/server/ManagementService.java
@@ -25,12 +25,10 @@ import java.util.Set;
 import com.cloud.alert.Alert;
 import org.apache.cloudstack.api.ServerApiException;
 import org.apache.cloudstack.api.command.admin.cluster.ListClustersCmd;
-import org.apache.cloudstack.api.command.admin.host.ListHostsCmd;
 import org.apache.cloudstack.api.command.admin.host.UpdateHostPasswordCmd;
 import org.apache.cloudstack.api.command.admin.pod.ListPodsByCmd;
 import org.apache.cloudstack.api.command.admin.resource.ListAlertsCmd;
 import org.apache.cloudstack.api.command.admin.resource.ListCapacityCmd;
-import org.apache.cloudstack.api.command.admin.router.ListRoutersCmd;
 import org.apache.cloudstack.api.command.admin.domain.UpdateDomainCmd;
 import org.apache.cloudstack.api.command.admin.storagepool.ListStoragePoolsCmd;
 import org.apache.cloudstack.api.command.admin.systemvm.*;
@@ -38,7 +36,6 @@ import org.apache.cloudstack.api.command.admin.vlan.ListVlanIpRangesCmd;
 import org.apache.cloudstack.api.command.user.address.ListPublicIpAddressesCmd;
 import org.apache.cloudstack.api.command.user.config.ListCapabilitiesCmd;
 import org.apache.cloudstack.api.command.user.guest.ListGuestOsCmd;
-import org.apache.cloudstack.api.command.user.job.ListAsyncJobsCmd;
 import org.apache.cloudstack.api.command.user.offering.ListDiskOfferingsCmd;
 import org.apache.cloudstack.api.command.user.offering.ListServiceOfferingsCmd;
 import org.apache.cloudstack.api.command.user.ssh.DeleteSSHKeyPairCmd;
@@ -48,12 +45,10 @@ import org.apache.cloudstack.api.command.user.vm.GetVMPasswordCmd;
 import org.apache.cloudstack.api.command.user.volume.ExtractVolumeCmd;
 import org.apache.cloudstack.api.command.user.template.UpdateTemplateCmd;
 import org.apache.cloudstack.api.command.admin.config.ListCfgsByCmd;
-import org.apache.cloudstack.api.command.user.event.ListEventsCmd;
 import org.apache.cloudstack.api.command.user.guest.ListGuestOsCategoriesCmd;
 import org.apache.cloudstack.api.command.user.iso.ListIsosCmd;
 import org.apache.cloudstack.api.command.user.ssh.ListSSHKeyPairsCmd;
 import org.apache.cloudstack.api.command.admin.systemvm.ListSystemVMsCmd;
-import org.apache.cloudstack.api.command.user.vmgroup.ListVMGroupsCmd;
 import org.apache.cloudstack.api.command.user.zone.ListZonesByCmd;
 import org.apache.cloudstack.api.command.admin.systemvm.RebootSystemVmCmd;
 import org.apache.cloudstack.api.command.user.ssh.RegisterSSHKeyPairCmd;
@@ -63,7 +58,6 @@ import org.apache.cloudstack.api.command.user.vmgroup.UpdateVMGroupCmd;
 import org.apache.cloudstack.api.command.admin.systemvm.UpgradeSystemVMCmd;
 import org.apache.cloudstack.api.command.admin.resource.UploadCustomCertificateCmd;
 
-import com.cloud.async.AsyncJob;
 import com.cloud.capacity.Capacity;
 import com.cloud.configuration.Configuration;
 import com.cloud.dc.DataCenter;
@@ -329,15 +323,6 @@ public interface ManagementService {
     Pair<List<? extends Vlan>, Integer> searchForVlans(ListVlanIpRangesCmd cmd);
 
     /**
-     * Search for async jobs by account and/or startDate
-     *
-     * @param cmd
-     *            the command specifying the account and start date parameters
-     * @return the list of async jobs that match the criteria
-     */
-    Pair<List<? extends AsyncJob>, Integer> searchForAsyncJobs(ListAsyncJobsCmd cmd);
-
-    /**
      * Generates a random password that will be used (initially) by newly created and started virtual machines
      *
      * @return a random password

http://git-wip-us.apache.org/repos/asf/incubator-cloudstack/blob/daeb4abc/api/src/org/apache/cloudstack/api/command/user/job/ListAsyncJobsCmd.java
----------------------------------------------------------------------
diff --git a/api/src/org/apache/cloudstack/api/command/user/job/ListAsyncJobsCmd.java b/api/src/org/apache/cloudstack/api/command/user/job/ListAsyncJobsCmd.java
index e9301e9..50ac52e 100644
--- a/api/src/org/apache/cloudstack/api/command/user/job/ListAsyncJobsCmd.java
+++ b/api/src/org/apache/cloudstack/api/command/user/job/ListAsyncJobsCmd.java
@@ -24,6 +24,7 @@ import org.apache.cloudstack.api.APICommand;
 import org.apache.cloudstack.api.ApiConstants;
 import org.apache.cloudstack.api.BaseListAccountResourcesCmd;
 import org.apache.cloudstack.api.Parameter;
+import org.apache.cloudstack.api.response.AccountResponse;
 import org.apache.cloudstack.api.response.AsyncJobResponse;
 import org.apache.cloudstack.api.response.ListResponse;
 import com.cloud.async.AsyncJob;
@@ -59,15 +60,10 @@ public class ListAsyncJobsCmd extends BaseListAccountResourcesCmd {
 
     @Override
     public void execute(){
-        Pair<List<? extends AsyncJob>, Integer> result = _mgr.searchForAsyncJobs(this);
-        ListResponse<AsyncJobResponse> response = new ListResponse<AsyncJobResponse>();
-        List<AsyncJobResponse> jobResponses = new ArrayList<AsyncJobResponse>();
-        for (AsyncJob job : result.first()) {
-            jobResponses.add(_responseGenerator.createAsyncJobResponse(job));
-        }
 
-        response.setResponses(jobResponses, result.second());
+        ListResponse<AsyncJobResponse> response = _queryService.searchForAsyncJobs(this);
         response.setResponseName(getCommandName());
         this.setResponseObject(response);
+
     }
 }

http://git-wip-us.apache.org/repos/asf/incubator-cloudstack/blob/daeb4abc/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 a310bb3..480eb31 100644
--- a/api/src/org/apache/cloudstack/query/QueryService.java
+++ b/api/src/org/apache/cloudstack/query/QueryService.java
@@ -16,12 +16,15 @@
 // under the License.
 package org.apache.cloudstack.query;
 
+import java.util.List;
+
 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.user.ListUsersCmd;
 import org.apache.cloudstack.api.command.user.account.ListAccountsCmd;
 import org.apache.cloudstack.api.command.user.account.ListProjectAccountsCmd;
 import org.apache.cloudstack.api.command.user.event.ListEventsCmd;
+import org.apache.cloudstack.api.command.user.job.ListAsyncJobsCmd;
 import org.apache.cloudstack.api.command.user.project.ListProjectInvitationsCmd;
 import org.apache.cloudstack.api.command.user.project.ListProjectsCmd;
 import org.apache.cloudstack.api.command.user.securitygroup.ListSecurityGroupsCmd;
@@ -30,6 +33,7 @@ import org.apache.cloudstack.api.command.user.vm.ListVMsCmd;
 import org.apache.cloudstack.api.command.user.vmgroup.ListVMGroupsCmd;
 import org.apache.cloudstack.api.command.user.volume.ListVolumesCmd;
 import org.apache.cloudstack.api.response.AccountResponse;
+import org.apache.cloudstack.api.response.AsyncJobResponse;
 import org.apache.cloudstack.api.response.DomainRouterResponse;
 import org.apache.cloudstack.api.response.EventResponse;
 import org.apache.cloudstack.api.response.HostResponse;
@@ -46,7 +50,9 @@ import org.apache.cloudstack.api.response.VolumeResponse;
 
 
 
+import com.cloud.async.AsyncJob;
 import com.cloud.exception.PermissionDeniedException;
+import com.cloud.utils.Pair;
 
 /**
  * Service used for list api query.
@@ -80,4 +86,6 @@ public interface QueryService {
     public ListResponse<VolumeResponse> searchForVolumes(ListVolumesCmd cmd);
 
     public ListResponse<AccountResponse> searchForAccounts(ListAccountsCmd cmd);
+
+    public ListResponse<AsyncJobResponse>  searchForAsyncJobs(ListAsyncJobsCmd cmd);
 }

http://git-wip-us.apache.org/repos/asf/incubator-cloudstack/blob/daeb4abc/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 1b2327a..343dad9 100755
--- a/server/src/com/cloud/api/ApiDBUtils.java
+++ b/server/src/com/cloud/api/ApiDBUtils.java
@@ -25,6 +25,7 @@ import java.util.Set;
 import org.apache.cloudstack.api.ApiConstants.HostDetails;
 import org.apache.cloudstack.api.ApiConstants.VMDetails;
 import org.apache.cloudstack.api.response.AccountResponse;
+import org.apache.cloudstack.api.response.AsyncJobResponse;
 import org.apache.cloudstack.api.response.DomainRouterResponse;
 import org.apache.cloudstack.api.response.EventResponse;
 import org.apache.cloudstack.api.response.HostResponse;
@@ -39,6 +40,7 @@ import org.apache.cloudstack.api.response.UserVmResponse;
 import org.apache.cloudstack.api.response.VolumeResponse;
 
 import com.cloud.api.query.dao.AccountJoinDao;
+import com.cloud.api.query.dao.AsyncJobJoinDao;
 import com.cloud.api.query.dao.DomainRouterJoinDao;
 import com.cloud.api.query.dao.HostJoinDao;
 import com.cloud.api.query.dao.InstanceGroupJoinDao;
@@ -51,6 +53,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.AsyncJobJoinVO;
 import com.cloud.api.query.vo.DomainRouterJoinVO;
 import com.cloud.api.query.vo.EventJoinVO;
 import com.cloud.api.query.vo.HostJoinVO;
@@ -322,6 +325,7 @@ public class ApiDBUtils {
     private static HostJoinDao _hostJoinDao;
     private static VolumeJoinDao _volJoinDao;
     private static AccountJoinDao _accountJoinDao;
+    private static AsyncJobJoinDao _jobJoinDao;
 
     private static PhysicalNetworkTrafficTypeDao _physicalNetworkTrafficTypeDao;
     private static PhysicalNetworkServiceProviderDao _physicalNetworkServiceProviderDao;
@@ -411,6 +415,7 @@ public class ApiDBUtils {
         _hostJoinDao = locator.getDao(HostJoinDao.class);
         _volJoinDao = locator.getDao(VolumeJoinDao.class);
         _accountJoinDao = locator.getDao(AccountJoinDao.class);
+        _jobJoinDao = locator.getDao(AsyncJobJoinDao.class);
 
         _physicalNetworkTrafficTypeDao = locator.getDao(PhysicalNetworkTrafficTypeDao.class);
         _physicalNetworkServiceProviderDao = locator.getDao(PhysicalNetworkServiceProviderDao.class);
@@ -1364,4 +1369,12 @@ public class ApiDBUtils {
    public static AccountJoinVO findAccountViewById(Long accountId) {
        return _accountJoinDao.findByIdIncludingRemoved(accountId);
    }
+
+   public static AsyncJobResponse newAsyncJobResponse(AsyncJobJoinVO ve) {
+       return _jobJoinDao.newAsyncJobResponse(ve);
+   }
+
+   public static AsyncJobJoinVO newAsyncJobView(AsyncJob e){
+       return _jobJoinDao.newAsyncJobView(e);
+   }
 }

http://git-wip-us.apache.org/repos/asf/incubator-cloudstack/blob/daeb4abc/server/src/com/cloud/api/ApiResponseHelper.java
----------------------------------------------------------------------
diff --git a/server/src/com/cloud/api/ApiResponseHelper.java b/server/src/com/cloud/api/ApiResponseHelper.java
index 1013bbf..7fc3c03 100755
--- a/server/src/com/cloud/api/ApiResponseHelper.java
+++ b/server/src/com/cloud/api/ApiResponseHelper.java
@@ -46,6 +46,7 @@ import org.apache.cloudstack.api.response.AccountResponse;
 
 import com.cloud.api.query.ViewResponseHelper;
 import com.cloud.api.query.vo.AccountJoinVO;
+import com.cloud.api.query.vo.AsyncJobJoinVO;
 import com.cloud.api.query.vo.ControlledViewEntity;
 import com.cloud.api.query.vo.DomainRouterJoinVO;
 import com.cloud.api.query.vo.EventJoinVO;
@@ -1803,49 +1804,8 @@ public class ApiResponseHelper implements ResponseGenerator {
 
     @Override
     public AsyncJobResponse createAsyncJobResponse(AsyncJob job) {
-        AsyncJobResponse jobResponse = new AsyncJobResponse();
-        Account account = ApiDBUtils.findAccountById(job.getAccountId());
-        if (account != null) {
-            jobResponse.setAccountId(account.getUuid());
-        }
-        User user = ApiDBUtils.findUserById(job.getUserId());
-        if (user != null) {
-            jobResponse.setUserId(user.getUuid());
-        }
-        jobResponse.setCmd(job.getCmd());
-        jobResponse.setCreated(job.getCreated());
-        jobResponse.setJobId(job.getUuid());
-        jobResponse.setJobStatus(job.getStatus());
-        jobResponse.setJobProcStatus(job.getProcessStatus());
-
-        if (job.getInstanceType() != null && job.getInstanceId() != null) {
-            jobResponse.setJobInstanceType(job.getInstanceType().toString());
-            String jobInstanceId = ApiDBUtils.findJobInstanceUuid(job);
-
-            if (jobInstanceId != null) {
-                jobResponse.setJobInstanceId(jobInstanceId);
-            }
-        }
-        jobResponse.setJobResultCode(job.getResultCode());
-
-        boolean savedValue = SerializationContext.current().getUuidTranslation();
-        SerializationContext.current().setUuidTranslation(false);
-
-        Object resultObject = ApiSerializerHelper.fromSerializedString(job.getResult());
-        jobResponse.setJobResult((ResponseObject) resultObject);
-        SerializationContext.current().setUuidTranslation(savedValue);
-
-        if (resultObject != null) {
-            Class<?> clz = resultObject.getClass();
-            if (clz.isPrimitive() || clz.getSuperclass() == Number.class || clz == String.class || clz == Date.class) {
-                jobResponse.setJobResultType("text");
-            } else {
-                jobResponse.setJobResultType("object");
-            }
-        }
-
-        jobResponse.setObjectName("asyncjobs");
-        return jobResponse;
+        AsyncJobJoinVO vJob = ApiDBUtils.newAsyncJobView(job);
+        return ApiDBUtils.newAsyncJobResponse(vJob);
     }
 
     @Override

http://git-wip-us.apache.org/repos/asf/incubator-cloudstack/blob/daeb4abc/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 a4ec02a..c47c1ef 100644
--- a/server/src/com/cloud/api/query/QueryManagerImpl.java
+++ b/server/src/com/cloud/api/query/QueryManagerImpl.java
@@ -34,6 +34,7 @@ import org.apache.cloudstack.api.command.admin.user.ListUsersCmd;
 import org.apache.cloudstack.api.command.user.account.ListAccountsCmd;
 import org.apache.cloudstack.api.command.user.account.ListProjectAccountsCmd;
 import org.apache.cloudstack.api.command.user.event.ListEventsCmd;
+import org.apache.cloudstack.api.command.user.job.ListAsyncJobsCmd;
 import org.apache.cloudstack.api.command.user.project.ListProjectInvitationsCmd;
 import org.apache.cloudstack.api.command.user.project.ListProjectsCmd;
 import org.apache.cloudstack.api.command.user.securitygroup.ListSecurityGroupsCmd;
@@ -42,6 +43,7 @@ import org.apache.cloudstack.api.command.user.vm.ListVMsCmd;
 import org.apache.cloudstack.api.command.user.vmgroup.ListVMGroupsCmd;
 import org.apache.cloudstack.api.command.user.volume.ListVolumesCmd;
 import org.apache.cloudstack.api.response.AccountResponse;
+import org.apache.cloudstack.api.response.AsyncJobResponse;
 import org.apache.cloudstack.api.response.DomainRouterResponse;
 import org.apache.cloudstack.api.response.EventResponse;
 import org.apache.cloudstack.api.response.HostResponse;
@@ -62,6 +64,7 @@ import com.cloud.acl.ControlledEntity;
 import com.cloud.api.ApiDBUtils;
 import com.cloud.api.ApiResponseHelper;
 import com.cloud.api.query.dao.AccountJoinDao;
+import com.cloud.api.query.dao.AsyncJobJoinDao;
 import com.cloud.api.query.dao.DomainRouterJoinDao;
 import com.cloud.api.query.dao.HostJoinDao;
 import com.cloud.api.query.dao.InstanceGroupJoinDao;
@@ -74,6 +77,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.AsyncJobJoinVO;
 import com.cloud.api.query.vo.DomainRouterJoinVO;
 import com.cloud.api.query.vo.EventJoinVO;
 import com.cloud.api.query.vo.HostJoinVO;
@@ -87,6 +91,7 @@ import com.cloud.api.query.vo.UserAccountJoinVO;
 import com.cloud.api.query.vo.UserVmJoinVO;
 import com.cloud.api.query.vo.VolumeJoinVO;
 import com.cloud.async.AsyncJob;
+import com.cloud.async.AsyncJobVO;
 import com.cloud.domain.Domain;
 import com.cloud.domain.DomainVO;
 import com.cloud.domain.dao.DomainDao;
@@ -217,6 +222,9 @@ public class QueryManagerImpl implements QueryService, Manager {
     private AccountJoinDao _accountJoinDao;
 
     @Inject
+    private AsyncJobJoinDao _jobJoinDao;
+
+    @Inject
     private HighAvailabilityManager _haMgr;
 
     @Override
@@ -1727,10 +1735,86 @@ public class QueryManagerImpl implements QueryService, Manager {
             }
         }
 
-        Pair<List<AccountJoinVO>, Integer> result = _accountJoinDao.searchAndCount(sc, searchFilter);
-        return new Pair<List<AccountJoinVO>, Integer>(result.first(), result.second());
+        return _accountJoinDao.searchAndCount(sc, searchFilter);
+    }
+
+    @Override
+    public ListResponse<AsyncJobResponse> searchForAsyncJobs(ListAsyncJobsCmd cmd) {
+        Pair<List<AsyncJobJoinVO>, Integer> result = searchForAsyncJobsInternal(cmd);
+        ListResponse<AsyncJobResponse> response = new ListResponse<AsyncJobResponse>();
+        List<AsyncJobResponse> jobResponses = ViewResponseHelper.createAsyncJobResponse(result.first().toArray(new AsyncJobJoinVO[result.first().size()]));
+        response.setResponses(jobResponses, result.second());
+        return response;
     }
 
 
+    public Pair<List<AsyncJobJoinVO>, Integer> searchForAsyncJobsInternal(ListAsyncJobsCmd cmd) {
+
+        Account caller = UserContext.current().getCaller();
+
+        List<Long> permittedAccounts = new ArrayList<Long>();
+
+        Ternary<Long, Boolean, ListProjectResourcesCriteria> domainIdRecursiveListProject = new Ternary<Long, Boolean, ListProjectResourcesCriteria>(
+                cmd.getDomainId(), cmd.isRecursive(), null);
+        _accountMgr.buildACLSearchParameters(caller, null, cmd.getAccountName(), null, permittedAccounts, domainIdRecursiveListProject,
+                cmd.listAll(), false);
+        Long domainId = domainIdRecursiveListProject.first();
+        Boolean isRecursive = domainIdRecursiveListProject.second();
+        ListProjectResourcesCriteria listProjectResourcesCriteria = domainIdRecursiveListProject.third();
+
+        Filter searchFilter = new Filter(AsyncJobJoinVO.class, "id", true, cmd.getStartIndex(), cmd.getPageSizeVal());
+        SearchBuilder<AsyncJobJoinVO> sb = _jobJoinDao.createSearchBuilder();
+        sb.and("accountIdIN", sb.entity().getAccountId(), SearchCriteria.Op.IN);
+        SearchBuilder<AccountVO> accountSearch = null;
+        boolean accountJoinIsDone = false;
+        if (permittedAccounts.isEmpty() && domainId != null) {
+            sb.and("domainId", sb.entity().getDomainId(), SearchCriteria.Op.EQ);
+            sb.and("path", sb.entity().getDomainPath(), SearchCriteria.Op.LIKE);
+            accountJoinIsDone = true;
+        }
+
+        if (listProjectResourcesCriteria != null) {
+
+            if (listProjectResourcesCriteria == Project.ListProjectResourcesCriteria.ListProjectResourcesOnly) {
+                sb.and("type", sb.entity().getAccountType(), SearchCriteria.Op.EQ);
+            } else if (listProjectResourcesCriteria == Project.ListProjectResourcesCriteria.SkipProjectResources) {
+                sb.and("type", sb.entity().getAccountType(), SearchCriteria.Op.NEQ);
+            }
+
+            if (!accountJoinIsDone) {
+                sb.and("domainId", sb.entity().getDomainId(), SearchCriteria.Op.EQ);
+                sb.and("path", sb.entity().getDomainPath(), SearchCriteria.Op.LIKE);
+            }
+        }
+
+        Object keyword = cmd.getKeyword();
+        Object startDate = cmd.getStartDate();
+
+        SearchCriteria<AsyncJobJoinVO> sc = sb.create();
+        if (listProjectResourcesCriteria != null) {
+            sc.setParameters("type", Account.ACCOUNT_TYPE_PROJECT);
+        }
+
+        if (!permittedAccounts.isEmpty()) {
+            sc.setParameters("accountIdIN", permittedAccounts.toArray());
+        } else if (domainId != null) {
+            DomainVO domain = _domainDao.findById(domainId);
+            if (isRecursive) {
+                sc.setParameters("path", domain.getPath() + "%");
+            } else {
+                sc.setParameters("domainId", domainId);
+            }
+        }
+
+        if (keyword != null) {
+            sc.addAnd("cmd", SearchCriteria.Op.LIKE, "%" + keyword + "%");
+        }
+
+        if (startDate != null) {
+            sc.addAnd("created", SearchCriteria.Op.GTEQ, startDate);
+        }
+
+        return _jobJoinDao.searchAndCount(sc, searchFilter);
+    }
 
 }

http://git-wip-us.apache.org/repos/asf/incubator-cloudstack/blob/daeb4abc/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 c29c93b..0849586 100644
--- a/server/src/com/cloud/api/query/ViewResponseHelper.java
+++ b/server/src/com/cloud/api/query/ViewResponseHelper.java
@@ -24,6 +24,7 @@ import java.util.List;
 import org.apache.cloudstack.api.ApiConstants.HostDetails;
 import org.apache.cloudstack.api.ApiConstants.VMDetails;
 import org.apache.cloudstack.api.response.AccountResponse;
+import org.apache.cloudstack.api.response.AsyncJobResponse;
 import org.apache.cloudstack.api.response.DomainRouterResponse;
 import org.apache.cloudstack.api.response.EventResponse;
 import org.apache.cloudstack.api.response.HostResponse;
@@ -40,6 +41,7 @@ import org.apache.log4j.Logger;
 
 import com.cloud.api.ApiDBUtils;
 import com.cloud.api.query.vo.AccountJoinVO;
+import com.cloud.api.query.vo.AsyncJobJoinVO;
 import com.cloud.api.query.vo.DomainRouterJoinVO;
 import com.cloud.api.query.vo.EventJoinVO;
 import com.cloud.api.query.vo.HostJoinVO;
@@ -243,4 +245,12 @@ public class ViewResponseHelper {
         }
         return respList;
     }
+
+    public static List<AsyncJobResponse> createAsyncJobResponse(AsyncJobJoinVO... jobs) {
+        List<AsyncJobResponse> respList = new ArrayList<AsyncJobResponse>();
+        for (AsyncJobJoinVO vt : jobs){
+            respList.add(ApiDBUtils.newAsyncJobResponse(vt));
+        }
+        return respList;
+    }
 }

http://git-wip-us.apache.org/repos/asf/incubator-cloudstack/blob/daeb4abc/server/src/com/cloud/api/query/dao/AsyncJobJoinDao.java
----------------------------------------------------------------------
diff --git a/server/src/com/cloud/api/query/dao/AsyncJobJoinDao.java b/server/src/com/cloud/api/query/dao/AsyncJobJoinDao.java
new file mode 100644
index 0000000..59fcc87
--- /dev/null
+++ b/server/src/com/cloud/api/query/dao/AsyncJobJoinDao.java
@@ -0,0 +1,34 @@
+// 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.api.response.AsyncJobResponse;
+
+import com.cloud.api.query.vo.AsyncJobJoinVO;
+import com.cloud.async.AsyncJob;
+import com.cloud.utils.db.GenericDao;
+
+public interface AsyncJobJoinDao extends GenericDao<AsyncJobJoinVO, Long> {
+
+    AsyncJobResponse newAsyncJobResponse(AsyncJobJoinVO vol);
+
+    AsyncJobJoinVO newAsyncJobView(AsyncJob vol);
+
+    List<AsyncJobJoinVO> searchByIds(Long... ids);
+}

http://git-wip-us.apache.org/repos/asf/incubator-cloudstack/blob/daeb4abc/server/src/com/cloud/api/query/dao/AsyncJobJoinDaoImpl.java
----------------------------------------------------------------------
diff --git a/server/src/com/cloud/api/query/dao/AsyncJobJoinDaoImpl.java b/server/src/com/cloud/api/query/dao/AsyncJobJoinDaoImpl.java
new file mode 100644
index 0000000..c0c827b
--- /dev/null
+++ b/server/src/com/cloud/api/query/dao/AsyncJobJoinDaoImpl.java
@@ -0,0 +1,161 @@
+// 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.Date;
+import java.util.Iterator;
+import java.util.List;
+
+import javax.ejb.Local;
+
+import org.apache.log4j.Logger;
+
+import com.cloud.api.ApiDBUtils;
+import com.cloud.api.ApiResponseHelper;
+import com.cloud.api.ApiSerializerHelper;
+import com.cloud.api.SerializationContext;
+import com.cloud.api.query.ViewResponseHelper;
+import com.cloud.api.query.vo.AccountJoinVO;
+import com.cloud.api.query.vo.AsyncJobJoinVO;
+import com.cloud.api.query.vo.InstanceGroupJoinVO;
+import com.cloud.api.query.vo.ResourceTagJoinVO;
+import com.cloud.api.query.vo.UserAccountJoinVO;
+import com.cloud.api.query.vo.UserVmJoinVO;
+import com.cloud.api.query.vo.VolumeJoinVO;
+import com.cloud.async.AsyncJob;
+import com.cloud.configuration.Resource.ResourceType;
+import com.cloud.dc.DataCenter;
+import com.cloud.domain.Domain;
+
+import org.apache.cloudstack.api.BaseCmd;
+import org.apache.cloudstack.api.ResponseObject;
+import org.apache.cloudstack.api.ServerApiException;
+import org.apache.cloudstack.api.response.AccountResponse;
+import org.apache.cloudstack.api.response.AsyncJobResponse;
+import org.apache.cloudstack.api.response.ListResponse;
+import org.apache.cloudstack.api.response.UserResponse;
+import org.apache.cloudstack.api.response.VolumeResponse;
+
+import com.cloud.offering.ServiceOffering;
+import com.cloud.server.Criteria;
+import com.cloud.storage.Storage;
+import com.cloud.storage.VMTemplateHostVO;
+import com.cloud.storage.Volume;
+import com.cloud.storage.VMTemplateStorageResourceAssoc.Status;
+import com.cloud.user.Account;
+import com.cloud.user.User;
+import com.cloud.user.UserContext;
+import com.cloud.user.UserStatisticsVO;
+import com.cloud.user.UserVO;
+import com.cloud.utils.db.GenericDaoBase;
+import com.cloud.utils.db.SearchBuilder;
+import com.cloud.utils.db.SearchCriteria;
+import com.cloud.vm.VirtualMachine.State;
+
+
+@Local(value={AsyncJobJoinDao.class})
+public class AsyncJobJoinDaoImpl extends GenericDaoBase<AsyncJobJoinVO, Long> implements AsyncJobJoinDao {
+    public static final Logger s_logger = Logger.getLogger(AsyncJobJoinDaoImpl.class);
+
+    private SearchBuilder<AsyncJobJoinVO> jobSearch;
+
+    private SearchBuilder<AsyncJobJoinVO> jobIdSearch;
+
+    protected AsyncJobJoinDaoImpl() {
+
+        jobSearch = createSearchBuilder();
+        jobSearch.and("idIN", jobSearch.entity().getId(), SearchCriteria.Op.IN);
+        jobSearch.done();
+
+        jobIdSearch = createSearchBuilder();
+        jobIdSearch.and("id", jobIdSearch.entity().getId(), SearchCriteria.Op.EQ);
+        jobIdSearch.done();
+
+        this._count = "select count(distinct id) from async_job_view WHERE ";
+    }
+
+
+
+
+
+    @Override
+    public AsyncJobResponse newAsyncJobResponse(AsyncJobJoinVO job) {
+        AsyncJobResponse jobResponse = new AsyncJobResponse();
+        jobResponse.setAccountId(job.getAccountUuid());
+        jobResponse.setUserId(job.getUserUuid());
+        jobResponse.setCmd(job.getCmd());
+        jobResponse.setCreated(job.getCreated());
+        jobResponse.setJobId(job.getUuid());
+        jobResponse.setJobStatus(job.getStatus());
+        jobResponse.setJobProcStatus(job.getProcessStatus());
+
+        if (job.getInstanceType() != null && job.getInstanceId() != null) {
+            jobResponse.setJobInstanceType(job.getInstanceType().toString());
+
+            jobResponse.setJobInstanceId(job.getInstanceUuid());
+
+        }
+        jobResponse.setJobResultCode(job.getResultCode());
+
+        boolean savedValue = SerializationContext.current().getUuidTranslation();
+        SerializationContext.current().setUuidTranslation(false);
+
+        Object resultObject = ApiSerializerHelper.fromSerializedString(job.getResult());
+        jobResponse.setJobResult((ResponseObject) resultObject);
+        SerializationContext.current().setUuidTranslation(savedValue);
+
+        if (resultObject != null) {
+            Class<?> clz = resultObject.getClass();
+            if (clz.isPrimitive() || clz.getSuperclass() == Number.class || clz == String.class || clz == Date.class) {
+                jobResponse.setJobResultType("text");
+            } else {
+                jobResponse.setJobResultType("object");
+            }
+        }
+
+        jobResponse.setObjectName("asyncjobs");
+        return jobResponse;
+    }
+
+
+
+
+
+    @Override
+    public AsyncJobJoinVO newAsyncJobView(AsyncJob job) {
+        SearchCriteria<AsyncJobJoinVO> sc = jobIdSearch.create();
+        sc.setParameters("id", job.getId());
+        List<AsyncJobJoinVO> accounts = searchIncludingRemoved(sc, null, null, false);
+        assert accounts != null && accounts.size() == 1 : "No async job found for job id " + job.getId();
+        return accounts.get(0);
+
+    }
+
+
+
+
+    @Override
+    public List<AsyncJobJoinVO> searchByIds(Long... ids) {
+        SearchCriteria<AsyncJobJoinVO> sc = jobSearch.create();
+        sc.setParameters("idIN", ids);
+        return searchIncludingRemoved(sc, null, null, false);
+    }
+
+
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-cloudstack/blob/daeb4abc/server/src/com/cloud/api/query/vo/AsyncJobJoinVO.java
----------------------------------------------------------------------
diff --git a/server/src/com/cloud/api/query/vo/AsyncJobJoinVO.java b/server/src/com/cloud/api/query/vo/AsyncJobJoinVO.java
new file mode 100644
index 0000000..39bcb17
--- /dev/null
+++ b/server/src/com/cloud/api/query/vo/AsyncJobJoinVO.java
@@ -0,0 +1,333 @@
+// 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 java.util.Date;
+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.async.AsyncJob.Type;
+import com.cloud.utils.db.GenericDao;
+import org.apache.cloudstack.api.Identity;
+import org.apache.cloudstack.api.InternalIdentity;
+
+@Entity
+@Table(name="async_job_view")
+public class AsyncJobJoinVO extends BaseViewVO implements InternalIdentity, Identity {
+
+    @Id
+    @Column(name="id")
+    private long id;
+
+    @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="user_id")
+    private long userId;
+
+    @Column(name="user_uuid")
+    private String userUuid;
+
+    @Column(name="job_cmd")
+    private String cmd;
+
+    @Column(name="job_status")
+    private int status;
+
+    @Column(name="job_process_status")
+    private int processStatus;
+
+    @Column(name="job_result_code")
+    private int resultCode;
+
+    @Column(name="job_result", length=65535)
+    private String result;
+
+    @Column(name=GenericDao.CREATED_COLUMN)
+    private Date created;
+
+    @Column(name=GenericDao.REMOVED_COLUMN)
+    private Date removed;
+
+    @Enumerated(value=EnumType.STRING)
+    @Column(name="instance_type", length=64)
+    private Type instanceType;
+
+    @Column(name="instance_id", length=64)
+    private Long instanceId;
+
+    @Column(name="instance_uuid")
+    private String instanceUuid;
+
+
+    public AsyncJobJoinVO() {
+    }
+
+
+    @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 long getAccountId() {
+        return accountId;
+    }
+
+
+    public void setAccountId(long accountId) {
+        this.accountId = accountId;
+    }
+
+
+    public String getAccountUuid() {
+        return accountUuid;
+    }
+
+
+    public void setAccountUuid(String accountUuid) {
+        this.accountUuid = accountUuid;
+    }
+
+
+    public String getAccountName() {
+        return accountName;
+    }
+
+
+    public void setAccountName(String accountName) {
+        this.accountName = accountName;
+    }
+
+
+    public short getAccountType() {
+        return accountType;
+    }
+
+
+    public void setAccountType(short accountType) {
+        this.accountType = accountType;
+    }
+
+
+    public long getDomainId() {
+        return domainId;
+    }
+
+
+    public void setDomainId(long domainId) {
+        this.domainId = domainId;
+    }
+
+
+    public String getDomainUuid() {
+        return domainUuid;
+    }
+
+
+    public void setDomainUuid(String domainUuid) {
+        this.domainUuid = domainUuid;
+    }
+
+
+    public String getDomainName() {
+        return domainName;
+    }
+
+
+    public void setDomainName(String domainName) {
+        this.domainName = domainName;
+    }
+
+
+    public String getDomainPath() {
+        return domainPath;
+    }
+
+
+    public void setDomainPath(String domainPath) {
+        this.domainPath = domainPath;
+    }
+
+
+    public long getUserId() {
+        return userId;
+    }
+
+
+    public void setUserId(long userId) {
+        this.userId = userId;
+    }
+
+
+    public String getUserUuid() {
+        return userUuid;
+    }
+
+
+    public void setUserUuid(String userUuid) {
+        this.userUuid = userUuid;
+    }
+
+
+    public String getCmd() {
+        return cmd;
+    }
+
+
+    public void setCmd(String cmd) {
+        this.cmd = cmd;
+    }
+
+
+    public int getStatus() {
+        return status;
+    }
+
+
+    public void setStatus(int status) {
+        this.status = status;
+    }
+
+
+    public int getProcessStatus() {
+        return processStatus;
+    }
+
+
+    public void setProcessStatus(int processStatus) {
+        this.processStatus = processStatus;
+    }
+
+
+    public int getResultCode() {
+        return resultCode;
+    }
+
+
+    public void setResultCode(int resultCode) {
+        this.resultCode = resultCode;
+    }
+
+
+    public String getResult() {
+        return result;
+    }
+
+
+    public void setResult(String result) {
+        this.result = result;
+    }
+
+
+    public Date getCreated() {
+        return created;
+    }
+
+
+    public void setCreated(Date created) {
+        this.created = created;
+    }
+
+
+    public Date getRemoved() {
+        return removed;
+    }
+
+
+    public void setRemoved(Date removed) {
+        this.removed = removed;
+    }
+
+
+    public Type getInstanceType() {
+        return instanceType;
+    }
+
+
+    public void setInstanceType(Type instanceType) {
+        this.instanceType = instanceType;
+    }
+
+
+    public Long getInstanceId() {
+        return instanceId;
+    }
+
+
+    public void setInstanceId(Long instanceId) {
+        this.instanceId = instanceId;
+    }
+
+
+    public String getInstanceUuid() {
+        return instanceUuid;
+    }
+
+
+    public void setInstanceUuid(String instanceUuid) {
+        this.instanceUuid = instanceUuid;
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-cloudstack/blob/daeb4abc/server/src/com/cloud/configuration/DefaultComponentLibrary.java
----------------------------------------------------------------------
diff --git a/server/src/com/cloud/configuration/DefaultComponentLibrary.java b/server/src/com/cloud/configuration/DefaultComponentLibrary.java
index ac7602c..2fbe758 100755
--- a/server/src/com/cloud/configuration/DefaultComponentLibrary.java
+++ b/server/src/com/cloud/configuration/DefaultComponentLibrary.java
@@ -26,6 +26,7 @@ import com.cloud.alert.AlertManagerImpl;
 import com.cloud.alert.dao.AlertDaoImpl;
 import com.cloud.api.query.QueryManagerImpl;
 import com.cloud.api.query.dao.AccountJoinDaoImpl;
+import com.cloud.api.query.dao.AsyncJobJoinDaoImpl;
 import com.cloud.api.query.dao.DomainRouterJoinDaoImpl;
 import com.cloud.api.query.dao.InstanceGroupJoinDaoImpl;
 import com.cloud.api.query.dao.ProjectAccountJoinDaoImpl;
@@ -246,6 +247,7 @@ public class DefaultComponentLibrary extends ComponentLibraryBase implements Com
         addDao("HostJoinDao", HostJoinDaoImpl.class);
         addDao("VolumeJoinDao", VolumeJoinDaoImpl.class);
         addDao("AccountJoinDao", AccountJoinDaoImpl.class);
+        addDao("AsyncJobJoinDao", AsyncJobJoinDaoImpl.class);
         ComponentInfo<? extends GenericDao<?, ? extends Serializable>> info = addDao("ServiceOfferingDao", ServiceOfferingDaoImpl.class);
         info.addParameter("cache.size", "50");
         info.addParameter("cache.time.to.live", "600");

http://git-wip-us.apache.org/repos/asf/incubator-cloudstack/blob/daeb4abc/server/src/com/cloud/server/ManagementServerImpl.java
----------------------------------------------------------------------
diff --git a/server/src/com/cloud/server/ManagementServerImpl.java b/server/src/com/cloud/server/ManagementServerImpl.java
index ee5f78e..e500192 100755
--- a/server/src/com/cloud/server/ManagementServerImpl.java
+++ b/server/src/com/cloud/server/ManagementServerImpl.java
@@ -1426,14 +1426,14 @@ public class ManagementServerImpl implements ManagementServer {
             }
         } else if (_s3Mgr.isS3Enabled()) {
             if (template == null) {
-                templateZonePairSet = _templateDao.searchSwiftTemplates(name, keyword, templateFilter, isIso, 
+                templateZonePairSet = _templateDao.searchSwiftTemplates(name, keyword, templateFilter, isIso,
                         hypers, bootable, domain, pageSize, startIndex, zoneId, hyperType, onlyReady, showDomr,
                         permittedAccounts, caller, tags);
                 Set<Pair<Long, Long>> templateZonePairSet2 = new HashSet<Pair<Long, Long>>();
-                templateZonePairSet2 = _templateDao.searchTemplates(name, keyword, templateFilter, isIso, hypers, 
+                templateZonePairSet2 = _templateDao.searchTemplates(name, keyword, templateFilter, isIso, hypers,
                         bootable, domain, pageSize, startIndex, zoneId, hyperType, onlyReady, showDomr,
                         permittedAccounts, caller, listProjectResourcesCriteria, tags);
-                
+
                 for (Pair<Long, Long> tmpltPair : templateZonePairSet2) {
                     if (!templateZonePairSet.contains(new Pair<Long, Long>(tmpltPair.first(), -1L))) {
                         templateZonePairSet.add(tmpltPair);
@@ -2417,84 +2417,6 @@ public class ManagementServerImpl implements ManagementServer {
         return _poolDao.searchAndCount(sc, searchFilter);
     }
 
-    @Override
-    public Pair<List<? extends AsyncJob>, Integer> searchForAsyncJobs(ListAsyncJobsCmd cmd) {
-
-        Account caller = UserContext.current().getCaller();
-
-        List<Long> permittedAccounts = new ArrayList<Long>();
-
-        Ternary<Long, Boolean, ListProjectResourcesCriteria> domainIdRecursiveListProject = new Ternary<Long, Boolean, ListProjectResourcesCriteria>(
-                cmd.getDomainId(), cmd.isRecursive(), null);
-        _accountMgr.buildACLSearchParameters(caller, null, cmd.getAccountName(), null, permittedAccounts, domainIdRecursiveListProject,
-                cmd.listAll(), false);
-        Long domainId = domainIdRecursiveListProject.first();
-        Boolean isRecursive = domainIdRecursiveListProject.second();
-        ListProjectResourcesCriteria listProjectResourcesCriteria = domainIdRecursiveListProject.third();
-
-        Filter searchFilter = new Filter(AsyncJobVO.class, "id", true, cmd.getStartIndex(), cmd.getPageSizeVal());
-        SearchBuilder<AsyncJobVO> sb = _jobDao.createSearchBuilder();
-        sb.and("accountIdIN", sb.entity().getAccountId(), SearchCriteria.Op.IN);
-        SearchBuilder<AccountVO> accountSearch = null;
-        boolean accountJoinIsDone = false;
-        if (permittedAccounts.isEmpty() && domainId != null) {
-            accountSearch = _accountDao.createSearchBuilder();
-            // if accountId isn't specified, we can do a domain match for the
-            // admin case if isRecursive is true
-            SearchBuilder<DomainVO> domainSearch = _domainDao.createSearchBuilder();
-            domainSearch.and("domainId", domainSearch.entity().getId(), SearchCriteria.Op.EQ);
-            domainSearch.and("path", domainSearch.entity().getPath(), SearchCriteria.Op.LIKE);
-            sb.join("accountSearch", accountSearch, sb.entity().getAccountId(), accountSearch.entity().getId(), JoinBuilder.JoinType.INNER);
-            accountJoinIsDone = true;
-            accountSearch.join("domainSearch", domainSearch, accountSearch.entity().getDomainId(), domainSearch.entity().getId(),
-                    JoinBuilder.JoinType.INNER);
-        }
-
-        if (listProjectResourcesCriteria != null) {
-            if (accountSearch == null) {
-                accountSearch = _accountDao.createSearchBuilder();
-            }
-            if (listProjectResourcesCriteria == Project.ListProjectResourcesCriteria.ListProjectResourcesOnly) {
-                accountSearch.and("type", accountSearch.entity().getType(), SearchCriteria.Op.EQ);
-            } else if (listProjectResourcesCriteria == Project.ListProjectResourcesCriteria.SkipProjectResources) {
-                accountSearch.and("type", accountSearch.entity().getType(), SearchCriteria.Op.NEQ);
-            }
-
-            if (!accountJoinIsDone) {
-                sb.join("accountSearch", accountSearch, sb.entity().getAccountId(), accountSearch.entity().getId(), JoinBuilder.JoinType.INNER);
-            }
-        }
-
-        Object keyword = cmd.getKeyword();
-        Object startDate = cmd.getStartDate();
-
-        SearchCriteria<AsyncJobVO> sc = sb.create();
-        if (listProjectResourcesCriteria != null) {
-            sc.setJoinParameters("accountSearch", "type", Account.ACCOUNT_TYPE_PROJECT);
-        }
-
-        if (!permittedAccounts.isEmpty()) {
-            sc.setParameters("accountIdIN", permittedAccounts.toArray());
-        } else if (domainId != null) {
-            DomainVO domain = _domainDao.findById(domainId);
-            if (isRecursive) {
-                sc.setJoinParameters("domainSearch", "path", domain.getPath() + "%");
-            } else {
-                sc.setJoinParameters("domainSearch", "domainId", domainId);
-            }
-        }
-
-        if (keyword != null) {
-            sc.addAnd("cmd", SearchCriteria.Op.LIKE, "%" + keyword + "%");
-        }
-
-        if (startDate != null) {
-            sc.addAnd("created", SearchCriteria.Op.GTEQ, startDate);
-        }
-
-        Pair<List<AsyncJobVO>, Integer> result = _jobDao.searchAndCount(sc, searchFilter);
-        return new Pair<List<? extends AsyncJob>, Integer>(result.first(), result.second());
-    }
 
     @ActionEvent(eventType = EventTypes.EVENT_SSVM_START, eventDescription = "starting secondary storage Vm", async = true)
     public SecondaryStorageVmVO startSecondaryStorageVm(long instanceId) {

http://git-wip-us.apache.org/repos/asf/incubator-cloudstack/blob/daeb4abc/setup/db/create-schema.sql
----------------------------------------------------------------------
diff --git a/setup/db/create-schema.sql b/setup/db/create-schema.sql
index dcea142..d95984a 100755
--- a/setup/db/create-schema.sql
+++ b/setup/db/create-schema.sql
@@ -3240,4 +3240,79 @@ left join resource_limit projectlimit on account.id = projectlimit.account_id an
 left join resource_count projectcount on account.id = projectcount.account_id and projectcount.type = "project"
 left join resource_limit networklimit on account.id = networklimit.account_id and networklimit.type = "network"
 left join resource_count networkcount on account.id = networkcount.account_id and networkcount.type = "network"
-left join async_job on async_job.instance_id = account.id and async_job.instance_type = "Account" and async_job.job_status = 0;
\ No newline at end of file
+left join async_job on async_job.instance_id = account.id and async_job.instance_type = "Account" and async_job.job_status = 0;
+
+DROP VIEW IF EXISTS `cloud`.`async_job_view`;
+CREATE VIEW async_job_view AS
+select 
+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,
+user.id user_id,
+user.uuid user_uuid,
+async_job.id,
+async_job.uuid,
+async_job.job_cmd,
+async_job.job_status,
+async_job.job_process_status,
+async_job.job_result_code,
+async_job.job_result,
+async_job.created,
+async_job.removed,
+async_job.instance_type,
+async_job.instance_id,
+CASE 
+WHEN async_job.instance_type = 'Volume' THEN volumes.uuid 
+WHEN async_job.instance_type = 'Template' or async_job.instance_type = 'Iso' THEN vm_template.uuid
+WHEN async_job.instance_type = 'VirtualMachine' or async_job.instance_type = 'ConsoleProxy' or async_job.instance_type = 'SystemVm' or async_job.instance_type = 'DomainRouter' THEN vm_instance.uuid 
+WHEN async_job.instance_type = 'Snapshot' THEN snapshots.uuid 
+WHEN async_job.instance_type = 'Host' THEN host.uuid 
+WHEN async_job.instance_type = 'StoragePool' THEN storage_pool.uuid 
+WHEN async_job.instance_type = 'IpAddress' THEN user_ip_address.uuid 
+WHEN async_job.instance_type = 'SecurityGroup' THEN security_group.uuid 
+WHEN async_job.instance_type = 'PhysicalNetwork' THEN physical_network.uuid 
+WHEN async_job.instance_type = 'TrafficType' THEN physical_network_traffic_types.uuid 
+WHEN async_job.instance_type = 'PhysicalNetworkServiceProvider' THEN physical_network_service_providers.uuid
+WHEN async_job.instance_type = 'FirewallRule' THEN firewall_rules.uuid
+WHEN async_job.instance_type = 'Account' THEN acct.uuid
+WHEN async_job.instance_type = 'User' THEN us.uuid
+WHEN async_job.instance_type = 'StaticRoute' THEN static_routes.uuid
+WHEN async_job.instance_type = 'PrivateGateway' THEN vpc_gateways.uuid
+WHEN async_job.instance_type = 'Counter' THEN counter.uuid
+WHEN async_job.instance_type = 'Condition' THEN conditions.uuid
+WHEN async_job.instance_type = 'AutoScalePolicy' THEN autoscale_policies.uuid
+WHEN async_job.instance_type = 'AutoScaleVmProfile' THEN autoscale_vmprofiles.uuid
+WHEN async_job.instance_type = 'AutoScaleVmGroup' THEN autoscale_vmgroups.uuid
+ELSE null
+END instance_uuid
+from async_job
+left join account on async_job.account_id = account.id
+left join domain on domain.id = account.domain_id
+left join user on async_job.user_id = user.id
+left join volumes on async_job.instance_id = volumes.id
+left join vm_template on async_job.instance_id = vm_template.id
+left join vm_instance on async_job.instance_id = vm_instance.id
+left join snapshots on async_job.instance_id = snapshots.id
+left join host on async_job.instance_id = host.id
+left join storage_pool on async_job.instance_id = storage_pool.id
+left join user_ip_address on async_job.instance_id = user_ip_address.id
+left join security_group on async_job.instance_id = security_group.id
+left join physical_network on async_job.instance_id = physical_network.id
+left join physical_network_traffic_types on async_job.instance_id = physical_network_traffic_types.id
+left join physical_network_service_providers on async_job.instance_id = physical_network_service_providers.id
+left join firewall_rules on async_job.instance_id = firewall_rules.id
+left join account acct on async_job.instance_id = acct.id
+left join user us on async_job.instance_id = us.id
+left join static_routes on async_job.instance_id = static_routes.id
+left join vpc_gateways on async_job.instance_id = vpc_gateways.id
+left join counter on async_job.instance_id = counter.id
+left join conditions on async_job.instance_id = conditions.id
+left join autoscale_policies on async_job.instance_id = autoscale_policies.id
+left join autoscale_vmprofiles on async_job.instance_id = autoscale_vmprofiles.id
+left join autoscale_vmgroups on async_job.instance_id = autoscale_vmgroups.id;
+

http://git-wip-us.apache.org/repos/asf/incubator-cloudstack/blob/daeb4abc/setup/db/db/schema-40to410.sql
----------------------------------------------------------------------
diff --git a/setup/db/db/schema-40to410.sql b/setup/db/db/schema-40to410.sql
index c862641..18e1ceb 100644
--- a/setup/db/db/schema-40to410.sql
+++ b/setup/db/db/schema-40to410.sql
@@ -821,3 +821,79 @@ left join resource_count projectcount on account.id = projectcount.account_id an
 left join resource_limit networklimit on account.id = networklimit.account_id and networklimit.type = "network"
 left join resource_count networkcount on account.id = networkcount.account_id and networkcount.type = "network"
 left join async_job on async_job.instance_id = account.id and async_job.instance_type = "Account" and async_job.job_status = 0;
+
+DROP VIEW IF EXISTS `cloud`.`async_job_view`;
+CREATE VIEW async_job_view AS
+select 
+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,
+user.id user_id,
+user.uuid user_uuid,
+async_job.id,
+async_job.uuid,
+async_job.job_cmd,
+async_job.job_status,
+async_job.job_process_status,
+async_job.job_result_code,
+async_job.job_result,
+async_job.created,
+async_job.removed,
+async_job.instance_type,
+async_job.instance_id,
+CASE 
+WHEN async_job.instance_type = 'Volume' THEN volumes.uuid 
+WHEN async_job.instance_type = 'Template' or async_job.instance_type = 'Iso' THEN vm_template.uuid
+WHEN async_job.instance_type = 'VirtualMachine' or async_job.instance_type = 'ConsoleProxy' or async_job.instance_type = 'SystemVm' or async_job.instance_type = 'DomainRouter' THEN vm_instance.uuid 
+WHEN async_job.instance_type = 'Snapshot' THEN snapshots.uuid 
+WHEN async_job.instance_type = 'Host' THEN host.uuid 
+WHEN async_job.instance_type = 'StoragePool' THEN storage_pool.uuid 
+WHEN async_job.instance_type = 'IpAddress' THEN user_ip_address.uuid 
+WHEN async_job.instance_type = 'SecurityGroup' THEN security_group.uuid 
+WHEN async_job.instance_type = 'PhysicalNetwork' THEN physical_network.uuid 
+WHEN async_job.instance_type = 'TrafficType' THEN physical_network_traffic_types.uuid 
+WHEN async_job.instance_type = 'PhysicalNetworkServiceProvider' THEN physical_network_service_providers.uuid
+WHEN async_job.instance_type = 'FirewallRule' THEN firewall_rules.uuid
+WHEN async_job.instance_type = 'Account' THEN acct.uuid
+WHEN async_job.instance_type = 'User' THEN us.uuid
+WHEN async_job.instance_type = 'StaticRoute' THEN static_routes.uuid
+WHEN async_job.instance_type = 'PrivateGateway' THEN vpc_gateways.uuid
+WHEN async_job.instance_type = 'Counter' THEN counter.uuid
+WHEN async_job.instance_type = 'Condition' THEN conditions.uuid
+WHEN async_job.instance_type = 'AutoScalePolicy' THEN autoscale_policies.uuid
+WHEN async_job.instance_type = 'AutoScaleVmProfile' THEN autoscale_vmprofiles.uuid
+WHEN async_job.instance_type = 'AutoScaleVmGroup' THEN autoscale_vmgroups.uuid
+ELSE null
+END instance_uuid
+from async_job
+left join account on async_job.account_id = account.id
+left join domain on domain.id = account.domain_id
+left join user on async_job.user_id = user.id
+left join volumes on async_job.instance_id = volumes.id
+left join vm_template on async_job.instance_id = vm_template.id
+left join vm_instance on async_job.instance_id = vm_instance.id
+left join snapshots on async_job.instance_id = snapshots.id
+left join host on async_job.instance_id = host.id
+left join storage_pool on async_job.instance_id = storage_pool.id
+left join user_ip_address on async_job.instance_id = user_ip_address.id
+left join security_group on async_job.instance_id = security_group.id
+left join physical_network on async_job.instance_id = physical_network.id
+left join physical_network_traffic_types on async_job.instance_id = physical_network_traffic_types.id
+left join physical_network_service_providers on async_job.instance_id = physical_network_service_providers.id
+left join firewall_rules on async_job.instance_id = firewall_rules.id
+left join account acct on async_job.instance_id = acct.id
+left join user us on async_job.instance_id = us.id
+left join static_routes on async_job.instance_id = static_routes.id
+left join vpc_gateways on async_job.instance_id = vpc_gateways.id
+left join counter on async_job.instance_id = counter.id
+left join conditions on async_job.instance_id = conditions.id
+left join autoscale_policies on async_job.instance_id = autoscale_policies.id
+left join autoscale_vmprofiles on async_job.instance_id = autoscale_vmprofiles.id
+left join autoscale_vmgroups on async_job.instance_id = autoscale_vmgroups.id;
+
+