cloudstack-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From weiz...@apache.org
Subject git commit: updated refs/heads/master to af2f218
Date Mon, 01 Dec 2014 12:04:07 GMT
Repository: cloudstack
Updated Branches:
  refs/heads/master 45423c737 -> af2f21894


CLOUDSTACK-7983: Create Disk/Service Offering for Domain Admin


Project: http://git-wip-us.apache.org/repos/asf/cloudstack/repo
Commit: http://git-wip-us.apache.org/repos/asf/cloudstack/commit/af2f2189
Tree: http://git-wip-us.apache.org/repos/asf/cloudstack/tree/af2f2189
Diff: http://git-wip-us.apache.org/repos/asf/cloudstack/diff/af2f2189

Branch: refs/heads/master
Commit: af2f21894ce061faadc8cec29b901719303a29dc
Parents: 45423c7
Author: Wei Zhou <w.zhou@tech.leaseweb.com>
Authored: Mon Dec 1 13:03:37 2014 +0100
Committer: Wei Zhou <w.zhou@tech.leaseweb.com>
Committed: Mon Dec 1 13:03:37 2014 +0100

----------------------------------------------------------------------
 api/src/com/cloud/user/AccountService.java      |   6 +
 .../user/offering/ListDiskOfferingsCmd.java     |  12 +-
 .../user/offering/ListServiceOfferingsCmd.java  |  17 +--
 client/tomcatconf/commands.properties.in        |  12 +-
 .../contrail/management/MockAccountManager.java |  12 ++
 server/src/com/cloud/acl/DomainChecker.java     |   2 +-
 .../com/cloud/api/query/QueryManagerImpl.java   | 107 ++++++++--------
 .../cloud/api/query/vo/DiskOfferingJoinVO.java  |   4 +-
 .../configuration/ConfigurationManagerImpl.java | 121 ++++++++++++++++++-
 .../src/com/cloud/user/AccountManagerImpl.java  |  34 ++++++
 server/src/com/cloud/vm/UserVmManagerImpl.java  |  17 +++
 .../com/cloud/user/MockAccountManagerImpl.java  |  12 ++
 ui/scripts/cloudStack.js                        |   2 +-
 ui/scripts/configuration.js                     |  54 +++++++--
 14 files changed, 317 insertions(+), 95 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/cloudstack/blob/af2f2189/api/src/com/cloud/user/AccountService.java
----------------------------------------------------------------------
diff --git a/api/src/com/cloud/user/AccountService.java b/api/src/com/cloud/user/AccountService.java
index 2785264..75f95ce 100644
--- a/api/src/com/cloud/user/AccountService.java
+++ b/api/src/com/cloud/user/AccountService.java
@@ -25,6 +25,8 @@ import org.apache.cloudstack.api.command.admin.user.RegisterCmd;
 
 import com.cloud.domain.Domain;
 import com.cloud.exception.PermissionDeniedException;
+import com.cloud.offering.DiskOffering;
+import com.cloud.offering.ServiceOffering;
 
 public interface AccountService {
 
@@ -111,6 +113,10 @@ public interface AccountService {
 
     void checkAccess(Account account, AccessType accessType, boolean sameOwner, ControlledEntity... entities) throws PermissionDeniedException;
 
+    void checkAccess(Account account, ServiceOffering so) throws PermissionDeniedException;
+
+    void checkAccess(Account account, DiskOffering dof) throws PermissionDeniedException;
+
     void checkAccess(Account account, AccessType accessType, boolean sameOwner, String apiName,
             ControlledEntity... entities) throws PermissionDeniedException;
 

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/af2f2189/api/src/org/apache/cloudstack/api/command/user/offering/ListDiskOfferingsCmd.java
----------------------------------------------------------------------
diff --git a/api/src/org/apache/cloudstack/api/command/user/offering/ListDiskOfferingsCmd.java b/api/src/org/apache/cloudstack/api/command/user/offering/ListDiskOfferingsCmd.java
index 0e4806a..e5f92c9 100644
--- a/api/src/org/apache/cloudstack/api/command/user/offering/ListDiskOfferingsCmd.java
+++ b/api/src/org/apache/cloudstack/api/command/user/offering/ListDiskOfferingsCmd.java
@@ -20,15 +20,14 @@ import org.apache.log4j.Logger;
 
 import org.apache.cloudstack.api.APICommand;
 import org.apache.cloudstack.api.ApiConstants;
-import org.apache.cloudstack.api.BaseListCmd;
+import org.apache.cloudstack.api.BaseListDomainResourcesCmd;
 import org.apache.cloudstack.api.Parameter;
 import org.apache.cloudstack.api.response.DiskOfferingResponse;
-import org.apache.cloudstack.api.response.DomainResponse;
 import org.apache.cloudstack.api.response.ListResponse;
 
 @APICommand(name = "listDiskOfferings", description = "Lists all available disk offerings.", responseObject = DiskOfferingResponse.class,
         requestHasSensitiveInfo = false, responseHasSensitiveInfo = false)
-public class ListDiskOfferingsCmd extends BaseListCmd {
+public class ListDiskOfferingsCmd extends BaseListDomainResourcesCmd {
     public static final Logger s_logger = Logger.getLogger(ListDiskOfferingsCmd.class.getName());
 
     private static final String s_name = "listdiskofferingsresponse";
@@ -37,9 +36,6 @@ public class ListDiskOfferingsCmd extends BaseListCmd {
     //////////////// API parameters /////////////////////
     /////////////////////////////////////////////////////
 
-    @Parameter(name = ApiConstants.DOMAIN_ID, type = CommandType.UUID, entityType = DomainResponse.class, description = "the ID of the domain of the disk offering.")
-    private Long domainId;
-
     @Parameter(name = ApiConstants.ID, type = CommandType.UUID, entityType = DiskOfferingResponse.class, description = "ID of the disk offering")
     private Long id;
 
@@ -50,10 +46,6 @@ public class ListDiskOfferingsCmd extends BaseListCmd {
     /////////////////// Accessors ///////////////////////
     /////////////////////////////////////////////////////
 
-    public Long getDomainId() {
-        return domainId;
-    }
-
     public Long getId() {
         return id;
     }

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/af2f2189/api/src/org/apache/cloudstack/api/command/user/offering/ListServiceOfferingsCmd.java
----------------------------------------------------------------------
diff --git a/api/src/org/apache/cloudstack/api/command/user/offering/ListServiceOfferingsCmd.java b/api/src/org/apache/cloudstack/api/command/user/offering/ListServiceOfferingsCmd.java
index abeebcb..4b74819 100644
--- a/api/src/org/apache/cloudstack/api/command/user/offering/ListServiceOfferingsCmd.java
+++ b/api/src/org/apache/cloudstack/api/command/user/offering/ListServiceOfferingsCmd.java
@@ -20,16 +20,15 @@ import org.apache.log4j.Logger;
 
 import org.apache.cloudstack.api.APICommand;
 import org.apache.cloudstack.api.ApiConstants;
-import org.apache.cloudstack.api.BaseListCmd;
+import org.apache.cloudstack.api.BaseListDomainResourcesCmd;
 import org.apache.cloudstack.api.Parameter;
-import org.apache.cloudstack.api.response.DomainResponse;
 import org.apache.cloudstack.api.response.ListResponse;
 import org.apache.cloudstack.api.response.ServiceOfferingResponse;
 import org.apache.cloudstack.api.response.UserVmResponse;
 
 @APICommand(name = "listServiceOfferings", description = "Lists all available service offerings.", responseObject = ServiceOfferingResponse.class,
         requestHasSensitiveInfo = false, responseHasSensitiveInfo = false)
-public class ListServiceOfferingsCmd extends BaseListCmd {
+public class ListServiceOfferingsCmd extends BaseListDomainResourcesCmd {
     public static final Logger s_logger = Logger.getLogger(ListServiceOfferingsCmd.class.getName());
 
     private static final String s_name = "listserviceofferingsresponse";
@@ -50,13 +49,7 @@ public class ListServiceOfferingsCmd extends BaseListCmd {
                description = "the ID of the virtual machine. Pass this in if you want to see the available service offering that a virtual machine can be changed to.")
     private Long virtualMachineId;
 
-    @Parameter(name = ApiConstants.DOMAIN_ID,
-               type = CommandType.UUID,
-               entityType = DomainResponse.class,
-               description = "the ID of the domain associated with the service offering")
-    private Long domainId;
-
-    @Parameter(name = ApiConstants.IS_SYSTEM_OFFERING, type = CommandType.BOOLEAN, description = "is this a system vm offering")
+    @Parameter(name=ApiConstants.IS_SYSTEM_OFFERING, type=CommandType.BOOLEAN, description="is this a system vm offering")
     private Boolean isSystem;
 
     @Parameter(name = ApiConstants.SYSTEM_VM_TYPE,
@@ -80,10 +73,6 @@ public class ListServiceOfferingsCmd extends BaseListCmd {
         return virtualMachineId;
     }
 
-    public Long getDomainId() {
-        return domainId;
-    }
-
     public Boolean getIsSystem() {
         return isSystem == null ? false : isSystem;
     }

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/af2f2189/client/tomcatconf/commands.properties.in
----------------------------------------------------------------------
diff --git a/client/tomcatconf/commands.properties.in b/client/tomcatconf/commands.properties.in
index a87d167..36d735d 100644
--- a/client/tomcatconf/commands.properties.in
+++ b/client/tomcatconf/commands.properties.in
@@ -131,15 +131,15 @@ updateGuestOsMapping=1
 removeGuestOsMapping=1
 
 #### service offering commands
-createServiceOffering=1
-deleteServiceOffering=1
-updateServiceOffering=1
+createServiceOffering=7
+deleteServiceOffering=7
+updateServiceOffering=7
 listServiceOfferings=15
 
 #### disk offering commands
-createDiskOffering=1
-updateDiskOffering=1
-deleteDiskOffering=1
+createDiskOffering=7
+updateDiskOffering=7
+deleteDiskOffering=7
 listDiskOfferings=15
 
 #### vlan commands

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/af2f2189/plugins/network-elements/juniper-contrail/test/org/apache/cloudstack/network/contrail/management/MockAccountManager.java
----------------------------------------------------------------------
diff --git a/plugins/network-elements/juniper-contrail/test/org/apache/cloudstack/network/contrail/management/MockAccountManager.java b/plugins/network-elements/juniper-contrail/test/org/apache/cloudstack/network/contrail/management/MockAccountManager.java
index ddc6df1..daeb6bd 100644
--- a/plugins/network-elements/juniper-contrail/test/org/apache/cloudstack/network/contrail/management/MockAccountManager.java
+++ b/plugins/network-elements/juniper-contrail/test/org/apache/cloudstack/network/contrail/management/MockAccountManager.java
@@ -42,6 +42,8 @@ import com.cloud.domain.Domain;
 import com.cloud.exception.ConcurrentOperationException;
 import com.cloud.exception.PermissionDeniedException;
 import com.cloud.exception.ResourceUnavailableException;
+import com.cloud.offering.DiskOffering;
+import com.cloud.offering.ServiceOffering;
 import com.cloud.projects.Project.ListProjectResourcesCriteria;
 import com.cloud.user.Account;
 import com.cloud.user.AccountManager;
@@ -401,4 +403,14 @@ public class MockAccountManager extends ManagerBase implements AccountManager {
         // TODO Auto-generated method stub
         return null;
     }
+
+    @Override
+    public void checkAccess(Account account, ServiceOffering so) throws PermissionDeniedException {
+        // TODO Auto-generated method stub
+    }
+
+    @Override
+    public void checkAccess(Account account, DiskOffering dof) throws PermissionDeniedException {
+        // TODO Auto-generated method stub
+    }
 }

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/af2f2189/server/src/com/cloud/acl/DomainChecker.java
----------------------------------------------------------------------
diff --git a/server/src/com/cloud/acl/DomainChecker.java b/server/src/com/cloud/acl/DomainChecker.java
index a6bdce4..a5ca9cc 100644
--- a/server/src/com/cloud/acl/DomainChecker.java
+++ b/server/src/com/cloud/acl/DomainChecker.java
@@ -170,7 +170,7 @@ public class DomainChecker extends AdapterBase implements SecurityChecker {
 
     @Override
     public boolean checkAccess(Account account, DiskOffering dof) throws PermissionDeniedException {
-        if (account == null || dof.getDomainId() == null) {//public offering
+        if (account == null || dof == null || dof.getDomainId() == null) {//public offering
             return true;
         } else {
             //admin has all permissions

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/af2f2189/server/src/com/cloud/api/query/QueryManagerImpl.java
----------------------------------------------------------------------
diff --git a/server/src/com/cloud/api/query/QueryManagerImpl.java b/server/src/com/cloud/api/query/QueryManagerImpl.java
index 418b81c..a0ad0ea 100644
--- a/server/src/com/cloud/api/query/QueryManagerImpl.java
+++ b/server/src/com/cloud/api/query/QueryManagerImpl.java
@@ -2422,6 +2422,7 @@ public class QueryManagerImpl extends ManagerBase implements QueryService {
         Object keyword = cmd.getKeyword();
         Long domainId = cmd.getDomainId();
         Boolean isRootAdmin = _accountMgr.isRootAdmin(account.getAccountId());
+        Boolean isRecursive = cmd.isRecursive();
         // Keeping this logic consistent with domain specific zones
         // if a domainId is provided, we just return the disk offering
         // associated with this domain
@@ -2444,32 +2445,32 @@ public class QueryManagerImpl extends ManagerBase implements QueryService {
         // and everything above till root
         if ((_accountMgr.isNormalUser(account.getId()) || _accountMgr.isDomainAdmin(account.getId()))
                 || account.getType() == Account.ACCOUNT_TYPE_RESOURCE_DOMAIN_ADMIN) {
-            // find all domain Id up to root domain for this account
-            domainIds = new ArrayList<Long>();
-            DomainVO domainRecord = _domainDao.findById(account.getDomainId());
-            if (domainRecord == null) {
-                s_logger.error("Could not find the domainId for account:" + account.getAccountName());
-                throw new CloudAuthenticationException("Could not find the domainId for account:" + account.getAccountName());
-            }
-            domainIds.add(domainRecord.getId());
-            while (domainRecord.getParent() != null) {
-                domainRecord = _domainDao.findById(domainRecord.getParent());
+            if (isRecursive) { // domain + all sub-domains
+                if (account.getType() == Account.ACCOUNT_TYPE_NORMAL)
+                    throw new InvalidParameterValueException("Only ROOT admins and Domain admins can list disk offerings with isrecursive=true");
+                DomainVO domainRecord = _domainDao.findById(account.getDomainId());
+                sc.addAnd("domainPath", SearchCriteria.Op.LIKE, domainRecord.getPath() + "%");
+            } else { // domain + all ancestors
+                // find all domain Id up to root domain for this account
+                domainIds = new ArrayList<Long>();
+                DomainVO domainRecord = _domainDao.findById(account.getDomainId());
+                if ( domainRecord == null ){
+                    s_logger.error("Could not find the domainId for account:" + account.getAccountName());
+                    throw new CloudAuthenticationException("Could not find the domainId for account:" + account.getAccountName());
+                }
                 domainIds.add(domainRecord.getId());
-            }
+                while (domainRecord.getParent() != null ){
+                    domainRecord = _domainDao.findById(domainRecord.getParent());
+                    domainIds.add(domainRecord.getId());
+                }
 
-            SearchCriteria<DiskOfferingJoinVO> spc = _diskOfferingJoinDao.createSearchCriteria();
+                SearchCriteria<DiskOfferingJoinVO> spc = _diskOfferingJoinDao.createSearchCriteria();
 
-            spc.addOr("domainId", SearchCriteria.Op.IN, domainIds.toArray());
-            spc.addOr("domainId", SearchCriteria.Op.NULL); // include public
-            // offering as where
-            sc.addAnd("domainId", SearchCriteria.Op.SC, spc);
-            sc.addAnd("displayOffering", SearchCriteria.Op.EQ, 1);
-            sc.addAnd("systemUse", SearchCriteria.Op.EQ, false); // non-root
-            // users should
-            // not see
-            // system
-            // offering at
-            // all
+                spc.addOr("domainId", SearchCriteria.Op.IN, domainIds.toArray());
+                spc.addOr("domainId", SearchCriteria.Op.NULL); // include public offering as where
+                sc.addAnd("domainId", SearchCriteria.Op.SC, spc);
+                sc.addAnd("systemUse", SearchCriteria.Op.EQ, false); // non-root users should not see system offering at all
+            }
 
         }
 
@@ -2563,6 +2564,7 @@ public class QueryManagerImpl extends ManagerBase implements QueryService {
         Boolean isSystem = cmd.getIsSystem();
         String vmTypeStr = cmd.getSystemVmType();
         ServiceOfferingVO currentVmOffering = null;
+        Boolean isRecursive = cmd.isRecursive();
 
         SearchCriteria<ServiceOfferingJoinVO> sc = _srvOfferingJoinDao.createSearchCriteria();
         if (!_accountMgr.isRootAdmin(caller.getId()) && isSystem) {
@@ -2611,35 +2613,40 @@ public class QueryManagerImpl extends ManagerBase implements QueryService {
             if (isSystem) {
                 throw new InvalidParameterValueException("Only root admins can access system's offering");
             }
-            // find all domain Id up to root domain for this account
-            List<Long> domainIds = new ArrayList<Long>();
-            DomainVO domainRecord;
-            if (vmId != null) {
-                 UserVmVO vmInstance = _userVmDao.findById(vmId);
-                 domainRecord = _domainDao.findById(vmInstance.getDomainId());
-                if (domainRecord == null) {
-                     s_logger.error("Could not find the domainId for vmId:" + vmId);
-                     throw new CloudAuthenticationException("Could not find the domainId for vmId:" + vmId);
-                 }
-            } else {
-                 domainRecord = _domainDao.findById(caller.getDomainId());
-                if (domainRecord == null) {
-                s_logger.error("Could not find the domainId for account:" + caller.getAccountName());
-                     throw new CloudAuthenticationException("Could not find the domainId for account:" + caller.getAccountName());
-                 }
-            }
-            domainIds.add(domainRecord.getId());
-            while (domainRecord.getParent() != null) {
-                domainRecord = _domainDao.findById(domainRecord.getParent());
+            if (isRecursive) { // domain + all sub-domains
+                if (caller.getType() == Account.ACCOUNT_TYPE_NORMAL)
+                    throw new InvalidParameterValueException("Only ROOT admins and Domain admins can list service offerings with isrecursive=true");
+                DomainVO domainRecord = _domainDao.findById(caller.getDomainId());
+                sc.addAnd("domainPath", SearchCriteria.Op.LIKE, domainRecord.getPath() + "%");
+            } else { // domain + all ancestors
+                // find all domain Id up to root domain for this account
+                List<Long> domainIds = new ArrayList<Long>();
+                DomainVO domainRecord;
+                if (vmId != null) {
+                    UserVmVO vmInstance = _userVmDao.findById(vmId);
+                    domainRecord = _domainDao.findById(vmInstance.getDomainId());
+                    if ( domainRecord == null ){
+                        s_logger.error("Could not find the domainId for vmId:" + vmId);
+                        throw new CloudAuthenticationException("Could not find the domainId for vmId:" + vmId);
+                    }
+                } else {
+                    domainRecord = _domainDao.findById(caller.getDomainId());
+                    if ( domainRecord == null ){
+                        s_logger.error("Could not find the domainId for account:" + caller.getAccountName());
+                        throw new CloudAuthenticationException("Could not find the domainId for account:" + caller.getAccountName());
+                    }
+                }
                 domainIds.add(domainRecord.getId());
-            }
-            SearchCriteria<ServiceOfferingJoinVO> spc = _srvOfferingJoinDao.createSearchCriteria();
-
-            spc.addOr("domainId", SearchCriteria.Op.IN, domainIds.toArray());
-            spc.addOr("domainId", SearchCriteria.Op.NULL); // include public
-            // offering as where
-            sc.addAnd("domainId", SearchCriteria.Op.SC, spc);
+                while (domainRecord.getParent() != null ){
+                    domainRecord = _domainDao.findById(domainRecord.getParent());
+                    domainIds.add(domainRecord.getId());
+                }
 
+                SearchCriteria<ServiceOfferingJoinVO> spc = _srvOfferingJoinDao.createSearchCriteria();
+                spc.addOr("domainId", SearchCriteria.Op.IN, domainIds.toArray());
+                spc.addOr("domainId", SearchCriteria.Op.NULL); // include public offering as well
+                sc.addAnd("domainId", SearchCriteria.Op.SC, spc);
+             }
         } else {
             // for root users
             if (caller.getDomainId() != 1 && isSystem) { // NON ROOT admin

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/af2f2189/server/src/com/cloud/api/query/vo/DiskOfferingJoinVO.java
----------------------------------------------------------------------
diff --git a/server/src/com/cloud/api/query/vo/DiskOfferingJoinVO.java b/server/src/com/cloud/api/query/vo/DiskOfferingJoinVO.java
index 1a1c787..58eeef9 100644
--- a/server/src/com/cloud/api/query/vo/DiskOfferingJoinVO.java
+++ b/server/src/com/cloud/api/query/vo/DiskOfferingJoinVO.java
@@ -111,10 +111,10 @@ public class DiskOfferingJoinVO extends BaseViewVO implements InternalIdentity,
     private String domainUuid;
 
     @Column(name = "domain_name")
-    private final String domainName = null;
+    private String domainName = null;
 
     @Column(name = "domain_path")
-    private final String domainPath = null;
+    private String domainPath = null;
 
     @Column(name = "display_offering")
     boolean displayOffering;

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/af2f2189/server/src/com/cloud/configuration/ConfigurationManagerImpl.java
----------------------------------------------------------------------
diff --git a/server/src/com/cloud/configuration/ConfigurationManagerImpl.java b/server/src/com/cloud/configuration/ConfigurationManagerImpl.java
index 918dd93..3d5214d 100644
--- a/server/src/com/cloud/configuration/ConfigurationManagerImpl.java
+++ b/server/src/com/cloud/configuration/ConfigurationManagerImpl.java
@@ -190,6 +190,7 @@ import com.cloud.user.AccountVO;
 import com.cloud.user.ResourceLimitService;
 import com.cloud.user.User;
 import com.cloud.user.dao.AccountDao;
+import com.cloud.user.dao.UserDao;
 import com.cloud.utils.NumbersUtil;
 import com.cloud.utils.Pair;
 import com.cloud.utils.StringUtils;
@@ -287,6 +288,8 @@ public class ConfigurationManagerImpl extends ManagerBase implements Configurati
     @Inject
     VpcManager _vpcMgr;
     @Inject
+    UserDao _userDao;
+    @Inject
     PortableIpRangeDao _portableIpRangeDao;
     @Inject
     RegionDao _regionDao;
@@ -2103,9 +2106,30 @@ public class ConfigurationManagerImpl extends ManagerBase implements Configurati
             Integer networkRate, String deploymentPlanner, Map<String, String> details, Boolean isCustomizedIops, Long minIops, Long maxIops,
             Long bytesReadRate, Long bytesWriteRate, Long iopsReadRate, Long iopsWriteRate, Integer hypervisorSnapshotReserve) {
 
+        // Check if user exists in the system
+        User user = _userDao.findById(userId);
+        if (user == null || user.getRemoved() != null) {
+            throw new InvalidParameterValueException("Unable to find active user by id " + userId);
+        }
+        Account account = _accountDao.findById(user.getAccountId());
+        if (account.getType() == Account.ACCOUNT_TYPE_DOMAIN_ADMIN) {
+            if (domainId == null) {
+                throw new InvalidParameterValueException("Unable to create public service offering by id " + userId + " because it is domain-admin");
+            }
+            if (tags != null || hostTag != null) {
+                throw new InvalidParameterValueException("Unable to create service offering with storage tags or host tags by id " + userId + " because it is domain-admin");
+            }
+            if (! _domainDao.isChildDomain(account.getDomainId(), domainId)) {
+                throw new InvalidParameterValueException("Unable to create service offering by another domain admin with id " + userId);
+            }
+        } else if (account.getType() != Account.ACCOUNT_TYPE_ADMIN) {
+            throw new InvalidParameterValueException("Unable to create service offering by id " + userId + " because it is not root-admin or domain-admin");
+        }
+
         ProvisioningType typedProvisioningType = ProvisioningType.getProvisioningType(provisioningType);
 
         tags = StringUtils.cleanupTags(tags);
+
         ServiceOfferingVO offering = new ServiceOfferingVO(name, cpu, ramSize, speed, networkRate, null, offerHA,
                 limitResourceUse, volatileVm, displayText, typedProvisioningType, localStorageRequired, false, tags, isSystem, vmType,
                 domainId, hostTag, deploymentPlanner);
@@ -2220,6 +2244,22 @@ public class ConfigurationManagerImpl extends ManagerBase implements Configurati
             throw new InvalidParameterValueException("unable to find service offering " + id);
         }
 
+        User user = _userDao.findById(userId);
+        if (user == null || user.getRemoved() != null) {
+            throw new InvalidParameterValueException("Unable to find active user by id " + userId);
+        }
+        Account account = _accountDao.findById(user.getAccountId());
+        if (account.getType() == Account.ACCOUNT_TYPE_DOMAIN_ADMIN) {
+            if (offeringHandle.getDomainId() == null) {
+                throw new InvalidParameterValueException("Unable to update public service offering by id " + userId + " because it is domain-admin");
+            }
+            if (! _domainDao.isChildDomain(account.getDomainId(), offeringHandle.getDomainId() )) {
+                throw new InvalidParameterValueException("Unable to update service offering by another domain admin with id " + userId);
+            }
+        } else if (account.getType() != Account.ACCOUNT_TYPE_ADMIN) {
+            throw new InvalidParameterValueException("Unable to update service offering by id " + userId + " because it is not root-admin or domain-admin");
+        }
+
         boolean updateNeeded = (name != null || displayText != null || sortKey != null);
         if (!updateNeeded) {
             return _serviceOfferingDao.findById(id);
@@ -2272,7 +2312,7 @@ public class ConfigurationManagerImpl extends ManagerBase implements Configurati
         }
     }
 
-    protected DiskOfferingVO createDiskOffering(Long domainId, String name, String description, String provisioningType,
+    protected DiskOfferingVO createDiskOffering(Long userId, Long domainId, String name, String description, String provisioningType,
             Long numGibibytes, String tags, boolean isCustomized, boolean localStorageRequired,
             boolean isDisplayOfferingEnabled, Boolean isCustomizedIops, Long minIops, Long maxIops,
             Long bytesReadRate, Long bytesWriteRate, Long iopsReadRate, Long iopsWriteRate,
@@ -2325,6 +2365,26 @@ public class ConfigurationManagerImpl extends ManagerBase implements Configurati
             maxIops = null;
         }
 
+        // Check if user exists in the system
+        User user = _userDao.findById(userId);
+        if (user == null || user.getRemoved() != null) {
+            throw new InvalidParameterValueException("Unable to find active user by id " + userId);
+        }
+        Account account = _accountDao.findById(user.getAccountId());
+        if (account.getType() == Account.ACCOUNT_TYPE_DOMAIN_ADMIN) {
+            if (domainId == null) {
+                throw new InvalidParameterValueException("Unable to create public disk offering by id " + userId + " because it is domain-admin");
+            }
+            if (tags != null) {
+                throw new InvalidParameterValueException("Unable to create disk offering with storage tags by id " + userId + " because it is domain-admin");
+            }
+            if (! _domainDao.isChildDomain(account.getDomainId(), domainId)) {
+                throw new InvalidParameterValueException("Unable to create disk offering by another domain admin with id " + userId);
+            }
+        } else if (account.getType() != Account.ACCOUNT_TYPE_ADMIN) {
+            throw new InvalidParameterValueException("Unable to create disk offering by id " + userId + " because it is not root-admin or domain-admin");
+        }
+
         tags = StringUtils.cleanupTags(tags);
         DiskOfferingVO newDiskOffering = new DiskOfferingVO(domainId, name, description, typedProvisioningType, diskSize, tags, isCustomized,
                 isCustomizedIops, minIops, maxIops);
@@ -2401,7 +2461,8 @@ public class ConfigurationManagerImpl extends ManagerBase implements Configurati
         Long iopsWriteRate = cmd.getIopsWriteRate();
         Integer hypervisorSnapshotReserve = cmd.getHypervisorSnapshotReserve();
 
-        return createDiskOffering(domainId, name, description, provisioningType, numGibibytes, tags, isCustomized,
+        Long userId = CallContext.current().getCallingUserId();
+        return createDiskOffering(userId, domainId, name, description, provisioningType, numGibibytes, tags, isCustomized,
                 localStorageRequired, isDisplayOfferingEnabled, isCustomizedIops, minIops,
                 maxIops, bytesReadRate, bytesWriteRate, iopsReadRate, iopsWriteRate, hypervisorSnapshotReserve);
     }
@@ -2422,6 +2483,26 @@ public class ConfigurationManagerImpl extends ManagerBase implements Configurati
             throw new InvalidParameterValueException("Unable to find disk offering by id " + diskOfferingId);
         }
 
+        Long userId = CallContext.current().getCallingUserId();
+        if (userId == null) {
+            userId = Long.valueOf(User.UID_SYSTEM);
+        }
+        User user = _userDao.findById(userId);
+        if (user == null || user.getRemoved() != null) {
+            throw new InvalidParameterValueException("Unable to find active user by id " + userId);
+        }
+        Account account = _accountDao.findById(user.getAccountId());
+        if (account.getType() == Account.ACCOUNT_TYPE_DOMAIN_ADMIN) {
+            if (diskOfferingHandle.getDomainId() == null) {
+                throw new InvalidParameterValueException("Unable to update public disk offering by id " + userId + " because it is domain-admin");
+            }
+            if (! _domainDao.isChildDomain(account.getDomainId(), diskOfferingHandle.getDomainId() )) {
+                throw new InvalidParameterValueException("Unable to update disk offering by another domain admin with id " + userId);
+            }
+        } else if (account.getType() != Account.ACCOUNT_TYPE_ADMIN) {
+            throw new InvalidParameterValueException("Unable to update disk offering by id " + userId + " because it is not root-admin or domain-admin");
+        }
+
         boolean updateNeeded = (name != null || displayText != null || sortKey != null || displayDiskOffering != null);
         if (!updateNeeded) {
             return _diskOfferingDao.findById(diskOfferingId);
@@ -2489,6 +2570,26 @@ public class ConfigurationManagerImpl extends ManagerBase implements Configurati
             throw new InvalidParameterValueException("Unable to find disk offering by id " + diskOfferingId);
         }
 
+        Long userId = CallContext.current().getCallingUserId();
+        if (userId == null) {
+            userId = Long.valueOf(User.UID_SYSTEM);
+        }
+        User user = _userDao.findById(userId);
+        if (user == null || user.getRemoved() != null) {
+            throw new InvalidParameterValueException("Unable to find active user by id " + userId);
+        }
+        Account account = _accountDao.findById(user.getAccountId());
+        if (account.getType() == Account.ACCOUNT_TYPE_DOMAIN_ADMIN) {
+            if (offering.getDomainId() == null) {
+                throw new InvalidParameterValueException("Unable to delete public disk offering by id " + userId + " because it is domain-admin");
+            }
+            if (! _domainDao.isChildDomain(account.getDomainId(), offering.getDomainId() )) {
+                throw new InvalidParameterValueException("Unable to delete disk offering by another domain admin with id " + userId);
+            }
+        } else if (account.getType() != Account.ACCOUNT_TYPE_ADMIN) {
+            throw new InvalidParameterValueException("Unable to delete disk offering by id " + userId + " because it is not root-admin or domain-admin");
+        }
+
         offering.setState(DiskOffering.State.Inactive);
         if (_diskOfferingDao.update(offering.getId(), offering)) {
             CallContext.current().setEventDetails("Disk offering id=" + diskOfferingId);
@@ -2519,6 +2620,22 @@ public class ConfigurationManagerImpl extends ManagerBase implements Configurati
             throw new InvalidParameterValueException("Default service offerings cannot be deleted");
         }
 
+        User user = _userDao.findById(userId);
+        if (user == null || user.getRemoved() != null) {
+            throw new InvalidParameterValueException("Unable to find active user by id " + userId);
+        }
+        Account account = _accountDao.findById(user.getAccountId());
+        if (account.getType() == Account.ACCOUNT_TYPE_DOMAIN_ADMIN) {
+            if (offering.getDomainId() == null) {
+                throw new InvalidParameterValueException("Unable to delete public service offering by id " + userId + " because it is domain-admin");
+            }
+            if (! _domainDao.isChildDomain(account.getDomainId(), offering.getDomainId() )) {
+                throw new InvalidParameterValueException("Unable to delete service offering by another domain admin with id " + userId);
+            }
+        } else if (account.getType() != Account.ACCOUNT_TYPE_ADMIN) {
+            throw new InvalidParameterValueException("Unable to delete service offering by id " + userId + " because it is not root-admin or domain-admin");
+        }
+
         offering.setState(DiskOffering.State.Inactive);
         if (_serviceOfferingDao.update(offeringId, offering)) {
             CallContext.current().setEventDetails("Service offering id=" + offeringId);

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/af2f2189/server/src/com/cloud/user/AccountManagerImpl.java
----------------------------------------------------------------------
diff --git a/server/src/com/cloud/user/AccountManagerImpl.java b/server/src/com/cloud/user/AccountManagerImpl.java
index f816ee4..b6aa201 100644
--- a/server/src/com/cloud/user/AccountManagerImpl.java
+++ b/server/src/com/cloud/user/AccountManagerImpl.java
@@ -110,6 +110,8 @@ import com.cloud.network.vpc.Vpc;
 import com.cloud.network.vpc.VpcManager;
 import com.cloud.network.vpn.RemoteAccessVpnService;
 import com.cloud.network.vpn.Site2SiteVpnManager;
+import com.cloud.offering.DiskOffering;
+import com.cloud.offering.ServiceOffering;
 import com.cloud.projects.Project;
 import com.cloud.projects.Project.ListProjectResourcesCriteria;
 import com.cloud.projects.ProjectInvitationVO;
@@ -2616,4 +2618,36 @@ public class AccountManagerImpl extends ManagerBase implements AccountManager, M
     public UserAccount getUserAccountById(Long userId) {
         return _userAccountDao.findById(userId);
     }
+
+    @Override
+    public void checkAccess(Account account, ServiceOffering so)
+            throws PermissionDeniedException {
+        for (SecurityChecker checker : _securityCheckers) {
+            if (checker.checkAccess(account, so)) {
+                if (s_logger.isDebugEnabled()) {
+                    s_logger.debug("Access granted to " + account + " to " + so + " by " + checker.getName());
+                }
+                return;
+            }
+        }
+
+        assert false : "How can all of the security checkers pass on checking this caller?";
+        throw new PermissionDeniedException("There's no way to confirm " + account + " has access to " + so);
+    }
+
+    @Override
+    public void checkAccess(Account account, DiskOffering dof)
+            throws PermissionDeniedException {
+        for (SecurityChecker checker : _securityCheckers) {
+            if (checker.checkAccess(account, dof)) {
+                if (s_logger.isDebugEnabled()) {
+                    s_logger.debug("Access granted to " + account + " to " + dof + " by " + checker.getName());
+                }
+                return;
+            }
+        }
+
+        assert false : "How can all of the security checkers pass on checking this caller?";
+        throw new PermissionDeniedException("There's no way to confirm " + account + " has access to " + dof);
+    }
 }

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/af2f2189/server/src/com/cloud/vm/UserVmManagerImpl.java
----------------------------------------------------------------------
diff --git a/server/src/com/cloud/vm/UserVmManagerImpl.java b/server/src/com/cloud/vm/UserVmManagerImpl.java
index 0cab57c..35556b1 100644
--- a/server/src/com/cloud/vm/UserVmManagerImpl.java
+++ b/server/src/com/cloud/vm/UserVmManagerImpl.java
@@ -948,6 +948,11 @@ public class UserVmManagerImpl extends ManagerBase implements UserVmManager, Vir
         // Check that the specified service offering ID is valid
         _itMgr.checkIfCanUpgrade(vmInstance, newServiceOffering);
 
+        // Check if the new service offering can be applied to vm instance
+        ServiceOffering newSvcOffering = _offeringDao.findById(svcOffId);
+        Account owner = _accountMgr.getActiveAccountById(vmInstance.getAccountId());
+        _accountMgr.checkAccess(owner, newSvcOffering);
+
         _itMgr.upgradeVmDb(vmId, svcOffId);
         if (newServiceOffering.isDynamic()) {
             //save the custom values to the database.
@@ -2373,6 +2378,10 @@ public class UserVmManagerImpl extends ManagerBase implements UserVmManager, Vir
         // Verify that caller can perform actions in behalf of vm owner
         _accountMgr.checkAccess(caller, null, true, owner);
 
+        // Verify that owner can use the service offering
+        _accountMgr.checkAccess(owner, serviceOffering);
+        _accountMgr.checkAccess(owner, _diskOfferingDao.findById(diskOfferingId));
+
         // Get default guest network in Basic zone
         Network defaultNetwork = _networkModel.getExclusiveGuestNetwork(zone.getId());
 
@@ -2428,6 +2437,10 @@ public class UserVmManagerImpl extends ManagerBase implements UserVmManager, Vir
         // Verify that caller can perform actions in behalf of vm owner
         _accountMgr.checkAccess(caller, null, true, owner);
 
+        // Verify that owner can use the service offering
+        _accountMgr.checkAccess(owner, serviceOffering);
+        _accountMgr.checkAccess(owner, _diskOfferingDao.findById(diskOfferingId));
+
         // If no network is specified, find system security group enabled network
         if (networkIdList == null || networkIdList.isEmpty()) {
             Network networkWithSecurityGroup = _networkModel.getNetworkWithSGWithFreeIPs(zone.getId());
@@ -2532,6 +2545,10 @@ public class UserVmManagerImpl extends ManagerBase implements UserVmManager, Vir
         // Verify that caller can perform actions in behalf of vm owner
         _accountMgr.checkAccess(caller, null, true, owner);
 
+        // Verify that owner can use the service offering
+        _accountMgr.checkAccess(owner, serviceOffering);
+        _accountMgr.checkAccess(owner, _diskOfferingDao.findById(diskOfferingId));
+
         List<HypervisorType> vpcSupportedHTypes = _vpcMgr.getSupportedVpcHypervisors();
         if (networkIdList == null || networkIdList.isEmpty()) {
             NetworkVO defaultNetwork = null;

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/af2f2189/server/test/com/cloud/user/MockAccountManagerImpl.java
----------------------------------------------------------------------
diff --git a/server/test/com/cloud/user/MockAccountManagerImpl.java b/server/test/com/cloud/user/MockAccountManagerImpl.java
index 6dcd46c..35eb94a 100644
--- a/server/test/com/cloud/user/MockAccountManagerImpl.java
+++ b/server/test/com/cloud/user/MockAccountManagerImpl.java
@@ -38,6 +38,8 @@ import com.cloud.domain.Domain;
 import com.cloud.exception.ConcurrentOperationException;
 import com.cloud.exception.PermissionDeniedException;
 import com.cloud.exception.ResourceUnavailableException;
+import com.cloud.offering.DiskOffering;
+import com.cloud.offering.ServiceOffering;
 import com.cloud.projects.Project.ListProjectResourcesCriteria;
 import com.cloud.utils.Pair;
 import com.cloud.utils.Ternary;
@@ -206,6 +208,16 @@ public class MockAccountManagerImpl extends ManagerBase implements Manager, Acco
     }
 
     @Override
+    public void checkAccess(Account account, ServiceOffering so) throws PermissionDeniedException {
+        // TODO Auto-generated method stub
+    }
+
+    @Override
+    public void checkAccess(Account account, DiskOffering dof) throws PermissionDeniedException {
+        // TODO Auto-generated method stub
+    }
+
+    @Override
     public Long checkAccessAndSpecifyAuthority(Account caller, Long zoneId) {
         // TODO Auto-generated method stub
         return null;

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/af2f2189/ui/scripts/cloudStack.js
----------------------------------------------------------------------
diff --git a/ui/scripts/cloudStack.js b/ui/scripts/cloudStack.js
index 7a59882..eca0c90 100644
--- a/ui/scripts/cloudStack.js
+++ b/ui/scripts/cloudStack.js
@@ -24,7 +24,7 @@
             if (isAdmin()) {
                 sections = ["dashboard", "instances", "storage", "network", "templates", "accounts", "domains", "events", "system", "global-settings", "configuration", "projects", "regions", "affinityGroups"];
             } else if (isDomainAdmin()) {
-                sections = ["dashboard", "instances", "storage", "network", "templates", "accounts", "domains", "events", "projects", "regions", "affinityGroups"];
+                sections = ["dashboard", "instances", "storage", "network", "templates", "accounts", "domains", "events", "projects", "configuration", "regions", "affinityGroups"];
             } else if (g_userProjectsEnabled) {
                 sections = ["dashboard", "instances", "storage", "network", "templates", "accounts", "events", "projects", "regions", "affinityGroups"];
             } else { //normal user

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/af2f2189/ui/scripts/configuration.js
----------------------------------------------------------------------
diff --git a/ui/scripts/configuration.js b/ui/scripts/configuration.js
index 0a5a017..76b5b7b 100644
--- a/ui/scripts/configuration.js
+++ b/ui/scripts/configuration.js
@@ -26,6 +26,14 @@
         title: 'label.menu.service.offerings',
         id: 'configuration',
         sectionSelect: {
+            preFilter: function(args) {
+               if(isAdmin())
+                   return ["serviceOfferings", "systemServiceOfferings", "diskOfferings", "networkOfferings"];
+               else if(isDomainAdmin())
+                   return ["serviceOfferings", "diskOfferings"];
+               else
+                   return null;
+            },
             label: 'label.select.offering'
         },
         sections: {
@@ -62,6 +70,17 @@
 
                             createForm: {
                                 title: 'label.add.compute.offering',
+                                preFilter: function(args) {
+                                    if (isAdmin()) {
+                                    } else {
+                                        args.$form.find('.form-item[rel=isPublic]').hide();
+                                        args.$form.find('.form-item[rel=domainId]').css('display', 'inline-block'); //shown
+                                        args.$form.find('.form-item[rel=deploymentPlanner]').hide();
+                                        args.$form.find('.form-item[rel=plannerMode]').hide();
+                                        args.$form.find('.form-item[rel=storageTags]').hide();
+                                        args.$form.find('.form-item[rel=hostTags]').hide();
+                                    }
+                                },
                                 fields: {
                                     name: {
                                         label: 'label.name',
@@ -385,7 +404,7 @@
                                         label: 'label.public',
                                         isBoolean: true,
                                         isReverse: true,
-                                        isChecked: true,
+                                        isChecked: false,
                                         docID: 'helpComputeOfferingPublic'
                                     },
 
@@ -399,6 +418,7 @@
                                     deploymentPlanner: {
                                         label: 'label.deployment.planner',
                                         select: function(args) {
+                                          if (isAdmin()) {
                                             $.ajax({
                                                 url: createURL('listDeploymentPlanners'),
                                                 dataType: 'json',
@@ -428,6 +448,7 @@
                                                     });
                                                 }
                                             });
+                                          }
                                         }
                                     },
 
@@ -761,7 +782,7 @@
                         });
 
                         $.ajax({
-                            url: createURL('listServiceOfferings'),
+                            url: createURL('listServiceOfferings&isrecursive=true'),
                             data: data,
                             success: function(json) {
                                 var items = json.listserviceofferingsresponse.serviceoffering;
@@ -975,7 +996,7 @@
                                         id: args.context.serviceOfferings[0].id
                                     };
                                     $.ajax({
-                                        url: createURL('listServiceOfferings'),
+                                        url: createURL('listServiceOfferings&isrecursive=true'),
                                         data: data,
                                         async: true,
                                         success: function(json) {
@@ -1038,6 +1059,13 @@
 
                             createForm: {
                                 title: 'label.add.system.service.offering',
+                                preFilter: function(args) {
+                                    if (isAdmin()) {
+                                    } else {
+                                        args.$form.find('.form-item[rel=isPublic]').hide();
+                                        args.$form.find('.form-item[rel=domainId]').css('display', 'inline-block'); //shown
+                                    }
+                                },
                                 fields: {
                                     name: {
                                         label: 'label.name',
@@ -1203,7 +1231,7 @@
                                         label: 'label.public',
                                         isBoolean: true,
                                         isReverse: true,
-                                        isChecked: true,
+                                        isChecked: false,
                                         docID: 'helpSystemOfferingPublic'
                                     },
                                     domainId: {
@@ -1332,7 +1360,7 @@
                         });
 
                         $.ajax({
-                            url: createURL('listServiceOfferings'),
+                            url: createURL('listServiceOfferings&isrecursive=true'),
                             data: data,
                             success: function(json) {
                                 var items = json.listserviceofferingsresponse.serviceoffering;
@@ -1515,7 +1543,7 @@
                                         id: args.context.systemServiceOfferings[0].id
                                     };
                                     $.ajax({
-                                        url: createURL('listServiceOfferings'),
+                                        url: createURL('listServiceOfferings&isrecursive=true'),
                                         data: data,
                                         success: function(json) {
                                             var item = json.listserviceofferingsresponse.serviceoffering[0];
@@ -1567,7 +1595,7 @@
                         listViewDataProvider(args, data);
 
                         $.ajax({
-                            url: createURL('listDiskOfferings'),
+                            url: createURL('listDiskOfferings&isrecursive=true'),
                             data: data,
                             success: function(json) {
                                 var items = json.listdiskofferingsresponse.diskoffering;
@@ -1596,6 +1624,14 @@
 
                             createForm: {
                                 title: 'label.add.disk.offering',
+                                preFilter: function(args) {
+                                    if (isAdmin()) {
+                                    } else {
+                                        args.$form.find('.form-item[rel=isPublic]').hide();
+                                        args.$form.find('.form-item[rel=domainId]').css('display', 'inline-block'); //shown
+                                        args.$form.find('.form-item[rel=tags]').hide();
+                                    }
+                                },
                                 fields: {
                                     name: {
                                         label: 'label.name',
@@ -1868,7 +1904,7 @@
                                         label: 'label.public',
                                         isBoolean: true,
                                         isReverse: true,
-                                        isChecked: true,
+                                        isChecked: false,
                                         docID: 'helpDiskOfferingPublic'
                                     },
                                     domainId: {
@@ -2165,7 +2201,7 @@
                                         id: args.context.diskOfferings[0].id
                                     };
                                     $.ajax({
-                                        url: createURL('listDiskOfferings'),
+                                        url: createURL('listDiskOfferings&isrecursive=true'),
                                         data: data,
                                         success: function(json) {
                                             var item = json.listdiskofferingsresponse.diskoffering[0];


Mime
View raw message