cloudstack-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From mc...@apache.org
Subject [1/2] git commit: updated refs/heads/rbac to d4d3c69
Date Sat, 28 Sep 2013 01:21:28 GMT
Updated Branches:
  refs/heads/rbac ed22dfef1 -> d4d3c69a2


Add All Apis for ACL Group.

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

Branch: refs/heads/rbac
Commit: 0be374a79634a1d6ab40b802ab5791e132d4a3c5
Parents: ed22dfe
Author: Min Chen <min.chen@citrix.com>
Authored: Fri Sep 27 18:16:18 2013 -0700
Committer: Min Chen <min.chen@citrix.com>
Committed: Fri Sep 27 18:16:18 2013 -0700

----------------------------------------------------------------------
 api/src/com/cloud/event/EventTypes.java         |   2 +
 .../org/apache/cloudstack/acl/AclService.java   |  24 +---
 .../org/apache/cloudstack/api/ApiConstants.java |   1 +
 .../admin/acl/AddAccountToAclGroupCmd.java      | 121 ++++++++++++++++
 .../command/admin/acl/CreateAclGroupCmd.java    | 137 ++++++++++++++++++
 .../command/admin/acl/DeleteAclGroupCmd.java    |  96 +++++++++++++
 .../api/command/admin/acl/ListAclGroupsCmd.java |  82 +++++++++++
 .../admin/acl/RemoveAccountFromAclGroupCmd.java | 121 ++++++++++++++++
 .../api/response/AccountResponse.java           |   3 +
 .../api/response/AclGroupResponse.java          |  11 +-
 .../apache/cloudstack/query/QueryService.java   |   4 +
 client/tomcatconf/commands.properties.in        |   5 +
 .../org/apache/cloudstack/acl/AclGroupVO.java   |   4 +
 .../acl/dao/AclGroupAccountMapDao.java          |   1 +
 .../acl/dao/AclGroupAccountMapDaoImpl.java      |   8 ++
 .../apache/cloudstack/acl/dao/AclGroupDao.java  |   2 +-
 .../cloudstack/acl/dao/AclGroupDaoImpl.java     |   6 +-
 server/src/com/cloud/api/ApiDBUtils.java        |  19 +++
 .../com/cloud/api/query/QueryManagerImpl.java   | 118 ++++++++++++++-
 .../com/cloud/api/query/ViewResponseHelper.java |  18 +++
 .../com/cloud/server/ManagementServerImpl.java  |  10 ++
 .../apache/cloudstack/acl/AclServiceImpl.java   | 143 +++++++++++++++++--
 setup/db/db/schema-420to430.sql                 |  53 +++++--
 23 files changed, 935 insertions(+), 54 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/cloudstack/blob/0be374a7/api/src/com/cloud/event/EventTypes.java
----------------------------------------------------------------------
diff --git a/api/src/com/cloud/event/EventTypes.java b/api/src/com/cloud/event/EventTypes.java
index 4b98433..5b7bf59 100755
--- a/api/src/com/cloud/event/EventTypes.java
+++ b/api/src/com/cloud/event/EventTypes.java
@@ -451,6 +451,8 @@ public class EventTypes {
     public static final String EVENT_ACL_ROLE_REVOKE = "ACLROLE.REVOKE";
     
     public static final String EVENT_ACL_GROUP_UPDATE = "ACLGROUP.UPDATE";
+    public static final String EVENT_ACL_GROUP_CREATE = "ACLGROUP.CREATE";
+    public static final String EVENT_ACL_GROUP_DELETE = "ACLGROUP.DELETE";
 
     static {
 

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/0be374a7/api/src/org/apache/cloudstack/acl/AclService.java
----------------------------------------------------------------------
diff --git a/api/src/org/apache/cloudstack/acl/AclService.java b/api/src/org/apache/cloudstack/acl/AclService.java
index 0b83a21..1f4d620 100644
--- a/api/src/org/apache/cloudstack/acl/AclService.java
+++ b/api/src/org/apache/cloudstack/acl/AclService.java
@@ -18,8 +18,6 @@ package org.apache.cloudstack.acl;
 
 import java.util.List;
 
-import com.cloud.utils.Pair;
-
 public interface AclService {
 
     /**
@@ -48,6 +46,10 @@ public interface AclService {
 
     AclGroup removeAclRolesFromGroup(List<Long> roleIds, Long groupId);
 
+    AclGroup addAccountsToGroup(List<Long> acctIds, Long groupId);
+
+    AclGroup removeAccountsFromGroup(List<Long> acctIds, Long groupId);
+
     /**
      * Creates an acl group for the given domain.
      *
@@ -66,23 +68,5 @@ public interface AclService {
      */
     boolean deleteAclGroup(Long aclGroupId);
 
-    /** Lists Acl groups for a domain
-     * @param domainId
-     * @param aclGroupId
-     * @param aclGroupName
-     * @param startIndex
-     * @param pageSize
-     * @return
-     */
-    Pair<List<? extends AclRole>, Integer> listAclGroups(Long aclRoleId, String aclRoleName,
-            Long domainId, Long startIndex, Long pageSize);
-
-
-    /**
-     * Get the acl group for the given group id.
-     * @param groupId
-     * @return AclGroup
-     */
-    AclRole getAclGroup(Long groupId);
 
 }

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/0be374a7/api/src/org/apache/cloudstack/api/ApiConstants.java
----------------------------------------------------------------------
diff --git a/api/src/org/apache/cloudstack/api/ApiConstants.java b/api/src/org/apache/cloudstack/api/ApiConstants.java
index da5e3d6..cd8479f 100755
--- a/api/src/org/apache/cloudstack/api/ApiConstants.java
+++ b/api/src/org/apache/cloudstack/api/ApiConstants.java
@@ -524,6 +524,7 @@ public class ApiConstants {
     public static final String ACL_ROLES = "roles";
     public static final String ACL_ROLE_IDS = "roleids";
     public static final String ACL_APIS = "apis";
+    public static final String ACL_GROUPS = "groups";
 
     public enum HostDetails {
         all, capacity, events, stats, min;

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/0be374a7/api/src/org/apache/cloudstack/api/command/admin/acl/AddAccountToAclGroupCmd.java
----------------------------------------------------------------------
diff --git a/api/src/org/apache/cloudstack/api/command/admin/acl/AddAccountToAclGroupCmd.java b/api/src/org/apache/cloudstack/api/command/admin/acl/AddAccountToAclGroupCmd.java
new file mode 100644
index 0000000..854f2b3
--- /dev/null
+++ b/api/src/org/apache/cloudstack/api/command/admin/acl/AddAccountToAclGroupCmd.java
@@ -0,0 +1,121 @@
+// 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.api.command.admin.acl;
+
+import java.util.List;
+
+import org.apache.log4j.Logger;
+
+import org.apache.cloudstack.acl.AclGroup;
+import org.apache.cloudstack.api.ACL;
+import org.apache.cloudstack.api.APICommand;
+import org.apache.cloudstack.api.ApiCommandJobType;
+import org.apache.cloudstack.api.ApiConstants;
+import org.apache.cloudstack.api.ApiErrorCode;
+import org.apache.cloudstack.api.BaseAsyncCmd;
+import org.apache.cloudstack.api.Parameter;
+import org.apache.cloudstack.api.ServerApiException;
+import org.apache.cloudstack.api.response.AccountResponse;
+import org.apache.cloudstack.api.response.AclGroupResponse;
+import org.apache.cloudstack.context.CallContext;
+
+import com.cloud.event.EventTypes;
+import com.cloud.exception.InsufficientCapacityException;
+import com.cloud.exception.ResourceUnavailableException;
+import com.cloud.user.Account;
+
+
+@APICommand(name = "addAccountToAclGroup", description = "add account to an acl group", responseObject = AclGroupResponse.class)
+public class AddAccountToAclGroupCmd extends BaseAsyncCmd {
+    public static final Logger s_logger = Logger.getLogger(AddAccountToAclGroupCmd.class.getName());
+    private static final String s_name = "addaccounttoaclgroupresponse";
+
+    /////////////////////////////////////////////////////
+    //////////////// API parameters /////////////////////
+    /////////////////////////////////////////////////////
+
+
+    @ACL
+    @Parameter(name = ApiConstants.ID, type = CommandType.UUID, entityType = AclGroupResponse.class,
+            required = true, description = "The ID of the acl group")
+    private Long id;
+
+    @ACL
+    @Parameter(name = ApiConstants.ACCOUNTS, type = CommandType.LIST, collectionType = CommandType.UUID, entityType = AccountResponse.class, description = "comma separated list of account id that are going to be assigned to the acl group.")
+    private List<Long> accountIdList;
+
+
+    /////////////////////////////////////////////////////
+    /////////////////// Accessors ///////////////////////
+    /////////////////////////////////////////////////////
+
+
+    public Long getId() {
+        return id;
+    }
+
+
+    public List<Long> getAccountIdList() {
+        return accountIdList;
+    }
+
+    /////////////////////////////////////////////////////
+    /////////////// API Implementation///////////////////
+    /////////////////////////////////////////////////////
+
+
+    @Override
+    public String getCommandName() {
+        return s_name;
+    }
+
+
+    @Override
+    public long getEntityOwnerId() {
+        return Account.ACCOUNT_ID_SYSTEM; // no account info given, parent this command to SYSTEM so ERROR events are tracked
+    }
+
+    @Override
+    public void execute() throws ResourceUnavailableException,
+            InsufficientCapacityException, ServerApiException {
+        CallContext.current().setEventDetails("Acl group Id: " + getId());
+        AclGroup result = _aclService.addAccountsToGroup(accountIdList, id);
+        if (result != null){
+            AclGroupResponse response = _responseGenerator.createAclGroupResponse(result);
+            response.setResponseName(getCommandName());
+            setResponseObject(response);
+        } else {
+            throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, "Failed to add accounts to acl group");
+        }
+    }
+
+    @Override
+    public String getEventType() {
+        return EventTypes.EVENT_ACL_GROUP_UPDATE;
+    }
+
+    @Override
+    public String getEventDescription() {
+        return "adding accounts to acl group";
+    }
+
+    @Override
+    public ApiCommandJobType getInstanceType() {
+        return ApiCommandJobType.AclGroup;
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/0be374a7/api/src/org/apache/cloudstack/api/command/admin/acl/CreateAclGroupCmd.java
----------------------------------------------------------------------
diff --git a/api/src/org/apache/cloudstack/api/command/admin/acl/CreateAclGroupCmd.java b/api/src/org/apache/cloudstack/api/command/admin/acl/CreateAclGroupCmd.java
new file mode 100644
index 0000000..a4bf4b3
--- /dev/null
+++ b/api/src/org/apache/cloudstack/api/command/admin/acl/CreateAclGroupCmd.java
@@ -0,0 +1,137 @@
+// 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.api.command.admin.acl;
+
+import org.apache.log4j.Logger;
+
+import org.apache.cloudstack.acl.AclGroup;
+import org.apache.cloudstack.api.APICommand;
+import org.apache.cloudstack.api.ApiCommandJobType;
+import org.apache.cloudstack.api.ApiConstants;
+import org.apache.cloudstack.api.ApiErrorCode;
+import org.apache.cloudstack.api.BaseAsyncCreateCmd;
+import org.apache.cloudstack.api.Parameter;
+import org.apache.cloudstack.api.ServerApiException;
+import org.apache.cloudstack.api.response.AclGroupResponse;
+import org.apache.cloudstack.api.response.DomainResponse;
+
+import com.cloud.event.EventTypes;
+import com.cloud.exception.ResourceAllocationException;
+import com.cloud.user.Account;
+
+@APICommand(name = "createAclGroup", responseObject = AclGroupResponse.class, description = "Creates an acl group")
+public class CreateAclGroupCmd extends BaseAsyncCreateCmd {
+    public static final Logger s_logger = Logger.getLogger(CreateAclGroupCmd.class.getName());
+
+    private static final String s_name = "createaclgroupresponse";
+
+    // ///////////////////////////////////////////////////
+    // ////////////// API parameters /////////////////////
+    // ///////////////////////////////////////////////////
+
+    @Parameter(name = ApiConstants.DOMAIN_ID, type = CommandType.UUID, description = "domainId of the account owning the acl group", entityType = DomainResponse.class)
+    private Long domainId;
+
+    @Parameter(name = ApiConstants.DESCRIPTION, type = CommandType.STRING, description = "optional description of the acl group")
+    private String description;
+
+    @Parameter(name = ApiConstants.NAME, type = CommandType.STRING, required = true, description = "name of the acl group")
+    private String name;
+
+
+    // ///////////////////////////////////////////////////
+    // ///////////////// Accessors ///////////////////////
+    // ///////////////////////////////////////////////////
+
+
+    public String getDescription() {
+        return description;
+    }
+
+    public Long getDomainId() {
+        return domainId;
+    }
+
+    public String getName() {
+        return name;
+    }
+
+
+    // ///////////////////////////////////////////////////
+    // ///////////// API Implementation///////////////////
+    // ///////////////////////////////////////////////////
+
+    @Override
+    public String getCommandName() {
+        return s_name;
+    }
+
+    @Override
+    public long getEntityOwnerId() {
+        return Account.ACCOUNT_ID_SYSTEM;
+    }
+
+    @Override
+    public void execute() {
+        AclGroup role = _entityMgr.findById(AclGroup.class, getEntityId());
+        if (role != null) {
+            AclGroupResponse response = _responseGenerator.createAclGroupResponse(role);
+            response.setResponseName(getCommandName());
+            setResponseObject(response);
+        } else {
+            throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, "Failed to create acl group:" + name);
+        }
+    }
+
+    @Override
+    public void create() throws ResourceAllocationException {
+        AclGroup result = _aclService.createAclGroup(domainId, name, description);
+        if (result != null) {
+            setEntityId(result.getId());
+            setEntityUuid(result.getUuid());
+        } else {
+            throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, "Failed to create acl group entity" + name);
+        }
+
+    }
+
+    @Override
+    public String getEventType() {
+        return EventTypes.EVENT_ACL_GROUP_CREATE;
+    }
+
+    @Override
+    public String getEventDescription() {
+        return "creating Acl group";
+    }
+
+    @Override
+    public String getCreateEventType() {
+        return EventTypes.EVENT_ACL_GROUP_CREATE;
+    }
+
+    @Override
+    public String getCreateEventDescription() {
+        return "creating acl group";
+    }
+
+    @Override
+    public ApiCommandJobType getInstanceType() {
+        return ApiCommandJobType.AclGroup;
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/0be374a7/api/src/org/apache/cloudstack/api/command/admin/acl/DeleteAclGroupCmd.java
----------------------------------------------------------------------
diff --git a/api/src/org/apache/cloudstack/api/command/admin/acl/DeleteAclGroupCmd.java b/api/src/org/apache/cloudstack/api/command/admin/acl/DeleteAclGroupCmd.java
new file mode 100644
index 0000000..661b9ed
--- /dev/null
+++ b/api/src/org/apache/cloudstack/api/command/admin/acl/DeleteAclGroupCmd.java
@@ -0,0 +1,96 @@
+// 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.api.command.admin.acl;
+
+import org.apache.log4j.Logger;
+
+import org.apache.cloudstack.api.ACL;
+import org.apache.cloudstack.api.APICommand;
+import org.apache.cloudstack.api.ApiCommandJobType;
+import org.apache.cloudstack.api.ApiConstants;
+import org.apache.cloudstack.api.ApiErrorCode;
+import org.apache.cloudstack.api.BaseAsyncCmd;
+import org.apache.cloudstack.api.Parameter;
+import org.apache.cloudstack.api.ServerApiException;
+import org.apache.cloudstack.api.response.AclGroupResponse;
+import org.apache.cloudstack.api.response.SuccessResponse;
+
+import com.cloud.event.EventTypes;
+import com.cloud.user.Account;
+
+@APICommand(name = "deleteAclGroup", description = "Deletes acl group", responseObject = SuccessResponse.class)
+public class DeleteAclGroupCmd extends BaseAsyncCmd {
+    public static final Logger s_logger = Logger.getLogger(DeleteAclGroupCmd.class.getName());
+    private static final String s_name = "deleteaclgroupresponse";
+
+    /////////////////////////////////////////////////////
+    //////////////// API parameters /////////////////////
+    /////////////////////////////////////////////////////
+
+    @ACL
+    @Parameter(name = ApiConstants.ID, type = CommandType.UUID, description = "The ID of the acl group.", required = true, entityType = AclGroupResponse.class)
+    private Long id;
+
+
+    /////////////////////////////////////////////////////
+    /////////////////// Accessors ///////////////////////
+    /////////////////////////////////////////////////////
+
+    public Long getId() {
+        return id;
+    }
+
+    /////////////////////////////////////////////////////
+    /////////////// API Implementation///////////////////
+    /////////////////////////////////////////////////////
+
+    @Override
+    public String getCommandName() {
+        return s_name;
+    }
+
+    @Override
+    public long getEntityOwnerId() {
+        return Account.ACCOUNT_ID_SYSTEM;
+    }
+
+    @Override
+    public void execute(){
+        boolean result = _aclService.deleteAclGroup(id);
+        if (result) {
+            SuccessResponse response = new SuccessResponse(getCommandName());
+            setResponseObject(response);
+        } else {
+            throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, "Failed to delete acl group");
+        }
+    }
+
+    @Override
+    public String getEventType() {
+        return EventTypes.EVENT_ACL_GROUP_DELETE;
+    }
+
+    @Override
+    public String getEventDescription() {
+        return "Deleting Acl group";
+    }
+
+    @Override
+    public ApiCommandJobType getInstanceType() {
+        return ApiCommandJobType.AclGroup;
+    }
+}

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/0be374a7/api/src/org/apache/cloudstack/api/command/admin/acl/ListAclGroupsCmd.java
----------------------------------------------------------------------
diff --git a/api/src/org/apache/cloudstack/api/command/admin/acl/ListAclGroupsCmd.java b/api/src/org/apache/cloudstack/api/command/admin/acl/ListAclGroupsCmd.java
new file mode 100644
index 0000000..881b65a
--- /dev/null
+++ b/api/src/org/apache/cloudstack/api/command/admin/acl/ListAclGroupsCmd.java
@@ -0,0 +1,82 @@
+// 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.api.command.admin.acl;
+
+import org.apache.log4j.Logger;
+
+import org.apache.cloudstack.api.APICommand;
+import org.apache.cloudstack.api.ApiCommandJobType;
+import org.apache.cloudstack.api.ApiConstants;
+import org.apache.cloudstack.api.BaseListDomainResourcesCmd;
+import org.apache.cloudstack.api.Parameter;
+import org.apache.cloudstack.api.response.AclGroupResponse;
+import org.apache.cloudstack.api.response.ListResponse;
+
+
+@APICommand(name = "listAclGroups", description = "Lists acl groups", responseObject = AclGroupResponse.class)
+public class ListAclGroupsCmd extends BaseListDomainResourcesCmd {
+    public static final Logger s_logger = Logger.getLogger(ListAclGroupsCmd.class.getName());
+
+    private static final String s_name = "listaclgroupsresponse";
+
+    /////////////////////////////////////////////////////
+    //////////////// API parameters /////////////////////
+    /////////////////////////////////////////////////////
+
+    @Parameter(name = ApiConstants.NAME, type = CommandType.STRING, description = "lists acl groups by name")
+    private String aclGroupName;
+
+    @Parameter(name = ApiConstants.ID, type = CommandType.UUID, description = "list the acl group by the id provided", entityType = AclGroupResponse.class)
+    private Long id;
+
+
+    /////////////////////////////////////////////////////
+    /////////////////// Accessors ///////////////////////
+    /////////////////////////////////////////////////////
+    public String getAclGroupName() {
+        return aclGroupName;
+    }
+
+
+    public Long getId(){
+        return id;
+    }
+
+    /////////////////////////////////////////////////////
+    /////////////// API Implementation///////////////////
+    /////////////////////////////////////////////////////
+
+    @Override
+    public String getCommandName() {
+        return s_name;
+    }
+
+    @Override
+    public void execute(){
+
+        ListResponse<AclGroupResponse> response = _queryService.listAclGroups(id, aclGroupName, getDomainId(),
+                getStartIndex(), getPageSizeVal());
+        response.setResponseName(getCommandName());
+        setResponseObject(response);
+
+    }
+
+    @Override
+    public ApiCommandJobType getInstanceType() {
+        return ApiCommandJobType.AclGroup;
+    }
+}

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/0be374a7/api/src/org/apache/cloudstack/api/command/admin/acl/RemoveAccountFromAclGroupCmd.java
----------------------------------------------------------------------
diff --git a/api/src/org/apache/cloudstack/api/command/admin/acl/RemoveAccountFromAclGroupCmd.java b/api/src/org/apache/cloudstack/api/command/admin/acl/RemoveAccountFromAclGroupCmd.java
new file mode 100644
index 0000000..d5c5c7c
--- /dev/null
+++ b/api/src/org/apache/cloudstack/api/command/admin/acl/RemoveAccountFromAclGroupCmd.java
@@ -0,0 +1,121 @@
+// 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.api.command.admin.acl;
+
+import java.util.List;
+
+import org.apache.log4j.Logger;
+
+import org.apache.cloudstack.acl.AclGroup;
+import org.apache.cloudstack.api.ACL;
+import org.apache.cloudstack.api.APICommand;
+import org.apache.cloudstack.api.ApiCommandJobType;
+import org.apache.cloudstack.api.ApiConstants;
+import org.apache.cloudstack.api.ApiErrorCode;
+import org.apache.cloudstack.api.BaseAsyncCmd;
+import org.apache.cloudstack.api.Parameter;
+import org.apache.cloudstack.api.ServerApiException;
+import org.apache.cloudstack.api.response.AccountResponse;
+import org.apache.cloudstack.api.response.AclGroupResponse;
+import org.apache.cloudstack.context.CallContext;
+
+import com.cloud.event.EventTypes;
+import com.cloud.exception.InsufficientCapacityException;
+import com.cloud.exception.ResourceUnavailableException;
+import com.cloud.user.Account;
+
+
+@APICommand(name = "removeAccountFromAclGroup", description = "remove accounts from an acl group", responseObject = AclGroupResponse.class)
+public class RemoveAccountFromAclGroupCmd extends BaseAsyncCmd {
+    public static final Logger s_logger = Logger.getLogger(RemoveAccountFromAclGroupCmd.class.getName());
+    private static final String s_name = "removeaccountfromaclgroupresponse";
+
+    /////////////////////////////////////////////////////
+    //////////////// API parameters /////////////////////
+    /////////////////////////////////////////////////////
+
+
+    @ACL
+    @Parameter(name = ApiConstants.ID, type = CommandType.UUID, entityType = AclGroupResponse.class,
+            required = true, description = "The ID of the acl group")
+    private Long id;
+
+    @ACL
+    @Parameter(name = ApiConstants.ACCOUNTS, type = CommandType.LIST, collectionType = CommandType.UUID, entityType = AccountResponse.class, description = "comma separated list of account id that are going to be assigned to the acl group.")
+    private List<Long> accountIdList;
+
+
+    /////////////////////////////////////////////////////
+    /////////////////// Accessors ///////////////////////
+    /////////////////////////////////////////////////////
+
+
+    public Long getId() {
+        return id;
+    }
+
+
+    public List<Long> getAccountIdList() {
+        return accountIdList;
+    }
+
+    /////////////////////////////////////////////////////
+    /////////////// API Implementation///////////////////
+    /////////////////////////////////////////////////////
+
+
+    @Override
+    public String getCommandName() {
+        return s_name;
+    }
+
+
+    @Override
+    public long getEntityOwnerId() {
+        return Account.ACCOUNT_ID_SYSTEM; // no account info given, parent this command to SYSTEM so ERROR events are tracked
+    }
+
+    @Override
+    public void execute() throws ResourceUnavailableException,
+            InsufficientCapacityException, ServerApiException {
+        CallContext.current().setEventDetails("Acl group Id: " + getId());
+        AclGroup result = _aclService.removeAccountsFromGroup(accountIdList, id);
+        if (result != null){
+            AclGroupResponse response = _responseGenerator.createAclGroupResponse(result);
+            response.setResponseName(getCommandName());
+            setResponseObject(response);
+        } else {
+            throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, "Failed to remove accounts from acl group");
+        }
+    }
+
+    @Override
+    public String getEventType() {
+        return EventTypes.EVENT_ACL_GROUP_UPDATE;
+    }
+
+    @Override
+    public String getEventDescription() {
+        return "removing accounts from acl group";
+    }
+
+    @Override
+    public ApiCommandJobType getInstanceType() {
+        return ApiCommandJobType.AclGroup;
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/0be374a7/api/src/org/apache/cloudstack/api/response/AccountResponse.java
----------------------------------------------------------------------
diff --git a/api/src/org/apache/cloudstack/api/response/AccountResponse.java b/api/src/org/apache/cloudstack/api/response/AccountResponse.java
index 957936b..2f96b26 100644
--- a/api/src/org/apache/cloudstack/api/response/AccountResponse.java
+++ b/api/src/org/apache/cloudstack/api/response/AccountResponse.java
@@ -187,6 +187,9 @@ public class AccountResponse extends BaseResponse implements ResourceLimitAndCou
     @SerializedName(ApiConstants.IS_DEFAULT) @Param(description="true if account is default, false otherwise", since="4.2.0")
     private Boolean isDefault;
 
+    @SerializedName(ApiConstants.ACL_GROUPS)
+    @Param(description = "the list of acl groups that account belongs to", responseObject = AclGroupResponse.class)
+    private List<AclGroupResponse> groups;
 
     @Override
     public String getObjectId() {

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/0be374a7/api/src/org/apache/cloudstack/api/response/AclGroupResponse.java
----------------------------------------------------------------------
diff --git a/api/src/org/apache/cloudstack/api/response/AclGroupResponse.java b/api/src/org/apache/cloudstack/api/response/AclGroupResponse.java
index 6e3562a..94fe8b5 100644
--- a/api/src/org/apache/cloudstack/api/response/AclGroupResponse.java
+++ b/api/src/org/apache/cloudstack/api/response/AclGroupResponse.java
@@ -16,9 +16,7 @@
 // under the License.
 package org.apache.cloudstack.api.response;
 
-import java.util.ArrayList;
 import java.util.LinkedHashSet;
-import java.util.List;
 import java.util.Set;
 
 import com.google.gson.annotations.SerializedName;
@@ -56,13 +54,14 @@ public class AclGroupResponse extends BaseResponse {
 
     @SerializedName(ApiConstants.ACL_ACCOUNT_IDS)
     @Param(description = "account Ids assigned to this acl group ")
-    private List<String> accountIdList;
+    private Set<String> accountIdList;
 
     @SerializedName(ApiConstants.ACL_ROLES)
     @Param(description = "acl roles granted to this acl group ")
     private Set<AclRoleResponse> roleList;
 
     public AclGroupResponse() {
+        accountIdList = new LinkedHashSet<String>();
         roleList = new LinkedHashSet<AclRoleResponse>();
     }
 
@@ -97,15 +96,11 @@ public class AclGroupResponse extends BaseResponse {
         this.domainName = domainName;
     }
 
-    public void setAccountIdList(List<String> acctIdList) {
+    public void setAccountIdList(Set<String> acctIdList) {
         accountIdList = acctIdList;
     }
 
     public void addAccountId(String acctId) {
-        if (accountIdList == null) {
-            accountIdList = new ArrayList<String>();
-        }
-
         accountIdList.add(acctId);
     }
 

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/0be374a7/api/src/org/apache/cloudstack/query/QueryService.java
----------------------------------------------------------------------
diff --git a/api/src/org/apache/cloudstack/query/QueryService.java b/api/src/org/apache/cloudstack/query/QueryService.java
index bfddcf3..9b88bdb 100644
--- a/api/src/org/apache/cloudstack/query/QueryService.java
+++ b/api/src/org/apache/cloudstack/query/QueryService.java
@@ -44,6 +44,7 @@ import org.apache.cloudstack.api.command.user.volume.ListResourceDetailsCmd;
 import org.apache.cloudstack.api.command.user.volume.ListVolumesCmd;
 import org.apache.cloudstack.api.command.user.zone.ListZonesByCmd;
 import org.apache.cloudstack.api.response.AccountResponse;
+import org.apache.cloudstack.api.response.AclGroupResponse;
 import org.apache.cloudstack.api.response.AclRoleResponse;
 import org.apache.cloudstack.api.response.AsyncJobResponse;
 import org.apache.cloudstack.api.response.DiskOfferingResponse;
@@ -129,4 +130,7 @@ public interface QueryService {
     public ListResponse<AclRoleResponse> listAclRoles(Long aclRoleId, String aclRoleName,
             Long domainId, Long startIndex, Long pageSize);
 
+    public ListResponse<AclGroupResponse> listAclGroups(Long aclGroupId, String aclGroupName,
+            Long domainId, Long startIndex, Long pageSize);
+
 }

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/0be374a7/client/tomcatconf/commands.properties.in
----------------------------------------------------------------------
diff --git a/client/tomcatconf/commands.properties.in b/client/tomcatconf/commands.properties.in
index be446bc..8aad3a7 100644
--- a/client/tomcatconf/commands.properties.in
+++ b/client/tomcatconf/commands.properties.in
@@ -685,6 +685,11 @@ deleteAclRole=7
 listAclRoles=7
 grantPermissionToAclRole=7
 revokePermissionFromAclRole=7
+createAclGroup=7
+deleteAclGroup=7
+listAclGroups=7
 addAclRoleToAclGroup=7
 removeAclRoleFromAclGroup=7
+addAccountToAclGroup=7
+removeAccountFromAclGroup=7
 

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/0be374a7/engine/schema/src/org/apache/cloudstack/acl/AclGroupVO.java
----------------------------------------------------------------------
diff --git a/engine/schema/src/org/apache/cloudstack/acl/AclGroupVO.java b/engine/schema/src/org/apache/cloudstack/acl/AclGroupVO.java
index 3fbbfc1..45e22eb 100644
--- a/engine/schema/src/org/apache/cloudstack/acl/AclGroupVO.java
+++ b/engine/schema/src/org/apache/cloudstack/acl/AclGroupVO.java
@@ -84,6 +84,10 @@ public class AclGroupVO implements AclGroup {
         return domainId;
     }
 
+    public void setDomainId(long domainId) {
+        this.domainId = domainId;
+    }
+
     @Override
     public String getUuid() {
     	return uuid;

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/0be374a7/engine/schema/src/org/apache/cloudstack/acl/dao/AclGroupAccountMapDao.java
----------------------------------------------------------------------
diff --git a/engine/schema/src/org/apache/cloudstack/acl/dao/AclGroupAccountMapDao.java b/engine/schema/src/org/apache/cloudstack/acl/dao/AclGroupAccountMapDao.java
index 1102047..76d417b 100644
--- a/engine/schema/src/org/apache/cloudstack/acl/dao/AclGroupAccountMapDao.java
+++ b/engine/schema/src/org/apache/cloudstack/acl/dao/AclGroupAccountMapDao.java
@@ -30,4 +30,5 @@ public interface AclGroupAccountMapDao extends GenericDao<AclGroupAccountMapVO,
 
     AclGroupAccountMapVO findAccountInAdminGroup(long accountId);
 
+    AclGroupAccountMapVO findByGroupAndAccount(long groupId, long acctId);
 }

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/0be374a7/engine/schema/src/org/apache/cloudstack/acl/dao/AclGroupAccountMapDaoImpl.java
----------------------------------------------------------------------
diff --git a/engine/schema/src/org/apache/cloudstack/acl/dao/AclGroupAccountMapDaoImpl.java b/engine/schema/src/org/apache/cloudstack/acl/dao/AclGroupAccountMapDaoImpl.java
index d0c8a5b..e389def 100644
--- a/engine/schema/src/org/apache/cloudstack/acl/dao/AclGroupAccountMapDaoImpl.java
+++ b/engine/schema/src/org/apache/cloudstack/acl/dao/AclGroupAccountMapDaoImpl.java
@@ -79,4 +79,12 @@ public class AclGroupAccountMapDaoImpl extends GenericDaoBase<AclGroupAccountMap
         return findOneBy(sc);
     }
 
+    @Override
+    public AclGroupAccountMapVO findByGroupAndAccount(long groupId, long acctId) {
+        SearchCriteria<AclGroupAccountMapVO> sc = _findByAccountAndGroupId.create();
+        sc.setParameters("accountId", acctId);
+        sc.setParameters("groupId", groupId);
+        return findOneBy(sc);
+    }
+
 }

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/0be374a7/engine/schema/src/org/apache/cloudstack/acl/dao/AclGroupDao.java
----------------------------------------------------------------------
diff --git a/engine/schema/src/org/apache/cloudstack/acl/dao/AclGroupDao.java b/engine/schema/src/org/apache/cloudstack/acl/dao/AclGroupDao.java
index 45494ab..ae50776 100644
--- a/engine/schema/src/org/apache/cloudstack/acl/dao/AclGroupDao.java
+++ b/engine/schema/src/org/apache/cloudstack/acl/dao/AclGroupDao.java
@@ -23,6 +23,6 @@ import com.cloud.utils.db.GenericDao;
 
 public interface AclGroupDao extends GenericDao<AclGroupVO, Long> {
 
-    AclGroup findByName(String groupName);
+    AclGroup findByName(Long domainId, String groupName);
 
 }

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/0be374a7/engine/schema/src/org/apache/cloudstack/acl/dao/AclGroupDaoImpl.java
----------------------------------------------------------------------
diff --git a/engine/schema/src/org/apache/cloudstack/acl/dao/AclGroupDaoImpl.java b/engine/schema/src/org/apache/cloudstack/acl/dao/AclGroupDaoImpl.java
index 27b31b5..5c0ae3a 100644
--- a/engine/schema/src/org/apache/cloudstack/acl/dao/AclGroupDaoImpl.java
+++ b/engine/schema/src/org/apache/cloudstack/acl/dao/AclGroupDaoImpl.java
@@ -39,6 +39,7 @@ public class AclGroupDaoImpl extends GenericDaoBase<AclGroupVO, Long> implements
 
         nameSearch = createSearchBuilder();
         nameSearch.and("name", nameSearch.entity().getName(), SearchCriteria.Op.EQ);
+        nameSearch.and("domainId", nameSearch.entity().getDomainId(), SearchCriteria.Op.EQ);
         nameSearch.done();
 
 
@@ -46,9 +47,12 @@ public class AclGroupDaoImpl extends GenericDaoBase<AclGroupVO, Long> implements
     }
 
     @Override
-    public AclGroup findByName(String name) {
+    public AclGroup findByName(Long domainId, String name) {
         SearchCriteria<AclGroupVO> sc = nameSearch.create();
         sc.setParameters("name", name);
+        if (domainId != null) {
+            sc.setParameters("domainId", domainId);
+        }
         return findOneBy(sc);
     }
 

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/0be374a7/server/src/com/cloud/api/ApiDBUtils.java
----------------------------------------------------------------------
diff --git a/server/src/com/cloud/api/ApiDBUtils.java b/server/src/com/cloud/api/ApiDBUtils.java
index 352500c..ec64d9e 100755
--- a/server/src/com/cloud/api/ApiDBUtils.java
+++ b/server/src/com/cloud/api/ApiDBUtils.java
@@ -25,6 +25,7 @@ import java.util.Set;
 import javax.annotation.PostConstruct;
 import javax.inject.Inject;
 
+import org.apache.cloudstack.acl.AclGroup;
 import org.apache.cloudstack.acl.AclRole;
 import org.apache.cloudstack.affinity.AffinityGroup;
 import org.apache.cloudstack.affinity.AffinityGroupResponse;
@@ -33,6 +34,7 @@ import org.apache.cloudstack.api.ApiCommandJobType;
 import org.apache.cloudstack.api.ApiConstants.HostDetails;
 import org.apache.cloudstack.api.ApiConstants.VMDetails;
 import org.apache.cloudstack.api.response.AccountResponse;
+import org.apache.cloudstack.api.response.AclGroupResponse;
 import org.apache.cloudstack.api.response.AclRoleResponse;
 import org.apache.cloudstack.api.response.AsyncJobResponse;
 import org.apache.cloudstack.api.response.DiskOfferingResponse;
@@ -65,6 +67,7 @@ import org.apache.cloudstack.storage.datastore.db.PrimaryDataStoreDao;
 import org.apache.cloudstack.storage.datastore.db.StoragePoolVO;
 
 import com.cloud.api.query.dao.AccountJoinDao;
+import com.cloud.api.query.dao.AclGroupJoinDao;
 import com.cloud.api.query.dao.AclRoleJoinDao;
 import com.cloud.api.query.dao.AffinityGroupJoinDao;
 import com.cloud.api.query.dao.AsyncJobJoinDao;
@@ -86,6 +89,7 @@ import com.cloud.api.query.dao.UserAccountJoinDao;
 import com.cloud.api.query.dao.UserVmJoinDao;
 import com.cloud.api.query.dao.VolumeJoinDao;
 import com.cloud.api.query.vo.AccountJoinVO;
+import com.cloud.api.query.vo.AclGroupJoinVO;
 import com.cloud.api.query.vo.AclRoleJoinVO;
 import com.cloud.api.query.vo.AffinityGroupJoinVO;
 import com.cloud.api.query.vo.AsyncJobJoinVO;
@@ -405,6 +409,7 @@ public class ApiDBUtils {
     static ServiceOfferingDetailsDao _serviceOfferingDetailsDao;
     static AccountService _accountService;
     static AclRoleJoinDao _aclRoleJoinDao;
+    static AclGroupJoinDao _aclGroupJoinDao;
 
 
     @Inject
@@ -522,6 +527,8 @@ public class ApiDBUtils {
     private ConfigurationManager configMgr;
     @Inject
     private AclRoleJoinDao aclRoleJoinDao;
+    @Inject
+    private AclGroupJoinDao aclGroupJoinDao;
 
     @PostConstruct
     void init() {
@@ -1691,6 +1698,18 @@ public class ApiDBUtils {
         return _aclRoleJoinDao.setAclRoleResponse(resp, role);
     }
 
+    public static List<AclGroupJoinVO> newAclGroupView(AclGroup group) {
+        return _aclGroupJoinDao.newAclGroupView(group);
+    }
+
+    public static AclGroupResponse newAclGroupResponse(AclGroupJoinVO group) {
+        return _aclGroupJoinDao.newAclGroupResponse(group);
+    }
+
+    public static AclGroupResponse fillAclGroupDetails(AclGroupResponse resp, AclGroupJoinVO group) {
+        return _aclGroupJoinDao.setAclGroupResponse(resp, group);
+    }
+
     public static List<? extends LoadBalancer> listSiteLoadBalancers(long gslbRuleId) {
         return _gslbService.listSiteLoadBalancers(gslbRuleId);
     }

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/0be374a7/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 60cc7a7..ee2d931 100644
--- a/server/src/com/cloud/api/query/QueryManagerImpl.java
+++ b/server/src/com/cloud/api/query/QueryManagerImpl.java
@@ -30,8 +30,10 @@ import javax.inject.Inject;
 import org.apache.log4j.Logger;
 import org.springframework.stereotype.Component;
 
+import org.apache.cloudstack.acl.AclGroup;
 import org.apache.cloudstack.acl.AclRole;
 import org.apache.cloudstack.acl.ControlledEntity.ACLType;
+import org.apache.cloudstack.acl.dao.AclGroupDao;
 import org.apache.cloudstack.acl.dao.AclRoleDao;
 import org.apache.cloudstack.affinity.AffinityGroupDomainMapVO;
 import org.apache.cloudstack.affinity.AffinityGroupResponse;
@@ -64,6 +66,7 @@ import org.apache.cloudstack.api.command.user.volume.ListResourceDetailsCmd;
 import org.apache.cloudstack.api.command.user.volume.ListVolumesCmd;
 import org.apache.cloudstack.api.command.user.zone.ListZonesByCmd;
 import org.apache.cloudstack.api.response.AccountResponse;
+import org.apache.cloudstack.api.response.AclGroupResponse;
 import org.apache.cloudstack.api.response.AclRoleResponse;
 import org.apache.cloudstack.api.response.AsyncJobResponse;
 import org.apache.cloudstack.api.response.DiskOfferingResponse;
@@ -92,6 +95,7 @@ import org.apache.cloudstack.framework.config.dao.ConfigurationDao;
 import org.apache.cloudstack.query.QueryService;
 
 import com.cloud.api.query.dao.AccountJoinDao;
+import com.cloud.api.query.dao.AclGroupJoinDao;
 import com.cloud.api.query.dao.AclRoleJoinDao;
 import com.cloud.api.query.dao.AffinityGroupJoinDao;
 import com.cloud.api.query.dao.AsyncJobJoinDao;
@@ -113,6 +117,7 @@ import com.cloud.api.query.dao.UserAccountJoinDao;
 import com.cloud.api.query.dao.UserVmJoinDao;
 import com.cloud.api.query.dao.VolumeJoinDao;
 import com.cloud.api.query.vo.AccountJoinVO;
+import com.cloud.api.query.vo.AclGroupJoinVO;
 import com.cloud.api.query.vo.AclRoleJoinVO;
 import com.cloud.api.query.vo.AffinityGroupJoinVO;
 import com.cloud.api.query.vo.AsyncJobJoinVO;
@@ -337,6 +342,12 @@ public class QueryManagerImpl extends ManagerBase implements QueryService {
     @Inject
     AclRoleDao _aclRoleDao;
 
+    @Inject
+    AclGroupJoinDao _aclGroupJoinDao;
+
+    @Inject
+    AclGroupDao _aclGroupDao;
+
     /*
      * (non-Javadoc)
      *
@@ -3313,10 +3324,12 @@ public class QueryManagerImpl extends ManagerBase implements QueryService {
             }
         }
 
-        Filter searchFilter = new Filter(AccountJoinVO.class, "id", true, startIndex, pageSize);
+        Filter searchFilter = new Filter(AclRoleJoinVO.class, "id", true, startIndex, pageSize);
 
 
         SearchBuilder<AclRoleJoinVO> sb = _aclRoleJoinDao.createSearchBuilder();
+        sb.select(null, Func.DISTINCT, sb.entity().getId()); // select distinct ids
+
         sb.and("name", sb.entity().getName(), SearchCriteria.Op.EQ);
         sb.and("domainId", sb.entity().getDomainId(), SearchCriteria.Op.EQ);
         sb.and("id", sb.entity().getId(), SearchCriteria.Op.EQ);
@@ -3362,4 +3375,107 @@ public class QueryManagerImpl extends ManagerBase implements QueryService {
         return new Pair<List<AclRoleJoinVO>, Integer>(vrs, count);
     }
 
+    @Override
+    public ListResponse<AclGroupResponse> listAclGroups(Long aclGroupId, String aclGroupName, Long domainId, Long startIndex, Long pageSize) {
+        Pair<List<AclGroupJoinVO>, Integer> result = listAclGroupsInternal(aclGroupId, aclGroupName, domainId, true, true, startIndex, pageSize);
+        ListResponse<AclGroupResponse> response = new ListResponse<AclGroupResponse>();
+
+        List<AclGroupResponse> groupResponses = ViewResponseHelper.createAclGroupResponses(result.first());
+        response.setResponses(groupResponses, result.second());
+        return response;
+    }
+
+    private Pair<List<AclGroupJoinVO>, Integer> listAclGroupsInternal(Long aclGroupId, String aclGroupName, Long domainId, boolean isRecursive, boolean listAll, Long startIndex,
+            Long pageSize) {
+
+        Account caller = CallContext.current().getCallingAccount();
+        Boolean listForDomain = false;
+
+        if (aclGroupId != null) {
+            AclGroup group = _aclGroupDao.findById(aclGroupId);
+            if (group == null) {
+                throw new InvalidParameterValueException("Unable to find acl group by id " + aclGroupId);
+            }
+
+            _accountMgr.checkAccess(caller, null, true, group);
+        }
+
+        if (domainId != null) {
+            Domain domain = _domainDao.findById(domainId);
+            if (domain == null) {
+                throw new InvalidParameterValueException("Domain id=" + domainId + " doesn't exist");
+            }
+
+            _accountMgr.checkAccess(caller, domain);
+
+            if (aclGroupName != null) {
+                AclGroup group = _aclGroupDao.findByName(domainId, aclGroupName);
+                if (group == null) {
+                    throw new InvalidParameterValueException("Unable to find acl group by name " + aclGroupName
+                            + " in domain " + domainId);
+                }
+                _accountMgr.checkAccess(caller, null, true, group);
+            }
+        }
+
+        if (aclGroupId == null) {
+            if (_accountMgr.isAdmin(caller.getType()) && listAll && domainId == null) {
+                listForDomain = true;
+                isRecursive = true;
+                if (domainId == null) {
+                    domainId = caller.getDomainId();
+                }
+            } else if (_accountMgr.isAdmin(caller.getType()) && domainId != null) {
+                listForDomain = true;
+            }
+        }
+
+        Filter searchFilter = new Filter(AclGroupJoinVO.class, "id", true, startIndex, pageSize);
+
+        SearchBuilder<AclGroupJoinVO> sb = _aclGroupJoinDao.createSearchBuilder();
+        sb.select(null, Func.DISTINCT, sb.entity().getId()); // select distinct ids
+
+        sb.and("name", sb.entity().getName(), SearchCriteria.Op.EQ);
+        sb.and("domainId", sb.entity().getDomainId(), SearchCriteria.Op.EQ);
+        sb.and("id", sb.entity().getId(), SearchCriteria.Op.EQ);
+
+        if (listForDomain && isRecursive) {
+            sb.and("path", sb.entity().getDomainPath(), SearchCriteria.Op.LIKE);
+        }
+
+        SearchCriteria<AclGroupJoinVO> sc = sb.create();
+
+        if (aclGroupName != null) {
+            sc.setParameters("name", aclGroupName);
+        }
+
+        if (aclGroupId != null) {
+            sc.setParameters("id", aclGroupId);
+        }
+
+        if (listForDomain) {
+            if (isRecursive) {
+                Domain domain = _domainDao.findById(domainId);
+                sc.setParameters("path", domain.getPath() + "%");
+            } else {
+                sc.setParameters("domainId", domainId);
+            }
+        }
+
+        // search group details by ids
+        Pair<List<AclGroupJoinVO>, Integer> uniqueGroupPair = _aclGroupJoinDao.searchAndCount(sc, searchFilter);
+        Integer count = uniqueGroupPair.second();
+        if (count.intValue() == 0) {
+            // empty result
+            return uniqueGroupPair;
+        }
+        List<AclGroupJoinVO> uniqueGroups = uniqueGroupPair.first();
+        Long[] vrIds = new Long[uniqueGroups.size()];
+        int i = 0;
+        for (AclGroupJoinVO v : uniqueGroups) {
+            vrIds[i++] = v.getId();
+        }
+        List<AclGroupJoinVO> vrs = _aclGroupJoinDao.searchByIds(vrIds);
+        return new Pair<List<AclGroupJoinVO>, Integer>(vrs, count);
+    }
 }

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/0be374a7/server/src/com/cloud/api/query/ViewResponseHelper.java
----------------------------------------------------------------------
diff --git a/server/src/com/cloud/api/query/ViewResponseHelper.java b/server/src/com/cloud/api/query/ViewResponseHelper.java
index 7a35a28..5abe14c 100644
--- a/server/src/com/cloud/api/query/ViewResponseHelper.java
+++ b/server/src/com/cloud/api/query/ViewResponseHelper.java
@@ -27,6 +27,7 @@ import org.apache.cloudstack.affinity.AffinityGroupResponse;
 import org.apache.cloudstack.api.ApiConstants.HostDetails;
 import org.apache.cloudstack.api.ApiConstants.VMDetails;
 import org.apache.cloudstack.api.response.AccountResponse;
+import org.apache.cloudstack.api.response.AclGroupResponse;
 import org.apache.cloudstack.api.response.AclRoleResponse;
 import org.apache.cloudstack.api.response.AsyncJobResponse;
 import org.apache.cloudstack.api.response.DiskOfferingResponse;
@@ -52,6 +53,7 @@ import org.apache.cloudstack.context.CallContext;
 
 import com.cloud.api.ApiDBUtils;
 import com.cloud.api.query.vo.AccountJoinVO;
+import com.cloud.api.query.vo.AclGroupJoinVO;
 import com.cloud.api.query.vo.AclRoleJoinVO;
 import com.cloud.api.query.vo.AffinityGroupJoinVO;
 import com.cloud.api.query.vo.AsyncJobJoinVO;
@@ -453,4 +455,20 @@ public class ViewResponseHelper {
         }
         return new ArrayList<AclRoleResponse>(vrDataList.values());
     }
+
+    public static List<AclGroupResponse> createAclGroupResponses(List<AclGroupJoinVO> groups) {
+        Hashtable<Long, AclGroupResponse> vrDataList = new Hashtable<Long, AclGroupResponse>();
+        for (AclGroupJoinVO vr : groups) {
+            AclGroupResponse vrData = vrDataList.get(vr.getId());
+            if (vrData == null) {
+                // first time encountering this Acl role
+                vrData = ApiDBUtils.newAclGroupResponse(vr);
+            } else {
+                // update vms
+                vrData = ApiDBUtils.fillAclGroupDetails(vrData, vr);
+            }
+            vrDataList.put(vr.getId(), vrData);
+        }
+        return new ArrayList<AclGroupResponse>(vrDataList.values());
+    }
 }

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/0be374a7/server/src/com/cloud/server/ManagementServerImpl.java
----------------------------------------------------------------------
diff --git a/server/src/com/cloud/server/ManagementServerImpl.java b/server/src/com/cloud/server/ManagementServerImpl.java
index 3ec6583..3a4fd31 100755
--- a/server/src/com/cloud/server/ManagementServerImpl.java
+++ b/server/src/com/cloud/server/ManagementServerImpl.java
@@ -57,11 +57,16 @@ import org.apache.cloudstack.api.command.admin.account.DisableAccountCmd;
 import org.apache.cloudstack.api.command.admin.account.EnableAccountCmd;
 import org.apache.cloudstack.api.command.admin.account.LockAccountCmd;
 import org.apache.cloudstack.api.command.admin.account.UpdateAccountCmd;
+import org.apache.cloudstack.api.command.admin.acl.AddAccountToAclGroupCmd;
 import org.apache.cloudstack.api.command.admin.acl.AddAclRoleToAclGroupCmd;
+import org.apache.cloudstack.api.command.admin.acl.CreateAclGroupCmd;
 import org.apache.cloudstack.api.command.admin.acl.CreateAclRoleCmd;
+import org.apache.cloudstack.api.command.admin.acl.DeleteAclGroupCmd;
 import org.apache.cloudstack.api.command.admin.acl.DeleteAclRoleCmd;
 import org.apache.cloudstack.api.command.admin.acl.GrantPermissionToAclRoleCmd;
+import org.apache.cloudstack.api.command.admin.acl.ListAclGroupsCmd;
 import org.apache.cloudstack.api.command.admin.acl.ListAclRolesCmd;
+import org.apache.cloudstack.api.command.admin.acl.RemoveAccountFromAclGroupCmd;
 import org.apache.cloudstack.api.command.admin.acl.RemoveAclRoleFromAclGroupCmd;
 import org.apache.cloudstack.api.command.admin.acl.RevokePermissionFromAclRoleCmd;
 import org.apache.cloudstack.api.command.admin.autoscale.CreateCounterCmd;
@@ -2867,6 +2872,11 @@ public class ManagementServerImpl extends ManagerBase implements ManagementServe
         cmdList.add(RevokePermissionFromAclRoleCmd.class);
         cmdList.add(AddAclRoleToAclGroupCmd.class);
         cmdList.add(RemoveAclRoleFromAclGroupCmd.class);
+        cmdList.add(CreateAclGroupCmd.class);
+        cmdList.add(DeleteAclGroupCmd.class);
+        cmdList.add(ListAclGroupsCmd.class);
+        cmdList.add(AddAccountToAclGroupCmd.class);
+        cmdList.add(RemoveAccountFromAclGroupCmd.class);
         return cmdList;
     }
 

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/0be374a7/server/src/org/apache/cloudstack/acl/AclServiceImpl.java
----------------------------------------------------------------------
diff --git a/server/src/org/apache/cloudstack/acl/AclServiceImpl.java b/server/src/org/apache/cloudstack/acl/AclServiceImpl.java
index 2ace72c..00d15db 100644
--- a/server/src/org/apache/cloudstack/acl/AclServiceImpl.java
+++ b/server/src/org/apache/cloudstack/acl/AclServiceImpl.java
@@ -37,7 +37,7 @@ import com.cloud.exception.InvalidParameterValueException;
 import com.cloud.exception.PermissionDeniedException;
 import com.cloud.user.Account;
 import com.cloud.user.AccountManager;
-import com.cloud.utils.Pair;
+import com.cloud.user.dao.AccountDao;
 import com.cloud.utils.component.Manager;
 import com.cloud.utils.component.ManagerBase;
 import com.cloud.utils.db.DB;
@@ -53,6 +53,9 @@ public class AclServiceImpl extends ManagerBase implements AclService, Manager {
     AccountManager _accountMgr;
 
     @Inject
+    AccountDao _accountDao;
+
+    @Inject
     AclRoleDao _aclRoleDao;
 
     @Inject
@@ -270,28 +273,142 @@ public class AclServiceImpl extends ManagerBase implements AclService, Manager {
         return group;
     }
 
+    @DB
     @Override
-    public AclGroup createAclGroup(Long domainId, String aclGroupName, String description) {
-        // TODO Auto-generated method stub
-        return null;
+    @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();
+        // 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);
+            }
+        }
+        txn.commit();
+        return group;
     }
 
+    @DB
     @Override
-    public boolean deleteAclGroup(Long aclGroupId) {
-        // TODO Auto-generated method stub
-        return false;
+    @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();
+        // 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();
+        // 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 removed yet
+                _aclGroupAccountMapDao.remove(grMap.getId());
+            }
+        }
+        txn.commit();
+        return group;
     }
 
+    @DB
     @Override
-    public Pair<List<? extends AclRole>, Integer> listAclGroups(Long aclRoleId, String aclRoleName, Long domainId, Long startIndex, Long pageSize) {
-        // TODO Auto-generated method stub
-        return null;
+    @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 (!_accountMgr.isRootAdmin(caller.getAccountId())) {
+            // domain admin can only create role for his domain
+            if (domainId != null && 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);
+        if (domainId != null) {
+            rvo.setDomainId(domainId);
+        }
+
+        return _aclGroupDao.persist(rvo);
     }
 
+    @DB
     @Override
-    public AclRole getAclGroup(Long groupId) {
-        // TODO Auto-generated method stub
-        return null;
+    @ActionEvent(eventType = EventTypes.EVENT_ACL_GROUP_DELETE, eventDescription = "Deleting Acl Group")
+    public boolean deleteAclGroup(Long aclGroupId) {
+        Account caller = CallContext.current().getCallingAccount();
+        // get the Acl Role entity
+        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());
+            }
+        }
+
+        // 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();
+
+        return true;
     }
 
 

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/0be374a7/setup/db/db/schema-420to430.sql
----------------------------------------------------------------------
diff --git a/setup/db/db/schema-420to430.sql b/setup/db/db/schema-420to430.sql
index 7afb0d1..78c2afe 100644
--- a/setup/db/db/schema-420to430.sql
+++ b/setup/db/db/schema-420to430.sql
@@ -334,17 +334,17 @@ CREATE TABLE `cloud`.`acl_group_role_map` (
 ) ENGINE=InnoDB DEFAULT CHARSET=utf8;        
 
 
-INSERT IGNORE INTO `cloud`.`acl_role` (id, name, description, uuid, created) VALUES (1,'NORMAL', 'Domain user role', UUID(), Now());
-INSERT IGNORE INTO `cloud`.`acl_role` (id, name, description, uuid, created) VALUES (2, 'ADMIN', 'Root admin role', UUID(), Now());
-INSERT IGNORE INTO `cloud`.`acl_role` (id, name, description, uuid, created) VALUES (3, 'DOMAIN_ADMIN', 'Domain admin role', UUID(), Now());
-INSERT IGNORE INTO `cloud`.`acl_role` (id, name, description, uuid, created) VALUES (4, 'RESOURCE_DOMAIN_ADMIN', 'Resource domain admin role', UUID(), Now());
-INSERT IGNORE INTO `cloud`.`acl_role` (id, name, description, uuid, created) VALUES (5, 'READ_ONLY_ADMIN', 'Read only admin role', UUID(), Now());
+INSERT IGNORE INTO `cloud`.`acl_role` (id, name, description, uuid, domain_id, created) VALUES (1,'NORMAL', 'Domain user role', UUID(), 1, Now());
+INSERT IGNORE INTO `cloud`.`acl_role` (id, name, description, uuid, domain_id, created) VALUES (2, 'ADMIN', 'Root admin role', UUID(), 1, Now());
+INSERT IGNORE INTO `cloud`.`acl_role` (id, name, description, uuid, domain_id, created) VALUES (3, 'DOMAIN_ADMIN', 'Domain admin role', UUID(), 1, Now());
+INSERT IGNORE INTO `cloud`.`acl_role` (id, name, description, uuid, domain_id, created) VALUES (4, 'RESOURCE_DOMAIN_ADMIN', 'Resource domain admin role', UUID(), 1, Now());
+INSERT IGNORE INTO `cloud`.`acl_role` (id, name, description, uuid, domain_id, created) VALUES (5, 'READ_ONLY_ADMIN', 'Read only admin role', UUID(), 1, Now());
 
-INSERT IGNORE INTO `cloud`.`acl_group` (id, name, description, uuid, created) VALUES (1, 'NORMAL', 'Domain user group', UUID(), Now());
-INSERT IGNORE INTO `cloud`.`acl_group` (id, name, description, uuid, created) VALUES (2, 'ADMIN', 'Root admin group', UUID(), Now());
-INSERT IGNORE INTO `cloud`.`acl_group` (id, name, description, uuid, created) VALUES (3, 'DOMAIN_ADMIN', 'Domain admin group', UUID(), Now());
-INSERT IGNORE INTO `cloud`.`acl_group` (id, name, description, uuid, created) VALUES (4, 'RESOURCE_DOMAIN_ADMIN', 'Resource domain admin group', UUID(), Now());
-INSERT IGNORE INTO `cloud`.`acl_group` (id, name, description, uuid, created) VALUES (5, 'READ_ONLY_ADMIN', 'Read only admin group', UUID(), Now());
+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,
@@ -394,4 +394,37 @@ CREATE VIEW `cloud`.`acl_role_view` AS
         `cloud`.`acl_role` parent_role on parent_role.id = acl_role.parent_role_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
+    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;                   
  
\ No newline at end of file


Mime
View raw message