Changes to add AffinityGroupprocessor, deployVM changes

This commit is contained in:
Prachi Damle 2013-03-13 13:57:47 -07:00
parent 1aed5bf9c2
commit fe2a86871f
20 changed files with 755 additions and 166 deletions

View File

@ -386,6 +386,7 @@ public class EventTypes {
public static final String EVENT_AFFINITY_GROUP_DELETE = "AG.DELETE"; 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_ASSIGN = "AG.ASSIGN";
public static final String EVENT_AFFINITY_GROUP_REMOVE = "AG.REMOVE"; public static final String EVENT_AFFINITY_GROUP_REMOVE = "AG.REMOVE";
public static final String EVENT_VM_AFFINITY_GROUP_UPDATE = "VM.AG.UPDATE";
static { static {

View File

@ -0,0 +1,18 @@
package com.cloud.exception;
import com.cloud.exception.CloudException;
import com.cloud.utils.SerialVersionUID;
public class AffinityConflictException extends CloudException {
private static final long serialVersionUID = SerialVersionUID.AffinityConflictException;
public AffinityConflictException(String message) {
super(message);
}
public AffinityConflictException(String message, Throwable th) {
super(message, th);
}
}

View File

@ -26,9 +26,6 @@ import org.apache.cloudstack.api.command.admin.vm.RecoverVMCmd;
import org.apache.cloudstack.api.command.user.vm.*; import org.apache.cloudstack.api.command.user.vm.*;
import org.apache.cloudstack.api.command.user.vmgroup.CreateVMGroupCmd; import org.apache.cloudstack.api.command.user.vmgroup.CreateVMGroupCmd;
import org.apache.cloudstack.api.command.user.vmgroup.DeleteVMGroupCmd; import org.apache.cloudstack.api.command.user.vmgroup.DeleteVMGroupCmd;
import org.apache.cloudstack.api.command.user.volume.AttachVolumeCmd;
import org.apache.cloudstack.api.command.user.volume.DetachVolumeCmd;
import com.cloud.dc.DataCenter; import com.cloud.dc.DataCenter;
import com.cloud.exception.ConcurrentOperationException; import com.cloud.exception.ConcurrentOperationException;
import com.cloud.exception.InsufficientCapacityException; import com.cloud.exception.InsufficientCapacityException;
@ -42,7 +39,6 @@ import com.cloud.hypervisor.Hypervisor.HypervisorType;
import com.cloud.network.Network.IpAddresses; import com.cloud.network.Network.IpAddresses;
import com.cloud.offering.ServiceOffering; import com.cloud.offering.ServiceOffering;
import com.cloud.storage.StoragePool; import com.cloud.storage.StoragePool;
import com.cloud.storage.Volume;
import com.cloud.template.VirtualMachineTemplate; import com.cloud.template.VirtualMachineTemplate;
import com.cloud.user.Account; import com.cloud.user.Account;
import com.cloud.uservm.UserVm; import com.cloud.uservm.UserVm;
@ -104,14 +100,14 @@ public interface UserVmService {
* @return the vm object if successful, null otherwise * @return the vm object if successful, null otherwise
*/ */
UserVm addNicToVirtualMachine(AddNicToVMCmd cmd); UserVm addNicToVirtualMachine(AddNicToVMCmd cmd);
/** /**
* Removes a NIC on the given network from the virtual machine * Removes a NIC on the given network from the virtual machine
* @param cmd the command object that defines the vm and the given network * @param cmd the command object that defines the vm and the given network
* @return the vm object if successful, null otherwise * @return the vm object if successful, null otherwise
*/ */
UserVm removeNicFromVirtualMachine(RemoveNicFromVMCmd cmd); UserVm removeNicFromVirtualMachine(RemoveNicFromVMCmd cmd);
/** /**
* Updates default Nic to the given network for given virtual machine * Updates default Nic to the given network for given virtual machine
* @param cmd the command object that defines the vm and the given network * @param cmd the command object that defines the vm and the given network
@ -123,7 +119,8 @@ public interface UserVmService {
/** /**
* Creates a Basic Zone User VM in the database and returns the VM to the caller. * Creates a Basic Zone User VM in the database and returns the VM to the
* caller.
* *
* @param zone * @param zone
* - availability zone for the virtual machine * - availability zone for the virtual machine
@ -132,61 +129,69 @@ public interface UserVmService {
* @param template * @param template
* - the template for the virtual machine * - the template for the virtual machine
* @param securityGroupIdList * @param securityGroupIdList
* - comma separated list of security groups id that going to be applied to the virtual machine * - comma separated list of security groups id that going to be
* applied to the virtual machine
* @param hostName * @param hostName
* - host name for the virtual machine * - host name for the virtual machine
* @param displayName * @param displayName
* - an optional user generated name for the virtual machine * - an optional user generated name for the virtual machine
* @param diskOfferingId * @param diskOfferingId
* - the ID of the disk offering for the virtual machine. If the template is of ISO format, the * - the ID of the disk offering for the virtual machine. If the
* diskOfferingId is * template is of ISO format, the diskOfferingId is for the root
* for the root disk volume. Otherwise this parameter is used to indicate the offering for the data disk * disk volume. Otherwise this parameter is used to indicate the
* volume. * offering for the data disk volume. If the templateId parameter
* If the templateId parameter passed is from a Template object, the diskOfferingId refers to a DATA Disk * passed is from a Template object, the diskOfferingId refers to
* Volume * a DATA Disk Volume created. If the templateId parameter passed
* created. If the templateId parameter passed is from an ISO object, the diskOfferingId refers to a ROOT * is from an ISO object, the diskOfferingId refers to a ROOT
* Disk * Disk Volume created
* Volume created
* @param diskSize * @param diskSize
* - the arbitrary size for the DATADISK volume. Mutually exclusive with diskOfferingId * - the arbitrary size for the DATADISK volume. Mutually
* exclusive with diskOfferingId
* @param group * @param group
* - an optional group for the virtual machine * - an optional group for the virtual machine
* @param hypervisor * @param hypervisor
* - the hypervisor on which to deploy the virtual machine * - the hypervisor on which to deploy the virtual machine
* @param userData * @param userData
* - an optional binary data that can be sent to the virtual machine upon a successful deployment. This * - an optional binary data that can be sent to the virtual
* binary * machine upon a successful deployment. This binary data must be
* data must be base64 encoded before adding it to the request. Currently only HTTP GET is supported. * base64 encoded before adding it to the request. Currently only
* Using HTTP * HTTP GET is supported. Using HTTP GET (via querystring), you
* GET (via querystring), you can send up to 2KB of data after base64 encoding * can send up to 2KB of data after base64 encoding
* @param sshKeyPair * @param sshKeyPair
* - name of the ssh key pair used to login to the virtual machine * - name of the ssh key pair used to login to the virtual
* machine
* @param requestedIps * @param requestedIps
* TODO * TODO
* @param defaultIp * @param defaultIp
* TODO * TODO
* @param affinityGroupIdList
* @param accountName * @param accountName
* - an optional account for the virtual machine. Must be used with domainId * - an optional account for the virtual machine. Must be used
* with domainId
* @param domainId * @param domainId
* - an optional domainId for the virtual machine. If the account parameter is used, domainId must also * - an optional domainId for the virtual machine. If the account
* be used * parameter is used, domainId must also be used
* @return UserVm object if successful. * @return UserVm object if successful.
* *
* @throws InsufficientCapacityException * @throws InsufficientCapacityException
* if there is insufficient capacity to deploy the VM. * if there is insufficient capacity to deploy the VM.
* @throws ConcurrentOperationException * @throws ConcurrentOperationException
* if there are multiple users working on the same VM or in the same environment. * if there are multiple users working on the same VM or in the
* same environment.
* @throws ResourceUnavailableException * @throws ResourceUnavailableException
* if the resources required to deploy the VM is not currently available. * if the resources required to deploy the VM is not currently
* available.
* @throws InsufficientResourcesException * @throws InsufficientResourcesException
*/ */
UserVm createBasicSecurityGroupVirtualMachine(DataCenter zone, ServiceOffering serviceOffering, VirtualMachineTemplate template, List<Long> securityGroupIdList, Account owner, String hostName, UserVm createBasicSecurityGroupVirtualMachine(DataCenter zone, ServiceOffering serviceOffering, VirtualMachineTemplate template, List<Long> securityGroupIdList, Account owner, String hostName,
String displayName, Long diskOfferingId, Long diskSize, String group, HypervisorType hypervisor, String userData, String sshKeyPair, Map<Long, IpAddresses> requestedIps, IpAddresses defaultIp, String keyboard) String displayName, Long diskOfferingId, Long diskSize, String group, HypervisorType hypervisor,
String userData, String sshKeyPair, Map<Long, IpAddresses> requestedIps, IpAddresses defaultIp,
String keyboard, List<Long> affinityGroupIdList)
throws InsufficientCapacityException, ConcurrentOperationException, ResourceUnavailableException, StorageUnavailableException, ResourceAllocationException; throws InsufficientCapacityException, ConcurrentOperationException, ResourceUnavailableException, StorageUnavailableException, ResourceAllocationException;
/** /**
* Creates a User VM in Advanced Zone (Security Group feature is enabled) in the database and returns the VM to the * Creates a User VM in Advanced Zone (Security Group feature is enabled) in
* caller. * the database and returns the VM to the caller.
* *
* @param zone * @param zone
* - availability zone for the virtual machine * - availability zone for the virtual machine
@ -197,63 +202,69 @@ public interface UserVmService {
* @param networkIdList * @param networkIdList
* - list of network ids used by virtual machine * - list of network ids used by virtual machine
* @param securityGroupIdList * @param securityGroupIdList
* - comma separated list of security groups id that going to be applied to the virtual machine * - comma separated list of security groups id that going to be
* applied to the virtual machine
* @param hostName * @param hostName
* - host name for the virtual machine * - host name for the virtual machine
* @param displayName * @param displayName
* - an optional user generated name for the virtual machine * - an optional user generated name for the virtual machine
* @param diskOfferingId * @param diskOfferingId
* - the ID of the disk offering for the virtual machine. If the template is of ISO format, the * - the ID of the disk offering for the virtual machine. If the
* diskOfferingId is * template is of ISO format, the diskOfferingId is for the root
* for the root disk volume. Otherwise this parameter is used to indicate the offering for the data disk * disk volume. Otherwise this parameter is used to indicate the
* volume. * offering for the data disk volume. If the templateId parameter
* If the templateId parameter passed is from a Template object, the diskOfferingId refers to a DATA Disk * passed is from a Template object, the diskOfferingId refers to
* Volume * a DATA Disk Volume created. If the templateId parameter passed
* created. If the templateId parameter passed is from an ISO object, the diskOfferingId refers to a ROOT * is from an ISO object, the diskOfferingId refers to a ROOT
* Disk * Disk Volume created
* Volume created
* @param diskSize * @param diskSize
* - the arbitrary size for the DATADISK volume. Mutually exclusive with diskOfferingId * - the arbitrary size for the DATADISK volume. Mutually
* exclusive with diskOfferingId
* @param group * @param group
* - an optional group for the virtual machine * - an optional group for the virtual machine
* @param hypervisor * @param hypervisor
* - the hypervisor on which to deploy the virtual machine * - the hypervisor on which to deploy the virtual machine
* @param userData * @param userData
* - an optional binary data that can be sent to the virtual machine upon a successful deployment. This * - an optional binary data that can be sent to the virtual
* binary * machine upon a successful deployment. This binary data must be
* data must be base64 encoded before adding it to the request. Currently only HTTP GET is supported. * base64 encoded before adding it to the request. Currently only
* Using HTTP * HTTP GET is supported. Using HTTP GET (via querystring), you
* GET (via querystring), you can send up to 2KB of data after base64 encoding * can send up to 2KB of data after base64 encoding
* @param sshKeyPair * @param sshKeyPair
* - name of the ssh key pair used to login to the virtual machine * - name of the ssh key pair used to login to the virtual
* machine
* @param requestedIps * @param requestedIps
* TODO * TODO
* @param defaultIps * @param defaultIps
* TODO * TODO
* @param affinityGroupIdList
* @param accountName * @param accountName
* - an optional account for the virtual machine. Must be used with domainId * - an optional account for the virtual machine. Must be used
* with domainId
* @param domainId * @param domainId
* - an optional domainId for the virtual machine. If the account parameter is used, domainId must also * - an optional domainId for the virtual machine. If the account
* be used * parameter is used, domainId must also be used
* @return UserVm object if successful. * @return UserVm object if successful.
* *
* @throws InsufficientCapacityException * @throws InsufficientCapacityException
* if there is insufficient capacity to deploy the VM. * if there is insufficient capacity to deploy the VM.
* @throws ConcurrentOperationException * @throws ConcurrentOperationException
* if there are multiple users working on the same VM or in the same environment. * if there are multiple users working on the same VM or in the
* same environment.
* @throws ResourceUnavailableException * @throws ResourceUnavailableException
* if the resources required to deploy the VM is not currently available. * if the resources required to deploy the VM is not currently
* available.
* @throws InsufficientResourcesException * @throws InsufficientResourcesException
*/ */
UserVm createAdvancedSecurityGroupVirtualMachine(DataCenter zone, ServiceOffering serviceOffering, VirtualMachineTemplate template, List<Long> networkIdList, List<Long> securityGroupIdList, UserVm createAdvancedSecurityGroupVirtualMachine(DataCenter zone, ServiceOffering serviceOffering, VirtualMachineTemplate template, List<Long> networkIdList, List<Long> securityGroupIdList,
Account owner, String hostName, String displayName, Long diskOfferingId, Long diskSize, String group, HypervisorType hypervisor, String userData, String sshKeyPair, Map<Long, IpAddresses> requestedIps, Account owner, String hostName, String displayName, Long diskOfferingId, Long diskSize, String group, HypervisorType hypervisor, String userData, String sshKeyPair, Map<Long, IpAddresses> requestedIps,
IpAddresses defaultIps, String keyboard) IpAddresses defaultIps, String keyboard, List<Long> affinityGroupIdList)
throws InsufficientCapacityException, ConcurrentOperationException, ResourceUnavailableException, StorageUnavailableException, ResourceAllocationException; throws InsufficientCapacityException, ConcurrentOperationException, ResourceUnavailableException, StorageUnavailableException, ResourceAllocationException;
/** /**
* Creates a User VM in Advanced Zone (Security Group feature is disabled) in the database and returns the VM to the * Creates a User VM in Advanced Zone (Security Group feature is disabled)
* caller. * in the database and returns the VM to the caller.
* *
* @param zone * @param zone
* - availability zone for the virtual machine * - availability zone for the virtual machine
* @param serviceOffering * @param serviceOffering
@ -267,49 +278,57 @@ public interface UserVmService {
* @param displayName * @param displayName
* - an optional user generated name for the virtual machine * - an optional user generated name for the virtual machine
* @param diskOfferingId * @param diskOfferingId
* - the ID of the disk offering for the virtual machine. If the template is of ISO format, the * - the ID of the disk offering for the virtual machine. If the
* diskOfferingId is * template is of ISO format, the diskOfferingId is for the root
* for the root disk volume. Otherwise this parameter is used to indicate the offering for the data disk * disk volume. Otherwise this parameter is used to indicate the
* volume. * offering for the data disk volume. If the templateId parameter
* If the templateId parameter passed is from a Template object, the diskOfferingId refers to a DATA Disk * passed is from a Template object, the diskOfferingId refers to
* Volume * a DATA Disk Volume created. If the templateId parameter passed
* created. If the templateId parameter passed is from an ISO object, the diskOfferingId refers to a ROOT * is from an ISO object, the diskOfferingId refers to a ROOT
* Disk * Disk Volume created
* Volume created
* @param diskSize * @param diskSize
* - the arbitrary size for the DATADISK volume. Mutually exclusive with diskOfferingId * - the arbitrary size for the DATADISK volume. Mutually
* exclusive with diskOfferingId
* @param group * @param group
* - an optional group for the virtual machine * - an optional group for the virtual machine
* @param hypervisor * @param hypervisor
* - the hypervisor on which to deploy the virtual machine * - the hypervisor on which to deploy the virtual machine
* @param userData * @param userData
* - an optional binary data that can be sent to the virtual machine upon a successful deployment. This * - an optional binary data that can be sent to the virtual
* binary * machine upon a successful deployment. This binary data must be
* data must be base64 encoded before adding it to the request. Currently only HTTP GET is supported. * base64 encoded before adding it to the request. Currently only
* Using HTTP * HTTP GET is supported. Using HTTP GET (via querystring), you
* GET (via querystring), you can send up to 2KB of data after base64 encoding * can send up to 2KB of data after base64 encoding
* @param sshKeyPair * @param sshKeyPair
* - name of the ssh key pair used to login to the virtual machine * - name of the ssh key pair used to login to the virtual
* machine
* @param requestedIps * @param requestedIps
* TODO * TODO
* @param defaultIps TODO * @param defaultIps
* TODO
* @param affinityGroupIdList
* @param accountName * @param accountName
* - an optional account for the virtual machine. Must be used with domainId * - an optional account for the virtual machine. Must be used
* with domainId
* @param domainId * @param domainId
* - an optional domainId for the virtual machine. If the account parameter is used, domainId must also * - an optional domainId for the virtual machine. If the account
* be used * parameter is used, domainId must also be used
* @return UserVm object if successful. * @return UserVm object if successful.
* *
* @throws InsufficientCapacityException * @throws InsufficientCapacityException
* if there is insufficient capacity to deploy the VM. * if there is insufficient capacity to deploy the VM.
* @throws ConcurrentOperationException * @throws ConcurrentOperationException
* if there are multiple users working on the same VM or in the same environment. * if there are multiple users working on the same VM or in the
* same environment.
* @throws ResourceUnavailableException * @throws ResourceUnavailableException
* if the resources required to deploy the VM is not currently available. * if the resources required to deploy the VM is not currently
* available.
* @throws InsufficientResourcesException * @throws InsufficientResourcesException
*/ */
UserVm createAdvancedVirtualMachine(DataCenter zone, ServiceOffering serviceOffering, VirtualMachineTemplate template, List<Long> networkIdList, Account owner, String hostName, UserVm createAdvancedVirtualMachine(DataCenter zone, ServiceOffering serviceOffering, VirtualMachineTemplate template, List<Long> networkIdList, Account owner, String hostName,
String displayName, Long diskOfferingId, Long diskSize, String group, HypervisorType hypervisor, String userData, String sshKeyPair, Map<Long, IpAddresses> requestedIps, IpAddresses defaultIps, String keyboard) String displayName, Long diskOfferingId, Long diskSize, String group, HypervisorType hypervisor,
String userData, String sshKeyPair, Map<Long, IpAddresses> requestedIps, IpAddresses defaultIps,
String keyboard, List<Long> affinityGroupIdList)
throws InsufficientCapacityException, ConcurrentOperationException, ResourceUnavailableException, StorageUnavailableException, ResourceAllocationException; throws InsufficientCapacityException, ConcurrentOperationException, ResourceUnavailableException, StorageUnavailableException, ResourceAllocationException;
/** /**

View File

@ -0,0 +1,14 @@
package org.apache.cloudstack.affinity;
import org.apache.cloudstack.deploy.UserPreferrenceProcessor;
public interface AffinityGroupProcessor extends UserPreferrenceProcessor {
/**
* getType() should return the affinity/anti-affinity group being
* implemented
*
* @return String Affinity/Anti-affinity type
*/
String getType();
}

View File

@ -3,6 +3,7 @@ package org.apache.cloudstack.affinity;
import java.util.List; import java.util.List;
import com.cloud.exception.ResourceInUseException; import com.cloud.exception.ResourceInUseException;
import com.cloud.uservm.UserVm;
import com.cloud.utils.Pair; import com.cloud.utils.Pair;
public interface AffinityGroupService { public interface AffinityGroupService {
@ -57,4 +58,6 @@ public interface AffinityGroupService {
AffinityGroup getAffinityGroup(Long groupId); AffinityGroup getAffinityGroup(Long groupId);
UserVm updateVMAffinityGroups(Long vmId, List<Long> affinityGroupIds);
} }

View File

@ -473,6 +473,8 @@ public class ApiConstants {
public static final String HEALTHCHECK_HEALTHY_THRESHOLD = "healthythreshold"; public static final String HEALTHCHECK_HEALTHY_THRESHOLD = "healthythreshold";
public static final String HEALTHCHECK_UNHEALTHY_THRESHOLD = "unhealthythreshold"; public static final String HEALTHCHECK_UNHEALTHY_THRESHOLD = "unhealthythreshold";
public static final String HEALTHCHECK_PINGPATH = "pingpath"; public static final String HEALTHCHECK_PINGPATH = "pingpath";
public static final String AFFINITY_GROUP_IDS = "affinitygroupids";
public static final String AFFINITY_GROUP_NAMES = "affinitygroupnames";
public enum HostDetails { public enum HostDetails {
all, capacity, events, stats, min; all, capacity, events, stats, min;

View File

@ -83,7 +83,8 @@ public class ListAffinityGroupsCmd extends BaseListCmd {
@Override @Override
public void execute(){ public void execute(){
Pair<List<AffinityGroup>, Integer> result = _affinityGroupService.listAffinityGroups(id, affinityGroupName, Pair<List<? extends AffinityGroup>, Integer> result = _affinityGroupService.listAffinityGroups(id,
affinityGroupName,
affinityGroupType, virtualMachineId, this.getStartIndex(), this.getPageSizeVal()); affinityGroupType, virtualMachineId, this.getStartIndex(), this.getPageSizeVal());
if (result != null) { if (result != null) {
ListResponse<AffinityGroupResponse> response = new ListResponse<AffinityGroupResponse>(); ListResponse<AffinityGroupResponse> response = new ListResponse<AffinityGroupResponse>();

View File

@ -0,0 +1,158 @@
// 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 java.util.ArrayList;
import java.util.List;
import org.apache.cloudstack.affinity.AffinityGroupResponse;
import org.apache.cloudstack.api.ACL;
import org.apache.cloudstack.api.APICommand;
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.UserVmResponse;
import org.apache.log4j.Logger;
import com.cloud.async.AsyncJob;
import com.cloud.event.EventTypes;
import com.cloud.exception.InsufficientCapacityException;
import com.cloud.exception.InvalidParameterValueException;
import com.cloud.exception.ResourceUnavailableException;
import com.cloud.user.Account;
import com.cloud.user.UserContext;
import com.cloud.uservm.UserVm;
@APICommand(name = "updateVMAffinityGroup", description = "Updates the affinity/anti-affinity group associations of a virtual machine. The VM has to be stopped and restarted for the "
+ "new properties to take effect.", responseObject = UserVmResponse.class)
public class UpdateVMAffinityGroupCmd extends BaseAsyncCmd {
public static final Logger s_logger = Logger.getLogger(UpdateVMAffinityGroupCmd.class.getName());
private static final String s_name = "updatevirtualmachineresponse";
/////////////////////////////////////////////////////
//////////////// API parameters /////////////////////
/////////////////////////////////////////////////////
@ACL
@Parameter(name=ApiConstants.ID, type=CommandType.UUID, entityType=UserVmResponse.class,
required=true, description="The ID of the virtual machine")
private Long id;
@ACL
@Parameter(name = ApiConstants.AFFINITY_GROUP_IDS, type = CommandType.LIST, collectionType = CommandType.UUID, entityType = AffinityGroupResponse.class, description = "comma separated list of affinity groups id that are going to be applied to the virtual machine. "
+ "Should be passed only when vm is created from a zone with Basic Network support."
+ " Mutually exclusive with securitygroupnames parameter")
private List<Long> affinityGroupIdList;
@ACL
@Parameter(name = ApiConstants.AFFINITY_GROUP_NAMES, type = CommandType.LIST, collectionType = CommandType.STRING, entityType = AffinityGroupResponse.class, description = "comma separated list of affinity groups names that are going to be applied to the virtual machine."
+ " Should be passed only when vm is created from a zone with Basic Network support. "
+ "Mutually exclusive with securitygroupids parameter")
private List<String> affinityGroupNameList;
/////////////////////////////////////////////////////
/////////////////// Accessors ///////////////////////
/////////////////////////////////////////////////////
public Long getId() {
return id;
}
public List<Long> getAffinityGroupIdList() {
if (affinityGroupNameList != null && affinityGroupIdList != null) {
throw new InvalidParameterValueException(
"affinitygroupids parameter is mutually exclusive with affinitygroupnames parameter");
}
// transform group names to ids here
if (affinityGroupNameList != null) {
List<Long> affinityGroupIds = new ArrayList<Long>();
for (String groupName : affinityGroupNameList) {
Long groupId = _responseGenerator.getAffinityGroupId(groupName, getEntityOwnerId());
if (groupId == null) {
throw new InvalidParameterValueException("Unable to find group by name " + groupName
+ " for account " + getEntityOwnerId());
} else {
affinityGroupIds.add(groupId);
}
}
return affinityGroupIds;
} else {
return affinityGroupIdList;
}
}
/////////////////////////////////////////////////////
/////////////// API Implementation///////////////////
/////////////////////////////////////////////////////
@Override
public String getCommandName() {
return s_name;
}
public static String getResultObjectName() {
return "virtualmachine";
}
@Override
public long getEntityOwnerId() {
UserVm userVm = _entityMgr.findById(UserVm.class, getId());
if (userVm != null) {
return userVm.getAccountId();
}
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 {
UserContext.current().setEventDetails("Vm Id: "+getId());
UserVm result = _affinityGroupService.updateVMAffinityGroups(getId(), getAffinityGroupIdList());
if (result != null){
UserVmResponse response = _responseGenerator.createUserVmResponse("virtualmachine", result).get(0);
response.setResponseName(getCommandName());
this.setResponseObject(response);
} else {
throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, "Failed to update vm's affinity groups");
}
}
@Override
public String getEventType() {
return EventTypes.EVENT_VM_AFFINITY_GROUP_UPDATE;
}
@Override
public String getEventDescription() {
return "updating VM Affinity Group";
}
@Override
public AsyncJob.Type getInstanceType() {
return AsyncJob.Type.AffinityGroup;
}
}

View File

@ -25,6 +25,7 @@ import java.util.List;
import java.util.Map; import java.util.Map;
import org.apache.cloudstack.acl.SecurityChecker.AccessType; import org.apache.cloudstack.acl.SecurityChecker.AccessType;
import org.apache.cloudstack.affinity.AffinityGroupResponse;
import org.apache.cloudstack.api.ACL; import org.apache.cloudstack.api.ACL;
import org.apache.cloudstack.api.APICommand; import org.apache.cloudstack.api.APICommand;
import org.apache.cloudstack.api.ApiConstants; import org.apache.cloudstack.api.ApiConstants;
@ -172,6 +173,18 @@ public class DeployVMCmd extends BaseAsyncCreateCmd {
@Parameter(name=ApiConstants.START_VM, type=CommandType.BOOLEAN, description="true if network offering supports specifying ip ranges; defaulted to true if not specified") @Parameter(name=ApiConstants.START_VM, type=CommandType.BOOLEAN, description="true if network offering supports specifying ip ranges; defaulted to true if not specified")
private Boolean startVm; private Boolean startVm;
@ACL
@Parameter(name = ApiConstants.AFFINITY_GROUP_IDS, type = CommandType.LIST, collectionType = CommandType.UUID, entityType = AffinityGroupResponse.class, description = "comma separated list of affinity groups id that are going to be applied to the virtual machine. "
+ "Should be passed only when vm is created from a zone with Basic Network support."
+ " Mutually exclusive with securitygroupnames parameter")
private List<Long> affinityGroupIdList;
@ACL
@Parameter(name = ApiConstants.AFFINITY_GROUP_NAMES, type = CommandType.LIST, collectionType = CommandType.STRING, entityType = AffinityGroupResponse.class, description = "comma separated list of affinity groups names that are going to be applied to the virtual machine."
+ " Should be passed only when vm is created from a zone with Basic Network support. "
+ "Mutually exclusive with securitygroupids parameter")
private List<String> affinityGroupNameList;
///////////////////////////////////////////////////// /////////////////////////////////////////////////////
/////////////////// Accessors /////////////////////// /////////////////// Accessors ///////////////////////
@ -321,6 +334,30 @@ public class DeployVMCmd extends BaseAsyncCreateCmd {
return ip6Address.toLowerCase(); return ip6Address.toLowerCase();
} }
public List<Long> getAffinityGroupIdList() {
if (affinityGroupNameList != null && affinityGroupIdList != null) {
throw new InvalidParameterValueException(
"affinitygroupids parameter is mutually exclusive with affinitygroupnames parameter");
}
// transform group names to ids here
if (affinityGroupNameList != null) {
List<Long> affinityGroupIds = new ArrayList<Long>();
for (String groupName : affinityGroupNameList) {
Long groupId = _responseGenerator.getAffinityGroupId(groupName, getEntityOwnerId());
if (groupId == null) {
throw new InvalidParameterValueException("Unable to find group by name " + groupName
+ " for account " + getEntityOwnerId());
} else {
affinityGroupIds.add(groupId);
}
}
return affinityGroupIds;
} else {
return affinityGroupIdList;
}
}
///////////////////////////////////////////////////// /////////////////////////////////////////////////////
/////////////// API Implementation/////////////////// /////////////// API Implementation///////////////////
///////////////////////////////////////////////////// /////////////////////////////////////////////////////
@ -447,18 +484,18 @@ public class DeployVMCmd extends BaseAsyncCreateCmd {
throw new InvalidParameterValueException("Can't specify network Ids in Basic zone"); throw new InvalidParameterValueException("Can't specify network Ids in Basic zone");
} else { } else {
vm = _userVmService.createBasicSecurityGroupVirtualMachine(zone, serviceOffering, template, getSecurityGroupIdList(), owner, name, vm = _userVmService.createBasicSecurityGroupVirtualMachine(zone, serviceOffering, template, getSecurityGroupIdList(), owner, name,
displayName, diskOfferingId, size, group, getHypervisor(), userData, sshKeyPairName, getIpToNetworkMap(), addrs, keyboard); displayName, diskOfferingId, size, group, getHypervisor(), userData, sshKeyPairName, getIpToNetworkMap(), addrs, keyboard, getAffinityGroupIdList());
} }
} else { } else {
if (zone.isSecurityGroupEnabled()) { if (zone.isSecurityGroupEnabled()) {
vm = _userVmService.createAdvancedSecurityGroupVirtualMachine(zone, serviceOffering, template, getNetworkIds(), getSecurityGroupIdList(), vm = _userVmService.createAdvancedSecurityGroupVirtualMachine(zone, serviceOffering, template, getNetworkIds(), getSecurityGroupIdList(),
owner, name, displayName, diskOfferingId, size, group, getHypervisor(), userData, sshKeyPairName, getIpToNetworkMap(), addrs, keyboard); owner, name, displayName, diskOfferingId, size, group, getHypervisor(), userData, sshKeyPairName, getIpToNetworkMap(), addrs, keyboard, getAffinityGroupIdList());
} else { } else {
if (getSecurityGroupIdList() != null && !getSecurityGroupIdList().isEmpty()) { if (getSecurityGroupIdList() != null && !getSecurityGroupIdList().isEmpty()) {
throw new InvalidParameterValueException("Can't create vm with security groups; security group feature is not enabled per zone"); throw new InvalidParameterValueException("Can't create vm with security groups; security group feature is not enabled per zone");
} }
vm = _userVmService.createAdvancedVirtualMachine(zone, serviceOffering, template, getNetworkIds(), owner, name, displayName, vm = _userVmService.createAdvancedVirtualMachine(zone, serviceOffering, template, getNetworkIds(), owner, name, displayName,
diskOfferingId, size, group, getHypervisor(), userData, sshKeyPairName, getIpToNetworkMap(), addrs, keyboard); diskOfferingId, size, group, getHypervisor(), userData, sshKeyPairName, getIpToNetworkMap(), addrs, keyboard, getAffinityGroupIdList());
} }
} }

View File

@ -0,0 +1,27 @@
package org.apache.cloudstack.deploy;
import com.cloud.deploy.DeploymentPlan;
import com.cloud.deploy.DeploymentPlanner.ExcludeList;
import com.cloud.exception.AffinityConflictException;
import com.cloud.utils.component.Adapter;
import com.cloud.vm.VirtualMachine;
import com.cloud.vm.VirtualMachineProfile;
public interface UserPreferrenceProcessor extends Adapter {
/**
* process() is called to apply any user preferences to the deployment plan
* and avoid set for the given VM placement.
*
* @param vm
* virtual machine.
* @param plan
* deployment plan that tells you where it's being deployed to.
* @param avoid
* avoid these data centers, pods, clusters, or hosts.
*/
void process(VirtualMachineProfile<? extends VirtualMachine> vm, DeploymentPlan plan, ExcludeList avoid)
throws AffinityConflictException;
}

View File

@ -0,0 +1,29 @@
package com.cloud.deploy;
import com.cloud.deploy.DeploymentPlanner.ExcludeList;
import com.cloud.exception.AffinityConflictException;
import com.cloud.exception.InsufficientServerCapacityException;
import com.cloud.utils.component.Manager;
import com.cloud.vm.VirtualMachine;
import com.cloud.vm.VirtualMachineProfile;
public interface DeploymentPlanningManager extends Manager {
/**
* Manages vm deployment stages: First Process Affinity/Anti-affinity - Call
* the chain of AffinityGroupProcessor adapters to set deploymentplan scope
* and exclude list Secondly, Call DeploymentPlanner - to use heuristics to
* find the best spot to place the vm/volume. Planner will drill down to the
* write set of clusters to look for placement based on various heuristics.
* Lastly, Call Allocators - Given a cluster, allocators matches the
* requirements to capabilities of the physical resource (host, storage
* pool).
*
* @throws AffinityConflictException
*
*
*
*/
DeployDestination planDeployment(VirtualMachineProfile<? extends VirtualMachine> vmProfile, DeploymentPlan plan,
ExcludeList avoids) throws InsufficientServerCapacityException, AffinityConflictException;
}

View File

@ -0,0 +1,80 @@
package com.cloud.deploy;
import java.util.List;
import javax.ejb.Local;
import javax.inject.Inject;
import org.apache.cloudstack.affinity.AffinityGroupProcessor;
import org.apache.cloudstack.affinity.AffinityGroupVMMapVO;
import org.apache.cloudstack.affinity.dao.AffinityGroupDao;
import org.apache.cloudstack.affinity.dao.AffinityGroupVMMapDao;
import org.apache.log4j.Logger;
import com.cloud.deploy.DeploymentPlanner.ExcludeList;
import com.cloud.exception.AffinityConflictException;
import com.cloud.exception.InsufficientServerCapacityException;
import com.cloud.utils.component.Manager;
import com.cloud.utils.component.ManagerBase;
import com.cloud.vm.VirtualMachine;
import com.cloud.vm.VirtualMachineProfile;
import com.cloud.vm.dao.UserVmDao;
import com.cloud.vm.dao.VMInstanceDao;
@Local(value = { DeploymentPlanningManager.class })
public class DeploymentPlanningManagerImpl extends ManagerBase implements DeploymentPlanningManager, Manager {
private static final Logger s_logger = Logger.getLogger(DeploymentPlanningManagerImpl.class);
@Inject
protected UserVmDao _vmDao;
@Inject
protected VMInstanceDao _vmInstanceDao;
@Inject
protected AffinityGroupDao _affinityGroupDao;
@Inject
protected AffinityGroupVMMapDao _affinityGroupVMMapDao;
@Inject
protected List<DeploymentPlanner> _planners;
@Inject
protected List<AffinityGroupProcessor> _affinityProcessors;
@Override
public DeployDestination planDeployment(VirtualMachineProfile<? extends VirtualMachine> vmProfile,
DeploymentPlan plan, ExcludeList avoids) throws InsufficientServerCapacityException,
AffinityConflictException {
// call affinitygroup chain
VirtualMachine vm = vmProfile.getVirtualMachine();
long vmGroupCount = _affinityGroupVMMapDao.countAffinityGroupsForVm(vm.getId());
if (vmGroupCount > 0) {
for (AffinityGroupProcessor processor : _affinityProcessors) {
processor.process(vmProfile, plan, avoids);
}
}
if (s_logger.isDebugEnabled()) {
s_logger.debug("Deploy avoids pods: " + avoids.getPodsToAvoid() + ", clusters: "
+ avoids.getClustersToAvoid() + ", hosts: " + avoids.getHostsToAvoid());
}
// call planners
DeployDestination dest = null;
for (DeploymentPlanner planner : _planners) {
if (planner.canHandle(vmProfile, plan, avoids)) {
dest = planner.plan(vmProfile, plan, avoids);
} else {
continue;
}
if (dest != null) {
avoids.addHost(dest.getHost().getId());
break;
}
}
return dest;
}
}

View File

@ -35,6 +35,9 @@ import javax.naming.ConfigurationException;
import com.cloud.api.ApiDBUtils; import com.cloud.api.ApiDBUtils;
import org.apache.cloudstack.acl.ControlledEntity.ACLType; import org.apache.cloudstack.acl.ControlledEntity.ACLType;
import org.apache.cloudstack.acl.SecurityChecker.AccessType; import org.apache.cloudstack.acl.SecurityChecker.AccessType;
import org.apache.cloudstack.affinity.AffinityGroupVO;
import org.apache.cloudstack.affinity.dao.AffinityGroupDao;
import org.apache.cloudstack.affinity.dao.AffinityGroupVMMapDao;
import org.apache.cloudstack.api.command.admin.vm.AssignVMCmd; import org.apache.cloudstack.api.command.admin.vm.AssignVMCmd;
import org.apache.cloudstack.api.command.admin.vm.RecoverVMCmd; import org.apache.cloudstack.api.command.admin.vm.RecoverVMCmd;
import org.apache.cloudstack.api.command.user.vm.*; import org.apache.cloudstack.api.command.user.vm.*;
@ -369,7 +372,7 @@ public class UserVmManagerImpl extends ManagerBase implements UserVmManager, Use
VpcManager _vpcMgr; VpcManager _vpcMgr;
@Inject @Inject
TemplateManager templateMgr; TemplateManager templateMgr;
@Inject @Inject
protected GuestOSCategoryDao _guestOSCategoryDao; protected GuestOSCategoryDao _guestOSCategoryDao;
@Inject @Inject
UsageEventDao _usageEventDao; UsageEventDao _usageEventDao;
@ -378,6 +381,11 @@ public class UserVmManagerImpl extends ManagerBase implements UserVmManager, Use
@Inject @Inject
protected VMSnapshotManager _vmSnapshotMgr; protected VMSnapshotManager _vmSnapshotMgr;
@Inject
AffinityGroupVMMapDao _affinityGroupVMMapDao;
@Inject
AffinityGroupDao _affinityGroupDao;
@Inject @Inject
List<DeployPlannerSelector> plannerSelectors; List<DeployPlannerSelector> plannerSelectors;
@ -684,7 +692,7 @@ public class UserVmManagerImpl extends ManagerBase implements UserVmManager, Use
try { try {
VirtualMachineEntity vmEntity = _orchSrvc.getVirtualMachine(vm.getUuid()); VirtualMachineEntity vmEntity = _orchSrvc.getVirtualMachine(vm.getUuid());
status = vmEntity.stop(new Long(userId).toString()); status = vmEntity.stop(new Long(userId).toString());
} catch (ResourceUnavailableException e) { } catch (ResourceUnavailableException e) {
s_logger.debug("Unable to stop due to ", e); s_logger.debug("Unable to stop due to ", e);
status = false; status = false;
@ -1916,7 +1924,10 @@ public class UserVmManagerImpl extends ManagerBase implements UserVmManager, Use
@Override @Override
public UserVm createBasicSecurityGroupVirtualMachine(DataCenter zone, ServiceOffering serviceOffering, VirtualMachineTemplate template, List<Long> securityGroupIdList, Account owner, public UserVm createBasicSecurityGroupVirtualMachine(DataCenter zone, ServiceOffering serviceOffering, VirtualMachineTemplate template, List<Long> securityGroupIdList, Account owner,
String hostName, String displayName, Long diskOfferingId, Long diskSize, String group, HypervisorType hypervisor, String userData, String sshKeyPair, Map<Long, IpAddresses> requestedIps, IpAddresses defaultIps, String keyboard) String hostName,
String displayName, Long diskOfferingId, Long diskSize, String group, HypervisorType hypervisor,
String userData, String sshKeyPair, Map<Long, IpAddresses> requestedIps, IpAddresses defaultIps,
String keyboard, List<Long> affinityGroupIdList)
throws InsufficientCapacityException, ConcurrentOperationException, ResourceUnavailableException, StorageUnavailableException, ResourceAllocationException { throws InsufficientCapacityException, ConcurrentOperationException, ResourceUnavailableException, StorageUnavailableException, ResourceAllocationException {
Account caller = UserContext.current().getCaller(); Account caller = UserContext.current().getCaller();
@ -1966,13 +1977,17 @@ public class UserVmManagerImpl extends ManagerBase implements UserVmManager, Use
} }
return createVirtualMachine(zone, serviceOffering, template, hostName, displayName, owner, diskOfferingId, return createVirtualMachine(zone, serviceOffering, template, hostName, displayName, owner, diskOfferingId,
diskSize, networkList, securityGroupIdList, group, userData, sshKeyPair, hypervisor, caller, requestedIps, defaultIps, keyboard); diskSize, networkList, securityGroupIdList, group, userData, sshKeyPair, hypervisor, caller,
requestedIps, defaultIps, keyboard, affinityGroupIdList);
} }
@Override @Override
public UserVm createAdvancedSecurityGroupVirtualMachine(DataCenter zone, ServiceOffering serviceOffering, VirtualMachineTemplate template, List<Long> networkIdList, public UserVm createAdvancedSecurityGroupVirtualMachine(DataCenter zone, ServiceOffering serviceOffering, VirtualMachineTemplate template, List<Long> networkIdList,
List<Long> securityGroupIdList, Account owner, String hostName, String displayName, Long diskOfferingId, Long diskSize, String group, HypervisorType hypervisor, String userData, List<Long> securityGroupIdList, Account owner, String hostName, String displayName, Long diskOfferingId, Long diskSize, String group, HypervisorType hypervisor, String userData,
String sshKeyPair, Map<Long, IpAddresses> requestedIps, IpAddresses defaultIps, String keyboard) throws InsufficientCapacityException, ConcurrentOperationException, ResourceUnavailableException, StorageUnavailableException, String sshKeyPair, Map<Long, IpAddresses> requestedIps,
IpAddresses defaultIps, String keyboard, List<Long> affinityGroupIdList)
throws InsufficientCapacityException, ConcurrentOperationException, ResourceUnavailableException,
StorageUnavailableException,
ResourceAllocationException { ResourceAllocationException {
Account caller = UserContext.current().getCaller(); Account caller = UserContext.current().getCaller();
@ -2018,7 +2033,7 @@ public class UserVmManagerImpl extends ManagerBase implements UserVmManager, Use
isSecurityGroupEnabledNetworkUsed = true; isSecurityGroupEnabledNetworkUsed = true;
} else { } else {
// Verify that all the networks are Shared/Guest; can't create combination of SG enabled and disabled networks // Verify that all the networks are Shared/Guest; can't create combination of SG enabled and disabled networks
for (Long networkId : networkIdList) { for (Long networkId : networkIdList) {
NetworkVO network = _networkDao.findById(networkId); NetworkVO network = _networkDao.findById(networkId);
@ -2034,7 +2049,7 @@ public class UserVmManagerImpl extends ManagerBase implements UserVmManager, Use
} }
isSecurityGroupEnabledNetworkUsed = true; isSecurityGroupEnabledNetworkUsed = true;
} }
if (!(network.getTrafficType() == TrafficType.Guest && network.getGuestType() == Network.GuestType.Shared)) { if (!(network.getTrafficType() == TrafficType.Guest && network.getGuestType() == Network.GuestType.Shared)) {
throw new InvalidParameterValueException("Can specify only Shared Guest networks when" + throw new InvalidParameterValueException("Can specify only Shared Guest networks when" +
@ -2079,12 +2094,15 @@ public class UserVmManagerImpl extends ManagerBase implements UserVmManager, Use
} }
return createVirtualMachine(zone, serviceOffering, template, hostName, displayName, owner, diskOfferingId, return createVirtualMachine(zone, serviceOffering, template, hostName, displayName, owner, diskOfferingId,
diskSize, networkList, securityGroupIdList, group, userData, sshKeyPair, hypervisor, caller, requestedIps, defaultIps, keyboard); diskSize, networkList, securityGroupIdList, group, userData, sshKeyPair, hypervisor, caller,
requestedIps, defaultIps, keyboard, affinityGroupIdList);
} }
@Override @Override
public UserVm createAdvancedVirtualMachine(DataCenter zone, ServiceOffering serviceOffering, VirtualMachineTemplate template, List<Long> networkIdList, Account owner, String hostName, public UserVm createAdvancedVirtualMachine(DataCenter zone, ServiceOffering serviceOffering, VirtualMachineTemplate template, List<Long> networkIdList, Account owner, String hostName,
String displayName, Long diskOfferingId, Long diskSize, String group, HypervisorType hypervisor, String userData, String sshKeyPair, Map<Long, IpAddresses> requestedIps, IpAddresses defaultIps, String keyboard) String displayName, Long diskOfferingId, Long diskSize, String group, HypervisorType hypervisor,
String userData, String sshKeyPair, Map<Long, IpAddresses> requestedIps, IpAddresses defaultIps,
String keyboard, List<Long> affinityGroupIdList)
throws InsufficientCapacityException, ConcurrentOperationException, ResourceUnavailableException, StorageUnavailableException, ResourceAllocationException { throws InsufficientCapacityException, ConcurrentOperationException, ResourceUnavailableException, StorageUnavailableException, ResourceAllocationException {
Account caller = UserContext.current().getCaller(); Account caller = UserContext.current().getCaller();
@ -2192,7 +2210,9 @@ public class UserVmManagerImpl extends ManagerBase implements UserVmManager, Use
} }
} }
return createVirtualMachine(zone, serviceOffering, template, hostName, displayName, owner, diskOfferingId, diskSize, networkList, null, group, userData, sshKeyPair, hypervisor, caller, requestedIps, defaultIps, keyboard); return createVirtualMachine(zone, serviceOffering, template, hostName, displayName, owner, diskOfferingId,
diskSize, networkList, null, group, userData, sshKeyPair, hypervisor, caller, requestedIps, defaultIps,
keyboard, affinityGroupIdList);
} }
@ -2205,7 +2225,9 @@ public class UserVmManagerImpl extends ManagerBase implements UserVmManager, Use
@DB @ActionEvent(eventType = EventTypes.EVENT_VM_CREATE, eventDescription = "deploying Vm", create = true) @DB @ActionEvent(eventType = EventTypes.EVENT_VM_CREATE, eventDescription = "deploying Vm", create = true)
protected UserVm createVirtualMachine(DataCenter zone, ServiceOffering serviceOffering, VirtualMachineTemplate template, String hostName, String displayName, Account owner, Long diskOfferingId, protected UserVm createVirtualMachine(DataCenter zone, ServiceOffering serviceOffering, VirtualMachineTemplate template, String hostName, String displayName, Account owner, Long diskOfferingId,
Long diskSize, List<NetworkVO> networkList, List<Long> securityGroupIdList, String group, String userData, String sshKeyPair, HypervisorType hypervisor, Account caller, Map<Long, IpAddresses> requestedIps, IpAddresses defaultIps, String keyboard) Long diskSize, List<NetworkVO> networkList, List<Long> securityGroupIdList, String group, String userData,
String sshKeyPair, HypervisorType hypervisor, Account caller, Map<Long, IpAddresses> requestedIps,
IpAddresses defaultIps, String keyboard, List<Long> affinityGroupIdList)
throws InsufficientCapacityException, ResourceUnavailableException, ConcurrentOperationException, StorageUnavailableException, ResourceAllocationException { throws InsufficientCapacityException, ResourceUnavailableException, ConcurrentOperationException, StorageUnavailableException, ResourceAllocationException {
_accountMgr.checkAccess(caller, null, true, owner); _accountMgr.checkAccess(caller, null, true, owner);
@ -2261,6 +2283,14 @@ public class UserVmManagerImpl extends ManagerBase implements UserVmManager, Use
} }
} }
// check that the affinity groups exist
for (Long affinityGroupId : affinityGroupIdList) {
AffinityGroupVO ag = _affinityGroupDao.findById(affinityGroupId);
if (ag == null) {
throw new InvalidParameterValueException("Unable to find affinity group by id " + affinityGroupId);
}
}
if (template.getHypervisorType() != null && template.getHypervisorType() != HypervisorType.BareMetal) { if (template.getHypervisorType() != null && template.getHypervisorType() != HypervisorType.BareMetal) {
// check if we have available pools for vm deployment // check if we have available pools for vm deployment
long availablePools = _storagePoolDao.countPoolsByStatus(StoragePoolStatus.Up); long availablePools = _storagePoolDao.countPoolsByStatus(StoragePoolStatus.Up);
@ -2438,7 +2468,7 @@ public class UserVmManagerImpl extends ManagerBase implements UserVmManager, Use
// * verify that there are no duplicates // * verify that there are no duplicates
if (hostNames.contains(hostName)) { if (hostNames.contains(hostName)) {
throw new InvalidParameterValueException("The vm with hostName " + hostName throw new InvalidParameterValueException("The vm with hostName " + hostName
+ " already exists in the network domain: " + ntwkDomain + "; network=" + " already exists in the network domain: " + ntwkDomain + "; network="
+ _networkModel.getNetwork(ntwkId)); + _networkModel.getNetwork(ntwkId));
} }
} }
@ -2510,7 +2540,7 @@ public class UserVmManagerImpl extends ManagerBase implements UserVmManager, Use
List<String> computeTags = new ArrayList<String>(); List<String> computeTags = new ArrayList<String>();
computeTags.add(offering.getHostTag()); computeTags.add(offering.getHostTag());
List<String> rootDiskTags = new ArrayList<String>(); List<String> rootDiskTags = new ArrayList<String>();
rootDiskTags.add(offering.getTags()); rootDiskTags.add(offering.getTags());
if(isIso){ if(isIso){
@ -2552,6 +2582,8 @@ public class UserVmManagerImpl extends ManagerBase implements UserVmManager, Use
_securityGroupMgr.addInstanceToGroups(vm.getId(), securityGroupIdList); _securityGroupMgr.addInstanceToGroups(vm.getId(), securityGroupIdList);
_affinityGroupVMMapDao.updateMap(vm.getId(), affinityGroupIdList);
return vm; return vm;
} }
@ -2829,7 +2861,7 @@ public class UserVmManagerImpl extends ManagerBase implements UserVmManager, Use
try { try {
VirtualMachineEntity vmEntity = _orchSrvc.getVirtualMachine(vm.getUuid()); VirtualMachineEntity vmEntity = _orchSrvc.getVirtualMachine(vm.getUuid());
vmEntity.stop(new Long(userId).toString()); vmEntity.stop(new Long(userId).toString());
} catch (ResourceUnavailableException e) { } catch (ResourceUnavailableException e) {
throw new CloudRuntimeException( throw new CloudRuntimeException(
"Unable to contact the agent to stop the virtual machine " "Unable to contact the agent to stop the virtual machine "
@ -3044,7 +3076,7 @@ public class UserVmManagerImpl extends ManagerBase implements UserVmManager, Use
try { try {
VirtualMachineEntity vmEntity = _orchSrvc.getVirtualMachine(vm.getUuid()); VirtualMachineEntity vmEntity = _orchSrvc.getVirtualMachine(vm.getUuid());
status = vmEntity.destroy(new Long(userId).toString()); status = vmEntity.destroy(new Long(userId).toString());
} catch (CloudException e) { } catch (CloudException e) {
CloudRuntimeException ex = new CloudRuntimeException( CloudRuntimeException ex = new CloudRuntimeException(
"Unable to destroy with specified vmId", e); "Unable to destroy with specified vmId", e);

View File

@ -5,7 +5,7 @@
// to you under the Apache License, Version 2.0 (the // to you under the Apache License, Version 2.0 (the
// "License"); you may not use this file except in compliance // "License"); you may not use this file except in compliance
// with the License. You may obtain a copy of the License at // with the License. You may obtain a copy of the License at
// //
// http://www.apache.org/licenses/LICENSE-2.0 // http://www.apache.org/licenses/LICENSE-2.0
// //
// Unless required by applicable law or agreed to in writing, // Unless required by applicable law or agreed to in writing,
@ -68,7 +68,9 @@ import com.cloud.deploy.DeployDestination;
import com.cloud.deploy.DeploymentPlan; import com.cloud.deploy.DeploymentPlan;
import com.cloud.deploy.DeploymentPlanner; import com.cloud.deploy.DeploymentPlanner;
import com.cloud.deploy.DeploymentPlanner.ExcludeList; import com.cloud.deploy.DeploymentPlanner.ExcludeList;
import com.cloud.deploy.DeploymentPlanningManager;
import com.cloud.domain.dao.DomainDao; import com.cloud.domain.dao.DomainDao;
import com.cloud.exception.AffinityConflictException;
import com.cloud.exception.AgentUnavailableException; import com.cloud.exception.AgentUnavailableException;
import com.cloud.exception.ConcurrentOperationException; import com.cloud.exception.ConcurrentOperationException;
import com.cloud.exception.ConnectionException; import com.cloud.exception.ConnectionException;
@ -226,8 +228,8 @@ public class VirtualMachineManagerImpl extends ManagerBase implements VirtualMac
@Inject @Inject
protected ResourceManager _resourceMgr; protected ResourceManager _resourceMgr;
@Inject @Inject
protected VMSnapshotManager _vmSnapshotMgr = null; protected VMSnapshotManager _vmSnapshotMgr = null;
@Inject @Inject
protected ClusterDetailsDao _clusterDetailsDao; protected ClusterDetailsDao _clusterDetailsDao;
@ -239,6 +241,9 @@ public class VirtualMachineManagerImpl extends ManagerBase implements VirtualMac
@Inject @Inject
VolumeManager volumeMgr; VolumeManager volumeMgr;
@Inject
DeploymentPlanningManager _dpMgr;
Map<VirtualMachine.Type, VirtualMachineGuru<? extends VMInstanceVO>> _vmGurus = new HashMap<VirtualMachine.Type, VirtualMachineGuru<? extends VMInstanceVO>>(); Map<VirtualMachine.Type, VirtualMachineGuru<? extends VMInstanceVO>> _vmGurus = new HashMap<VirtualMachine.Type, VirtualMachineGuru<? extends VMInstanceVO>>();
protected StateMachine2<State, VirtualMachine.Event, VirtualMachine> _stateMachine; protected StateMachine2<State, VirtualMachine.Event, VirtualMachine> _stateMachine;
@ -586,7 +591,7 @@ public class VirtualMachineManagerImpl extends ManagerBase implements VirtualMac
ConcurrentOperationException, ResourceUnavailableException { ConcurrentOperationException, ResourceUnavailableException {
return advanceStart(vm, params, caller, account, null); return advanceStart(vm, params, caller, account, null);
} }
@Override @Override
public <T extends VMInstanceVO> T advanceStart(T vm, Map<VirtualMachineProfile.Param, Object> params, User caller, Account account, DeploymentPlan planToDeploy) public <T extends VMInstanceVO> T advanceStart(T vm, Map<VirtualMachineProfile.Param, Object> params, User caller, Account account, DeploymentPlan planToDeploy)
throws InsufficientCapacityException, ConcurrentOperationException, ResourceUnavailableException { throws InsufficientCapacityException, ConcurrentOperationException, ResourceUnavailableException {
@ -695,17 +700,11 @@ public class VirtualMachineManagerImpl extends ManagerBase implements VirtualMac
VirtualMachineProfileImpl<T> vmProfile = new VirtualMachineProfileImpl<T>(vm, template, offering, account, params); VirtualMachineProfileImpl<T> vmProfile = new VirtualMachineProfileImpl<T>(vm, template, offering, account, params);
DeployDestination dest = null; DeployDestination dest = null;
for (DeploymentPlanner planner : _planners) { try {
if (planner.canHandle(vmProfile, plan, avoids)) { dest = _dpMgr.planDeployment(vmProfile, plan, avoids);
dest = planner.plan(vmProfile, plan, avoids); } catch (AffinityConflictException e2) {
} else { // TODO Auto-generated catch block
continue; e2.printStackTrace();
}
if (dest != null) {
avoids.addHost(dest.getHost().getId());
journal.record("Deployment found ", vmProfile, dest);
break;
}
} }
if (dest == null) { if (dest == null) {
@ -739,7 +738,7 @@ public class VirtualMachineManagerImpl extends ManagerBase implements VirtualMac
if (s_logger.isDebugEnabled()) { if (s_logger.isDebugEnabled()) {
s_logger.debug("VM is being created in podId: " + vm.getPodIdToDeployIn()); s_logger.debug("VM is being created in podId: " + vm.getPodIdToDeployIn());
} }
_networkMgr.prepare(vmProfile, dest, ctx); _networkMgr.prepare(vmProfile, dest, ctx);
if (vm.getHypervisorType() != HypervisorType.BareMetal) { if (vm.getHypervisorType() != HypervisorType.BareMetal) {
this.volumeMgr.prepare(vmProfile, dest); this.volumeMgr.prepare(vmProfile, dest);
} }
@ -797,7 +796,7 @@ public class VirtualMachineManagerImpl extends ManagerBase implements VirtualMac
StopCommand cmd = new StopCommand(vm); StopCommand cmd = new StopCommand(vm);
StopAnswer answer = (StopAnswer) _agentMgr.easySend(destHostId, cmd); StopAnswer answer = (StopAnswer) _agentMgr.easySend(destHostId, cmd);
if (answer == null || !answer.getResult()) { if (answer == null || !answer.getResult()) {
s_logger.warn("Unable to stop " + vm + " due to " + (answer != null ? answer.getDetails() : "no answers")); s_logger.warn("Unable to stop " + vm + " due to " + (answer != null ? answer.getDetails() : "no answers"));
_haMgr.scheduleStop(vm, destHostId, WorkType.ForceStop); _haMgr.scheduleStop(vm, destHostId, WorkType.ForceStop);
throw new ExecutionException("Unable to stop " + vm + " so we are unable to retry the start operation"); throw new ExecutionException("Unable to stop " + vm + " so we are unable to retry the start operation");
} }
@ -1144,7 +1143,7 @@ public class VirtualMachineManagerImpl extends ManagerBase implements VirtualMac
s_logger.error("State transit with event: " + e + " failed due to: " + vm.getInstanceName() + " has active VM snapshots tasks"); s_logger.error("State transit with event: " + e + " failed due to: " + vm.getInstanceName() + " has active VM snapshots tasks");
return false; return false;
} }
State oldState = vm.getState(); State oldState = vm.getState();
if (oldState == State.Starting) { if (oldState == State.Starting) {
if (e == Event.OperationSucceeded) { if (e == Event.OperationSucceeded) {
@ -1179,12 +1178,12 @@ public class VirtualMachineManagerImpl extends ManagerBase implements VirtualMac
s_logger.debug("Unable to stop " + vm); s_logger.debug("Unable to stop " + vm);
return false; return false;
} }
if (!_vmSnapshotMgr.deleteAllVMSnapshots(vm.getId(),null)){ if (!_vmSnapshotMgr.deleteAllVMSnapshots(vm.getId(),null)){
s_logger.debug("Unable to delete all snapshots for " + vm); s_logger.debug("Unable to delete all snapshots for " + vm);
return false; return false;
} }
try { try {
if (!stateTransitTo(vm, VirtualMachine.Event.DestroyRequested, vm.getHostId())) { if (!stateTransitTo(vm, VirtualMachine.Event.DestroyRequested, vm.getHostId())) {
s_logger.debug("Unable to destroy the vm because it is not in the correct state: " + vm); s_logger.debug("Unable to destroy the vm because it is not in the correct state: " + vm);
@ -1559,7 +1558,7 @@ public class VirtualMachineManagerImpl extends ManagerBase implements VirtualMac
@Override @Override
public boolean isVirtualMachineUpgradable(VirtualMachine vm, ServiceOffering offering) { public boolean isVirtualMachineUpgradable(VirtualMachine vm, ServiceOffering offering) {
boolean isMachineUpgradable = true; boolean isMachineUpgradable = true;
for(HostAllocator allocator : _hostAllocators) { for(HostAllocator allocator : _hostAllocators) {
isMachineUpgradable = allocator.isVirtualMachineUpgradable(vm, offering); isMachineUpgradable = allocator.isVirtualMachineUpgradable(vm, offering);
if(isMachineUpgradable) if(isMachineUpgradable)
@ -1628,7 +1627,7 @@ public class VirtualMachineManagerImpl extends ManagerBase implements VirtualMac
return new StopCommand(vmName); return new StopCommand(vmName);
} }
public Commands fullHostSync(final long hostId, StartupRoutingCommand startup) { public Commands fullHostSync(final long hostId, StartupRoutingCommand startup) {
Commands commands = new Commands(OnError.Continue); Commands commands = new Commands(OnError.Continue);
Map<Long, AgentVmInfo> infos = convertToInfos(startup); Map<Long, AgentVmInfo> infos = convertToInfos(startup);
@ -1637,7 +1636,7 @@ public class VirtualMachineManagerImpl extends ManagerBase implements VirtualMac
s_logger.debug("Found " + vms.size() + " VMs for host " + hostId); s_logger.debug("Found " + vms.size() + " VMs for host " + hostId);
for (VMInstanceVO vm : vms) { for (VMInstanceVO vm : vms) {
AgentVmInfo info = infos.remove(vm.getId()); AgentVmInfo info = infos.remove(vm.getId());
// sync VM Snapshots related transient states // sync VM Snapshots related transient states
List<VMSnapshotVO> vmSnapshotsInTrasientStates = _vmSnapshotDao.listByInstanceId(vm.getId(), VMSnapshot.State.Expunging,VMSnapshot.State.Reverting, VMSnapshot.State.Creating); List<VMSnapshotVO> vmSnapshotsInTrasientStates = _vmSnapshotDao.listByInstanceId(vm.getId(), VMSnapshot.State.Expunging,VMSnapshot.State.Reverting, VMSnapshot.State.Creating);
if(vmSnapshotsInTrasientStates.size() > 1){ if(vmSnapshotsInTrasientStates.size() > 1){
@ -1649,11 +1648,11 @@ public class VirtualMachineManagerImpl extends ManagerBase implements VirtualMac
s_logger.info("Successfully sync VM with transient snapshot: " + vm.getInstanceName()); s_logger.info("Successfully sync VM with transient snapshot: " + vm.getInstanceName());
} }
} }
VMInstanceVO castedVm = null; VMInstanceVO castedVm = null;
if (info == null) { if (info == null) {
info = new AgentVmInfo(vm.getInstanceName(), getVmGuru(vm), vm, State.Stopped); info = new AgentVmInfo(vm.getInstanceName(), getVmGuru(vm), vm, State.Stopped);
} }
castedVm = info.guru.findById(vm.getId()); castedVm = info.guru.findById(vm.getId());
HypervisorGuru hvGuru = _hvGuruMgr.getGuru(castedVm.getHypervisorType()); HypervisorGuru hvGuru = _hvGuruMgr.getGuru(castedVm.getHypervisorType());
@ -1767,7 +1766,7 @@ public class VirtualMachineManagerImpl extends ManagerBase implements VirtualMac
for (VMInstanceVO vm : set_vms) { for (VMInstanceVO vm : set_vms) {
AgentVmInfo info = infos.remove(vm.getId()); AgentVmInfo info = infos.remove(vm.getId());
VMInstanceVO castedVm = null; VMInstanceVO castedVm = null;
// sync VM Snapshots related transient states // sync VM Snapshots related transient states
List<VMSnapshotVO> vmSnapshotsInExpungingStates = _vmSnapshotDao.listByInstanceId(vm.getId(), VMSnapshot.State.Expunging, VMSnapshot.State.Creating,VMSnapshot.State.Reverting); List<VMSnapshotVO> vmSnapshotsInExpungingStates = _vmSnapshotDao.listByInstanceId(vm.getId(), VMSnapshot.State.Expunging, VMSnapshot.State.Creating,VMSnapshot.State.Reverting);
if(vmSnapshotsInExpungingStates.size() > 0){ if(vmSnapshotsInExpungingStates.size() > 0){
@ -1785,9 +1784,9 @@ public class VirtualMachineManagerImpl extends ManagerBase implements VirtualMac
s_logger.info("Successfully sync VM with transient snapshot: " + vm.getInstanceName()); s_logger.info("Successfully sync VM with transient snapshot: " + vm.getInstanceName());
} }
} }
if ((info == null && (vm.getState() == State.Running || vm.getState() == State.Starting )) if ((info == null && (vm.getState() == State.Running || vm.getState() == State.Starting ))
|| (info != null && (info.state == State.Running && vm.getState() == State.Starting))) || (info != null && (info.state == State.Running && vm.getState() == State.Starting)))
{ {
s_logger.info("Found vm " + vm.getInstanceName() + " in inconsistent state. " + vm.getState() + " on CS while " + (info == null ? "Stopped" : "Running") + " on agent"); s_logger.info("Found vm " + vm.getInstanceName() + " in inconsistent state. " + vm.getState() + " on CS while " + (info == null ? "Stopped" : "Running") + " on agent");
info = new AgentVmInfo(vm.getInstanceName(), getVmGuru(vm), vm, State.Stopped); info = new AgentVmInfo(vm.getInstanceName(), getVmGuru(vm), vm, State.Stopped);
@ -1925,7 +1924,7 @@ public class VirtualMachineManagerImpl extends ManagerBase implements VirtualMac
return map; return map;
} }
protected Map<Long, AgentVmInfo> convertToInfos(StartupRoutingCommand cmd) { protected Map<Long, AgentVmInfo> convertToInfos(StartupRoutingCommand cmd) {
final Map<String, VmState> states = cmd.getVmStates(); final Map<String, VmState> states = cmd.getVmStates();
final HashMap<Long, AgentVmInfo> map = new HashMap<Long, AgentVmInfo>(); final HashMap<Long, AgentVmInfo> map = new HashMap<Long, AgentVmInfo>();
if (states == null) { if (states == null) {
@ -1989,7 +1988,7 @@ public class VirtualMachineManagerImpl extends ManagerBase implements VirtualMac
* compareState does as its name suggests and compares the states between * compareState does as its name suggests and compares the states between
* management server and agent. It returns whether something should be * management server and agent. It returns whether something should be
* cleaned up * cleaned up
* *
*/ */
protected Command compareState(long hostId, VMInstanceVO vm, final AgentVmInfo info, final boolean fullSync, boolean trackExternalChange) { protected Command compareState(long hostId, VMInstanceVO vm, final AgentVmInfo info, final boolean fullSync, boolean trackExternalChange) {
State agentState = info.state; State agentState = info.state;
@ -2192,7 +2191,7 @@ public class VirtualMachineManagerImpl extends ManagerBase implements VirtualMac
List<NicVO> nics = _nicsDao.listByVmId(profile.getId()); List<NicVO> nics = _nicsDao.listByVmId(profile.getId());
for (NicVO nic : nics) { for (NicVO nic : nics) {
Network network = _networkModel.getNetwork(nic.getNetworkId()); Network network = _networkModel.getNetwork(nic.getNetworkId());
NicProfile nicProfile = new NicProfile(nic, network, nic.getBroadcastUri(), nic.getIsolationUri(), null, NicProfile nicProfile = new NicProfile(nic, network, nic.getBroadcastUri(), nic.getIsolationUri(), null,
_networkModel.isSecurityGroupSupportedInNetwork(network), _networkModel.getNetworkTag(profile.getHypervisorType(), network)); _networkModel.isSecurityGroupSupportedInNetwork(network), _networkModel.getNetworkTag(profile.getHypervisorType(), network));
profile.addNic(nicProfile); profile.addNic(nicProfile);
} }
@ -2319,7 +2318,7 @@ public class VirtualMachineManagerImpl extends ManagerBase implements VirtualMac
s_logger.fatal("The Cluster VM sync process failed for cluster id " + clusterId + " with ", e); s_logger.fatal("The Cluster VM sync process failed for cluster id " + clusterId + " with ", e);
} }
} }
else { // for others KVM and VMWare else { // for others KVM and VMWare
StartupRoutingCommand startup = (StartupRoutingCommand) cmd; StartupRoutingCommand startup = (StartupRoutingCommand) cmd;
Commands commands = fullHostSync(agentId, startup); Commands commands = fullHostSync(agentId, startup);
@ -2492,7 +2491,7 @@ public class VirtualMachineManagerImpl extends ManagerBase implements VirtualMac
} }
@Override @Override
public NicProfile addVmToNetwork(VirtualMachine vm, Network network, NicProfile requested) throws ConcurrentOperationException, public NicProfile addVmToNetwork(VirtualMachine vm, Network network, NicProfile requested) throws ConcurrentOperationException,
ResourceUnavailableException, InsufficientCapacityException { ResourceUnavailableException, InsufficientCapacityException {
s_logger.debug("Adding vm " + vm + " to network " + network + "; requested nic profile " + requested); s_logger.debug("Adding vm " + vm + " to network " + network + "; requested nic profile " + requested);
@ -2502,14 +2501,14 @@ public class VirtualMachineManagerImpl extends ManagerBase implements VirtualMac
} else { } else {
vmVO = _vmDao.findById(vm.getId()); vmVO = _vmDao.findById(vm.getId());
} }
ReservationContext context = new ReservationContextImpl(null, null, _accountMgr.getActiveUser(User.UID_SYSTEM), ReservationContext context = new ReservationContextImpl(null, null, _accountMgr.getActiveUser(User.UID_SYSTEM),
_accountMgr.getAccount(Account.ACCOUNT_ID_SYSTEM)); _accountMgr.getAccount(Account.ACCOUNT_ID_SYSTEM));
VirtualMachineProfileImpl<VMInstanceVO> vmProfile = new VirtualMachineProfileImpl<VMInstanceVO>(vmVO, null, VirtualMachineProfileImpl<VMInstanceVO> vmProfile = new VirtualMachineProfileImpl<VMInstanceVO>(vmVO, null,
null, null, null); null, null, null);
DataCenter dc = _configMgr.getZone(network.getDataCenterId()); DataCenter dc = _configMgr.getZone(network.getDataCenterId());
Host host = _hostDao.findById(vm.getHostId()); Host host = _hostDao.findById(vm.getHostId());
DeployDestination dest = new DeployDestination(dc, null, null, host); DeployDestination dest = new DeployDestination(dc, null, null, host);
//check vm state //check vm state
@ -2557,14 +2556,14 @@ public class VirtualMachineManagerImpl extends ManagerBase implements VirtualMac
public boolean removeNicFromVm(VirtualMachine vm, NicVO nic) throws ConcurrentOperationException, ResourceUnavailableException { public boolean removeNicFromVm(VirtualMachine vm, NicVO nic) throws ConcurrentOperationException, ResourceUnavailableException {
VMInstanceVO vmVO = _vmDao.findById(vm.getId()); VMInstanceVO vmVO = _vmDao.findById(vm.getId());
NetworkVO network = _networkDao.findById(nic.getNetworkId()); NetworkVO network = _networkDao.findById(nic.getNetworkId());
ReservationContext context = new ReservationContextImpl(null, null, _accountMgr.getActiveUser(User.UID_SYSTEM), ReservationContext context = new ReservationContextImpl(null, null, _accountMgr.getActiveUser(User.UID_SYSTEM),
_accountMgr.getAccount(Account.ACCOUNT_ID_SYSTEM)); _accountMgr.getAccount(Account.ACCOUNT_ID_SYSTEM));
VirtualMachineProfileImpl<VMInstanceVO> vmProfile = new VirtualMachineProfileImpl<VMInstanceVO>(vmVO, null, VirtualMachineProfileImpl<VMInstanceVO> vmProfile = new VirtualMachineProfileImpl<VMInstanceVO>(vmVO, null,
null, null, null); null, null, null);
DataCenter dc = _configMgr.getZone(network.getDataCenterId()); DataCenter dc = _configMgr.getZone(network.getDataCenterId());
Host host = _hostDao.findById(vm.getHostId()); Host host = _hostDao.findById(vm.getHostId());
DeployDestination dest = new DeployDestination(dc, null, null, host); DeployDestination dest = new DeployDestination(dc, null, null, host);
VirtualMachineGuru<VMInstanceVO> vmGuru = getVmGuru(vmVO); VirtualMachineGuru<VMInstanceVO> vmGuru = getVmGuru(vmVO);
HypervisorGuru hvGuru = _hvGuruMgr.getGuru(vmProfile.getVirtualMachine().getHypervisorType()); HypervisorGuru hvGuru = _hvGuruMgr.getGuru(vmProfile.getVirtualMachine().getHypervisorType());
@ -2576,9 +2575,9 @@ public class VirtualMachineManagerImpl extends ManagerBase implements VirtualMac
throw new CloudRuntimeException("Failed to remove nic from " + vm + " in " + network + ", nic is default."); throw new CloudRuntimeException("Failed to remove nic from " + vm + " in " + network + ", nic is default.");
} }
NicProfile nicProfile = new NicProfile(nic, network, nic.getBroadcastUri(), nic.getIsolationUri(), NicProfile nicProfile = new NicProfile(nic, network, nic.getBroadcastUri(), nic.getIsolationUri(),
_networkModel.getNetworkRate(network.getId(), vm.getId()), _networkModel.getNetworkRate(network.getId(), vm.getId()),
_networkModel.isSecurityGroupSupportedInNetwork(network), _networkModel.isSecurityGroupSupportedInNetwork(network),
_networkModel.getNetworkTag(vmProfile.getVirtualMachine().getHypervisorType(), network)); _networkModel.getNetworkTag(vmProfile.getVirtualMachine().getHypervisorType(), network));
//1) Unplug the nic //1) Unplug the nic
@ -2611,14 +2610,14 @@ public class VirtualMachineManagerImpl extends ManagerBase implements VirtualMac
@Override @Override
public boolean removeVmFromNetwork(VirtualMachine vm, Network network, URI broadcastUri) throws ConcurrentOperationException, ResourceUnavailableException { public boolean removeVmFromNetwork(VirtualMachine vm, Network network, URI broadcastUri) throws ConcurrentOperationException, ResourceUnavailableException {
VMInstanceVO vmVO = _vmDao.findById(vm.getId()); VMInstanceVO vmVO = _vmDao.findById(vm.getId());
ReservationContext context = new ReservationContextImpl(null, null, _accountMgr.getActiveUser(User.UID_SYSTEM), ReservationContext context = new ReservationContextImpl(null, null, _accountMgr.getActiveUser(User.UID_SYSTEM),
_accountMgr.getAccount(Account.ACCOUNT_ID_SYSTEM)); _accountMgr.getAccount(Account.ACCOUNT_ID_SYSTEM));
VirtualMachineProfileImpl<VMInstanceVO> vmProfile = new VirtualMachineProfileImpl<VMInstanceVO>(vmVO, null, VirtualMachineProfileImpl<VMInstanceVO> vmProfile = new VirtualMachineProfileImpl<VMInstanceVO>(vmVO, null,
null, null, null); null, null, null);
DataCenter dc = _configMgr.getZone(network.getDataCenterId()); DataCenter dc = _configMgr.getZone(network.getDataCenterId());
Host host = _hostDao.findById(vm.getHostId()); Host host = _hostDao.findById(vm.getHostId());
DeployDestination dest = new DeployDestination(dc, null, null, host); DeployDestination dest = new DeployDestination(dc, null, null, host);
VirtualMachineGuru<VMInstanceVO> vmGuru = getVmGuru(vmVO); VirtualMachineGuru<VMInstanceVO> vmGuru = getVmGuru(vmVO);
HypervisorGuru hvGuru = _hvGuruMgr.getGuru(vmProfile.getVirtualMachine().getHypervisorType()); HypervisorGuru hvGuru = _hvGuruMgr.getGuru(vmProfile.getVirtualMachine().getHypervisorType());
@ -2643,9 +2642,9 @@ public class VirtualMachineManagerImpl extends ManagerBase implements VirtualMac
throw new CloudRuntimeException("Failed to remove nic from " + vm + " in " + network + ", nic is default."); throw new CloudRuntimeException("Failed to remove nic from " + vm + " in " + network + ", nic is default.");
} }
NicProfile nicProfile = new NicProfile(nic, network, nic.getBroadcastUri(), nic.getIsolationUri(), NicProfile nicProfile = new NicProfile(nic, network, nic.getBroadcastUri(), nic.getIsolationUri(),
_networkModel.getNetworkRate(network.getId(), vm.getId()), _networkModel.getNetworkRate(network.getId(), vm.getId()),
_networkModel.isSecurityGroupSupportedInNetwork(network), _networkModel.isSecurityGroupSupportedInNetwork(network),
_networkModel.getNetworkTag(vmProfile.getVirtualMachine().getHypervisorType(), network)); _networkModel.getNetworkTag(vmProfile.getVirtualMachine().getHypervisorType(), network));
//1) Unplug the nic //1) Unplug the nic

View File

@ -1,6 +1,5 @@
package org.apache.cloudstack.affinity; package org.apache.cloudstack.affinity;
import java.util.ArrayList;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
@ -13,36 +12,34 @@ import org.apache.cloudstack.affinity.dao.AffinityGroupVMMapDao;
import org.apache.log4j.Logger; import org.apache.log4j.Logger;
import com.cloud.api.query.vo.SecurityGroupJoinVO;
import com.cloud.event.ActionEvent; import com.cloud.event.ActionEvent;
import com.cloud.event.EventTypes; import com.cloud.event.EventTypes;
import com.cloud.exception.InvalidParameterValueException; import com.cloud.exception.InvalidParameterValueException;
import com.cloud.exception.ResourceInUseException; import com.cloud.exception.ResourceInUseException;
import com.cloud.network.PhysicalNetwork; import com.cloud.network.security.SecurityGroup;
import com.cloud.network.dao.PhysicalNetworkVO;
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.Account;
import com.cloud.user.AccountManager; import com.cloud.user.AccountManager;
import com.cloud.user.UserContext; import com.cloud.user.UserContext;
import com.cloud.uservm.UserVm;
import com.cloud.utils.Pair; import com.cloud.utils.Pair;
import com.cloud.utils.component.Manager; import com.cloud.utils.component.Manager;
import com.cloud.utils.component.ManagerBase; import com.cloud.utils.component.ManagerBase;
import com.cloud.utils.db.DB; import com.cloud.utils.db.DB;
import com.cloud.utils.db.Filter; import com.cloud.utils.db.Filter;
import com.cloud.utils.db.JoinBuilder.JoinType;
import com.cloud.utils.db.JoinBuilder; import com.cloud.utils.db.JoinBuilder;
import com.cloud.utils.db.SearchBuilder; import com.cloud.utils.db.SearchBuilder;
import com.cloud.utils.db.SearchCriteria; import com.cloud.utils.db.SearchCriteria;
import com.cloud.utils.db.Transaction; import com.cloud.utils.db.Transaction;
import com.cloud.utils.fsm.StateListener;
import com.cloud.vm.UserVmVO; import com.cloud.vm.UserVmVO;
import com.cloud.vm.VMInstanceVO; import com.cloud.vm.VirtualMachine;
import com.cloud.vm.VirtualMachine.Event;
import com.cloud.vm.VirtualMachine.State;
import com.cloud.vm.dao.UserVmDao; import com.cloud.vm.dao.UserVmDao;
@Local(value = { AffinityGroupService.class }) @Local(value = { AffinityGroupService.class })
public class AffinityGroupServiceImpl extends ManagerBase implements AffinityGroupService, Manager { public class AffinityGroupServiceImpl extends ManagerBase implements AffinityGroupService, Manager,
StateListener<State, VirtualMachine.Event, VirtualMachine> {
public static final Logger s_logger = Logger.getLogger(AffinityGroupServiceImpl.class); public static final Logger s_logger = Logger.getLogger(AffinityGroupServiceImpl.class);
private String _name; private String _name;
@ -221,4 +218,56 @@ public class AffinityGroupServiceImpl extends ManagerBase implements AffinityGro
return _affinityGroupDao.findById(groupId); return _affinityGroupDao.findById(groupId);
} }
@Override
public boolean preStateTransitionEvent(State oldState, Event event, State newState, VirtualMachine vo,
boolean status, Object opaque) {
return true;
}
@Override
public boolean postStateTransitionEvent(State oldState, Event event, State newState, VirtualMachine vo,
boolean status, Object opaque) {
if (!status) {
return false;
}
if ((newState == State.Expunging)) {
// cleanup all affinity groups associated to the Expunged VM
SearchCriteria<AffinityGroupVMMapVO> sc = _affinityGroupVMMapDao.createSearchCriteria();
sc.addAnd("instanceId", SearchCriteria.Op.EQ, vo.getId());
_affinityGroupVMMapDao.expunge(sc);
}
return true;
}
@Override
public UserVm updateVMAffinityGroups(Long vmId, List<Long> affinityGroupIds) {
// Verify input parameters
UserVmVO vmInstance = _userVmDao.findById(vmId);
if (vmInstance == null) {
throw new InvalidParameterValueException("unable to find a virtual machine with id " + vmId);
}
// Check that the VM is stopped
if (!vmInstance.getState().equals(State.Stopped)) {
s_logger.warn("Unable to update affinity groups of the virtual machine " + vmInstance.toString()
+ " in state " + vmInstance.getState());
throw new InvalidParameterValueException("Unable update affinity groups of the virtual machine "
+ vmInstance.toString() + " " + "in state " + vmInstance.getState()
+ "; make sure the virtual machine is stopped and not in an error state before updating.");
}
// check that the affinity groups exist
for (Long affinityGroupId : affinityGroupIds) {
AffinityGroupVO ag = _affinityGroupDao.findById(affinityGroupId);
if (ag == null) {
throw new InvalidParameterValueException("Unable to find affinity group by id " + affinityGroupId);
}
}
_affinityGroupVMMapDao.updateMap(vmId, affinityGroupIds);
// APIResponseHelper will pull out the updated affinitygroups.
return vmInstance;
}
} }

View File

@ -0,0 +1,66 @@
package org.apache.cloudstack.affinity;
import java.util.List;
import javax.ejb.Local;
import javax.inject.Inject;
import org.apache.cloudstack.affinity.dao.AffinityGroupDao;
import org.apache.cloudstack.affinity.dao.AffinityGroupVMMapDao;
import org.apache.log4j.Logger;
import com.cloud.deploy.DeploymentPlan;
import com.cloud.deploy.DeploymentPlanner.ExcludeList;
import com.cloud.exception.AffinityConflictException;
import com.cloud.utils.component.AdapterBase;
import com.cloud.vm.VMInstanceVO;
import com.cloud.vm.VirtualMachine;
import com.cloud.vm.VirtualMachineProfile;
import com.cloud.vm.dao.UserVmDao;
import com.cloud.vm.dao.VMInstanceDao;
@Local(value = AffinityGroupProcessor.class)
public class HostAntiAffinityProcessor extends AdapterBase implements AffinityGroupProcessor {
private static final Logger s_logger = Logger.getLogger(HostAntiAffinityProcessor.class);
@Inject
protected UserVmDao _vmDao;
@Inject
protected VMInstanceDao _vmInstanceDao;
@Inject
protected AffinityGroupDao _affinityGroupDao;
@Inject
protected AffinityGroupVMMapDao _affinityGroupVMMapDao;
@Override
public void process(VirtualMachineProfile<? extends VirtualMachine> vmProfile, DeploymentPlan plan,
ExcludeList avoid)
throws AffinityConflictException {
VirtualMachine vm = vmProfile.getVirtualMachine();
AffinityGroupVMMapVO vmGroupMapping = _affinityGroupVMMapDao.findByVmIdType(vm.getId(), getType());
if (vmGroupMapping != null) {
AffinityGroupVO group = _affinityGroupDao.findById(vmGroupMapping.getAffinityGroupId());
if (s_logger.isDebugEnabled()) {
s_logger.debug("Processing affinity group " + group.getName() + " for VM Id: " + vm.getId());
}
List<Long> groupVMIds = _affinityGroupVMMapDao.listVmIdsByAffinityGroup(group.getId());
for (Long groupVMId : groupVMIds) {
VMInstanceVO groupVM = _vmInstanceDao.findById(groupVMId);
if (groupVM != null && !groupVM.isRemoved() && groupVM.getHostId() != null) {
avoid.addHost(groupVM.getHostId());
}
}
}
}
@Override
public String getType() {
return "HostAntiAffinity";
}
}

View File

@ -40,4 +40,8 @@ public interface AffinityGroupVMMapDao extends GenericDao<AffinityGroupVMMapVO,
long countAffinityGroupsForVm(long instanceId); long countAffinityGroupsForVm(long instanceId);
int deleteVM(long instanceId); int deleteVM(long instanceId);
AffinityGroupVMMapVO findByVmIdType(long instanceId, String type);
void updateMap(Long vmId, List<Long> affinityGroupIds);
} }

View File

@ -19,17 +19,22 @@ package org.apache.cloudstack.affinity.dao;
import java.util.List; import java.util.List;
import javax.ejb.Local; import javax.ejb.Local;
import javax.inject.Inject;
import org.apache.cloudstack.affinity.AffinityGroupVMMapVO; import org.apache.cloudstack.affinity.AffinityGroupVMMapVO;
import org.apache.cloudstack.affinity.AffinityGroupVO;
import org.springframework.stereotype.Component; import org.springframework.stereotype.Component;
import com.cloud.host.HostTagVO;
import com.cloud.utils.Pair; import com.cloud.utils.Pair;
import com.cloud.utils.db.Filter; import com.cloud.utils.db.Filter;
import com.cloud.utils.db.GenericDaoBase; import com.cloud.utils.db.GenericDaoBase;
import com.cloud.utils.db.GenericSearchBuilder; import com.cloud.utils.db.GenericSearchBuilder;
import com.cloud.utils.db.JoinBuilder.JoinType;
import com.cloud.utils.db.SearchBuilder; import com.cloud.utils.db.SearchBuilder;
import com.cloud.utils.db.SearchCriteria; import com.cloud.utils.db.SearchCriteria;
import com.cloud.utils.db.SearchCriteria.Func; import com.cloud.utils.db.SearchCriteria.Func;
import com.cloud.utils.db.Transaction;
@Component @Component
@Local(value = { AffinityGroupVMMapDao.class }) @Local(value = { AffinityGroupVMMapDao.class })
@ -40,6 +45,10 @@ public class AffinityGroupVMMapDaoImpl extends GenericDaoBase<AffinityGroupVMMap
protected GenericSearchBuilder<AffinityGroupVMMapVO, Long> CountSGForVm; protected GenericSearchBuilder<AffinityGroupVMMapVO, Long> CountSGForVm;
private GenericSearchBuilder<AffinityGroupVMMapVO, Long> ListVmIdByAffinityGroup; private GenericSearchBuilder<AffinityGroupVMMapVO, Long> ListVmIdByAffinityGroup;
private SearchBuilder<AffinityGroupVMMapVO> ListByAffinityGroup; private SearchBuilder<AffinityGroupVMMapVO> ListByAffinityGroup;
private SearchBuilder<AffinityGroupVMMapVO> ListByVmIdType;
@Inject
protected AffinityGroupDao _affinityGroupDao;
protected AffinityGroupVMMapDaoImpl() { protected AffinityGroupVMMapDaoImpl() {
ListVmIdByAffinityGroup = createSearchBuilder(Long.class); ListVmIdByAffinityGroup = createSearchBuilder(Long.class);
@ -62,6 +71,14 @@ public class AffinityGroupVMMapDaoImpl extends GenericDaoBase<AffinityGroupVMMap
ListByVmIdGroupId.and("affinityGroupId", ListByVmIdGroupId.entity().getAffinityGroupId(), SearchCriteria.Op.EQ); ListByVmIdGroupId.and("affinityGroupId", ListByVmIdGroupId.entity().getAffinityGroupId(), SearchCriteria.Op.EQ);
ListByVmIdGroupId.done(); ListByVmIdGroupId.done();
ListByVmIdType = createSearchBuilder();
ListByVmIdType.and("instanceId", ListByVmIdType.entity().getInstanceId(), SearchCriteria.Op.EQ);
SearchBuilder<AffinityGroupVO> groupSearch = _affinityGroupDao.createSearchBuilder();
groupSearch.and("type", groupSearch.entity().getType(), SearchCriteria.Op.EQ);
ListByVmIdType.join("groupSearch", groupSearch, ListByVmIdType.entity().getAffinityGroupId(), groupSearch
.entity().getId(), JoinType.INNER);
ListByVmIdType.done();
CountSGForVm = createSearchBuilder(Long.class); CountSGForVm = createSearchBuilder(Long.class);
CountSGForVm.select(null, Func.COUNT, null); CountSGForVm.select(null, Func.COUNT, null);
CountSGForVm.and("vmId", CountSGForVm.entity().getInstanceId(), SearchCriteria.Op.EQ); CountSGForVm.and("vmId", CountSGForVm.entity().getInstanceId(), SearchCriteria.Op.EQ);
@ -117,4 +134,30 @@ public class AffinityGroupVMMapDaoImpl extends GenericDaoBase<AffinityGroupVMMap
sc.setParameters("vmId", instanceId); sc.setParameters("vmId", instanceId);
return customSearch(sc, null).get(0); return customSearch(sc, null).get(0);
} }
@Override
public AffinityGroupVMMapVO findByVmIdType(long instanceId, String type) {
SearchCriteria<AffinityGroupVMMapVO> sc = ListByVmIdType.create();
sc.setParameters("instanceId", instanceId);
sc.setJoinParameters("groupSearch", "type", type);
return customSearch(sc, null).get(0);
}
@Override
public void updateMap(Long vmId, List<Long> affinityGroupIds) {
Transaction txn = Transaction.currentTxn();
txn.start();
SearchCriteria<AffinityGroupVMMapVO> sc = createSearchCriteria();
sc.addAnd("instanceId", SearchCriteria.Op.EQ, vmId);
expunge(sc);
for (Long groupId : affinityGroupIds) {
AffinityGroupVMMapVO vo = new AffinityGroupVMMapVO(groupId, vmId);
persist(vo);
}
txn.commit();
}
} }

View File

@ -253,13 +253,13 @@ public class MockUserVmManagerImpl extends ManagerBase implements UserVmManager,
// TODO Auto-generated method stub // TODO Auto-generated method stub
return null; return null;
} }
@Override @Override
public UserVm removeNicFromVirtualMachine(RemoveNicFromVMCmd cmd) throws InvalidParameterValueException, PermissionDeniedException, CloudRuntimeException { public UserVm removeNicFromVirtualMachine(RemoveNicFromVMCmd cmd) throws InvalidParameterValueException, PermissionDeniedException, CloudRuntimeException {
// TODO Auto-generated method stub // TODO Auto-generated method stub
return null; return null;
} }
@Override @Override
public UserVm updateDefaultNicForVirtualMachine(UpdateDefaultNicForVMCmd cmd) throws InvalidParameterValueException, CloudRuntimeException { public UserVm updateDefaultNicForVirtualMachine(UpdateDefaultNicForVMCmd cmd) throws InvalidParameterValueException, CloudRuntimeException {
// TODO Auto-generated method stub // TODO Auto-generated method stub
@ -330,7 +330,9 @@ public class MockUserVmManagerImpl extends ManagerBase implements UserVmManager,
@Override @Override
public UserVm createBasicSecurityGroupVirtualMachine(DataCenter zone, ServiceOffering serviceOffering, VirtualMachineTemplate template, List<Long> securityGroupIdList, Account owner, public UserVm createBasicSecurityGroupVirtualMachine(DataCenter zone, ServiceOffering serviceOffering, VirtualMachineTemplate template, List<Long> securityGroupIdList, Account owner,
String hostName, String displayName, Long diskOfferingId, Long diskSize, String group, HypervisorType hypervisor, String userData, String sshKeyPair, Map<Long, IpAddresses> requestedIps, String hostName, String displayName, Long diskOfferingId, Long diskSize, String group, HypervisorType hypervisor, String userData, String sshKeyPair, Map<Long, IpAddresses> requestedIps,
IpAddresses defaultIp, String keyboard) throws InsufficientCapacityException, ConcurrentOperationException, ResourceUnavailableException, StorageUnavailableException, IpAddresses defaultIp,
String keyboard, List<Long> affinityGroupIdList) throws InsufficientCapacityException,
ConcurrentOperationException, ResourceUnavailableException, StorageUnavailableException,
ResourceAllocationException { ResourceAllocationException {
// TODO Auto-generated method stub // TODO Auto-generated method stub
return null; return null;
@ -339,7 +341,9 @@ public class MockUserVmManagerImpl extends ManagerBase implements UserVmManager,
@Override @Override
public UserVm createAdvancedSecurityGroupVirtualMachine(DataCenter zone, ServiceOffering serviceOffering, VirtualMachineTemplate template, List<Long> networkIdList, public UserVm createAdvancedSecurityGroupVirtualMachine(DataCenter zone, ServiceOffering serviceOffering, VirtualMachineTemplate template, List<Long> networkIdList,
List<Long> securityGroupIdList, Account owner, String hostName, String displayName, Long diskOfferingId, Long diskSize, String group, HypervisorType hypervisor, String userData, List<Long> securityGroupIdList, Account owner, String hostName, String displayName, Long diskOfferingId, Long diskSize, String group, HypervisorType hypervisor, String userData,
String sshKeyPair, Map<Long, IpAddresses> requestedIps, IpAddresses defaultIps, String keyboard) throws InsufficientCapacityException, ConcurrentOperationException, ResourceUnavailableException, String sshKeyPair, Map<Long, IpAddresses> requestedIps,
IpAddresses defaultIps, String keyboard, List<Long> affinityGroupIdList)
throws InsufficientCapacityException, ConcurrentOperationException, ResourceUnavailableException,
StorageUnavailableException, ResourceAllocationException { StorageUnavailableException, ResourceAllocationException {
// TODO Auto-generated method stub // TODO Auto-generated method stub
return null; return null;
@ -348,7 +352,9 @@ public class MockUserVmManagerImpl extends ManagerBase implements UserVmManager,
@Override @Override
public UserVm createAdvancedVirtualMachine(DataCenter zone, ServiceOffering serviceOffering, VirtualMachineTemplate template, List<Long> networkIdList, Account owner, String hostName, public UserVm createAdvancedVirtualMachine(DataCenter zone, ServiceOffering serviceOffering, VirtualMachineTemplate template, List<Long> networkIdList, Account owner, String hostName,
String displayName, Long diskOfferingId, Long diskSize, String group, HypervisorType hypervisor, String userData, String sshKeyPair, Map<Long, IpAddresses> requestedIps, IpAddresses defaultIps, String displayName, Long diskOfferingId, Long diskSize, String group, HypervisorType hypervisor, String userData, String sshKeyPair, Map<Long, IpAddresses> requestedIps, IpAddresses defaultIps,
String keyboard) throws InsufficientCapacityException, ConcurrentOperationException, ResourceUnavailableException, StorageUnavailableException, ResourceAllocationException { String keyboard, List<Long> affinityGroupIdList) throws InsufficientCapacityException,
ConcurrentOperationException, ResourceUnavailableException, StorageUnavailableException,
ResourceAllocationException {
// TODO Auto-generated method stub // TODO Auto-generated method stub
return null; return null;
} }

View File

@ -61,4 +61,5 @@ public interface SerialVersionUID {
public static final long CloudExecutionException = Base | 0x27; public static final long CloudExecutionException = Base | 0x27;
public static final long CallFailedException = Base | 0x28; public static final long CallFailedException = Base | 0x28;
public static final long UnableDeleteHostException = Base | 0x29; public static final long UnableDeleteHostException = Base | 0x29;
public static final long AffinityConflictException = Base | 0x2a;
} }