Skip to content

Commit f46250f

Browse files
shwstppryadvr
authored andcommitted
server: multiple domains for disk offering
This change allows associating multiple domains with a disk offering. ID of selected domains will be stored in disk_offering_details table as comma separated list with key 'domainids'. create, update disk offering API now accepts new parameter domainids to provide ID of domains. UI shows domains list as comma separated names string in offering details tab. Create disk offering form now allows multi-selection. Signed-off-by: Abhishek Kumar <abhishek.mrt22@gmail.com>
1 parent 1d26d03 commit f46250f

12 files changed

Lines changed: 233 additions & 96 deletions

File tree

api/src/main/java/org/apache/cloudstack/api/ApiConstants.java

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -112,6 +112,8 @@ public class ApiConstants {
112112
public static final String DOMAIN = "domain";
113113
public static final String DOMAIN_ID = "domainid";
114114
public static final String DOMAIN__ID = "domainId";
115+
public static final String DOMAIN_ID_LIST = "domainids";
116+
public static final String DOMAIN_NAME_LIST = "domainnames";
115117
public static final String DURATION = "duration";
116118
public static final String ELIGIBLE = "eligible";
117119
public static final String EMAIL = "email";

api/src/main/java/org/apache/cloudstack/api/command/admin/offering/CreateDiskOfferingCmd.java

Lines changed: 16 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -66,12 +66,22 @@ public class CreateDiskOfferingCmd extends BaseCmd {
6666
description = "the ID of the containing domain, null for public offerings")
6767
private Long domainId;
6868

69+
@Parameter(name = ApiConstants.DOMAIN_ID_LIST,
70+
type = CommandType.LIST,
71+
collectionType = CommandType.UUID,
72+
entityType = DomainResponse.class,
73+
required = false,
74+
description = "the ID of the domains offering is associated with, null for all domain offerings",
75+
since = "4.13")
76+
protected List<Long> domainIds;
77+
6978
@Parameter(name = ApiConstants.ZONE_ID_LIST,
70-
type=CommandType.LIST,
79+
type = CommandType.LIST,
7180
collectionType = CommandType.UUID,
7281
entityType = ZoneResponse.class,
7382
required = false,
74-
description = "the ID of the zones offering is associated with, null for all zone offerings")
83+
description = "the ID of the zones offering is associated with, null for all zone offerings",
84+
since = "4.13")
7585
protected List<Long> zoneIds;
7686

7787
@Parameter(name = ApiConstants.STORAGE_TYPE, type = CommandType.STRING, description = "the storage type of the disk offering. Values are local and shared.")
@@ -180,6 +190,10 @@ public Long getDomainId() {
180190
return domainId;
181191
}
182192

193+
public List<Long> getDomainIds() {
194+
return domainIds;
195+
}
196+
183197
public List<Long> getZoneIds() {
184198
return zoneIds;
185199
}

api/src/main/java/org/apache/cloudstack/api/command/admin/offering/UpdateDiskOfferingCmd.java

Lines changed: 16 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -69,12 +69,22 @@ public class UpdateDiskOfferingCmd extends BaseCmd {
6969
description = "the ID of the containing domain, null for public offerings")
7070
private Long domainId;
7171

72+
@Parameter(name = ApiConstants.DOMAIN_ID_LIST,
73+
type = CommandType.LIST,
74+
collectionType = CommandType.UUID,
75+
entityType = DomainResponse.class,
76+
required = false,
77+
description = "the ID of the domains offering is associated with, null for all domain offerings",
78+
since = "4.13")
79+
protected List<Long> domainIds;
80+
7281
@Parameter(name = ApiConstants.ZONE_ID_LIST,
73-
type=CommandType.LIST,
82+
type = CommandType.LIST,
7483
collectionType = CommandType.UUID,
7584
entityType = ZoneResponse.class,
7685
required = false,
77-
description = "the ID of the zones offering is associated with, null for all zone offerings")
86+
description = "the ID of the zones offering is associated with, null for all zone offerings",
87+
since = "4.13")
7888
protected List<Long> zoneIds;
7989

8090
/////////////////////////////////////////////////////
@@ -105,6 +115,10 @@ public Long getDomainId() {
105115
return domainId;
106116
}
107117

118+
public List<Long> getDomainIds() {
119+
return domainIds;
120+
}
121+
108122
public List<Long> getZoneIds() {
109123
return zoneIds;
110124
}

api/src/main/java/org/apache/cloudstack/api/command/user/offering/ListDiskOfferingsCmd.java

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,11 @@ public class ListDiskOfferingsCmd extends BaseListDomainResourcesCmd {
4343
@Parameter(name = ApiConstants.NAME, type = CommandType.STRING, description = "name of the disk offering")
4444
private String diskOfferingName;
4545

46-
@Parameter(name = ApiConstants.ZONE_ID, type = CommandType.UUID, entityType = ZoneResponse.class, description = "id of zone disk offering is associated with")
46+
@Parameter(name = ApiConstants.ZONE_ID,
47+
type = CommandType.UUID,
48+
entityType = ZoneResponse.class,
49+
description = "id of zone disk offering is associated with",
50+
since = "4.13")
4751
private Long zoneId;
4852

4953
/////////////////////////////////////////////////////

engine/schema/src/main/java/com/cloud/domain/dao/DomainDao.java

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,4 +40,6 @@ public interface DomainDao extends GenericDao<DomainVO, Long> {
4040
Set<Long> getDomainParentIds(long domainId);
4141

4242
List<Long> getDomainChildrenIds(String path);
43+
44+
List<DomainVO> list(Object[] ids);
4345
}

engine/schema/src/main/java/com/cloud/domain/dao/DomainDaoImpl.java

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -291,4 +291,11 @@ public Set<Long> getDomainParentIds(long domainId) {
291291
return parentDomains;
292292
}
293293

294+
@Override
295+
public List<DomainVO> list(Object[] ids) {
296+
SearchBuilder<DomainVO> sb = createSearchBuilder();
297+
SearchCriteria<DomainVO> sc = sb.create();
298+
sc.addAnd("id", SearchCriteria.Op.IN, ids);
299+
return listBy(sc);
300+
}
294301
}

engine/schema/src/main/java/com/cloud/storage/DiskOfferingVO.java

Lines changed: 19 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,7 @@ public class DiskOfferingVO implements DiskOffering {
5151
long id;
5252

5353
@Column(name = "domain_id")
54-
Long domainId;
54+
Long domainId = null;
5555

5656
@Column(name = "unique_name")
5757
private String uniqueName;
@@ -182,6 +182,24 @@ public DiskOfferingVO(Long domainId, String name, String displayText, Storage.Pr
182182
this.cacheMode = cacheMode;
183183
}
184184

185+
public DiskOfferingVO(String name, String displayText, Storage.ProvisioningType provisioningType, long diskSize, String tags, boolean isCustomized, Boolean isCustomizedIops,
186+
Long minIops, Long maxIops) {
187+
this.name = name;
188+
this.displayText = displayText;
189+
this.provisioningType = provisioningType;
190+
this.diskSize = diskSize;
191+
this.tags = tags;
192+
recreatable = false;
193+
type = Type.Disk;
194+
useLocalStorage = false;
195+
customized = isCustomized;
196+
uuid = UUID.randomUUID().toString();
197+
customizedIops = isCustomizedIops;
198+
this.minIops = minIops;
199+
this.maxIops = maxIops;
200+
state = State.Active;
201+
}
202+
185203
public DiskOfferingVO(Long domainId, String name, String displayText, Storage.ProvisioningType provisioningType, long diskSize, String tags, boolean isCustomized, Boolean isCustomizedIops,
186204
Long minIops, Long maxIops) {
187205
this.domainId = domainId;

server/src/main/java/com/cloud/acl/DomainChecker.java

Lines changed: 15 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -177,7 +177,8 @@ public boolean checkAccess(User user, ControlledEntity entity) throws Permission
177177
@Override
178178
public boolean checkAccess(Account account, DiskOffering dof, DataCenter zone) throws PermissionDeniedException {
179179
boolean isAccess = false;
180-
if (account == null || dof == null || dof.getDomainId() == null) {//public offering
180+
Map<String, String> details = null;
181+
if (account == null || dof == null) {//public offering
181182
isAccess = true;
182183
} else {
183184
//admin has all permissions
@@ -190,31 +191,26 @@ else if (_accountService.isNormalUser(account.getId())
190191
|| account.getType() == Account.ACCOUNT_TYPE_RESOURCE_DOMAIN_ADMIN
191192
|| _accountService.isDomainAdmin(account.getId())
192193
|| account.getType() == Account.ACCOUNT_TYPE_PROJECT) {
193-
if (account.getDomainId() == dof.getDomainId()) {
194-
isAccess = true; //disk offering and account at exact node
195-
} else {
196-
Domain domainRecord = _domainDao.findById(account.getDomainId());
197-
if (domainRecord != null) {
198-
while (true) {
199-
if (domainRecord.getId() == dof.getDomainId()) {
200-
//found as a child
201-
isAccess = true;
202-
}
203-
if (domainRecord.getParent() != null) {
204-
domainRecord = _domainDao.findById(domainRecord.getParent());
205-
} else {
206-
break;
207-
}
194+
details = diskOfferingDetailsDao.listDetailsKeyPairs(dof.getId());
195+
isAccess = true;
196+
if (details.containsKey(ApiConstants.DOMAIN_ID_LIST) &&
197+
!Strings.isNullOrEmpty(details.get(ApiConstants.DOMAIN_ID_LIST))) {
198+
List<String> domainIds = Arrays.asList(details.get(ApiConstants.DOMAIN_ID_LIST).split(","));
199+
for (String domainId : domainIds) {
200+
if (!_domainDao.isChildDomain(Long.valueOf(domainId), account.getDomainId())) {
201+
isAccess = false;
202+
break;
208203
}
209204
}
210205
}
211206
}
212207
}
213208

209+
// Check for zones
214210
if (isAccess && dof != null && zone != null) {
215-
Map<String, String> details = diskOfferingDetailsDao.listDetailsKeyPairs(dof.getId());
216-
if (details != null && !details.isEmpty() &&
217-
details.containsKey(ApiConstants.ZONE_ID_LIST) &&
211+
if (details == null)
212+
details = diskOfferingDetailsDao.listDetailsKeyPairs(dof.getId());
213+
if (details.containsKey(ApiConstants.ZONE_ID_LIST) &&
218214
!Strings.isNullOrEmpty(details.get(ApiConstants.ZONE_ID_LIST))) {
219215
List<String> zoneIds = Arrays.asList(details.get(ApiConstants.ZONE_ID_LIST).split(","));
220216
isAccess = zoneIds.contains(String.valueOf(zone.getId()));

server/src/main/java/com/cloud/api/ApiDBUtils.java

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1917,6 +1917,19 @@ public static DiskOfferingResponse newDiskOfferingResponse(DiskOfferingJoinVO of
19171917
if(diskOfferingResponse!=null) {
19181918
Map<String, String> details = s_diskOfferingDetailsDao.listDetailsKeyPairs(offering.getId());
19191919
if (details != null && !details.isEmpty()) {
1920+
if(details.containsKey(ApiConstants.DOMAIN_ID_LIST) &&
1921+
!Strings.isNullOrEmpty(details.get(ApiConstants.DOMAIN_ID_LIST))) {
1922+
String[] domainIdsArray = details.get(ApiConstants.DOMAIN_ID_LIST).split(",");
1923+
List<DomainVO> domains = s_domainDao.list(domainIdsArray);
1924+
List<String> domainIdsList = new ArrayList<>();
1925+
List<String> domainNamesList = new ArrayList<>();
1926+
for (DomainVO domain : domains) {
1927+
domainIdsList.add(domain.getUuid());
1928+
domainNamesList.add(domain.getName());
1929+
}
1930+
details.put(ApiConstants.DOMAIN_ID_LIST, String.join(",", domainIdsList));
1931+
details.put(ApiConstants.DOMAIN_NAME_LIST, String.join(", ", domainNamesList));
1932+
}
19201933
if(details.containsKey(ApiConstants.ZONE_ID_LIST) &&
19211934
!Strings.isNullOrEmpty(details.get(ApiConstants.ZONE_ID_LIST))) {
19221935
String[] zoneIdsArray = details.get(ApiConstants.ZONE_ID_LIST).split(",");

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

Lines changed: 40 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -2544,35 +2544,14 @@ private Pair<List<DiskOfferingJoinVO>, Integer> searchForDiskOfferingsInternal(L
25442544
}
25452545
}
25462546

2547-
List<Long> domainIds = null;
25482547
// For non-root users, only return all offerings for the user's domain,
25492548
// and everything above till root
25502549
if ((_accountMgr.isNormalUser(account.getId()) || _accountMgr.isDomainAdmin(account.getId())) || account.getType() == Account.ACCOUNT_TYPE_RESOURCE_DOMAIN_ADMIN) {
25512550
if (isRecursive) { // domain + all sub-domains
25522551
if (account.getType() == Account.ACCOUNT_TYPE_NORMAL) {
25532552
throw new InvalidParameterValueException("Only ROOT admins and Domain admins can list disk offerings with isrecursive=true");
25542553
}
2555-
DomainVO domainRecord = _domainDao.findById(account.getDomainId());
2556-
sc.addAnd("domainPath", SearchCriteria.Op.LIKE, domainRecord.getPath() + "%");
25572554
} else { // domain + all ancestors
2558-
// find all domain Id up to root domain for this account
2559-
domainIds = new ArrayList<Long>();
2560-
DomainVO domainRecord = _domainDao.findById(account.getDomainId());
2561-
if (domainRecord == null) {
2562-
s_logger.error("Could not find the domainId for account:" + account.getAccountName());
2563-
throw new CloudAuthenticationException("Could not find the domainId for account:" + account.getAccountName());
2564-
}
2565-
domainIds.add(domainRecord.getId());
2566-
while (domainRecord.getParent() != null) {
2567-
domainRecord = _domainDao.findById(domainRecord.getParent());
2568-
domainIds.add(domainRecord.getId());
2569-
}
2570-
2571-
SearchCriteria<DiskOfferingJoinVO> spc = _diskOfferingJoinDao.createSearchCriteria();
2572-
2573-
spc.addOr("domainId", SearchCriteria.Op.IN, domainIds.toArray());
2574-
spc.addOr("domainId", SearchCriteria.Op.NULL); // include public offering as where
2575-
sc.addAnd("domainId", SearchCriteria.Op.SC, spc);
25762555
sc.addAnd("systemUse", SearchCriteria.Op.EQ, false); // non-root users should not see system offering at all
25772556
}
25782557

@@ -2617,22 +2596,50 @@ private Pair<List<DiskOfferingJoinVO>, Integer> searchForDiskOfferingsInternal(L
26172596
*/
26182597

26192598
Pair<List<DiskOfferingJoinVO>, Integer> result = _diskOfferingJoinDao.searchAndCount(sc, searchFilter);
2620-
// If zoneid is passed remove offer offerings that are not associated with the zone
2621-
// TODO: Needs better approach
2622-
if (cmd.getZoneId() != null && result.first() != null && !result.first().isEmpty()) {
2623-
final Long zoneId = cmd.getZoneId();
2599+
// Remove offerings that are not associated with caller's domain and passed zone
2600+
// TODO: Better approach
2601+
if (result.first() != null && !result.first().isEmpty()) {
26242602
List<DiskOfferingJoinVO> offerings = result.first();
26252603
for (int i = offerings.size() - 1; i >= 0; i--) {
26262604
DiskOfferingJoinVO offering = offerings.get(i);
26272605
Map<String, String> details = diskOfferingDetailsDao.listDetailsKeyPairs(offering.getId());
2628-
if (details.containsKey(ApiConstants.ZONE_ID_LIST) &&
2629-
!Strings.isNullOrEmpty(details.get(ApiConstants.ZONE_ID_LIST))) {
2630-
String[] zoneIdsArray = details.get(ApiConstants.ZONE_ID_LIST).split(",");
2631-
List<Long> zoneIds = new ArrayList<>();
2632-
for (String zId : zoneIdsArray)
2633-
zoneIds.add(Long.valueOf(zId.trim()));
2634-
if (!zoneIds.contains(zoneId)) {
2635-
offerings.remove(i);
2606+
boolean toRemove = isRecursive;
2607+
if (account.getType() != Account.ACCOUNT_TYPE_ADMIN &&
2608+
details.containsKey(ApiConstants.DOMAIN_ID_LIST) &&
2609+
!Strings.isNullOrEmpty(details.get(ApiConstants.DOMAIN_ID_LIST))) {
2610+
toRemove = true;
2611+
String[] domainIdsArray = details.get(ApiConstants.DOMAIN_ID_LIST).split(",");
2612+
for (String dIdStr : domainIdsArray) {
2613+
Long dId = Long.valueOf(dIdStr.trim());
2614+
if(isRecursive) {
2615+
if (_domainDao.isChildDomain(account.getDomainId(), dId)) {
2616+
toRemove = false;
2617+
break;
2618+
}
2619+
} else {
2620+
if (_domainDao.isChildDomain(dId, account.getDomainId())) {
2621+
toRemove = false;
2622+
break;
2623+
}
2624+
}
2625+
}
2626+
}
2627+
if (toRemove) {
2628+
offerings.remove(i);
2629+
} else {
2630+
// If zoneid is passed remove offerings that are not associated with the zone
2631+
if (cmd.getZoneId() != null) {
2632+
final Long zoneId = cmd.getZoneId();
2633+
if (details.containsKey(ApiConstants.ZONE_ID_LIST) &&
2634+
!Strings.isNullOrEmpty(details.get(ApiConstants.ZONE_ID_LIST))) {
2635+
String[] zoneIdsArray = details.get(ApiConstants.ZONE_ID_LIST).split(",");
2636+
List<Long> zoneIds = new ArrayList<>();
2637+
for (String zId : zoneIdsArray)
2638+
zoneIds.add(Long.valueOf(zId.trim()));
2639+
if (!zoneIds.contains(zoneId)) {
2640+
offerings.remove(i);
2641+
}
2642+
}
26362643
}
26372644
}
26382645
}

0 commit comments

Comments
 (0)