DeleteAffinityGroup API changes
Project: http://git-wip-us.apache.org/repos/asf/cloudstack/repo Commit: http://git-wip-us.apache.org/repos/asf/cloudstack/commit/50f53c86 Tree: http://git-wip-us.apache.org/repos/asf/cloudstack/tree/50f53c86 Diff: http://git-wip-us.apache.org/repos/asf/cloudstack/diff/50f53c86 Branch: refs/heads/marvin_refactor Commit: 50f53c86f59dd696f5f5315ba9a4c11b3f84c302 Parents: 1e205a3 Author: Prachi Damle <[email protected]> Authored: Thu Feb 28 13:42:33 2013 -0800 Committer: Prachi Damle <[email protected]> Committed: Thu Apr 11 13:22:34 2013 -0700 ---------------------------------------------------------------------- api/src/com/cloud/event/EventTypes.java | 7 +- .../cloudstack/affinity/AffinityGroupService.java | 9 +- .../apache/cloudstack/api/ResponseGenerator.java | 2 + .../user/affinitygroup/DeleteAffinityGroupCmd.java | 137 +++++++++++++++ server/src/com/cloud/api/ApiDBUtils.java | 14 ++- server/src/com/cloud/api/ApiResponseHelper.java | 10 + .../affinity/AffinityGroupServiceImpl.java | 70 +++++++- 7 files changed, 239 insertions(+), 10 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/cloudstack/blob/50f53c86/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 5671f99..bd5f220 100755 --- a/api/src/com/cloud/event/EventTypes.java +++ b/api/src/com/cloud/event/EventTypes.java @@ -348,7 +348,7 @@ public class EventTypes { // tag related events public static final String EVENT_TAGS_CREATE = "CREATE_TAGS"; public static final String EVENT_TAGS_DELETE = "DELETE_TAGS"; - + // vm snapshot events public static final String EVENT_VM_SNAPSHOT_CREATE = "VMSNAPSHOT.CREATE"; public static final String EVENT_VM_SNAPSHOT_DELETE = "VMSNAPSHOT.DELETE"; @@ -382,6 +382,11 @@ public class EventTypes { public static final String EVENT_BAREMETAL_PXE_SERVER_ADD = "PHYSICAL.PXE.ADD"; public static final String EVENT_BAREMETAL_PXE_SERVER_DELETE = "PHYSICAL.PXE.DELETE"; + public static final String EVENT_AFFINITY_GROUP_CREATE = "AG.CREATE"; + public static final String EVENT_AFFINITY_GROUP_DELETE = "AG.DELETE"; + public static final String EVENT_AFFINITY_GROUP_ASSIGN = "AG.ASSIGN"; + public static final String EVENT_AFFINITY_GROUP_REMOVE = "AG.REMOVE"; + static { // TODO: need a way to force author adding event types to declare the entity details as well, with out braking http://git-wip-us.apache.org/repos/asf/cloudstack/blob/50f53c86/api/src/org/apache/cloudstack/affinity/AffinityGroupService.java ---------------------------------------------------------------------- diff --git a/api/src/org/apache/cloudstack/affinity/AffinityGroupService.java b/api/src/org/apache/cloudstack/affinity/AffinityGroupService.java index 8323176..501280d 100644 --- a/api/src/org/apache/cloudstack/affinity/AffinityGroupService.java +++ b/api/src/org/apache/cloudstack/affinity/AffinityGroupService.java @@ -2,6 +2,8 @@ package org.apache.cloudstack.affinity; import java.util.List; +import com.cloud.exception.ResourceInUseException; + public interface AffinityGroupService { /** @@ -20,14 +22,15 @@ public interface AffinityGroupService { /** * Creates an affinity/anti-affinity group. - * + * * @param affinityGroupId * @param account * @param domainId * @param affinityGroupName - * @param vmId + * @throws ResourceInUseException */ - void deleteAffinityGroup(Long affinityGroupId, String account, Long domainId, String affinityGroupName, Long vmId); + boolean deleteAffinityGroup(Long affinityGroupId, String account, Long domainId, String affinityGroupName) + throws ResourceInUseException; /** * Lists Affinity Groups http://git-wip-us.apache.org/repos/asf/cloudstack/blob/50f53c86/api/src/org/apache/cloudstack/api/ResponseGenerator.java ---------------------------------------------------------------------- diff --git a/api/src/org/apache/cloudstack/api/ResponseGenerator.java b/api/src/org/apache/cloudstack/api/ResponseGenerator.java index f09f8ae..9777130 100644 --- a/api/src/org/apache/cloudstack/api/ResponseGenerator.java +++ b/api/src/org/apache/cloudstack/api/ResponseGenerator.java @@ -386,4 +386,6 @@ public interface ResponseGenerator { public NicResponse createNicResponse(Nic result); AffinityGroupResponse createAffinityGroupResponse(AffinityGroup group); + + Long getAffinityGroupId(String name, long entityOwnerId); } http://git-wip-us.apache.org/repos/asf/cloudstack/blob/50f53c86/api/src/org/apache/cloudstack/api/command/user/affinitygroup/DeleteAffinityGroupCmd.java ---------------------------------------------------------------------- diff --git a/api/src/org/apache/cloudstack/api/command/user/affinitygroup/DeleteAffinityGroupCmd.java b/api/src/org/apache/cloudstack/api/command/user/affinitygroup/DeleteAffinityGroupCmd.java new file mode 100644 index 0000000..8ace2e5 --- /dev/null +++ b/api/src/org/apache/cloudstack/api/command/user/affinitygroup/DeleteAffinityGroupCmd.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.user.affinitygroup; + +import org.apache.cloudstack.affinity.AffinityGroupResponse; +import org.apache.cloudstack.api.APICommand; +import org.apache.cloudstack.api.ApiConstants; +import org.apache.cloudstack.api.ApiErrorCode; +import org.apache.cloudstack.api.BaseCmd; +import org.apache.cloudstack.api.Parameter; +import org.apache.cloudstack.api.ServerApiException; +import org.apache.cloudstack.api.response.DomainResponse; +import org.apache.cloudstack.api.response.SuccessResponse; +import org.apache.log4j.Logger; + +import com.cloud.exception.InvalidParameterValueException; +import com.cloud.exception.ResourceInUseException; +import com.cloud.user.Account; +import com.cloud.user.UserContext; + +@APICommand(name = "deleteAffinityGroup", description = "Deletes affinity group", responseObject = SuccessResponse.class) +public class DeleteAffinityGroupCmd extends BaseCmd { + public static final Logger s_logger = Logger.getLogger(DeleteAffinityGroupCmd.class.getName()); + private static final String s_name = "deleteaffinitygroupresponse"; + + ///////////////////////////////////////////////////// + //////////////// API parameters ///////////////////// + ///////////////////////////////////////////////////// + + @Parameter(name = ApiConstants.ACCOUNT, type = CommandType.STRING, description = "the account of the affinity group. Must be specified with domain ID") + private String accountName; + + @Parameter(name = ApiConstants.DOMAIN_ID, type = CommandType.UUID, description = "the domain ID of account owning the affinity group", entityType = DomainResponse.class) + private Long domainId; + + @Parameter(name = ApiConstants.ID, type = CommandType.UUID, description = "The ID of the affinity group. Mutually exclusive with name parameter", entityType = AffinityGroupResponse.class) + private Long id; + + @Parameter(name = ApiConstants.NAME, type = CommandType.STRING, description = "The ID of the affinity group. Mutually exclusive with id parameter") + private String name; + + + ///////////////////////////////////////////////////// + /////////////////// Accessors /////////////////////// + ///////////////////////////////////////////////////// + + public String getAccountName() { + return accountName; + } + + public Long getDomainId() { + return domainId; + } + + + public Long getId() { + if (id != null && name != null) { + throw new InvalidParameterValueException("name and id parameters are mutually exclusive"); + } + + if (name != null) { + id = _responseGenerator.getAffinityGroupId(name, getEntityOwnerId()); + if (id == null) { + throw new InvalidParameterValueException("Unable to find affinity group by name " + name + + " for the account id=" + getEntityOwnerId()); + } + } + + if (id == null) { + throw new InvalidParameterValueException( + "Either id or name parameter is requred by deleteAffinityGroup command"); + } + + return id; + } + + ///////////////////////////////////////////////////// + /////////////// API Implementation/////////////////// + ///////////////////////////////////////////////////// + + @Override + public String getCommandName() { + return s_name; + } + + @Override + public long getEntityOwnerId() { + Account account = UserContext.current().getCaller(); + if ((account == null) || isAdmin(account.getType())) { + if ((domainId != null) && (accountName != null)) { + Account userAccount = _responseGenerator.findAccountByNameDomain(accountName, domainId); + if (userAccount != null) { + return userAccount.getId(); + } + } + } + + if (account != null) { + return account.getId(); + } + + return Account.ACCOUNT_ID_SYSTEM; // no account info given, parent this + // command to SYSTEM so ERROR events + // are tracked + + } + + @Override + public void execute(){ + try{ + boolean result = _affinityGroupService.deleteAffinityGroup(id, accountName, domainId, name); + if (result) { + SuccessResponse response = new SuccessResponse(getCommandName()); + this.setResponseObject(response); + } else { + throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, "Failed to delete affinity group"); + } + } catch (ResourceInUseException ex) { + s_logger.warn("Exception: ", ex); + throw new ServerApiException(ApiErrorCode.RESOURCE_IN_USE_ERROR, ex.getMessage()); + } + } +} http://git-wip-us.apache.org/repos/asf/cloudstack/blob/50f53c86/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 7b44190..d21e2c4 100755 --- a/server/src/com/cloud/api/ApiDBUtils.java +++ b/server/src/com/cloud/api/ApiDBUtils.java @@ -25,6 +25,8 @@ import java.util.Set; import javax.annotation.PostConstruct; import javax.inject.Inject; +import org.apache.cloudstack.affinity.AffinityGroup; +import org.apache.cloudstack.affinity.dao.AffinityGroupDao; import org.apache.cloudstack.api.ApiConstants.HostDetails; import org.apache.cloudstack.api.ApiConstants.VMDetails; import org.apache.cloudstack.api.response.AccountResponse; @@ -284,7 +286,7 @@ public class ApiDBUtils { static NetworkModel _networkModel; static NetworkManager _networkMgr; static TemplateManager _templateMgr; - + static StatsCollector _statsCollector; static AccountDao _accountDao; @@ -379,6 +381,7 @@ public class ApiDBUtils { static ClusterDetailsDao _clusterDetailsDao; static NicSecondaryIpDao _nicSecondaryIpDao; static VpcProvisioningService _vpcProvSvc; + static AffinityGroupDao _affinityGroupDao; @Inject private ManagementServer ms; @Inject public AsyncJobManager asyncMgr; @@ -483,6 +486,8 @@ public class ApiDBUtils { @Inject private VMSnapshotDao vmSnapshotDao; @Inject private NicSecondaryIpDao nicSecondaryIpDao; @Inject private VpcProvisioningService vpcProvSvc; + @Inject private AffinityGroupDao affinityGroupDao; + @PostConstruct void init() { _ms = ms; @@ -585,6 +590,7 @@ public class ApiDBUtils { _vmSnapshotDao = vmSnapshotDao; _nicSecondaryIpDao = nicSecondaryIpDao; _vpcProvSvc = vpcProvSvc; + _affinityGroupDao = affinityGroupDao; // Note: stats collector should already have been initialized by this time, otherwise a null instance is returned _statsCollector = StatsCollector.getInstance(); } @@ -1579,7 +1585,7 @@ public class ApiDBUtils { public static DataCenterJoinVO newDataCenterView(DataCenter dc){ return _dcJoinDao.newDataCenterView(dc); } - + public static Map<String, String> findHostDetailsById(long hostId){ return _hostDetailsDao.findDetails(hostId); } @@ -1587,4 +1593,8 @@ public class ApiDBUtils { public static List<NicSecondaryIpVO> findNicSecondaryIps(long nicId) { return _nicSecondaryIpDao.listByNicId(nicId); } + + public static AffinityGroup getAffinityGroup(String groupName, long accountId) { + return _affinityGroupDao.findByAccountAndName(accountId, groupName); + } } http://git-wip-us.apache.org/repos/asf/cloudstack/blob/50f53c86/server/src/com/cloud/api/ApiResponseHelper.java ---------------------------------------------------------------------- diff --git a/server/src/com/cloud/api/ApiResponseHelper.java b/server/src/com/cloud/api/ApiResponseHelper.java index 7b23b3b..d651f1f 100755 --- a/server/src/com/cloud/api/ApiResponseHelper.java +++ b/server/src/com/cloud/api/ApiResponseHelper.java @@ -3668,4 +3668,14 @@ public class ApiResponseHelper implements ResponseGenerator { return response; } + + @Override + public Long getAffinityGroupId(String groupName, long accountId) { + AffinityGroup ag = ApiDBUtils.getAffinityGroup(groupName, accountId); + if (ag == null) { + return null; + } else { + return ag.getId(); + } + } } http://git-wip-us.apache.org/repos/asf/cloudstack/blob/50f53c86/server/src/org/apache/cloudstack/affinity/AffinityGroupServiceImpl.java ---------------------------------------------------------------------- diff --git a/server/src/org/apache/cloudstack/affinity/AffinityGroupServiceImpl.java b/server/src/org/apache/cloudstack/affinity/AffinityGroupServiceImpl.java index eee3e6f..f3b166f 100644 --- a/server/src/org/apache/cloudstack/affinity/AffinityGroupServiceImpl.java +++ b/server/src/org/apache/cloudstack/affinity/AffinityGroupServiceImpl.java @@ -8,15 +8,25 @@ import javax.inject.Inject; import javax.naming.ConfigurationException; import org.apache.cloudstack.affinity.dao.AffinityGroupDao; +import org.apache.cloudstack.affinity.dao.AffinityGroupVMMapDao; import org.apache.log4j.Logger; +import com.cloud.event.ActionEvent; +import com.cloud.event.EventTypes; import com.cloud.exception.InvalidParameterValueException; +import com.cloud.exception.ResourceInUseException; +import com.cloud.network.security.SecurityGroupManager; +import com.cloud.network.security.SecurityGroupRuleVO; +import com.cloud.network.security.SecurityGroupVMMapVO; +import com.cloud.network.security.SecurityGroupVO; import com.cloud.user.Account; import com.cloud.user.AccountManager; import com.cloud.user.UserContext; import com.cloud.utils.component.Manager; import com.cloud.utils.component.ManagerBase; +import com.cloud.utils.db.DB; +import com.cloud.utils.db.Transaction; @Local(value = { AffinityGroupService.class }) public class AffinityGroupServiceImpl extends ManagerBase implements AffinityGroupService, Manager { @@ -30,6 +40,9 @@ public class AffinityGroupServiceImpl extends ManagerBase implements AffinityGro @Inject AffinityGroupDao _affinityGroupDao; + @Inject + AffinityGroupVMMapDao _affinityGroupVMMapDao; + @Override public AffinityGroup createAffinityGroup(String account, Long domainId, String affinityGroupName, String affinityGroupType, String description) { @@ -37,7 +50,7 @@ public class AffinityGroupServiceImpl extends ManagerBase implements AffinityGro Account caller = UserContext.current().getCaller(); Account owner = _accountMgr.finalizeOwner(caller, account, domainId, null); - if (_affinityGroupDao.isNameInUse(owner.getId(), owner.getDomainId(), affinityGroupName)) { + if (_affinityGroupDao.isNameInUse(owner.getAccountId(), owner.getDomainId(), affinityGroupName)) { throw new InvalidParameterValueException("Unable to create affinity group, a group with name " + affinityGroupName + " already exisits."); @@ -47,14 +60,63 @@ public class AffinityGroupServiceImpl extends ManagerBase implements AffinityGro owner.getId()); _affinityGroupDao.persist(group); + if (s_logger.isDebugEnabled()) { + s_logger.debug("Created affinity group =" + affinityGroupName); + } + return group; } + @DB @Override - public void deleteAffinityGroup(Long affinityGroupId, String account, Long domainId, String affinityGroupName, - Long vmId) { - // TODO Auto-generated method stub + @ActionEvent(eventType = EventTypes.EVENT_SECURITY_GROUP_DELETE, eventDescription = "deleting affinity group") + public boolean deleteAffinityGroup(Long affinityGroupId, String account, Long domainId, String affinityGroupName) + throws ResourceInUseException { + + Account caller = UserContext.current().getCaller(); + Account owner = _accountMgr.finalizeOwner(caller, account, domainId, null); + + AffinityGroupVO group = null; + if (affinityGroupId != null) { + group = _affinityGroupDao.findById(affinityGroupId); + if (group == null) { + throw new InvalidParameterValueException("Unable to find affinity group: " + affinityGroupId + + "; failed to delete group."); + } + } else if (affinityGroupName != null) { + group = _affinityGroupDao.findByAccountAndName(owner.getAccountId(), affinityGroupName); + if (group == null) { + throw new InvalidParameterValueException("Unable to find affinity group: " + affinityGroupName + + "; failed to delete group."); + } + } else { + throw new InvalidParameterValueException( + "Either the affinity group Id or group name must be specified to delete the group"); + } + // check permissions + _accountMgr.checkAccess(caller, null, true, group); + + final Transaction txn = Transaction.currentTxn(); + txn.start(); + + group = _affinityGroupDao.lockRow(affinityGroupId, true); + if (group == null) { + throw new InvalidParameterValueException("Unable to find affinity group by id " + affinityGroupId); + } + + List<AffinityGroupVMMapVO> affinityGroupVmMap = _affinityGroupVMMapDao.listByAffinityGroup(affinityGroupId); + if (!affinityGroupVmMap.isEmpty()) { + throw new ResourceInUseException("Cannot delete affinity group when it's in use by virtual machines"); + } + + _affinityGroupDao.expunge(affinityGroupId); + txn.commit(); + + if (s_logger.isDebugEnabled()) { + s_logger.debug("Deleted affinity group id=" + affinityGroupId); + } + return true; } @Override
