server: update template to another template type (#3945)

this contains other changes
(1) add isrouting field for vm templates on UI
(2) show register URL of template/iso on UI
(3) set 'Bootable' field to changable for existing ISO
This commit is contained in:
Wei Zhou 2020-10-28 11:11:36 +01:00 committed by GitHub
parent b9f15fd159
commit dbb66850b2
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 119 additions and 4 deletions

View File

@ -21,6 +21,7 @@ import org.apache.log4j.Logger;
import org.apache.cloudstack.api.APICommand; import org.apache.cloudstack.api.APICommand;
import org.apache.cloudstack.api.ApiErrorCode; import org.apache.cloudstack.api.ApiErrorCode;
import org.apache.cloudstack.api.BaseUpdateTemplateOrIsoCmd; import org.apache.cloudstack.api.BaseUpdateTemplateOrIsoCmd;
import org.apache.cloudstack.api.Parameter;
import org.apache.cloudstack.api.ResponseObject.ResponseView; import org.apache.cloudstack.api.ResponseObject.ResponseView;
import org.apache.cloudstack.api.ServerApiException; import org.apache.cloudstack.api.ServerApiException;
import org.apache.cloudstack.api.command.user.UserCmd; 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()); public static final Logger s_logger = Logger.getLogger(UpdateTemplateCmd.class.getName());
private static final String s_name = "updatetemplateresponse"; 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 /////////////////////// /////////////////// Accessors ///////////////////////
///////////////////////////////////////////////////// /////////////////////////////////////////////////////
@ -44,6 +52,10 @@ public class UpdateTemplateCmd extends BaseUpdateTemplateOrIsoCmd implements Use
return null; return null;
} }
public String getTemplateType() {
return templateType;
}
///////////////////////////////////////////////////// /////////////////////////////////////////////////////
/////////////// API Implementation/////////////////// /////////////// API Implementation///////////////////
///////////////////////////////////////////////////// /////////////////////////////////////////////////////

View File

@ -201,6 +201,10 @@ public class TemplateResponse extends BaseResponseWithTagInformation implements
@Param(description = "true if template requires HVM enabled, false otherwise") @Param(description = "true if template requires HVM enabled, false otherwise")
private Boolean requiresHvm; private Boolean requiresHvm;
@SerializedName(ApiConstants.URL)
@Param(description = "the URL which the template/iso is registered from")
private String url;
public TemplateResponse() { public TemplateResponse() {
tags = new LinkedHashSet<>(); tags = new LinkedHashSet<>();
} }
@ -402,4 +406,8 @@ public class TemplateResponse extends BaseResponseWithTagInformation implements
public void setRequiresHvm(Boolean requiresHvm) { public void setRequiresHvm(Boolean requiresHvm) {
this.requiresHvm = requiresHvm; this.requiresHvm = requiresHvm;
} }
public void setUrl(String url) {
this.url = url;
}
} }

View File

@ -184,6 +184,7 @@ public class TemplateJoinDaoImpl extends GenericDaoBaseWithTagInformation<Templa
if (templateStatus != null) { if (templateStatus != null) {
templateResponse.setStatus(templateStatus); templateResponse.setStatus(templateStatus);
} }
templateResponse.setUrl(template.getUrl());
} }
if (template.getDataCenterId() > 0) { if (template.getDataCenterId() > 0) {
@ -373,6 +374,7 @@ public class TemplateJoinDaoImpl extends GenericDaoBaseWithTagInformation<Templa
} else { } else {
isoResponse.setStatus("Successfully Installed"); isoResponse.setStatus("Successfully Installed");
} }
isoResponse.setUrl(iso.getUrl());
} }
if (iso.getDataCenterId() > 0) { if (iso.getDataCenterId() > 0) {

View File

@ -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 // update is needed if any of the fields below got filled by the user
boolean updateNeeded = boolean updateNeeded =
!(name == null && !(name == null &&
@ -2088,6 +2107,7 @@ public class TemplateManagerImpl extends ManagerBase implements TemplateManager,
sortKey == null && sortKey == null &&
isDynamicallyScalable == null && isDynamicallyScalable == null &&
isRoutingTemplate == null && isRoutingTemplate == null &&
templateType == null &&
(! cleanupDetails && details == null) //update details in every case except this one (! cleanupDetails && details == null) //update details in every case except this one
); );
if (!updateNeeded) { if (!updateNeeded) {
@ -2165,9 +2185,13 @@ public class TemplateManagerImpl extends ManagerBase implements TemplateManager,
if (isRoutingTemplate != null) { if (isRoutingTemplate != null) {
if (isRoutingTemplate) { if (isRoutingTemplate) {
template.setTemplateType(TemplateType.ROUTING); template.setTemplateType(TemplateType.ROUTING);
} else if (templateType != null) {
template.setTemplateType(templateType);
} else { } else {
template.setTemplateType(TemplateType.USER); template.setTemplateType(TemplateType.USER);
} }
} else if (templateType != null) {
template.setTemplateType(templateType);
} }
if (cleanupDetails) { if (cleanupDetails) {

View File

@ -1336,9 +1336,15 @@
name: args.data.name, name: args.data.name,
displaytext: args.data.displaytext, displaytext: args.data.displaytext,
ostypeid: args.data.ostypeid, ostypeid: args.data.ostypeid,
templatetype: args.data.templatetype,
passwordenabled: (args.data.passwordenabled == "on"), passwordenabled: (args.data.passwordenabled == "on"),
isdynamicallyscalable: (args.data.isdynamicallyscalable == "on") isdynamicallyscalable: (args.data.isdynamicallyscalable == "on")
}; };
if (args.data.isrouting != null) {
$.extend(data, {
isrouting: (args.data.isrouting === 'on')
});
}
$.ajax({ $.ajax({
url: createURL('updateTemplate'), url: createURL('updateTemplate'),
data: data, data: data,
@ -1846,7 +1852,7 @@
if (isAdmin()) { if (isAdmin()) {
hiddenFields = []; hiddenFields = [];
} else { } else {
hiddenFields = ["hypervisor", 'xenserverToolsVersion61plus']; hiddenFields = ["hypervisor", 'xenserverToolsVersion61plus', 'isrouting'];
} }
if ('templates' in args.context && args.context.templates[0].hypervisor != 'XenServer') { 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; 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: { crossZones: {
label: 'label.cross.zones', label: 'label.cross.zones',
converter: cloudStack.converters.toBooleanText converter: cloudStack.converters.toBooleanText
@ -2013,9 +2035,45 @@
label: 'label.created', label: 'label.created',
converter: cloudStack.converters.toLocalDate converter: cloudStack.converters.toLocalDate
}, },
url: {
label: 'label.url'
},
templatetype: { 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: { id: {
@ -2045,6 +2103,11 @@
else else
jsonObj.xenserverToolsVersion61plus = false; jsonObj.xenserverToolsVersion61plus = false;
} }
if (jsonObj.templatetype == 'ROUTING') {
jsonObj.isrouting = true;
} else {
jsonObj.isrouting = false;
}
args.response.success({ args.response.success({
actionFilter: templateActionfilter, 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. //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, name: args.data.name,
displaytext: args.data.displaytext, displaytext: args.data.displaytext,
bootable: (args.data.bootable == "on"),
ostypeid: args.data.ostypeid ostypeid: args.data.ostypeid
}; };
$.ajax({ $.ajax({
@ -3410,6 +3474,8 @@
}, },
bootable: { bootable: {
label: 'label.bootable', label: 'label.bootable',
isBoolean: true,
isEditable: true,
converter: cloudStack.converters.toBooleanText converter: cloudStack.converters.toBooleanText
}, },
ispublic: { ispublic: {
@ -3470,6 +3536,9 @@
created: { created: {
label: 'label.created', label: 'label.created',
converter: cloudStack.converters.toLocalDate converter: cloudStack.converters.toLocalDate
},
url: {
label: 'label.url'
} }
}], }],
@ -3805,7 +3874,7 @@
// "Edit Template", "Copy Template", "Create VM" // "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 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 //do nothing
} else { } else {
allowedActions.push("edit"); allowedActions.push("edit");
@ -3815,7 +3884,7 @@
// "Download Template" , "Update Template Permissions" // "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 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 //do nothing
} else { } else {
if (jsonObj.isextractable){ if (jsonObj.isextractable){