From e7fa1a86fbdf39a43528921a0ea7530d3a5f1e57 Mon Sep 17 00:00:00 2001 From: Min Chen Date: Sat, 22 Dec 2012 21:47:05 -0800 Subject: [PATCH] Create DB views to improve ListHostsCmd performance. Signed-off-by: Min Chen --- .../com/cloud/server/ManagementService.java | 8 - .../api/command/admin/host/ListHostsCmd.java | 42 +- .../cloudstack/api/response/HostResponse.java | 5 + .../apache/cloudstack/query/QueryService.java | 4 +- client/cloudstack-ui.launch | 18 - client/tomcatconf/log4j-cloud.xml.in | 4 + server/src/com/cloud/api/ApiDBUtils.java | 20 +- .../src/com/cloud/api/ApiResponseHelper.java | 135 +---- server/src/com/cloud/api/ApiServer.java | 4 +- .../com/cloud/api/query/QueryManagerImpl.java | 129 +++++ .../cloud/api/query/ViewResponseHelper.java | 21 + .../com/cloud/api/query/dao/HostJoinDao.java | 38 ++ .../cloud/api/query/dao/HostJoinDaoImpl.java | 222 ++++++++ .../com/cloud/api/query/vo/HostJoinVO.java | 503 ++++++++++++++++++ .../api/response/ApiResponseSerializer.java | 39 +- .../DefaultComponentLibrary.java | 2 + .../cloud/resource/ResourceManagerImpl.java | 46 +- .../cloud/server/ManagementServerImpl.java | 17 - .../src/com/cloud/storage/StorageManager.java | 36 +- .../com/cloud/storage/StorageManagerImpl.java | 128 ++--- server/test/com/cloud/api/APITest.java | 189 +++++++ server/test/com/cloud/api/ListPerfTest.java | 109 ++++ server/test/com/cloud/api/LoginResponse.java | 142 +++++ 23 files changed, 1541 insertions(+), 320 deletions(-) create mode 100644 server/src/com/cloud/api/query/dao/HostJoinDao.java create mode 100644 server/src/com/cloud/api/query/dao/HostJoinDaoImpl.java create mode 100644 server/src/com/cloud/api/query/vo/HostJoinVO.java create mode 100644 server/test/com/cloud/api/APITest.java create mode 100644 server/test/com/cloud/api/ListPerfTest.java create mode 100644 server/test/com/cloud/api/LoginResponse.java diff --git a/api/src/com/cloud/server/ManagementService.java b/api/src/com/cloud/server/ManagementService.java index 70ef79973ac..ccccb90e92a 100755 --- a/api/src/com/cloud/server/ManagementService.java +++ b/api/src/com/cloud/server/ManagementService.java @@ -146,14 +146,6 @@ public interface ManagementService { */ Pair, Integer> searchForPods(ListPodsByCmd cmd); - /** - * Searches for servers by the specified search criteria Can search by: "name", "type", "state", "dataCenterId", - * "podId" - * - * @param cmd - * @return List of Hosts - */ - List searchForServers(ListHostsCmd cmd); /** * Creates a new template diff --git a/api/src/org/apache/cloudstack/api/command/admin/host/ListHostsCmd.java b/api/src/org/apache/cloudstack/api/command/admin/host/ListHostsCmd.java index 32395e7be48..881b1f2c300 100644 --- a/api/src/org/apache/cloudstack/api/command/admin/host/ListHostsCmd.java +++ b/api/src/org/apache/cloudstack/api/command/admin/host/ListHostsCmd.java @@ -28,6 +28,7 @@ import org.apache.cloudstack.api.BaseListCmd; import org.apache.cloudstack.api.Implementation; import org.apache.cloudstack.api.Parameter; import org.apache.cloudstack.api.response.ClusterResponse; +import org.apache.cloudstack.api.response.DomainRouterResponse; import org.apache.cloudstack.api.response.HostResponse; import org.apache.cloudstack.api.response.ListResponse; import org.apache.cloudstack.api.response.PodResponse; @@ -164,32 +165,35 @@ public class ListHostsCmd extends BaseListCmd { @Override public void execute(){ - List result = new ArrayList(); - List hostsWithCapacity = new ArrayList(); + ListResponse response = null; + if (getVirtualMachineId() == null) { + response = _queryService.searchForServers(this); + } else { + List result = new ArrayList(); + List hostsWithCapacity = new ArrayList(); - if(getVirtualMachineId() != null){ - Pair, List> hostsForMigration = _mgr.listHostsForMigrationOfVM(getVirtualMachineId(), this.getStartIndex(), this.getPageSizeVal()); + Pair, List> hostsForMigration = _mgr.listHostsForMigrationOfVM(getVirtualMachineId(), + this.getStartIndex(), this.getPageSizeVal()); result = hostsForMigration.first(); hostsWithCapacity = hostsForMigration.second(); - }else{ - result = _mgr.searchForServers(this); - } - ListResponse response = new ListResponse(); - List hostResponses = new ArrayList(); - for (Host host : result) { - HostResponse hostResponse = _responseGenerator.createHostResponse(host, getDetails()); - Boolean suitableForMigration = false; - if(hostsWithCapacity.contains(host)){ - suitableForMigration = true; + response = new ListResponse(); + List hostResponses = new ArrayList(); + for (Host host : result) { + HostResponse hostResponse = _responseGenerator.createHostResponse(host, getDetails()); + Boolean suitableForMigration = false; + if (hostsWithCapacity.contains(host)) { + suitableForMigration = true; + } + hostResponse.setSuitableForMigration(suitableForMigration); + hostResponse.setObjectName("host"); + hostResponses.add(hostResponse); } - hostResponse.setSuitableForMigration(suitableForMigration); - hostResponse.setObjectName("host"); - hostResponses.add(hostResponse); - } - response.setResponses(hostResponses); + response.setResponses(hostResponses); + } response.setResponseName(getCommandName()); this.setResponseObject(response); + } } diff --git a/api/src/org/apache/cloudstack/api/response/HostResponse.java b/api/src/org/apache/cloudstack/api/response/HostResponse.java index 39309caef6c..348d48a48a9 100644 --- a/api/src/org/apache/cloudstack/api/response/HostResponse.java +++ b/api/src/org/apache/cloudstack/api/response/HostResponse.java @@ -317,6 +317,11 @@ public class HostResponse extends BaseResponse { this.events = events; } + + public String getHostTags() { + return hostTags; + } + public void setHostTags(String hostTags) { this.hostTags = hostTags; } diff --git a/api/src/org/apache/cloudstack/query/QueryService.java b/api/src/org/apache/cloudstack/query/QueryService.java index da526e0539f..1847edef4eb 100644 --- a/api/src/org/apache/cloudstack/query/QueryService.java +++ b/api/src/org/apache/cloudstack/query/QueryService.java @@ -16,6 +16,7 @@ // under the License. package org.apache.cloudstack.query; +import org.apache.cloudstack.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.ListProjectAccountsCmd; @@ -28,6 +29,7 @@ import org.apache.cloudstack.api.command.user.vm.ListVMsCmd; import org.apache.cloudstack.api.command.user.vmgroup.ListVMGroupsCmd; import org.apache.cloudstack.api.response.DomainRouterResponse; import org.apache.cloudstack.api.response.EventResponse; +import org.apache.cloudstack.api.response.HostResponse; import org.apache.cloudstack.api.response.InstanceGroupResponse; import org.apache.cloudstack.api.response.ListResponse; import org.apache.cloudstack.api.response.ProjectAccountResponse; @@ -70,5 +72,5 @@ public interface QueryService { public ListResponse listProjectAccounts(ListProjectAccountsCmd cmd); - + public ListResponse searchForServers(ListHostsCmd cmd); } diff --git a/client/cloudstack-ui.launch b/client/cloudstack-ui.launch index 1943d17aebd..b47097c33cf 100644 --- a/client/cloudstack-ui.launch +++ b/client/cloudstack-ui.launch @@ -1,22 +1,4 @@ - diff --git a/client/tomcatconf/log4j-cloud.xml.in b/client/tomcatconf/log4j-cloud.xml.in index 6c7f29d0162..02f70998d53 100755 --- a/client/tomcatconf/log4j-cloud.xml.in +++ b/client/tomcatconf/log4j-cloud.xml.in @@ -104,6 +104,10 @@ under the License. + + + + diff --git a/server/src/com/cloud/api/ApiDBUtils.java b/server/src/com/cloud/api/ApiDBUtils.java index 2aaee2e2fc5..ac7aeb62bb7 100755 --- a/server/src/com/cloud/api/ApiDBUtils.java +++ b/server/src/com/cloud/api/ApiDBUtils.java @@ -22,9 +22,11 @@ import java.util.List; import java.util.Map; import java.util.Set; +import org.apache.cloudstack.api.ApiConstants.HostDetails; import org.apache.cloudstack.api.ApiConstants.VMDetails; import org.apache.cloudstack.api.response.DomainRouterResponse; import org.apache.cloudstack.api.response.EventResponse; +import org.apache.cloudstack.api.response.HostResponse; import org.apache.cloudstack.api.response.InstanceGroupResponse; import org.apache.cloudstack.api.response.ProjectAccountResponse; import org.apache.cloudstack.api.response.ProjectInvitationResponse; @@ -35,6 +37,7 @@ import org.apache.cloudstack.api.response.UserResponse; import org.apache.cloudstack.api.response.UserVmResponse; import com.cloud.api.query.dao.DomainRouterJoinDao; +import com.cloud.api.query.dao.HostJoinDao; import com.cloud.api.query.dao.InstanceGroupJoinDao; import com.cloud.api.query.dao.ProjectAccountJoinDao; import com.cloud.api.query.dao.ProjectInvitationJoinDao; @@ -44,6 +47,7 @@ import com.cloud.api.query.dao.SecurityGroupJoinDao; import com.cloud.api.query.dao.UserVmJoinDao; import com.cloud.api.query.vo.DomainRouterJoinVO; import com.cloud.api.query.vo.EventJoinVO; +import com.cloud.api.query.vo.HostJoinVO; import com.cloud.api.query.vo.InstanceGroupJoinVO; import com.cloud.api.query.vo.ProjectAccountJoinVO; import com.cloud.api.query.vo.ProjectInvitationJoinVO; @@ -305,6 +309,7 @@ public class ApiDBUtils { private static ProjectJoinDao _projectJoinDao; private static ProjectAccountJoinDao _projectAccountJoinDao; private static ProjectInvitationJoinDao _projectInvitationJoinDao; + private static HostJoinDao _hostJoinDao; private static PhysicalNetworkTrafficTypeDao _physicalNetworkTrafficTypeDao; private static PhysicalNetworkServiceProviderDao _physicalNetworkServiceProviderDao; @@ -390,6 +395,7 @@ public class ApiDBUtils { _projectJoinDao = locator.getDao(ProjectJoinDao.class); _projectAccountJoinDao = locator.getDao(ProjectAccountJoinDao.class); _projectInvitationJoinDao = locator.getDao(ProjectInvitationJoinDao.class); + _hostJoinDao = locator.getDao(HostJoinDao.class); _physicalNetworkTrafficTypeDao = locator.getDao(PhysicalNetworkTrafficTypeDao.class); _physicalNetworkServiceProviderDao = locator.getDao(PhysicalNetworkServiceProviderDao.class); @@ -506,8 +512,8 @@ public class ApiDBUtils { return _storageMgr.getStoragePoolTags(poolId); } - public static boolean isLocalStorageActiveOnHost(Host host) { - return _storageMgr.isLocalStorageActiveOnHost(host); + public static boolean isLocalStorageActiveOnHost(Long hostId) { + return _storageMgr.isLocalStorageActiveOnHost(hostId); } public static InstanceGroupVO findInstanceGroupForVM(long vmId) { @@ -1295,5 +1301,15 @@ public class ApiDBUtils { return _projectInvitationJoinDao.newProjectInvitationView(proj); } + public static HostResponse newHostResponse(HostJoinVO vr, EnumSet details) { + return _hostJoinDao.newHostResponse(vr, details); + } + public static HostResponse fillHostDetails(HostResponse vrData, HostJoinVO vr){ + return _hostJoinDao.setHostResponse(vrData, vr); + } + + public static List newHostView(Host vr){ + return _hostJoinDao.newHostView(vr); + } } diff --git a/server/src/com/cloud/api/ApiResponseHelper.java b/server/src/com/cloud/api/ApiResponseHelper.java index 5640ab7f22d..5cb0f4890a8 100755 --- a/server/src/com/cloud/api/ApiResponseHelper.java +++ b/server/src/com/cloud/api/ApiResponseHelper.java @@ -45,6 +45,7 @@ import com.cloud.api.query.ViewResponseHelper; import com.cloud.api.query.vo.ControlledViewEntity; import com.cloud.api.query.vo.DomainRouterJoinVO; import com.cloud.api.query.vo.EventJoinVO; +import com.cloud.api.query.vo.HostJoinVO; import com.cloud.api.query.vo.InstanceGroupJoinVO; import com.cloud.api.query.vo.ProjectAccountJoinVO; import com.cloud.api.query.vo.ProjectInvitationJoinVO; @@ -616,136 +617,10 @@ public class ApiResponseHelper implements ResponseGenerator { @Override public HostResponse createHostResponse(Host host, EnumSet details) { - HostResponse hostResponse = new HostResponse(); - hostResponse.setId(host.getUuid()); - hostResponse.setCapabilities(host.getCapabilities()); - ClusterVO cluster = null; - if (host.getClusterId() != null) { - cluster = ApiDBUtils.findClusterById(host.getClusterId()); - if (cluster != null) { - hostResponse.setClusterId(cluster.getUuid()); - } - } - hostResponse.setCpuNumber(host.getCpus()); - DataCenter zone = ApiDBUtils.findZoneById(host.getDataCenterId()); - if (zone != null) { - hostResponse.setZoneId(zone.getUuid()); - } - hostResponse.setDisconnectedOn(host.getDisconnectedOn()); - hostResponse.setHypervisor(host.getHypervisorType()); - hostResponse.setHostType(host.getType()); - hostResponse.setLastPinged(new Date(host.getLastPinged())); - hostResponse.setManagementServerId(host.getManagementServerId()); - hostResponse.setName(host.getName()); - HostPodVO pod = ApiDBUtils.findPodById(host.getPodId()); - if (pod != null) { - hostResponse.setPodId(pod.getUuid()); - } - hostResponse.setRemoved(host.getRemoved()); - hostResponse.setCpuSpeed(host.getSpeed()); - hostResponse.setState(host.getStatus()); - hostResponse.setIpAddress(host.getPrivateIpAddress()); - hostResponse.setVersion(host.getVersion()); - hostResponse.setCreated(host.getCreated()); - - if (details.contains(HostDetails.all) || details.contains(HostDetails.capacity) - || details.contains(HostDetails.stats) || details.contains(HostDetails.events)) { - - GuestOSCategoryVO guestOSCategory = ApiDBUtils.getHostGuestOSCategory(host.getId()); - if (guestOSCategory != null) { - hostResponse.setOsCategoryId(guestOSCategory.getUuid()); - hostResponse.setOsCategoryName(guestOSCategory.getName()); - } - if (zone != null) { - hostResponse.setZoneName(zone.getName()); - } - - if (pod != null) { - hostResponse.setPodName(pod.getName()); - } - - if (cluster != null) { - hostResponse.setClusterName(cluster.getName()); - hostResponse.setClusterType(cluster.getClusterType().toString()); - } - } - - DecimalFormat decimalFormat = new DecimalFormat("#.##"); - if (host.getType() == Host.Type.Routing) { - if (details.contains(HostDetails.all) || details.contains(HostDetails.capacity)) { - // set allocated capacities - Long mem = ApiDBUtils.getMemoryOrCpuCapacitybyHost(host.getId(), Capacity.CAPACITY_TYPE_MEMORY); - Long cpu = ApiDBUtils.getMemoryOrCpuCapacitybyHost(host.getId(), Capacity.CAPACITY_TYPE_CPU); - - hostResponse.setMemoryAllocated(mem); - hostResponse.setMemoryTotal(host.getTotalMemory()); - String hostTags = ApiDBUtils.getHostTags(host.getId()); - hostResponse.setHostTags(hostTags); - - String haTag = ApiDBUtils.getHaTag(); - if (haTag != null && !haTag.isEmpty() && hostTags != null && !hostTags.isEmpty()) { - if (haTag.equalsIgnoreCase(hostTags)) { - hostResponse.setHaHost(true); - } else { - hostResponse.setHaHost(false); - } - } else { - hostResponse.setHaHost(false); - } - - hostResponse.setHypervisorVersion(host.getHypervisorVersion()); - - String cpuAlloc = decimalFormat.format(((float) cpu / (float) (host.getCpus() * host.getSpeed())) * 100f) + "%"; - hostResponse.setCpuAllocated(cpuAlloc); - String cpuWithOverprovisioning = new Float(host.getCpus() * host.getSpeed() * ApiDBUtils.getCpuOverprovisioningFactor()).toString(); - hostResponse.setCpuWithOverprovisioning(cpuWithOverprovisioning); - } - - if (details.contains(HostDetails.all) || details.contains(HostDetails.stats)) { - // set CPU/RAM/Network stats - String cpuUsed = null; - HostStats hostStats = ApiDBUtils.getHostStatistics(host.getId()); - if (hostStats != null) { - float cpuUtil = (float) hostStats.getCpuUtilization(); - cpuUsed = decimalFormat.format(cpuUtil) + "%"; - hostResponse.setCpuUsed(cpuUsed); - hostResponse.setMemoryUsed((new Double(hostStats.getUsedMemory())).longValue()); - hostResponse.setNetworkKbsRead((new Double(hostStats.getNetworkReadKBs())).longValue()); - hostResponse.setNetworkKbsWrite((new Double(hostStats.getNetworkWriteKBs())).longValue()); - - } - } - - } else if (host.getType() == Host.Type.SecondaryStorage) { - StorageStats secStorageStats = ApiDBUtils.getSecondaryStorageStatistics(host.getId()); - if (secStorageStats != null) { - hostResponse.setDiskSizeTotal(secStorageStats.getCapacityBytes()); - hostResponse.setDiskSizeAllocated(secStorageStats.getByteUsed()); - } - } - - hostResponse.setLocalStorageActive(ApiDBUtils.isLocalStorageActiveOnHost(host)); - - if (details.contains(HostDetails.all) || details.contains(HostDetails.events)) { - Set possibleEvents = host.getStatus().getPossibleEvents(); - if ((possibleEvents != null) && !possibleEvents.isEmpty()) { - String events = ""; - Iterator iter = possibleEvents.iterator(); - while (iter.hasNext()) { - com.cloud.host.Status.Event event = iter.next(); - events += event.toString(); - if (iter.hasNext()) { - events += "; "; - } - } - hostResponse.setEvents(events); - } - } - - hostResponse.setResourceState(host.getResourceState().toString()); - hostResponse.setObjectName("host"); - - return hostResponse; + List viewHosts = ApiDBUtils.newHostView(host); + List listHosts = ViewResponseHelper.createHostResponse(details, viewHosts.toArray(new HostJoinVO[viewHosts.size()])); + assert listHosts != null && listHosts.size() == 1 : "There should be one host returned"; + return listHosts.get(0); } @Override diff --git a/server/src/com/cloud/api/ApiServer.java b/server/src/com/cloud/api/ApiServer.java index 651de7ff67f..9e549efc73e 100755 --- a/server/src/com/cloud/api/ApiServer.java +++ b/server/src/com/cloud/api/ApiServer.java @@ -85,6 +85,7 @@ import org.apache.http.protocol.ResponseDate; import org.apache.http.protocol.ResponseServer; import org.apache.log4j.Logger; +import org.apache.cloudstack.api.command.admin.host.ListHostsCmd; import org.apache.cloudstack.api.command.admin.router.ListRoutersCmd; import org.apache.cloudstack.api.command.user.project.ListProjectInvitationsCmd; import org.apache.cloudstack.api.command.user.project.ListProjectsCmd; @@ -460,7 +461,8 @@ public class ApiServer implements HttpRequestHandler { && !(cmdObj instanceof ListVMGroupsCmd) && !(cmdObj instanceof ListProjectsCmd) && !(cmdObj instanceof ListProjectAccountsCmd) - && !(cmdObj instanceof ListProjectInvitationsCmd)) { + && !(cmdObj instanceof ListProjectInvitationsCmd) + && !(cmdObj instanceof ListHostsCmd)) { buildAsyncListResponse((BaseListCmd) cmdObj, caller); } diff --git a/server/src/com/cloud/api/query/QueryManagerImpl.java b/server/src/com/cloud/api/query/QueryManagerImpl.java index b9ed92a3069..61af1616e49 100644 --- a/server/src/com/cloud/api/query/QueryManagerImpl.java +++ b/server/src/com/cloud/api/query/QueryManagerImpl.java @@ -26,7 +26,9 @@ import javax.ejb.Local; import javax.naming.ConfigurationException; import org.apache.cloudstack.api.ResponseGenerator; +import org.apache.cloudstack.api.ApiConstants.HostDetails; import org.apache.cloudstack.api.ApiConstants.VMDetails; +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.ListProjectAccountsCmd; @@ -39,6 +41,7 @@ import org.apache.cloudstack.api.command.user.vm.ListVMsCmd; import org.apache.cloudstack.api.command.user.vmgroup.ListVMGroupsCmd; import org.apache.cloudstack.api.response.DomainRouterResponse; import org.apache.cloudstack.api.response.EventResponse; +import org.apache.cloudstack.api.response.HostResponse; import org.apache.cloudstack.api.response.InstanceGroupResponse; import org.apache.cloudstack.api.response.ListResponse; import org.apache.cloudstack.api.response.ProjectAccountResponse; @@ -54,6 +57,7 @@ import org.apache.log4j.Logger; import com.cloud.api.ApiDBUtils; import com.cloud.api.ApiResponseHelper; import com.cloud.api.query.dao.DomainRouterJoinDao; +import com.cloud.api.query.dao.HostJoinDao; import com.cloud.api.query.dao.InstanceGroupJoinDao; import com.cloud.api.query.dao.ProjectAccountJoinDao; import com.cloud.api.query.dao.ProjectInvitationJoinDao; @@ -63,6 +67,7 @@ import com.cloud.api.query.dao.SecurityGroupJoinDao; import com.cloud.api.query.dao.UserVmJoinDao; import com.cloud.api.query.vo.DomainRouterJoinVO; import com.cloud.api.query.vo.EventJoinVO; +import com.cloud.api.query.vo.HostJoinVO; import com.cloud.api.query.vo.InstanceGroupJoinVO; import com.cloud.api.query.vo.ProjectAccountJoinVO; import com.cloud.api.query.vo.ProjectInvitationJoinVO; @@ -78,6 +83,10 @@ import com.cloud.domain.dao.DomainDao; import com.cloud.event.dao.EventJoinDao; import com.cloud.exception.InvalidParameterValueException; import com.cloud.exception.PermissionDeniedException; +import com.cloud.ha.HighAvailabilityManager; +import com.cloud.host.Host; +import com.cloud.host.HostTagVO; +import com.cloud.host.HostVO; import com.cloud.hypervisor.Hypervisor.HypervisorType; import com.cloud.network.security.SecurityGroupVMMapVO; import com.cloud.network.security.dao.SecurityGroupVMMapDao; @@ -104,6 +113,7 @@ import com.cloud.utils.Ternary; import com.cloud.utils.component.Inject; import com.cloud.utils.component.Manager; import com.cloud.utils.db.Filter; +import com.cloud.utils.db.JoinBuilder; import com.cloud.utils.db.SearchBuilder; import com.cloud.utils.db.SearchCriteria; import com.cloud.utils.db.SearchCriteria.Func; @@ -175,6 +185,12 @@ public class QueryManagerImpl implements QueryService, Manager { @Inject private ProjectAccountJoinDao _projectAccountJoinDao; + @Inject + private HostJoinDao _hostJoinDao; + + @Inject + private HighAvailabilityManager _haMgr; + @Override public boolean configure(String name, Map params) throws ConfigurationException { _name = name; @@ -1309,5 +1325,118 @@ public class QueryManagerImpl implements QueryService, Manager { return _projectAccountJoinDao.searchAndCount(sc, searchFilter); } + @Override + public ListResponse searchForServers(ListHostsCmd cmd) { + //FIXME: do we need to support list hosts with VmId, maybe we should create another command just for this + // Right now it is handled separately outside this QueryService + s_logger.debug(">>>Searching for hosts>>>"); + Pair, Integer> hosts = searchForServersInternal(cmd); + ListResponse response = new ListResponse(); + s_logger.debug(">>>Generating Response>>>"); + List hostResponses = ViewResponseHelper.createHostResponse(cmd.getDetails(), hosts.first().toArray(new HostJoinVO[hosts.first().size()])); + response.setResponses(hostResponses, hosts.second()); + return response; + } + + public Pair, Integer> searchForServersInternal(ListHostsCmd cmd) { + + Long zoneId = _accountMgr.checkAccessAndSpecifyAuthority(UserContext.current().getCaller(), cmd.getZoneId()); + Object name = cmd.getHostName(); + Object type = cmd.getType(); + Object state = cmd.getState(); + Object pod = cmd.getPodId(); + Object cluster = cmd.getClusterId(); + Object id = cmd.getId(); + Object keyword = cmd.getKeyword(); + Object resourceState = cmd.getResourceState(); + Object haHosts = cmd.getHaHost(); + Long startIndex = cmd.getStartIndex(); + Long pageSize = cmd.getPageSizeVal(); + + Filter searchFilter = new Filter(HostJoinVO.class, "id", Boolean.TRUE, startIndex, pageSize); + + SearchBuilder sb = _hostJoinDao.createSearchBuilder(); + sb.select(null, Func.DISTINCT, sb.entity().getId()); // select distinct ids + sb.and("id", sb.entity().getId(), SearchCriteria.Op.EQ); + sb.and("name", sb.entity().getName(), SearchCriteria.Op.LIKE); + sb.and("type", sb.entity().getType(), SearchCriteria.Op.LIKE); + sb.and("status", sb.entity().getStatus(), SearchCriteria.Op.EQ); + sb.and("dataCenterId", sb.entity().getZoneId(), SearchCriteria.Op.EQ); + sb.and("podId", sb.entity().getPodId(), SearchCriteria.Op.EQ); + sb.and("clusterId", sb.entity().getClusterId(), SearchCriteria.Op.EQ); + sb.and("resourceState", sb.entity().getResourceState(), SearchCriteria.Op.EQ); + + String haTag = _haMgr.getHaTag(); + if (haHosts != null && haTag != null && !haTag.isEmpty()) { + if ((Boolean) haHosts) { + sb.and("tag", sb.entity().getTag(), SearchCriteria.Op.EQ); + } else { + sb.and("tag", sb.entity().getTag(), SearchCriteria.Op.NEQ); + //FIXME: should we have another condition say tag = null? + //hostTagSearch.or("tagNull", hostTagSearch.entity().getTag(), SearchCriteria.Op.NULL); + } + + } + + + SearchCriteria sc = sb.create(); + + if (keyword != null) { + SearchCriteria ssc = _hostJoinDao.createSearchCriteria(); + ssc.addOr("name", SearchCriteria.Op.LIKE, "%" + keyword + "%"); + ssc.addOr("status", SearchCriteria.Op.LIKE, "%" + keyword + "%"); + ssc.addOr("type", SearchCriteria.Op.LIKE, "%" + keyword + "%"); + + sc.addAnd("name", SearchCriteria.Op.SC, ssc); + } + + if (id != null) { + sc.setParameters("id", id); + } + + if (name != null) { + sc.setParameters("name", "%" + name + "%"); + } + if (type != null) { + sc.setParameters("type", "%" + type); + } + if (state != null) { + sc.setParameters("status", state); + } + if (zoneId != null) { + sc.setParameters("dataCenterId", zoneId); + } + if (pod != null) { + sc.setParameters("podId", pod); + } + if (cluster != null) { + sc.setParameters("clusterId", cluster); + } + + if (resourceState != null) { + sc.setParameters("resourceState", resourceState); + } + + if (haHosts != null && haTag != null && !haTag.isEmpty()) { + sc.setJoinParameters("hostTagSearch", "tag", haTag); + } + + // search host details by ids + Pair, Integer> uniqueHostPair = _hostJoinDao.searchAndCount(sc, searchFilter); + Integer count = uniqueHostPair.second(); + if ( count.intValue() == 0 ){ + // handle empty result cases + return uniqueHostPair; + } + List uniqueHosts = uniqueHostPair.first(); + Long[] hostIds = new Long[uniqueHosts.size()]; + int i = 0; + for (HostJoinVO v : uniqueHosts ){ + hostIds[i++] = v.getId(); + } + List hosts = _hostJoinDao.searchByIds(hostIds); + return new Pair, Integer>(hosts, count); + + } } diff --git a/server/src/com/cloud/api/query/ViewResponseHelper.java b/server/src/com/cloud/api/query/ViewResponseHelper.java index d2072753a15..bb6c66bebb4 100644 --- a/server/src/com/cloud/api/query/ViewResponseHelper.java +++ b/server/src/com/cloud/api/query/ViewResponseHelper.java @@ -21,9 +21,11 @@ import java.util.EnumSet; import java.util.Hashtable; import java.util.List; +import org.apache.cloudstack.api.ApiConstants.HostDetails; import org.apache.cloudstack.api.ApiConstants.VMDetails; import org.apache.cloudstack.api.response.DomainRouterResponse; import org.apache.cloudstack.api.response.EventResponse; +import org.apache.cloudstack.api.response.HostResponse; import org.apache.cloudstack.api.response.InstanceGroupResponse; import org.apache.cloudstack.api.response.ProjectAccountResponse; import org.apache.cloudstack.api.response.ProjectInvitationResponse; @@ -37,6 +39,7 @@ import org.apache.log4j.Logger; import com.cloud.api.ApiDBUtils; import com.cloud.api.query.vo.DomainRouterJoinVO; import com.cloud.api.query.vo.EventJoinVO; +import com.cloud.api.query.vo.HostJoinVO; import com.cloud.api.query.vo.InstanceGroupJoinVO; import com.cloud.api.query.vo.ProjectAccountJoinVO; import com.cloud.api.query.vo.ProjectInvitationJoinVO; @@ -193,4 +196,22 @@ public class ViewResponseHelper { } return respList; } + + public static List createHostResponse(EnumSet details, HostJoinVO... hosts) { + Hashtable vrDataList = new Hashtable(); + // Initialise the vrdatalist with the input data + for (HostJoinVO vr : hosts) { + HostResponse vrData = vrDataList.get(vr.getId()); + if ( vrData == null ){ + // first time encountering this vm + vrData = ApiDBUtils.newHostResponse(vr, details); + } + else{ + // update tags + vrData = ApiDBUtils.fillHostDetails(vrData, vr); + } + vrDataList.put(vr.getId(), vrData); + } + return new ArrayList(vrDataList.values()); + } } diff --git a/server/src/com/cloud/api/query/dao/HostJoinDao.java b/server/src/com/cloud/api/query/dao/HostJoinDao.java new file mode 100644 index 00000000000..1a2129998ed --- /dev/null +++ b/server/src/com/cloud/api/query/dao/HostJoinDao.java @@ -0,0 +1,38 @@ +// 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.EnumSet; +import java.util.List; + +import org.apache.cloudstack.api.ApiConstants.HostDetails; +import org.apache.cloudstack.api.response.HostResponse; +import com.cloud.api.query.vo.HostJoinVO; +import com.cloud.host.Host; +import com.cloud.utils.db.GenericDao; + +public interface HostJoinDao extends GenericDao { + + HostResponse newHostResponse(HostJoinVO host, EnumSet details); + + HostResponse setHostResponse(HostResponse response, HostJoinVO host); + + List newHostView(Host group); + + List searchByIds(Long... ids); + +} diff --git a/server/src/com/cloud/api/query/dao/HostJoinDaoImpl.java b/server/src/com/cloud/api/query/dao/HostJoinDaoImpl.java new file mode 100644 index 00000000000..aa09d0933a5 --- /dev/null +++ b/server/src/com/cloud/api/query/dao/HostJoinDaoImpl.java @@ -0,0 +1,222 @@ +// 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.text.DecimalFormat; +import java.util.Date; +import java.util.EnumSet; +import java.util.Iterator; +import java.util.List; +import java.util.Set; + +import javax.ejb.Local; + +import org.apache.log4j.Logger; + +import com.cloud.api.ApiDBUtils; +import com.cloud.api.query.vo.HostJoinVO; +import com.cloud.host.Host; +import com.cloud.host.HostStats; + +import org.apache.cloudstack.api.ApiConstants.HostDetails; +import org.apache.cloudstack.api.response.HostResponse; +import com.cloud.storage.StorageStats; +import com.cloud.utils.db.GenericDaoBase; +import com.cloud.utils.db.SearchBuilder; +import com.cloud.utils.db.SearchCriteria; + + +@Local(value={HostJoinDao.class}) +public class HostJoinDaoImpl extends GenericDaoBase implements HostJoinDao { + public static final Logger s_logger = Logger.getLogger(HostJoinDaoImpl.class); + + private SearchBuilder vrSearch; + + private SearchBuilder vrIdSearch; + + + protected HostJoinDaoImpl() { + + vrSearch = createSearchBuilder(); + vrSearch.and("idIN", vrSearch.entity().getId(), SearchCriteria.Op.IN); + vrSearch.done(); + + vrIdSearch = createSearchBuilder(); + vrIdSearch.and("id", vrIdSearch.entity().getId(), SearchCriteria.Op.EQ); + vrIdSearch.done(); + + this._count = "select count(distinct id) from host_view WHERE "; + } + + + + @Override + public HostResponse newHostResponse(HostJoinVO host, EnumSet details) { + HostResponse hostResponse = new HostResponse(); + hostResponse.setId(host.getUuid()); + hostResponse.setCapabilities(host.getCapabilities()); + hostResponse.setClusterId(host.getClusterUuid()); + hostResponse.setCpuNumber(host.getCpus()); + hostResponse.setZoneId(host.getUuid()); + hostResponse.setDisconnectedOn(host.getDisconnectedOn()); + hostResponse.setHypervisor(host.getHypervisorType()); + hostResponse.setHostType(host.getType()); + hostResponse.setLastPinged(new Date(host.getLastPinged())); + hostResponse.setManagementServerId(host.getManagementServerId()); + hostResponse.setName(host.getName()); + hostResponse.setPodId(host.getPodUuid()); + hostResponse.setRemoved(host.getRemoved()); + hostResponse.setCpuSpeed(host.getSpeed()); + hostResponse.setState(host.getStatus()); + hostResponse.setIpAddress(host.getPrivateIpAddress()); + hostResponse.setVersion(host.getVersion()); + hostResponse.setCreated(host.getCreated()); + + if (details.contains(HostDetails.all) || details.contains(HostDetails.capacity) + || details.contains(HostDetails.stats) || details.contains(HostDetails.events)) { + + hostResponse.setOsCategoryId(host.getOsCategoryUuid()); + hostResponse.setOsCategoryName(host.getOsCategoryName()); + hostResponse.setZoneName(host.getZoneName()); + hostResponse.setPodName(host.getPodName()); + if ( host.getClusterId() > 0) { + hostResponse.setClusterName(host.getClusterName()); + hostResponse.setClusterType(host.getClusterType().toString()); + } + } + + DecimalFormat decimalFormat = new DecimalFormat("#.##"); + if (host.getType() == Host.Type.Routing) { + if (details.contains(HostDetails.all) || details.contains(HostDetails.capacity)) { + // set allocated capacities + Long mem = host.getMemReservedCapacity() + host.getMemUsedCapacity(); + Long cpu = host.getCpuReservedCapacity() + host.getCpuReservedCapacity(); + + hostResponse.setMemoryAllocated(mem); + hostResponse.setMemoryTotal(host.getTotalMemory()); + + String hostTags = host.getTag(); + hostResponse.setHostTags(host.getTag()); + + String haTag = ApiDBUtils.getHaTag(); + if (haTag != null && !haTag.isEmpty() && hostTags != null && !hostTags.isEmpty()) { + if (haTag.equalsIgnoreCase(hostTags)) { + hostResponse.setHaHost(true); + } else { + hostResponse.setHaHost(false); + } + } else { + hostResponse.setHaHost(false); + } + + hostResponse.setHypervisorVersion(host.getHypervisorVersion()); + + String cpuAlloc = decimalFormat.format(((float) cpu / (float) (host.getCpus() * host.getSpeed())) * 100f) + "%"; + hostResponse.setCpuAllocated(cpuAlloc); + String cpuWithOverprovisioning = new Float(host.getCpus() * host.getSpeed() * ApiDBUtils.getCpuOverprovisioningFactor()).toString(); + hostResponse.setCpuWithOverprovisioning(cpuWithOverprovisioning); + } + + if (details.contains(HostDetails.all) || details.contains(HostDetails.stats)) { + // set CPU/RAM/Network stats + String cpuUsed = null; + HostStats hostStats = ApiDBUtils.getHostStatistics(host.getId()); + if (hostStats != null) { + float cpuUtil = (float) hostStats.getCpuUtilization(); + cpuUsed = decimalFormat.format(cpuUtil) + "%"; + hostResponse.setCpuUsed(cpuUsed); + hostResponse.setMemoryUsed((new Double(hostStats.getUsedMemory())).longValue()); + hostResponse.setNetworkKbsRead((new Double(hostStats.getNetworkReadKBs())).longValue()); + hostResponse.setNetworkKbsWrite((new Double(hostStats.getNetworkWriteKBs())).longValue()); + + } + } + + } else if (host.getType() == Host.Type.SecondaryStorage) { + StorageStats secStorageStats = ApiDBUtils.getSecondaryStorageStatistics(host.getId()); + if (secStorageStats != null) { + hostResponse.setDiskSizeTotal(secStorageStats.getCapacityBytes()); + hostResponse.setDiskSizeAllocated(secStorageStats.getByteUsed()); + } + } + + hostResponse.setLocalStorageActive(ApiDBUtils.isLocalStorageActiveOnHost(host.getId())); + + if (details.contains(HostDetails.all) || details.contains(HostDetails.events)) { + Set possibleEvents = host.getStatus().getPossibleEvents(); + if ((possibleEvents != null) && !possibleEvents.isEmpty()) { + String events = ""; + Iterator iter = possibleEvents.iterator(); + while (iter.hasNext()) { + com.cloud.host.Status.Event event = iter.next(); + events += event.toString(); + if (iter.hasNext()) { + events += "; "; + } + } + hostResponse.setEvents(events); + } + } + + hostResponse.setResourceState(host.getResourceState().toString()); + hostResponse.setObjectName("host"); + + return hostResponse; + } + + + + + + + @Override + public HostResponse setHostResponse(HostResponse response, HostJoinVO host) { + String tag = host.getTag(); + if (tag != null) { + if ( response.getHostTags() != null && response.getHostTags().length() > 0){ + response.setHostTags(response.getHostTags() + "," + tag); + } + else{ + response.setHostTags(tag); + } + } + return response; + } + + + + @Override + public List newHostView(Host host) { + SearchCriteria sc = vrIdSearch.create(); + sc.setParameters("id", host.getId()); + return searchIncludingRemoved(sc, null, null, false); + + } + + + + @Override + public List searchByIds(Long... ids) { + SearchCriteria sc = vrSearch.create(); + sc.setParameters("idIN", ids); + return searchIncludingRemoved(sc, null, null, false); + } + + + + +} diff --git a/server/src/com/cloud/api/query/vo/HostJoinVO.java b/server/src/com/cloud/api/query/vo/HostJoinVO.java new file mode 100644 index 00000000000..83de5f6a0db --- /dev/null +++ b/server/src/com/cloud/api/query/vo/HostJoinVO.java @@ -0,0 +1,503 @@ +// 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.Table; +import javax.persistence.Temporal; +import javax.persistence.TemporalType; + +import com.cloud.host.Status; +import com.cloud.host.Host.Type; +import com.cloud.hypervisor.Hypervisor.HypervisorType; +import com.cloud.org.Cluster; +import com.cloud.resource.ResourceState; +import com.cloud.utils.db.GenericDao; + +/** + * Host DB view. + * @author minc + * + */ +@Entity +@Table(name="host_view") +public class HostJoinVO extends BaseViewVO { + + @Column(name="id") + private long id; + + @Column(name="uuid") + private String uuid; + + @Column(name="name") + private String name; + + + @Column(name="status") + private Status status = null; + + @Column(name="type") + @Enumerated(value=EnumType.STRING) + private Type type; + + @Column(name="private_ip_address") + private String privateIpAddress; + + @Column(name="disconnected") + @Temporal(value=TemporalType.TIMESTAMP) + private Date disconnectedOn; + + @Column(name="version") + private String version; + + @Column(name="hypervisor_type") + @Enumerated(value=EnumType.STRING) + private HypervisorType hypervisorType; + + @Column(name="hypervisor_version") + private String hypervisorVersion; + + @Column(name="capabilities") + private String caps; + + @Column(name="last_ping") + private long lastPinged; + + @Column(name=GenericDao.CREATED_COLUMN) + private Date created; + + @Column(name=GenericDao.REMOVED_COLUMN) + private Date removed; + + @Column(name="resource_state") + @Enumerated(value=EnumType.STRING) + private ResourceState resourceState; + + @Column(name="mgmt_server_id") + private Long managementServerId; + + @Column(name="cpus") + private Integer cpus; + + @Column(name="speed") + private Long speed; + + @Column(name="ram") + private long totalMemory; + + @Column(name="cluster_id") + private long clusterId; + + @Column(name="cluster_uuid") + private String clusterUuid; + + @Column(name="cluster_name") + private String clusterName; + + @Column(name="cluster_type") + @Enumerated(value=EnumType.STRING) + Cluster.ClusterType clusterType; + + @Column(name="data_center_id") + private long zoneId; + + @Column(name="data_center_uuid") + private String zoneUuid; + + @Column(name="data_center_name") + private String zoneName; + + @Column(name="pod_id") + private long podId; + + @Column(name="pod_uuid") + private String podUuid; + + @Column(name="pod_name") + private String podName; + + + @Column(name="guest_os_category_id") + private long osCategoryId; + + @Column(name="guest_os_category_uuid") + private String osCategoryUuid; + + @Column(name="guest_os_category_name") + private String osCategoryName; + + @Column(name="tag") + private String tag; + + @Column(name="memory_used_capacity") + private long memUsedCapacity; + + @Column(name="memory_reserved_capacity") + private long memReservedCapacity; + + @Column(name="cpu_used_capacity") + private long cpuUsedCapacity; + + @Column(name="cpu_reserved_capacity") + private long cpuReservedCapacity; + + @Column(name="job_id") + private long jobId; + + @Column(name="job_uuid") + private String jobUuid; + + @Column(name="job_status") + private int jobStatus; + + + /* (non-Javadoc) + * @see com.cloud.api.query.vo.BaseViewVO#getId() + */ + @Override + public long getId() { + return this.id; + } + + /* (non-Javadoc) + * @see com.cloud.api.query.vo.BaseViewVO#setId(long) + */ + @Override + public void setId(long id) { + this.id = id; + } + + + public String getUuid() { + return uuid; + } + + public void setUuid(String uuid) { + this.uuid = uuid; + } + + public String getVersion() { + return version; + } + + public void setVersion(String version) { + this.version = version; + } + + public long getZoneId() { + return zoneId; + } + + public void setZoneId(long zoneId) { + this.zoneId = zoneId; + } + + public String getZoneUuid() { + return zoneUuid; + } + + public void setZoneUuid(String zoneUuid) { + this.zoneUuid = zoneUuid; + } + + public String getZoneName() { + return zoneName; + } + + public void setZoneName(String zoneName) { + this.zoneName = zoneName; + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public Status getStatus() { + return status; + } + + public void setStatus(Status status) { + this.status = status; + } + + public Type getType() { + return type; + } + + public void setType(Type type) { + this.type = type; + } + + public String getPrivateIpAddress() { + return privateIpAddress; + } + + public void setPrivateIpAddress(String privateIpAddress) { + this.privateIpAddress = privateIpAddress; + } + + public Date getDisconnectedOn() { + return disconnectedOn; + } + + public void setDisconnectedOn(Date disconnectedOn) { + this.disconnectedOn = disconnectedOn; + } + + public HypervisorType getHypervisorType() { + return hypervisorType; + } + + public void setHypervisorType(HypervisorType hypervisorType) { + this.hypervisorType = hypervisorType; + } + + public String getHypervisorVersion() { + return hypervisorVersion; + } + + public void setHypervisorVersion(String hypervisorVersion) { + this.hypervisorVersion = hypervisorVersion; + } + + public String getCapabilities() { + return caps; + } + + public void setCapabilities(String caps) { + this.caps = caps; + } + + public long getLastPinged() { + return lastPinged; + } + + public void setLastPinged(long lastPinged) { + this.lastPinged = lastPinged; + } + + 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 ResourceState getResourceState() { + return resourceState; + } + + public void setResourceState(ResourceState resourceState) { + this.resourceState = resourceState; + } + + public Long getManagementServerId() { + return managementServerId; + } + + public void setManagementServerId(Long managementServerId) { + this.managementServerId = managementServerId; + } + + public Integer getCpus() { + return cpus; + } + + public void setCpus(Integer cpus) { + this.cpus = cpus; + } + + public Long getSpeed() { + return speed; + } + + public void setSpeed(Long speed) { + this.speed = speed; + } + + public long getTotalMemory() { + return totalMemory; + } + + public void setTotalMemory(long totalMemory) { + this.totalMemory = totalMemory; + } + + public long getClusterId() { + return clusterId; + } + + public void setClusterId(long clusterId) { + this.clusterId = clusterId; + } + + public String getClusterUuid() { + return clusterUuid; + } + + public void setClusterUuid(String clusterUuid) { + this.clusterUuid = clusterUuid; + } + + public String getClusterName() { + return clusterName; + } + + public void setClusterName(String clusterName) { + this.clusterName = clusterName; + } + + public Cluster.ClusterType getClusterType() { + return clusterType; + } + + public void setClusterType(Cluster.ClusterType clusterType) { + this.clusterType = clusterType; + } + + public long getOsCategoryId() { + return osCategoryId; + } + + public void setOsCategoryId(long osCategoryId) { + this.osCategoryId = osCategoryId; + } + + public String getOsCategoryUuid() { + return osCategoryUuid; + } + + public void setOsCategoryUuid(String osCategoryUuid) { + this.osCategoryUuid = osCategoryUuid; + } + + public String getOsCategoryName() { + return osCategoryName; + } + + public void setOsCategoryName(String osCategoryName) { + this.osCategoryName = osCategoryName; + } + + public long getJobId() { + return jobId; + } + + public void setJobId(long jobId) { + this.jobId = jobId; + } + + public String getJobUuid() { + return jobUuid; + } + + public void setJobUuid(String jobUuid) { + this.jobUuid = jobUuid; + } + + public int getJobStatus() { + return jobStatus; + } + + public void setJobStatus(int jobStatus) { + this.jobStatus = jobStatus; + } + + public long getPodId() { + return podId; + } + + public void setPodId(long podId) { + this.podId = podId; + } + + public String getPodUuid() { + return podUuid; + } + + public void setPodUuid(String podUuid) { + this.podUuid = podUuid; + } + + public String getPodName() { + return podName; + } + + public void setPodName(String podName) { + this.podName = podName; + } + + public long getMemUsedCapacity() { + return memUsedCapacity; + } + + public void setMemUsedCapacity(long memUsedCapacity) { + this.memUsedCapacity = memUsedCapacity; + } + + public long getMemReservedCapacity() { + return memReservedCapacity; + } + + public void setMemReservedCapacity(long memReservedCapacity) { + this.memReservedCapacity = memReservedCapacity; + } + + public long getCpuUsedCapacity() { + return cpuUsedCapacity; + } + + public void setCpuUsedCapacity(long cpuUsedCapacity) { + this.cpuUsedCapacity = cpuUsedCapacity; + } + + public long getCpuReservedCapacity() { + return cpuReservedCapacity; + } + + public void setCpuReservedCapacity(long cpuReservedCapacity) { + this.cpuReservedCapacity = cpuReservedCapacity; + } + + public String getTag() { + return tag; + } + + public void setTag(String tag) { + this.tag = tag; + } + + +} diff --git a/server/src/com/cloud/api/response/ApiResponseSerializer.java b/server/src/com/cloud/api/response/ApiResponseSerializer.java index af37aa2807e..470cc5f9587 100644 --- a/server/src/com/cloud/api/response/ApiResponseSerializer.java +++ b/server/src/com/cloud/api/response/ApiResponseSerializer.java @@ -49,6 +49,7 @@ public class ApiResponseSerializer { private static final Logger s_logger = Logger.getLogger(ApiResponseSerializer.class.getName()); public static String toSerializedString(ResponseObject result, String responseType) { + s_logger.trace("===Serializing Response==="); if (BaseCmd.RESPONSE_TYPE_JSON.equalsIgnoreCase(responseType)) { return toJSONSerializedString(result); } else { @@ -70,7 +71,7 @@ public class ApiResponseSerializer { public static String toJSONSerializedString(ResponseObject result) { if (result != null) { Gson gson = ApiResponseGsonHelper.getBuilder().excludeFieldsWithModifiers(Modifier.TRANSIENT).create(); - + StringBuilder sb = new StringBuilder(); sb.append("{ \"").append(result.getResponseName()).append("\" : "); @@ -81,15 +82,15 @@ public class ApiResponseSerializer { if (nonZeroCount) { sb.append("{ \"").append(ApiConstants.COUNT).append("\":").append(count); } - + if ((responses != null) && !responses.isEmpty()) { - String jsonStr = gson.toJson(responses.get(0)); + String jsonStr = gson.toJson(responses.get(0)); jsonStr = unescape(jsonStr); if (nonZeroCount) { sb.append(" ,\"").append(responses.get(0).getObjectName()).append("\" : [ ").append(jsonStr); } - + for (int i = 1; i < ((ListResponse) result).getResponses().size(); i++) { jsonStr = gson.toJson(responses.get(i)); jsonStr = unescape(jsonStr); @@ -97,10 +98,10 @@ public class ApiResponseSerializer { } sb.append(" ] }"); } else { - if (!nonZeroCount){ + if (!nonZeroCount){ sb.append("{"); } - + sb.append(" }"); } } else if (result instanceof SuccessResponse) { @@ -108,7 +109,7 @@ public class ApiResponseSerializer { } else if (result instanceof ExceptionResponse) { String jsonErrorText = gson.toJson((ExceptionResponse) result); jsonErrorText = unescape(jsonErrorText); - sb.append(jsonErrorText); + sb.append(jsonErrorText); } else { String jsonStr = gson.toJson(result); if ((jsonStr != null) && !"".equals(jsonStr)) { @@ -178,7 +179,7 @@ public class ApiResponseSerializer { } return fields.toArray(new Field[] {}); } - + private static void serializeResponseObjFieldsXML(StringBuilder sb, ResponseObject obj) { boolean isAsync = false; if (obj instanceof AsyncJobResponse) @@ -227,26 +228,26 @@ public class ApiResponseSerializer { serializeResponseObjXML(sb, subObj); } else if (value instanceof IdentityProxy) { // Only exception reponses carry a list of IdentityProxy objects. - IdentityProxy idProxy = (IdentityProxy)value; + IdentityProxy idProxy = (IdentityProxy)value; String id = (idProxy.getValue() != null ? String.valueOf(idProxy.getValue()) : ""); if(!id.isEmpty()) { IdentityDao identityDao = new IdentityDaoImpl(); id = identityDao.getIdentityUuid(idProxy.getTableName(), id); - } + } if(id != null && !id.isEmpty()) { // If this is the first IdentityProxy field encountered, put in a uuidList tag. if (!usedUuidList) { sb.append("<").append(serializedName.value()).append(">"); usedUuidList = true; } - sb.append("").append(id).append(""); + sb.append("").append(id).append(""); } // Append the new idFieldName property also. String idFieldName = idProxy.getidFieldName(); if (idFieldName != null) { - sb.append("").append(idFieldName).append(""); + sb.append("").append(idFieldName).append(""); } - } + } } if (usedUuidList) { // close the uuidList. @@ -254,8 +255,8 @@ public class ApiResponseSerializer { } } else if (fieldValue instanceof Date) { sb.append("<").append(serializedName.value()).append(">").append(BaseCmd.getDateString((Date) fieldValue)). - append(""); - } else if (fieldValue instanceof IdentityProxy) { + append(""); + } else if (fieldValue instanceof IdentityProxy) { IdentityProxy idProxy = (IdentityProxy)fieldValue; String id = (idProxy.getValue() != null ? String.valueOf(idProxy.getValue()) : ""); if(!id.isEmpty()) { @@ -273,7 +274,7 @@ public class ApiResponseSerializer { if (!(obj instanceof ExceptionResponse)) { resultString = encodeParam(resultString); } - + sb.append("<").append(serializedName.value()).append(">").append(resultString).append(""); } } @@ -340,10 +341,10 @@ public class ApiResponseSerializer { resultString.append(singleChar); } } - + return resultString.toString(); } - + private static String encodeParam(String value) { if (!ApiServer.encodeApiResponse) { return value; @@ -355,5 +356,5 @@ public class ApiResponseSerializer { } return value; } - + } diff --git a/server/src/com/cloud/configuration/DefaultComponentLibrary.java b/server/src/com/cloud/configuration/DefaultComponentLibrary.java index d41bda67324..e1616c000b4 100755 --- a/server/src/com/cloud/configuration/DefaultComponentLibrary.java +++ b/server/src/com/cloud/configuration/DefaultComponentLibrary.java @@ -33,6 +33,7 @@ import com.cloud.api.query.dao.ProjectJoinDaoImpl; import com.cloud.api.query.dao.ResourceTagJoinDaoImpl; import com.cloud.api.query.dao.SecurityGroupJoinDaoImpl; import com.cloud.api.query.dao.UserVmJoinDaoImpl; +import com.cloud.api.query.dao.HostJoinDaoImpl; import com.cloud.async.AsyncJobExecutorContextImpl; import com.cloud.async.AsyncJobManagerImpl; import com.cloud.async.SyncQueueManagerImpl; @@ -236,6 +237,7 @@ public class DefaultComponentLibrary extends ComponentLibraryBase implements Com addDao("ProjectJoinDao", ProjectJoinDaoImpl.class); addDao("ProjectAccountJoinDao", ProjectAccountJoinDaoImpl.class); addDao("ProjectInvitationJoinDao", ProjectInvitationJoinDaoImpl.class); + addDao("HostJoinDao", HostJoinDaoImpl.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/resource/ResourceManagerImpl.java b/server/src/com/cloud/resource/ResourceManagerImpl.java index 59873479eb1..cfdb8becdcd 100755 --- a/server/src/com/cloud/resource/ResourceManagerImpl.java +++ b/server/src/com/cloud/resource/ResourceManagerImpl.java @@ -181,22 +181,22 @@ public class ResourceManagerImpl implements ResourceManager, ResourceService, Ma @Inject protected ConfigurationDao _configDao; @Inject - protected HostTagsDao _hostTagsDao; + protected HostTagsDao _hostTagsDao; @Inject protected GuestOSCategoryDao _guestOSCategoryDao; - @Inject + @Inject protected StoragePoolDao _storagePoolDao; @Inject protected DataCenterIpAddressDao _privateIPAddressDao; @Inject protected IPAddressDao _publicIPAddressDao; @Inject - protected VirtualMachineManager _vmMgr; + protected VirtualMachineManager _vmMgr; @Inject - protected VMInstanceDao _vmDao; + protected VMInstanceDao _vmDao; @Inject protected HighAvailabilityManager _haMgr; - @Inject + @Inject protected StorageService _storageSvr; @Inject(adapter = Discoverer.class) protected Adapters _discoverers; @@ -581,7 +581,7 @@ public class ResourceManagerImpl implements ResourceManager, ResourceService, Ma if (pod == null) { throw new InvalidParameterValueException("Can't find pod by id " + podId); } - // check if pod belongs to the zone + // check if pod belongs to the zone if (!Long.valueOf(pod.getDataCenterId()).equals(dcId)) { InvalidParameterValueException ex = new InvalidParameterValueException("Pod with specified podId" + podId + " doesn't belong to the zone with specified zoneId" + dcId); ex.addProxyObject(pod, podId, "podId"); @@ -643,7 +643,7 @@ public class ResourceManagerImpl implements ResourceManager, ResourceService, Ma CloudRuntimeException ex = new CloudRuntimeException("Unable to create cluster " + clusterName + " in pod with specified podId and data center with specified dcID", e); ex.addProxyObject(pod, podId, "podId"); ex.addProxyObject(zone, dcId, "dcId"); - throw ex; + throw ex; } } clusterId = cluster.getId(); @@ -744,7 +744,7 @@ public class ResourceManagerImpl implements ResourceManager, ResourceService, Ma // Verify that host exists HostVO host = _hostDao.findById(hostId); if (host == null) { - throw new InvalidParameterValueException("Host with id " + hostId + " doesn't exist"); + throw new InvalidParameterValueException("Host with id " + hostId + " doesn't exist"); } _accountMgr.checkAccessAndSpecifyAuthority(UserContext.current().getCaller(), host.getDataCenterId()); @@ -752,7 +752,7 @@ public class ResourceManagerImpl implements ResourceManager, ResourceService, Ma * TODO: check current agent status and updateAgentStatus to removed. If it was already removed, that means * someone is deleting host concurrently, return. And consider the situation of CloudStack shutdown during delete. * A global lock? - * + * */ AgentAttache attache = _agentMgr.findAttache(hostId); // Get storage pool host mappings here because they can be removed as a part of handleDisconnect later @@ -847,7 +847,7 @@ public class ResourceManagerImpl implements ResourceManager, ResourceService, Ma @DB public boolean deleteCluster(DeleteClusterCmd cmd) { Transaction txn = Transaction.currentTxn(); - try { + try { txn.start(); ClusterVO cluster = _clusterDao.lockRow(cmd.getId(), true); if (cluster == null) { @@ -973,7 +973,7 @@ public class ResourceManagerImpl implements ResourceManager, ResourceService, Ma try { txn.start(); _clusterDao.update(cluster.getId(), cluster); - txn.commit(); + txn.commit(); } catch (Exception e) { s_logger.error("Unable to update cluster due to " + e.getMessage(), e); throw new CloudRuntimeException("Failed to update cluster. Please contact Cloud Support."); @@ -989,12 +989,12 @@ public class ResourceManagerImpl implements ResourceManager, ResourceService, Ma cluster.setManagedState(Managed.ManagedState.PrepareUnmanaged); _clusterDao.update(cluster.getId(), cluster); txn.commit(); - List hosts = listAllUpAndEnabledHosts(Host.Type.Routing, cluster.getId(), cluster.getPodId(), cluster.getDataCenterId()); + List hosts = listAllUpAndEnabledHosts(Host.Type.Routing, cluster.getId(), cluster.getPodId(), cluster.getDataCenterId()); for( HostVO host : hosts ) { - if(host.getType().equals(Host.Type.Routing) && !host.getStatus().equals(Status.Down) && !host.getStatus().equals(Status.Disconnected) + if(host.getType().equals(Host.Type.Routing) && !host.getStatus().equals(Status.Down) && !host.getStatus().equals(Status.Disconnected) && !host.getStatus().equals(Status.Up) && !host.getStatus().equals(Status.Alert) ) { String msg = "host " + host.getPrivateIpAddress() + " should not be in " + host.getStatus().toString() + " status"; - throw new CloudRuntimeException("PrepareUnmanaged Failed due to " + msg); + throw new CloudRuntimeException("PrepareUnmanaged Failed due to " + msg); } } @@ -1011,9 +1011,9 @@ public class ResourceManagerImpl implements ResourceManager, ResourceService, Ma Thread.sleep(5 * 1000); } catch (Exception e) { } - hosts = listAllUpAndEnabledHosts(Host.Type.Routing, cluster.getId(), cluster.getPodId(), cluster.getDataCenterId()); + hosts = listAllUpAndEnabledHosts(Host.Type.Routing, cluster.getId(), cluster.getPodId(), cluster.getDataCenterId()); for( HostVO host : hosts ) { - if ( !host.getStatus().equals(Status.Down) && !host.getStatus().equals(Status.Disconnected) + if ( !host.getStatus().equals(Status.Down) && !host.getStatus().equals(Status.Disconnected) && !host.getStatus().equals(Status.Alert)) { lsuccess = false; break; @@ -1025,7 +1025,7 @@ public class ResourceManagerImpl implements ResourceManager, ResourceService, Ma } } if ( success == false ) { - throw new CloudRuntimeException("PrepareUnmanaged Failed due to some hosts are still in UP status after 5 Minutes, please try later "); + throw new CloudRuntimeException("PrepareUnmanaged Failed due to some hosts are still in UP status after 5 Minutes, please try later "); } } finally { txn.start(); @@ -1033,7 +1033,7 @@ public class ResourceManagerImpl implements ResourceManager, ResourceService, Ma _clusterDao.update(cluster.getId(), cluster); txn.commit(); } - } else if( newManagedState.equals(Managed.ManagedState.Managed)) { + } else if( newManagedState.equals(Managed.ManagedState.Managed)) { txn.start(); cluster.setManagedState(Managed.ManagedState.Managed); _clusterDao.update(cluster.getId(), cluster); @@ -1159,7 +1159,7 @@ public class ResourceManagerImpl implements ResourceManager, ResourceService, Ma throw new InvalidParameterValueException("There are other servers in PrepareForMaintenance OR ErrorInMaintenance STATUS in cluster " + host.getClusterId()); } - if (_storageMgr.isLocalStorageActiveOnHost(host)) { + if (_storageMgr.isLocalStorageActiveOnHost(host.getId())) { throw new InvalidParameterValueException("There are active VMs using the host's local storage pool. Please stop all VMs on this host that use local storage."); } @@ -1353,7 +1353,7 @@ public class ResourceManagerImpl implements ResourceManager, ResourceService, Ma public void unregisterResourceStateAdapter(String name) { synchronized (_resourceStateAdapters) { _resourceStateAdapters.remove(name); - } + } } private Object dispatchToStateAdapters(ResourceStateAdapter.Event event, boolean singleTaker, Object... args) { @@ -1605,7 +1605,7 @@ public class ResourceManagerImpl implements ResourceManager, ResourceService, Ma } } } - + if (s_logger.isDebugEnabled()) { new Request(-1l, -1l, cmds, true, false).logD("Startup request from directly connected host: ", true); } @@ -1646,7 +1646,7 @@ public class ResourceManagerImpl implements ResourceManager, ResourceService, Ma } } } - + if (tempHost != null) { /* Change agent status to Alert */ _agentMgr.agentStatusTransitTo(tempHost, Status.Event.AgentDisconnected, _nodeId); @@ -1754,7 +1754,7 @@ public class ResourceManagerImpl implements ResourceManager, ResourceService, Ma host.setCpus(ssCmd.getCpus()); host.setTotalMemory(ssCmd.getMemory()); host.setSpeed(ssCmd.getSpeed()); - host.setHypervisorType(hyType); + host.setHypervisorType(hyType); return host; } diff --git a/server/src/com/cloud/server/ManagementServerImpl.java b/server/src/com/cloud/server/ManagementServerImpl.java index 8c73bad98a6..79a325c8957 100755 --- a/server/src/com/cloud/server/ManagementServerImpl.java +++ b/server/src/com/cloud/server/ManagementServerImpl.java @@ -924,23 +924,6 @@ public class ManagementServerImpl implements ManagementServer { return new Pair, Integer>(result.first(), result.second()); } - @Override - public List searchForServers(ListHostsCmd cmd) { - - Long zoneId = _accountMgr.checkAccessAndSpecifyAuthority(UserContext.current().getCaller(), cmd.getZoneId()); - Object name = cmd.getHostName(); - Object type = cmd.getType(); - Object state = cmd.getState(); - Object pod = cmd.getPodId(); - Object cluster = cmd.getClusterId(); - Object id = cmd.getId(); - Object keyword = cmd.getKeyword(); - Object resourceState = cmd.getResourceState(); - Object haHosts = cmd.getHaHost(); - - return searchForServers(cmd.getStartIndex(), cmd.getPageSizeVal(), name, type, state, zoneId, pod, cluster, id, keyword, resourceState, - haHosts); - } @Override public Pair, List> listHostsForMigrationOfVM(Long vmId, Long startIndex, Long pageSize) { diff --git a/server/src/com/cloud/storage/StorageManager.java b/server/src/com/cloud/storage/StorageManager.java index ce00cbf4e81..97853ac76de 100755 --- a/server/src/com/cloud/storage/StorageManager.java +++ b/server/src/com/cloud/storage/StorageManager.java @@ -53,28 +53,28 @@ public interface StorageManager extends StorageService, Manager { * @return absolute ISO path */ public Pair getAbsoluteIsoPath(long templateId, long dataCenterId); - + /** * Returns the URL of the secondary storage host * @param zoneId * @return URL */ public String getSecondaryStorageURL(long zoneId); - + /** * Returns a comma separated list of tags for the specified storage pool * @param poolId * @return comma separated list of tags */ public String getStoragePoolTags(long poolId); - + /** * Returns the secondary storage host * @param zoneId * @return secondary storage host */ public HostVO getSecondaryStorageHost(long zoneId); - + /** * Returns the secondary storage host * @param zoneId @@ -89,7 +89,7 @@ public interface StorageManager extends StorageService, Manager { * @param destPoolPodId * @param destPoolClusterId * @return VolumeVO - * @throws ConcurrentOperationException + * @throws ConcurrentOperationException */ VolumeVO moveVolume(VolumeVO volume, long destPoolDcId, Long destPoolPodId, Long destPoolClusterId, HypervisorType dataDiskHyperType) throws ConcurrentOperationException; @@ -114,10 +114,10 @@ public interface StorageManager extends StorageService, Manager { /** * Marks the specified volume as destroyed in the management server database. The expunge thread will delete the volume from its storage pool. * @param volume - * @return + * @return */ boolean destroyVolume(VolumeVO volume) throws ConcurrentOperationException; - + /** Create capacity entries in the op capacity table * @param storagePool */ @@ -136,7 +136,7 @@ public interface StorageManager extends StorageService, Manager { Answer[] sendToPool(StoragePool pool, Commands cmds) throws StorageUnavailableException; Pair sendToPool(StoragePool pool, long[] hostIdsToTryFirst, List hostIdsToAvoid, Commands cmds) throws StorageUnavailableException; Pair sendToPool(StoragePool pool, long[] hostIdsToTryFirst, List hostIdsToAvoid, Command cmd) throws StorageUnavailableException; - + /** * Checks that one of the following is true: * 1. The volume is not attached to any VM @@ -145,21 +145,21 @@ public interface StorageManager extends StorageService, Manager { * @return true if one of the above conditions is true */ boolean volumeInactive(VolumeVO volume); - + String getVmNameOnVolume(VolumeVO volume); - + /** * Checks if a host has running VMs that are using its local storage pool. * @return true if local storage is active on the host */ - boolean isLocalStorageActiveOnHost(Host host); - + boolean isLocalStorageActiveOnHost(Long hostId); + /** * Cleans up storage pools by removing unused templates. * @param recurring - true if this cleanup is part of a recurring garbage collection thread */ void cleanupStorage(boolean recurring); - + String getPrimaryStorageNameLabel(VolumeVO volume); /** @@ -176,16 +176,16 @@ public interface StorageManager extends StorageService, Manager { */ DiskProfile allocateRawVolume(Type type, String name, DiskOfferingVO offering, Long size, T vm, Account owner); DiskProfile allocateTemplatedVolume(Type type, String name, DiskOfferingVO offering, VMTemplateVO template, T vm, Account owner); - + void createCapacityEntry(StoragePoolVO storagePool, short capacityType, long allocated); - + void prepare(VirtualMachineProfile vm, DeployDestination dest) throws StorageUnavailableException, InsufficientStorageCapacityException, ConcurrentOperationException; void release(VirtualMachineProfile profile); void cleanupVolumes(long vmId) throws ConcurrentOperationException; - + void prepareForMigration(VirtualMachineProfile vm, DeployDestination dest); Answer sendToPool(StoragePool pool, long[] hostIdsToTryFirst, Command cmd) throws StorageUnavailableException; @@ -217,7 +217,7 @@ public interface StorageManager extends StorageService, Manager { boolean stateTransitTo(Volume vol, Event event) throws NoTransitionException; - + VolumeVO allocateDuplicateVolume(VolumeVO oldVol, Long templateId); Host updateSecondaryStorage(long secStorageId, String newUrl); @@ -237,6 +237,6 @@ public interface StorageManager extends StorageService, Manager { HypervisorType getHypervisorTypeFromFormat(ImageFormat format); boolean storagePoolHasEnoughSpace(List volume, StoragePool pool); - + boolean deleteVolume(long volumeId, Account caller) throws ConcurrentOperationException; } diff --git a/server/src/com/cloud/storage/StorageManagerImpl.java b/server/src/com/cloud/storage/StorageManagerImpl.java index 1f625d3f69b..824af6a744c 100755 --- a/server/src/com/cloud/storage/StorageManagerImpl.java +++ b/server/src/com/cloud/storage/StorageManagerImpl.java @@ -431,8 +431,8 @@ public class StorageManagerImpl implements StorageManager, Manager, ClusterManag } @Override - public boolean isLocalStorageActiveOnHost(Host host) { - List storagePoolHostRefs = _storagePoolHostDao.listByHostId(host.getId()); + public boolean isLocalStorageActiveOnHost(Long hostId) { + List storagePoolHostRefs = _storagePoolHostDao.listByHostId(hostId); for (StoragePoolHostVO storagePoolHostRef : storagePoolHostRefs) { StoragePoolVO storagePool = _storagePoolDao.findById(storagePoolHostRef.getPoolId()); if (storagePool.getPoolType() == StoragePoolType.LVM || storagePool.getPoolType() == StoragePoolType.EXT) { @@ -652,7 +652,7 @@ public class StorageManagerImpl implements StorageManager, Manager, ClusterManag Pair volumeDetails = createVolumeFromSnapshot(volume, snapshot); if (volumeDetails != null) { createdVolume = volumeDetails.first(); - UsageEventVO usageEvent = new UsageEventVO(EventTypes.EVENT_VOLUME_CREATE, createdVolume.getAccountId(), createdVolume.getDataCenterId(), createdVolume.getId(), createdVolume.getName(), + UsageEventVO usageEvent = new UsageEventVO(EventTypes.EVENT_VOLUME_CREATE, createdVolume.getAccountId(), createdVolume.getDataCenterId(), createdVolume.getId(), createdVolume.getName(), createdVolume.getDiskOfferingId(), null, createdVolume.getSize()); _usageEventDao.persist(usageEvent); } @@ -737,21 +737,21 @@ public class StorageManagerImpl implements StorageManager, Manager, ClusterManag @DB public VolumeVO copyVolumeFromSecToPrimary(VolumeVO volume, VMInstanceVO vm, VMTemplateVO template, DataCenterVO dc, HostPodVO pod, Long clusterId, ServiceOfferingVO offering, DiskOfferingVO diskOffering, List avoids, long size, HypervisorType hyperType) throws NoTransitionException { - + final HashSet avoidPools = new HashSet(avoids); DiskProfile dskCh = createDiskCharacteristics(volume, template, dc, diskOffering); dskCh.setHyperType(vm.getHypervisorType()); - // Find a suitable storage to create volume on + // Find a suitable storage to create volume on StoragePoolVO destPool = findStoragePool(dskCh, dc, pod, clusterId, null, vm, avoidPools); - - // Copy the volume from secondary storage to the destination storage pool + + // Copy the volume from secondary storage to the destination storage pool stateTransitTo(volume, Event.CopyRequested); VolumeHostVO volumeHostVO = _volumeHostDao.findByVolumeId(volume.getId()); HostVO secStorage = _hostDao.findById(volumeHostVO.getHostId()); String secondaryStorageURL = secStorage.getStorageUrl(); String[] volumePath = volumeHostVO.getInstallPath().split("/"); String volumeUUID = volumePath[volumePath.length - 1].split("\\.")[0]; - + CopyVolumeCommand cvCmd = new CopyVolumeCommand(volume.getId(), volumeUUID, destPool, secondaryStorageURL, false, _copyvolumewait); CopyVolumeAnswer cvAnswer; try { @@ -764,23 +764,23 @@ public class StorageManagerImpl implements StorageManager, Manager, ClusterManag if (cvAnswer == null || !cvAnswer.getResult()) { stateTransitTo(volume, Event.CopyFailed); throw new CloudRuntimeException("Failed to copy the volume from secondary storage to the destination primary storage pool."); - } + } Transaction txn = Transaction.currentTxn(); - txn.start(); + txn.start(); volume.setPath(cvAnswer.getVolumePath()); volume.setFolder(destPool.getPath()); volume.setPodId(destPool.getPodId()); - volume.setPoolId(destPool.getId()); + volume.setPoolId(destPool.getId()); volume.setPodId(destPool.getPodId()); - stateTransitTo(volume, Event.CopySucceeded); + stateTransitTo(volume, Event.CopySucceeded); UsageEventVO usageEvent = new UsageEventVO(EventTypes.EVENT_VOLUME_CREATE, volume.getAccountId(), volume.getDataCenterId(), volume.getId(), volume.getName(), volume.getDiskOfferingId(), null, volume.getSize()); _usageEventDao.persist(usageEvent); _volumeHostDao.remove(volumeHostVO.getId()); txn.commit(); return volume; - + } - + @Override @DB public VolumeVO createVolume(VolumeVO volume, VMInstanceVO vm, VMTemplateVO template, DataCenterVO dc, HostPodVO pod, Long clusterId, ServiceOfferingVO offering, DiskOfferingVO diskOffering, @@ -975,7 +975,7 @@ public class StorageManagerImpl implements StorageManager, Manager, ClusterManag value = configDao.getValue(Config.RecreateSystemVmEnabled.key()); _recreateSystemVmEnabled = Boolean.parseBoolean(value); - + value = configDao.getValue(Config.StorageTemplateCleanupEnabled.key()); _templateCleanupEnabled = (value == null ? true : Boolean.parseBoolean(value)); @@ -1517,7 +1517,7 @@ public class StorageManagerImpl implements StorageManager, Manager, ClusterManag } if(sPool.getStatus() != StoragePoolStatus.Maintenance){ s_logger.warn("Unable to delete storage id: " + id +" due to it is not in Maintenance state"); - throw new InvalidParameterValueException("Unable to delete storage due to it is not in Maintenance state, id: " + id); + throw new InvalidParameterValueException("Unable to delete storage due to it is not in Maintenance state, id: " + id); } if (sPool.getPoolType().equals(StoragePoolType.LVM) || sPool.getPoolType().equals(StoragePoolType.EXT)) { s_logger.warn("Unable to delete local storage id:" + id); @@ -1546,7 +1546,7 @@ public class StorageManagerImpl implements StorageManager, Manager, ClusterManag " for this pool"); } } - + // First get the host_id from storage_pool_host_ref for given pool id StoragePoolVO lock = _storagePoolDao.acquireInLockTable(sPool.getId()); @@ -1740,10 +1740,10 @@ public class StorageManagerImpl implements StorageManager, Manager, ClusterManag return _volsDao.findById(volume.getId()); } - + /* * Upload the volume to secondary storage. - * + * */ @Override @DB @@ -1755,13 +1755,13 @@ public class StorageManagerImpl implements StorageManager, Manager, ClusterManag String volumeName = cmd.getVolumeName(); String url = cmd.getUrl(); String format = cmd.getFormat(); - + validateVolume(caller, ownerId, zoneId, volumeName, url, format); VolumeVO volume = persistVolume(caller, ownerId, zoneId, volumeName, url, cmd.getFormat()); _downloadMonitor.downloadVolumeToStorage(volume, zoneId, url, cmd.getChecksum(), ImageFormat.valueOf(format.toUpperCase())); - return volume; + return volume; } - + private boolean validateVolume(Account caller, long ownerId, Long zoneId, String volumeName, String url, String format) throws ResourceAllocationException{ // permission check @@ -1769,7 +1769,7 @@ public class StorageManagerImpl implements StorageManager, Manager, ClusterManag // Check that the resource limit for volumes won't be exceeded _resourceLimitMgr.checkResourceLimit(_accountMgr.getAccount(ownerId), ResourceType.volume); - + // Verify that zone exists DataCenterVO zone = _dcDao.findById(zoneId); @@ -1781,22 +1781,22 @@ public class StorageManagerImpl implements StorageManager, Manager, ClusterManag if (Grouping.AllocationState.Disabled == zone.getAllocationState() && !_accountMgr.isRootAdmin(caller.getType())) { throw new PermissionDeniedException("Cannot perform this operation, Zone is currently disabled: " + zoneId); } - + if (url.toLowerCase().contains("file://")) { throw new InvalidParameterValueException("File:// type urls are currently unsupported"); } - + ImageFormat imgfmt = ImageFormat.valueOf(format.toUpperCase()); if (imgfmt == null) { throw new IllegalArgumentException("Image format is incorrect " + format + ". Supported formats are " + EnumUtils.listValues(ImageFormat.values())); } - + String userSpecifiedName = volumeName; if (userSpecifiedName == null) { userSpecifiedName = getRandomVolumeName(); } if((!url.toLowerCase().endsWith("vhd"))&&(!url.toLowerCase().endsWith("vhd.zip")) - &&(!url.toLowerCase().endsWith("vhd.bz2"))&&(!url.toLowerCase().endsWith("vhd.gz")) + &&(!url.toLowerCase().endsWith("vhd.bz2"))&&(!url.toLowerCase().endsWith("vhd.gz")) &&(!url.toLowerCase().endsWith("qcow2"))&&(!url.toLowerCase().endsWith("qcow2.zip")) &&(!url.toLowerCase().endsWith("qcow2.bz2"))&&(!url.toLowerCase().endsWith("qcow2.gz")) &&(!url.toLowerCase().endsWith("ova"))&&(!url.toLowerCase().endsWith("ova.zip")) @@ -1804,7 +1804,7 @@ public class StorageManagerImpl implements StorageManager, Manager, ClusterManag &&(!url.toLowerCase().endsWith("img"))&&(!url.toLowerCase().endsWith("raw"))){ throw new InvalidParameterValueException("Please specify a valid " + format.toLowerCase()); } - + if ((format.equalsIgnoreCase("vhd") && (!url.toLowerCase().endsWith(".vhd") && !url.toLowerCase().endsWith("vhd.zip") && !url.toLowerCase().endsWith("vhd.bz2") && !url.toLowerCase().endsWith("vhd.gz") )) || (format.equalsIgnoreCase("qcow2") && (!url.toLowerCase().endsWith(".qcow2") && !url.toLowerCase().endsWith("qcow2.zip") && !url.toLowerCase().endsWith("qcow2.bz2") && !url.toLowerCase().endsWith("qcow2.gz") )) || (format.equalsIgnoreCase("ova") && (!url.toLowerCase().endsWith(".ova") && !url.toLowerCase().endsWith("ova.zip") && !url.toLowerCase().endsWith("ova.bz2") && !url.toLowerCase().endsWith("ova.gz"))) @@ -1812,14 +1812,14 @@ public class StorageManagerImpl implements StorageManager, Manager, ClusterManag throw new InvalidParameterValueException("Please specify a valid URL. URL:" + url + " is an invalid for the format " + format.toLowerCase()); } validateUrl(url); - + return false; } - + private String validateUrl(String url){ try { URI uri = new URI(url); - if ((uri.getScheme() == null) || (!uri.getScheme().equalsIgnoreCase("http") + if ((uri.getScheme() == null) || (!uri.getScheme().equalsIgnoreCase("http") && !uri.getScheme().equalsIgnoreCase("https") && !uri.getScheme().equalsIgnoreCase("file"))) { throw new IllegalArgumentException("Unsupported scheme for url: " + url); } @@ -1840,16 +1840,16 @@ public class StorageManagerImpl implements StorageManager, Manager, ClusterManag } catch (UnknownHostException uhe) { throw new IllegalArgumentException("Unable to resolve " + host); } - + return uri.toString(); } catch (URISyntaxException e) { throw new IllegalArgumentException("Invalid URL " + url); } - + } - + private VolumeVO persistVolume(Account caller, long ownerId, Long zoneId, String volumeName, String url, String format) { - + Transaction txn = Transaction.currentTxn(); txn.start(); @@ -1860,7 +1860,7 @@ public class StorageManagerImpl implements StorageManager, Manager, ClusterManag volume.setAccountId(ownerId); volume.setDomainId(((caller == null) ? Domain.ROOT_DOMAIN : caller.getDomainId())); long diskOfferingId = _diskOfferingDao.findByUniqueName("Cloud.com-Custom").getId(); - volume.setDiskOfferingId(diskOfferingId); + volume.setDiskOfferingId(diskOfferingId); //volume.setSize(size); volume.setInstanceId(null); volume.setUpdated(new Date()); @@ -1881,8 +1881,8 @@ public class StorageManagerImpl implements StorageManager, Manager, ClusterManag txn.commit(); return volume; } - - + + /* * Just allocate a volume in the database, don't send the createvolume cmd to hypervisor. The volume will be finally * created @@ -1984,7 +1984,7 @@ public class StorageManagerImpl implements StorageManager, Manager, ClusterManag * throw new UnsupportedServiceException("operation not supported, snapshot with id " + snapshotId + * " is created from ROOT volume"); * } - * + * */ } @@ -2189,7 +2189,7 @@ public class StorageManagerImpl implements StorageManager, Manager, ClusterManag s_logger.debug("Successfully set Capacity - " + totalOverProvCapacity + " for capacity type - " + capacityType + " , DataCenterId - " + storagePool.getDataCenterId() + ", HostOrPoolId - " + storagePool.getId() + ", PodId " + storagePool.getPodId()); } - + @Override public List getUpHostsInPool(long poolId) { SearchCriteria sc = UpHostsInPoolSearch.create(); @@ -2290,7 +2290,7 @@ public class StorageManagerImpl implements StorageManager, Manager, ClusterManag s_logger.warn("Unable to destroy " + vol.getId(), e); } } - + // remove snapshots in Error state List snapshots = _snapshotDao.listAllByStatus(Snapshot.Status.Error); for (SnapshotVO snapshotVO : snapshots) { @@ -2300,7 +2300,7 @@ public class StorageManagerImpl implements StorageManager, Manager, ClusterManag s_logger.warn("Unable to destroy " + snapshotVO.getId(), e); } } - + } finally { scanLock.unlock(); } @@ -2439,7 +2439,7 @@ public class StorageManagerImpl implements StorageManager, Manager, ClusterManag s_logger.warn("problem cleaning up snapshots in secondary storage " + secondaryStorageHost, e2); } } - + //CleanUp volumes on Secondary Storage. for (HostVO secondaryStorageHost : secondaryStorageHosts) { try { @@ -2467,7 +2467,7 @@ public class StorageManagerImpl implements StorageManager, Manager, ClusterManag _volumeHostDao.remove(destroyedVolumeHostVO.getId()); } } - + }catch (Exception e2) { s_logger.warn("problem cleaning up volumes in secondary storage " + secondaryStorageHost, e2); } @@ -2899,14 +2899,14 @@ public class StorageManagerImpl implements StorageManager, Manager, ClusterManag throw new InvalidParameterValueException("Please specify a volume that is not attached to any VM."); } - // Check that volume is completely Uploaded + // Check that volume is completely Uploaded if (volume.getState() == Volume.State.UploadOp){ VolumeHostVO volumeHost = _volumeHostDao.findByVolumeId(volume.getId()); if (volumeHost.getDownloadState() == VMTemplateStorageResourceAssoc.Status.DOWNLOAD_IN_PROGRESS){ throw new InvalidParameterValueException("Please specify a volume that is not uploading"); - } + } } - + // Check that the volume is not already destroyed if (volume.getState() != Volume.State.Destroy) { if (!destroyVolume(volume)) { @@ -3258,7 +3258,7 @@ public class StorageManagerImpl implements StorageManager, Manager, ClusterManag if (s_logger.isDebugEnabled()) { s_logger.debug("Checking if we need to prepare " + vols.size() + " volumes for " + vm); } - + boolean recreate = _recreateSystemVmEnabled; List recreateVols = new ArrayList(vols.size()); @@ -3270,7 +3270,7 @@ public class StorageManagerImpl implements StorageManager, Manager, ClusterManag } if (assignedPool == null && recreate) { assignedPool = _storagePoolDao.findById(vol.getPoolId()); - + } if (assignedPool != null || recreate) { Volume.State state = vol.getState(); @@ -3311,7 +3311,7 @@ public class StorageManagerImpl implements StorageManager, Manager, ClusterManag StoragePoolVO pool = _storagePoolDao.findById(vol.getPoolId()); vm.addDisk(new VolumeTO(vol, pool)); } - + } } } else { @@ -3333,7 +3333,7 @@ public class StorageManagerImpl implements StorageManager, Manager, ClusterManag existingPool = _storagePoolDao.findById(vol.getPoolId()); s_logger.debug("existing pool: " + existingPool.getId()); } - + if (vol.getState() == Volume.State.Allocated || vol.getState() == Volume.State.Creating) { newVol = vol; } else { @@ -3422,7 +3422,7 @@ public class StorageManagerImpl implements StorageManager, Manager, ClusterManag if (toBeCreated.getTemplateId() != null) { template = _templateDao.findById(toBeCreated.getTemplateId()); } - + StoragePool pool = null; if (sPool != null) { pool = sPool; @@ -3506,27 +3506,27 @@ public class StorageManagerImpl implements StorageManager, Manager, ClusterManag if (s_logger.isDebugEnabled()) { s_logger.debug("Expunging " + vol); } - + //Find out if the volume is present on secondary storage VolumeHostVO volumeHost = _volumeHostDao.findByVolumeId(vol.getId()); if(volumeHost != null){ if (volumeHost.getDownloadState() == VMTemplateStorageResourceAssoc.Status.DOWNLOADED){ HostVO ssHost = _hostDao.findById(volumeHost.getHostId()); - DeleteVolumeCommand dtCommand = new DeleteVolumeCommand(ssHost.getStorageUrl(), volumeHost.getInstallPath()); + DeleteVolumeCommand dtCommand = new DeleteVolumeCommand(ssHost.getStorageUrl(), volumeHost.getInstallPath()); Answer answer = _agentMgr.sendToSecStorage(ssHost, dtCommand); if (answer == null || !answer.getResult()) { s_logger.debug("Failed to delete " + volumeHost + " due to " + ((answer == null) ? "answer is null" : answer.getDetails())); return; } - }else if(volumeHost.getDownloadState() == VMTemplateStorageResourceAssoc.Status.DOWNLOAD_IN_PROGRESS){ + }else if(volumeHost.getDownloadState() == VMTemplateStorageResourceAssoc.Status.DOWNLOAD_IN_PROGRESS){ s_logger.debug("Volume: " + vol.getName() + " is currently being uploaded; cant' delete it."); throw new CloudRuntimeException("Please specify a volume that is not currently being uploaded."); } _volumeHostDao.remove(volumeHost.getId()); _volumeDao.remove(vol.getId()); - return; + return; } - + String vmName = null; if (vol.getVolumeType() == Type.ROOT && vol.getInstanceId() != null) { VirtualMachine vm = _vmInstanceDao.findByIdIncludingRemoved(vol.getInstanceId()); @@ -3894,7 +3894,7 @@ public class StorageManagerImpl implements StorageManager, Manager, ClusterManag vmSearch.and("type", vmSearch.entity().getType(), SearchCriteria.Op.NIN); vmSearch.or("nulltype", vmSearch.entity().getType(), SearchCriteria.Op.NULL); sb.join("vmSearch", vmSearch, sb.entity().getInstanceId(), vmSearch.entity().getId(), JoinBuilder.JoinType.LEFTOUTER); - + if (tags != null && !tags.isEmpty()) { SearchBuilder tagSearch = _resourceTagDao.createSearchBuilder(); for (int count=0; count < tags.size(); count++) { @@ -3924,7 +3924,7 @@ public class StorageManagerImpl implements StorageManager, Manager, ClusterManag } sc.setJoinParameters("diskOfferingSearch", "systemUse", 1); - + if (tags != null && !tags.isEmpty()) { int count = 0; sc.setJoinParameters("tagSearch", "resourceType", TaggedResourceType.Volume.toString()); @@ -3957,7 +3957,7 @@ public class StorageManagerImpl implements StorageManager, Manager, ClusterManag // Only return volumes that are not destroyed sc.setParameters("state", Volume.State.Destroy); - + Pair, Integer> volumes = _volumeDao.searchAndCount(sc, searchFilter); return new Pair, Integer>(volumes.first(), volumes.second()); @@ -3979,14 +3979,14 @@ public class StorageManagerImpl implements StorageManager, Manager, ClusterManag return null; } } - + @Override public HypervisorType getHypervisorTypeFromFormat(ImageFormat format) { - + if(format == null) { return HypervisorType.None; } - + if (format == ImageFormat.VHD) { return HypervisorType.XenServer; } else if (format == ImageFormat.OVA) { @@ -4075,5 +4075,5 @@ public class StorageManagerImpl implements StorageManager, Manager, ClusterManag } return true; } - + } diff --git a/server/test/com/cloud/api/APITest.java b/server/test/com/cloud/api/APITest.java new file mode 100644 index 00000000000..69c488f5a10 --- /dev/null +++ b/server/test/com/cloud/api/APITest.java @@ -0,0 +1,189 @@ +// 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 +// 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; + +import java.io.BufferedReader; +import java.io.EOFException; +import java.io.InputStreamReader; +import java.io.OutputStreamWriter; +import java.math.BigInteger; +import java.net.HttpURLConnection; +import java.net.URL; +import java.net.URLConnection; +import java.net.URLEncoder; +import java.security.MessageDigest; +import java.security.NoSuchAlgorithmException; +import java.util.HashMap; +import java.util.Iterator; + +import com.cloud.utils.exception.CloudRuntimeException; +import com.google.gson.Gson; + +/** + * Base class for API Test + * + * @author Min Chen + * + */ +public abstract class APITest { + + protected String rootUrl = "http://localhost:8080/client/api"; + protected String sessionKey = null; + protected String cookieToSent = null; + + + /** + * Sending an api request through Http GET + * @param command command name + * @param params command query parameters in a HashMap + * @return http request response string + */ + protected String sendRequest(String command, HashMap params){ + try { + // Construct query string + StringBuilder sBuilder = new StringBuilder(); + sBuilder.append("command="); + sBuilder.append(command); + if ( params != null && params.size() > 0){ + Iterator keys = params.keySet().iterator(); + while (keys.hasNext()){ + String key = keys.next(); + sBuilder.append("&"); + sBuilder.append(key); + sBuilder.append("="); + sBuilder.append(URLEncoder.encode(params.get(key), "UTF-8")); + } + } + + // Construct request url + String reqUrl = rootUrl + "?" + sBuilder.toString(); + + // Send Http GET request + URL url = new URL(reqUrl); + HttpURLConnection conn = (HttpURLConnection) url.openConnection(); + conn.setRequestMethod("GET"); + + if ( !command.equals("login") && cookieToSent != null){ + // add the cookie to a request + conn.setRequestProperty("Cookie", cookieToSent); + } + conn.connect(); + + + if ( command.equals("login")){ + // if it is login call, store cookie + String headerName=null; + for (int i=1; (headerName = conn.getHeaderFieldKey(i))!=null; i++) { + if (headerName.equals("Set-Cookie")) { + String cookie = conn.getHeaderField(i); + cookie = cookie.substring(0, cookie.indexOf(";")); + String cookieName = cookie.substring(0, cookie.indexOf("=")); + String cookieValue = cookie.substring(cookie.indexOf("=") + 1, cookie.length()); + cookieToSent = cookieName + "=" + cookieValue; + } + } + } + + // Get the response + StringBuilder response = new StringBuilder(); + BufferedReader rd = new BufferedReader(new InputStreamReader(conn.getInputStream())); + String line; + try { + while ((line = rd.readLine()) != null) { + response.append(line); + } + } catch (EOFException ex) { + // ignore this exception + System.out.println("EOF exception due to java bug"); + } + rd.close(); + + + + return response.toString(); + + } catch (Exception e) { + throw new CloudRuntimeException("Problem with sending api request", e); + } + } + + protected String createMD5String(String password) { + MessageDigest md5; + try { + md5 = MessageDigest.getInstance("MD5"); + } catch (NoSuchAlgorithmException e) { + throw new CloudRuntimeException("Error", e); + } + + md5.reset(); + BigInteger pwInt = new BigInteger(1, md5.digest(password.getBytes())); + + // make sure our MD5 hash value is 32 digits long... + StringBuffer sb = new StringBuffer(); + String pwStr = pwInt.toString(16); + int padding = 32 - pwStr.length(); + for (int i = 0; i < padding; i++) { + sb.append('0'); + } + sb.append(pwStr); + return sb.toString(); + } + + + protected Object fromSerializedString(String result, Class repCls) { + try { + if (result != null && !result.isEmpty()) { + + // get real content + int start = result.indexOf('{', result.indexOf('{') + 1); // find the second { + if ( start < 0 ){ + throw new CloudRuntimeException("Response format is wrong: " + result); + } + int end = result.lastIndexOf('}', result.lastIndexOf('}')-1); // find the second } backwards + if ( end < 0 ){ + throw new CloudRuntimeException("Response format is wrong: " + result); + } + String content = result.substring(start, end+1); + Gson gson = ApiGsonHelper.getBuilder().create(); + return gson.fromJson(content, repCls); + } + return null; + } catch (RuntimeException e) { + throw new CloudRuntimeException("Caught runtime exception when doing GSON deserialization on: " + result, e); + } + } + + /** + * Login call + * @param username user name + * @param password password (plain password, we will do MD5 hash here for you) + * @return login response string + */ + protected void login(String username, String password) + { + //String md5Psw = createMD5String(password); + // send login request + HashMap params = new HashMap(); + params.put("response", "json"); + params.put("username", username); + params.put("password", password); + String result = this.sendRequest("login", params); + LoginResponse loginResp = (LoginResponse)fromSerializedString(result, LoginResponse.class); + sessionKey = loginResp.getSessionkey(); + + } +} diff --git a/server/test/com/cloud/api/ListPerfTest.java b/server/test/com/cloud/api/ListPerfTest.java new file mode 100644 index 00000000000..47abcaedc12 --- /dev/null +++ b/server/test/com/cloud/api/ListPerfTest.java @@ -0,0 +1,109 @@ +// 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 +// 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; + +import java.util.HashMap; + +import org.junit.Before; +import org.junit.Test; + + +/** + * Test fixture to do performance test for list command + * Currently we commented out this test suite since it requires a real MS and Db running. + * + * @author Min Chen + * + */ +public class ListPerfTest extends APITest { + + + + @Before + public void setup(){ + // always login for each testcase + login("admin", "password"); + } + + @Test + public void testListVM(){ + // issue list VM calls + HashMap params = new HashMap(); + params.put("response", "json"); + params.put("listAll", "true"); + params.put("sessionkey", sessionKey); + long before = System.currentTimeMillis(); + String result = this.sendRequest("listVirtualMachines", params); + long after = System.currentTimeMillis(); + System.out.println("Time taken to list VM: " + (after - before) + " ms"); + + } + + @Test + public void testListVMXML(){ + // issue list VM calls + HashMap params = new HashMap(); + params.put("listAll", "true"); + params.put("sessionkey", sessionKey); + long before = System.currentTimeMillis(); + String result = this.sendRequest("listVirtualMachines", params); + long after = System.currentTimeMillis(); + System.out.println("Time taken to list VM: " + (after - before) + " ms"); + + } + + @Test + public void testListRouter(){ + // issue list VM calls + HashMap params = new HashMap(); + params.put("response", "json"); + params.put("listAll", "true"); + params.put("sessionkey", sessionKey); + long before = System.currentTimeMillis(); + String result = this.sendRequest("listRouters", params); + long after = System.currentTimeMillis(); + System.out.println("Time taken to list Routers: " + (after - before) + " ms"); + + } + + @Test + public void testListRouterXML(){ + // issue list VM calls + HashMap params = new HashMap(); + params.put("listAll", "true"); + params.put("sessionkey", sessionKey); + long before = System.currentTimeMillis(); + String result = this.sendRequest("listRouters", params); + long after = System.currentTimeMillis(); + System.out.println("Time taken to list Routers: " + (after - before) + " ms"); + + } + + @Test + public void testListHosts(){ + // issue list Hosts calls + HashMap params = new HashMap(); + params.put("response", "json"); + params.put("listAll", "true"); + params.put("sessionkey", sessionKey); + long before = System.currentTimeMillis(); + String result = this.sendRequest("listHosts", params); + long after = System.currentTimeMillis(); + System.out.println("Time taken to list Hosts: " + (after - before) + " ms"); + + } +} diff --git a/server/test/com/cloud/api/LoginResponse.java b/server/test/com/cloud/api/LoginResponse.java new file mode 100644 index 00000000000..097ae42c999 --- /dev/null +++ b/server/test/com/cloud/api/LoginResponse.java @@ -0,0 +1,142 @@ +// 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 +// 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; + +import org.apache.cloudstack.api.BaseResponse; + +import com.cloud.serializer.Param; +import com.google.gson.annotations.SerializedName; + +/** + * Login Response object + * + * @author Min Chen + * + */ +public class LoginResponse extends BaseResponse { + + @SerializedName("timeout") + @Param(description = "session timeout period") + private String timeout; + + @SerializedName("sessionkey") + @Param(description = "login session key") + private String sessionkey; + + @SerializedName("username") + @Param(description = "login username") + private String username; + + @SerializedName("userid") + @Param(description = "login user internal uuid") + private String userid; + + @SerializedName("firstname") + @Param(description = "login user firstname") + private String firstname; + + @SerializedName("lastname") + @Param(description = "login user lastname") + private String lastname; + + @SerializedName("account") + @Param(description = "login user account type") + private String account; + + @SerializedName("domainid") + @Param(description = "login user domain id") + private String domainid; + + @SerializedName("type") + @Param(description = "login user type") + private int type; + + public String getTimeout() { + return timeout; + } + + public void setTimeout(String timeout) { + this.timeout = timeout; + } + + public String getSessionkey() { + return sessionkey; + } + + public void setSessionkey(String sessionkey) { + this.sessionkey = sessionkey; + } + + public String getUsername() { + return username; + } + + public void setUsername(String username) { + this.username = username; + } + + public String getUserid() { + return userid; + } + + public void setUserid(String userid) { + this.userid = userid; + } + + public String getFirstname() { + return firstname; + } + + public void setFirstname(String firstname) { + this.firstname = firstname; + } + + public String getLastname() { + return lastname; + } + + public void setLastname(String lastname) { + this.lastname = lastname; + } + + public String getAccount() { + return account; + } + + public void setAccount(String account) { + this.account = account; + } + + public String getDomainid() { + return domainid; + } + + public void setDomainid(String domainid) { + this.domainid = domainid; + } + + public int getType() { + return type; + } + + public void setType(int type) { + this.type = type; + } + + + +}