Skip to content

Commit fe0e5b5

Browse files
committed
Match template tags with host tag for vm deployment
1. Match the template tags with host tags for vm deployment/migration 2. Allow updating templates/isos with template tag by admin 3. Allow adding template tag while registering/creating template/iso 4. Allow searching templats/isos using template tags If a template has template tag then deploy the vm which uses this template on hosts which matches the template tags. If no suitable hosts are found then throw exception Similarly match the template tag with host tags while starting or migrating a vm to a different host
1 parent 5f8289f commit fe0e5b5

18 files changed

Lines changed: 449 additions & 20 deletions

File tree

api/src/main/java/org/apache/cloudstack/api/command/user/iso/ListIsosCmd.java

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616
// under the License.
1717
package org.apache.cloudstack.api.command.user.iso;
1818

19+
import org.apache.cloudstack.acl.RoleType;
1920
import org.apache.log4j.Logger;
2021

2122
import org.apache.cloudstack.api.APICommand;
@@ -82,6 +83,9 @@ public class ListIsosCmd extends BaseListTaggedResourcesCmd implements UserCmd {
8283
@Parameter(name = ApiConstants.SHOW_UNIQUE, type = CommandType.BOOLEAN, description = "If set to true, list only unique isos across zones", since = "4.13.2")
8384
private Boolean showUnique;
8485

86+
@Parameter(name = ApiConstants.TEMPLATE_TAG, type = CommandType.STRING, description = "show ISO's which matches the tag", authorized = {RoleType.Admin})
87+
private String templateTag;
88+
8589
/////////////////////////////////////////////////////
8690
/////////////////// Accessors ///////////////////////
8791
/////////////////////////////////////////////////////
@@ -145,6 +149,10 @@ public boolean listInReadyState() {
145149
return onlyReady;
146150
}
147151

152+
public String getTemplateTag() {
153+
return templateTag;
154+
}
155+
148156
/////////////////////////////////////////////////////
149157
/////////////// API Implementation///////////////////
150158
/////////////////////////////////////////////////////

api/src/main/java/org/apache/cloudstack/api/command/user/iso/RegisterIsoCmd.java

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818

1919
import java.util.List;
2020

21+
import org.apache.cloudstack.acl.RoleType;
2122
import org.apache.cloudstack.api.APICommand;
2223
import org.apache.cloudstack.api.ApiConstants;
2324
import org.apache.cloudstack.api.ApiErrorCode;
@@ -119,6 +120,9 @@ public class RegisterIsoCmd extends BaseCmd implements UserCmd {
119120
description = "true if password reset feature is supported; default is false")
120121
private Boolean passwordEnabled;
121122

123+
@Parameter(name = ApiConstants.TEMPLATE_TAG, type = CommandType.STRING, description = "the tag for this template.", authorized = {RoleType.Admin})
124+
private String templateTag;
125+
122126
/////////////////////////////////////////////////////
123127
/////////////////// Accessors ///////////////////////
124128
/////////////////////////////////////////////////////
@@ -223,6 +227,8 @@ public boolean isPasswordEnabled() {
223227
return passwordEnabled == null ? false : passwordEnabled;
224228
}
225229

230+
public String getTemplateTag() {return templateTag; }
231+
226232
/////////////////////////////////////////////////////
227233
/////////////// API Implementation///////////////////
228234
/////////////////////////////////////////////////////

api/src/main/java/org/apache/cloudstack/api/command/user/iso/UpdateIsoCmd.java

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,9 @@
1616
// under the License.
1717
package org.apache.cloudstack.api.command.user.iso;
1818

19+
import org.apache.cloudstack.acl.RoleType;
20+
import org.apache.cloudstack.api.ApiConstants;
21+
import org.apache.cloudstack.api.Parameter;
1922
import org.apache.log4j.Logger;
2023

2124
import org.apache.cloudstack.api.APICommand;
@@ -35,6 +38,13 @@ public class UpdateIsoCmd extends BaseUpdateTemplateOrIsoCmd implements UserCmd
3538
public static final Logger s_logger = Logger.getLogger(UpdateIsoCmd.class.getName());
3639
private static final String s_name = "updateisoresponse";
3740

41+
/////////////////////////////////////////////////////
42+
//////////////// API parameters /////////////////////
43+
/////////////////////////////////////////////////////
44+
45+
@Parameter(name = ApiConstants.TEMPLATE_TAG, type = CommandType.STRING, description = "the tag for this iso.", authorized = {RoleType.Admin})
46+
private String templateTag;
47+
3848
/////////////////////////////////////////////////////
3949
/////////////////// Accessors ///////////////////////
4050
/////////////////////////////////////////////////////
@@ -49,6 +59,10 @@ public String getFormat() {
4959
return null;
5060
}
5161

62+
public String getTemplateTag() {
63+
return templateTag;
64+
}
65+
5266
/////////////////////////////////////////////////////
5367
/////////////// API Implementation///////////////////
5468
/////////////////////////////////////////////////////

api/src/main/java/org/apache/cloudstack/api/command/user/template/CreateTemplateCmd.java

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020
import java.util.List;
2121
import java.util.Map;
2222

23+
import org.apache.cloudstack.acl.RoleType;
2324
import org.apache.cloudstack.acl.SecurityChecker;
2425
import org.apache.cloudstack.api.command.user.UserCmd;
2526
import org.apache.cloudstack.api.response.GuestOSResponse;
@@ -121,7 +122,7 @@ public class CreateTemplateCmd extends BaseAsyncCreateCmd implements UserCmd {
121122
description = "Optional, only for baremetal hypervisor. The directory name where template stored on CIFS server")
122123
private String url;
123124

124-
@Parameter(name = ApiConstants.TEMPLATE_TAG, type = CommandType.STRING, description = "the tag for this template.")
125+
@Parameter(name = ApiConstants.TEMPLATE_TAG, type = CommandType.STRING, description = "the tag for this template.", authorized = {RoleType.Admin})
125126
private String templateTag;
126127

127128
@Parameter(name = ApiConstants.DETAILS, type = CommandType.MAP, description = "Template details in key/value pairs using format details[i].keyname=keyvalue. Example: details[0].hypervisortoolsversion=xenserver61")

api/src/main/java/org/apache/cloudstack/api/command/user/template/ListTemplatesCmd.java

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@
2323
import java.util.ArrayList;
2424
import java.util.EnumSet;
2525
import java.util.List;
26+
import org.apache.cloudstack.acl.RoleType;
2627
import org.apache.cloudstack.api.APICommand;
2728
import org.apache.cloudstack.api.ApiCommandJobType;
2829
import org.apache.cloudstack.api.ApiConstants;
@@ -93,6 +94,9 @@ public class ListTemplatesCmd extends BaseListTaggedResourcesCmd implements User
9394
description = "comma separated list of template details requested, value can be a list of [ all, min]")
9495
private List<String> viewDetails;
9596

97+
@Parameter(name = ApiConstants.TEMPLATE_TAG, type = CommandType.STRING, description = "show templates with matching templatetag", authorized = {RoleType.Admin})
98+
private String templateTag;
99+
96100
/////////////////////////////////////////////////////
97101
/////////////////// Accessors ///////////////////////
98102
/////////////////////////////////////////////////////
@@ -161,6 +165,10 @@ public boolean listInReadyState() {
161165
return onlyReady;
162166
}
163167

168+
public String getTemplateTag() {
169+
return templateTag;
170+
}
171+
164172
/////////////////////////////////////////////////////
165173
/////////////// API Implementation///////////////////
166174
/////////////////////////////////////////////////////

api/src/main/java/org/apache/cloudstack/api/command/user/template/RegisterTemplateCmd.java

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@
2323
import java.util.List;
2424
import java.util.Map;
2525

26+
import org.apache.cloudstack.acl.RoleType;
2627
import org.apache.cloudstack.api.APICommand;
2728
import org.apache.cloudstack.api.ApiCommandJobType;
2829
import org.apache.cloudstack.api.ApiConstants;
@@ -127,7 +128,7 @@ public class RegisterTemplateCmd extends BaseCmd implements UserCmd {
127128
@Parameter(name = ApiConstants.CHECKSUM, type = CommandType.STRING, description = "the checksum value of this template. " + ApiConstants.CHECKSUM_PARAMETER_PREFIX_DESCRIPTION)
128129
private String checksum;
129130

130-
@Parameter(name = ApiConstants.TEMPLATE_TAG, type = CommandType.STRING, description = "the tag for this template.")
131+
@Parameter(name = ApiConstants.TEMPLATE_TAG, type = CommandType.STRING, description = "the tag for this template.", authorized = {RoleType.Admin})
131132
private String templateTag;
132133

133134
@Parameter(name = ApiConstants.PROJECT_ID, type = CommandType.UUID, entityType = ProjectResponse.class, description = "Register template for the project")

api/src/main/java/org/apache/cloudstack/api/command/user/template/UpdateTemplateCmd.java

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,12 +16,14 @@
1616
// under the License.
1717
package org.apache.cloudstack.api.command.user.template;
1818

19+
import org.apache.cloudstack.acl.RoleType;
20+
import org.apache.cloudstack.api.ApiConstants;
21+
import org.apache.cloudstack.api.Parameter;
1922
import org.apache.log4j.Logger;
2023

2124
import org.apache.cloudstack.api.APICommand;
2225
import org.apache.cloudstack.api.ApiErrorCode;
2326
import org.apache.cloudstack.api.BaseUpdateTemplateOrIsoCmd;
24-
import org.apache.cloudstack.api.Parameter;
2527
import org.apache.cloudstack.api.ResponseObject.ResponseView;
2628
import org.apache.cloudstack.api.ServerApiException;
2729
import org.apache.cloudstack.api.command.user.UserCmd;
@@ -43,6 +45,9 @@ public class UpdateTemplateCmd extends BaseUpdateTemplateOrIsoCmd implements Use
4345
@Parameter(name = "templatetype", type = CommandType.STRING, description = "the type of the template")
4446
private String templateType;
4547

48+
@Parameter(name = ApiConstants.TEMPLATE_TAG, type = CommandType.STRING, description = "the tag for this template.", authorized = {RoleType.Admin})
49+
private String templateTag;
50+
4651
/////////////////////////////////////////////////////
4752
/////////////////// Accessors ///////////////////////
4853
/////////////////////////////////////////////////////
@@ -56,6 +61,10 @@ public String getTemplateType() {
5661
return templateType;
5762
}
5863

64+
public String getTemplateTag() {
65+
return templateTag;
66+
}
67+
5968
/////////////////////////////////////////////////////
6069
/////////////// API Implementation///////////////////
6170
/////////////////////////////////////////////////////

plugins/host-allocators/random/src/main/java/com/cloud/agent/manager/allocator/impl/RandomAllocator.java

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@
2222

2323
import javax.inject.Inject;
2424

25+
import com.cloud.storage.VMTemplateVO;
2526
import org.apache.log4j.Logger;
2627
import org.springframework.stereotype.Component;
2728

@@ -66,11 +67,11 @@ public List<Host> allocateTo(VirtualMachineProfile vmProfile, DeploymentPlan pla
6667
}
6768

6869
String hostTag = offering.getHostTag();
70+
String message = "Looking for hosts in dc: " + dcId + " pod:" + podId + " cluster:" + clusterId;
6971
if (hostTag != null) {
70-
s_logger.debug("Looking for hosts in dc: " + dcId + " pod:" + podId + " cluster:" + clusterId + " having host tag:" + hostTag);
71-
} else {
72-
s_logger.debug("Looking for hosts in dc: " + dcId + " pod:" + podId + " cluster:" + clusterId);
72+
message = message + " having host tag:" + hostTag;
7373
}
74+
s_logger.debug(message);
7475

7576
// list all computing hosts, regardless of whether they support routing...it's random after all
7677
if (hostTag != null) {
@@ -79,6 +80,13 @@ public List<Host> allocateTo(VirtualMachineProfile vmProfile, DeploymentPlan pla
7980
hostsCopy.retainAll(_resourceMgr.listAllUpAndEnabledHosts(type, clusterId, podId, dcId));
8081
}
8182

83+
VMTemplateVO template = (VMTemplateVO)vmProfile.getTemplate();
84+
String templateTag = template.getTemplateTag();
85+
if (templateTag != null) {
86+
s_logger.debug(message + " having host tag:" + templateTag);
87+
hostsCopy.retainAll(_hostDao.listByHostTag(type, clusterId, podId, dcId, templateTag));
88+
}
89+
8290
s_logger.debug("Random Allocator found " + hostsCopy.size() + " hosts");
8391
if (hostsCopy.size() == 0) {
8492
return suitableHosts;

server/src/main/java/com/cloud/api/query/QueryManagerImpl.java

Lines changed: 15 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3348,6 +3348,10 @@ private Pair<List<TemplateJoinVO>, Integer> searchForTemplatesInternal(ListTempl
33483348
listAll = true;
33493349
}
33503350

3351+
if (cmd.getTemplateTag() != null && !(caller.getType() == Account.ACCOUNT_TYPE_ADMIN)) {
3352+
throw new InvalidParameterValueException("Parameter templatetag can only be specified by admins");
3353+
}
3354+
33513355
List<Long> permittedAccountIds = new ArrayList<Long>();
33523356
Ternary<Long, Boolean, ListProjectResourcesCriteria> domainIdRecursiveListProject = new Ternary<Long, Boolean, ListProjectResourcesCriteria>(cmd.getDomainId(), cmd.isRecursive(), null);
33533357
_accountMgr.buildACLSearchParameters(caller, id, cmd.getAccountName(), cmd.getProjectId(), permittedAccountIds, domainIdRecursiveListProject, listAll, false);
@@ -3361,12 +3365,12 @@ private Pair<List<TemplateJoinVO>, Integer> searchForTemplatesInternal(ListTempl
33613365
HypervisorType hypervisorType = HypervisorType.getType(cmd.getHypervisor());
33623366

33633367
return searchForTemplatesInternal(id, cmd.getTemplateName(), cmd.getKeyword(), templateFilter, false, null, cmd.getPageSizeVal(), cmd.getStartIndex(), cmd.getZoneId(), hypervisorType,
3364-
showDomr, cmd.listInReadyState(), permittedAccounts, caller, listProjectResourcesCriteria, tags, showRemovedTmpl, cmd.getIds(), parentTemplateId, cmd.getShowUnique());
3368+
showDomr, cmd.listInReadyState(), permittedAccounts, caller, listProjectResourcesCriteria, tags, showRemovedTmpl, cmd.getIds(), parentTemplateId, cmd.getShowUnique(), cmd.getTemplateTag());
33653369
}
33663370

33673371
private Pair<List<TemplateJoinVO>, Integer> searchForTemplatesInternal(Long templateId, String name, String keyword, TemplateFilter templateFilter, boolean isIso, Boolean bootable, Long pageSize,
33683372
Long startIndex, Long zoneId, HypervisorType hyperType, boolean showDomr, boolean onlyReady, List<Account> permittedAccounts, Account caller,
3369-
ListProjectResourcesCriteria listProjectResourcesCriteria, Map<String, String> tags, boolean showRemovedTmpl, List<Long> ids, Long parentTemplateId, Boolean showUnique) {
3373+
ListProjectResourcesCriteria listProjectResourcesCriteria, Map<String, String> tags, boolean showRemovedTmpl, List<Long> ids, Long parentTemplateId, Boolean showUnique, final String templateTag) {
33703374

33713375
// check if zone is configured, if not, just return empty list
33723376
List<HypervisorType> hypers = null;
@@ -3610,6 +3614,10 @@ else if (!template.isPublicTemplate() && caller.getType() != Account.ACCOUNT_TYP
36103614
sc.addAnd("dataCenterId", SearchCriteria.Op.SC, zoneSc);
36113615
}
36123616

3617+
if (templateTag != null && !templateTag.equalsIgnoreCase("")) {
3618+
sc.addAnd("templateTag", SearchCriteria.Op.EQ, templateTag);
3619+
}
3620+
36133621
if (parentTemplateId != null) {
36143622
sc.addAnd("parentTemplateId", SearchCriteria.Op.EQ, parentTemplateId);
36153623
}
@@ -3691,6 +3699,10 @@ private Pair<List<TemplateJoinVO>, Integer> searchForIsosInternal(ListIsosCmd cm
36913699
listAll = true;
36923700
}
36933701

3702+
if (cmd.getTemplateTag() != null && !(caller.getType() == Account.ACCOUNT_TYPE_ADMIN)) {
3703+
throw new InvalidParameterValueException("Parameter templatetag can only be specified by admins");
3704+
}
3705+
36943706
List<Long> permittedAccountIds = new ArrayList<Long>();
36953707
Ternary<Long, Boolean, ListProjectResourcesCriteria> domainIdRecursiveListProject = new Ternary<Long, Boolean, ListProjectResourcesCriteria>(cmd.getDomainId(), cmd.isRecursive(), null);
36963708
_accountMgr.buildACLSearchParameters(caller, id, cmd.getAccountName(), cmd.getProjectId(), permittedAccountIds, domainIdRecursiveListProject, listAll, false);
@@ -3703,7 +3715,7 @@ private Pair<List<TemplateJoinVO>, Integer> searchForIsosInternal(ListIsosCmd cm
37033715
HypervisorType hypervisorType = HypervisorType.getType(cmd.getHypervisor());
37043716

37053717
return searchForTemplatesInternal(cmd.getId(), cmd.getIsoName(), cmd.getKeyword(), isoFilter, true, cmd.isBootable(), cmd.getPageSizeVal(), cmd.getStartIndex(), cmd.getZoneId(),
3706-
hypervisorType, true, cmd.listInReadyState(), permittedAccounts, caller, listProjectResourcesCriteria, tags, showRemovedISO, null, null, cmd.getShowUnique());
3718+
hypervisorType, true, cmd.listInReadyState(), permittedAccounts, caller, listProjectResourcesCriteria, tags, showRemovedISO, null, null, cmd.getShowUnique(), cmd.getTemplateTag());
37073719
}
37083720

37093721
@Override

server/src/main/java/com/cloud/api/query/dao/TemplateJoinDaoImpl.java

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -233,7 +233,9 @@ public TemplateResponse newTemplateResponse(EnumSet<ApiConstants.DomainDetails>
233233
if (template.getSourceTemplateId() != null) {
234234
templateResponse.setSourceTemplateId(template.getSourceTemplateUuid());
235235
}
236-
templateResponse.setTemplateTag(template.getTemplateTag());
236+
if (view == ResponseView.Full) {
237+
templateResponse.setTemplateTag(template.getTemplateTag());
238+
}
237239

238240
if (template.getParentTemplateId() != null) {
239241
templateResponse.setParentTemplateId(template.getParentTemplateUuid());
@@ -394,7 +396,7 @@ public TemplateResponse newIsoResponse(TemplateJoinVO iso) {
394396
isAdmin = true;
395397
}
396398

397-
// If the user is an admin, add the template download status
399+
// If the user is an admin, add the template download status and template tag
398400
if (isAdmin || caller.getId() == iso.getAccountId()) {
399401
// add download status
400402
if (iso.getDownloadState() != Status.DOWNLOADED) {
@@ -440,6 +442,11 @@ public TemplateResponse newIsoResponse(TemplateJoinVO iso) {
440442

441443
isoResponse.setDirectDownload(iso.isDirectDownload());
442444

445+
// Update ISO template tag
446+
if (_accountService.isRootAdmin(caller.getId())) {
447+
isoResponse.setTemplateTag(iso.getTemplateTag());
448+
}
449+
443450
isoResponse.setObjectName("iso");
444451
return isoResponse;
445452

0 commit comments

Comments
 (0)