From daeb4abcca6f6f97d64bd560ce9087d4c92ca4a2 Mon Sep 17 00:00:00 2001 From: Min Chen Date: Thu, 3 Jan 2013 15:35:26 -0800 Subject: [PATCH] Create DB views for AsyncJobResponse to speed up listAsyncJobsCmd. Signed-off-by: Min Chen --- .../com/cloud/server/ManagementService.java | 15 - .../command/user/job/ListAsyncJobsCmd.java | 10 +- .../apache/cloudstack/query/QueryService.java | 8 + server/src/com/cloud/api/ApiDBUtils.java | 13 + .../src/com/cloud/api/ApiResponseHelper.java | 46 +-- .../com/cloud/api/query/QueryManagerImpl.java | 88 ++++- .../cloud/api/query/ViewResponseHelper.java | 10 + .../cloud/api/query/dao/AsyncJobJoinDao.java | 34 ++ .../api/query/dao/AsyncJobJoinDaoImpl.java | 161 +++++++++ .../cloud/api/query/vo/AsyncJobJoinVO.java | 333 ++++++++++++++++++ .../DefaultComponentLibrary.java | 2 + .../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(-) create mode 100644 server/src/com/cloud/api/query/dao/AsyncJobJoinDao.java create mode 100644 server/src/com/cloud/api/query/dao/AsyncJobJoinDaoImpl.java create mode 100644 server/src/com/cloud/api/query/vo/AsyncJobJoinVO.java diff --git a/api/src/com/cloud/server/ManagementService.java b/api/src/com/cloud/server/ManagementService.java index ccccb90e92a..cacf5cf1100 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; @@ -328,15 +322,6 @@ public interface ManagementService { */ Pair, 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, Integer> searchForAsyncJobs(ListAsyncJobsCmd cmd); - /** * Generates a random password that will be used (initially) by newly created and started virtual machines * 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 e9301e95b6d..50ac52e025f 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, Integer> result = _mgr.searchForAsyncJobs(this); - ListResponse response = new ListResponse(); - List jobResponses = new ArrayList(); - for (AsyncJob job : result.first()) { - jobResponses.add(_responseGenerator.createAsyncJobResponse(job)); - } - response.setResponses(jobResponses, result.second()); + ListResponse response = _queryService.searchForAsyncJobs(this); response.setResponseName(getCommandName()); this.setResponseObject(response); + } } diff --git a/api/src/org/apache/cloudstack/query/QueryService.java b/api/src/org/apache/cloudstack/query/QueryService.java index a310bb3b35f..480eb316e97 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 searchForVolumes(ListVolumesCmd cmd); public ListResponse searchForAccounts(ListAccountsCmd cmd); + + public ListResponse searchForAsyncJobs(ListAsyncJobsCmd cmd); } diff --git a/server/src/com/cloud/api/ApiDBUtils.java b/server/src/com/cloud/api/ApiDBUtils.java index 1b2327ad156..343dad9b67a 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); + } } diff --git a/server/src/com/cloud/api/ApiResponseHelper.java b/server/src/com/cloud/api/ApiResponseHelper.java index 1013bbf93c2..7fc3c036e95 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 diff --git a/server/src/com/cloud/api/query/QueryManagerImpl.java b/server/src/com/cloud/api/query/QueryManagerImpl.java index a4ec02ad856..c47c1ef3375 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; @@ -216,6 +221,9 @@ public class QueryManagerImpl implements QueryService, Manager { @Inject private AccountJoinDao _accountJoinDao; + @Inject + private AsyncJobJoinDao _jobJoinDao; + @Inject private HighAvailabilityManager _haMgr; @@ -1727,10 +1735,86 @@ public class QueryManagerImpl implements QueryService, Manager { } } - Pair, Integer> result = _accountJoinDao.searchAndCount(sc, searchFilter); - return new Pair, Integer>(result.first(), result.second()); + return _accountJoinDao.searchAndCount(sc, searchFilter); + } + + @Override + public ListResponse searchForAsyncJobs(ListAsyncJobsCmd cmd) { + Pair, Integer> result = searchForAsyncJobsInternal(cmd); + ListResponse response = new ListResponse(); + List jobResponses = ViewResponseHelper.createAsyncJobResponse(result.first().toArray(new AsyncJobJoinVO[result.first().size()])); + response.setResponses(jobResponses, result.second()); + return response; } + public Pair, Integer> searchForAsyncJobsInternal(ListAsyncJobsCmd cmd) { + + Account caller = UserContext.current().getCaller(); + + List permittedAccounts = new ArrayList(); + + Ternary domainIdRecursiveListProject = new Ternary( + 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 sb = _jobJoinDao.createSearchBuilder(); + sb.and("accountIdIN", sb.entity().getAccountId(), SearchCriteria.Op.IN); + SearchBuilder 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 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); + } } diff --git a/server/src/com/cloud/api/query/ViewResponseHelper.java b/server/src/com/cloud/api/query/ViewResponseHelper.java index c29c93b394f..08495860b20 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 createAsyncJobResponse(AsyncJobJoinVO... jobs) { + List respList = new ArrayList(); + for (AsyncJobJoinVO vt : jobs){ + respList.add(ApiDBUtils.newAsyncJobResponse(vt)); + } + return respList; + } } 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 00000000000..59fcc87247a --- /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 { + + AsyncJobResponse newAsyncJobResponse(AsyncJobJoinVO vol); + + AsyncJobJoinVO newAsyncJobView(AsyncJob vol); + + List searchByIds(Long... ids); +} 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 00000000000..c0c827b124a --- /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 implements AsyncJobJoinDao { + public static final Logger s_logger = Logger.getLogger(AsyncJobJoinDaoImpl.class); + + private SearchBuilder jobSearch; + + private SearchBuilder 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 sc = jobIdSearch.create(); + sc.setParameters("id", job.getId()); + List 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 searchByIds(Long... ids) { + SearchCriteria sc = jobSearch.create(); + sc.setParameters("idIN", ids); + return searchIncludingRemoved(sc, null, null, false); + } + + + +} 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 00000000000..39bcb1777e6 --- /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; + } + +} diff --git a/server/src/com/cloud/configuration/DefaultComponentLibrary.java b/server/src/com/cloud/configuration/DefaultComponentLibrary.java index ac7602c45c0..2fbe7586ac9 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> info = addDao("ServiceOfferingDao", ServiceOfferingDaoImpl.class); info.addParameter("cache.size", "50"); info.addParameter("cache.time.to.live", "600"); diff --git a/server/src/com/cloud/server/ManagementServerImpl.java b/server/src/com/cloud/server/ManagementServerImpl.java index ee5f78e5640..e5001927191 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> templateZonePairSet2 = new HashSet>(); - 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 tmpltPair : templateZonePairSet2) { if (!templateZonePairSet.contains(new Pair(tmpltPair.first(), -1L))) { templateZonePairSet.add(tmpltPair); @@ -2417,84 +2417,6 @@ public class ManagementServerImpl implements ManagementServer { return _poolDao.searchAndCount(sc, searchFilter); } - @Override - public Pair, Integer> searchForAsyncJobs(ListAsyncJobsCmd cmd) { - - Account caller = UserContext.current().getCaller(); - - List permittedAccounts = new ArrayList(); - - Ternary domainIdRecursiveListProject = new Ternary( - 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 sb = _jobDao.createSearchBuilder(); - sb.and("accountIdIN", sb.entity().getAccountId(), SearchCriteria.Op.IN); - SearchBuilder 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 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 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, Integer> result = _jobDao.searchAndCount(sc, searchFilter); - return new Pair, Integer>(result.first(), result.second()); - } @ActionEvent(eventType = EventTypes.EVENT_SSVM_START, eventDescription = "starting secondary storage Vm", async = true) public SecondaryStorageVmVO startSecondaryStorageVm(long instanceId) { diff --git a/setup/db/create-schema.sql b/setup/db/create-schema.sql index dcea14201b3..d95984aa69c 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; + diff --git a/setup/db/db/schema-40to410.sql b/setup/db/db/schema-40to410.sql index c8626419ae5..18e1cebf43b 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; + +