You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@cloudstack.apache.org by mc...@apache.org on 2013/11/01 01:21:53 UTC

[42/50] [abbrv] Merge branch 'master' into rbac.

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/2ef4d520/server/src/org/apache/cloudstack/acl/AclServiceImpl.java
----------------------------------------------------------------------
diff --cc server/src/org/apache/cloudstack/acl/AclServiceImpl.java
index ccd3bf0,0000000..c7badd0
mode 100644,000000..100644
--- a/server/src/org/apache/cloudstack/acl/AclServiceImpl.java
+++ b/server/src/org/apache/cloudstack/acl/AclServiceImpl.java
@@@ -1,666 -1,0 +1,692 @@@
 +// Licensed to the Apache Software Foundation (ASF) under one
 +// or more contributor license agreements.  See the NOTICE file
 +// distributed with this work for additional information
 +// regarding copyright ownership.  The ASF licenses this file
 +// to you under the Apache License, Version 2.0 (the
 +// "License"); you may not use this file except in compliance
 +// with the License.  You may obtain a copy of the License at
 +//
 +//   http://www.apache.org/licenses/LICENSE-2.0
 +//
 +// Unless required by applicable law or agreed to in writing,
 +// software distributed under the License is distributed on an
 +// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 +// KIND, either express or implied.  See the License for the
 +// specific language governing permissions and limitations
 +// under the License.
 +package org.apache.cloudstack.acl;
 +
 +import java.util.ArrayList;
 +import java.util.HashMap;
 +import java.util.HashSet;
 +import java.util.List;
 +import java.util.Set;
 +
 +import javax.ejb.Local;
 +import javax.inject.Inject;
 +
 +import org.apache.log4j.Logger;
 +
 +import org.apache.cloudstack.acl.SecurityChecker.AccessType;
 +import org.apache.cloudstack.acl.dao.AclApiPermissionDao;
 +import org.apache.cloudstack.acl.dao.AclEntityPermissionDao;
 +import org.apache.cloudstack.acl.dao.AclGroupAccountMapDao;
 +import org.apache.cloudstack.acl.dao.AclGroupDao;
 +import org.apache.cloudstack.acl.dao.AclGroupRoleMapDao;
 +import org.apache.cloudstack.acl.dao.AclRoleDao;
 +import org.apache.cloudstack.acl.dao.AclRolePermissionDao;
 +import org.apache.cloudstack.api.Identity;
 +import org.apache.cloudstack.context.CallContext;
 +
 +import com.cloud.domain.Domain;
 +import com.cloud.event.ActionEvent;
 +import com.cloud.event.EventTypes;
 +import com.cloud.exception.InvalidParameterValueException;
 +import com.cloud.exception.PermissionDeniedException;
 +import com.cloud.storage.Snapshot;
 +import com.cloud.storage.Volume;
 +import com.cloud.template.VirtualMachineTemplate;
 +import com.cloud.user.Account;
 +import com.cloud.user.AccountManager;
 +import com.cloud.user.dao.AccountDao;
 +import com.cloud.uservm.UserVm;
 +import com.cloud.utils.Pair;
 +import com.cloud.utils.component.Manager;
 +import com.cloud.utils.component.ManagerBase;
 +import com.cloud.utils.db.DB;
 +import com.cloud.utils.db.EntityManager;
 +import com.cloud.utils.db.GenericSearchBuilder;
 +import com.cloud.utils.db.JoinBuilder.JoinType;
 +import com.cloud.utils.db.SearchBuilder;
 +import com.cloud.utils.db.SearchCriteria;
 +import com.cloud.utils.db.SearchCriteria.Op;
 +import com.cloud.utils.db.Transaction;
++import com.cloud.utils.db.TransactionCallback;
++import com.cloud.utils.db.TransactionCallbackNoReturn;
++import com.cloud.utils.db.TransactionStatus;
 +
 +@Local(value = {AclService.class})
 +public class AclServiceImpl extends ManagerBase implements AclService, Manager {
 +
 +    public static final Logger s_logger = Logger.getLogger(AclServiceImpl.class);
 +    private String _name;
 +
 +    @Inject
 +    AccountManager _accountMgr;
 +
 +    @Inject
 +    AccountDao _accountDao;
 +
 +    @Inject
 +    AclRoleDao _aclRoleDao;
 +
 +    @Inject
 +    AclGroupDao _aclGroupDao;
 +
 +    @Inject
 +    EntityManager _entityMgr;
 +
 +    @Inject
 +    AclGroupRoleMapDao _aclGroupRoleMapDao;
 +
 +    @Inject
 +    AclGroupAccountMapDao _aclGroupAccountMapDao;
 +
 +    @Inject
 +    AclApiPermissionDao _apiPermissionDao;
 +
 +    @Inject
 +    AclRolePermissionDao _rolePermissionDao;
 +
 +    @Inject
 +    AclEntityPermissionDao _entityPermissionDao;
 +
 +    public static HashMap<String, Class> entityClassMap = new HashMap<String, Class>();
 +
 +    static {
 +        entityClassMap.put("VirtualMachine", UserVm.class);
 +        entityClassMap.put("Volume", Volume.class);
 +        entityClassMap.put("Template", VirtualMachineTemplate.class);
 +        entityClassMap.put("Snapshot", Snapshot.class);
 +        // To be filled in later depending on the entity permission grant scope
 +    }
 +
 +    @DB
 +    @Override
 +    @ActionEvent(eventType = EventTypes.EVENT_ACL_ROLE_CREATE, eventDescription = "Creating Acl Role", create = true)
-     public AclRole createAclRole(Long domainId, String aclRoleName, String description, Long parentRoleId) {
++    public AclRole createAclRole(Long domainId, final String aclRoleName, final String description, final Long parentRoleId) {
 +        Account caller = CallContext.current().getCallingAccount();
 +        if (domainId == null) {
 +            domainId = caller.getDomainId();
 +        }
 +        if (!_accountMgr.isRootAdmin(caller.getAccountId())) {
 +            // domain admin can only create role for his domain
 +            if (caller.getDomainId() != domainId.longValue()) {
 +                throw new PermissionDeniedException("Can't create acl role in domain " + domainId + ", permission denied");
 +            }
 +        }
 +        // check if the role is already existing
 +        AclRole ro = _aclRoleDao.findByName(domainId, aclRoleName);
 +        if (ro != null) {
 +            throw new InvalidParameterValueException(
 +                    "Unable to create acl role with name " + aclRoleName
 +                            + " already exisits for domain " + domainId);
 +        }
 +
-         Transaction txn = Transaction.currentTxn();
-         txn.start();
-         AclRoleVO rvo = new AclRoleVO(aclRoleName, description);
-         rvo.setDomainId(domainId);
-         AclRole role = _aclRoleDao.persist(rvo);
-         if (parentRoleId != null) {
-             // copy parent role permissions
-             List<AclRolePermissionVO> perms = _rolePermissionDao.listByRole(parentRoleId);
-             if (perms != null) {
-                 for (AclRolePermissionVO perm : perms) {
-                     perm.setAclRoleId(role.getId());
-                     _rolePermissionDao.persist(perm);
++        final long domain_id = domainId;
++        AclRole role = Transaction.execute(new TransactionCallback<AclRole>() {
++            @Override
++            public AclRole doInTransaction(TransactionStatus status) {
++                AclRoleVO rvo = new AclRoleVO(aclRoleName, description);
++                rvo.setDomainId(domain_id);
++                AclRole role = _aclRoleDao.persist(rvo);
++                if (parentRoleId != null) {
++                    // copy parent role permissions
++                    List<AclRolePermissionVO> perms = _rolePermissionDao.listByRole(parentRoleId);
++                    if (perms != null) {
++                        for (AclRolePermissionVO perm : perms) {
++                            perm.setAclRoleId(role.getId());
++                            _rolePermissionDao.persist(perm);
++                        }
++                    }
 +                }
++                return role;
 +            }
-         }
-         txn.commit();
++        });
++                
 +
 +        return role;
 +    }
 +
 +    @DB
 +    @Override
 +    @ActionEvent(eventType = EventTypes.EVENT_ACL_ROLE_DELETE, eventDescription = "Deleting Acl Role")
-     public boolean deleteAclRole(long aclRoleId) {
++    public boolean deleteAclRole(final long aclRoleId) {
 +        Account caller = CallContext.current().getCallingAccount();
 +        // get the Acl Role entity
-         AclRole role = _aclRoleDao.findById(aclRoleId);
++        final AclRole role = _aclRoleDao.findById(aclRoleId);
 +        if (role == null) {
 +            throw new InvalidParameterValueException("Unable to find acl role: " + aclRoleId
 +                    + "; failed to delete acl role.");
 +        }
 +        // check permissions
 +        _accountMgr.checkAccess(caller, null, true, role);
 +
-         Transaction txn = Transaction.currentTxn();
-         txn.start();
-         // remove this role related entry in acl_group_role_map
-         List<AclGroupRoleMapVO> groupRoleMap = _aclGroupRoleMapDao.listByRoleId(role.getId());
-         if (groupRoleMap != null) {
-             for (AclGroupRoleMapVO gr : groupRoleMap) {
-                 _aclGroupRoleMapDao.remove(gr.getId());
-             }
-         }
++        Transaction.execute(new TransactionCallbackNoReturn() {
++            @Override
++            public void doInTransactionWithoutResult(TransactionStatus status) {
++                // remove this role related entry in acl_group_role_map
++                List<AclGroupRoleMapVO> groupRoleMap = _aclGroupRoleMapDao.listByRoleId(role.getId());
++                if (groupRoleMap != null) {
++                    for (AclGroupRoleMapVO gr : groupRoleMap) {
++                        _aclGroupRoleMapDao.remove(gr.getId());
++                    }
++                }
 +
-         // remove this role related entry in acl_api_permission table
-         List<AclApiPermissionVO> roleApiMap = _apiPermissionDao.listByRoleId(role.getId());
-         if (roleApiMap != null) {
-             for (AclApiPermissionVO roleApi : roleApiMap) {
-                 _apiPermissionDao.remove(roleApi.getId());
-             }
-         }
++                // remove this role related entry in acl_api_permission table
++                List<AclApiPermissionVO> roleApiMap = _apiPermissionDao.listByRoleId(role.getId());
++                if (roleApiMap != null) {
++                    for (AclApiPermissionVO roleApi : roleApiMap) {
++                        _apiPermissionDao.remove(roleApi.getId());
++                    }
++                }
 +
-         // remove this role from acl_role table
-         _aclRoleDao.remove(aclRoleId);
-         txn.commit();
++                // remove this role from acl_role table
++                _aclRoleDao.remove(aclRoleId);
++            }
++        });
 +
 +        return true;
 +    }
 +
 +
 +    @DB
 +    @Override
 +    @ActionEvent(eventType = EventTypes.EVENT_ACL_ROLE_GRANT, eventDescription = "Granting permission to Acl Role")
-     public AclRole grantApiPermissionToAclRole(long aclRoleId, List<String> apiNames) {
++    public AclRole grantApiPermissionToAclRole(final long aclRoleId, final List<String> apiNames) {
 +        Account caller = CallContext.current().getCallingAccount();
 +        // get the Acl Role entity
 +        AclRole role = _aclRoleDao.findById(aclRoleId);
 +        if (role == null) {
 +            throw new InvalidParameterValueException("Unable to find acl role: " + aclRoleId
 +                    + "; failed to grant permission to role.");
 +        }
 +        // check permissions
 +        _accountMgr.checkAccess(caller, null, true, role);
 +
-         Transaction txn = Transaction.currentTxn();
-         txn.start();
-         // add entries in acl_api_permission table
-         for (String api : apiNames) {
-             AclApiPermissionVO perm = _apiPermissionDao.findByRoleAndApi(aclRoleId, api);
-             if (perm == null) {
-                 // not there already
-                 perm = new AclApiPermissionVO(aclRoleId, api);
-                 _apiPermissionDao.persist(perm);
++        Transaction.execute(new TransactionCallbackNoReturn() {
++            @Override
++            public void doInTransactionWithoutResult(TransactionStatus status) {
++                // add entries in acl_api_permission table
++                for (String api : apiNames) {
++                    AclApiPermissionVO perm = _apiPermissionDao.findByRoleAndApi(aclRoleId, api);
++                    if (perm == null) {
++                        // not there already
++                        perm = new AclApiPermissionVO(aclRoleId, api);
++                        _apiPermissionDao.persist(perm);
++                    }
++                }
 +            }
-         }
-         txn.commit();
++        });
++            
 +        return role;
 +
 +    }
 +
 +    @DB
 +    @Override
 +    @ActionEvent(eventType = EventTypes.EVENT_ACL_ROLE_REVOKE, eventDescription = "Revoking permission from Acl Role")
-     public AclRole revokeApiPermissionFromAclRole(long aclRoleId, List<String> apiNames) {
++    public AclRole revokeApiPermissionFromAclRole(final long aclRoleId, final List<String> apiNames) {
 +        Account caller = CallContext.current().getCallingAccount();
 +        // get the Acl Role entity
 +        AclRole role = _aclRoleDao.findById(aclRoleId);
 +        if (role == null) {
 +            throw new InvalidParameterValueException("Unable to find acl role: " + aclRoleId
 +                    + "; failed to revoke permission from role.");
 +        }
 +        // check permissions
 +        _accountMgr.checkAccess(caller, null, true, role);
 +
-         Transaction txn = Transaction.currentTxn();
-         txn.start();
-         // remove entries from acl_api_permission table
-         for (String api : apiNames) {
-             AclApiPermissionVO perm = _apiPermissionDao.findByRoleAndApi(aclRoleId, api);
-             if (perm != null) {
-                 // not removed yet
-                 _apiPermissionDao.remove(perm.getId());
++        Transaction.execute(new TransactionCallbackNoReturn() {
++            @Override
++            public void doInTransactionWithoutResult(TransactionStatus status) {
++                // remove entries from acl_api_permission table
++                for (String api : apiNames) {
++                    AclApiPermissionVO perm = _apiPermissionDao.findByRoleAndApi(aclRoleId, api);
++                    if (perm != null) {
++                        // not removed yet
++                        _apiPermissionDao.remove(perm.getId());
++                    }
++                }
 +            }
-         }
-         txn.commit();
++        });
 +        return role;
 +    }
 +
 +    @DB
 +    @Override
 +    @ActionEvent(eventType = EventTypes.EVENT_ACL_GROUP_GRANT, eventDescription = "Granting entity permission to Acl Group")
 +    public AclGroup grantEntityPermissionToAclGroup(long aclGroupId, String entityType, long entityId, AccessType accessType) {
 +        Account caller = CallContext.current().getCallingAccount();
 +        // get the Acl Group entity
 +        AclGroup group = _aclGroupDao.findById(aclGroupId);
 +        if (group == null) {
 +            throw new InvalidParameterValueException("Unable to find acl group: " + aclGroupId
 +                    + "; failed to grant permission to group.");
 +        }
 +        // check permissions
 +        _accountMgr.checkAccess(caller, null, true, group);
 +
 +        // get the entity and check permission
 +        Class entityClass = entityClassMap.get(entityType);
 +        if (entityClass == null) {
 +            throw new InvalidParameterValueException("Entity type " + entityType + " permission granting is not supported yet");
 +        }
 +        ControlledEntity entity = (ControlledEntity)_entityMgr.findById(entityClass, entityId);
 +        if (entity == null) {
 +            throw new InvalidParameterValueException("Unable to find entity " + entityType + " by id: " + entityId);
 +        }
 +        _accountMgr.checkAccess(caller,null, true, entity);
 +        
 +        // add entry in acl_entity_permission table
 +        AclEntityPermissionVO perm = _entityPermissionDao.findByGroupAndEntity(aclGroupId, entityType, entityId, accessType);
 +        if (perm == null) {
 +            // not there already
 +            String entityUuid = String.valueOf(entityId);
 +            if (entity instanceof Identity) {
 +                entityUuid = ((Identity)entity).getUuid();
 +            }
 +            perm = new AclEntityPermissionVO(aclGroupId, entityType, entityId, entityUuid, accessType, true);
 +            _entityPermissionDao.persist(perm);
 +        }
 +        return group;
 +
 +    }
 +
 +    @DB
 +    @Override
 +    @ActionEvent(eventType = EventTypes.EVENT_ACL_GROUP_REVOKE, eventDescription = "Revoking entity permission from Acl Group")
 +    public AclGroup revokeEntityPermissionFromAclGroup(long aclGroupId, String entityType, long entityId, AccessType accessType) {
 +        Account caller = CallContext.current().getCallingAccount();
 +        // get the Acl Group entity
 +        AclGroup group = _aclGroupDao.findById(aclGroupId);
 +        if (group == null) {
 +            throw new InvalidParameterValueException("Unable to find acl group: " + aclGroupId
 +                    + "; failed to revoke permission from group.");
 +        }
 +        // check permissions
 +        _accountMgr.checkAccess(caller, null, true, group);
 +
 +        // get the entity and check permission
 +        Class entityClass = entityClassMap.get(entityType);
 +        if (entityClass == null) {
 +            throw new InvalidParameterValueException("Entity type " + entityType + " permission revoke is not supported yet");
 +        }
 +        ControlledEntity entity = (ControlledEntity)_entityMgr.findById(entityClass, entityId);
 +        if (entity == null) {
 +            throw new InvalidParameterValueException("Unable to find entity " + entityType + " by id: " + entityId);
 +        }
 +        _accountMgr.checkAccess(caller, null, true, entity);
 +
 +        // remove entry from acl_entity_permission table
 +        AclEntityPermissionVO perm = _entityPermissionDao.findByGroupAndEntity(aclGroupId, entityType, entityId, accessType);
 +        if (perm != null) {
 +            // not removed yet
 +            _entityPermissionDao.remove(perm.getId());
 +        }
 +        return group;
 +    }
 +
 +    @DB
 +    @Override
 +    @ActionEvent(eventType = EventTypes.EVENT_ACL_GROUP_UPDATE, eventDescription = "Adding roles to acl group")
-     public AclGroup addAclRolesToGroup(List<Long> roleIds, Long groupId) {
-         Account caller = CallContext.current().getCallingAccount();
++    public AclGroup addAclRolesToGroup(final List<Long> roleIds, final Long groupId) {
++        final Account caller = CallContext.current().getCallingAccount();
 +        // get the Acl Group entity
 +        AclGroup group = _aclGroupDao.findById(groupId);
 +        if (group == null) {
 +            throw new InvalidParameterValueException("Unable to find acl group: " + groupId
 +                    + "; failed to add roles to acl group.");
 +        }
 +        // check group permissions
 +        _accountMgr.checkAccess(caller, null, true, group);
 + 
-         Transaction txn = Transaction.currentTxn();
-         txn.start();
-         // add entries in acl_group_role_map table
-         for (Long roleId : roleIds) {
-             // check role permissions
-             AclRole role = _aclRoleDao.findById(roleId);
-             if ( role == null ){
-                 throw new InvalidParameterValueException("Unable to find acl role: " + roleId
-                         + "; failed to add roles to acl group.");
-             }
-             _accountMgr.checkAccess(caller,null, true, role);
-             
-             AclGroupRoleMapVO grMap = _aclGroupRoleMapDao.findByGroupAndRole(groupId, roleId);
-             if (grMap == null) {
-                 // not there already
-                 grMap = new AclGroupRoleMapVO(groupId, roleId);
-                 _aclGroupRoleMapDao.persist(grMap);
++        Transaction.execute(new TransactionCallbackNoReturn() {
++            @Override
++            public void doInTransactionWithoutResult(TransactionStatus status) {
++                // add entries in acl_group_role_map table
++                for (Long roleId : roleIds) {
++                    // check role permissions
++                    AclRole role = _aclRoleDao.findById(roleId);
++                    if (role == null) {
++                        throw new InvalidParameterValueException("Unable to find acl role: " + roleId
++                                + "; failed to add roles to acl group.");
++                    }
++                    _accountMgr.checkAccess(caller, null, true, role);
++
++                    AclGroupRoleMapVO grMap = _aclGroupRoleMapDao.findByGroupAndRole(groupId, roleId);
++                    if (grMap == null) {
++                        // not there already
++                        grMap = new AclGroupRoleMapVO(groupId, roleId);
++                        _aclGroupRoleMapDao.persist(grMap);
++                    }
++                }
 +            }
-         }
-         txn.commit();
++        });
++
 +        return group;
 +    }
 +
 +    @DB
 +    @Override
 +    @ActionEvent(eventType = EventTypes.EVENT_ACL_GROUP_UPDATE, eventDescription = "Removing roles from acl group")
-     public AclGroup removeAclRolesFromGroup(List<Long> roleIds, Long groupId) {
-         Account caller = CallContext.current().getCallingAccount();
++    public AclGroup removeAclRolesFromGroup(final List<Long> roleIds, final Long groupId) {
++        final Account caller = CallContext.current().getCallingAccount();
 +        // get the Acl Group entity
 +        AclGroup group = _aclGroupDao.findById(groupId);
 +        if (group == null) {
 +            throw new InvalidParameterValueException("Unable to find acl group: " + groupId
 +                    + "; failed to remove roles from acl group.");
 +        }
 +        // check group permissions
 +        _accountMgr.checkAccess(caller, null, true, group);
 +
-         Transaction txn = Transaction.currentTxn();
-         txn.start();
-         // add entries in acl_group_role_map table
-         for (Long roleId : roleIds) {
-             // check role permissions
-             AclRole role = _aclRoleDao.findById(roleId);
-             if (role == null) {
-                 throw new InvalidParameterValueException("Unable to find acl role: " + roleId
-                         + "; failed to add roles to acl group.");
-             }
-             _accountMgr.checkAccess(caller, null, true, role);
- 
-             AclGroupRoleMapVO grMap = _aclGroupRoleMapDao.findByGroupAndRole(groupId, roleId);
-             if (grMap != null) {
-                 // not removed yet
-                 _aclGroupRoleMapDao.remove(grMap.getId());
++        Transaction.execute(new TransactionCallbackNoReturn() {
++            @Override
++            public void doInTransactionWithoutResult(TransactionStatus status) {
++                // add entries in acl_group_role_map table
++                for (Long roleId : roleIds) {
++                    // check role permissions
++                    AclRole role = _aclRoleDao.findById(roleId);
++                    if (role == null) {
++                        throw new InvalidParameterValueException("Unable to find acl role: " + roleId
++                                + "; failed to add roles to acl group.");
++                    }
++                    _accountMgr.checkAccess(caller, null, true, role);
++
++                    AclGroupRoleMapVO grMap = _aclGroupRoleMapDao.findByGroupAndRole(groupId, roleId);
++                    if (grMap != null) {
++                        // not removed yet
++                        _aclGroupRoleMapDao.remove(grMap.getId());
++                    }
++                }
 +            }
-         }
-         txn.commit();
++        });
 +        return group;
 +    }
 +
 +    @DB
 +    @Override
 +    @ActionEvent(eventType = EventTypes.EVENT_ACL_GROUP_UPDATE, eventDescription = "Adding accounts to acl group")
-     public AclGroup addAccountsToGroup(List<Long> acctIds, Long groupId) {
-         Account caller = CallContext.current().getCallingAccount();
++    public AclGroup addAccountsToGroup(final List<Long> acctIds, final Long groupId) {
++        final Account caller = CallContext.current().getCallingAccount();
 +        // get the Acl Group entity
 +        AclGroup group = _aclGroupDao.findById(groupId);
 +        if (group == null) {
 +            throw new InvalidParameterValueException("Unable to find acl group: " + groupId
 +                    + "; failed to add accounts to acl group.");
 +        }
 +        // check group permissions
 +        _accountMgr.checkAccess(caller, null, true, group);
 +
-         Transaction txn = Transaction.currentTxn();
-         txn.start();
-         // add entries in acl_group_account_map table
-         for (Long acctId : acctIds) {
-             // check account permissions
-             Account account = _accountDao.findById(acctId);
-             if (account == null) {
-                 throw new InvalidParameterValueException("Unable to find account: " + acctId
-                         + "; failed to add account to acl group.");
-             }
-             _accountMgr.checkAccess(caller, null, true, account);
- 
-             AclGroupAccountMapVO grMap = _aclGroupAccountMapDao.findByGroupAndAccount(groupId, acctId);
-             if (grMap == null) {
-                 // not there already
-                 grMap = new AclGroupAccountMapVO(groupId, acctId);
-                 _aclGroupAccountMapDao.persist(grMap);
++        Transaction.execute(new TransactionCallbackNoReturn() {
++            @Override
++            public void doInTransactionWithoutResult(TransactionStatus status) {
++                // add entries in acl_group_account_map table
++                for (Long acctId : acctIds) {
++                    // check account permissions
++                    Account account = _accountDao.findById(acctId);
++                    if (account == null) {
++                        throw new InvalidParameterValueException("Unable to find account: " + acctId
++                                + "; failed to add account to acl group.");
++                    }
++                    _accountMgr.checkAccess(caller, null, true, account);
++
++                    AclGroupAccountMapVO grMap = _aclGroupAccountMapDao.findByGroupAndAccount(groupId, acctId);
++                    if (grMap == null) {
++                        // not there already
++                        grMap = new AclGroupAccountMapVO(groupId, acctId);
++                        _aclGroupAccountMapDao.persist(grMap);
++                    }
++                }
 +            }
-         }
-         txn.commit();
++        });
 +        return group;
 +    }
 +
 +    @DB
 +    @Override
 +    @ActionEvent(eventType = EventTypes.EVENT_ACL_GROUP_UPDATE, eventDescription = "Removing accounts from acl group")
-     public AclGroup removeAccountsFromGroup(List<Long> acctIds, Long groupId) {
-         Account caller = CallContext.current().getCallingAccount();
++    public AclGroup removeAccountsFromGroup(final List<Long> acctIds, final Long groupId) {
++        final Account caller = CallContext.current().getCallingAccount();
 +        // get the Acl Group entity
 +        AclGroup group = _aclGroupDao.findById(groupId);
 +        if (group == null) {
 +            throw new InvalidParameterValueException("Unable to find acl group: " + groupId
 +                    + "; failed to remove accounts from acl group.");
 +        }
 +        // check group permissions
 +        _accountMgr.checkAccess(caller, null, true, group);
 +
-         Transaction txn = Transaction.currentTxn();
-         txn.start();
-         // remove entries from acl_group_account_map table
-         for (Long acctId : acctIds) {
-             // check account permissions
-             Account account = _accountDao.findById(acctId);
-             if (account == null) {
-                 throw new InvalidParameterValueException("Unable to find account: " + acctId
-                         + "; failed to add account to acl group.");
-             }
-             _accountMgr.checkAccess(caller, null, true, account);
- 
-             AclGroupAccountMapVO grMap = _aclGroupAccountMapDao.findByGroupAndAccount(groupId, acctId);
-             if (grMap != null) {
-                 // not removed yet
-                 _aclGroupAccountMapDao.remove(grMap.getId());
++        Transaction.execute(new TransactionCallbackNoReturn() {
++            @Override
++            public void doInTransactionWithoutResult(TransactionStatus status) {
++                // remove entries from acl_group_account_map table
++                for (Long acctId : acctIds) {
++                    // check account permissions
++                    Account account = _accountDao.findById(acctId);
++                    if (account == null) {
++                        throw new InvalidParameterValueException("Unable to find account: " + acctId
++                                + "; failed to add account to acl group.");
++                    }
++                    _accountMgr.checkAccess(caller, null, true, account);
++
++                    AclGroupAccountMapVO grMap = _aclGroupAccountMapDao.findByGroupAndAccount(groupId, acctId);
++                    if (grMap != null) {
++                        // not removed yet
++                        _aclGroupAccountMapDao.remove(grMap.getId());
++                    }
++                }
 +            }
-         }
-         txn.commit();
++        });
 +        return group;
 +    }
 +
 +    @DB
 +    @Override
 +    @ActionEvent(eventType = EventTypes.EVENT_ACL_GROUP_CREATE, eventDescription = "Creating Acl Group", create = true)
 +    public AclGroup createAclGroup(Long domainId, String aclGroupName, String description) {
 +        Account caller = CallContext.current().getCallingAccount();
 +        if (domainId == null) {
 +            domainId = caller.getDomainId(); // use caller's domain id
 +        }
 +        if (!_accountMgr.isRootAdmin(caller.getAccountId())) {
 +            // domain admin can only create role for his domain
 +            if (caller.getDomainId() != domainId.longValue()) {
 +                throw new PermissionDeniedException("Can't create acl group in domain " + domainId + ", permission denied");
 +            }
 +        }
 +        // check if the role is already existing
 +        AclGroup grp = _aclGroupDao.findByName(domainId, aclGroupName);
 +        if (grp != null) {
 +            throw new InvalidParameterValueException(
 +                    "Unable to create acl group with name " + aclGroupName
 +                            + " already exisits for domain " + domainId);
 +        }
 +        AclGroupVO rvo = new AclGroupVO(aclGroupName, description);
 +        rvo.setDomainId(domainId);
 +
 +        return _aclGroupDao.persist(rvo);
 +    }
 +
 +    @DB
 +    @Override
 +    @ActionEvent(eventType = EventTypes.EVENT_ACL_GROUP_DELETE, eventDescription = "Deleting Acl Group")
-     public boolean deleteAclGroup(Long aclGroupId) {
++    public boolean deleteAclGroup(final Long aclGroupId) {
 +        Account caller = CallContext.current().getCallingAccount();
 +        // get the Acl Role entity
-         AclGroup grp = _aclGroupDao.findById(aclGroupId);
++        final AclGroup grp = _aclGroupDao.findById(aclGroupId);
 +        if (grp == null) {
 +            throw new InvalidParameterValueException("Unable to find acl group: " + aclGroupId
 +                    + "; failed to delete acl group.");
 +        }
 +        // check permissions
 +        _accountMgr.checkAccess(caller, null, true, grp);
 +
-         Transaction txn = Transaction.currentTxn();
-         txn.start();
-         // remove this group related entry in acl_group_role_map
-         List<AclGroupRoleMapVO> groupRoleMap = _aclGroupRoleMapDao.listByGroupId(grp.getId());
-         if (groupRoleMap != null) {
-             for (AclGroupRoleMapVO gr : groupRoleMap) {
-                 _aclGroupRoleMapDao.remove(gr.getId());
-             }
-         }
++        Transaction.execute(new TransactionCallbackNoReturn() {
++            @Override
++            public void doInTransactionWithoutResult(TransactionStatus status) {
++                // remove this group related entry in acl_group_role_map
++                List<AclGroupRoleMapVO> groupRoleMap = _aclGroupRoleMapDao.listByGroupId(grp.getId());
++                if (groupRoleMap != null) {
++                    for (AclGroupRoleMapVO gr : groupRoleMap) {
++                        _aclGroupRoleMapDao.remove(gr.getId());
++                    }
++                }
 +
-         // remove this group related entry in acl_group_account table
-         List<AclGroupAccountMapVO> groupAcctMap = _aclGroupAccountMapDao.listByGroupId(grp.getId());
-         if (groupAcctMap != null) {
-             for (AclGroupAccountMapVO grpAcct : groupAcctMap) {
-                 _aclGroupAccountMapDao.remove(grpAcct.getId());
-             }
-         }
++                // remove this group related entry in acl_group_account table
++                List<AclGroupAccountMapVO> groupAcctMap = _aclGroupAccountMapDao.listByGroupId(grp.getId());
++                if (groupAcctMap != null) {
++                    for (AclGroupAccountMapVO grpAcct : groupAcctMap) {
++                        _aclGroupAccountMapDao.remove(grpAcct.getId());
++                    }
++                }
 +
-         // remove this group from acl_group table
-         _aclGroupDao.remove(aclGroupId);
-         txn.commit();
++                // remove this group from acl_group table
++                _aclGroupDao.remove(aclGroupId);
++            }
++        });
 +
 +        return true;
 +    }
 +
 +    @Override
 +    public List<AclRole> getAclRoles(long accountId) {
 +
 +        // static roles of the account
 +        SearchBuilder<AclGroupAccountMapVO> groupSB = _aclGroupAccountMapDao.createSearchBuilder();
 +        groupSB.and("account", groupSB.entity().getAccountId(), Op.EQ);
 +
 +        GenericSearchBuilder<AclGroupRoleMapVO, Long> roleSB = _aclGroupRoleMapDao.createSearchBuilder(Long.class);
-         roleSB.selectField(roleSB.entity().getAclRoleId());
++        roleSB.selectFields(roleSB.entity().getAclRoleId());
 +        roleSB.join("accountgroupjoin", groupSB, groupSB.entity().getAclGroupId(), roleSB.entity().getAclGroupId(),
 +                JoinType.INNER);
 +        roleSB.done();
 +        SearchCriteria<Long> roleSc = roleSB.create();
 +        roleSc.setJoinParameters("accountgroupjoin", "account", accountId);
 +
 +        List<Long> roleIds = _aclGroupRoleMapDao.customSearch(roleSc, null);
 +
 +        SearchBuilder<AclRoleVO> sb = _aclRoleDao.createSearchBuilder();
 +        sb.and("ids", sb.entity().getId(), Op.IN);
 +        SearchCriteria<AclRoleVO> sc = sb.create();
 +        sc.setParameters("ids", roleIds.toArray(new Object[roleIds.size()]));
 +        List<AclRoleVO> roles = _aclRoleDao.customSearch(sc, null);
 +
 +        return new ArrayList<AclRole>(roles);
 +    }
 +
 +    @Override
 +    public AclRolePermission getAclRolePermission(long accountId, String entityType, AccessType accessType) {
 +        List<AclRole> roles = getAclRoles(accountId);
 +        AclRolePermission curPerm = null;
 +        for (AclRole role : roles) {
 +            AclRolePermission perm = _rolePermissionDao.findByRoleEntityAndPermission(role.getId(), entityType, accessType, true);
 +            if (perm == null)
 +                continue;
 +            if (curPerm == null) {
 +                curPerm = perm;
 +            } else if (perm.getScope().greaterThan(curPerm.getScope())) {
 +                // pick the more relaxed allowed permission
 +                curPerm = perm;
 +            }
 +        }
 +
 +        return curPerm;
 +    }
 +
 +    @Override
 +    public List<AclGroup> getAclGroups(long accountId) {
 +
 +        GenericSearchBuilder<AclGroupAccountMapVO, Long> groupSB = _aclGroupAccountMapDao.createSearchBuilder(Long.class);
-         groupSB.selectField(groupSB.entity().getAclGroupId());
++        groupSB.selectFields(groupSB.entity().getAclGroupId());
 +        groupSB.and("account", groupSB.entity().getAccountId(), Op.EQ);
 +        SearchCriteria<Long> groupSc = groupSB.create();
 +
 +        List<Long> groupIds = _aclGroupAccountMapDao.customSearch(groupSc, null);
 +
 +        SearchBuilder<AclGroupVO> sb = _aclGroupDao.createSearchBuilder();
 +        sb.and("ids", sb.entity().getId(), Op.IN);
 +        SearchCriteria<AclGroupVO> sc = sb.create();
 +        sc.setParameters("ids", groupIds.toArray(new Object[groupIds.size()]));
 +        List<AclGroupVO> groups = _aclGroupDao.search(sc, null);
 +
 +        return new ArrayList<AclGroup>(groups);
 +    }
 +
 +    @Override
 +    public Pair<List<Long>, List<Long>> getAclEntityPermission(long accountId, String entityType, AccessType accessType) {
 +        List<AclGroup> groups = getAclGroups(accountId);
 +        if (groups == null || groups.size() == 0) {
 +            return new Pair<List<Long>, List<Long>>(new ArrayList<Long>(), new ArrayList<Long>());
 +        }
 +        Set<Long> allowedIds = new HashSet<Long>();
 +        Set<Long> deniedIds = new HashSet<Long>();
 +        for (AclGroup grp : groups) {
 +            // get allowed id  and denied list for each group
 +            List<Long> allowedIdList = _entityPermissionDao.findEntityIdByGroupAndPermission(grp.getId(), entityType, accessType, true);
 +            if (allowedIdList != null) {
 +                allowedIds.addAll(allowedIdList);
 +            }
 +            List<Long> deniedIdList = _entityPermissionDao.findEntityIdByGroupAndPermission(grp.getId(), entityType, accessType, false);
 +            if (deniedIdList != null) {
 +                deniedIds.addAll(deniedIdList);
 +            }
 +        }
 +        return new Pair<List<Long>, List<Long>>(new ArrayList<Long>(allowedIds), new ArrayList<Long>(deniedIds))
 +        ;
 +    }
 +
 +    @Override
 +    public boolean isAPIAccessibleForRoles(String apiName, List<AclRole> roles) {
 +
 +        boolean accessible = false;
 +
 +        List<Long> roleIds = new ArrayList<Long>();
 +        for (AclRole role : roles) {
 +            roleIds.add(role.getId());
 +        }
 +
 +        SearchBuilder<AclApiPermissionVO> sb = _apiPermissionDao.createSearchBuilder();
 +        sb.and("apiName", sb.entity().getApiName(), Op.EQ);
 +        sb.and("roleId", sb.entity().getAclRoleId(), Op.IN);
 +
 +        SearchCriteria<AclApiPermissionVO> sc = sb.create();
 +        sc.setParameters("roleId", roleIds.toArray(new Object[roleIds.size()]));
 +
 +        List<AclApiPermissionVO> permissions = _apiPermissionDao.customSearch(sc, null);
 +
 +        if (permissions != null && !permissions.isEmpty()) {
 +            accessible = true;
 +        }
 +
 +        return accessible;
 +    }
 +
 +    @Override
 +    public List<AclRole> getEffectiveRoles(Account caller, ControlledEntity entity) {
 +
 +        // Get the static Roles of the Caller
 +        List<AclRole> roles = getAclRoles(caller.getId());
 +
 +        // add any dynamic roles w.r.t the entity
 +        if (caller.getId() == entity.getAccountId()) {
 +            // The caller owns the entity
 +            AclRole owner = _aclRoleDao.findByName(Domain.ROOT_DOMAIN, "RESOURCE_OWNER");
 +            roles.add(owner);
 +        }
 +
 +        return roles;
 +    }
 +
 +}

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/2ef4d520/server/src/org/apache/cloudstack/affinity/AffinityGroupServiceImpl.java
----------------------------------------------------------------------
diff --cc server/src/org/apache/cloudstack/affinity/AffinityGroupServiceImpl.java
index 9343b22,b7b51c9..ebcdc60
--- a/server/src/org/apache/cloudstack/affinity/AffinityGroupServiceImpl.java
+++ b/server/src/org/apache/cloudstack/affinity/AffinityGroupServiceImpl.java
@@@ -159,9 -166,9 +166,9 @@@ public class AffinityGroupServiceImpl e
                      "Unable to create affinity group, no Affinity Group Types configured");
          }
  
-         AffinityGroupProcessor processor = typeProcessorMap.get(affinityGroupType);
+         final AffinityGroupProcessor processor = typeProcessorMap.get(affinityGroupType);
  
 -        if (processor.isAdminControlledGroup() && !_accountMgr.isRootAdmin(caller.getType())) {
 +        if (processor.isAdminControlledGroup() && !_accountMgr.isRootAdmin(caller.getId())) {
              throw new PermissionDeniedException("Cannot create the affinity group");
          }
  
@@@ -210,21 -217,26 +217,26 @@@
                      + affinityGroupName + " already exisits under the domain.");
          }
  
-         Transaction txn = Transaction.currentTxn();
-         txn.start();
-         
-         AffinityGroupVO group = new AffinityGroupVO(affinityGroupName, affinityGroupType, description, owner.getDomainId(),
-                 owner.getId(), aclType);
+         final Account ownerFinal = owner;
+         final ControlledEntity.ACLType aclTypeFinal = aclType;
+         AffinityGroupVO group = Transaction.execute(new TransactionCallback<AffinityGroupVO>() {
+             @Override
+             public AffinityGroupVO doInTransaction(TransactionStatus status) {
+                 AffinityGroupVO group = new AffinityGroupVO(affinityGroupName, affinityGroupType, description, ownerFinal.getDomainId(),
+                         ownerFinal.getId(), aclTypeFinal);
 -                _affinityGroupDao.persist(group);
 +        _affinityGroupDao.persist(group);
  
-         if (domainId != null && aclType == ACLType.Domain) {
+                 if (domainId != null && aclTypeFinal == ACLType.Domain) {
 -                    boolean subDomainAccess = false;
 -                    subDomainAccess = processor.subDomainAccess();
 -                    AffinityGroupDomainMapVO domainMap = new AffinityGroupDomainMapVO(group.getId(), domainId, subDomainAccess);
 -                    _affinityGroupDomainMapDao.persist(domainMap);
 -                }
 +            boolean subDomainAccess = false;
 +            subDomainAccess = processor.subDomainAccess();
 +            AffinityGroupDomainMapVO domainMap = new AffinityGroupDomainMapVO(group.getId(), domainId, subDomainAccess);
 +            _affinityGroupDomainMapDao.persist(domainMap);
 +        }
  
-         txn.commit();
+                 return group;
+             }
+         });
+         
  
          if (s_logger.isDebugEnabled()) {
              s_logger.debug("Created affinity group =" + affinityGroupName);
@@@ -265,35 -277,38 +277,38 @@@
          // check permissions
          _accountMgr.checkAccess(caller, AccessType.ModifyEntry, true, group);
  
-         final Transaction txn = Transaction.currentTxn();
-         txn.start();
+         final Long affinityGroupIdFinal = affinityGroupId;
+         Transaction.execute(new TransactionCallbackNoReturn() {
+             @Override
+             public void doInTransactionWithoutResult(TransactionStatus status) {
  
-         group = _affinityGroupDao.lockRow(affinityGroupId, true);
+                 AffinityGroupVO group = _affinityGroupDao.lockRow(affinityGroupIdFinal, true);
 -                if (group == null) {
 +        if (group == null) {
-             throw new InvalidParameterValueException("Unable to find affinity group by id " + affinityGroupId);
+                     throw new InvalidParameterValueException("Unable to find affinity group by id " + affinityGroupIdFinal);
 -                }
 -        
 +        }
 +
-         List<AffinityGroupVMMapVO> affinityGroupVmMap = _affinityGroupVMMapDao.listByAffinityGroup(affinityGroupId);
+                 List<AffinityGroupVMMapVO> affinityGroupVmMap = _affinityGroupVMMapDao.listByAffinityGroup(affinityGroupIdFinal);
 -                if (!affinityGroupVmMap.isEmpty()) {
 -                    SearchBuilder<AffinityGroupVMMapVO> listByAffinityGroup = _affinityGroupVMMapDao.createSearchBuilder();
 -                    listByAffinityGroup.and("affinityGroupId", listByAffinityGroup.entity().getAffinityGroupId(),
 -                            SearchCriteria.Op.EQ);
 -                    listByAffinityGroup.done();
 -                    SearchCriteria<AffinityGroupVMMapVO> sc = listByAffinityGroup.create();
 +        if (!affinityGroupVmMap.isEmpty()) {
 +            SearchBuilder<AffinityGroupVMMapVO> listByAffinityGroup = _affinityGroupVMMapDao.createSearchBuilder();
 +            listByAffinityGroup.and("affinityGroupId", listByAffinityGroup.entity().getAffinityGroupId(),
 +                    SearchCriteria.Op.EQ);
 +            listByAffinityGroup.done();
 +            SearchCriteria<AffinityGroupVMMapVO> sc = listByAffinityGroup.create();
-             sc.setParameters("affinityGroupId", affinityGroupId);
+                     sc.setParameters("affinityGroupId", affinityGroupIdFinal);
 -        
 -                    _affinityGroupVMMapDao.lockRows(sc, null, true);
 -                    _affinityGroupVMMapDao.remove(sc);
 -                }
 -        
 -                // call processor to handle the group delete
 -                AffinityGroupProcessor processor = getAffinityGroupProcessorForType(group.getType());
 -                if (processor != null) {
 -                    processor.handleDeleteGroup(group);
 -                }
 -        
 +
 +            _affinityGroupVMMapDao.lockRows(sc, null, true);
 +            _affinityGroupVMMapDao.remove(sc);
 +        }
 +
 +        // call processor to handle the group delete
 +        AffinityGroupProcessor processor = getAffinityGroupProcessorForType(group.getType());
 +        if (processor != null) {
 +            processor.handleDeleteGroup(group);
 +        }
 +
-         _affinityGroupDao.expunge(affinityGroupId);
-         txn.commit();
+                 _affinityGroupDao.expunge(affinityGroupIdFinal);
+             }
+         });
  
          if (s_logger.isDebugEnabled()) {
              s_logger.debug("Deleted affinity group id=" + affinityGroupId);

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/2ef4d520/setup/db/db/schema-421to430.sql
----------------------------------------------------------------------
diff --cc setup/db/db/schema-421to430.sql
index 0000000,803f1d9..5d7ba4c
mode 000000,100644..100644
--- a/setup/db/db/schema-421to430.sql
+++ b/setup/db/db/schema-421to430.sql
@@@ -1,0 -1,483 +1,666 @@@
+ -- Licensed to the Apache Software Foundation (ASF) under one
+ -- or more contributor license agreements.  See the NOTICE file
+ -- distributed with this work for additional information
+ -- regarding copyright ownership.  The ASF licenses this file
+ -- to you under the Apache License, Version 2.0 (the
+ -- "License"); you may not use this file except in compliance
+ -- with the License.  You may obtain a copy of the License at
+ --
+ --   http://www.apache.org/licenses/LICENSE-2.0
+ --
+ -- Unless required by applicable law or agreed to in writing,
+ -- software distributed under the License is distributed on an
+ -- "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ -- KIND, either express or implied.  See the License for the
+ -- specific language governing permissions and limitations
+ -- under the License.
+ 
+ --;
+ -- Schema upgrade from 4.2.0 to 4.3.0;
+ --;
+ 
+ -- Disable foreign key checking
+ SET foreign_key_checks = 0;
+ 
+ ALTER TABLE `cloud`.`async_job` ADD COLUMN `related` CHAR(40) NOT NULL;
+ ALTER TABLE `cloud`.`async_job` DROP COLUMN `session_key`;
+ ALTER TABLE `cloud`.`async_job` DROP COLUMN `job_cmd_originator`;
+ ALTER TABLE `cloud`.`async_job` DROP COLUMN `callback_type`;
+ ALTER TABLE `cloud`.`async_job` DROP COLUMN `callback_address`;
+ 
+ ALTER TABLE `cloud`.`async_job` ADD COLUMN `job_type` VARCHAR(32);
+ ALTER TABLE `cloud`.`async_job` ADD COLUMN `job_dispatcher` VARCHAR(64);
+ ALTER TABLE `cloud`.`async_job` ADD COLUMN `job_executing_msid` bigint;
+ ALTER TABLE `cloud`.`async_job` ADD COLUMN `job_pending_signals` int(10) NOT NULL DEFAULT 0;
+ 
+ ALTER TABLE `cloud`.`network_offerings` ADD COLUMN `keep_alive_enabled` int(1) unsigned NOT NULL DEFAULT 1 COMMENT 'true if connection should be reset after requests.';
+ 
+ ALTER TABLE `cloud`.`vm_instance` ADD COLUMN `power_state` VARCHAR(74) DEFAULT 'PowerUnknown';
+ ALTER TABLE `cloud`.`vm_instance` ADD COLUMN `power_state_update_time` DATETIME;
+ ALTER TABLE `cloud`.`vm_instance` ADD COLUMN `power_state_update_count` INT DEFAULT 0;
+ ALTER TABLE `cloud`.`vm_instance` ADD COLUMN `power_host` bigint unsigned;
+ ALTER TABLE `cloud`.`vm_instance` ADD CONSTRAINT `fk_vm_instance__power_host` FOREIGN KEY (`power_host`) REFERENCES `cloud`.`host`(`id`);
+ 
+ DROP TABLE IF EXISTS `cloud`.`vm_snapshot_details`;
+ CREATE TABLE `cloud`.`vm_snapshot_details` (
+   `id` bigint unsigned UNIQUE NOT NULL,
+   `vm_snapshot_id` bigint unsigned NOT NULL,
+   `name` varchar(255) NOT NULL,
+   `value` varchar(255) NOT NULL,
+   PRIMARY KEY (`id`)
+ ) ENGINE=InnoDB DEFAULT CHARSET=utf8;
+ 
+ CREATE TABLE `cloud`.`vm_work_job` (
+   `id` bigint unsigned UNIQUE NOT NULL,
+   `step` char(32) NOT NULL COMMENT 'state',
+   `vm_type` char(32) NOT NULL COMMENT 'type of vm',
+   `vm_instance_id` bigint unsigned NOT NULL COMMENT 'vm instance',
+   PRIMARY KEY (`id`),
+   CONSTRAINT `fk_vm_work_job__instance_id` FOREIGN KEY (`vm_instance_id`) REFERENCES `vm_instance`(`id`) ON DELETE CASCADE,
+   INDEX `i_vm_work_job__vm`(`vm_type`, `vm_instance_id`),
+   INDEX `i_vm_work_job__step`(`step`)
+ ) ENGINE=InnoDB DEFAULT CHARSET=utf8;
+ 
+ CREATE TABLE `cloud`.`async_job_journal` (
+   `id` bigint unsigned NOT NULL AUTO_INCREMENT COMMENT 'id',
+   `job_id` bigint unsigned NOT NULL,
+   `journal_type` varchar(32),
+   `journal_text` varchar(1024) COMMENT 'journal descriptive informaton',
+   `journal_obj` varchar(1024) COMMENT 'journal strutural information, JSON encoded object',
+   `created` datetime NOT NULL COMMENT 'date created',
+   PRIMARY KEY (`id`),
+   CONSTRAINT `fk_async_job_journal__job_id` FOREIGN KEY (`job_id`) REFERENCES `async_job`(`id`) ON DELETE CASCADE
+ ) ENGINE=InnoDB DEFAULT CHARSET=utf8;
+ 
+ CREATE TABLE `cloud`.`async_job_join_map` (
+   `id` bigint unsigned NOT NULL AUTO_INCREMENT COMMENT 'id',
+   `job_id` bigint unsigned NOT NULL,
+   `join_job_id` bigint unsigned NOT NULL,
+   `join_status` int NOT NULL,
+   `join_result` varchar(1024),
+   `join_msid` bigint,
+   `complete_msid` bigint,
+   `sync_source_id` bigint COMMENT 'upper-level job sync source info before join',
+   `wakeup_handler` varchar(64),
+   `wakeup_dispatcher` varchar(64),
+   `wakeup_interval` bigint NOT NULL DEFAULT 3000 COMMENT 'wakeup interval in seconds',
+   `created` datetime NOT NULL,
+   `last_updated` datetime,
+   `next_wakeup` datetime,
+   `expiration` datetime,
+   PRIMARY KEY (`id`),
+   CONSTRAINT `fk_async_job_join_map__job_id` FOREIGN KEY (`job_id`) REFERENCES `async_job`(`id`) ON DELETE CASCADE,
+   CONSTRAINT `fk_async_job_join_map__join_job_id` FOREIGN KEY (`join_job_id`) REFERENCES `async_job`(`id`),
+   CONSTRAINT `fk_async_job_join_map__join` UNIQUE (`job_id`, `join_job_id`),
+   INDEX `i_async_job_join_map__join_job_id`(`join_job_id`),
+   INDEX `i_async_job_join_map__created`(`created`),
+   INDEX `i_async_job_join_map__last_updated`(`last_updated`),
+   INDEX `i_async_job_join_map__next_wakeup`(`next_wakeup`),
+   INDEX `i_async_job_join_map__expiration`(`expiration`)
+ ) ENGINE=InnoDB DEFAULT CHARSET=utf8;
+ 
+ ALTER TABLE `cloud`.`configuration` ADD COLUMN `default_value` VARCHAR(4095) COMMENT 'Default value for a configuration parameter';
+ ALTER TABLE `cloud`.`configuration` ADD COLUMN `updated` datetime COMMENT 'Time this was updated by the server. null means this row is obsolete.';
+ ALTER TABLE `cloud`.`configuration` ADD COLUMN `scope` VARCHAR(255) DEFAULT NULL COMMENT 'Can this parameter be scoped';
+ ALTER TABLE `cloud`.`configuration` ADD COLUMN `is_dynamic` TINYINT(1) NOT NULL DEFAULT 0 COMMENT 'Can the parameter be change dynamically without restarting the server';
+ 
+ UPDATE `cloud`.`configuration` SET `default_value` = `value`;
+ 
+ #Upgrade the offerings and template table to have actual remove and states
+ ALTER TABLE `cloud`.`disk_offering` ADD COLUMN `state` CHAR(40) NOT NULL DEFAULT 'Active' COMMENT 'state for disk offering';
+ 
+ UPDATE `cloud`.`disk_offering` SET `state`='Inactive' WHERE `removed` IS NOT NULL;
+ UPDATE `cloud`.`disk_offering` SET `removed`=NULL;
+ 
+ UPDATE `cloud`.`vm_template` SET `state`='Inactive' WHERE `removed` IS NOT NULL;
+ UPDATE `cloud`.`vm_template` SET `state`='Active' WHERE `removed` IS NULL;
+ UPDATE `cloud`.`vm_template` SET `removed`=NULL;
+ 
+ ALTER TABLE `cloud`.`remote_access_vpn` MODIFY COLUMN `network_id` bigint unsigned;
+ ALTER TABLE `cloud`.`remote_access_vpn` ADD COLUMN `vpc_id` bigint unsigned default NULL;
+ 
+ DROP VIEW IF EXISTS `cloud`.`disk_offering_view`;
+ CREATE VIEW `cloud`.`disk_offering_view` AS
+     select
+         disk_offering.id,
+         disk_offering.uuid,
+         disk_offering.name,
+         disk_offering.display_text,
+         disk_offering.disk_size,
+         disk_offering.min_iops,
+         disk_offering.max_iops,
+         disk_offering.created,
+         disk_offering.tags,
+         disk_offering.customized,
+         disk_offering.customized_iops,
+         disk_offering.removed,
+         disk_offering.use_local_storage,
+         disk_offering.system_use,
+         disk_offering.bytes_read_rate,
+         disk_offering.bytes_write_rate,
+         disk_offering.iops_read_rate,
+         disk_offering.iops_write_rate,
+         disk_offering.sort_key,
+         disk_offering.type,
+ 		disk_offering.display_offering,
+         domain.id domain_id,
+         domain.uuid domain_uuid,
+         domain.name domain_name,
+         domain.path domain_path
+     from
+         `cloud`.`disk_offering`
+             left join
+         `cloud`.`domain` ON disk_offering.domain_id = domain.id
+ 	where
+ 		disk_offering.state='ACTIVE';
+ 
+ DROP VIEW IF EXISTS `cloud`.`service_offering_view`;
+ CREATE VIEW `cloud`.`service_offering_view` AS
+     select 
+         service_offering.id,
+         disk_offering.uuid,
+         disk_offering.name,
+         disk_offering.display_text,
+         disk_offering.created,
+         disk_offering.tags,
+         disk_offering.removed,
+         disk_offering.use_local_storage,
+         disk_offering.system_use,
+         disk_offering.bytes_read_rate,
+         disk_offering.bytes_write_rate,
+         disk_offering.iops_read_rate,
+         disk_offering.iops_write_rate,
+         service_offering.cpu,
+         service_offering.speed,
+         service_offering.ram_size,
+         service_offering.nw_rate,
+         service_offering.mc_rate,
+         service_offering.ha_enabled,
+         service_offering.limit_cpu_use,
+         service_offering.host_tag,
+         service_offering.default_use,
+         service_offering.vm_type,
+         service_offering.sort_key,
+         service_offering.is_volatile,
+         service_offering.deployment_planner,
+         domain.id domain_id,
+         domain.uuid domain_uuid,
+         domain.name domain_name,
+         domain.path domain_path
+     from
+         `cloud`.`service_offering`
+             inner join
+         `cloud`.`disk_offering` ON service_offering.id = disk_offering.id
+             left join
+         `cloud`.`domain` ON disk_offering.domain_id = domain.id
+ 	where
+ 		disk_offering.state='Active';
+ 		
+ DROP VIEW IF EXISTS `cloud`.`template_view`;
+ CREATE VIEW `cloud`.`template_view` AS
+     select 
+         vm_template.id,
+         vm_template.uuid,
+         vm_template.unique_name,
+         vm_template.name,
+         vm_template.public,
+         vm_template.featured,
+         vm_template.type,
+         vm_template.hvm,
+         vm_template.bits,
+         vm_template.url,
+         vm_template.format,
+         vm_template.created,
+         vm_template.checksum,
+         vm_template.display_text,
+         vm_template.enable_password,
+         vm_template.dynamically_scalable,
+         vm_template.guest_os_id,
+         guest_os.uuid guest_os_uuid,
+         guest_os.display_name guest_os_name,
+         vm_template.bootable,
+         vm_template.prepopulate,
+         vm_template.cross_zones,
+         vm_template.hypervisor_type,
+         vm_template.extractable,
+         vm_template.template_tag,
+         vm_template.sort_key,
+         vm_template.removed,
+         vm_template.enable_sshkey,
+         source_template.id source_template_id,
+         source_template.uuid source_template_uuid,
+         account.id account_id,
+         account.uuid account_uuid,
+         account.account_name account_name,
+         account.type account_type,
+         domain.id domain_id,
+         domain.uuid domain_uuid,
+         domain.name domain_name,
+         domain.path domain_path,
+         projects.id project_id,
+         projects.uuid project_uuid,
+         projects.name project_name,        
+         data_center.id data_center_id,
+         data_center.uuid data_center_uuid,
+         data_center.name data_center_name,
+         launch_permission.account_id lp_account_id,
+         template_store_ref.store_id,
+ 		image_store.scope as store_scope,
+         template_store_ref.state,
+         template_store_ref.download_state,
+         template_store_ref.download_pct,
+         template_store_ref.error_str,
+         template_store_ref.size,
+         template_store_ref.destroyed,
+         template_store_ref.created created_on_store,
+         vm_template_details.name detail_name,
+         vm_template_details.value detail_value,
+         resource_tags.id tag_id,
+         resource_tags.uuid tag_uuid,
+         resource_tags.key tag_key,
+         resource_tags.value tag_value,
+         resource_tags.domain_id tag_domain_id,
+         resource_tags.account_id tag_account_id,
+         resource_tags.resource_id tag_resource_id,
+         resource_tags.resource_uuid tag_resource_uuid,
+         resource_tags.resource_type tag_resource_type,
+         resource_tags.customer tag_customer,
+ 		CONCAT(vm_template.id, '_', IFNULL(data_center.id, 0)) as temp_zone_pair
+     from
+         `cloud`.`vm_template`
+             inner join
+         `cloud`.`guest_os` ON guest_os.id = vm_template.guest_os_id        
+             inner join
+         `cloud`.`account` ON account.id = vm_template.account_id
+             inner join
+         `cloud`.`domain` ON domain.id = account.domain_id
+             left join
+         `cloud`.`projects` ON projects.project_account_id = account.id    
+             left join
+         `cloud`.`vm_template_details` ON vm_template_details.template_id = vm_template.id         
+             left join
+         `cloud`.`vm_template` source_template ON source_template.id = vm_template.source_template_id    
+             left join
+         `cloud`.`template_store_ref` ON template_store_ref.template_id = vm_template.id and template_store_ref.store_role = 'Image'
+             left join
+         `cloud`.`image_store` ON image_store.removed is NULL AND template_store_ref.store_id is not NULL AND image_store.id = template_store_ref.store_id 
+         	left join
+         `cloud`.`template_zone_ref` ON template_zone_ref.template_id = vm_template.id AND template_store_ref.store_id is NULL AND template_zone_ref.removed is null    
+             left join
+         `cloud`.`data_center` ON (image_store.data_center_id = data_center.id OR template_zone_ref.zone_id = data_center.id)
+             left join
+         `cloud`.`launch_permission` ON launch_permission.template_id = vm_template.id
+             left join
+         `cloud`.`resource_tags` ON resource_tags.resource_id = vm_template.id
+             and (resource_tags.resource_type = 'Template' or resource_tags.resource_type='ISO')
+     where
 -        vm_template.state='Active';
++        vm_template.state='Active';	
++        
++-- ACL DB schema        
++CREATE TABLE `cloud`.`acl_group` (
++  `id` bigint unsigned NOT NULL UNIQUE auto_increment,
++  `name` varchar(255) NOT NULL,
++  `description` varchar(255) default NULL,
++  `uuid` varchar(40),
++  `domain_id` bigint unsigned NOT NULL,  
++  `removed` datetime COMMENT 'date the group was removed',
++  `created` datetime COMMENT 'date the group was created',
++  PRIMARY KEY  (`id`),
++  INDEX `i_acl_group__removed`(`removed`),
++  CONSTRAINT `uc_acl_group__uuid` UNIQUE (`uuid`)  
++) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8;
++
++CREATE TABLE `cloud`.`acl_group_account_map` (
++  `id` bigint unsigned NOT NULL auto_increment,
++  `group_id` bigint unsigned NOT NULL,
++  `account_id` bigint unsigned NOT NULL,
++  `removed` datetime COMMENT 'date the account was removed from the group',
++  `created` datetime COMMENT 'date the account was assigned to the group',  
++  PRIMARY KEY  (`id`),
++  CONSTRAINT `fk_acl_group_vm_map__group_id` FOREIGN KEY(`group_id`) REFERENCES `acl_group` (`id`) ON DELETE CASCADE,
++  CONSTRAINT `fk_acl_group_vm_map__account_id` FOREIGN KEY(`account_id`) REFERENCES `account` (`id`) ON DELETE CASCADE
++) ENGINE=InnoDB DEFAULT CHARSET=utf8;        
++
++CREATE TABLE `cloud`.`acl_role` (
++  `id` bigint unsigned NOT NULL UNIQUE auto_increment,
++  `name` varchar(255) NOT NULL,
++  `description` varchar(255) default NULL,  
++  `uuid` varchar(40),
++  `domain_id` bigint unsigned NOT NULL,
++  `removed` datetime COMMENT 'date the role was removed',
++  `created` datetime COMMENT 'date the role was created',
++  `role_type` varchar(64) DEFAULT 'Static' COMMENT 'Static or Dynamic',
++  PRIMARY KEY  (`id`),
++  INDEX `i_acl_role__removed`(`removed`),
++  CONSTRAINT `uc_acl_role__uuid` UNIQUE (`uuid`)  
++) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8;
++
++CREATE TABLE `cloud`.`acl_group_role_map` (
++  `id` bigint unsigned NOT NULL auto_increment,
++  `group_id` bigint unsigned NOT NULL,
++  `role_id` bigint unsigned NOT NULL,
++  `removed` datetime COMMENT 'date the role was revoked from the group',
++  `created` datetime COMMENT 'date the role was granted to the group',   
++  PRIMARY KEY  (`id`),
++  CONSTRAINT `fk_acl_group_role_map__group_id` FOREIGN KEY(`group_id`) REFERENCES `acl_group` (`id`) ON DELETE CASCADE,
++  CONSTRAINT `fk_acl_group_role_map__role_id` FOREIGN KEY(`role_id`) REFERENCES `acl_role` (`id`) ON DELETE CASCADE
++) ENGINE=InnoDB DEFAULT CHARSET=utf8;        
++
++
++INSERT IGNORE INTO `cloud`.`acl_role` (id, name, description, uuid, domain_id, created, role_type) VALUES (1, 'NORMAL', 'Domain user role', UUID(), 1, Now(), 'Static');
++INSERT IGNORE INTO `cloud`.`acl_role` (id, name, description, uuid, domain_id, created, role_type) VALUES (2, 'ADMIN', 'Root admin role', UUID(), 1, Now(), 'Static');
++INSERT IGNORE INTO `cloud`.`acl_role` (id, name, description, uuid, domain_id, created, role_type) VALUES (3, 'DOMAIN_ADMIN', 'Domain admin role', UUID(), 1, Now(), 'Static');
++INSERT IGNORE INTO `cloud`.`acl_role` (id, name, description, uuid, domain_id, created, role_type) VALUES (4, 'RESOURCE_DOMAIN_ADMIN', 'Resource domain admin role', UUID(), 1, Now(), 'Static');
++INSERT IGNORE INTO `cloud`.`acl_role` (id, name, description, uuid, domain_id, created, role_type) VALUES (5, 'READ_ONLY_ADMIN', 'Read only admin role', UUID(), 1, Now(), 'Static');
++INSERT IGNORE INTO `cloud`.`acl_role` (id, name, description, uuid, domain_id, created, role_type) VALUES (6, 'RESOURCE_OWNER', 'Resource owner role', UUID(), 1, Now(), 'Dynamic');
++
++INSERT IGNORE INTO `cloud`.`acl_group` (id, name, description, uuid, domain_id, created) VALUES (1, 'NORMAL', 'Domain user group', UUID(), 1, Now());
++INSERT IGNORE INTO `cloud`.`acl_group` (id, name, description, uuid, domain_id, created) VALUES (2, 'ADMIN', 'Root admin group', UUID(), 1, Now());
++INSERT IGNORE INTO `cloud`.`acl_group` (id, name, description, uuid, domain_id, created) VALUES (3, 'DOMAIN_ADMIN', 'Domain admin group', UUID(), 1, Now());
++INSERT IGNORE INTO `cloud`.`acl_group` (id, name, description, uuid, domain_id, created) VALUES (4, 'RESOURCE_DOMAIN_ADMIN', 'Resource domain admin group', UUID(), 1, Now());
++INSERT IGNORE INTO `cloud`.`acl_group` (id, name, description, uuid, domain_id, created) VALUES (5, 'READ_ONLY_ADMIN', 'Read only admin group', UUID(), 1, Now());
++
++CREATE TABLE `cloud`.`acl_api_permission` (
++  `id` bigint unsigned NOT NULL UNIQUE auto_increment,
++  `role_id` bigint unsigned NOT NULL,
++  `api` varchar(255) NOT NULL,
++  `removed` datetime COMMENT 'date the permission was revoked',
++  `created` datetime COMMENT 'date the permission was granted',  
++  PRIMARY KEY  (`id`),
++  CONSTRAINT `fk_acl_api_permission__role_id` FOREIGN KEY(`role_id`) REFERENCES `acl_role` (`id`) ON DELETE CASCADE
++) ENGINE=InnoDB DEFAULT CHARSET=utf8;
+ 
++CREATE TABLE `cloud`.`acl_entity_permission` (
++  `id` bigint unsigned NOT NULL UNIQUE auto_increment,
++  `group_id` bigint unsigned NOT NULL,
++  `entity_type` varchar(100) NOT NULL,
++  `entity_id` bigint unsigned NOT NULL,
++  `entity_uuid` varchar(40),  
++  `access_type` varchar(40) NOT NULL,
++  `permission` int(1) unsigned NOT NULL COMMENT '1 allowed, 0 for denied',
++  `removed` datetime COMMENT 'date the permission was revoked',
++  `created` datetime COMMENT 'date the permission was granted',   
++  PRIMARY KEY  (`id`),
++  CONSTRAINT `fk_acl_entity_permission__group_id` FOREIGN KEY(`group_id`) REFERENCES `acl_group` (`id`) ON DELETE CASCADE
++) ENGINE=InnoDB DEFAULT CHARSET=utf8;
++
++CREATE TABLE `cloud`.`acl_role_permission` (
++  `id` bigint unsigned NOT NULL UNIQUE auto_increment,
++  `role_id` bigint unsigned NOT NULL,
++  `entity_type` varchar(100) NOT NULL,
++  `access_type` varchar(40) NOT NULL,
++  `scope` varchar(100) NOT NULL,
++  `permission` int(1) unsigned NOT NULL COMMENT '1 allowed, 0 for denied',
++  PRIMARY KEY  (`id`),
++  CONSTRAINT `fk_acl_role_permission___role_id` FOREIGN KEY(`role_id`) REFERENCES `acl_role` (`id`) ON DELETE CASCADE
++) ENGINE=InnoDB DEFAULT CHARSET=utf8;
++
++
++INSERT IGNORE INTO `cloud`.`acl_role_permission` (role_id, entity_type, access_type, scope, permission) VALUES (6, '*', 'CreateEntry', 'ACCOUNT', 1);
++INSERT IGNORE INTO `cloud`.`acl_role_permission` (role_id, entity_type, access_type, scope, permission) VALUES (6, '*', 'ListEntry', 'ACCOUNT', 1);
++INSERT IGNORE INTO `cloud`.`acl_role_permission` (role_id, entity_type, access_type, scope, permission) VALUES (6, '*', 'ModifyEntry', 'ACCOUNT', 1);
++INSERT IGNORE INTO `cloud`.`acl_role_permission` (role_id, entity_type, access_type, scope, permission) VALUES (6, '*', 'DeleteEntry', 'ACCOUNT', 1);
++INSERT IGNORE INTO `cloud`.`acl_role_permission` (role_id, entity_type, access_type, scope, permission) VALUES (6, '*', 'OperateEntry', 'ACCOUNT', 1);
++INSERT IGNORE INTO `cloud`.`acl_role_permission` (role_id, entity_type, access_type, scope, permission) VALUES (3, '*', 'CreateEntry', 'DOMAIN', 1);
++INSERT IGNORE INTO `cloud`.`acl_role_permission` (role_id, entity_type, access_type, scope, permission) VALUES (3, '*', 'ListEntry', 'DOMAIN', 1);
++INSERT IGNORE INTO `cloud`.`acl_role_permission` (role_id, entity_type, access_type, scope, permission) VALUES (3, '*', 'ModifyEntry', 'DOMAIN', 1);
++INSERT IGNORE INTO `cloud`.`acl_role_permission` (role_id, entity_type, access_type, scope, permission) VALUES (3, '*', 'DeleteEntry', 'DOMAIN', 1);
++INSERT IGNORE INTO `cloud`.`acl_role_permission` (role_id, entity_type, access_type, scope, permission) VALUES (3, '*', 'OperateEntry', 'DOMAIN', 1);
++INSERT IGNORE INTO `cloud`.`acl_role_permission` (role_id, entity_type, access_type, scope, permission) VALUES (2, '*', 'CreateEntry', 'REGION', 1);
++INSERT IGNORE INTO `cloud`.`acl_role_permission` (role_id, entity_type, access_type, scope, permission) VALUES (2, '*', 'ListEntry', 'REGION', 1);
++INSERT IGNORE INTO `cloud`.`acl_role_permission` (role_id, entity_type, access_type, scope, permission) VALUES (2, '*', 'ModifyEntry', 'REGION', 1);
++INSERT IGNORE INTO `cloud`.`acl_role_permission` (role_id, entity_type, access_type, scope, permission) VALUES (2, '*', 'DeleteEntry', 'REGION', 1);
++INSERT IGNORE INTO `cloud`.`acl_role_permission` (role_id, entity_type, access_type, scope, permission) VALUES (2, '*', 'OperateEntry', 'REGION', 1);
++INSERT IGNORE INTO `cloud`.`acl_role_permission` (role_id, entity_type, access_type, scope, permission) VALUES (1, '*', 'CreateEntry', 'ACCOUNT', 1);
++INSERT IGNORE INTO `cloud`.`acl_role_permission` (role_id, entity_type, access_type, scope, permission) VALUES (1, '*', 'ListEntry', 'ACCOUNT', 1);
++INSERT IGNORE INTO `cloud`.`acl_role_permission` (role_id, entity_type, access_type, scope, permission) VALUES (1, '*', 'ModifyEntry', 'ACCOUNT', 1);
++INSERT IGNORE INTO `cloud`.`acl_role_permission` (role_id, entity_type, access_type, scope, permission) VALUES (1, '*', 'DeleteEntry', 'ACCOUNT', 1);
++INSERT IGNORE INTO `cloud`.`acl_role_permission` (role_id, entity_type, access_type, scope, permission) VALUES (1, '*', 'OperateEntry', 'ACCOUNT', 1);
++
++DROP VIEW IF EXISTS `cloud`.`acl_role_view`;
++CREATE VIEW `cloud`.`acl_role_view` AS
++    select 
++        acl_role.id id,
++        acl_role.uuid uuid,        
++        acl_role.name name,
++        acl_role.description description,
++        acl_role.removed removed,
++        acl_role.created created,
++        domain.id domain_id,
++        domain.uuid domain_uuid,
++        domain.name domain_name,
++        domain.path domain_path,
++        acl_api_permission.api api_name
++    from
++        `cloud`.`acl_role`
++            inner join
++        `cloud`.`domain` ON acl_role.domain_id = domain.id
++            left join
++        `cloud`.`acl_api_permission` ON acl_role.id = acl_api_permission.role_id;
++ 
++ 
++DROP VIEW IF EXISTS `cloud`.`acl_group_view`;
++CREATE VIEW `cloud`.`acl_group_view` AS
++    select 
++        acl_group.id id,
++        acl_group.uuid uuid,        
++        acl_group.name name,
++        acl_group.description description,
++        acl_group.removed removed,
++        acl_group.created created,
++        domain.id domain_id,
++        domain.uuid domain_uuid,
++        domain.name domain_name,
++        domain.path domain_path,
++        acl_role.id role_id,
++        acl_role.uuid role_uuid,
++        acl_role.name role_name,
++        account.id account_id,
++        account.uuid account_uuid,
++        account.account_name account_name,
++        acl_entity_permission.entity_id entity_id,
++        acl_entity_permission.entity_uuid entity_uuid,
++        acl_entity_permission.entity_type entity_type,
++        acl_entity_permission.access_type access_type
++    from
++        `cloud`.`acl_group`
++            inner join
++        `cloud`.`domain` ON acl_group.domain_id = domain.id
++            left join
++        `cloud`.`acl_group_role_map` on acl_group.id = acl_group_role_map.group_id  
++            left join         
++        `cloud`.`acl_role` on acl_group_role_map.role_id = acl_role.id    
++            left join
++        `cloud`.`acl_group_account_map` ON acl_group.id = acl_group_account_map.group_id
++            left join
++        `cloud`.`account` ON acl_group_account_map.account_id = account.id
++            left join
++         `cloud`.`acl_entity_permission` ON acl_group.id = acl_entity_permission.group_id;                         
++ 
+ DROP VIEW IF EXISTS `cloud`.`volume_view`;
+ CREATE VIEW `cloud`.`volume_view` AS
+     select
+         volumes.id,
+         volumes.uuid,
+         volumes.name,
+         volumes.device_id,
+         volumes.volume_type,
+         volumes.size,
+         volumes.min_iops,
+         volumes.max_iops,
+         volumes.created,
+         volumes.state,
+         volumes.attached,
+         volumes.removed,
+         volumes.pod_id,
 -	volumes.display_volume,
++        volumes.display_volume,
+         volumes.format,
 -	volumes.path,
++        volumes.path,
+         account.id account_id,
+         account.uuid account_uuid,
+         account.account_name account_name,
+         account.type account_type,
+         domain.id domain_id,
+         domain.uuid domain_uuid,
+         domain.name domain_name,
+         domain.path domain_path,
+         projects.id project_id,
+         projects.uuid project_uuid,
+         projects.name project_name,
+         data_center.id data_center_id,
+         data_center.uuid data_center_uuid,
+         data_center.name data_center_name,
 -	data_center.networktype data_center_type,
++        data_center.networktype data_center_type,
+         vm_instance.id vm_id,
+         vm_instance.uuid vm_uuid,
+         vm_instance.name vm_name,
+         vm_instance.state vm_state,
+         vm_instance.vm_type,
+         user_vm.display_name vm_display_name,
+         volume_store_ref.size volume_store_size,
+         volume_store_ref.download_pct,
+         volume_store_ref.download_state,
+         volume_store_ref.error_str,
+         volume_store_ref.created created_on_store,
+         disk_offering.id disk_offering_id,
+         disk_offering.uuid disk_offering_uuid,
+         disk_offering.name disk_offering_name,
+         disk_offering.display_text disk_offering_display_text,
+         disk_offering.use_local_storage,
+         disk_offering.system_use,
+         disk_offering.bytes_read_rate,
+         disk_offering.bytes_write_rate,
+         disk_offering.iops_read_rate,
+         disk_offering.iops_write_rate,
+         storage_pool.id pool_id,
+         storage_pool.uuid pool_uuid,
+         storage_pool.name pool_name,
+         cluster.hypervisor_type,
+         vm_template.id template_id,
+         vm_template.uuid template_uuid,
+         vm_template.extractable,
+         vm_template.type template_type,
+         resource_tags.id tag_id,
+         resource_tags.uuid tag_uuid,
+         resource_tags.key tag_key,
+         resource_tags.value tag_value,
+         resource_tags.domain_id tag_domain_id,
+         resource_tags.account_id tag_account_id,
+         resource_tags.resource_id tag_resource_id,
+         resource_tags.resource_uuid tag_resource_uuid,
+         resource_tags.resource_type tag_resource_type,
+         resource_tags.customer tag_customer,
+         async_job.id job_id,
+         async_job.uuid job_uuid,
+         async_job.job_status job_status,
+         async_job.account_id job_account_id
+     from
+         `cloud`.`volumes`
+             inner join
+         `cloud`.`account` ON volumes.account_id = account.id
+             inner join
+         `cloud`.`domain` ON volumes.domain_id = domain.id
+             left join
+         `cloud`.`projects` ON projects.project_account_id = account.id
+             left join
+         `cloud`.`data_center` ON volumes.data_center_id = data_center.id
+             left join
+         `cloud`.`vm_instance` ON volumes.instance_id = vm_instance.id
+             left join
+         `cloud`.`user_vm` ON user_vm.id = vm_instance.id
+             left join
+         `cloud`.`volume_store_ref` ON volumes.id = volume_store_ref.volume_id
+             left join
+         `cloud`.`disk_offering` ON volumes.disk_offering_id = disk_offering.id
+             left join
+         `cloud`.`storage_pool` ON volumes.pool_id = storage_pool.id
+             left join
+         `cloud`.`cluster` ON storage_pool.cluster_id = cluster.id
+             left join
+         `cloud`.`vm_template` ON volumes.template_id = vm_template.id OR volumes.iso_id = vm_template.id
+             left join
+         `cloud`.`resource_tags` ON resource_tags.resource_id = volumes.id
+             and resource_tags.resource_type = 'Volume'
+             left join
+         `cloud`.`async_job` ON async_job.instance_id = volumes.id
+             and async_job.instance_type = 'Volume'
+             and async_job.job_status = 0;
 -            
++
++
+ DROP VIEW IF EXISTS `cloud`.`storage_pool_view`;
+ CREATE VIEW `cloud`.`storage_pool_view` AS
+     select
+         storage_pool.id,
+         storage_pool.uuid,
+         storage_pool.name,
+         storage_pool.status,
+         storage_pool.path,
+         storage_pool.pool_type,
+         storage_pool.host_address,
+         storage_pool.created,
+         storage_pool.removed,
+         storage_pool.capacity_bytes,
+         storage_pool.capacity_iops,
+         storage_pool.scope,
+         storage_pool.hypervisor,
+         storage_pool.storage_provider_name,
+         cluster.id cluster_id,
+         cluster.uuid cluster_uuid,
+         cluster.name cluster_name,
+         cluster.cluster_type,
+         data_center.id data_center_id,
+         data_center.uuid data_center_uuid,
+         data_center.name data_center_name,
+         data_center.networktype data_center_type,
+         host_pod_ref.id pod_id,
+         host_pod_ref.uuid pod_uuid,
+         host_pod_ref.name pod_name,
+         storage_pool_details.name tag,
+         op_host_capacity.used_capacity disk_used_capacity,
+         op_host_capacity.reserved_capacity disk_reserved_capacity,
+         async_job.id job_id,
+         async_job.uuid job_uuid,
+         async_job.job_status job_status,
+         async_job.account_id job_account_id
+     from
+         `cloud`.`storage_pool`
+             left join
+         `cloud`.`cluster` ON storage_pool.cluster_id = cluster.id
+             left join
+         `cloud`.`data_center` ON storage_pool.data_center_id = data_center.id
+             left join
+         `cloud`.`host_pod_ref` ON storage_pool.pod_id = host_pod_ref.id
+             left join
+         `cloud`.`storage_pool_details` ON storage_pool_details.pool_id = storage_pool.id
+             and storage_pool_details.value = 'true'
+             left join
+         `cloud`.`op_host_capacity` ON storage_pool.id = op_host_capacity.host_id
+             and op_host_capacity.capacity_type = 3
+             left join
+         `cloud`.`async_job` ON async_job.instance_id = storage_pool.id
+             and async_job.instance_type = 'StoragePool'
+             and async_job.job_status = 0;
+             
+             
+             DROP TABLE IF EXISTS `cloud`.`vm_snapshot_details`;
+             
+ CREATE TABLE `cloud`.`firewall_rule_details` (
+   `id` bigint unsigned NOT NULL auto_increment,
+   `firewall_rule_id` bigint unsigned NOT NULL COMMENT 'Firewall rule id',
+   `name` varchar(255) NOT NULL,
+   `value` varchar(1024) NOT NULL,
+   `display` tinyint(1) NOT NULL DEFAULT '0' COMMENT 'True if the detail can be displayed to the end user',
+   PRIMARY KEY (`id`),
+   CONSTRAINT `fk_firewall_rule_details__firewall_rule_id` FOREIGN KEY `fk_firewall_rule_details__firewall_rule_id`(`firewall_rule_id`) REFERENCES `firewall_rules`(`id`) ON DELETE CASCADE
+ ) ENGINE=InnoDB DEFAULT CHARSET=utf8;
+ 
+ 
+ ALTER TABLE `cloud`.`data_center_details` ADD COLUMN `display` tinyint(1) NOT NULL DEFAULT '0' COMMENT 'True if the detail can be displayed to the end user';
+ ALTER TABLE `cloud`.`network_details` CHANGE `display_detail` `display` tinyint(0) NOT NULL DEFAULT '0' COMMENT 'True if the detail can be displayed to the end user';
+ ALTER TABLE `cloud`.`vm_template_details` ADD COLUMN `display` tinyint(1) NOT NULL DEFAULT '0' COMMENT 'True if the detail can be displayed to the end user';
+ ALTER TABLE `cloud`.`volume_details` CHANGE `display_detail` `display` tinyint(1) NOT NULL DEFAULT '0' COMMENT 'True if the detail can be displayed to the end user';
+ ALTER TABLE `cloud`.`nic_details` CHANGE `display_detail` `display` tinyint(1) NOT NULL DEFAULT '0' COMMENT 'True if the detail can be displayed to the end user';
+ ALTER TABLE `cloud`.`user_vm_details` CHANGE `display_detail` `display` tinyint(1) NOT NULL DEFAULT '0' COMMENT 'True if the detail can be displayed to the end user';
+ ALTER TABLE `cloud`.`service_offering_details` ADD COLUMN `display` tinyint(1) NOT NULL DEFAULT '0' COMMENT 'True if the detail can be displayed to the end user';
+ ALTER TABLE `cloud`.`storage_pool_details` ADD COLUMN `display` tinyint(1) NOT NULL DEFAULT '0' COMMENT 'True if the detail can be displayed to the end user';
++

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/2ef4d520/tools/apidoc/gen_toc.py
----------------------------------------------------------------------