diff --git a/api/src/com/cloud/api/ApiConstants.java b/api/src/com/cloud/api/ApiConstants.java index 15d9f411a18..f250a4ff99e 100755 --- a/api/src/com/cloud/api/ApiConstants.java +++ b/api/src/com/cloud/api/ApiConstants.java @@ -270,5 +270,6 @@ public class ApiConstants { public static final String ACTIVE_ONLY = "activeonly"; public static final String TOKEN = "token"; public static final String ACCEPT = "accept"; + public static final String SORT_KEY = "sortkey"; } diff --git a/api/src/com/cloud/api/commands/UpdateDiskOfferingCmd.java b/api/src/com/cloud/api/commands/UpdateDiskOfferingCmd.java old mode 100644 new mode 100755 index d496e22b491..d7d9526b379 --- a/api/src/com/cloud/api/commands/UpdateDiskOfferingCmd.java +++ b/api/src/com/cloud/api/commands/UpdateDiskOfferingCmd.java @@ -47,6 +47,9 @@ public class UpdateDiskOfferingCmd extends BaseCmd{ @Parameter(name=ApiConstants.NAME, type=CommandType.STRING, description="updates name of the disk offering with this value") private String diskOfferingName; + + @Parameter(name=ApiConstants.SORT_KEY, type=CommandType.INTEGER, description="sort key of the disk offering, integer") + private Integer sortKey; ///////////////////////////////////////////////////// /////////////////// Accessors /////////////////////// @@ -63,6 +66,10 @@ public class UpdateDiskOfferingCmd extends BaseCmd{ public String getDiskOfferingName() { return diskOfferingName; } + + public Integer getSortKey() { + return sortKey; + } ///////////////////////////////////////////////////// diff --git a/api/src/com/cloud/api/commands/UpdateNetworkOfferingCmd.java b/api/src/com/cloud/api/commands/UpdateNetworkOfferingCmd.java old mode 100644 new mode 100755 index 764aef50f00..28680fda0b8 --- a/api/src/com/cloud/api/commands/UpdateNetworkOfferingCmd.java +++ b/api/src/com/cloud/api/commands/UpdateNetworkOfferingCmd.java @@ -28,6 +28,7 @@ import com.cloud.api.IdentityMapper; import com.cloud.api.Implementation; import com.cloud.api.Parameter; import com.cloud.api.ServerApiException; +import com.cloud.api.BaseCmd.CommandType; import com.cloud.api.response.NetworkOfferingResponse; import com.cloud.offering.NetworkOffering; import com.cloud.offering.NetworkOffering.Availability; @@ -53,7 +54,10 @@ public class UpdateNetworkOfferingCmd extends BaseCmd { private String displayText; @Parameter(name=ApiConstants.AVAILABILITY, type=CommandType.STRING, description="the availability of network offering. Default value is Required for Guest Virtual network offering; Optional for Guest Direct network offering") - private String availability; + private String availability; + + @Parameter(name=ApiConstants.SORT_KEY, type=CommandType.INTEGER, description="sort key of the network offering, integer") + private Integer sortKey; ///////////////////////////////////////////////////// /////////////////// Accessors /////////////////////// @@ -74,6 +78,10 @@ public class UpdateNetworkOfferingCmd extends BaseCmd { public String getAvailability() { return availability == null ? Availability.Required.toString() : availability; } + + public Integer getSortKey() { + return sortKey; + } ///////////////////////////////////////////////////// /////////////// API Implementation/////////////////// diff --git a/api/src/com/cloud/api/commands/UpdateServiceOfferingCmd.java b/api/src/com/cloud/api/commands/UpdateServiceOfferingCmd.java old mode 100644 new mode 100755 index 9d46b8c754c..ad1e1eadbaa --- a/api/src/com/cloud/api/commands/UpdateServiceOfferingCmd.java +++ b/api/src/com/cloud/api/commands/UpdateServiceOfferingCmd.java @@ -25,6 +25,7 @@ import com.cloud.api.IdentityMapper; import com.cloud.api.Implementation; import com.cloud.api.Parameter; import com.cloud.api.ServerApiException; +import com.cloud.api.BaseCmd.CommandType; import com.cloud.api.response.ServiceOfferingResponse; import com.cloud.offering.ServiceOffering; import com.cloud.user.Account; @@ -48,6 +49,8 @@ public class UpdateServiceOfferingCmd extends BaseCmd { @Parameter(name=ApiConstants.NAME, type=CommandType.STRING, description="the name of the service offering to be updated") private String serviceOfferingName; + @Parameter(name=ApiConstants.SORT_KEY, type=CommandType.INTEGER, description="sort key of the service offering, integer") + private Integer sortKey; ///////////////////////////////////////////////////// /////////////////// Accessors /////////////////////// ///////////////////////////////////////////////////// @@ -64,7 +67,9 @@ public class UpdateServiceOfferingCmd extends BaseCmd { return serviceOfferingName; } - + public Integer getSortKey() { + return sortKey; + } ///////////////////////////////////////////////////// /////////////// API Implementation/////////////////// diff --git a/api/src/com/cloud/api/commands/UpdateTemplateOrIsoCmd.java b/api/src/com/cloud/api/commands/UpdateTemplateOrIsoCmd.java old mode 100644 new mode 100755 index ab667d0107e..7b50df7bb23 --- a/api/src/com/cloud/api/commands/UpdateTemplateOrIsoCmd.java +++ b/api/src/com/cloud/api/commands/UpdateTemplateOrIsoCmd.java @@ -24,6 +24,7 @@ import com.cloud.api.ApiConstants; import com.cloud.api.BaseCmd; import com.cloud.api.IdentityMapper; import com.cloud.api.Parameter; +import com.cloud.api.BaseCmd.CommandType; public abstract class UpdateTemplateOrIsoCmd extends BaseCmd { public static final Logger s_logger = Logger.getLogger(UpdateIsoCmd.class.getName()); @@ -53,6 +54,9 @@ public abstract class UpdateTemplateOrIsoCmd extends BaseCmd { @Parameter(name=ApiConstants.PASSWORD_ENABLED, type=CommandType.BOOLEAN, description="true if the image supports the password reset feature; default is false") private Boolean passwordEnabled; + + @Parameter(name=ApiConstants.SORT_KEY, type=CommandType.INTEGER, description="sort key of the template, integer") + private Integer sortKey; ///////////////////////////////////////////////////// /////////////////// Accessors /////////////////////// @@ -85,4 +89,8 @@ public abstract class UpdateTemplateOrIsoCmd extends BaseCmd { public String getFormat() { return format; } + + public Integer getSortKey() { + return sortKey; + } } diff --git a/client/tomcatconf/commands.properties.in b/client/tomcatconf/commands.properties.in index b66ed506bd0..3884f03c781 100755 --- a/client/tomcatconf/commands.properties.in +++ b/client/tomcatconf/commands.properties.in @@ -175,7 +175,6 @@ listAlerts=com.cloud.api.commands.ListAlertsCmd;3 #### system capacity commands listCapacity=com.cloud.api.commands.ListCapacityCmd;3 -listCapacityByType=com.cloud.api.commands.ListCapacityByTypeCmd;3 #### host commands addHost=com.cloud.api.commands.AddHostCmd;3 diff --git a/core/src/com/cloud/storage/DiskOfferingVO.java b/core/src/com/cloud/storage/DiskOfferingVO.java old mode 100644 new mode 100755 index 94056a3aaa5..8528a90cce6 --- a/core/src/com/cloud/storage/DiskOfferingVO.java +++ b/core/src/com/cloud/storage/DiskOfferingVO.java @@ -98,10 +98,13 @@ public class DiskOfferingVO implements DiskOffering, Identity { @Column(name="uuid") private String uuid; + @Column(name="sort_key") + int sortKey; + public DiskOfferingVO() { this.uuid = UUID.randomUUID().toString(); - } - + } + public DiskOfferingVO(Long domainId, String name, String displayText, long diskSize, String tags, boolean isCustomized) { this.domainId = domainId; this.name = name; @@ -300,5 +303,13 @@ public class DiskOfferingVO implements DiskOffering, Identity { public void setUuid(String uuid) { this.uuid = uuid; + } + + public void setSortKey(int key) { + sortKey = key; + } + + public int getSortKey() { + return sortKey; } } diff --git a/core/src/com/cloud/storage/VMTemplateVO.java b/core/src/com/cloud/storage/VMTemplateVO.java index 203aae2ba71..cf757da11fc 100755 --- a/core/src/com/cloud/storage/VMTemplateVO.java +++ b/core/src/com/cloud/storage/VMTemplateVO.java @@ -123,6 +123,9 @@ public class VMTemplateVO implements VirtualMachineTemplate, Identity { private String uuid; + @Column(name="sort_key") + int sortKey; + @Override public String getUniqueName() { return uniqueName; @@ -433,5 +436,13 @@ public class VMTemplateVO implements VirtualMachineTemplate, Identity { public void setRemoved(Date removed) { this.removed = removed; } + + public void setSortKey(int key) { + sortKey = key; + } + + public int getSortKey() { + return sortKey; + } } diff --git a/server/src/com/cloud/configuration/Config.java b/server/src/com/cloud/configuration/Config.java index 7658b10e4a9..22c14a4ad49 100755 --- a/server/src/com/cloud/configuration/Config.java +++ b/server/src/com/cloud/configuration/Config.java @@ -216,7 +216,8 @@ public enum Config { ElasticLoadBalancerVmCpuMhz("Advanced", ManagementServer.class, Integer.class, "network.loadbalancer.basiczone.elb.vm.cpu.mhz", "128", "CPU speed for the elastic load balancer vm", null), ElasticLoadBalancerVmNumVcpu("Advanced", ManagementServer.class, Integer.class, "network.loadbalancer.basiczone.elb.vm.vcpu.num", "1", "Number of VCPU for the elastic load balancer vm", null), ElasticLoadBalancerVmGcInterval("Advanced", ManagementServer.class, Integer.class, "network.loadbalancer.basiczone.elb.gc.interval.minutes", "30", "Garbage collection interval to destroy unused ELB vms in minutes. Minimum of 5", null), - + SortKeyAlgorithm("Advanced", ManagementServer.class, Boolean.class, "sortkey.algorithm", "false", "Sort algorithm for those who use sort key(template, disk offering, service offering, network offering), true means ascending sort while false means descending sort", null), + // Ovm OvmPublicNetwork("Advanced", ManagementServer.class, String.class, "ovm.public.network.device", null, "Specify the public bridge on host for public network", null), OvmPrivateNetwork("Advanced", ManagementServer.class, String.class, "ovm.private.network.device", null, "Specify the private bridge on host for private network", null), diff --git a/server/src/com/cloud/configuration/ConfigurationManagerImpl.java b/server/src/com/cloud/configuration/ConfigurationManagerImpl.java index a26696d0329..258615df1cd 100755 --- a/server/src/com/cloud/configuration/ConfigurationManagerImpl.java +++ b/server/src/com/cloud/configuration/ConfigurationManagerImpl.java @@ -1709,6 +1709,7 @@ public class ConfigurationManagerImpl implements ConfigurationManager, Configura String displayText = cmd.getDisplayText(); Long id = cmd.getId(); String name = cmd.getServiceOfferingName(); + Integer sortKey = cmd.getSortKey(); Long userId = UserContext.current().getCallerUserId(); if (userId == null) { @@ -1736,6 +1737,10 @@ public class ConfigurationManagerImpl implements ConfigurationManager, Configura if (displayText != null) { offering.setDisplayText(displayText); } + + if (sortKey != null) { + offering.setSortKey(sortKey); + } // Note: tag editing commented out for now; keeping the code intact, might need to re-enable in next releases // if (tags != null) @@ -1823,6 +1828,7 @@ public class ConfigurationManagerImpl implements ConfigurationManager, Configura Long diskOfferingId = cmd.getId(); String name = cmd.getDiskOfferingName(); String displayText = cmd.getDisplayText(); + Integer sortKey = cmd.getSortKey(); // Check if diskOffering exists DiskOffering diskOfferingHandle = getDiskOffering(diskOfferingId); @@ -1831,7 +1837,7 @@ public class ConfigurationManagerImpl implements ConfigurationManager, Configura throw new InvalidParameterValueException("Unable to find disk offering by id " + diskOfferingId); } - boolean updateNeeded = (name != null || displayText != null); + boolean updateNeeded = (name != null || displayText != null || sortKey != null); if (!updateNeeded) { return _diskOfferingDao.findById(diskOfferingId); } @@ -1845,6 +1851,10 @@ public class ConfigurationManagerImpl implements ConfigurationManager, Configura if (displayText != null) { diskOffering.setDisplayText(displayText); } + + if (sortKey != null) { + diskOffering.setSortKey(sortKey); + } // Note: tag editing commented out for now;keeping the code intact, might need to re-enable in next releases // if (tags != null) @@ -2944,7 +2954,9 @@ public class ConfigurationManagerImpl implements ConfigurationManager, Configura @Override public List searchForNetworkOfferings(ListNetworkOfferingsCmd cmd) { - Filter searchFilter = new Filter(NetworkOfferingVO.class, "created", false, cmd.getStartIndex(), cmd.getPageSizeVal()); + Boolean isAscending = Boolean.parseBoolean(_configDao.getValue("sortkey.algorithm")); + isAscending = (isAscending == null ? true : isAscending); + Filter searchFilter = new Filter(NetworkOfferingVO.class, "sortKey", isAscending, cmd.getStartIndex(), cmd.getPageSizeVal()); SearchCriteria sc = _networkOfferingDao.createSearchCriteria(); Object id = cmd.getId(); @@ -3054,6 +3066,7 @@ public class ConfigurationManagerImpl implements ConfigurationManager, Configura Long id = cmd.getId(); String name = cmd.getNetworkOfferingName(); String availabilityStr = cmd.getAvailability(); + Integer sortKey = cmd.getSortKey(); Availability availability = null; UserContext.current().setEventDetails(" Id: "+id); @@ -3082,6 +3095,10 @@ public class ConfigurationManagerImpl implements ConfigurationManager, Configura if (displayText != null) { offering.setDisplayText(displayText); } + + if (sortKey != null) { + offering.setSortKey(sortKey); + } // Verify availability if (availabilityStr != null) { diff --git a/server/src/com/cloud/offerings/NetworkOfferingVO.java b/server/src/com/cloud/offerings/NetworkOfferingVO.java old mode 100644 new mode 100755 index b700c0579df..74c2beb4da5 --- a/server/src/com/cloud/offerings/NetworkOfferingVO.java +++ b/server/src/com/cloud/offerings/NetworkOfferingVO.java @@ -120,6 +120,9 @@ public class NetworkOfferingVO implements NetworkOffering, Identity { @Column(name="redundant_router") boolean redundantRouter; + + @Column(name="sort_key") + int sortKey; @Column(name="uuid") String uuid; @@ -393,4 +396,12 @@ public class NetworkOfferingVO implements NetworkOffering, Identity { public void setUuid(String uuid) { this.uuid = uuid; } + + public void setSortKey(int key) { + sortKey = key; + } + + public int getSortKey() { + return sortKey; + } } diff --git a/server/src/com/cloud/server/ManagementServerImpl.java b/server/src/com/cloud/server/ManagementServerImpl.java index 6bb26ecaccf..dc0bc3ae177 100755 --- a/server/src/com/cloud/server/ManagementServerImpl.java +++ b/server/src/com/cloud/server/ManagementServerImpl.java @@ -729,7 +729,9 @@ public class ManagementServerImpl implements ManagementServer { // 1. For root, we will list all offerings // 2. For domainAdmin and regular users, we will list everything in their domains+parent domains ... all the way till // root - Filter searchFilter = new Filter(ServiceOfferingVO.class, "created", false, cmd.getStartIndex(), cmd.getPageSizeVal()); + Boolean isAscending = Boolean.parseBoolean(_configDao.getValue("sortkey.algorithm")); + isAscending = (isAscending == null ? true : isAscending); + Filter searchFilter = new Filter(ServiceOfferingVO.class, "sortKey", isAscending, cmd.getStartIndex(), cmd.getPageSizeVal()); SearchCriteria sc = _offeringsDao.createSearchCriteria(); Account caller = UserContext.current().getCaller(); @@ -1568,6 +1570,7 @@ public class ManagementServerImpl implements ManagementServer { Long guestOSId = cmd.getOsTypeId(); Boolean passwordEnabled = cmd.isPasswordEnabled(); Boolean bootable = cmd.isBootable(); + Integer sortKey = cmd.getSortKey(); Account account = UserContext.current().getCaller(); // verify that template exists @@ -1584,7 +1587,7 @@ public class ManagementServerImpl implements ManagementServer { // do a permission check _accountMgr.checkAccess(account, AccessType.ModifyEntry, template); - boolean updateNeeded = !(name == null && displayText == null && format == null && guestOSId == null && passwordEnabled == null && bootable == null); + boolean updateNeeded = !(name == null && displayText == null && format == null && guestOSId == null && passwordEnabled == null && bootable == null && sortKey == null); if (!updateNeeded) { return template; } @@ -1598,6 +1601,10 @@ public class ManagementServerImpl implements ManagementServer { if (displayText != null) { template.setDisplayText(displayText); } + + if (sortKey != null) { + template.setSortKey(sortKey); + } ImageFormat imageFormat = null; if (format != null) { @@ -2826,7 +2833,9 @@ public class ManagementServerImpl implements ManagementServer { // 2. For domainAdmin and regular users, we will list everything in their domains+parent domains ... all the way till // root - Filter searchFilter = new Filter(DiskOfferingVO.class, "created", false, cmd.getStartIndex(), cmd.getPageSizeVal()); + Boolean isAscending = Boolean.parseBoolean(_configDao.getValue("sortkey.algorithm")); + isAscending = (isAscending == null ? true : isAscending); + Filter searchFilter = new Filter(DiskOfferingVO.class, "sortKey", isAscending, cmd.getStartIndex(), cmd.getPageSizeVal()); SearchBuilder sb = _diskOfferingDao.createSearchBuilder(); // SearchBuilder and SearchCriteria are now flexible so that the search builder can be built with all possible diff --git a/server/src/com/cloud/service/ServiceOfferingVO.java b/server/src/com/cloud/service/ServiceOfferingVO.java old mode 100644 new mode 100755 index 1a37ceb36b8..53906fb6a21 --- a/server/src/com/cloud/service/ServiceOfferingVO.java +++ b/server/src/com/cloud/service/ServiceOfferingVO.java @@ -63,6 +63,9 @@ public class ServiceOfferingVO extends DiskOfferingVO implements ServiceOffering @Column(name="vm_type") private String vm_type; + + @Column(name="sort_key") + int sortKey; protected ServiceOfferingVO() { super(); @@ -188,5 +191,13 @@ public class ServiceOfferingVO extends DiskOfferingVO implements ServiceOffering public String getSystemVmType(){ return vm_type; } + + public void setSortKey(int key) { + sortKey = key; + } + + public int getSortKey() { + return sortKey; + } } diff --git a/server/src/com/cloud/storage/dao/VMTemplateDaoImpl.java b/server/src/com/cloud/storage/dao/VMTemplateDaoImpl.java index fbe547dc94f..ab2d0da790a 100755 --- a/server/src/com/cloud/storage/dao/VMTemplateDaoImpl.java +++ b/server/src/com/cloud/storage/dao/VMTemplateDaoImpl.java @@ -24,6 +24,7 @@ import java.sql.SQLException; import java.util.ArrayList; import java.util.Date; import java.util.HashSet; +import java.util.LinkedHashSet; import java.util.List; import java.util.Map; import java.util.Set; @@ -401,7 +402,7 @@ public class VMTemplateDaoImpl extends GenericDaoBase implem return templateZonePairList; } - sql += joinClause + whereClause; + sql += joinClause + whereClause + getOrderByLimit(pageSize, startIndex); pstmt = txn.prepareStatement(sql); rs = pstmt.executeQuery(); while (rs.next()) { @@ -448,7 +449,8 @@ public class VMTemplateDaoImpl extends GenericDaoBase implem Transaction txn = Transaction.currentTxn(); txn.start(); - Set> templateZonePairList = new HashSet>(); + /* Use LinkedHashSet here to guarantee iteration order */ + Set> templateZonePairList = new LinkedHashSet>(); PreparedStatement pstmt = null; ResultSet rs = null; StringBuilder relatedDomainIds = new StringBuilder(); @@ -648,8 +650,17 @@ public class VMTemplateDaoImpl extends GenericDaoBase implem return sql; } - private String getOrderByLimit(Long pageSize, Long startIndex) { - String sql = " ORDER BY t.created DESC"; + private String getOrderByLimit(Long pageSize, Long startIndex) { + Boolean isAscending = Boolean.parseBoolean(_configDao.getValue("sortkey.algorithm")); + isAscending = (isAscending == null ? true : isAscending); + + String sql; + if (isAscending) { + sql = " ORDER BY t.sort_key ASC"; + } else { + sql = " ORDER BY t.sort_key DESC"; + } + if ((pageSize != null) && (startIndex != null)) { sql += " LIMIT " + startIndex.toString() + "," + pageSize.toString(); } diff --git a/setup/db/create-schema.sql b/setup/db/create-schema.sql index 3e352462f3a..d0456f5e046 100755 --- a/setup/db/create-schema.sql +++ b/setup/db/create-schema.sql @@ -274,6 +274,7 @@ CREATE TABLE `cloud`.`network_offerings` ( `shared_source_nat_service` int(1) unsigned NOT NULL DEFAULT 0 COMMENT 'true if the network offering provides the shared source nat service', `guest_type` char(32) COMMENT 'guest ip type of network offering', `redundant_router` int(1) unsigned NOT NULL DEFAULT 0 COMMENT 'true if network offering provides redundant routers', + `sort_key` int(32) NOT NULL default 0 COMMENT 'sort key used for customising sort method', PRIMARY KEY (`id`), INDEX `i_network_offerings__system_only`(`system_only`), INDEX `i_network_offerings__removed`(`removed`), @@ -890,6 +891,7 @@ CREATE TABLE `cloud`.`vm_template` ( `hypervisor_type` varchar(32) COMMENT 'hypervisor that the template belongs to', `source_template_id` bigint unsigned COMMENT 'Id of the original template, if this template is created from snapshot', `template_tag` varchar(255) COMMENT 'template tag', + `sort_key` int(32) NOT NULL default 0 COMMENT 'sort key used for customising sort method', PRIMARY KEY (`id`), INDEX `i_vm_template__removed`(`removed`), CONSTRAINT `uc_vm_template__uuid` UNIQUE (`uuid`) @@ -1267,6 +1269,7 @@ CREATE TABLE `cloud`.`disk_offering` ( `customized` tinyint(1) unsigned NOT NULL DEFAULT 0 COMMENT '0 implies not customized by default', `removed` datetime COMMENT 'date removed', `created` datetime COMMENT 'date the disk offering was created', + `sort_key` int(32) NOT NULL default 0 COMMENT 'sort key used for customising sort method', PRIMARY KEY (`id`), INDEX `i_disk_offering__removed`(`removed`), CONSTRAINT `uc_disk_offering__uuid` UNIQUE (`uuid`) @@ -1284,6 +1287,7 @@ CREATE TABLE `cloud`.`service_offering` ( `host_tag` varchar(255) COMMENT 'host tag specified by the service_offering', `default_use` tinyint(1) unsigned NOT NULL DEFAULT 0 COMMENT 'is this offering a default system offering', `vm_type` varchar(32) COMMENT 'type of offering specified for system offerings', + `sort_key` int(32) NOT NULL default 0 COMMENT 'sort key used for customising sort method', PRIMARY KEY (`id`), CONSTRAINT `fk_service_offering__id` FOREIGN KEY `fk_service_offering__id`(`id`) REFERENCES `disk_offering`(`id`) ON DELETE CASCADE ) ENGINE=InnoDB DEFAULT CHARSET=utf8;