diff --git a/api/src/main/java/org/apache/cloudstack/api/command/user/template/UpdateTemplateCmd.java b/api/src/main/java/org/apache/cloudstack/api/command/user/template/UpdateTemplateCmd.java index ee60ad5142d..8396b078c15 100644 --- a/api/src/main/java/org/apache/cloudstack/api/command/user/template/UpdateTemplateCmd.java +++ b/api/src/main/java/org/apache/cloudstack/api/command/user/template/UpdateTemplateCmd.java @@ -21,6 +21,7 @@ import org.apache.log4j.Logger; import org.apache.cloudstack.api.APICommand; import org.apache.cloudstack.api.ApiErrorCode; import org.apache.cloudstack.api.BaseUpdateTemplateOrIsoCmd; +import org.apache.cloudstack.api.Parameter; import org.apache.cloudstack.api.ResponseObject.ResponseView; import org.apache.cloudstack.api.ServerApiException; import org.apache.cloudstack.api.command.user.UserCmd; @@ -35,6 +36,13 @@ public class UpdateTemplateCmd extends BaseUpdateTemplateOrIsoCmd implements Use public static final Logger s_logger = Logger.getLogger(UpdateTemplateCmd.class.getName()); private static final String s_name = "updatetemplateresponse"; + ///////////////////////////////////////////////////// + //////////////// API parameters ///////////////////// + ///////////////////////////////////////////////////// + + @Parameter(name = "templatetype", type = CommandType.STRING, description = "the type of the template") + private String templateType; + ///////////////////////////////////////////////////// /////////////////// Accessors /////////////////////// ///////////////////////////////////////////////////// @@ -44,6 +52,10 @@ public class UpdateTemplateCmd extends BaseUpdateTemplateOrIsoCmd implements Use return null; } + public String getTemplateType() { + return templateType; + } + ///////////////////////////////////////////////////// /////////////// API Implementation/////////////////// ///////////////////////////////////////////////////// diff --git a/api/src/main/java/org/apache/cloudstack/api/response/TemplateResponse.java b/api/src/main/java/org/apache/cloudstack/api/response/TemplateResponse.java index 81fc2f37b0d..9aeba0fad31 100644 --- a/api/src/main/java/org/apache/cloudstack/api/response/TemplateResponse.java +++ b/api/src/main/java/org/apache/cloudstack/api/response/TemplateResponse.java @@ -201,6 +201,10 @@ public class TemplateResponse extends BaseResponseWithTagInformation implements @Param(description = "true if template requires HVM enabled, false otherwise") private Boolean requiresHvm; + @SerializedName(ApiConstants.URL) + @Param(description = "the URL which the template/iso is registered from") + private String url; + public TemplateResponse() { tags = new LinkedHashSet<>(); } @@ -402,4 +406,8 @@ public class TemplateResponse extends BaseResponseWithTagInformation implements public void setRequiresHvm(Boolean requiresHvm) { this.requiresHvm = requiresHvm; } + + public void setUrl(String url) { + this.url = url; + } } diff --git a/server/src/main/java/com/cloud/api/query/dao/TemplateJoinDaoImpl.java b/server/src/main/java/com/cloud/api/query/dao/TemplateJoinDaoImpl.java index 61a101743c9..3c441e5fc2b 100644 --- a/server/src/main/java/com/cloud/api/query/dao/TemplateJoinDaoImpl.java +++ b/server/src/main/java/com/cloud/api/query/dao/TemplateJoinDaoImpl.java @@ -184,6 +184,7 @@ public class TemplateJoinDaoImpl extends GenericDaoBaseWithTagInformation 0) { @@ -373,6 +374,7 @@ public class TemplateJoinDaoImpl extends GenericDaoBaseWithTagInformation 0) { diff --git a/server/src/main/java/com/cloud/template/TemplateManagerImpl.java b/server/src/main/java/com/cloud/template/TemplateManagerImpl.java index a651cff7b3e..0240a6131bd 100755 --- a/server/src/main/java/com/cloud/template/TemplateManagerImpl.java +++ b/server/src/main/java/com/cloud/template/TemplateManagerImpl.java @@ -2075,6 +2075,25 @@ public class TemplateManagerImpl extends ManagerBase implements TemplateManager, } } + // update template type + TemplateType templateType = null; + if (cmd instanceof UpdateTemplateCmd) { + String newType = ((UpdateTemplateCmd)cmd).getTemplateType(); + if (newType != null) { + if (!_accountService.isRootAdmin(account.getId())) { + throw new PermissionDeniedException("Parameter templatetype can only be specified by a Root Admin, permission denied"); + } + try { + templateType = TemplateType.valueOf(newType.toUpperCase()); + } catch (IllegalArgumentException ex) { + throw new InvalidParameterValueException("Please specify a valid templatetype: ROUTING / SYSTEM / USER / BUILTIN / PERHOST"); + } + } + if (templateType != null && cmd.isRoutingType() != null && (TemplateType.ROUTING.equals(templateType) != cmd.isRoutingType())) { + throw new InvalidParameterValueException("Please specify a valid templatetype (consistent with isrouting parameter)."); + } + } + // update is needed if any of the fields below got filled by the user boolean updateNeeded = !(name == null && @@ -2088,6 +2107,7 @@ public class TemplateManagerImpl extends ManagerBase implements TemplateManager, sortKey == null && isDynamicallyScalable == null && isRoutingTemplate == null && + templateType == null && (! cleanupDetails && details == null) //update details in every case except this one ); if (!updateNeeded) { @@ -2165,9 +2185,13 @@ public class TemplateManagerImpl extends ManagerBase implements TemplateManager, if (isRoutingTemplate != null) { if (isRoutingTemplate) { template.setTemplateType(TemplateType.ROUTING); + } else if (templateType != null) { + template.setTemplateType(templateType); } else { template.setTemplateType(TemplateType.USER); } + } else if (templateType != null) { + template.setTemplateType(templateType); } if (cleanupDetails) { diff --git a/ui/scripts/templates.js b/ui/scripts/templates.js index 92167335958..f7e784f6f34 100644 --- a/ui/scripts/templates.js +++ b/ui/scripts/templates.js @@ -1336,9 +1336,15 @@ name: args.data.name, displaytext: args.data.displaytext, ostypeid: args.data.ostypeid, + templatetype: args.data.templatetype, passwordenabled: (args.data.passwordenabled == "on"), isdynamicallyscalable: (args.data.isdynamicallyscalable == "on") }; + if (args.data.isrouting != null) { + $.extend(data, { + isrouting: (args.data.isrouting === 'on') + }); + } $.ajax({ url: createURL('updateTemplate'), data: data, @@ -1846,7 +1852,7 @@ if (isAdmin()) { hiddenFields = []; } else { - hiddenFields = ["hypervisor", 'xenserverToolsVersion61plus']; + hiddenFields = ["hypervisor", 'xenserverToolsVersion61plus', 'isrouting']; } if ('templates' in args.context && args.context.templates[0].hypervisor != 'XenServer') { @@ -1878,6 +1884,9 @@ } } + if (!('templates' in args.context && args.context.templates[0].domainid == g_domainid && args.context.templates[0].account == g_account) && !isAdmin()) { + hiddenFields.push('url'); + } return hiddenFields; }, @@ -1991,6 +2000,19 @@ } }, + isrouting: { + label: 'label.routing', + isBoolean: true, + isEditable: function() { + if (isAdmin()) { + return true; + } else { + return false; + } + }, + converter: cloudStack.converters.toBooleanText + }, + crossZones: { label: 'label.cross.zones', converter: cloudStack.converters.toBooleanText @@ -2013,9 +2035,45 @@ label: 'label.created', converter: cloudStack.converters.toLocalDate }, + url: { + label: 'label.url' + }, templatetype: { - label: 'label.type' + label: 'label.type', + isEditable: function() { + if (isAdmin()) { + return true; + } else { + return false; + } + }, + select: function(args) { + var items = []; + items.push({ + id: 'ROUTING', + description: 'ROUTING' + }); + items.push({ + id: 'SYSTEM', + description: 'SYSTEM' + }); + items.push({ + id: 'BUILTIN', + description: 'BUILTIN' + }); + items.push({ + id: 'PERHOST', + description: 'PERHOST' + }); + items.push({ + id: 'USER', + description: 'USER' + }); + args.response.success({ + data: items + }); + } }, id: { @@ -2045,6 +2103,11 @@ else jsonObj.xenserverToolsVersion61plus = false; } + if (jsonObj.templatetype == 'ROUTING') { + jsonObj.isrouting = true; + } else { + jsonObj.isrouting = false; + } args.response.success({ actionFilter: templateActionfilter, @@ -3236,6 +3299,7 @@ //zoneid: args.context.isos[0].zoneid, //can't update template/ISO in only one zone. It always get updated in all zones. name: args.data.name, displaytext: args.data.displaytext, + bootable: (args.data.bootable == "on"), ostypeid: args.data.ostypeid }; $.ajax({ @@ -3410,6 +3474,8 @@ }, bootable: { label: 'label.bootable', + isBoolean: true, + isEditable: true, converter: cloudStack.converters.toBooleanText }, ispublic: { @@ -3470,6 +3536,9 @@ created: { label: 'label.created', converter: cloudStack.converters.toLocalDate + }, + url: { + label: 'label.url' } }], @@ -3805,7 +3874,7 @@ // "Edit Template", "Copy Template", "Create VM" if ((isAdmin() == false && !(jsonObj.domainid == g_domainid && jsonObj.account == g_account) && !(jsonObj.domainid == g_domainid && cloudStack.context.projects && jsonObj.projectid == cloudStack.context.projects[0].id)) //if neither root-admin, nor the same account, nor the same project - || jsonObj.templatetype == "SYSTEM" || jsonObj.isready == false) { + || jsonObj.isready == false) { //do nothing } else { allowedActions.push("edit"); @@ -3815,7 +3884,7 @@ // "Download Template" , "Update Template Permissions" if (((isAdmin() == false && !(jsonObj.domainid == g_domainid && jsonObj.account == g_account) && !(jsonObj.domainid == g_domainid && cloudStack.context.projects && jsonObj.projectid == cloudStack.context.projects[0].id))) //if neither root-admin, nor the same account, nor the same project - || (jsonObj.isready == false) || jsonObj.templatetype == "SYSTEM") { + || (jsonObj.isready == false)) { //do nothing } else { if (jsonObj.isextractable){