Skip to content

Commit 8ea124a

Browse files
bug 7046 : extracting templates should allow for exclusion of some templates. An attribute "extractable" would be set on templates by the template owner at upload time. It would specify if we allow the template to be extracted from the system. Default would be true ie "allow extraction". If set to false, it would not be possible to extract the template or any derivatives of the template. For example, volumes, snapshots or templates from that template.
status 7046: resolved fixed
1 parent bb790b4 commit 8ea124a

11 files changed

Lines changed: 92 additions & 18 deletions

File tree

api/src/com/cloud/api/ApiConstants.java

100644100755
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -81,6 +81,7 @@ public class ApiConstants {
8181
public static final String IP_LIMIT = "iplimit";
8282
public static final String IP_TOTAL = "iptotal";
8383
public static final String IS_CLEANUP_REQUIRED = "iscleanuprequired";
84+
public static final String IS_EXTRACTABLE = "isextractable";
8485
public static final String IS_FEATURED = "isfeatured";
8586
public static final String IS_PUBLIC = "ispublic";
8687
public static final String IS_READY = "isready";

api/src/com/cloud/api/commands/RegisterTemplateCmd.java

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -67,6 +67,9 @@ public class RegisterTemplateCmd extends BaseCmd {
6767

6868
@Parameter(name=ApiConstants.PASSWORD_ENABLED, type=CommandType.BOOLEAN, description="true if the template supports the password reset feature; default is false")
6969
private Boolean passwordEnabled;
70+
71+
@Parameter(name=ApiConstants.IS_EXTRACTABLE, type=CommandType.BOOLEAN, description="true if the template or its derivatives are extractable; default is true")
72+
private Boolean extractable;
7073

7174
@Parameter(name=ApiConstants.REQUIRES_HVM, type=CommandType.BOOLEAN, description="true if this template requires HVM")
7275
private Boolean requiresHvm;
@@ -123,6 +126,10 @@ public Boolean isPasswordEnabled() {
123126
return passwordEnabled;
124127
}
125128

129+
public Boolean isExtractable() {
130+
return extractable;
131+
}
132+
126133
public Boolean getRequiresHvm() {
127134
return requiresHvm;
128135
}

api/src/com/cloud/api/response/TemplateResponse.java

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -104,6 +104,9 @@ public class TemplateResponse extends BaseResponse {
104104
@SerializedName("domainid") @Param(description="the ID of the domain to which the template belongs")
105105
private Long domainId;
106106

107+
@SerializedName("isextractable") @Param(description="true if the template is extractable, false otherwise")
108+
private Boolean extractable;
109+
107110
public Long getZoneId() {
108111
return zoneId;
109112
}
@@ -311,4 +314,12 @@ public void setDomainName(String domainName) {
311314
public void setDomainId(long domainId) {
312315
this.domainId = domainId;
313316
}
317+
318+
public Boolean isExtractable() {
319+
return extractable;
320+
}
321+
322+
public void setExtractable(Boolean extractable) {
323+
this.extractable = extractable;
324+
}
314325
}

api/src/com/cloud/template/VirtualMachineTemplate.java

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,8 @@ public enum TemplateFilter {
4949
*/
5050
boolean isPublicTemplate();
5151

52+
boolean isExtractable();
53+
5254
/**
5355
* @return name
5456
*/

core/src/com/cloud/storage/VMTemplateVO.java

100644100755
Lines changed: 41 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -106,7 +106,9 @@ public class VMTemplateVO implements VirtualMachineTemplate {
106106
@Column(name="hypervisor_type")
107107
private String hypervisorType;
108108

109-
109+
@Column(name="extractable")
110+
private boolean extractable = true;
111+
110112
public String getUniqueName() {
111113
return uniqueName;
112114
}
@@ -121,8 +123,8 @@ protected VMTemplateVO() {
121123
/**
122124
* Proper constructor for a new vm template.
123125
*/
124-
public VMTemplateVO(long id, String name, ImageFormat format, boolean isPublic, boolean featured, TemplateType type, String url, boolean requiresHvm, int bits, long accountId, String cksum, String displayText, boolean enablePassword, long guestOSId, boolean bootable, HypervisorType hyperType) {
125-
this(id, generateUniqueName(id, accountId, name), name, format, isPublic, featured, type, url, null, requiresHvm, bits, accountId, cksum, displayText, enablePassword, guestOSId, bootable, hyperType);
126+
public VMTemplateVO(long id, String name, ImageFormat format, boolean isPublic, boolean featured, boolean isExtractable, TemplateType type, String url, boolean requiresHvm, int bits, long accountId, String cksum, String displayText, boolean enablePassword, long guestOSId, boolean bootable, HypervisorType hyperType) {
127+
this(id, generateUniqueName(id, accountId, name), name, format, isPublic, featured, isExtractable, type, url, null, requiresHvm, bits, accountId, cksum, displayText, enablePassword, guestOSId, bootable, hyperType);
126128
}
127129

128130
public VMTemplateVO(Long id, String uniqueName, String name, ImageFormat format, boolean isPublic, boolean featured, TemplateType type, String url, Date created, boolean requiresHvm, int bits, long accountId, String cksum, String displayText, boolean enablePassword, long guestOSId, boolean bootable, HypervisorType hyperType) {
@@ -144,10 +146,33 @@ public VMTemplateVO(Long id, String uniqueName, String name, ImageFormat format,
144146
this.guestOSId = guestOSId;
145147
this.bootable = bootable;
146148
this.hypervisorType = hyperType.toString();
147-
}
148-
149-
@Override
150-
public boolean getEnablePassword() {
149+
}
150+
151+
// Has an extra attribute - isExtractable
152+
public VMTemplateVO(Long id, String uniqueName, String name, ImageFormat format, boolean isPublic, boolean featured, boolean isExtractable, TemplateType type, String url, Date created, boolean requiresHvm, int bits, long accountId, String cksum, String displayText, boolean enablePassword, long guestOSId, boolean bootable, HypervisorType hyperType) {
153+
this.id = id;
154+
this.name = name;
155+
this.publicTemplate = isPublic;
156+
this.featured = featured;
157+
this.extractable = isExtractable;
158+
this.templateType = type;
159+
this.url = url;
160+
this.requiresHvm = requiresHvm;
161+
this.bits = bits;
162+
this.accountId = accountId;
163+
this.checksum = cksum;
164+
this.uniqueName = uniqueName;
165+
this.displayText = displayText;
166+
this.enablePassword = enablePassword;
167+
this.format = format;
168+
this.created = created;
169+
this.guestOSId = guestOSId;
170+
this.bootable = bootable;
171+
this.hypervisorType = hyperType.toString();
172+
}
173+
174+
@Override
175+
public boolean getEnablePassword() {
151176
return enablePassword;
152177
}
153178

@@ -310,6 +335,15 @@ public void setHypervisorType(HypervisorType hyperType) {
310335
hypervisorType = hyperType.toString();
311336
}
312337

338+
@Override
339+
public boolean isExtractable() {
340+
return extractable;
341+
}
342+
343+
public void setExtractable(boolean extractable) {
344+
this.extractable = extractable;
345+
}
346+
313347
@Override
314348
public long getDomainId() {
315349
return -1;

server/src/com/cloud/api/ApiResponseHelper.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1571,6 +1571,7 @@ public ListResponse<TemplateResponse> createTemplateResponse2(VirtualMachineTemp
15711571
templateResponse.setName(template.getName());
15721572
templateResponse.setDisplayText(template.getDisplayText());
15731573
templateResponse.setPublic(template.isPublicTemplate());
1574+
templateResponse.setExtractable(template.isExtractable());
15741575
templateResponse.setCrossZones(template.isCrossZones());
15751576

15761577
VMTemplateHostVO isoHostRef = ApiDBUtils.findTemplateHostRef(template.getId(), zone.getId());

server/src/com/cloud/server/ManagementServerImpl.java

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5197,6 +5197,12 @@ public Long extractVolume(ExtractVolumeCmd cmd) throws URISyntaxException {
51975197
throw new PermissionDeniedException("Invalid state of the volume with ID: " + volumeId + ". It should be either detached or the VM should be in stopped state.");
51985198
}
51995199

5200+
VMTemplateVO template = ApiDBUtils.findTemplateById(volume.getTemplateId());
5201+
boolean isExtractable = template != null && template.isExtractable() && !(template.getTemplateType()== Storage.TemplateType.SYSTEM || template.getTemplateType()== Storage.TemplateType.BUILTIN);
5202+
if( !isExtractable ){
5203+
throw new PermissionDeniedException("The volume:" +volumeId+ " is not allowed to be extracted");
5204+
}
5205+
52005206
Upload.Mode extractMode;
52015207
if( mode == null || (!mode.equals(Upload.Mode.FTP_UPLOAD.toString()) && !mode.equals(Upload.Mode.HTTP_DOWNLOAD.toString())) ){
52025208
throw new ServerApiException(BaseCmd.PARAM_ERROR, "Please specify a valid extract Mode ");

server/src/com/cloud/template/TemplateManager.java

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,7 @@ public interface TemplateManager {
4646
* @param displayText user readable name.
4747
* @param isPublic is this a public template?
4848
* @param featured is this template featured?
49+
* @param isExtractable is this template extractable?
4950
* @param format which image format is the template.
5051
* @param fs what is the file system on the template
5152
* @param url url to download the template from.
@@ -57,7 +58,7 @@ public interface TemplateManager {
5758
* @param bootable true if this template will represent a bootable ISO
5859
* @return id of the template created.
5960
*/
60-
Long createInZone(long zoneId, long userId, String displayText, boolean isPublic, boolean featured, ImageFormat format, TemplateType type, URI url, String chksum, boolean requiresHvm, int bits, boolean enablePassword, long guestOSId, boolean bootable);
61+
Long createInZone(long zoneId, long userId, String displayText, boolean isPublic, boolean featured, boolean isExtractable, ImageFormat format, TemplateType type, URI url, String chksum, boolean requiresHvm, int bits, boolean enablePassword, long guestOSId, boolean bootable);
6162

6263
/**
6364
* Prepares a template for vm creation for a certain storage pool.

server/src/com/cloud/template/TemplateManagerImpl.java

Lines changed: 15 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -248,7 +248,7 @@ public VirtualMachineTemplate registerIso(RegisterIsoCmd cmd) throws ResourceAll
248248
throw new ServerApiException(BaseCmd.PARAM_ERROR, "File:// type urls are currently unsupported");
249249
}
250250

251-
return createTemplateOrIso(userId, accountId, zoneId, name, displayText, isPublic.booleanValue(), featured.booleanValue(), ImageFormat.ISO.toString(), null, url, null, true, 64 /*bits*/, false, guestOSId, bootable, HypervisorType.None);
251+
return createTemplateOrIso(userId, accountId, zoneId, name, displayText, isPublic.booleanValue(), featured.booleanValue(), true, ImageFormat.ISO.toString(), null, url, null, true, 64 /*bits*/, false, guestOSId, bootable, HypervisorType.None);
252252
}
253253

254254
@Override
@@ -264,6 +264,7 @@ public VirtualMachineTemplate registerTemplate(RegisterTemplateCmd cmd) throws U
264264
String url = cmd.getUrl();
265265
Boolean isPublic = cmd.isPublic();
266266
Boolean featured = cmd.isFeatured();
267+
Boolean isExtractable = cmd.isExtractable();
267268
String format = cmd.getFormat();
268269
Long guestOSId = cmd.getOsTypeId();
269270
Long zoneId = cmd.getZoneId();
@@ -286,6 +287,9 @@ public VirtualMachineTemplate registerTemplate(RegisterTemplateCmd cmd) throws U
286287
if (isPublic == null) {
287288
isPublic = Boolean.FALSE;
288289
}
290+
if(isExtractable == null){
291+
isExtractable = Boolean.TRUE;
292+
}
289293

290294
if (zoneId.longValue() == -1) {
291295
zoneId = null;
@@ -353,11 +357,11 @@ public VirtualMachineTemplate registerTemplate(RegisterTemplateCmd cmd) throws U
353357
userId = Long.valueOf(1);
354358
}
355359

356-
return createTemplateOrIso(userId, accountId, zoneId, name, displayText, isPublic, featured, format, "ext3", url, null, requiresHVM, bits, passwordEnabled, guestOSId, true, hypervisorType);
360+
return createTemplateOrIso(userId, accountId, zoneId, name, displayText, isPublic, featured, isExtractable, format, "ext3", url, null, requiresHVM, bits, passwordEnabled, guestOSId, true, hypervisorType);
357361

358362
}
359363

360-
private VMTemplateVO createTemplateOrIso(long userId, Long accountId, Long zoneId, String name, String displayText, boolean isPublic, boolean featured, String format, String diskType, String url, String chksum, boolean requiresHvm, int bits, boolean enablePassword, long guestOSId, boolean bootable, HypervisorType hypervisorType) throws IllegalArgumentException, ResourceAllocationException {
364+
private VMTemplateVO createTemplateOrIso(long userId, Long accountId, Long zoneId, String name, String displayText, boolean isPublic, boolean featured, boolean isExtractable, String format, String diskType, String url, String chksum, boolean requiresHvm, int bits, boolean enablePassword, long guestOSId, boolean bootable, HypervisorType hypervisorType) throws IllegalArgumentException, ResourceAllocationException {
361365
try
362366
{
363367
if (name.length() > 32)
@@ -419,21 +423,21 @@ private VMTemplateVO createTemplateOrIso(long userId, Long accountId, Long zoneI
419423
throw new IllegalArgumentException("Cannot use reserved names for templates");
420424
}
421425

422-
return create(userId, accountId, zoneId, name, displayText, isPublic, featured, imgfmt, null, uri, chksum, requiresHvm, bits, enablePassword, guestOSId, bootable, hypervisorType);
426+
return create(userId, accountId, zoneId, name, displayText, isPublic, featured, isExtractable, imgfmt, null, uri, chksum, requiresHvm, bits, enablePassword, guestOSId, bootable, hypervisorType);
423427
} catch (URISyntaxException e) {
424428
throw new IllegalArgumentException("Invalid URL " + url);
425429
}
426430
}
427431

428-
private VMTemplateVO create(long userId, long accountId, Long zoneId, String name, String displayText, boolean isPublic, boolean featured, ImageFormat format, TemplateType type, URI url, String chksum, boolean requiresHvm, int bits, boolean enablePassword, long guestOSId, boolean bootable, HypervisorType hyperType) {
432+
private VMTemplateVO create(long userId, long accountId, Long zoneId, String name, String displayText, boolean isPublic, boolean featured, boolean isExtractable, ImageFormat format, TemplateType type, URI url, String chksum, boolean requiresHvm, int bits, boolean enablePassword, long guestOSId, boolean bootable, HypervisorType hyperType) {
429433
Long id = _tmpltDao.getNextInSequence(Long.class, "id");
430434

431435
AccountVO account = _accountDao.findById(accountId);
432436
if (account.getType() != Account.ACCOUNT_TYPE_ADMIN && zoneId == null) {
433437
throw new IllegalArgumentException("Only admins can create templates in all zones");
434438
}
435439

436-
VMTemplateVO template = new VMTemplateVO(id, name, format, isPublic, featured, type, url.toString(), requiresHvm, bits, accountId, chksum, displayText, enablePassword, guestOSId, bootable, hyperType);
440+
VMTemplateVO template = new VMTemplateVO(id, name, format, isPublic, featured, isExtractable, type, url.toString(), requiresHvm, bits, accountId, chksum, displayText, enablePassword, guestOSId, bootable, hyperType);
437441
if (zoneId == null) {
438442
List<DataCenterVO> dcs = _dcDao.listAllIncludingRemoved();
439443

@@ -500,7 +504,9 @@ private Long extract(Account account, Long templateId, String url, Long zoneId,
500504
throw new InvalidParameterValueException("Unsupported format, could not extract the template");
501505
}
502506
}
503-
507+
if(!template.isExtractable()){
508+
throw new PermissionDeniedException("The "+ desc + " is not allowed to be extracted" );
509+
}
504510
if (_dcDao.findById(zoneId) == null) {
505511
throw new IllegalArgumentException("Please specify a valid zone.");
506512
}
@@ -1117,15 +1123,15 @@ protected TemplateManagerImpl() {
11171123

11181124
@Override
11191125
public Long createInZone(long zoneId, long userId, String displayText,
1120-
boolean isPublic, boolean featured, ImageFormat format,
1126+
boolean isPublic, boolean featured, boolean isExtractable, ImageFormat format,
11211127
TemplateType type, URI url, String chksum, boolean requiresHvm,
11221128
int bits, boolean enablePassword, long guestOSId, boolean bootable) {
11231129
Long id = _tmpltDao.getNextInSequence(Long.class, "id");
11241130

11251131
UserVO user = _userDao.findById(userId);
11261132
long accountId = user.getAccountId();
11271133

1128-
VMTemplateVO template = new VMTemplateVO(id, displayText, format, isPublic, featured, type, url.toString(), requiresHvm, bits, accountId, chksum, displayText, enablePassword, guestOSId, bootable, null);
1134+
VMTemplateVO template = new VMTemplateVO(id, displayText, format, isPublic, featured, isExtractable, type, url.toString(), requiresHvm, bits, accountId, chksum, displayText, enablePassword, guestOSId, bootable, null);
11291135

11301136
Long templateId = _tmpltDao.addTemplateToZone(template, zoneId);
11311137
UserAccount userAccount = _userAccountDao.findById(userId);

server/src/com/cloud/vm/UserVmManagerImpl.java

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,7 @@
6363
import com.cloud.agent.api.storage.CreatePrivateTemplateAnswer;
6464
import com.cloud.agent.manager.Commands;
6565
import com.cloud.alert.AlertManager;
66+
import com.cloud.api.ApiDBUtils;
6667
import com.cloud.api.BaseCmd;
6768
import com.cloud.api.ServerApiException;
6869
import com.cloud.api.commands.AttachVolumeCmd;
@@ -2472,13 +2473,16 @@ public VMTemplateVO createPrivateTemplateRecord(CreateTemplateCmd cmd) throws In
24722473

24732474
Long nextTemplateId = _templateDao.getNextInSequence(Long.class, "id");
24742475
String description = cmd.getDisplayText();
2476+
VMTemplateVO template = ApiDBUtils.findTemplateById(volume.getTemplateId());
2477+
boolean isExtractable = template != null && template.isExtractable() && !(template.getTemplateType()== Storage.TemplateType.SYSTEM || template.getTemplateType()== Storage.TemplateType.BUILTIN);
24752478

24762479
privateTemplate = new VMTemplateVO(nextTemplateId,
24772480
uniqueName,
24782481
name,
24792482
ImageFormat.RAW,
24802483
isPublic,
24812484
featured,
2485+
isExtractable,
24822486
null,
24832487
null,
24842488
null,
@@ -2490,7 +2494,7 @@ public VMTemplateVO createPrivateTemplateRecord(CreateTemplateCmd cmd) throws In
24902494
passwordEnabledValue,
24912495
guestOS.getId(),
24922496
true,
2493-
hyperType);
2497+
hyperType);
24942498

24952499
// FIXME: scheduled events should get saved when the command is actually scheduled, not when it starts executing, need another callback
24962500
// for when the command is scheduled? Could this fit into the setup / execute / response lifecycle? Right after setup you would

0 commit comments

Comments
 (0)