Merge branch 'master' into internallb1

Conflicts:
	api/src/com/cloud/async/AsyncJob.java
	api/src/org/apache/cloudstack/api/ApiConstants.java
	api/src/org/apache/cloudstack/api/BaseCmd.java
	api/src/org/apache/cloudstack/api/ResponseGenerator.java
	client/tomcatconf/commands.properties.in
	server/src/com/cloud/api/ApiDBUtils.java
	server/src/com/cloud/api/ApiResponseHelper.java
	server/src/com/cloud/server/ManagementServerImpl.java
	setup/db/db/schema-410to420.sql
This commit is contained in:
Alena Prokharchyk 2013-04-11 14:09:31 -07:00
commit 3795048fcc
79 changed files with 4808 additions and 387 deletions

View File

@ -50,7 +50,8 @@ public interface AsyncJob extends Identity, InternalIdentity {
AutoScaleVmProfile,
AutoScaleVmGroup,
GlobalLoadBalancerRule,
LoadBalancerRule
LoadBalancerRule,
AffinityGroup
}
long getUserId();

View File

@ -348,7 +348,7 @@ public class EventTypes {
// tag related events
public static final String EVENT_TAGS_CREATE = "CREATE_TAGS";
public static final String EVENT_TAGS_DELETE = "DELETE_TAGS";
// vm snapshot events
public static final String EVENT_VM_SNAPSHOT_CREATE = "VMSNAPSHOT.CREATE";
public static final String EVENT_VM_SNAPSHOT_DELETE = "VMSNAPSHOT.DELETE";
@ -382,6 +382,12 @@ public class EventTypes {
public static final String EVENT_BAREMETAL_PXE_SERVER_ADD = "PHYSICAL.PXE.ADD";
public static final String EVENT_BAREMETAL_PXE_SERVER_DELETE = "PHYSICAL.PXE.DELETE";
public static final String EVENT_AFFINITY_GROUP_CREATE = "AG.CREATE";
public static final String EVENT_AFFINITY_GROUP_DELETE = "AG.DELETE";
public static final String EVENT_AFFINITY_GROUP_ASSIGN = "AG.ASSIGN";
public static final String EVENT_AFFINITY_GROUP_REMOVE = "AG.REMOVE";
public static final String EVENT_VM_AFFINITY_GROUP_UPDATE = "VM.AG.UPDATE";
static {
// TODO: need a way to force author adding event types to declare the entity details as well, with out braking

View File

@ -0,0 +1,34 @@
// 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 com.cloud.exception;
import com.cloud.utils.SerialVersionUID;
import com.cloud.utils.exception.CloudRuntimeException;
public class AffinityConflictException extends CloudRuntimeException {
private static final long serialVersionUID = SerialVersionUID.AffinityConflictException;
public AffinityConflictException(String message) {
super(message);
}
public AffinityConflictException(String message, Throwable th) {
super(message, th);
}
}

View File

@ -123,7 +123,7 @@ public interface ManagementService {
/**
* Searches for servers by the specified search criteria Can search by: "name", "type", "state", "dataCenterId",
* "podId"
*
*
* @param cmd
* @return List of Hosts
*/
@ -407,4 +407,6 @@ public interface ManagementService {
*/
List<? extends Capacity> listTopConsumedResources(ListCapacityCmd cmd);
List<String> listDeploymentPlanners();
}

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.vmgroup.CreateVMGroupCmd;
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.exception.ConcurrentOperationException;
import com.cloud.exception.InsufficientCapacityException;
@ -42,7 +39,6 @@ import com.cloud.hypervisor.Hypervisor.HypervisorType;
import com.cloud.network.Network.IpAddresses;
import com.cloud.offering.ServiceOffering;
import com.cloud.storage.StoragePool;
import com.cloud.storage.Volume;
import com.cloud.template.VirtualMachineTemplate;
import com.cloud.user.Account;
import com.cloud.uservm.UserVm;
@ -104,14 +100,14 @@ public interface UserVmService {
* @return the vm object if successful, null otherwise
*/
UserVm addNicToVirtualMachine(AddNicToVMCmd cmd);
/**
* Removes a NIC on the given network from the virtual machine
* @param cmd the command object that defines the vm and the given network
* @return the vm object if successful, null otherwise
*/
UserVm removeNicFromVirtualMachine(RemoveNicFromVMCmd cmd);
/**
* Updates default Nic to the given network for given virtual machine
* @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
* - availability zone for the virtual machine
@ -132,61 +129,69 @@ public interface UserVmService {
* @param template
* - the template for the virtual machine
* @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
* - host name for the virtual machine
* @param displayName
* - an optional user generated name for the virtual machine
* @param diskOfferingId
* - the ID of the disk offering for the virtual machine. If the template is of ISO format, the
* diskOfferingId is
* for the root disk volume. Otherwise this parameter is used to indicate the offering for the data disk
* volume.
* If the templateId parameter passed is from a Template object, the diskOfferingId refers to a DATA Disk
* Volume
* created. If the templateId parameter passed is from an ISO object, the diskOfferingId refers to a ROOT
* Disk
* Volume created
* - the ID of the disk offering for the virtual machine. If the
* template is of ISO format, the diskOfferingId is for the root
* disk volume. Otherwise this parameter is used to indicate the
* offering for the data disk volume. If the templateId parameter
* passed is from a Template object, the diskOfferingId refers to
* a DATA Disk Volume created. If the templateId parameter passed
* is from an ISO object, the diskOfferingId refers to a ROOT
* Disk Volume created
* @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
* - an optional group for the virtual machine
* @param hypervisor
* - the hypervisor on which to deploy the virtual machine
* @param userData
* - an optional binary data that can be sent to the virtual machine upon a successful deployment. This
* binary
* data must be base64 encoded before adding it to the request. Currently only HTTP GET is supported.
* Using HTTP
* GET (via querystring), you can send up to 2KB of data after base64 encoding
* - an optional binary data that can be sent to the virtual
* machine upon a successful deployment. This binary data must be
* base64 encoded before adding it to the request. Currently only
* HTTP GET is supported. Using HTTP GET (via querystring), you
* can send up to 2KB of data after base64 encoding
* @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
* TODO
* @param defaultIp
* TODO
* @param affinityGroupIdList
* @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
* - an optional domainId for the virtual machine. If the account parameter is used, domainId must also
* be used
* - an optional domainId for the virtual machine. If the account
* parameter is used, domainId must also be used
* @return UserVm object if successful.
*
* @throws InsufficientCapacityException
* if there is insufficient capacity to deploy the VM.
* @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
* 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
*/
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;
/**
* Creates a User VM in Advanced Zone (Security Group feature is enabled) in the database and returns the VM to the
* caller.
* Creates a User VM in Advanced Zone (Security Group feature is enabled) in
* the database and returns the VM to the caller.
*
* @param zone
* - availability zone for the virtual machine
@ -197,63 +202,69 @@ public interface UserVmService {
* @param networkIdList
* - list of network ids used by virtual machine
* @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
* - host name for the virtual machine
* @param displayName
* - an optional user generated name for the virtual machine
* @param diskOfferingId
* - the ID of the disk offering for the virtual machine. If the template is of ISO format, the
* diskOfferingId is
* for the root disk volume. Otherwise this parameter is used to indicate the offering for the data disk
* volume.
* If the templateId parameter passed is from a Template object, the diskOfferingId refers to a DATA Disk
* Volume
* created. If the templateId parameter passed is from an ISO object, the diskOfferingId refers to a ROOT
* Disk
* Volume created
* - the ID of the disk offering for the virtual machine. If the
* template is of ISO format, the diskOfferingId is for the root
* disk volume. Otherwise this parameter is used to indicate the
* offering for the data disk volume. If the templateId parameter
* passed is from a Template object, the diskOfferingId refers to
* a DATA Disk Volume created. If the templateId parameter passed
* is from an ISO object, the diskOfferingId refers to a ROOT
* Disk Volume created
* @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
* - an optional group for the virtual machine
* @param hypervisor
* - the hypervisor on which to deploy the virtual machine
* @param userData
* - an optional binary data that can be sent to the virtual machine upon a successful deployment. This
* binary
* data must be base64 encoded before adding it to the request. Currently only HTTP GET is supported.
* Using HTTP
* GET (via querystring), you can send up to 2KB of data after base64 encoding
* - an optional binary data that can be sent to the virtual
* machine upon a successful deployment. This binary data must be
* base64 encoded before adding it to the request. Currently only
* HTTP GET is supported. Using HTTP GET (via querystring), you
* can send up to 2KB of data after base64 encoding
* @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
* TODO
* @param defaultIps
* TODO
* @param affinityGroupIdList
* @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
* - an optional domainId for the virtual machine. If the account parameter is used, domainId must also
* be used
* - an optional domainId for the virtual machine. If the account
* parameter is used, domainId must also be used
* @return UserVm object if successful.
*
* @throws InsufficientCapacityException
* if there is insufficient capacity to deploy the VM.
* @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
* 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
*/
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,
IpAddresses defaultIps, String keyboard)
IpAddresses defaultIps, String keyboard, List<Long> affinityGroupIdList)
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
* caller.
*
* Creates a User VM in Advanced Zone (Security Group feature is disabled)
* in the database and returns the VM to the caller.
*
* @param zone
* - availability zone for the virtual machine
* @param serviceOffering
@ -267,49 +278,57 @@ public interface UserVmService {
* @param displayName
* - an optional user generated name for the virtual machine
* @param diskOfferingId
* - the ID of the disk offering for the virtual machine. If the template is of ISO format, the
* diskOfferingId is
* for the root disk volume. Otherwise this parameter is used to indicate the offering for the data disk
* volume.
* If the templateId parameter passed is from a Template object, the diskOfferingId refers to a DATA Disk
* Volume
* created. If the templateId parameter passed is from an ISO object, the diskOfferingId refers to a ROOT
* Disk
* Volume created
* - the ID of the disk offering for the virtual machine. If the
* template is of ISO format, the diskOfferingId is for the root
* disk volume. Otherwise this parameter is used to indicate the
* offering for the data disk volume. If the templateId parameter
* passed is from a Template object, the diskOfferingId refers to
* a DATA Disk Volume created. If the templateId parameter passed
* is from an ISO object, the diskOfferingId refers to a ROOT
* Disk Volume created
* @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
* - an optional group for the virtual machine
* @param hypervisor
* - the hypervisor on which to deploy the virtual machine
* @param userData
* - an optional binary data that can be sent to the virtual machine upon a successful deployment. This
* binary
* data must be base64 encoded before adding it to the request. Currently only HTTP GET is supported.
* Using HTTP
* GET (via querystring), you can send up to 2KB of data after base64 encoding
* - an optional binary data that can be sent to the virtual
* machine upon a successful deployment. This binary data must be
* base64 encoded before adding it to the request. Currently only
* HTTP GET is supported. Using HTTP GET (via querystring), you
* can send up to 2KB of data after base64 encoding
* @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
* TODO
* @param defaultIps TODO
* @param defaultIps
* TODO
* @param affinityGroupIdList
* @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
* - an optional domainId for the virtual machine. If the account parameter is used, domainId must also
* be used
* - an optional domainId for the virtual machine. If the account
* parameter is used, domainId must also be used
* @return UserVm object if successful.
*
*
* @throws InsufficientCapacityException
* if there is insufficient capacity to deploy the VM.
* @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
* 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
*/
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;
/**

View File

@ -0,0 +1,31 @@
// 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.affinity;
import org.apache.cloudstack.acl.ControlledEntity;
import org.apache.cloudstack.api.Identity;
import org.apache.cloudstack.api.InternalIdentity;
public interface AffinityGroup extends ControlledEntity, InternalIdentity, Identity {
String getName();
String getDescription();
String getType();
}

View File

@ -0,0 +1,49 @@
// 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.affinity;
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 AffinityGroupProcessor 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;
/**
* getType() should return the affinity/anti-affinity group being
* implemented
*
* @return String Affinity/Anti-affinity type
*/
String getType();
}

View File

@ -0,0 +1,155 @@
// 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.affinity;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Set;
import org.apache.cloudstack.api.ApiConstants;
import org.apache.cloudstack.api.BaseResponse;
import org.apache.cloudstack.api.EntityReference;
import org.apache.cloudstack.api.response.ControlledEntityResponse;
import org.apache.cloudstack.api.response.ControlledViewEntityResponse;
import org.apache.cloudstack.api.response.UserVmResponse;
import com.cloud.network.security.SecurityGroup;
import com.cloud.serializer.Param;
import com.google.gson.annotations.SerializedName;
@SuppressWarnings("unused")
@EntityReference(value = AffinityGroup.class)
public class AffinityGroupResponse extends BaseResponse implements ControlledViewEntityResponse {
@SerializedName(ApiConstants.ID) @Param(description="the ID of the affinity group")
private String id;
@SerializedName(ApiConstants.NAME) @Param(description="the name of the affinity group")
private String name;
@SerializedName(ApiConstants.DESCRIPTION) @Param(description="the description of the affinity group")
private String description;
@SerializedName(ApiConstants.ACCOUNT) @Param(description="the account owning the affinity group")
private String accountName;
@SerializedName(ApiConstants.DOMAIN_ID) @Param(description="the domain ID of the affinity group")
private String domainId;
@SerializedName(ApiConstants.DOMAIN) @Param(description="the domain name of the affinity group")
private String domainName;
@SerializedName(ApiConstants.TYPE)
@Param(description = "the type of the affinity group")
private String type;
@SerializedName("virtualmachineIds")
@Param(description = "virtual machine Ids associated with this affinity group ")
private List<String> vmIdList;
public AffinityGroupResponse() {
this.vmIdList = new ArrayList<String>();
}
@Override
public String getObjectId() {
return this.getId();
}
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public void setName(String name) {
this.name = name;
}
public void setDescription(String description) {
this.description = description;
}
public void setAccountName(String accountName) {
this.accountName = accountName;
}
public void setType(String type) {
this.type = type;
}
@Override
public void setDomainId(String domainId) {
this.domainId = domainId;
}
public void setDomainName(String domainName) {
this.domainName = domainName;
}
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + ((id == null) ? 0 : id.hashCode());
return result;
}
@Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
AffinityGroupResponse other = (AffinityGroupResponse) obj;
if (id == null) {
if (other.id != null)
return false;
} else if (!id.equals(other.id))
return false;
return true;
}
@Override
public void setProjectId(String projectId) {
// TODO Auto-generated method stub
}
@Override
public void setProjectName(String projectName) {
// TODO Auto-generated method stub
}
public void setVMIdList(List<String> vmIdList) {
this.vmIdList = vmIdList;
}
public void addVMId(String vmId) {
this.vmIdList.add(vmId);
}
}

View File

@ -0,0 +1,79 @@
// 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.affinity;
import java.util.List;
import com.cloud.exception.ResourceInUseException;
import com.cloud.uservm.UserVm;
import com.cloud.utils.Pair;
public interface AffinityGroupService {
/**
* Creates an affinity/anti-affinity group for the given account/domain.
*
* @param account
* @param domainId
* @param name
* @param type
* @param description
* @return AffinityGroup
*/
AffinityGroup createAffinityGroup(String account, Long domainId, String affinityGroupName,
String affinityGroupType, String description);
/**
* Creates an affinity/anti-affinity group.
*
* @param affinityGroupId
* @param account
* @param domainId
* @param affinityGroupName
* @throws ResourceInUseException
*/
boolean deleteAffinityGroup(Long affinityGroupId, String account, Long domainId, String affinityGroupName)
throws ResourceInUseException;
/** Lists Affinity Groups in your account
* @param account
* @param domainId
* @param affinityGroupId
* @param affinityGroupName
* @param affinityGroupType
* @param vmId
* @param startIndex
* @param pageSize
* @return
*/
Pair<List<? extends AffinityGroup>, Integer> listAffinityGroups(Long affinityGroupId, String affinityGroupName,
String affinityGroupType, Long vmId, Long startIndex, Long pageSize);
/**
* List group types available in deployment
*
* @return
*/
List<String> listAffinityGroupTypes();
AffinityGroup getAffinityGroup(Long groupId);
UserVm updateVMAffinityGroups(Long vmId, List<Long> affinityGroupIds);
}

View File

@ -0,0 +1,48 @@
// 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.affinity;
import java.util.HashSet;
import java.util.Set;
import org.apache.cloudstack.api.ApiConstants;
import org.apache.cloudstack.api.BaseResponse;
import org.apache.cloudstack.api.EntityReference;
import org.apache.cloudstack.api.response.ControlledEntityResponse;
import org.apache.cloudstack.api.response.ControlledViewEntityResponse;
import com.cloud.network.security.SecurityGroup;
import com.cloud.serializer.Param;
import com.google.gson.annotations.SerializedName;
@SuppressWarnings("unused")
@EntityReference(value = AffinityGroup.class)
public class AffinityGroupTypeResponse extends BaseResponse {
@SerializedName(ApiConstants.TYPE)
@Param(description = "the type of the affinity group")
private String type;
public AffinityGroupTypeResponse() {
}
public void setType(String type) {
this.type = type;
}
}

View File

@ -0,0 +1,44 @@
// 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.affinity;
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.VirtualMachine;
import com.cloud.vm.VirtualMachineProfile;
public class AffinityProcessorBase extends AdapterBase implements AffinityGroupProcessor {
protected String _type;
@Override
public void process(VirtualMachineProfile<? extends VirtualMachine> vm, DeploymentPlan plan, ExcludeList avoid)
throws AffinityConflictException {
}
@Override
public String getType() {
return _type;
}
public void setType(String type) {
_type = type;
}
}

View File

@ -479,13 +479,16 @@ public class ApiConstants {
public static final String SOURCE_IP_NETWORK_ID = "sourceipaddressnetworkid";
public static final String SCHEME = "scheme";
public static final String PROVIDER_TYPE = "providertype";
public static final String AFFINITY_GROUP_IDS = "affinitygroupids";
public static final String AFFINITY_GROUP_NAMES = "affinitygroupnames";
public static final String DEPLOYMENT_PLANNER = "deploymentplanner";
public enum HostDetails {
all, capacity, events, stats, min;
}
public enum VMDetails {
all, group, nics, stats, secgrp, tmpl, servoff, iso, volume, min;
all, group, nics, stats, secgrp, tmpl, servoff, iso, volume, min, affgrp;
}
public enum LDAPParams {

View File

@ -27,6 +27,7 @@ import java.util.regex.Pattern;
import javax.inject.Inject;
import org.apache.cloudstack.affinity.AffinityGroupService;
import org.apache.cloudstack.network.lb.ApplicationLoadBalancerService;
import org.apache.cloudstack.query.QueryService;
import org.apache.cloudstack.usage.UsageService;
@ -137,6 +138,7 @@ public abstract class BaseCmd {
@Inject public ApplicationLoadBalancerService _newLbSvc;
@Inject public NetworkModel _ntwkModel;
@Inject public ApplicationLoadBalancerService _appLbService;
@Inject public AffinityGroupService _affinityGroupService;
public abstract void execute() throws ResourceUnavailableException, InsufficientCapacityException, ServerApiException, ConcurrentOperationException, ResourceAllocationException, NetworkRuleConflictException;
@ -159,7 +161,7 @@ public abstract class BaseCmd {
/**
* For commands the API framework needs to know the owner of the object being acted upon. This method is
* used to determine that information.
*
*
* @return the id of the account that owns the object being acted upon
*/
public abstract long getEntityOwnerId();
@ -472,7 +474,7 @@ public abstract class BaseCmd {
if (!enabledOnly || account.getState() == Account.State.enabled) {
return account.getId();
} else {
throw new PermissionDeniedException("Can't add resources to the account id=" + account.getId() + " in state=" + account.getState() + " as it's no longer active");
throw new PermissionDeniedException("Can't add resources to the account id=" + account.getId() + " in state=" + account.getState() + " as it's no longer active");
}
} else {
// idList is not used anywhere, so removed it now
@ -489,7 +491,7 @@ public abstract class BaseCmd {
return project.getProjectAccountId();
} else {
PermissionDeniedException ex = new PermissionDeniedException("Can't add resources to the project with specified projectId in state=" + project.getState() + " as it's no longer active");
ex.addProxyObject(project, projectId, "projectId");
ex.addProxyObject(project, projectId, "projectId");
throw ex;
}
} else {

View File

@ -21,10 +21,13 @@ import java.util.EnumSet;
import java.util.List;
import java.util.Map;
import org.apache.cloudstack.affinity.AffinityGroup;
import org.apache.cloudstack.affinity.AffinityGroupResponse;
import org.apache.cloudstack.api.ApiConstants.HostDetails;
import org.apache.cloudstack.api.ApiConstants.VMDetails;
import org.apache.cloudstack.api.command.user.job.QueryAsyncJobResultCmd;
import org.apache.cloudstack.api.response.AccountResponse;
import org.apache.cloudstack.api.response.ApplicationLoadBalancerResponse;
import org.apache.cloudstack.api.response.AsyncJobResponse;
import org.apache.cloudstack.api.response.AutoScalePolicyResponse;
import org.apache.cloudstack.api.response.AutoScaleVmGroupResponse;
@ -42,6 +45,7 @@ import org.apache.cloudstack.api.response.EventResponse;
import org.apache.cloudstack.api.response.ExtractResponse;
import org.apache.cloudstack.api.response.FirewallResponse;
import org.apache.cloudstack.api.response.FirewallRuleResponse;
import org.apache.cloudstack.api.response.GlobalLoadBalancerResponse;
import org.apache.cloudstack.api.response.GuestOSResponse;
import org.apache.cloudstack.api.response.HostResponse;
import org.apache.cloudstack.api.response.HypervisorCapabilitiesResponse;
@ -51,7 +55,6 @@ import org.apache.cloudstack.api.response.IpForwardingRuleResponse;
import org.apache.cloudstack.api.response.LBHealthCheckResponse;
import org.apache.cloudstack.api.response.LBStickinessResponse;
import org.apache.cloudstack.api.response.LDAPConfigResponse;
import org.apache.cloudstack.api.response.ApplicationLoadBalancerResponse;
import org.apache.cloudstack.api.response.LoadBalancerResponse;
import org.apache.cloudstack.api.response.NetworkACLResponse;
import org.apache.cloudstack.api.response.NetworkOfferingResponse;
@ -118,9 +121,23 @@ import com.cloud.domain.Domain;
import com.cloud.event.Event;
import com.cloud.host.Host;
import com.cloud.hypervisor.HypervisorCapabilities;
import com.cloud.network.*;
import com.cloud.network.IpAddress;
import com.cloud.network.Network;
import com.cloud.network.Network.Service;
import com.cloud.network.as.*;
import com.cloud.network.PhysicalNetwork;
import com.cloud.network.PhysicalNetworkServiceProvider;
import com.cloud.network.PhysicalNetworkTrafficType;
import com.cloud.network.RemoteAccessVpn;
import com.cloud.network.Site2SiteCustomerGateway;
import com.cloud.network.Site2SiteVpnConnection;
import com.cloud.network.Site2SiteVpnGateway;
import com.cloud.network.VirtualRouterProvider;
import com.cloud.network.VpnUser;
import com.cloud.network.as.AutoScalePolicy;
import com.cloud.network.as.AutoScaleVmGroup;
import com.cloud.network.as.AutoScaleVmProfile;
import com.cloud.network.as.Condition;
import com.cloud.network.as.Counter;
import com.cloud.network.router.VirtualRouter;
import com.cloud.network.rules.FirewallRule;
import com.cloud.network.rules.HealthCheckPolicy;
@ -143,7 +160,12 @@ import com.cloud.projects.ProjectAccount;
import com.cloud.projects.ProjectInvitation;
import com.cloud.region.ha.GlobalLoadBalancerRule;
import com.cloud.server.ResourceTag;
import com.cloud.storage.*;
import com.cloud.storage.GuestOS;
import com.cloud.storage.S3;
import com.cloud.storage.Snapshot;
import com.cloud.storage.StoragePool;
import com.cloud.storage.Swift;
import com.cloud.storage.Volume;
import com.cloud.storage.snapshot.SnapshotPolicy;
import com.cloud.storage.snapshot.SnapshotSchedule;
import com.cloud.template.VirtualMachineTemplate;
@ -154,18 +176,8 @@ import com.cloud.uservm.UserVm;
import com.cloud.utils.net.Ip;
import com.cloud.vm.InstanceGroup;
import com.cloud.vm.Nic;
import com.cloud.vm.NicSecondaryIp;
import com.cloud.vm.snapshot.VMSnapshot;
import com.cloud.vm.VirtualMachine;
import org.apache.cloudstack.api.ApiConstants.HostDetails;
import org.apache.cloudstack.api.ApiConstants.VMDetails;
import org.apache.cloudstack.api.command.user.job.QueryAsyncJobResultCmd;
import org.apache.cloudstack.api.response.*;
import org.apache.cloudstack.region.Region;
import java.text.DecimalFormat;
import java.util.EnumSet;
import java.util.List;
import com.cloud.vm.snapshot.VMSnapshot;
public interface ResponseGenerator {
UserResponse createUserResponse(UserAccount user);
@ -388,14 +400,19 @@ public interface ResponseGenerator {
GuestOSResponse createGuestOSResponse(GuestOS os);
SnapshotScheduleResponse createSnapshotScheduleResponse(SnapshotSchedule sched);
UsageRecordResponse createUsageResponse(Usage usageRecord);
TrafficMonitorResponse createTrafficMonitorResponse(Host trafficMonitor);
VMSnapshotResponse createVMSnapshotResponse(VMSnapshot vmSnapshot);
NicSecondaryIpResponse createSecondaryIPToNicResponse(String ip,
Long nicId, Long networkId);
public NicResponse createNicResponse(Nic result);
ApplicationLoadBalancerResponse createLoadBalancerContainerReponse(ApplicationLoadBalancerRule lb, Map<Ip, UserVm> lbInstances);
AffinityGroupResponse createAffinityGroupResponse(AffinityGroup group);
Long getAffinityGroupId(String name, long entityOwnerId);
}

View File

@ -0,0 +1,71 @@
// Licensed to the Apache Software Foundation (ASF) under one
// or more contributor license agreements. See the NOTICE file
// distributed with this work for additional information
// regarding copyright ownership. The ASF licenses this file
// to you under the Apache License, Version 2.0 (the
// "License"); you may not use this file except in compliance
// with the License. You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing,
// software distributed under the License is distributed on an
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
// KIND, either express or implied. See the License for the
// specific language governing permissions and limitations
// under the License.
package org.apache.cloudstack.api.command.admin.config;
import java.util.ArrayList;
import java.util.List;
import org.apache.cloudstack.api.APICommand;
import org.apache.cloudstack.api.BaseListCmd;
import org.apache.cloudstack.api.response.DeploymentPlannersResponse;
import org.apache.cloudstack.api.response.ListResponse;
import org.apache.log4j.Logger;
@APICommand(name = "listDeploymentPlanners", description = "Lists all DeploymentPlanners available.", responseObject = DeploymentPlannersResponse.class)
public class ListDeploymentPlannersCmd extends BaseListCmd {
public static final Logger s_logger = Logger.getLogger(ListDeploymentPlannersCmd.class.getName());
private static final String s_name = "listdeploymentplannersresponse";
/////////////////////////////////////////////////////
//////////////// API parameters /////////////////////
/////////////////////////////////////////////////////
/////////////////////////////////////////////////////
/////////////////// Accessors ///////////////////////
/////////////////////////////////////////////////////
/////////////////////////////////////////////////////
/////////////// API Implementation///////////////////
/////////////////////////////////////////////////////
@Override
public String getCommandName() {
return s_name;
}
@Override
public void execute(){
List<String> planners = _mgr.listDeploymentPlanners();
ListResponse<DeploymentPlannersResponse> response = new ListResponse<DeploymentPlannersResponse>();
List<DeploymentPlannersResponse> plannerResponses = new ArrayList<DeploymentPlannersResponse>();
for (String planner : planners) {
DeploymentPlannersResponse plannerResponse = new DeploymentPlannersResponse();
plannerResponse.setName(planner);
plannerResponse.setObjectName("deploymentPlanner");
plannerResponses.add(plannerResponse);
}
response.setResponses(plannerResponses);
response.setResponseName(getCommandName());
this.setResponseObject(response);
}
}

View File

@ -84,6 +84,9 @@ public class CreateServiceOfferingCmd extends BaseCmd {
@Parameter(name=ApiConstants.NETWORKRATE, type=CommandType.INTEGER, description="data transfer rate in megabits per second allowed. Supported only for non-System offering and system offerings having \"domainrouter\" systemvmtype")
private Integer networkRate;
@Parameter(name = ApiConstants.DEPLOYMENT_PLANNER, type = CommandType.STRING, description = "The deployment planner heuristics used to deploy a VM of this offering, default \"FirstFitPlanner\".")
private String deploymentPlanner;
/////////////////////////////////////////////////////
/////////////////// Accessors ///////////////////////
/////////////////////////////////////////////////////
@ -148,6 +151,10 @@ public class CreateServiceOfferingCmd extends BaseCmd {
return networkRate;
}
public String getDeploymentPlanner() {
return deploymentPlanner;
}
/////////////////////////////////////////////////////
/////////////// API Implementation///////////////////
/////////////////////////////////////////////////////

View File

@ -0,0 +1,167 @@
// Licensed to the Apache Software Foundation (ASF) under one
// or more contributor license agreements. See the NOTICE file
// distributed with this work for additional information
// regarding copyright ownership. The ASF licenses this file
// to you under the Apache License, Version 2.0 (the
// "License"); you may not use this file except in compliance
// with the License. You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing,
// software distributed under the License is distributed on an
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
// KIND, either express or implied. See the License for the
// specific language governing permissions and limitations
// under the License.
package org.apache.cloudstack.api.command.user.affinitygroup;
import org.apache.cloudstack.affinity.AffinityGroup;
import org.apache.cloudstack.affinity.AffinityGroupResponse;
import org.apache.cloudstack.api.APICommand;
import org.apache.cloudstack.api.ApiConstants;
import org.apache.cloudstack.api.ApiErrorCode;
import org.apache.cloudstack.api.BaseAsyncCreateCmd;
import org.apache.cloudstack.api.Parameter;
import org.apache.cloudstack.api.ServerApiException;
import org.apache.cloudstack.api.response.DomainResponse;
import org.apache.log4j.Logger;
import com.cloud.async.AsyncJob;
import com.cloud.event.EventTypes;
import com.cloud.exception.ResourceAllocationException;
import com.cloud.user.Account;
import com.cloud.user.UserContext;
@APICommand(name = "createAffinityGroup", responseObject = AffinityGroupResponse.class, description = "Creates an affinity/anti-affinity group")
public class CreateAffinityGroupCmd extends BaseAsyncCreateCmd {
public static final Logger s_logger = Logger.getLogger(CreateAffinityGroupCmd.class.getName());
private static final String s_name = "createaffinitygroupresponse";
// ///////////////////////////////////////////////////
// ////////////// API parameters /////////////////////
// ///////////////////////////////////////////////////
@Parameter(name = ApiConstants.ACCOUNT, type = CommandType.STRING, description = "an account for the affinity group. Must be used with domainId.")
private String accountName;
@Parameter(name = ApiConstants.DOMAIN_ID, type = CommandType.UUID, description = "domainId of the account owning the affinity group", entityType = DomainResponse.class)
private Long domainId;
@Parameter(name = ApiConstants.DESCRIPTION, type = CommandType.STRING, description = "optional description of the affinity group")
private String description;
@Parameter(name = ApiConstants.NAME, type = CommandType.STRING, required = true, description = "name of the affinity group")
private String affinityGroupName;
@Parameter(name = ApiConstants.TYPE, type = CommandType.STRING, required = true, description = "Type of the affinity group from the available affinity/anti-affinity group types")
private String affinityGroupType;
// ///////////////////////////////////////////////////
// ///////////////// Accessors ///////////////////////
// ///////////////////////////////////////////////////
public String getAccountName() {
return accountName;
}
public String getDescription() {
return description;
}
public Long getDomainId() {
return domainId;
}
public String getAffinityGroupName() {
return affinityGroupName;
}
public String getAffinityGroupType() {
return affinityGroupType;
}
// ///////////////////////////////////////////////////
// ///////////// API Implementation///////////////////
// ///////////////////////////////////////////////////
@Override
public String getCommandName() {
return s_name;
}
@Override
public long getEntityOwnerId() {
Account account = UserContext.current().getCaller();
if ((account == null) || isAdmin(account.getType())) {
if ((domainId != null) && (accountName != null)) {
Account userAccount = _responseGenerator.findAccountByNameDomain(accountName, domainId);
if (userAccount != null) {
return userAccount.getId();
}
}
}
if (account != null) {
return account.getId();
}
return Account.ACCOUNT_ID_SYSTEM; // no account info given, parent this
// command to SYSTEM so ERROR events
// are tracked
}
@Override
public void execute() {
AffinityGroup group = _affinityGroupService.getAffinityGroup(getEntityId());
if (group != null) {
AffinityGroupResponse response = _responseGenerator.createAffinityGroupResponse(group);
response.setResponseName(getCommandName());
this.setResponseObject(response);
} else {
throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, "Failed to create affinity group:"
+ affinityGroupName);
}
}
@Override
public void create() throws ResourceAllocationException {
AffinityGroup result = _affinityGroupService.createAffinityGroup(accountName, domainId, affinityGroupName,
affinityGroupType, description);
if (result != null) {
setEntityId(result.getId());
setEntityUuid(result.getUuid());
} else {
throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, "Failed to create affinity group entity" + affinityGroupName);
}
}
@Override
public String getEventType() {
return EventTypes.EVENT_AFFINITY_GROUP_CREATE;
}
@Override
public String getEventDescription() {
return "creating Affinity Group";
}
@Override
public String getCreateEventType() {
return EventTypes.EVENT_AFFINITY_GROUP_CREATE;
}
@Override
public String getCreateEventDescription() {
return "creating Affinity Group";
}
@Override
public AsyncJob.Type getInstanceType() {
return AsyncJob.Type.AffinityGroup;
}
}

View File

@ -0,0 +1,154 @@
// Licensed to the Apache Software Foundation (ASF) under one
// or more contributor license agreements. See the NOTICE file
// distributed with this work for additional information
// regarding copyright ownership. The ASF licenses this file
// to you under the Apache License, Version 2.0 (the
// "License"); you may not use this file except in compliance
// with the License. You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing,
// software distributed under the License is distributed on an
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
// KIND, either express or implied. See the License for the
// specific language governing permissions and limitations
// under the License.
package org.apache.cloudstack.api.command.user.affinitygroup;
import org.apache.cloudstack.affinity.AffinityGroupResponse;
import org.apache.cloudstack.api.APICommand;
import org.apache.cloudstack.api.ApiConstants;
import org.apache.cloudstack.api.ApiErrorCode;
import org.apache.cloudstack.api.BaseAsyncCmd;
import org.apache.cloudstack.api.Parameter;
import org.apache.cloudstack.api.ServerApiException;
import org.apache.cloudstack.api.response.DomainResponse;
import org.apache.cloudstack.api.response.SuccessResponse;
import org.apache.log4j.Logger;
import com.cloud.async.AsyncJob;
import com.cloud.event.EventTypes;
import com.cloud.exception.InvalidParameterValueException;
import com.cloud.exception.ResourceInUseException;
import com.cloud.user.Account;
import com.cloud.user.UserContext;
@APICommand(name = "deleteAffinityGroup", description = "Deletes affinity group", responseObject = SuccessResponse.class)
public class DeleteAffinityGroupCmd extends BaseAsyncCmd {
public static final Logger s_logger = Logger.getLogger(DeleteAffinityGroupCmd.class.getName());
private static final String s_name = "deleteaffinitygroupresponse";
/////////////////////////////////////////////////////
//////////////// API parameters /////////////////////
/////////////////////////////////////////////////////
@Parameter(name = ApiConstants.ACCOUNT, type = CommandType.STRING, description = "the account of the affinity group. Must be specified with domain ID")
private String accountName;
@Parameter(name = ApiConstants.DOMAIN_ID, type = CommandType.UUID, description = "the domain ID of account owning the affinity group", entityType = DomainResponse.class)
private Long domainId;
@Parameter(name = ApiConstants.ID, type = CommandType.UUID, description = "The ID of the affinity group. Mutually exclusive with name parameter", entityType = AffinityGroupResponse.class)
private Long id;
@Parameter(name = ApiConstants.NAME, type = CommandType.STRING, description = "The name of the affinity group. Mutually exclusive with id parameter")
private String name;
/////////////////////////////////////////////////////
/////////////////// Accessors ///////////////////////
/////////////////////////////////////////////////////
public String getAccountName() {
return accountName;
}
public Long getDomainId() {
return domainId;
}
public Long getId() {
if (id != null && name != null) {
throw new InvalidParameterValueException("name and id parameters are mutually exclusive");
}
if (name != null) {
id = _responseGenerator.getAffinityGroupId(name, getEntityOwnerId());
if (id == null) {
throw new InvalidParameterValueException("Unable to find affinity group by name " + name
+ " for the account id=" + getEntityOwnerId());
}
}
if (id == null) {
throw new InvalidParameterValueException(
"Either id or name parameter is requred by deleteAffinityGroup command");
}
return id;
}
/////////////////////////////////////////////////////
/////////////// API Implementation///////////////////
/////////////////////////////////////////////////////
@Override
public String getCommandName() {
return s_name;
}
@Override
public long getEntityOwnerId() {
Account account = UserContext.current().getCaller();
if ((account == null) || isAdmin(account.getType())) {
if ((domainId != null) && (accountName != null)) {
Account userAccount = _responseGenerator.findAccountByNameDomain(accountName, domainId);
if (userAccount != null) {
return userAccount.getId();
}
}
}
if (account != null) {
return account.getId();
}
return Account.ACCOUNT_ID_SYSTEM; // no account info given, parent this
// command to SYSTEM so ERROR events
// are tracked
}
@Override
public void execute(){
try{
boolean result = _affinityGroupService.deleteAffinityGroup(id, accountName, domainId, name);
if (result) {
SuccessResponse response = new SuccessResponse(getCommandName());
this.setResponseObject(response);
} else {
throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, "Failed to delete affinity group");
}
} catch (ResourceInUseException ex) {
s_logger.warn("Exception: ", ex);
throw new ServerApiException(ApiErrorCode.RESOURCE_IN_USE_ERROR, ex.getMessage());
}
}
@Override
public String getEventType() {
return EventTypes.EVENT_AFFINITY_GROUP_DELETE;
}
@Override
public String getEventDescription() {
return "Deleting Affinity Group";
}
@Override
public AsyncJob.Type getInstanceType() {
return AsyncJob.Type.AffinityGroup;
}
}

View File

@ -0,0 +1,67 @@
// 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.AffinityGroupTypeResponse;
import org.apache.cloudstack.api.APICommand;
import org.apache.cloudstack.api.BaseListCmd;
import org.apache.cloudstack.api.response.ListResponse;
import org.apache.log4j.Logger;
import com.cloud.user.Account;
@APICommand(name = "listAffinityGroupTypes", description = "Lists affinity group types available", responseObject = AffinityGroupTypeResponse.class)
public class ListAffinityGroupTypesCmd extends BaseListCmd {
public static final Logger s_logger = Logger.getLogger(ListAffinityGroupTypesCmd.class.getName());
private static final String s_name = "listaffinitygrouptypesresponse";
/////////////////////////////////////////////////////
/////////////// API Implementation///////////////////
/////////////////////////////////////////////////////
@Override
public String getCommandName() {
return s_name;
}
public long getEntityOwnerId() {
return Account.ACCOUNT_ID_SYSTEM;
}
@Override
public void execute() {
List<String> result = _affinityGroupService.listAffinityGroupTypes();
ListResponse<AffinityGroupTypeResponse> response = new ListResponse<AffinityGroupTypeResponse>();
ArrayList<AffinityGroupTypeResponse> responses = new ArrayList<AffinityGroupTypeResponse>();
if (result != null) {
for (String type : result) {
AffinityGroupTypeResponse affinityTypeResponse = new AffinityGroupTypeResponse();
affinityTypeResponse.setType(type);
affinityTypeResponse.setObjectName("affinityGroupType");
responses.add(affinityTypeResponse);
}
}
response.setResponses(responses);
response.setResponseName(getCommandName());
this.setResponseObject(response);
}
}

View File

@ -0,0 +1,90 @@
// Licensed to the Apache Software Foundation (ASF) under one
// or more contributor license agreements. See the NOTICE file
// distributed with this work for additional information
// regarding copyright ownership. The ASF licenses this file
// to you under the Apache License, Version 2.0 (the
// "License"); you may not use this file except in compliance
// with the License. You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing,
// software distributed under the License is distributed on an
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
// KIND, either express or implied. See the License for the
// specific language governing permissions and limitations
// under the License.
package org.apache.cloudstack.api.command.user.affinitygroup;
import org.apache.cloudstack.affinity.AffinityGroupResponse;
import org.apache.cloudstack.api.APICommand;
import org.apache.cloudstack.api.ApiConstants;
import org.apache.cloudstack.api.BaseListCmd;
import org.apache.cloudstack.api.Parameter;
import org.apache.cloudstack.api.response.ListResponse;
import org.apache.cloudstack.api.response.UserVmResponse;
import org.apache.log4j.Logger;
import com.cloud.async.AsyncJob;
@APICommand(name = "listAffinityGroups", description = "Lists affinity groups", responseObject = AffinityGroupResponse.class)
public class ListAffinityGroupsCmd extends BaseListCmd {
public static final Logger s_logger = Logger.getLogger(ListAffinityGroupsCmd.class.getName());
private static final String s_name = "listaffinitygroupsresponse";
/////////////////////////////////////////////////////
//////////////// API parameters /////////////////////
/////////////////////////////////////////////////////
@Parameter(name = ApiConstants.NAME, type = CommandType.STRING, description = "lists affinity groups by name")
private String affinityGroupName;
@Parameter(name = ApiConstants.VIRTUAL_MACHINE_ID, type = CommandType.UUID, description = "lists affinity groups by virtual machine id", entityType = UserVmResponse.class)
private Long virtualMachineId;
@Parameter(name = ApiConstants.ID, type = CommandType.UUID, description = "list the affinity group by the id provided", entityType = AffinityGroupResponse.class)
private Long id;
@Parameter(name = ApiConstants.TYPE, type = CommandType.STRING, description = "lists affinity groups by type")
private String affinityGroupType;
/////////////////////////////////////////////////////
/////////////////// Accessors ///////////////////////
/////////////////////////////////////////////////////
public String getAffinityGroupName() {
return affinityGroupName;
}
public Long getVirtualMachineId() {
return virtualMachineId;
}
public Long getId(){
return id;
}
/////////////////////////////////////////////////////
/////////////// API Implementation///////////////////
/////////////////////////////////////////////////////
@Override
public String getCommandName() {
return s_name;
}
@Override
public void execute(){
ListResponse<AffinityGroupResponse> response = _queryService.listAffinityGroups(id, affinityGroupName,
affinityGroupType, virtualMachineId, this.getStartIndex(), this.getPageSizeVal());
response.setResponseName(getCommandName());
this.setResponseObject(response);
}
@Override
public AsyncJob.Type getInstanceType() {
return AsyncJob.Type.AffinityGroup;
}
}

View File

@ -0,0 +1,164 @@
// 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.EnumSet;
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.ApiConstants.VMDetails;
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());
ArrayList<VMDetails> dc = new ArrayList<VMDetails>();
dc.add(VMDetails.valueOf("affgrp"));
EnumSet<VMDetails> details = EnumSet.copyOf(dc);
if (result != null){
UserVmResponse response = _responseGenerator.createUserVmResponse("virtualmachine", details, 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 org.apache.cloudstack.acl.SecurityChecker.AccessType;
import org.apache.cloudstack.affinity.AffinityGroupResponse;
import org.apache.cloudstack.api.ACL;
import org.apache.cloudstack.api.APICommand;
import org.apache.cloudstack.api.ApiConstants;
@ -172,6 +173,16 @@ 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")
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."
+ " Mutually exclusive with affinitygroupnames 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."
+ "Mutually exclusive with affinitygroupids parameter")
private List<String> affinityGroupNameList;
/////////////////////////////////////////////////////
/////////////////// Accessors ///////////////////////
@ -321,6 +332,30 @@ public class DeployVMCmd extends BaseAsyncCreateCmd {
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///////////////////
/////////////////////////////////////////////////////
@ -447,18 +482,18 @@ public class DeployVMCmd extends BaseAsyncCreateCmd {
throw new InvalidParameterValueException("Can't specify network Ids in Basic zone");
} else {
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 {
if (zone.isSecurityGroupEnabled()) {
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 {
if (getSecurityGroupIdList() != null && !getSecurityGroupIdList().isEmpty()) {
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,
diskOfferingId, size, group, getHypervisor(), userData, sshKeyPairName, getIpToNetworkMap(), addrs, keyboard);
diskOfferingId, size, group, getHypervisor(), userData, sshKeyPairName, getIpToNetworkMap(), addrs, keyboard, getAffinityGroupIdList());
}
}

View File

@ -0,0 +1,37 @@
// 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.response;
import org.apache.cloudstack.api.ApiConstants;
import org.apache.cloudstack.api.BaseResponse;
import com.cloud.serializer.Param;
import com.google.gson.annotations.SerializedName;
public class DeploymentPlannersResponse extends BaseResponse {
@SerializedName(ApiConstants.NAME)
@Param(description = "Deployment Planner name")
private String name;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}

View File

@ -21,6 +21,7 @@ import java.util.HashSet;
import java.util.LinkedHashSet;
import java.util.Set;
import org.apache.cloudstack.affinity.AffinityGroupResponse;
import org.apache.cloudstack.api.ApiConstants;
import org.apache.cloudstack.api.BaseResponse;
import org.apache.cloudstack.api.EntityReference;
@ -169,10 +170,15 @@ public class UserVmResponse extends BaseResponse implements ControlledEntityResp
@SerializedName(ApiConstants.SSH_KEYPAIR) @Param(description="ssh key-pair")
private String keyPairName;
@SerializedName("affinitygroup")
@Param(description = "list of affinity groups associated with the virtual machine", responseObject = AffinityGroupResponse.class)
private Set<AffinityGroupResponse> affinityGroupList;
public UserVmResponse(){
securityGroupList = new LinkedHashSet<SecurityGroupResponse>();
nics = new LinkedHashSet<NicResponse>();
tags = new LinkedHashSet<ResourceTagResponse>();
affinityGroupList = new LinkedHashSet<AffinityGroupResponse>();
}
public void setHypervisor(String hypervisor) {
@ -381,4 +387,12 @@ public class UserVmResponse extends BaseResponse implements ControlledEntityResp
this.keyPairName = keyPairName;
}
public void setAffinityGroupList(Set<AffinityGroupResponse> affinityGroups) {
this.affinityGroupList = affinityGroups;
}
public void addAffinityGroup(AffinityGroupResponse affinityGroup) {
this.affinityGroupList.add(affinityGroup);
}
}

View File

@ -16,6 +16,7 @@
// under the License.
package org.apache.cloudstack.query;
import org.apache.cloudstack.affinity.AffinityGroupResponse;
import org.apache.cloudstack.api.command.admin.host.ListHostsCmd;
import org.apache.cloudstack.api.command.admin.router.ListRoutersCmd;
import org.apache.cloudstack.api.command.admin.storage.ListStoragePoolsCmd;
@ -97,4 +98,7 @@ public interface QueryService {
public ListResponse<ServiceOfferingResponse> searchForServiceOfferings(ListServiceOfferingsCmd cmd);
public ListResponse<ZoneResponse> listDataCenters(ListZonesByCmd cmd);
public ListResponse<AffinityGroupResponse> listAffinityGroups(Long affinityGroupId, String affinityGroupName,
String affinityGroupType, Long vmId, Long startIndex, Long pageSize);
}

View File

@ -239,6 +239,11 @@
<artifactId>cloud-plugin-snmp-alerts</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>org.apache.cloudstack</groupId>
<artifactId>cloud-plugin-host-anti-affinity</artifactId>
<version>${project.version}</version>
</dependency>
</dependencies>
<build>
<defaultGoal>install</defaultGoal>
@ -289,7 +294,7 @@
-->
<execution>
<id>copy-systemvm</id>
<phase>package</phase>
<phase>process-resources</phase>
<goals>
<goal>run</goal>
</goals>

View File

@ -842,5 +842,15 @@
<bean id="baremetalDhcpDaoImpl" class="com.cloud.baremetal.database.BaremetalDhcpDaoImpl" />
<bean id="baremetalPxeDaoImpl" class="com.cloud.baremetal.database.BaremetalPxeDaoImpl" />
-->
<bean id="AffinityGroupServiceImpl" class="org.apache.cloudstack.affinity.AffinityGroupServiceImpl"/>
<bean id="DeploymentPlanningManager" class="com.cloud.deploy.DeploymentPlanningManagerImpl" />
<bean id="AffinityGroupJoinDaoImpl" class="com.cloud.api.query.dao.AffinityGroupJoinDaoImpl">
</bean>
<bean id="AffinityGroupDaoImpl" class="org.apache.cloudstack.affinity.dao.AffinityGroupDaoImpl">
</bean>
<bean id="AffinityGroupVMMapDaoImpl" class="org.apache.cloudstack.affinity.dao.AffinityGroupVMMapDaoImpl">
</bean>
</beans>

View File

@ -580,3 +580,9 @@ createInternalLoadBalancerElement=1
listInternalLoadBalancerElements=1
#### Affinity group commands
createAffinityGroup=15
deleteAffinityGroup=15
listAffinityGroups=15
updateVMAffinityGroup=15
listAffinityGroupTypes=15

View File

@ -31,6 +31,7 @@
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-3.0.xsd">
<!--
OSS deployment configuration
@ -155,7 +156,6 @@
<ref bean="FirstFitPlanner" />
<ref bean="UserDispersingPlanner" />
<ref bean="UserConcentratedPodPlanner" />
<!--
<ref bean="BareMetalPlanner" />
-->
@ -250,5 +250,12 @@
</property>
</bean>
<!--
AffinityGroup Processors
-->
<bean id="HostAntiAffinityProcessor" class="org.apache.cloudstack.affinity.HostAntiAffinityProcessor">
<property name="name" value="HostAntiAffinityProcessor"/>
<property name="type" value="host anti-affinity"/>
</bean>
</beans>

View File

@ -1,4 +1,3 @@
<!--
~ Licensed to the Apache Software Foundation (ASF) under one
~ or more contributor license agreements. See the NOTICE file
@ -34,8 +33,8 @@
<!--
OSS deployment component configuration
-->
<bean id="databaseUpgradeChecker" class="com.cloud.upgrade.DatabaseUpgradeChecker" />
<bean id="configurationDaoImpl" class="com.cloud.configuration.dao.ConfigurationDaoImpl" />
<bean id="databaseUpgradeChecker" class="com.cloud.upgrade.DatabaseUpgradeChecker"/>
<bean id="configurationDaoImpl" class="com.cloud.configuration.dao.ConfigurationDaoImpl"/>
<!-- simulator components -->
<bean id="SimulatorSecondaryDiscoverer" class="com.cloud.resource.SimulatorSecondaryDiscoverer">
@ -122,9 +121,9 @@
<bean id="deploymentPlanners" class="com.cloud.utils.component.AdapterList">
<property name="Adapters">
<list>
<ref bean="FirstFitPlanner" />
<ref bean="UserDispersingPlanner" />
<ref bean="UserConcentratedPodPlanner" />
<ref bean="FirstFitPlanner"/>
<ref bean="UserDispersingPlanner"/>
<ref bean="UserConcentratedPodPlanner"/>
<!--
<ref bean="BareMetalPlanner" />
@ -215,6 +214,16 @@
</property>
</bean>
<bean id="GlobalLoadBalancingRulesServiceImpl" class ="org.apache.cloudstack.region.gslb.GlobalLoadBalancingRulesServiceImpl" />
<bean id="GlobalLoadBalancingRulesServiceImpl"
class="org.apache.cloudstack.region.gslb.GlobalLoadBalancingRulesServiceImpl"/>
<!--
AffinityGroup Processors
-->
<bean id="HostAntiAffinityProcessor" class="org.apache.cloudstack.affinity.HostAntiAffinityProcessor">
<property name="name" value="HostAntiAffinityProcessor"/>
<property name="type" value="host anti-affinity"/>
</bean>
</beans>

View File

@ -36,7 +36,9 @@ import com.cloud.deploy.DataCenterDeployment;
import com.cloud.deploy.DeployDestination;
import com.cloud.deploy.DeploymentPlan;
import com.cloud.deploy.DeploymentPlanner;
import com.cloud.deploy.DeploymentPlanningManager;
import com.cloud.deploy.DeploymentPlanner.ExcludeList;
import com.cloud.exception.AffinityConflictException;
import com.cloud.exception.AgentUnavailableException;
import com.cloud.exception.ConcurrentOperationException;
import com.cloud.exception.InsufficientCapacityException;
@ -55,7 +57,7 @@ import com.cloud.storage.dao.VMTemplateDao;
import com.cloud.storage.dao.VolumeDao;
import com.cloud.user.dao.AccountDao;
import com.cloud.user.dao.UserDao;
import com.cloud.utils.component.ComponentContext;
import com.cloud.utils.exception.CloudRuntimeException;
import com.cloud.vm.VMInstanceVO;
import com.cloud.vm.VirtualMachineManager;
import com.cloud.vm.VirtualMachineProfile;
@ -69,42 +71,45 @@ public class VMEntityManagerImpl implements VMEntityManager {
protected VMInstanceDao _vmDao;
@Inject
protected VMTemplateDao _templateDao = null;
@Inject
protected ServiceOfferingDao _serviceOfferingDao;
@Inject
protected DiskOfferingDao _diskOfferingDao = null;
@Inject
protected NetworkDao _networkDao;
@Inject
protected AccountDao _accountDao = null;
@Inject
protected UserDao _userDao = null;
@Inject
@Inject
protected VMEntityDao _vmEntityDao;
@Inject
@Inject
protected VMReservationDao _reservationDao;
@Inject
protected VirtualMachineManager _itMgr;
@Inject
protected List<DeploymentPlanner> _planners;
@Inject
protected VolumeDao _volsDao;
@Inject
protected PrimaryDataStoreDao _storagePoolDao;
@Inject
DataStoreManager dataStoreMgr;
@Inject
DeploymentPlanningManager _dpMgr;
@Override
public VMEntityVO loadVirtualMachine(String vmId) {
// TODO Auto-generated method stub
@ -114,11 +119,11 @@ public class VMEntityManagerImpl implements VMEntityManager {
@Override
public void saveVirtualMachine(VMEntityVO entity) {
_vmEntityDao.persist(entity);
}
@Override
public String reserveVirtualMachine(VMEntityVO vmEntityVO, String plannerToUse, DeploymentPlan planToDeploy, ExcludeList exclude)
public String reserveVirtualMachine(VMEntityVO vmEntityVO, String plannerToUse, DeploymentPlan planToDeploy, ExcludeList exclude)
throws InsufficientCapacityException, ResourceUnavailableException {
//call planner and get the deployDestination.
@ -130,12 +135,12 @@ public class VMEntityManagerImpl implements VMEntityManager {
if(planToDeploy != null && planToDeploy.getDataCenterId() != 0){
plan = new DataCenterDeployment(planToDeploy.getDataCenterId(), planToDeploy.getPodId(), planToDeploy.getClusterId(), planToDeploy.getHostId(), planToDeploy.getPoolId(), planToDeploy.getPhysicalNetworkId());
}
List<VolumeVO> vols = _volsDao.findReadyRootVolumesByInstance(vm.getId());
if(!vols.isEmpty()){
VolumeVO vol = vols.get(0);
StoragePool pool = (StoragePool)this.dataStoreMgr.getPrimaryDataStore(vol.getPoolId());
if (!pool.isInMaintenance()) {
long rootVolDcId = pool.getDataCenterId();
Long rootVolPodId = pool.getPodId();
@ -156,21 +161,21 @@ public class VMEntityManagerImpl implements VMEntityManager {
}
}
}
DeployDestination dest;
try {
dest = _dpMgr.planDeployment(vmProfile, plan, exclude);
} catch (AffinityConflictException e) {
throw new CloudRuntimeException("Unable to create deployment, affinity rules associted to the VM conflict");
}
DeploymentPlanner planner = ComponentContext.getComponent(plannerToUse);
DeployDestination dest = null;
if (planner.canHandle(vmProfile, plan, exclude)) {
dest = planner.plan(vmProfile, plan, exclude);
}
if (dest != null) {
//save destination with VMEntityVO
VMReservationVO vmReservation = new VMReservationVO(vm.getId(), dest.getDataCenter().getId(), dest.getPod().getId(), dest.getCluster().getId(), dest.getHost().getId());
Map<Long,Long> volumeReservationMap = new HashMap<Long,Long>();
if (vm.getHypervisorType() != HypervisorType.BareMetal) {
for(Volume vo : dest.getStorageForDisks().keySet()){
volumeReservationMap.put(vo.getId(), dest.getStorageForDisks().get(vo).getId());
@ -180,21 +185,21 @@ public class VMEntityManagerImpl implements VMEntityManager {
vmEntityVO.setVmReservation(vmReservation);
_vmEntityDao.persist(vmEntityVO);
return vmReservation.getUuid();
}else{
throw new InsufficientServerCapacityException("Unable to create a deployment for " + vmProfile, DataCenter.class, plan.getDataCenterId());
}
}
@Override
public void deployVirtualMachine(String reservationId, String caller, Map<VirtualMachineProfile.Param, Object> params) throws InsufficientCapacityException, ResourceUnavailableException{
//grab the VM Id and destination using the reservationId.
VMReservationVO vmReservation = _reservationDao.findByReservationId(reservationId);
long vmId = vmReservation.getVmId();
VMInstanceVO vm = _vmDao.findById(vmId);
//Pass it down
Long poolId = null;
@ -205,12 +210,17 @@ public class VMEntityManagerImpl implements VMEntityManager {
poolId = storage.get(volIdList.get(0));
}
}
DataCenterDeployment plan = new DataCenterDeployment(vm.getDataCenterId(), vmReservation.getPodId(), vmReservation.getClusterId(),
DataCenterDeployment reservedPlan = new DataCenterDeployment(vm.getDataCenterId(), vmReservation.getPodId(), vmReservation.getClusterId(),
vmReservation.getHostId(), null , null);
VMInstanceVO vmDeployed = _itMgr.start(vm, params, _userDao.findById(new Long(caller)), _accountDao.findById(vm.getAccountId()), plan);
try{
VMInstanceVO vmDeployed = _itMgr.start(vm, params, _userDao.findById(new Long(caller)), _accountDao.findById(vm.getAccountId()), reservedPlan);
}catch(Exception ex){
//Retry the deployment without using the reservation plan
DataCenterDeployment plan = new DataCenterDeployment(vm.getDataCenterId(), null, null,null, null , null);
_itMgr.start(vm, params, _userDao.findById(new Long(caller)), _accountDao.findById(vm.getAccountId()), plan);
}
}
@Override
@ -227,7 +237,7 @@ public class VMEntityManagerImpl implements VMEntityManager {
VMInstanceVO vm = _vmDao.findByUuid(vmEntityVO.getUuid());
return _itMgr.destroy(vm, _userDao.findById(new Long(caller)), _accountDao.findById(vm.getAccountId()));
}
}

View File

@ -51,7 +51,6 @@ import com.cloud.user.dao.AccountDao;
import com.cloud.utils.Pair;
import com.cloud.utils.component.ComponentContext;
import com.cloud.vm.NicProfile;
import com.cloud.vm.UserVmVO;
import com.cloud.vm.VMInstanceVO;
import com.cloud.vm.VirtualMachineManager;
import com.cloud.vm.dao.UserVmDao;
@ -66,25 +65,25 @@ public class CloudOrchestrator implements OrchestrationService {
@Inject
private VirtualMachineManager _itMgr;
@Inject
protected VMTemplateDao _templateDao = null;
@Inject
protected VMInstanceDao _vmDao;
@Inject
protected UserVmDao _userVmDao = null;
@Inject
protected ServiceOfferingDao _serviceOfferingDao;
@Inject
protected DiskOfferingDao _diskOfferingDao = null;
@Inject
protected NetworkDao _networkDao;
@Inject
protected AccountDao _accountDao = null;
@ -147,17 +146,17 @@ public class CloudOrchestrator implements OrchestrationService {
@Override
public VirtualMachineEntity createVirtualMachine(
String id,
String owner,
String templateId,
String hostName,
String id,
String owner,
String templateId,
String hostName,
String displayName,
String hypervisor,
int cpu,
int speed,
int cpu,
int speed,
long memory,
Long diskSize,
List<String> computeTags,
List<String> computeTags,
List<String> rootDiskTags,
Map<String, NicProfile> networkNicMap, DeploymentPlan plan) throws InsufficientCapacityException {
@ -173,22 +172,22 @@ public class CloudOrchestrator implements OrchestrationService {
VirtualMachineEntityImpl vmEntity = ComponentContext.inject(VirtualMachineEntityImpl.class);
vmEntity.init(id, owner, hostName, displayName, cpu, speed, memory, computeTags, rootDiskTags, new ArrayList<String>(networkNicMap.keySet()));
HypervisorType hypervisorType = HypervisorType.valueOf(hypervisor);
//load vm instance and offerings and call virtualMachineManagerImpl
VMInstanceVO vm = _vmDao.findByUuid(id);
// If the template represents an ISO, a disk offering must be passed in, and will be used to create the root disk
// Else, a disk offering is optional, and if present will be used to create the data disk
Pair<DiskOfferingVO, Long> rootDiskOffering = new Pair<DiskOfferingVO, Long>(null, null);
List<Pair<DiskOfferingVO, Long>> dataDiskOfferings = new ArrayList<Pair<DiskOfferingVO, Long>>();
ServiceOfferingVO offering = _serviceOfferingDao.findById(vm.getServiceOfferingId());
rootDiskOffering.first(offering);
if(vm.getDiskOfferingId() != null){
DiskOfferingVO diskOffering = _diskOfferingDao.findById(vm.getDiskOfferingId());
if (diskOffering == null) {
@ -205,32 +204,32 @@ public class CloudOrchestrator implements OrchestrationService {
}
dataDiskOfferings.add(new Pair<DiskOfferingVO, Long>(diskOffering, size));
}
if (_itMgr.allocate(_userVmDao.findById(vm.getId(), true), _templateDao.findById(new Long(templateId)), offering, rootDiskOffering, dataDiskOfferings, networkIpMap, null, plan, hypervisorType, _accountDao.findById(new Long(owner))) == null) {
return null;
}
return vmEntity;
}
@Override
public VirtualMachineEntity createVirtualMachineFromScratch(String id, String owner, String isoId, String hostName, String displayName, String hypervisor, String os, int cpu, int speed, long memory,Long diskSize,
List<String> computeTags, List<String> rootDiskTags, Map<String, NicProfile> networkNicMap, DeploymentPlan plan) throws InsufficientCapacityException {
// VirtualMachineEntityImpl vmEntity = new VirtualMachineEntityImpl(id, owner, hostName, displayName, cpu, speed, memory, computeTags, rootDiskTags, networks, vmEntityManager);
VirtualMachineEntityImpl vmEntity = ComponentContext.inject(VirtualMachineEntityImpl.class);
vmEntity.init(id, owner, hostName, displayName, cpu, speed, memory, computeTags, rootDiskTags, new ArrayList<String>(networkNicMap.keySet()));
//load vm instance and offerings and call virtualMachineManagerImpl
VMInstanceVO vm = _vmDao.findByUuid(id);
Pair<DiskOfferingVO, Long> rootDiskOffering = new Pair<DiskOfferingVO, Long>(null, null);
ServiceOfferingVO offering = _serviceOfferingDao.findById(vm.getServiceOfferingId());
rootDiskOffering.first(offering);
List<Pair<DiskOfferingVO, Long>> dataDiskOfferings = new ArrayList<Pair<DiskOfferingVO, Long>>();
Long diskOfferingId = vm.getDiskOfferingId();
if (diskOfferingId == null) {
@ -251,7 +250,7 @@ public class CloudOrchestrator implements OrchestrationService {
}
rootDiskOffering.first(diskOffering);
rootDiskOffering.second(size);
List<Pair<NetworkVO, NicProfile>> networkIpMap = new ArrayList<Pair<NetworkVO, NicProfile>>();
for (String uuid : networkNicMap.keySet()) {
NetworkVO network = _networkDao.findByUuid(uuid);
@ -259,13 +258,13 @@ public class CloudOrchestrator implements OrchestrationService {
networkIpMap.add(new Pair<NetworkVO, NicProfile>(network, networkNicMap.get(uuid)));
}
}
HypervisorType hypervisorType = HypervisorType.valueOf(hypervisor);
if (_itMgr.allocate(_userVmDao.findById(vm.getId(), true), _templateDao.findById(new Long(isoId)), offering, rootDiskOffering, dataDiskOfferings, networkIpMap, null, plan, hypervisorType, _accountDao.findById(new Long(owner))) == null) {
return null;
}
return vmEntity;
}

View File

@ -0,0 +1,33 @@
<!--
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.
-->
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<artifactId>cloud-plugin-host-anti-affinity</artifactId>
<name>Apache CloudStack Plugin - Host Anti-Affinity Processor</name>
<parent>
<groupId>org.apache.cloudstack</groupId>
<artifactId>cloudstack-plugins</artifactId>
<version>4.2.0-SNAPSHOT</version>
<relativePath>../../pom.xml</relativePath>
</parent>
<build>
<defaultGoal>install</defaultGoal>
<sourceDirectory>src</sourceDirectory>
</build>
</project>

View File

@ -0,0 +1,91 @@
// 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.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.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 AffinityProcessorBase 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());
groupVMIds.remove(vm.getId());
for (Long groupVMId : groupVMIds) {
VMInstanceVO groupVM = _vmInstanceDao.findById(groupVMId);
if (groupVM != null && !groupVM.isRemoved()) {
if (groupVM.getHostId() != null) {
avoid.addHost(groupVM.getHostId());
if (s_logger.isDebugEnabled()) {
s_logger.debug("Added host " + groupVM.getHostId() + " to avoid set, since VM "
+ groupVM.getId() + " is present on the host");
}
} else if (VirtualMachine.State.Stopped.equals(groupVM.getState())
&& groupVM.getLastHostId() != null) {
avoid.addHost(groupVM.getLastHostId());
if (s_logger.isDebugEnabled()) {
s_logger.debug("Added host " + groupVM.getLastHostId() + " to avoid set, since VM "
+ groupVM.getId() + " is present on the host, in Stopped state");
}
}
}
}
}
}
}

View File

@ -36,6 +36,7 @@
<module>api/rate-limit</module>
<module>api/discovery</module>
<module>acl/static-role-based</module>
<module>affinity-group-processors/host-anti-affinity</module>
<module>deployment-planners/user-concentrated-pod</module>
<module>deployment-planners/user-dispersing</module>
<module>host-allocators/random</module>

View File

@ -25,6 +25,9 @@ import java.util.Set;
import javax.annotation.PostConstruct;
import javax.inject.Inject;
import org.apache.cloudstack.affinity.AffinityGroup;
import org.apache.cloudstack.affinity.AffinityGroupResponse;
import org.apache.cloudstack.affinity.dao.AffinityGroupDao;
import org.apache.cloudstack.api.ApiConstants.HostDetails;
import org.apache.cloudstack.api.ApiConstants.VMDetails;
import org.apache.cloudstack.api.response.AccountResponse;
@ -51,6 +54,7 @@ import org.apache.cloudstack.storage.datastore.db.StoragePoolVO;
import org.springframework.stereotype.Component;
import com.cloud.api.query.dao.AccountJoinDao;
import com.cloud.api.query.dao.AffinityGroupJoinDao;
import com.cloud.api.query.dao.AsyncJobJoinDao;
import com.cloud.api.query.dao.DataCenterJoinDao;
import com.cloud.api.query.dao.DiskOfferingJoinDao;
@ -68,6 +72,7 @@ import com.cloud.api.query.dao.UserAccountJoinDao;
import com.cloud.api.query.dao.UserVmJoinDao;
import com.cloud.api.query.dao.VolumeJoinDao;
import com.cloud.api.query.vo.AccountJoinVO;
import com.cloud.api.query.vo.AffinityGroupJoinVO;
import com.cloud.api.query.vo.AsyncJobJoinVO;
import com.cloud.api.query.vo.DataCenterJoinVO;
import com.cloud.api.query.vo.DiskOfferingJoinVO;
@ -285,7 +290,7 @@ public class ApiDBUtils {
static NetworkModel _networkModel;
static NetworkManager _networkMgr;
static TemplateManager _templateMgr;
static StatsCollector _statsCollector;
static AccountDao _accountDao;
@ -380,6 +385,8 @@ public class ApiDBUtils {
static ClusterDetailsDao _clusterDetailsDao;
static NicSecondaryIpDao _nicSecondaryIpDao;
static VpcProvisioningService _vpcProvSvc;
static AffinityGroupDao _affinityGroupDao;
static AffinityGroupJoinDao _affinityGroupJoinDao;
@Inject private ManagementServer ms;
@Inject public AsyncJobManager asyncMgr;
@ -485,6 +492,9 @@ public class ApiDBUtils {
@Inject private NicSecondaryIpDao nicSecondaryIpDao;
@Inject private VpcProvisioningService vpcProvSvc;
@Inject private ApplicationLoadBalancerRuleDao _appLbDao;
@Inject private AffinityGroupDao affinityGroupDao;
@Inject private AffinityGroupJoinDao affinityGroupJoinDao;
@PostConstruct
void init() {
_ms = ms;
@ -587,6 +597,8 @@ public class ApiDBUtils {
_vmSnapshotDao = vmSnapshotDao;
_nicSecondaryIpDao = nicSecondaryIpDao;
_vpcProvSvc = vpcProvSvc;
_affinityGroupDao = affinityGroupDao;
_affinityGroupJoinDao = affinityGroupJoinDao;
// Note: stats collector should already have been initialized by this time, otherwise a null instance is returned
_statsCollector = StatsCollector.getInstance();
}
@ -1581,7 +1593,7 @@ public class ApiDBUtils {
public static DataCenterJoinVO newDataCenterView(DataCenter dc){
return _dcJoinDao.newDataCenterView(dc);
}
public static Map<String, String> findHostDetailsById(long hostId){
return _hostDetailsDao.findDetails(hostId);
}
@ -1589,4 +1601,16 @@ public class ApiDBUtils {
public static List<NicSecondaryIpVO> findNicSecondaryIps(long nicId) {
return _nicSecondaryIpDao.listByNicId(nicId);
}
public static AffinityGroup getAffinityGroup(String groupName, long accountId) {
return _affinityGroupDao.findByAccountAndName(accountId, groupName);
}
public static AffinityGroupResponse newAffinityGroupResponse(AffinityGroupJoinVO group) {
return _affinityGroupJoinDao.newAffinityGroupResponse(group);
}
public static AffinityGroupResponse fillAffinityGroupDetails(AffinityGroupResponse resp, AffinityGroupJoinVO group) {
return _affinityGroupJoinDao.setAffinityGroupResponse(resp, group);
}
}

View File

@ -36,6 +36,8 @@ import javax.inject.Inject;
import org.apache.cloudstack.acl.ControlledEntity;
import org.apache.cloudstack.acl.ControlledEntity.ACLType;
import org.apache.cloudstack.affinity.AffinityGroup;
import org.apache.cloudstack.affinity.AffinityGroupResponse;
import org.apache.cloudstack.api.ApiConstants.HostDetails;
import org.apache.cloudstack.api.ApiConstants.VMDetails;
import org.apache.cloudstack.api.BaseCmd;
@ -445,7 +447,7 @@ public class ApiResponseHelper implements ResponseGenerator {
vmSnapshotResponse.setCreated(vmSnapshot.getCreated());
vmSnapshotResponse.setDescription(vmSnapshot.getDescription());
vmSnapshotResponse.setDisplayName(vmSnapshot.getDisplayName());
UserVm vm = ApiDBUtils.findUserVmById(vmSnapshot.getVmId());
UserVm vm = ApiDBUtils.findUserVmById(vmSnapshot.getVmId());
if(vm!=null)
vmSnapshotResponse.setVirtualMachineid(vm.getUuid());
if(vmSnapshot.getParent() != null)
@ -455,7 +457,7 @@ public class ApiResponseHelper implements ResponseGenerator {
vmSnapshotResponse.setObjectName("vmsnapshot");
return vmSnapshotResponse;
}
@Override
public SnapshotPolicyResponse createSnapshotPolicyResponse(SnapshotPolicy policy) {
SnapshotPolicyResponse policyResponse = new SnapshotPolicyResponse();
@ -552,7 +554,7 @@ public class ApiResponseHelper implements ResponseGenerator {
vlanResponse.setIp6Gateway(vlan.getIp6Gateway());
vlanResponse.setIp6Cidr(vlan.getIp6Cidr());
String ip6Range = vlan.getIp6Range();
if (ip6Range != null) {
String[] range = ip6Range.split("-");
@ -2256,7 +2258,7 @@ public class ApiResponseHelper implements ResponseGenerator {
if (((network.getCidr()) != null) && (network.getNetworkCidr() == null)) {
response.setNetmask(NetUtils.cidr2Netmask(network.getCidr()));
}
response.setIp6Gateway(network.getIp6Gateway());
response.setIp6Cidr(network.getIp6Cidr());
@ -2451,7 +2453,7 @@ public class ApiResponseHelper implements ResponseGenerator {
List<String> cidrs = ApiDBUtils.findFirewallSourceCidrs(fwRule.getId());
response.setCidrList(StringUtils.join(cidrs, ","));
if (fwRule.getTrafficType() == FirewallRule.TrafficType.Ingress) {
IpAddress ip = ApiDBUtils.findIpAddressById(fwRule.getSourceIpAddressId());
response.setPublicIpAddressId(ip.getId());
@ -3483,7 +3485,7 @@ public class ApiResponseHelper implements ResponseGenerator {
return usageRecResponse;
}
public String getDateStringInternal(Date inputDate) {
if (inputDate == null) return null;
@ -3567,7 +3569,7 @@ public class ApiResponseHelper implements ResponseGenerator {
return sb.toString();
}
@Override
public TrafficMonitorResponse createTrafficMonitorResponse(Host trafficMonitor) {
Map<String, String> tmDetails = ApiDBUtils.findHostDetailsById(trafficMonitor.getId());
@ -3627,6 +3629,7 @@ public class ApiResponseHelper implements ResponseGenerator {
response.setIsDefault(result.isDefaultNic());
return response;
}
@Override
public ApplicationLoadBalancerResponse createLoadBalancerContainerReponse(ApplicationLoadBalancerRule lb, Map<Ip, UserVm> lbInstances) {
@ -3693,4 +3696,29 @@ public class ApiResponseHelper implements ResponseGenerator {
lbResponse.setObjectName("loadbalancer");
return lbResponse;
}
@Override
public AffinityGroupResponse createAffinityGroupResponse(AffinityGroup group) {
AffinityGroupResponse response = new AffinityGroupResponse();
Account account = ApiDBUtils.findAccountById(group.getAccountId());
response.setAccountName(account.getAccountName());
response.setName(group.getName());
response.setType(group.getType());
response.setDescription(group.getDescription());
// response.setDomainId(account.)
return response;
}
@Override
public Long getAffinityGroupId(String groupName, long accountId) {
AffinityGroup ag = ApiDBUtils.getAffinityGroup(groupName, accountId);
if (ag == null) {
return null;
} else {
return ag.getId();
}
}
}

View File

@ -27,6 +27,11 @@ import javax.ejb.Local;
import javax.inject.Inject;
import javax.naming.ConfigurationException;
import org.apache.cloudstack.affinity.AffinityGroup;
import org.apache.cloudstack.affinity.AffinityGroupResponse;
import org.apache.cloudstack.affinity.AffinityGroupVMMapVO;
import org.apache.cloudstack.affinity.AffinityGroupVO;
import org.apache.cloudstack.affinity.dao.AffinityGroupVMMapDao;
import org.apache.cloudstack.api.command.admin.host.ListHostsCmd;
import org.apache.cloudstack.api.command.admin.router.ListRoutersCmd;
import org.apache.cloudstack.api.command.admin.storage.ListStoragePoolsCmd;
@ -69,6 +74,7 @@ import org.apache.log4j.Logger;
import org.springframework.stereotype.Component;
import com.cloud.api.query.dao.AccountJoinDao;
import com.cloud.api.query.dao.AffinityGroupJoinDao;
import com.cloud.api.query.dao.AsyncJobJoinDao;
import com.cloud.api.query.dao.DataCenterJoinDao;
import com.cloud.api.query.dao.DiskOfferingJoinDao;
@ -86,6 +92,7 @@ import com.cloud.api.query.dao.UserAccountJoinDao;
import com.cloud.api.query.dao.UserVmJoinDao;
import com.cloud.api.query.dao.VolumeJoinDao;
import com.cloud.api.query.vo.AccountJoinVO;
import com.cloud.api.query.vo.AffinityGroupJoinVO;
import com.cloud.api.query.vo.AsyncJobJoinVO;
import com.cloud.api.query.vo.DataCenterJoinVO;
import com.cloud.api.query.vo.DiskOfferingJoinVO;
@ -138,6 +145,7 @@ import com.cloud.utils.Ternary;
import com.cloud.utils.component.Manager;
import com.cloud.utils.component.ManagerBase;
import com.cloud.utils.db.Filter;
import com.cloud.utils.db.JoinBuilder;
import com.cloud.utils.db.SearchBuilder;
import com.cloud.utils.db.SearchCriteria;
import com.cloud.utils.db.SearchCriteria.Func;
@ -246,6 +254,12 @@ public class QueryManagerImpl extends ManagerBase implements QueryService {
@Inject
private HighAvailabilityManager _haMgr;
@Inject
AffinityGroupVMMapDao _affinityGroupVMMapDao;
@Inject
private AffinityGroupJoinDao _affinityGroupJoinDao;
/* (non-Javadoc)
* @see com.cloud.api.query.QueryService#searchForUsers(org.apache.cloudstack.api.command.admin.user.ListUsersCmd)
*/
@ -2328,5 +2342,99 @@ public class QueryManagerImpl extends ManagerBase implements QueryService {
return false;
}
@Override
public ListResponse<AffinityGroupResponse> listAffinityGroups(Long affinityGroupId, String affinityGroupName,
String affinityGroupType, Long vmId, Long startIndex, Long pageSize) {
Pair<List<AffinityGroupJoinVO>, Integer> result = listAffinityGroupsInternal(affinityGroupId,
affinityGroupName, affinityGroupType, vmId, startIndex, pageSize);
ListResponse<AffinityGroupResponse> response = new ListResponse<AffinityGroupResponse>();
List<AffinityGroupResponse> agResponses = ViewResponseHelper.createAffinityGroupResponses(result.first());
response.setResponses(agResponses, result.second());
return response;
}
public Pair<List<AffinityGroupJoinVO>, Integer> listAffinityGroupsInternal(Long affinityGroupId,
String affinityGroupName, String affinityGroupType, Long vmId, Long startIndex, Long pageSize) {
Account caller = UserContext.current().getCaller();
Long accountId = caller.getAccountId();
Long domainId = caller.getDomainId();
if (vmId != null) {
UserVmVO userVM = _userVmDao.findById(vmId);
if (userVM == null){
throw new InvalidParameterValueException("Unable to list affinity groups for virtual machine instance "
+ vmId + "; instance not found.");
}
_accountMgr.checkAccess(caller, null, true, userVM);
return listAffinityGroupsByVM(vmId.longValue(), startIndex, pageSize);
}
Filter searchFilter = new Filter(AffinityGroupJoinVO.class, "id", true, startIndex, pageSize);
SearchBuilder<AffinityGroupJoinVO> groupSearch = _affinityGroupJoinDao.createSearchBuilder();
groupSearch.select(null, Func.DISTINCT, groupSearch.entity().getId()); // select
// distinct
SearchCriteria<AffinityGroupJoinVO> sc = groupSearch.create();
if (accountId != null) {
sc.addAnd("accountId", SearchCriteria.Op.EQ, accountId);
}
if (domainId != null) {
sc.addAnd("domainId", SearchCriteria.Op.EQ, domainId);
}
if (affinityGroupId != null) {
sc.addAnd("id", SearchCriteria.Op.EQ, affinityGroupId);
}
if (affinityGroupName != null) {
sc.addAnd("name", SearchCriteria.Op.EQ, affinityGroupName);
}
if (affinityGroupType != null) {
sc.addAnd("type", SearchCriteria.Op.EQ, affinityGroupType);
}
Pair<List<AffinityGroupJoinVO>, Integer> uniqueGroupsPair = _affinityGroupJoinDao.searchAndCount(sc,
searchFilter);
// search group details by ids
Integer count = uniqueGroupsPair.second();
if (count.intValue() == 0) {
// empty result
return uniqueGroupsPair;
}
List<AffinityGroupJoinVO> uniqueGroups = uniqueGroupsPair.first();
Long[] vrIds = new Long[uniqueGroups.size()];
int i = 0;
for (AffinityGroupJoinVO v : uniqueGroups) {
vrIds[i++] = v.getId();
}
List<AffinityGroupJoinVO> vrs = _affinityGroupJoinDao.searchByIds(vrIds);
return new Pair<List<AffinityGroupJoinVO>, Integer>(vrs, count);
}
private Pair<List<AffinityGroupJoinVO>, Integer> listAffinityGroupsByVM(long vmId, long pageInd, long pageSize) {
Filter sf = new Filter(SecurityGroupVMMapVO.class, null, true, pageInd, pageSize);
Pair<List<AffinityGroupVMMapVO>, Integer> agVmMappingPair = _affinityGroupVMMapDao.listByInstanceId(vmId, sf);
Integer count = agVmMappingPair.second();
if (count.intValue() == 0) {
// handle empty result cases
return new Pair<List<AffinityGroupJoinVO>, Integer>(new ArrayList<AffinityGroupJoinVO>(), count);
}
List<AffinityGroupVMMapVO> agVmMappings = agVmMappingPair.first();
Long[] agIds = new Long[agVmMappings.size()];
int i = 0;
for (AffinityGroupVMMapVO agVm : agVmMappings) {
agIds[i++] = agVm.getAffinityGroupId();
}
List<AffinityGroupJoinVO> ags = _affinityGroupJoinDao.searchByIds(agIds);
return new Pair<List<AffinityGroupJoinVO>, Integer>(ags, count);
}
}

View File

@ -21,6 +21,7 @@ import java.util.EnumSet;
import java.util.Hashtable;
import java.util.List;
import org.apache.cloudstack.affinity.AffinityGroupResponse;
import org.apache.cloudstack.api.ApiConstants.HostDetails;
import org.apache.cloudstack.api.ApiConstants.VMDetails;
import org.apache.cloudstack.api.response.AccountResponse;
@ -45,6 +46,7 @@ import org.apache.log4j.Logger;
import com.cloud.api.ApiDBUtils;
import com.cloud.api.query.vo.AccountJoinVO;
import com.cloud.api.query.vo.AffinityGroupJoinVO;
import com.cloud.api.query.vo.AsyncJobJoinVO;
import com.cloud.api.query.vo.DataCenterJoinVO;
import com.cloud.api.query.vo.DiskOfferingJoinVO;
@ -123,7 +125,7 @@ public class ViewResponseHelper {
// first time encountering this vm
userVmData = ApiDBUtils.newUserVmResponse(objectName, userVm, details, caller);
} else{
// update nics, securitygroups, tags for 1 to many mapping fields
// update nics, securitygroups, tags, affinitygroups for 1 to many mapping fields
userVmData = ApiDBUtils.fillVmDetails(userVmData, userVm);
}
vmDataList.put(userVm.getId(), userVmData);
@ -303,4 +305,20 @@ public class ViewResponseHelper {
}
return respList;
}
public static List<AffinityGroupResponse> createAffinityGroupResponses(List<AffinityGroupJoinVO> groups) {
Hashtable<Long, AffinityGroupResponse> vrDataList = new Hashtable<Long, AffinityGroupResponse>();
for (AffinityGroupJoinVO vr : groups) {
AffinityGroupResponse vrData = vrDataList.get(vr.getId());
if (vrData == null) {
// first time encountering this AffinityGroup
vrData = ApiDBUtils.newAffinityGroupResponse(vr);
} else {
// update vms
vrData = ApiDBUtils.fillAffinityGroupDetails(vrData, vr);
}
vrDataList.put(vr.getId(), vrData);
}
return new ArrayList<AffinityGroupResponse>(vrDataList.values());
}
}

View File

@ -0,0 +1,37 @@
// 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 com.cloud.api.query.dao;
import java.util.List;
import org.apache.cloudstack.affinity.AffinityGroup;
import org.apache.cloudstack.affinity.AffinityGroupResponse;
import com.cloud.api.query.vo.AffinityGroupJoinVO;
import com.cloud.user.Account;
import com.cloud.utils.db.GenericDao;
public interface AffinityGroupJoinDao extends GenericDao<AffinityGroupJoinVO, Long> {
AffinityGroupResponse newAffinityGroupResponse(AffinityGroupJoinVO vsg);
AffinityGroupResponse setAffinityGroupResponse(AffinityGroupResponse vsgData, AffinityGroupJoinVO vsg);
List<AffinityGroupJoinVO> newAffinityGroupView(AffinityGroup ag);
List<AffinityGroupJoinVO> searchByIds(Long... ids);
}

View File

@ -0,0 +1,142 @@
// 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 com.cloud.api.query.dao;
import java.util.ArrayList;
import java.util.List;
import javax.ejb.Local;
import javax.inject.Inject;
import org.apache.cloudstack.affinity.AffinityGroup;
import org.apache.cloudstack.affinity.AffinityGroupResponse;
import org.apache.log4j.Logger;
import com.cloud.api.ApiResponseHelper;
import com.cloud.api.query.vo.AffinityGroupJoinVO;
import com.cloud.configuration.dao.ConfigurationDao;
import com.cloud.utils.db.GenericDaoBase;
import com.cloud.utils.db.SearchBuilder;
import com.cloud.utils.db.SearchCriteria;
@Local(value = { AffinityGroupJoinDao.class })
public class AffinityGroupJoinDaoImpl extends GenericDaoBase<AffinityGroupJoinVO, Long> implements AffinityGroupJoinDao {
public static final Logger s_logger = Logger.getLogger(AffinityGroupJoinDaoImpl.class);
@Inject
private ConfigurationDao _configDao;
private final SearchBuilder<AffinityGroupJoinVO> agSearch;
private final SearchBuilder<AffinityGroupJoinVO> agIdSearch;
protected AffinityGroupJoinDaoImpl() {
agSearch = createSearchBuilder();
agSearch.and("idIN", agSearch.entity().getId(), SearchCriteria.Op.IN);
agSearch.done();
agIdSearch = createSearchBuilder();
agIdSearch.and("id", agIdSearch.entity().getId(), SearchCriteria.Op.EQ);
agIdSearch.done();
this._count = "select count(distinct id) from affinity_group_view WHERE ";
}
@Override
public AffinityGroupResponse newAffinityGroupResponse(AffinityGroupJoinVO vag) {
AffinityGroupResponse agResponse = new AffinityGroupResponse();
agResponse.setId(vag.getUuid());
agResponse.setName(vag.getName());
agResponse.setDescription(vag.getDescription());
ApiResponseHelper.populateOwner(agResponse, vag);
// update vm information
long instanceId = vag.getVmId();
if (instanceId > 0) {
List<String> vmIdList = new ArrayList<String>();
vmIdList.add(vag.getVmUuid());
agResponse.setVMIdList(vmIdList);
}
agResponse.setObjectName("affinitygroup");
return agResponse;
}
@Override
public AffinityGroupResponse setAffinityGroupResponse(AffinityGroupResponse vagData, AffinityGroupJoinVO vag) {
// update vm information
long instanceId = vag.getVmId();
if (instanceId > 0) {
vagData.addVMId(vag.getVmUuid());
}
return vagData;
}
@Override
public List<AffinityGroupJoinVO> newAffinityGroupView(AffinityGroup ag) {
SearchCriteria<AffinityGroupJoinVO> sc = agIdSearch.create();
sc.setParameters("id", ag.getId());
return searchIncludingRemoved(sc, null, null, false);
}
@Override
public List<AffinityGroupJoinVO> searchByIds(Long... agIds) {
// set detail batch query size
int DETAILS_BATCH_SIZE = 2000;
String batchCfg = _configDao.getValue("detail.batch.query.size");
if ( batchCfg != null ){
DETAILS_BATCH_SIZE = Integer.parseInt(batchCfg);
}
// query details by batches
List<AffinityGroupJoinVO> uvList = new ArrayList<AffinityGroupJoinVO>();
// query details by batches
int curr_index = 0;
if (agIds.length > DETAILS_BATCH_SIZE) {
while ((curr_index + DETAILS_BATCH_SIZE) <= agIds.length) {
Long[] ids = new Long[DETAILS_BATCH_SIZE];
for (int k = 0, j = curr_index; j < curr_index + DETAILS_BATCH_SIZE; j++, k++) {
ids[k] = agIds[j];
}
SearchCriteria<AffinityGroupJoinVO> sc = agSearch.create();
sc.setParameters("idIN", ids);
List<AffinityGroupJoinVO> vms = searchIncludingRemoved(sc, null, null, false);
if (vms != null) {
uvList.addAll(vms);
}
curr_index += DETAILS_BATCH_SIZE;
}
}
if (curr_index < agIds.length) {
int batch_size = (agIds.length - curr_index);
// set the ids value
Long[] ids = new Long[batch_size];
for (int k = 0, j = curr_index; j < curr_index + batch_size; j++, k++) {
ids[k] = agIds[j];
}
SearchCriteria<AffinityGroupJoinVO> sc = agSearch.create();
sc.setParameters("idIN", ids);
List<AffinityGroupJoinVO> vms = searchIncludingRemoved(sc, null, null, false);
if (vms != null) {
uvList.addAll(vms);
}
}
return uvList;
}
}

View File

@ -26,6 +26,7 @@ import java.util.Set;
import javax.ejb.Local;
import javax.inject.Inject;
import org.apache.cloudstack.affinity.AffinityGroupResponse;
import org.apache.cloudstack.api.ApiConstants.VMDetails;
import org.apache.cloudstack.api.response.NicResponse;
import org.apache.cloudstack.api.response.SecurityGroupResponse;
@ -216,6 +217,20 @@ public class UserVmJoinDaoImpl extends GenericDaoBase<UserVmJoinVO, Long> implem
userVmResponse.addTag(ApiDBUtils.newResourceTagResponse(vtag, false));
}
}
if (details.contains(VMDetails.all) || details.contains(VMDetails.affgrp)) {
Long affinityGroupId = userVm.getAffinityGroupId();
if (affinityGroupId != null && affinityGroupId.longValue() != 0) {
AffinityGroupResponse resp = new AffinityGroupResponse();
resp.setId(userVm.getAffinityGroupUuid());
resp.setName(userVm.getAffinityGroupName());
resp.setDescription(userVm.getAffinityGroupDescription());
resp.setObjectName("affinitygroup");
resp.setAccountName(userVm.getAccountName());
userVmResponse.addAffinityGroup(resp);
}
}
userVmResponse.setObjectName(objectName);
return userVmResponse;
@ -276,6 +291,18 @@ public class UserVmJoinDaoImpl extends GenericDaoBase<UserVmJoinVO, Long> implem
userVmData.addTag(ApiDBUtils.newResourceTagResponse(vtag, false));
}
}
Long affinityGroupId = uvo.getAffinityGroupId();
if (affinityGroupId != null && affinityGroupId.longValue() != 0) {
AffinityGroupResponse resp = new AffinityGroupResponse();
resp.setId(uvo.getAffinityGroupUuid());
resp.setName(uvo.getAffinityGroupName());
resp.setDescription(uvo.getAffinityGroupDescription());
resp.setObjectName("affinitygroup");
resp.setAccountName(uvo.getAccountName());
userVmData.addAffinityGroup(resp);
}
return userVmData;
}

View File

@ -0,0 +1,248 @@
// 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 com.cloud.api.query.vo;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.EnumType;
import javax.persistence.Enumerated;
import javax.persistence.Id;
import javax.persistence.Table;
import com.cloud.vm.VirtualMachine;
@Entity
@Table(name = "affinity_group_view")
public class AffinityGroupJoinVO extends BaseViewVO implements ControlledViewEntity {
@Id
@Column(name="id", updatable=false, nullable = false)
private long id;
@Column(name="name")
private String name;
@Column(name = "description")
private String description;
@Column(name = "uuid")
private String uuid;
@Column(name="account_id")
private long accountId;
@Column(name="account_uuid")
private String accountUuid;
@Column(name="account_name")
private String accountName = null;
@Column(name="account_type")
private short accountType;
@Column(name="domain_id")
private long domainId;
@Column(name="domain_uuid")
private String domainUuid;
@Column(name="domain_name")
private String domainName = null;
@Column(name="domain_path")
private String domainPath = null;
@Column(name = "vm_id")
private long vmId;
@Column(name = "vm_uuid")
private String vmUuid;
@Column(name = "vm_name")
private String vmName;
@Column(name = "vm_display_name")
private String vmDisplayName;
@Column(name = "vm_state")
@Enumerated(value = EnumType.STRING)
protected VirtualMachine.State vmState = null;
public AffinityGroupJoinVO() {
}
@Override
public long getId() {
return id;
}
@Override
public void setId(long id) {
this.id = id;
}
@Override
public String getUuid() {
return uuid;
}
public void setUuid(String uuid) {
this.uuid = uuid;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
@Override
public long getAccountId() {
return accountId;
}
public void setAccountId(long accountId) {
this.accountId = accountId;
}
@Override
public String getAccountUuid() {
return accountUuid;
}
public void setAccountUuid(String accountUuid) {
this.accountUuid = accountUuid;
}
@Override
public String getAccountName() {
return accountName;
}
public void setAccountName(String accountName) {
this.accountName = accountName;
}
@Override
public short getAccountType() {
return accountType;
}
public void setAccountType(short accountType) {
this.accountType = accountType;
}
@Override
public long getDomainId() {
return domainId;
}
public void setDomainId(long domainId) {
this.domainId = domainId;
}
@Override
public String getDomainUuid() {
return domainUuid;
}
public void setDomainUuid(String domainUuid) {
this.domainUuid = domainUuid;
}
@Override
public String getDomainName() {
return domainName;
}
public void setDomainName(String domainName) {
this.domainName = domainName;
}
@Override
public String getDomainPath() {
return domainPath;
}
public void setDomainPath(String domainPath) {
this.domainPath = domainPath;
}
public String getDescription() {
return description;
}
public void setDescription(String description) {
this.description = description;
}
public long getVmId() {
return vmId;
}
public void setVmId(long vmId) {
this.vmId = vmId;
}
public String getVmUuid() {
return vmUuid;
}
public void setVmUuid(String vmUuid) {
this.vmUuid = vmUuid;
}
public String getVmName() {
return vmName;
}
public void setVmName(String vmName) {
this.vmName = vmName;
}
public String getVmDisplayName() {
return vmDisplayName;
}
public void setVmDisplayName(String vmDisplayName) {
this.vmDisplayName = vmDisplayName;
}
public VirtualMachine.State getVmState() {
return vmState;
}
public void setVmState(VirtualMachine.State vmState) {
this.vmState = vmState;
}
@Override
public String getProjectUuid() {
// TODO Auto-generated method stub
return null;
}
@Override
public String getProjectName() {
// TODO Auto-generated method stub
return null;
}
}

View File

@ -368,6 +368,18 @@ public class UserVmJoinVO extends BaseViewVO implements ControlledViewEntity {
@Column(name="tag_customer")
private String tagCustomer;
@Column(name = "affinity_group_id")
private long affinityGroupId;
@Column(name = "affinity_group_uuid")
private String affinityGroupUuid;
@Column(name = "affinity_group_name")
private String affinityGroupName;
@Column(name = "affinity_group_description")
private String affinityGroupDescription;
transient String password;
@Transient
@ -1671,4 +1683,29 @@ public class UserVmJoinVO extends BaseViewVO implements ControlledViewEntity {
public void setIp6Cidr(String ip6Cidr) {
this.ip6Cidr = ip6Cidr;
}
public long getAffinityGroupId() {
return affinityGroupId;
}
public String getAffinityGroupUuid() {
return affinityGroupUuid;
}
public String getAffinityGroupName() {
return affinityGroupName;
}
public String getAffinityGroupDescription() {
return affinityGroupDescription;
}
}

View File

@ -78,10 +78,11 @@ public interface ConfigurationManager extends ConfigurationService, Manager {
* TODO
* @param id
* @param useVirtualNetwork
* @param deploymentPlanner
* @return ID
*/
ServiceOfferingVO createServiceOffering(long userId, boolean isSystem, VirtualMachine.Type vm_typeType, String name, int cpu, int ramSize, int speed, String displayText, boolean localStorageRequired,
boolean offerHA, boolean limitResourceUse, boolean volatileVm, String tags, Long domainId, String hostTag, Integer networkRate);
boolean offerHA, boolean limitResourceUse, boolean volatileVm, String tags, Long domainId, String hostTag, Integer networkRate, String deploymentPlanner);
/**
* Creates a new disk offering

View File

@ -1821,16 +1821,16 @@ public class ConfigurationManagerImpl extends ManagerBase implements Configurati
}
return createServiceOffering(userId, cmd.getIsSystem(), vmType, cmd.getServiceOfferingName(), cpuNumber.intValue(), memory.intValue(), cpuSpeed.intValue(), cmd.getDisplayText(),
localStorageRequired, offerHA, limitCpuUse, volatileVm, cmd.getTags(), cmd.getDomainId(), cmd.getHostTag(), cmd.getNetworkRate());
localStorageRequired, offerHA, limitCpuUse, volatileVm, cmd.getTags(), cmd.getDomainId(), cmd.getHostTag(), cmd.getNetworkRate(), cmd.getDeploymentPlanner());
}
@Override
@ActionEvent(eventType = EventTypes.EVENT_SERVICE_OFFERING_CREATE, eventDescription = "creating service offering")
public ServiceOfferingVO createServiceOffering(long userId, boolean isSystem, VirtualMachine.Type vm_type, String name, int cpu, int ramSize, int speed, String displayText,
boolean localStorageRequired, boolean offerHA, boolean limitResourceUse, boolean volatileVm, String tags, Long domainId, String hostTag, Integer networkRate) {
boolean localStorageRequired, boolean offerHA, boolean limitResourceUse, boolean volatileVm, String tags, Long domainId, String hostTag, Integer networkRate, String deploymentPlanner) {
tags = cleanupTags(tags);
ServiceOfferingVO offering = new ServiceOfferingVO(name, cpu, ramSize, speed, networkRate, null, offerHA, limitResourceUse, volatileVm, displayText, localStorageRequired, false, tags, isSystem, vm_type,
domainId, hostTag);
domainId, hostTag, deploymentPlanner);
if ((offering = _serviceOfferingDao.persist(offering)) != null) {
UserContext.current().setEventDetails("Service offering id=" + offering.getId());

View File

@ -0,0 +1,45 @@
// 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 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,96 @@
// Licensed to the Apache Software Foundation (ASF) under one
// or more contributor license agreements. See the NOTICE file
// distributed with this work for additional information
// regarding copyright ownership. The ASF licenses this file
// to you under the Apache License, Version 2.0 (the
// "License"); you may not use this file except in compliance
// with the License. You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing,
// software distributed under the License is distributed on an
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
// KIND, either express or implied. See the License for the
// specific language governing permissions and limitations
// under the License.
package 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

@ -161,38 +161,44 @@ public class FirstFitPlanner extends PlannerBase implements DeploymentPlanner {
+ hostIdSpecified);
}
HostVO host = _hostDao.findById(hostIdSpecified);
if (s_logger.isDebugEnabled()) {
if(host == null){
s_logger.debug("The specified host cannot be found");
}else{
if (host == null) {
s_logger.debug("The specified host cannot be found");
} else if (avoid.shouldAvoid(host)) {
s_logger.debug("The specified host is in avoid set");
} else {
if (s_logger.isDebugEnabled()) {
s_logger.debug("Looking for suitable pools for this host under zone: "+host.getDataCenterId() +", pod: "+ host.getPodId()+", cluster: "+ host.getClusterId());
}
}
//search for storage under the zone, pod, cluster of the host.
DataCenterDeployment lastPlan = new DataCenterDeployment(host.getDataCenterId(), host.getPodId(), host.getClusterId(), hostIdSpecified, plan.getPoolId(), null, plan.getReservationContext());
// search for storage under the zone, pod, cluster of the host.
DataCenterDeployment lastPlan = new DataCenterDeployment(host.getDataCenterId(), host.getPodId(),
host.getClusterId(), hostIdSpecified, plan.getPoolId(), null, plan.getReservationContext());
Pair<Map<Volume, List<StoragePool>>, List<Volume>> result = findSuitablePoolsForVolumes(vmProfile, lastPlan, avoid, HostAllocator.RETURN_UPTO_ALL);
Map<Volume, List<StoragePool>> suitableVolumeStoragePools = result.first();
List<Volume> readyAndReusedVolumes = result.second();
Pair<Map<Volume, List<StoragePool>>, List<Volume>> result = findSuitablePoolsForVolumes(vmProfile,
lastPlan, avoid, HostAllocator.RETURN_UPTO_ALL);
Map<Volume, List<StoragePool>> suitableVolumeStoragePools = result.first();
List<Volume> readyAndReusedVolumes = result.second();
//choose the potential pool for this VM for this host
if(!suitableVolumeStoragePools.isEmpty()){
List<Host> suitableHosts = new ArrayList<Host>();
suitableHosts.add(host);
// choose the potential pool for this VM for this host
if (!suitableVolumeStoragePools.isEmpty()) {
List<Host> suitableHosts = new ArrayList<Host>();
suitableHosts.add(host);
Pair<Host, Map<Volume, StoragePool>> potentialResources = findPotentialDeploymentResources(suitableHosts, suitableVolumeStoragePools);
if(potentialResources != null){
Pod pod = _podDao.findById(host.getPodId());
Cluster cluster = _clusterDao.findById(host.getClusterId());
Map<Volume, StoragePool> storageVolMap = potentialResources.second();
// remove the reused vol<->pool from destination, since we don't have to prepare this volume.
for(Volume vol : readyAndReusedVolumes){
storageVolMap.remove(vol);
Pair<Host, Map<Volume, StoragePool>> potentialResources = findPotentialDeploymentResources(
suitableHosts, suitableVolumeStoragePools);
if (potentialResources != null) {
Pod pod = _podDao.findById(host.getPodId());
Cluster cluster = _clusterDao.findById(host.getClusterId());
Map<Volume, StoragePool> storageVolMap = potentialResources.second();
// remove the reused vol<->pool from destination, since
// we don't have to prepare this volume.
for (Volume vol : readyAndReusedVolumes) {
storageVolMap.remove(vol);
}
DeployDestination dest = new DeployDestination(dc, pod, cluster, host, storageVolMap);
s_logger.debug("Returning Deployment Destination: " + dest);
return dest;
}
DeployDestination dest = new DeployDestination(dc, pod, cluster, host, storageVolMap);
s_logger.debug("Returning Deployment Destination: "+ dest);
return dest;
}
}
s_logger.debug("Cannnot deploy to specified host, returning.");

View File

@ -262,11 +262,14 @@ public class DomainDaoImpl extends GenericDaoBase<DomainVO, Long> implements Dom
public Set<Long> getDomainParentIds(long domainId) {
Set<Long> parentDomains = new HashSet<Long>();
Domain domain = findById(domainId);
parentDomains.add(domain.getId());
while (domain.getParent() != null) {
domain = findById(domain.getParent());
if (domain != null) {
parentDomains.add(domain.getId());
while (domain.getParent() != null) {
domain = findById(domain.getParent());
parentDomains.add(domain.getId());
}
}
return parentDomains;

View File

@ -148,8 +148,6 @@ public class ConfigurationServerImpl extends ManagerBase implements Configuratio
@DB
public void persistDefaultValues() throws InternalErrorException {
fixupScriptFileAttribute();
// Create system user and admin user
saveUser();
@ -701,24 +699,6 @@ public class ConfigurationServerImpl extends ManagerBase implements Configuratio
}
private void fixupScriptFileAttribute() {
// TODO : this is a hacking fix to workaround that executable bit is not preserved in WAR package
String scriptPath = Script.findScript("", "scripts/vm/systemvm/injectkeys.sh");
if(scriptPath != null) {
File file = new File(scriptPath);
if(!file.canExecute()) {
s_logger.info("Some of the shell script files may not have executable bit set. Fixup...");
String cmd = "sudo chmod ugo+x " + scriptPath;
s_logger.info("Executing " + cmd);
String result = Script.runSimpleBashScript(cmd);
if (result != null) {
s_logger.warn("Failed to fixup shell script executable bits " + result);
}
}
}
}
private void updateKeyPairsOnDisk(String homeDir) {
File keyDir = new File(homeDir + "/.ssh");
Boolean devel = Boolean.valueOf(_configDao.getValue("developer"));
@ -749,7 +729,7 @@ public class ConfigurationServerImpl extends ManagerBase implements Configuratio
if (systemVmIsoPath == null) {
throw new CloudRuntimeException("Unable to find systemvm iso vms/systemvm.iso");
}
final Script command = new Script(scriptPath, s_logger);
final Script command = new Script("/bin/bash " + scriptPath, s_logger);
command.add(publicKeyPath);
command.add(privKeyPath);
command.add(systemVmIsoPath);

View File

@ -44,6 +44,8 @@ import javax.naming.ConfigurationException;
import org.apache.cloudstack.acl.ControlledEntity;
import org.apache.cloudstack.acl.SecurityChecker.AccessType;
import org.apache.cloudstack.affinity.AffinityGroupProcessor;
import org.apache.cloudstack.affinity.dao.AffinityGroupVMMapDao;
import org.apache.cloudstack.api.ApiConstants;
import org.apache.cloudstack.api.BaseUpdateTemplateOrIsoCmd;
import org.apache.cloudstack.api.command.admin.account.CreateAccountCmd;
@ -188,6 +190,11 @@ import org.apache.cloudstack.api.command.user.account.ListProjectAccountsCmd;
import org.apache.cloudstack.api.command.user.address.AssociateIPAddrCmd;
import org.apache.cloudstack.api.command.user.address.DisassociateIPAddrCmd;
import org.apache.cloudstack.api.command.user.address.ListPublicIpAddressesCmd;
import org.apache.cloudstack.api.command.user.affinitygroup.CreateAffinityGroupCmd;
import org.apache.cloudstack.api.command.user.affinitygroup.DeleteAffinityGroupCmd;
import org.apache.cloudstack.api.command.user.affinitygroup.ListAffinityGroupTypesCmd;
import org.apache.cloudstack.api.command.user.affinitygroup.ListAffinityGroupsCmd;
import org.apache.cloudstack.api.command.user.affinitygroup.UpdateVMAffinityGroupCmd;
import org.apache.cloudstack.api.command.user.autoscale.CreateAutoScalePolicyCmd;
import org.apache.cloudstack.api.command.user.autoscale.CreateAutoScaleVmGroupCmd;
import org.apache.cloudstack.api.command.user.autoscale.CreateAutoScaleVmProfileCmd;
@ -431,6 +438,7 @@ import com.cloud.dc.dao.HostPodDao;
import com.cloud.dc.dao.PodVlanMapDao;
import com.cloud.dc.dao.VlanDao;
import com.cloud.deploy.DataCenterDeployment;
import com.cloud.deploy.DeploymentPlanner;
import com.cloud.deploy.DeploymentPlanner.ExcludeList;
import com.cloud.domain.DomainVO;
import com.cloud.domain.dao.DomainDao;
@ -687,9 +695,18 @@ public class ManagementServerImpl extends ManagerBase implements ManagementServe
private List<UserAuthenticator> _userAuthenticators;
private List<UserAuthenticator> _userPasswordEncoders;
@Inject
protected List<DeploymentPlanner> _planners;
@Inject ClusterManager _clusterMgr;
private String _hashKey = null;
@Inject
protected AffinityGroupVMMapDao _affinityGroupVMMapDao;
@Inject
protected List<AffinityGroupProcessor> _affinityProcessors;
public ManagementServerImpl() {
setRunLevel(ComponentLifecycle.RUN_LEVEL_APPLICATION_MAINLOOP);
}
@ -1048,6 +1065,15 @@ public class ManagementServerImpl extends ManagerBase implements ManagementServe
ExcludeList excludes = new ExcludeList();
excludes.addHost(srcHostId);
// call affinitygroup chain
long vmGroupCount = _affinityGroupVMMapDao.countAffinityGroupsForVm(vm.getId());
if (vmGroupCount > 0) {
for (AffinityGroupProcessor processor : _affinityProcessors) {
processor.process(vmProfile, plan, excludes);
}
}
for (HostAllocator allocator : _hostAllocators) {
suitableHosts = allocator.allocateTo(vmProfile, plan, Host.Type.Routing, excludes, HostAllocator.RETURN_UPTO_ALL, false);
if (suitableHosts != null && !suitableHosts.isEmpty()) {
@ -2534,6 +2560,11 @@ public class ManagementServerImpl extends ManagerBase implements ManagementServe
cmdList.add(ConfigureInternalLoadBalancerElementCmd.class);
cmdList.add(CreateInternalLoadBalancerElementCmd.class);
cmdList.add(ListInternalLoadBalancerElementsCmd.class);
cmdList.add(CreateAffinityGroupCmd.class);
cmdList.add(DeleteAffinityGroupCmd.class);
cmdList.add(ListAffinityGroupsCmd.class);
cmdList.add(UpdateVMAffinityGroupCmd.class);
cmdList.add(ListAffinityGroupTypesCmd.class);
return cmdList;
}
@ -3599,4 +3630,14 @@ public class ManagementServerImpl extends ManagerBase implements ManagementServe
}
@Override
public List<String> listDeploymentPlanners() {
List<String> plannersAvailable = new ArrayList<String>();
for (DeploymentPlanner planner : _planners) {
plannersAvailable.add(planner.getName());
}
return plannersAvailable;
}
}

View File

@ -34,25 +34,25 @@ import com.cloud.vm.VirtualMachine;
public class ServiceOfferingVO extends DiskOfferingVO implements ServiceOffering {
@Column(name="cpu")
private int cpu;
@Column(name="speed")
private int speed;
@Column(name="ram_size")
private int ramSize;
@Column(name="nw_rate")
private Integer rateMbps;
@Column(name="mc_rate")
private Integer multicastRateMbps;
@Column(name="ha_enabled")
private boolean offerHA;
@Column(name="limit_cpu_use")
private boolean limitCpuUse;
private boolean limitCpuUse;
@Column(name="is_volatile")
private boolean volatileVm;
@ -64,10 +64,13 @@ public class ServiceOfferingVO extends DiskOfferingVO implements ServiceOffering
@Column(name="vm_type")
private String vm_type;
@Column(name="sort_key")
int sortKey;
@Column(name = "deployment_planner")
private String deploymentPlanner = "FirstFitPlanner";
protected ServiceOfferingVO() {
super();
}
@ -80,10 +83,11 @@ public class ServiceOfferingVO extends DiskOfferingVO implements ServiceOffering
this.rateMbps = rateMbps;
this.multicastRateMbps = multicastRateMbps;
this.offerHA = offerHA;
this.limitCpuUse = false;
this.limitCpuUse = false;
this.volatileVm = false;
this.default_use = defaultUse;
this.vm_type = vm_type == null ? null : vm_type.toString().toLowerCase();
this.deploymentPlanner = "FirstFitPlanner";
}
public ServiceOfferingVO(String name, int cpu, int ramSize, int speed, Integer rateMbps, Integer multicastRateMbps, boolean offerHA, boolean limitCpuUse, boolean volatileVm, String displayText, boolean useLocalStorage, boolean recreatable, String tags, boolean systemUse, VirtualMachine.Type vm_type, Long domainId) {
@ -94,39 +98,54 @@ public class ServiceOfferingVO extends DiskOfferingVO implements ServiceOffering
this.rateMbps = rateMbps;
this.multicastRateMbps = multicastRateMbps;
this.offerHA = offerHA;
this.limitCpuUse = limitCpuUse;
this.limitCpuUse = limitCpuUse;
this.volatileVm = volatileVm;
this.vm_type = vm_type == null ? null : vm_type.toString().toLowerCase();
this.deploymentPlanner = "FirstFitPlanner";
}
public ServiceOfferingVO(String name, int cpu, int ramSize, int speed, Integer rateMbps, Integer multicastRateMbps, boolean offerHA, boolean limitResourceUse, boolean volatileVm, String displayText, boolean useLocalStorage, boolean recreatable, String tags, boolean systemUse, VirtualMachine.Type vm_type, Long domainId, String hostTag) {
this(name, cpu, ramSize, speed, rateMbps, multicastRateMbps, offerHA, limitResourceUse, volatileVm, displayText, useLocalStorage, recreatable, tags, systemUse, vm_type, domainId);
this.hostTag = hostTag;
}
this.deploymentPlanner = "FirstFitPlanner";
}
public ServiceOfferingVO(String name, int cpu, int ramSize, int speed, Integer rateMbps, Integer multicastRateMbps,
boolean offerHA, boolean limitResourceUse, boolean volatileVm, String displayText, boolean useLocalStorage,
boolean recreatable, String tags, boolean systemUse, VirtualMachine.Type vm_type, Long domainId,
String hostTag, String deploymentPlanner) {
this(name, cpu, ramSize, speed, rateMbps, multicastRateMbps, offerHA, limitResourceUse, volatileVm,
displayText, useLocalStorage, recreatable, tags, systemUse, vm_type, domainId, hostTag);
if (deploymentPlanner != null) {
this.deploymentPlanner = deploymentPlanner;
} else {
this.deploymentPlanner = "FirstFitPlanner";
}
}
@Override
public boolean getOfferHA() {
return offerHA;
}
public void setOfferHA(boolean offerHA) {
this.offerHA = offerHA;
}
@Override
@Override
public boolean getLimitCpuUse() {
return limitCpuUse;
}
public void setLimitResourceUse(boolean limitCpuUse) {
this.limitCpuUse = limitCpuUse;
}
@Override
@Override
public boolean getDefaultUse() {
return default_use;
}
@Override
@Transient
public String[] getTagsArray() {
@ -134,15 +153,15 @@ public class ServiceOfferingVO extends DiskOfferingVO implements ServiceOffering
if (tags == null || tags.length() == 0) {
return new String[0];
}
return tags.split(",");
}
@Override
public int getCpu() {
return cpu;
}
public void setCpu(int cpu) {
this.cpu = cpu;
}
@ -154,17 +173,17 @@ public class ServiceOfferingVO extends DiskOfferingVO implements ServiceOffering
public void setRamSize(int ramSize) {
this.ramSize = ramSize;
}
@Override
public int getSpeed() {
return speed;
}
@Override
public int getRamSize() {
return ramSize;
}
public void setRateMbps(Integer rateMbps) {
this.rateMbps = rateMbps;
}
@ -177,7 +196,7 @@ public class ServiceOfferingVO extends DiskOfferingVO implements ServiceOffering
public void setMulticastRateMbps(Integer multicastRateMbps) {
this.multicastRateMbps = multicastRateMbps;
}
@Override
public Integer getMulticastRateMbps() {
return multicastRateMbps;
@ -185,12 +204,12 @@ public class ServiceOfferingVO extends DiskOfferingVO implements ServiceOffering
public void setHostTag(String hostTag) {
this.hostTag = hostTag;
}
}
public String getHostTag() {
return hostTag;
}
public String getSystemVmType(){
return vm_type;
}
@ -202,10 +221,14 @@ public class ServiceOfferingVO extends DiskOfferingVO implements ServiceOffering
public int getSortKey() {
return sortKey;
}
@Override
public boolean getVolatileVm() {
return volatileVm;
}
public String getDeploymentPlanner() {
return deploymentPlanner;
}
}

View File

@ -42,6 +42,7 @@ import org.apache.cloudstack.acl.ControlledEntity;
import org.apache.cloudstack.acl.RoleType;
import org.apache.cloudstack.acl.SecurityChecker;
import org.apache.cloudstack.acl.SecurityChecker.AccessType;
import org.apache.cloudstack.affinity.dao.AffinityGroupDao;
import org.apache.cloudstack.api.command.admin.account.UpdateAccountCmd;
import org.apache.cloudstack.api.command.admin.user.DeleteUserCmd;
import org.apache.cloudstack.api.command.admin.user.RegisterCmd;
@ -220,6 +221,8 @@ public class AccountManagerImpl extends ManagerBase implements AccountManager, M
@Inject
private AutoScaleManager _autoscaleMgr;
@Inject VolumeManager volumeMgr;
@Inject
private AffinityGroupDao _affinityGroupDao;
private List<UserAuthenticator> _userAuthenticators;
List<UserAuthenticator> _userPasswordEncoders;
@ -238,7 +241,7 @@ public class AccountManagerImpl extends ManagerBase implements AccountManager, M
public List<UserAuthenticator> getUserAuthenticators() {
return _userAuthenticators;
}
public void setUserAuthenticators(List<UserAuthenticator> authenticators) {
_userAuthenticators = authenticators;
}
@ -623,6 +626,10 @@ public class AccountManagerImpl extends ManagerBase implements AccountManager, M
int numRemoved = _securityGroupDao.removeByAccountId(accountId);
s_logger.info("deleteAccount: Deleted " + numRemoved + " network groups for account " + accountId);
// Cleanup affinity groups
int numAGRemoved = _affinityGroupDao.removeByAccountId(accountId);
s_logger.info("deleteAccount: Deleted " + numAGRemoved + " affinity groups for account " + accountId);
// Delete all the networks
boolean networksDeleted = true;
s_logger.debug("Deleting networks for account " + account.getId());

View File

@ -35,6 +35,9 @@ import javax.naming.ConfigurationException;
import com.cloud.api.ApiDBUtils;
import org.apache.cloudstack.acl.ControlledEntity.ACLType;
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.RecoverVMCmd;
import org.apache.cloudstack.api.command.user.vm.*;
@ -369,7 +372,7 @@ public class UserVmManagerImpl extends ManagerBase implements UserVmManager, Use
VpcManager _vpcMgr;
@Inject
TemplateManager templateMgr;
@Inject
@Inject
protected GuestOSCategoryDao _guestOSCategoryDao;
@Inject
UsageEventDao _usageEventDao;
@ -378,6 +381,11 @@ public class UserVmManagerImpl extends ManagerBase implements UserVmManager, Use
@Inject
protected VMSnapshotManager _vmSnapshotMgr;
@Inject
AffinityGroupVMMapDao _affinityGroupVMMapDao;
@Inject
AffinityGroupDao _affinityGroupDao;
@Inject
List<DeployPlannerSelector> plannerSelectors;
@ -684,7 +692,7 @@ public class UserVmManagerImpl extends ManagerBase implements UserVmManager, Use
try {
VirtualMachineEntity vmEntity = _orchSrvc.getVirtualMachine(vm.getUuid());
status = vmEntity.stop(new Long(userId).toString());
status = vmEntity.stop(new Long(userId).toString());
} catch (ResourceUnavailableException e) {
s_logger.debug("Unable to stop due to ", e);
status = false;
@ -1916,7 +1924,10 @@ public class UserVmManagerImpl extends ManagerBase implements UserVmManager, Use
@Override
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 {
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,
diskSize, networkList, securityGroupIdList, group, userData, sshKeyPair, hypervisor, caller, requestedIps, defaultIps, keyboard);
diskSize, networkList, securityGroupIdList, group, userData, sshKeyPair, hypervisor, caller,
requestedIps, defaultIps, keyboard, affinityGroupIdList);
}
@Override
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,
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 {
Account caller = UserContext.current().getCaller();
@ -2018,7 +2033,7 @@ public class UserVmManagerImpl extends ManagerBase implements UserVmManager, Use
isSecurityGroupEnabledNetworkUsed = true;
} 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) {
NetworkVO network = _networkDao.findById(networkId);
@ -2034,7 +2049,7 @@ public class UserVmManagerImpl extends ManagerBase implements UserVmManager, Use
}
isSecurityGroupEnabledNetworkUsed = true;
}
}
if (!(network.getTrafficType() == TrafficType.Guest && network.getGuestType() == Network.GuestType.Shared)) {
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,
diskSize, networkList, securityGroupIdList, group, userData, sshKeyPair, hypervisor, caller, requestedIps, defaultIps, keyboard);
diskSize, networkList, securityGroupIdList, group, userData, sshKeyPair, hypervisor, caller,
requestedIps, defaultIps, keyboard, affinityGroupIdList);
}
@Override
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 {
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)
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 {
_accountMgr.checkAccess(caller, null, true, owner);
@ -2261,6 +2283,19 @@ public class UserVmManagerImpl extends ManagerBase implements UserVmManager, Use
}
}
// check that the affinity groups exist
if (affinityGroupIdList != null) {
for (Long affinityGroupId : affinityGroupIdList) {
AffinityGroupVO ag = _affinityGroupDao.findById(affinityGroupId);
if (ag == null) {
throw new InvalidParameterValueException("Unable to find affinity group by id " + affinityGroupId);
} else {
// verify permissions
_accountMgr.checkAccess(caller, null, true, owner, ag);
}
}
}
if (template.getHypervisorType() != null && template.getHypervisorType() != HypervisorType.BareMetal) {
// check if we have available pools for vm deployment
long availablePools = _storagePoolDao.countPoolsByStatus(StoragePoolStatus.Up);
@ -2438,7 +2473,7 @@ public class UserVmManagerImpl extends ManagerBase implements UserVmManager, Use
// * verify that there are no duplicates
if (hostNames.contains(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));
}
}
@ -2510,7 +2545,7 @@ public class UserVmManagerImpl extends ManagerBase implements UserVmManager, Use
List<String> computeTags = new ArrayList<String>();
computeTags.add(offering.getHostTag());
List<String> rootDiskTags = new ArrayList<String>();
List<String> rootDiskTags = new ArrayList<String>();
rootDiskTags.add(offering.getTags());
if(isIso){
@ -2552,6 +2587,10 @@ public class UserVmManagerImpl extends ManagerBase implements UserVmManager, Use
_securityGroupMgr.addInstanceToGroups(vm.getId(), securityGroupIdList);
if (affinityGroupIdList != null && !affinityGroupIdList.isEmpty()) {
_affinityGroupVMMapDao.updateMap(vm.getId(), affinityGroupIdList);
}
return vm;
}
@ -2829,7 +2868,7 @@ public class UserVmManagerImpl extends ManagerBase implements UserVmManager, Use
try {
VirtualMachineEntity vmEntity = _orchSrvc.getVirtualMachine(vm.getUuid());
vmEntity.stop(new Long(userId).toString());
vmEntity.stop(new Long(userId).toString());
} catch (ResourceUnavailableException e) {
throw new CloudRuntimeException(
"Unable to contact the agent to stop the virtual machine "
@ -3044,7 +3083,7 @@ public class UserVmManagerImpl extends ManagerBase implements UserVmManager, Use
try {
VirtualMachineEntity vmEntity = _orchSrvc.getVirtualMachine(vm.getUuid());
status = vmEntity.destroy(new Long(userId).toString());
status = vmEntity.destroy(new Long(userId).toString());
} catch (CloudException e) {
CloudRuntimeException ex = new CloudRuntimeException(
"Unable to destroy with specified vmId", e);

View File

@ -5,7 +5,7 @@
// 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,
@ -68,7 +68,9 @@ import com.cloud.deploy.DeployDestination;
import com.cloud.deploy.DeploymentPlan;
import com.cloud.deploy.DeploymentPlanner;
import com.cloud.deploy.DeploymentPlanner.ExcludeList;
import com.cloud.deploy.DeploymentPlanningManager;
import com.cloud.domain.dao.DomainDao;
import com.cloud.exception.AffinityConflictException;
import com.cloud.exception.AgentUnavailableException;
import com.cloud.exception.ConcurrentOperationException;
import com.cloud.exception.ConnectionException;
@ -226,8 +228,8 @@ public class VirtualMachineManagerImpl extends ManagerBase implements VirtualMac
@Inject
protected ResourceManager _resourceMgr;
@Inject
@Inject
protected VMSnapshotManager _vmSnapshotMgr = null;
@Inject
protected ClusterDetailsDao _clusterDetailsDao;
@ -239,6 +241,9 @@ public class VirtualMachineManagerImpl extends ManagerBase implements VirtualMac
@Inject
VolumeManager volumeMgr;
@Inject
DeploymentPlanningManager _dpMgr;
Map<VirtualMachine.Type, VirtualMachineGuru<? extends VMInstanceVO>> _vmGurus = new HashMap<VirtualMachine.Type, VirtualMachineGuru<? extends VMInstanceVO>>();
protected StateMachine2<State, VirtualMachine.Event, VirtualMachine> _stateMachine;
@ -586,7 +591,7 @@ public class VirtualMachineManagerImpl extends ManagerBase implements VirtualMac
ConcurrentOperationException, ResourceUnavailableException {
return advanceStart(vm, params, caller, account, null);
}
@Override
public <T extends VMInstanceVO> T advanceStart(T vm, Map<VirtualMachineProfile.Param, Object> params, User caller, Account account, DeploymentPlan planToDeploy)
throws InsufficientCapacityException, ConcurrentOperationException, ResourceUnavailableException {
@ -695,17 +700,13 @@ public class VirtualMachineManagerImpl extends ManagerBase implements VirtualMac
VirtualMachineProfileImpl<T> vmProfile = new VirtualMachineProfileImpl<T>(vm, template, offering, account, params);
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());
journal.record("Deployment found ", vmProfile, dest);
break;
}
try {
dest = _dpMgr.planDeployment(vmProfile, plan, avoids);
} catch (AffinityConflictException e2) {
s_logger.warn("Unable to create deployment, affinity rules associted to the VM conflict", e2);
throw new CloudRuntimeException(
"Unable to create deployment, affinity rules associted to the VM conflict");
}
if (dest == null) {
@ -719,6 +720,11 @@ public class VirtualMachineManagerImpl extends ManagerBase implements VirtualMac
throw new InsufficientServerCapacityException("Unable to create a deployment for " + vmProfile, DataCenter.class, plan.getDataCenterId());
}
if (dest != null) {
avoids.addHost(dest.getHost().getId());
journal.record("Deployment found ", vmProfile, dest);
}
long destHostId = dest.getHost().getId();
vm.setPodId(dest.getPod().getId());
Long cluster_id = dest.getCluster().getId();
@ -739,7 +745,7 @@ public class VirtualMachineManagerImpl extends ManagerBase implements VirtualMac
if (s_logger.isDebugEnabled()) {
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) {
this.volumeMgr.prepare(vmProfile, dest);
}
@ -797,7 +803,7 @@ public class VirtualMachineManagerImpl extends ManagerBase implements VirtualMac
StopCommand cmd = new StopCommand(vm);
StopAnswer answer = (StopAnswer) _agentMgr.easySend(destHostId, cmd);
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);
throw new ExecutionException("Unable to stop " + vm + " so we are unable to retry the start operation");
}
@ -1144,7 +1150,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");
return false;
}
State oldState = vm.getState();
if (oldState == State.Starting) {
if (e == Event.OperationSucceeded) {
@ -1179,12 +1185,12 @@ public class VirtualMachineManagerImpl extends ManagerBase implements VirtualMac
s_logger.debug("Unable to stop " + vm);
return false;
}
if (!_vmSnapshotMgr.deleteAllVMSnapshots(vm.getId(),null)){
s_logger.debug("Unable to delete all snapshots for " + vm);
return false;
}
try {
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);
@ -1487,25 +1493,23 @@ public class VirtualMachineManagerImpl extends ManagerBase implements VirtualMac
DeployDestination dest = null;
while (true) {
for (DeploymentPlanner planner : _planners) {
if (planner.canHandle(profile, plan, excludes)) {
dest = planner.plan(profile, plan, excludes);
} else {
continue;
}
if (dest != null) {
if (s_logger.isDebugEnabled()) {
s_logger.debug("Planner " + planner + " found " + dest + " for migrating to.");
}
break;
}
if (s_logger.isDebugEnabled()) {
s_logger.debug("Planner " + planner + " was unable to find anything.");
}
try {
dest = _dpMgr.planDeployment(profile, plan, excludes);
} catch (AffinityConflictException e2) {
s_logger.warn("Unable to create deployment, affinity rules associted to the VM conflict", e2);
throw new CloudRuntimeException(
"Unable to create deployment, affinity rules associted to the VM conflict");
}
if (dest == null) {
if (dest != null) {
if (s_logger.isDebugEnabled()) {
s_logger.debug("Found destination " + dest + " for migrating to.");
}
} else {
if (s_logger.isDebugEnabled()) {
s_logger.debug("Unable to find destination for migrating the vm " + profile);
}
throw new InsufficientServerCapacityException("Unable to find a server to migrate to.", host.getClusterId());
}
@ -1559,7 +1563,7 @@ public class VirtualMachineManagerImpl extends ManagerBase implements VirtualMac
@Override
public boolean isVirtualMachineUpgradable(VirtualMachine vm, ServiceOffering offering) {
boolean isMachineUpgradable = true;
boolean isMachineUpgradable = true;
for(HostAllocator allocator : _hostAllocators) {
isMachineUpgradable = allocator.isVirtualMachineUpgradable(vm, offering);
if(isMachineUpgradable)
@ -1628,7 +1632,7 @@ public class VirtualMachineManagerImpl extends ManagerBase implements VirtualMac
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);
Map<Long, AgentVmInfo> infos = convertToInfos(startup);
@ -1637,7 +1641,7 @@ public class VirtualMachineManagerImpl extends ManagerBase implements VirtualMac
s_logger.debug("Found " + vms.size() + " VMs for host " + hostId);
for (VMInstanceVO vm : vms) {
AgentVmInfo info = infos.remove(vm.getId());
// sync VM Snapshots related transient states
List<VMSnapshotVO> vmSnapshotsInTrasientStates = _vmSnapshotDao.listByInstanceId(vm.getId(), VMSnapshot.State.Expunging,VMSnapshot.State.Reverting, VMSnapshot.State.Creating);
if(vmSnapshotsInTrasientStates.size() > 1){
@ -1649,11 +1653,11 @@ public class VirtualMachineManagerImpl extends ManagerBase implements VirtualMac
s_logger.info("Successfully sync VM with transient snapshot: " + vm.getInstanceName());
}
}
VMInstanceVO castedVm = null;
if (info == null) {
info = new AgentVmInfo(vm.getInstanceName(), getVmGuru(vm), vm, State.Stopped);
}
}
castedVm = info.guru.findById(vm.getId());
HypervisorGuru hvGuru = _hvGuruMgr.getGuru(castedVm.getHypervisorType());
@ -1767,7 +1771,7 @@ public class VirtualMachineManagerImpl extends ManagerBase implements VirtualMac
for (VMInstanceVO vm : set_vms) {
AgentVmInfo info = infos.remove(vm.getId());
VMInstanceVO castedVm = null;
// sync VM Snapshots related transient states
List<VMSnapshotVO> vmSnapshotsInExpungingStates = _vmSnapshotDao.listByInstanceId(vm.getId(), VMSnapshot.State.Expunging, VMSnapshot.State.Creating,VMSnapshot.State.Reverting);
if(vmSnapshotsInExpungingStates.size() > 0){
@ -1785,9 +1789,9 @@ public class VirtualMachineManagerImpl extends ManagerBase implements VirtualMac
s_logger.info("Successfully sync VM with transient snapshot: " + vm.getInstanceName());
}
}
if ((info == null && (vm.getState() == State.Running || vm.getState() == State.Starting ))
|| (info != null && (info.state == 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)))
{
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);
@ -1925,7 +1929,7 @@ public class VirtualMachineManagerImpl extends ManagerBase implements VirtualMac
return map;
}
protected Map<Long, AgentVmInfo> convertToInfos(StartupRoutingCommand cmd) {
protected Map<Long, AgentVmInfo> convertToInfos(StartupRoutingCommand cmd) {
final Map<String, VmState> states = cmd.getVmStates();
final HashMap<Long, AgentVmInfo> map = new HashMap<Long, AgentVmInfo>();
if (states == null) {
@ -1989,7 +1993,7 @@ public class VirtualMachineManagerImpl extends ManagerBase implements VirtualMac
* compareState does as its name suggests and compares the states between
* management server and agent. It returns whether something should be
* cleaned up
*
*
*/
protected Command compareState(long hostId, VMInstanceVO vm, final AgentVmInfo info, final boolean fullSync, boolean trackExternalChange) {
State agentState = info.state;
@ -2192,7 +2196,7 @@ public class VirtualMachineManagerImpl extends ManagerBase implements VirtualMac
List<NicVO> nics = _nicsDao.listByVmId(profile.getId());
for (NicVO nic : nics) {
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));
profile.addNic(nicProfile);
}
@ -2319,7 +2323,7 @@ public class VirtualMachineManagerImpl extends ManagerBase implements VirtualMac
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;
Commands commands = fullHostSync(agentId, startup);
@ -2492,7 +2496,7 @@ public class VirtualMachineManagerImpl extends ManagerBase implements VirtualMac
}
@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 {
s_logger.debug("Adding vm " + vm + " to network " + network + "; requested nic profile " + requested);
@ -2502,14 +2506,14 @@ public class VirtualMachineManagerImpl extends ManagerBase implements VirtualMac
} else {
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));
VirtualMachineProfileImpl<VMInstanceVO> vmProfile = new VirtualMachineProfileImpl<VMInstanceVO>(vmVO, null,
VirtualMachineProfileImpl<VMInstanceVO> vmProfile = new VirtualMachineProfileImpl<VMInstanceVO>(vmVO, null,
null, null, null);
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);
//check vm state
@ -2557,14 +2561,14 @@ public class VirtualMachineManagerImpl extends ManagerBase implements VirtualMac
public boolean removeNicFromVm(VirtualMachine vm, NicVO nic) throws ConcurrentOperationException, ResourceUnavailableException {
VMInstanceVO vmVO = _vmDao.findById(vm.getId());
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));
VirtualMachineProfileImpl<VMInstanceVO> vmProfile = new VirtualMachineProfileImpl<VMInstanceVO>(vmVO, null,
VirtualMachineProfileImpl<VMInstanceVO> vmProfile = new VirtualMachineProfileImpl<VMInstanceVO>(vmVO, null,
null, null, null);
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);
VirtualMachineGuru<VMInstanceVO> vmGuru = getVmGuru(vmVO);
HypervisorGuru hvGuru = _hvGuruMgr.getGuru(vmProfile.getVirtualMachine().getHypervisorType());
@ -2576,9 +2580,9 @@ public class VirtualMachineManagerImpl extends ManagerBase implements VirtualMac
throw new CloudRuntimeException("Failed to remove nic from " + vm + " in " + network + ", nic is default.");
}
NicProfile nicProfile = new NicProfile(nic, network, nic.getBroadcastUri(), nic.getIsolationUri(),
_networkModel.getNetworkRate(network.getId(), vm.getId()),
_networkModel.isSecurityGroupSupportedInNetwork(network),
NicProfile nicProfile = new NicProfile(nic, network, nic.getBroadcastUri(), nic.getIsolationUri(),
_networkModel.getNetworkRate(network.getId(), vm.getId()),
_networkModel.isSecurityGroupSupportedInNetwork(network),
_networkModel.getNetworkTag(vmProfile.getVirtualMachine().getHypervisorType(), network));
//1) Unplug the nic
@ -2611,14 +2615,14 @@ public class VirtualMachineManagerImpl extends ManagerBase implements VirtualMac
@Override
public boolean removeVmFromNetwork(VirtualMachine vm, Network network, URI broadcastUri) throws ConcurrentOperationException, ResourceUnavailableException {
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));
VirtualMachineProfileImpl<VMInstanceVO> vmProfile = new VirtualMachineProfileImpl<VMInstanceVO>(vmVO, null,
VirtualMachineProfileImpl<VMInstanceVO> vmProfile = new VirtualMachineProfileImpl<VMInstanceVO>(vmVO, null,
null, null, null);
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);
VirtualMachineGuru<VMInstanceVO> vmGuru = getVmGuru(vmVO);
HypervisorGuru hvGuru = _hvGuruMgr.getGuru(vmProfile.getVirtualMachine().getHypervisorType());
@ -2643,9 +2647,9 @@ public class VirtualMachineManagerImpl extends ManagerBase implements VirtualMac
throw new CloudRuntimeException("Failed to remove nic from " + vm + " in " + network + ", nic is default.");
}
NicProfile nicProfile = new NicProfile(nic, network, nic.getBroadcastUri(), nic.getIsolationUri(),
_networkModel.getNetworkRate(network.getId(), vm.getId()),
_networkModel.isSecurityGroupSupportedInNetwork(network),
NicProfile nicProfile = new NicProfile(nic, network, nic.getBroadcastUri(), nic.getIsolationUri(),
_networkModel.getNetworkRate(network.getId(), vm.getId()),
_networkModel.isSecurityGroupSupportedInNetwork(network),
_networkModel.getNetworkTag(vmProfile.getVirtualMachine().getHypervisorType(), network));
//1) Unplug the nic

View File

@ -0,0 +1,346 @@
// 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.affinity;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import javax.ejb.Local;
import javax.inject.Inject;
import javax.naming.ConfigurationException;
import org.apache.cloudstack.affinity.dao.AffinityGroupDao;
import org.apache.cloudstack.affinity.dao.AffinityGroupVMMapDao;
import org.apache.log4j.Logger;
import org.springframework.context.annotation.Primary;
import com.cloud.deploy.DeploymentPlanner;
import com.cloud.event.ActionEvent;
import com.cloud.event.EventTypes;
import com.cloud.exception.InvalidParameterValueException;
import com.cloud.exception.ResourceInUseException;
import com.cloud.network.security.SecurityGroup;
import com.cloud.user.Account;
import com.cloud.user.AccountManager;
import com.cloud.user.UserContext;
import com.cloud.uservm.UserVm;
import com.cloud.utils.Pair;
import com.cloud.utils.component.ComponentContext;
import com.cloud.utils.component.Manager;
import com.cloud.utils.component.ManagerBase;
import com.cloud.utils.db.DB;
import com.cloud.utils.db.Filter;
import com.cloud.utils.db.JoinBuilder;
import com.cloud.utils.db.SearchBuilder;
import com.cloud.utils.db.SearchCriteria;
import com.cloud.utils.db.Transaction;
import com.cloud.utils.exception.CloudRuntimeException;
import com.cloud.utils.fsm.StateListener;
import com.cloud.vm.UserVmVO;
import com.cloud.vm.VirtualMachine;
import com.cloud.vm.VirtualMachine.Event;
import com.cloud.vm.VirtualMachine.State;
import com.cloud.vm.dao.UserVmDao;
@Local(value = { AffinityGroupService.class })
public class AffinityGroupServiceImpl extends ManagerBase implements AffinityGroupService, Manager,
StateListener<State, VirtualMachine.Event, VirtualMachine> {
public static final Logger s_logger = Logger.getLogger(AffinityGroupServiceImpl.class);
private String _name;
@Inject
AccountManager _accountMgr;
@Inject
AffinityGroupDao _affinityGroupDao;
@Inject
AffinityGroupVMMapDao _affinityGroupVMMapDao;
@Inject
private UserVmDao _userVmDao;
@Override
@ActionEvent(eventType = EventTypes.EVENT_AFFINITY_GROUP_CREATE, eventDescription = "Creating Affinity Group", create = true)
public AffinityGroup createAffinityGroup(String account, Long domainId, String affinityGroupName,
String affinityGroupType, String description) {
Account caller = UserContext.current().getCaller();
Account owner = _accountMgr.finalizeOwner(caller, account, domainId, null);
if (_affinityGroupDao.isNameInUse(owner.getAccountId(), owner.getDomainId(), affinityGroupName)) {
throw new InvalidParameterValueException("Unable to create affinity group, a group with name "
+ affinityGroupName
+ " already exisits.");
}
//validate the affinityGroupType
Map<String, AffinityGroupProcessor> typeProcessorMap = getAffinityTypeToProcessorMap();
if (typeProcessorMap != null && !typeProcessorMap.isEmpty()) {
if (!typeProcessorMap.containsKey(affinityGroupType)) {
throw new InvalidParameterValueException("Unable to create affinity group, invalid affinity group type"
+ affinityGroupType);
}
} else {
throw new InvalidParameterValueException(
"Unable to create affinity group, no Affinity Group Types configured");
}
if (domainId == null) {
domainId = owner.getDomainId();
}
AffinityGroupVO group = new AffinityGroupVO(affinityGroupName, affinityGroupType, description, domainId,
owner.getId());
_affinityGroupDao.persist(group);
if (s_logger.isDebugEnabled()) {
s_logger.debug("Created affinity group =" + affinityGroupName);
}
return group;
}
@DB
@Override
@ActionEvent(eventType = EventTypes.EVENT_AFFINITY_GROUP_DELETE, eventDescription = "Deleting affinity group")
public boolean deleteAffinityGroup(Long affinityGroupId, String account, Long domainId, String affinityGroupName)
throws ResourceInUseException {
Account caller = UserContext.current().getCaller();
Account owner = _accountMgr.finalizeOwner(caller, account, domainId, null);
AffinityGroupVO group = null;
if (affinityGroupId != null) {
group = _affinityGroupDao.findById(affinityGroupId);
if (group == null) {
throw new InvalidParameterValueException("Unable to find affinity group: " + affinityGroupId
+ "; failed to delete group.");
}
} else if (affinityGroupName != null) {
group = _affinityGroupDao.findByAccountAndName(owner.getAccountId(), affinityGroupName);
if (group == null) {
throw new InvalidParameterValueException("Unable to find affinity group: " + affinityGroupName
+ "; failed to delete group.");
}
} else {
throw new InvalidParameterValueException(
"Either the affinity group Id or group name must be specified to delete the group");
}
if (affinityGroupId == null) {
affinityGroupId = group.getId();
}
// check permissions
_accountMgr.checkAccess(caller, null, true, group);
final Transaction txn = Transaction.currentTxn();
txn.start();
group = _affinityGroupDao.lockRow(affinityGroupId, true);
if (group == null) {
throw new InvalidParameterValueException("Unable to find affinity group by id " + affinityGroupId);
}
List<AffinityGroupVMMapVO> affinityGroupVmMap = _affinityGroupVMMapDao.listByAffinityGroup(affinityGroupId);
if (!affinityGroupVmMap.isEmpty()) {
throw new ResourceInUseException("Cannot delete affinity group when it's in use by virtual machines");
}
_affinityGroupDao.expunge(affinityGroupId);
txn.commit();
if (s_logger.isDebugEnabled()) {
s_logger.debug("Deleted affinity group id=" + affinityGroupId);
}
return true;
}
@Override
public Pair<List<? extends AffinityGroup>, Integer> listAffinityGroups(Long affinityGroupId, String affinityGroupName, String affinityGroupType, Long vmId, Long startIndex, Long pageSize) {
Filter searchFilter = new Filter(AffinityGroupVO.class, "id", Boolean.TRUE, startIndex, pageSize);
Account caller = UserContext.current().getCaller();
Long accountId = caller.getAccountId();
Long domainId = caller.getDomainId();
SearchBuilder<AffinityGroupVMMapVO> vmInstanceSearch = _affinityGroupVMMapDao.createSearchBuilder();
vmInstanceSearch.and("instanceId", vmInstanceSearch.entity().getInstanceId(), SearchCriteria.Op.EQ);
SearchBuilder<AffinityGroupVO> groupSearch = _affinityGroupDao.createSearchBuilder();
SearchCriteria<AffinityGroupVO> sc = groupSearch.create();
if (accountId != null) {
sc.addAnd("accountId", SearchCriteria.Op.EQ, accountId);
}
if (domainId != null) {
sc.addAnd("domainId", SearchCriteria.Op.EQ, domainId);
}
if (affinityGroupId != null) {
sc.addAnd("id", SearchCriteria.Op.EQ, affinityGroupId);
}
if (affinityGroupName != null) {
sc.addAnd("name", SearchCriteria.Op.EQ, affinityGroupName);
}
if (affinityGroupType != null) {
sc.addAnd("type", SearchCriteria.Op.EQ, affinityGroupType);
}
if (vmId != null) {
UserVmVO userVM = _userVmDao.findById(vmId);
if (userVM == null) {
throw new InvalidParameterValueException("Unable to list affinity groups for virtual machine instance "
+ vmId + "; instance not found.");
}
_accountMgr.checkAccess(caller, null, true, userVM);
// add join to affinity_groups_vm_map
groupSearch.join("vmInstanceSearch", vmInstanceSearch, groupSearch.entity().getId(), vmInstanceSearch
.entity().getAffinityGroupId(), JoinBuilder.JoinType.INNER);
sc.setJoinParameters("vmInstanceSearch", "instanceId", vmId);
}
Pair<List<AffinityGroupVO>, Integer> result = _affinityGroupDao.searchAndCount(sc, searchFilter);
return new Pair<List<? extends AffinityGroup>, Integer>(result.first(), result.second());
}
@Override
public List<String> listAffinityGroupTypes() {
List<String> types = new ArrayList<String>();
Map<String, AffinityGroupProcessor> componentMap = ComponentContext.getComponentsOfType(AffinityGroupProcessor.class);
if (componentMap.size() > 0) {
for (Entry<String, AffinityGroupProcessor> entry : componentMap.entrySet()) {
types.add(entry.getValue().getType());
}
}
return types;
}
protected Map<String, AffinityGroupProcessor> getAffinityTypeToProcessorMap() {
Map<String, AffinityGroupProcessor> typeProcessorMap = new HashMap<String, AffinityGroupProcessor>();
Map<String, AffinityGroupProcessor> componentMap = ComponentContext
.getComponentsOfType(AffinityGroupProcessor.class);
if (componentMap.size() > 0) {
for (Entry<String, AffinityGroupProcessor> entry : componentMap.entrySet()) {
typeProcessorMap.put(entry.getValue().getType(), entry.getValue());
}
}
return typeProcessorMap;
}
@Override
public boolean configure(final String name, final Map<String, Object> params) throws ConfigurationException {
_name = name;
VirtualMachine.State.getStateMachine().registerListener(this);
return true;
}
@Override
public boolean start() {
return true;
}
@Override
public boolean stop() {
return true;
}
@Override
public String getName() {
return _name;
}
@Override
public AffinityGroup getAffinityGroup(Long 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 associations of 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.");
}
Account caller = UserContext.current().getCaller();
Account owner = _accountMgr.getAccount(vmInstance.getAccountId());
// 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);
} else {
// verify permissions
_accountMgr.checkAccess(caller, null, true, owner, ag);
}
}
_affinityGroupVMMapDao.updateMap(vmId, affinityGroupIds);
if (s_logger.isDebugEnabled()) {
s_logger.debug("Updated VM :" + vmId + " affinity groups to =" + affinityGroupIds);
}
// APIResponseHelper will pull out the updated affinitygroups.
return vmInstance;
}
}

View File

@ -0,0 +1,66 @@
// 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.affinity;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.PrimaryKeyJoinColumn;
import javax.persistence.SecondaryTable;
import javax.persistence.SecondaryTables;
import javax.persistence.Table;
import org.apache.cloudstack.api.InternalIdentity;
@Entity
@Table(name = ("affinity_group_vm_map"))
public class AffinityGroupVMMapVO implements InternalIdentity {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(name = "id")
private Long id;
@Column(name = "affinity_group_id")
private long affinityGroupId;
@Column(name = "instance_id")
private long instanceId;
public AffinityGroupVMMapVO() {
}
public AffinityGroupVMMapVO(long affinityGroupId, long instanceId) {
this.affinityGroupId = affinityGroupId;
this.instanceId = instanceId;
}
public long getId() {
return id;
}
public long getAffinityGroupId() {
return affinityGroupId;
}
public long getInstanceId() {
return instanceId;
}
}

View File

@ -0,0 +1,114 @@
// 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.affinity;
import java.util.UUID;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.Table;
@Entity
@Table(name = ("affinity_group"))
public class AffinityGroupVO implements AffinityGroup {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(name = "id")
private long id;
@Column(name = "name")
private String name;
@Column(name = "type")
private String type;
@Column(name = "description")
private String description;
@Column(name = "domain_id")
private long domainId;
@Column(name = "account_id")
private long accountId;
@Column(name = "uuid")
private String uuid;
public AffinityGroupVO() {
this.uuid = UUID.randomUUID().toString();
}
public AffinityGroupVO(String name, String type, String description, long domainId, long accountId) {
this.name = name;
this.description = description;
this.domainId = domainId;
this.accountId = accountId;
this.uuid = UUID.randomUUID().toString();
this.type = type;
}
@Override
public long getId() {
return id;
}
@Override
public String getName() {
return name;
}
@Override
public String getDescription() {
return description;
}
@Override
public long getDomainId() {
return domainId;
}
@Override
public long getAccountId() {
return accountId;
}
@Override
public String getUuid() {
return this.uuid;
}
public void setUuid(String uuid) {
this.uuid = uuid;
}
@Override
public String getType() {
return type;
}
@Override
public String toString() {
StringBuilder buf = new StringBuilder("AffinityGroup[");
buf.append(id).append("|").append(name).append("|").append(type).append("]");
return buf.toString();
}
}

View File

@ -0,0 +1,30 @@
// 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.affinity.dao;
import java.util.List;
import org.apache.cloudstack.affinity.AffinityGroupVO;
import com.cloud.utils.db.GenericDao;
public interface AffinityGroupDao extends GenericDao<AffinityGroupVO, Long> {
List<AffinityGroupVO> listByAccountId(long accountId);
boolean isNameInUse(Long accountId, Long domainId, String name);
AffinityGroupVO findByAccountAndName(Long accountId, String name);
List<AffinityGroupVO> findByAccountAndNames(Long accountId, String... names);
int removeByAccountId(long accountId);
}

View File

@ -0,0 +1,102 @@
// 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.affinity.dao;
import java.util.List;
import javax.annotation.PostConstruct;
import javax.ejb.Local;
import org.apache.cloudstack.affinity.AffinityGroupVO;
import org.springframework.stereotype.Component;
import com.cloud.utils.db.GenericDaoBase;
import com.cloud.utils.db.SearchBuilder;
import com.cloud.utils.db.SearchCriteria;
@Local(value = { AffinityGroupDao.class })
public class AffinityGroupDaoImpl extends GenericDaoBase<AffinityGroupVO, Long> implements AffinityGroupDao {
private SearchBuilder<AffinityGroupVO> AccountIdSearch;
private SearchBuilder<AffinityGroupVO> AccountIdNameSearch;
private SearchBuilder<AffinityGroupVO> AccountIdNamesSearch;
public AffinityGroupDaoImpl() {
}
@PostConstruct
protected void init() {
AccountIdSearch = createSearchBuilder();
AccountIdSearch.and("accountId", AccountIdSearch.entity().getAccountId(), SearchCriteria.Op.EQ);
AccountIdSearch.done();
AccountIdNameSearch = createSearchBuilder();
AccountIdNameSearch.and("accountId", AccountIdNameSearch.entity().getAccountId(), SearchCriteria.Op.EQ);
AccountIdNameSearch.and("name", AccountIdNameSearch.entity().getName(), SearchCriteria.Op.EQ);
AccountIdNamesSearch = createSearchBuilder();
AccountIdNamesSearch.and("accountId", AccountIdNamesSearch.entity().getAccountId(), SearchCriteria.Op.EQ);
AccountIdNamesSearch.and("groupNames", AccountIdNamesSearch.entity().getName(), SearchCriteria.Op.IN);
AccountIdNameSearch.done();
}
@Override
public List<AffinityGroupVO> listByAccountId(long accountId) {
SearchCriteria<AffinityGroupVO> sc = AccountIdSearch.create();
sc.setParameters("accountId", accountId);
return listBy(sc);
}
@Override
public boolean isNameInUse(Long accountId, Long domainId, String name) {
SearchCriteria<AffinityGroupVO> sc = createSearchCriteria();
sc.addAnd("name", SearchCriteria.Op.EQ, name);
if (accountId != null) {
sc.addAnd("accountId", SearchCriteria.Op.EQ, accountId);
} else {
sc.addAnd("domainId", SearchCriteria.Op.EQ, domainId);
sc.addAnd("accountId", SearchCriteria.Op.NULL);
}
List<AffinityGroupVO> AffinityGroups = listBy(sc);
return ((AffinityGroups != null) && !AffinityGroups.isEmpty());
}
@Override
public AffinityGroupVO findByAccountAndName(Long accountId, String name) {
SearchCriteria<AffinityGroupVO> sc = AccountIdNameSearch.create();
sc.setParameters("accountId", accountId);
sc.setParameters("name", name);
return findOneIncludingRemovedBy(sc);
}
@Override
public List<AffinityGroupVO> findByAccountAndNames(Long accountId, String... names) {
SearchCriteria<AffinityGroupVO> sc = AccountIdNamesSearch.create();
sc.setParameters("accountId", accountId);
sc.setParameters("groupNames", (Object [])names);
return listBy(sc);
}
@Override
public int removeByAccountId(long accountId) {
SearchCriteria<AffinityGroupVO> sc = AccountIdSearch.create();
sc.setParameters("accountId", accountId);
return expunge(sc);
}
}

View File

@ -0,0 +1,47 @@
// 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.affinity.dao;
import java.util.List;
import org.apache.cloudstack.affinity.AffinityGroupVMMapVO;
import com.cloud.utils.Pair;
import com.cloud.utils.db.Filter;
import com.cloud.utils.db.GenericDao;
import com.cloud.vm.VirtualMachine.State;
public interface AffinityGroupVMMapDao extends GenericDao<AffinityGroupVMMapVO, Long> {
List<AffinityGroupVMMapVO> listByInstanceId(long instanceId);
Pair<List<AffinityGroupVMMapVO>, Integer> listByInstanceId(long instanceId, Filter filter);
List<AffinityGroupVMMapVO> listByAffinityGroup(long affinityGroupId);
List<Long> listVmIdsByAffinityGroup(long affinityGroupId);
AffinityGroupVMMapVO findByVmIdGroupId(long instanceId, long affinityGroupId);
long countAffinityGroupsForVm(long instanceId);
int deleteVM(long instanceId);
AffinityGroupVMMapVO findByVmIdType(long instanceId, String type);
void updateMap(Long vmId, List<Long> affinityGroupIds);
}

View File

@ -0,0 +1,167 @@
// 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.affinity.dao;
import java.util.List;
import javax.annotation.PostConstruct;
import javax.ejb.Local;
import javax.inject.Inject;
import org.apache.cloudstack.affinity.AffinityGroupVMMapVO;
import org.apache.cloudstack.affinity.AffinityGroupVO;
import org.springframework.stereotype.Component;
import com.cloud.host.HostTagVO;
import com.cloud.utils.Pair;
import com.cloud.utils.db.Filter;
import com.cloud.utils.db.GenericDaoBase;
import com.cloud.utils.db.GenericSearchBuilder;
import com.cloud.utils.db.JoinBuilder.JoinType;
import com.cloud.utils.db.SearchBuilder;
import com.cloud.utils.db.SearchCriteria;
import com.cloud.utils.db.SearchCriteria.Func;
import com.cloud.utils.db.Transaction;
@Local(value = { AffinityGroupVMMapDao.class })
public class AffinityGroupVMMapDaoImpl extends GenericDaoBase<AffinityGroupVMMapVO, Long> implements
AffinityGroupVMMapDao {
private SearchBuilder<AffinityGroupVMMapVO> ListByVmId;
private SearchBuilder<AffinityGroupVMMapVO> ListByVmIdGroupId;
protected GenericSearchBuilder<AffinityGroupVMMapVO, Long> CountSGForVm;
private GenericSearchBuilder<AffinityGroupVMMapVO, Long> ListVmIdByAffinityGroup;
private SearchBuilder<AffinityGroupVMMapVO> ListByAffinityGroup;
private SearchBuilder<AffinityGroupVMMapVO> ListByVmIdType;
@Inject
protected AffinityGroupDao _affinityGroupDao;
public AffinityGroupVMMapDaoImpl() {
}
@PostConstruct
protected void init() {
ListVmIdByAffinityGroup = createSearchBuilder(Long.class);
ListVmIdByAffinityGroup.and("affinityGroupId", ListVmIdByAffinityGroup.entity().getAffinityGroupId(),
SearchCriteria.Op.EQ);
ListVmIdByAffinityGroup.selectField(ListVmIdByAffinityGroup.entity().getInstanceId());
ListVmIdByAffinityGroup.done();
ListByAffinityGroup = createSearchBuilder();
ListByAffinityGroup.and("affinityGroupId", ListByAffinityGroup.entity().getAffinityGroupId(),
SearchCriteria.Op.EQ);
ListByAffinityGroup.done();
ListByVmId = createSearchBuilder();
ListByVmId.and("instanceId", ListByVmId.entity().getInstanceId(), SearchCriteria.Op.EQ);
ListByVmId.done();
ListByVmIdGroupId = createSearchBuilder();
ListByVmIdGroupId.and("instanceId", ListByVmIdGroupId.entity().getInstanceId(), SearchCriteria.Op.EQ);
ListByVmIdGroupId.and("affinityGroupId", ListByVmIdGroupId.entity().getAffinityGroupId(), SearchCriteria.Op.EQ);
ListByVmIdGroupId.done();
SearchBuilder<AffinityGroupVO> groupSearch = _affinityGroupDao.createSearchBuilder();
groupSearch.and("type", groupSearch.entity().getType(), SearchCriteria.Op.EQ);
ListByVmIdType = createSearchBuilder();
ListByVmIdType.and("instanceId", ListByVmIdType.entity().getInstanceId(), SearchCriteria.Op.EQ);
ListByVmIdType.join("groupSearch", groupSearch, ListByVmIdType.entity().getAffinityGroupId(), groupSearch.entity().getId(), JoinType.INNER);
ListByVmIdType.done();
CountSGForVm = createSearchBuilder(Long.class);
CountSGForVm.select(null, Func.COUNT, null);
CountSGForVm.and("vmId", CountSGForVm.entity().getInstanceId(), SearchCriteria.Op.EQ);
CountSGForVm.done();
}
@Override
public List<AffinityGroupVMMapVO> listByAffinityGroup(long affinityGroupId) {
SearchCriteria<AffinityGroupVMMapVO> sc = ListByAffinityGroup.create();
sc.setParameters("affinityGroupId", affinityGroupId);
return listBy(sc);
}
@Override
public List<AffinityGroupVMMapVO> listByInstanceId(long vmId) {
SearchCriteria<AffinityGroupVMMapVO> sc = ListByVmId.create();
sc.setParameters("instanceId", vmId);
return listBy(sc);
}
@Override
public Pair<List<AffinityGroupVMMapVO>, Integer> listByInstanceId(long instanceId, Filter filter) {
SearchCriteria<AffinityGroupVMMapVO> sc = ListByVmId.create();
sc.setParameters("instanceId", instanceId);
return this.searchAndCount(sc, filter);
}
@Override
public int deleteVM(long instanceId) {
SearchCriteria<AffinityGroupVMMapVO> sc = ListByVmId.create();
sc.setParameters("instanceId", instanceId);
return super.expunge(sc);
}
@Override
public List<Long> listVmIdsByAffinityGroup(long affinityGroupId) {
SearchCriteria<Long> sc = ListVmIdByAffinityGroup.create();
sc.setParameters("affinityGroupId", affinityGroupId);
return customSearchIncludingRemoved(sc, null);
}
@Override
public AffinityGroupVMMapVO findByVmIdGroupId(long instanceId, long affinityGroupId) {
SearchCriteria<AffinityGroupVMMapVO> sc = ListByVmIdGroupId.create();
sc.setParameters("affinityGroupId", affinityGroupId);
sc.setParameters("instanceId", instanceId);
return findOneIncludingRemovedBy(sc);
}
@Override
public long countAffinityGroupsForVm(long instanceId) {
SearchCriteria<Long> sc = CountSGForVm.create();
sc.setParameters("vmId", instanceId);
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 findOneBy(sc);
}
@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
return null;
}
@Override
public UserVm removeNicFromVirtualMachine(RemoveNicFromVMCmd cmd) throws InvalidParameterValueException, PermissionDeniedException, CloudRuntimeException {
// TODO Auto-generated method stub
return null;
}
@Override
public UserVm updateDefaultNicForVirtualMachine(UpdateDefaultNicForVMCmd cmd) throws InvalidParameterValueException, CloudRuntimeException {
// TODO Auto-generated method stub
@ -330,7 +330,9 @@ public class MockUserVmManagerImpl extends ManagerBase implements UserVmManager,
@Override
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 defaultIp, String keyboard) throws InsufficientCapacityException, ConcurrentOperationException, ResourceUnavailableException, StorageUnavailableException,
IpAddresses defaultIp,
String keyboard, List<Long> affinityGroupIdList) throws InsufficientCapacityException,
ConcurrentOperationException, ResourceUnavailableException, StorageUnavailableException,
ResourceAllocationException {
// TODO Auto-generated method stub
return null;
@ -339,7 +341,9 @@ public class MockUserVmManagerImpl extends ManagerBase implements UserVmManager,
@Override
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,
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 {
// TODO Auto-generated method stub
return null;
@ -348,7 +352,9 @@ public class MockUserVmManagerImpl extends ManagerBase implements UserVmManager,
@Override
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) throws InsufficientCapacityException, ConcurrentOperationException, ResourceUnavailableException, StorageUnavailableException, ResourceAllocationException {
String keyboard, List<Long> affinityGroupIdList) throws InsufficientCapacityException,
ConcurrentOperationException, ResourceUnavailableException, StorageUnavailableException,
ResourceAllocationException {
// TODO Auto-generated method stub
return null;
}

View File

@ -433,7 +433,7 @@ public class MockConfigurationManagerImpl extends ManagerBase implements Configu
*/
@Override
public ServiceOfferingVO createServiceOffering(long userId, boolean isSystem, Type vm_typeType, String name, int cpu, int ramSize, int speed, String displayText, boolean localStorageRequired, boolean offerHA,
boolean limitResourceUse, boolean volatileVm, String tags, Long domainId, String hostTag, Integer networkRate) {
boolean limitResourceUse, boolean volatileVm, String tags, Long domainId, String hostTag, Integer networkRate, String deploymentPlanner) {
// TODO Auto-generated method stub
return null;
}

View File

@ -0,0 +1,332 @@
// 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.affinity;
import java.io.IOException;
import org.apache.cloudstack.acl.SecurityChecker;
import org.apache.cloudstack.affinity.dao.AffinityGroupDao;
import org.apache.cloudstack.affinity.dao.AffinityGroupVMMapDao;
import org.apache.cloudstack.storage.datastore.db.PrimaryDataStoreDaoImpl;
import org.mockito.Mockito;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.FilterType;
import org.springframework.context.annotation.ComponentScan.Filter;
import org.springframework.core.type.classreading.MetadataReader;
import org.springframework.core.type.classreading.MetadataReaderFactory;
import org.springframework.core.type.filter.TypeFilter;
import com.cloud.utils.component.ComponentContext;
import com.cloud.agent.AgentManager;
import com.cloud.alert.AlertManager;
import com.cloud.api.query.dao.UserAccountJoinDaoImpl;
import com.cloud.capacity.dao.CapacityDaoImpl;
import com.cloud.cluster.agentlb.dao.HostTransferMapDaoImpl;
import com.cloud.configuration.dao.ConfigurationDao;
import com.cloud.dc.dao.AccountVlanMapDaoImpl;
import com.cloud.dc.dao.ClusterDaoImpl;
import com.cloud.dc.dao.DataCenterDaoImpl;
import com.cloud.dc.dao.DataCenterIpAddressDaoImpl;
import com.cloud.dc.dao.DataCenterLinkLocalIpAddressDaoImpl;
import com.cloud.dc.dao.DataCenterVnetDaoImpl;
import com.cloud.dc.dao.DcDetailsDaoImpl;
import com.cloud.dc.dao.HostPodDaoImpl;
import com.cloud.dc.dao.PodVlanDaoImpl;
import com.cloud.dc.dao.PodVlanMapDaoImpl;
import com.cloud.dc.dao.VlanDaoImpl;
import com.cloud.domain.dao.DomainDaoImpl;
import com.cloud.event.EventUtils;
import com.cloud.event.dao.EventDaoImpl;
import com.cloud.event.dao.UsageEventDaoImpl;
import com.cloud.host.dao.HostDaoImpl;
import com.cloud.host.dao.HostDetailsDaoImpl;
import com.cloud.host.dao.HostTagsDaoImpl;
import com.cloud.network.Ipv6AddressManager;
import com.cloud.network.NetworkManager;
import com.cloud.network.NetworkModel;
import com.cloud.network.NetworkService;
import com.cloud.network.StorageNetworkManager;
import com.cloud.network.dao.FirewallRulesCidrsDaoImpl;
import com.cloud.network.dao.FirewallRulesDaoImpl;
import com.cloud.network.dao.IPAddressDaoImpl;
import com.cloud.network.dao.LoadBalancerDaoImpl;
import com.cloud.network.dao.NetworkDao;
import com.cloud.network.dao.NetworkDomainDaoImpl;
import com.cloud.network.dao.NetworkServiceMapDaoImpl;
import com.cloud.network.dao.PhysicalNetworkDaoImpl;
import com.cloud.network.dao.PhysicalNetworkServiceProviderDaoImpl;
import com.cloud.network.dao.PhysicalNetworkTrafficTypeDaoImpl;
import com.cloud.network.dao.UserIpv6AddressDaoImpl;
import com.cloud.network.element.DhcpServiceProvider;
import com.cloud.network.element.IpDeployer;
import com.cloud.network.element.NetworkElement;
import com.cloud.network.guru.NetworkGuru;
import com.cloud.network.lb.LoadBalancingRulesManager;
import com.cloud.network.rules.FirewallManager;
import com.cloud.network.rules.RulesManager;
import com.cloud.network.rules.dao.PortForwardingRulesDaoImpl;
import com.cloud.network.vpc.NetworkACLManager;
import com.cloud.network.vpc.VpcManager;
import com.cloud.network.vpc.dao.PrivateIpDaoImpl;
import com.cloud.network.vpn.RemoteAccessVpnService;
import com.cloud.offerings.dao.NetworkOfferingDao;
import com.cloud.offerings.dao.NetworkOfferingServiceMapDao;
import com.cloud.projects.ProjectManager;
import com.cloud.service.dao.ServiceOfferingDaoImpl;
import com.cloud.storage.dao.DiskOfferingDaoImpl;
import com.cloud.storage.dao.S3DaoImpl;
import com.cloud.storage.dao.SnapshotDaoImpl;
import com.cloud.storage.dao.StoragePoolDetailsDaoImpl;
import com.cloud.storage.dao.SwiftDaoImpl;
import com.cloud.storage.dao.VolumeDaoImpl;
import com.cloud.storage.s3.S3Manager;
import com.cloud.storage.secondary.SecondaryStorageVmManager;
import com.cloud.storage.swift.SwiftManager;
import com.cloud.tags.dao.ResourceTagsDaoImpl;
import com.cloud.user.AccountManager;
import com.cloud.user.ResourceLimitService;
import com.cloud.user.UserContext;
import com.cloud.user.UserContextInitializer;
import com.cloud.user.dao.AccountDao;
import com.cloud.user.dao.AccountDaoImpl;
import com.cloud.user.dao.UserDaoImpl;
import com.cloud.utils.component.SpringComponentScanUtils;
import com.cloud.utils.db.GenericDao;
import com.cloud.utils.db.GenericDaoBase;
import com.cloud.vm.UserVmVO;
import com.cloud.vm.dao.InstanceGroupDaoImpl;
import com.cloud.vm.dao.NicDaoImpl;
import com.cloud.vm.dao.NicSecondaryIpDaoImpl;
import com.cloud.vm.dao.UserVmDao;
import com.cloud.vm.dao.VMInstanceDaoImpl;
@Configuration
@ComponentScan(basePackageClasses = { AccountVlanMapDaoImpl.class, VolumeDaoImpl.class, HostPodDaoImpl.class,
DomainDaoImpl.class, SwiftDaoImpl.class, ServiceOfferingDaoImpl.class, VlanDaoImpl.class,
IPAddressDaoImpl.class, ResourceTagsDaoImpl.class, InstanceGroupDaoImpl.class,
UserAccountJoinDaoImpl.class, CapacityDaoImpl.class, SnapshotDaoImpl.class, HostDaoImpl.class,
VMInstanceDaoImpl.class, HostTransferMapDaoImpl.class, PortForwardingRulesDaoImpl.class,
PrivateIpDaoImpl.class, UsageEventDaoImpl.class, PodVlanMapDaoImpl.class, DiskOfferingDaoImpl.class,
DataCenterDaoImpl.class, DataCenterIpAddressDaoImpl.class, DataCenterLinkLocalIpAddressDaoImpl.class,
DataCenterVnetDaoImpl.class, PodVlanDaoImpl.class, DcDetailsDaoImpl.class, NicSecondaryIpDaoImpl.class,
UserIpv6AddressDaoImpl.class, S3DaoImpl.class, UserDaoImpl.class, NicDaoImpl.class, NetworkDomainDaoImpl.class,
HostDetailsDaoImpl.class, HostTagsDaoImpl.class, ClusterDaoImpl.class, FirewallRulesDaoImpl.class,
FirewallRulesCidrsDaoImpl.class, PhysicalNetworkDaoImpl.class, PhysicalNetworkTrafficTypeDaoImpl.class,
PhysicalNetworkServiceProviderDaoImpl.class, LoadBalancerDaoImpl.class, NetworkServiceMapDaoImpl.class,
PrimaryDataStoreDaoImpl.class, StoragePoolDetailsDaoImpl.class, AffinityGroupServiceImpl.class,
ComponentContext.class, AffinityGroupProcessor.class, UserVmVO.class, EventUtils.class, UserVmVO.class,
EventDaoImpl.class }, includeFilters = { @Filter(value = AffinityApiTestConfiguration.Library.class, type = FilterType.CUSTOM) }, useDefaultFilters = false)
public class AffinityApiTestConfiguration {
@Bean
public AccountDao accountDao() {
return Mockito.mock(AccountDao.class);
}
@Bean
public EventUtils eventUtils() {
return Mockito.mock(EventUtils.class);
}
@Bean
public AffinityGroupProcessor affinityGroupProcessor() {
return Mockito.mock(AffinityGroupProcessor.class);
}
@Bean
public ComponentContext componentContext() {
return Mockito.mock(ComponentContext.class);
}
@Bean
public UserContextInitializer userContextInitializer() {
return Mockito.mock(UserContextInitializer.class);
}
@Bean
public UserVmVO userVmVO() {
return Mockito.mock(UserVmVO.class);
}
@Bean
public AffinityGroupDao affinityGroupDao() {
return Mockito.mock(AffinityGroupDao.class);
}
@Bean
public AffinityGroupVMMapDao affinityGroupVMMapDao() {
return Mockito.mock(AffinityGroupVMMapDao.class);
}
@Bean
public AccountManager acctMgr() {
return Mockito.mock(AccountManager.class);
}
@Bean
public NetworkService ntwkSvc() {
return Mockito.mock(NetworkService.class);
}
@Bean
public NetworkModel ntwkMdl() {
return Mockito.mock(NetworkModel.class);
}
@Bean
public AlertManager alertMgr() {
return Mockito.mock(AlertManager.class);
}
@Bean
public SecurityChecker securityChkr() {
return Mockito.mock(SecurityChecker.class);
}
@Bean
public ResourceLimitService resourceSvc() {
return Mockito.mock(ResourceLimitService.class);
}
@Bean
public ProjectManager projectMgr() {
return Mockito.mock(ProjectManager.class);
}
@Bean
public SecondaryStorageVmManager ssvmMgr() {
return Mockito.mock(SecondaryStorageVmManager.class);
}
@Bean
public SwiftManager swiftMgr() {
return Mockito.mock(SwiftManager.class);
}
@Bean
public S3Manager s3Mgr() {
return Mockito.mock(S3Manager.class);
}
@Bean
public VpcManager vpcMgr() {
return Mockito.mock(VpcManager.class);
}
@Bean
public UserVmDao userVMDao() {
return Mockito.mock(UserVmDao.class);
}
@Bean
public RulesManager rulesMgr() {
return Mockito.mock(RulesManager.class);
}
@Bean
public LoadBalancingRulesManager lbRulesMgr() {
return Mockito.mock(LoadBalancingRulesManager.class);
}
@Bean
public RemoteAccessVpnService vpnMgr() {
return Mockito.mock(RemoteAccessVpnService.class);
}
@Bean
public NetworkGuru ntwkGuru() {
return Mockito.mock(NetworkGuru.class);
}
@Bean
public NetworkElement ntwkElement() {
return Mockito.mock(NetworkElement.class);
}
@Bean
public IpDeployer ipDeployer() {
return Mockito.mock(IpDeployer.class);
}
@Bean
public DhcpServiceProvider dhcpProvider() {
return Mockito.mock(DhcpServiceProvider.class);
}
@Bean
public FirewallManager firewallMgr() {
return Mockito.mock(FirewallManager.class);
}
@Bean
public AgentManager agentMgr() {
return Mockito.mock(AgentManager.class);
}
@Bean
public StorageNetworkManager storageNtwkMgr() {
return Mockito.mock(StorageNetworkManager.class);
}
@Bean
public NetworkACLManager ntwkAclMgr() {
return Mockito.mock(NetworkACLManager.class);
}
@Bean
public Ipv6AddressManager ipv6Mgr() {
return Mockito.mock(Ipv6AddressManager.class);
}
@Bean
public ConfigurationDao configDao() {
return Mockito.mock(ConfigurationDao.class);
}
@Bean
public NetworkManager networkManager() {
return Mockito.mock(NetworkManager.class);
}
@Bean
public NetworkOfferingDao networkOfferingDao() {
return Mockito.mock(NetworkOfferingDao.class);
}
@Bean
public NetworkDao networkDao() {
return Mockito.mock(NetworkDao.class);
}
@Bean
public NetworkOfferingServiceMapDao networkOfferingServiceMapDao() {
return Mockito.mock(NetworkOfferingServiceMapDao.class);
}
public static class Library implements TypeFilter {
@Override
public boolean match(MetadataReader mdr, MetadataReaderFactory arg1) throws IOException {
mdr.getClassMetadata().getClassName();
ComponentScan cs = AffinityApiTestConfiguration.class.getAnnotation(ComponentScan.class);
return SpringComponentScanUtils.includedInBasePackageClasses(mdr.getClassMetadata().getClassName(), cs);
}
}
}

View File

@ -0,0 +1,174 @@
// 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.affinity;
import static org.junit.Assert.*;
import static org.mockito.Matchers.anyLong;
import static org.mockito.Mockito.*;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.apache.cloudstack.affinity.dao.AffinityGroupDao;
import org.apache.cloudstack.affinity.dao.AffinityGroupVMMapDao;
import org.junit.Before;
import org.junit.BeforeClass;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import com.cloud.event.EventUtils;
import com.cloud.exception.InvalidParameterValueException;
import com.cloud.exception.ResourceInUseException;
import com.cloud.hypervisor.Hypervisor.HypervisorType;
import com.cloud.user.Account;
import com.cloud.user.AccountManager;
import com.cloud.user.AccountManagerImpl;
import com.cloud.user.AccountVO;
import com.cloud.user.UserContext;
import com.cloud.user.UserContextInitializer;
import com.cloud.user.dao.AccountDao;
import com.cloud.utils.component.ComponentContext;
import com.cloud.vm.UserVmVO;
import com.cloud.vm.VirtualMachine;
import com.cloud.vm.dao.UserVmDao;
import javax.inject.Inject;
import javax.naming.ConfigurationException;
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations = "classpath:/affinityContext.xml")
public class AffinityApiUnitTest {
@Inject
AffinityGroupServiceImpl _affinityService;
@Inject
AccountManager _acctMgr;
@Inject
AffinityGroupProcessor _processor;
@Inject
AffinityGroupDao _groupDao;
@Inject
UserVmDao _vmDao;
@Inject
AffinityGroupVMMapDao _affinityGroupVMMapDao;
@Inject
EventUtils _eventUtils;
@Inject
AccountDao _accountDao;
private static long domainId = 5L;
@BeforeClass
public static void setUp() throws ConfigurationException {
}
@Before
public void testSetUp() {
ComponentContext.initComponentsLifeCycle();
AccountVO acct = new AccountVO(200L);
acct.setType(Account.ACCOUNT_TYPE_NORMAL);
acct.setAccountName("user");
acct.setDomainId(domainId);
UserContext.registerContext(1, acct, null, true);
when(_acctMgr.finalizeOwner((Account) anyObject(), anyString(), anyLong(), anyLong())).thenReturn(acct);
when(_processor.getType()).thenReturn("mock");
when(_accountDao.findByIdIncludingRemoved(0L)).thenReturn(acct);
}
@Test
public void createAffinityGroupTest() {
AffinityGroup group = _affinityService.createAffinityGroup("user", domainId, "group1", "mock",
"affinity group one");
assertNotNull("Affinity group 'group1' of type 'mock' failed to create ", group);
}
@Test(expected = InvalidParameterValueException.class)
public void invalidAffinityTypeTest() {
AffinityGroup group = _affinityService.createAffinityGroup("user", domainId, "group1", "invalid",
"affinity group one");
}
@Test(expected = InvalidParameterValueException.class)
public void uniqueAffinityNameTest() {
when(_groupDao.isNameInUse(anyLong(), anyLong(), eq("group1"))).thenReturn(true);
AffinityGroup group2 = _affinityService.createAffinityGroup("user", domainId, "group1", "mock",
"affinity group two");
}
@Test(expected = InvalidParameterValueException.class)
public void deleteAffinityGroupInvalidIdTest() throws ResourceInUseException {
when(_groupDao.findById(20L)).thenReturn(null);
_affinityService.deleteAffinityGroup(20L, "user", domainId, "group1");
}
@Test(expected = InvalidParameterValueException.class)
public void deleteAffinityGroupInvalidIdName() throws ResourceInUseException {
when(_groupDao.findByAccountAndName(200L, "group1")).thenReturn(null);
_affinityService.deleteAffinityGroup(null, "user", domainId, "group1");
}
@Test(expected = InvalidParameterValueException.class)
public void deleteAffinityGroupNullIdName() throws ResourceInUseException {
_affinityService.deleteAffinityGroup(null, "user", domainId, null);
}
@Test(expected = ResourceInUseException.class)
public void deleteAffinityGroupInUse() throws ResourceInUseException {
List<AffinityGroupVMMapVO> affinityGroupVmMap = new ArrayList<AffinityGroupVMMapVO>();
AffinityGroupVMMapVO mapVO = new AffinityGroupVMMapVO(20L, 10L);
affinityGroupVmMap.add(mapVO);
when(_affinityGroupVMMapDao.listByAffinityGroup(20L)).thenReturn(affinityGroupVmMap);
AffinityGroupVO groupVO = new AffinityGroupVO();
when(_groupDao.findById(20L)).thenReturn(groupVO);
when(_groupDao.lockRow(20L, true)).thenReturn(groupVO);
_affinityService.deleteAffinityGroup(20L, "user", domainId, null);
}
@Test(expected = InvalidParameterValueException.class)
public void updateAffinityGroupVMRunning() throws ResourceInUseException {
UserVmVO vm = new UserVmVO(10L, "test", "test", 101L, HypervisorType.Any, 21L, false, false, domainId, 200L,
5L, "", "test", 1L);
vm.setState(VirtualMachine.State.Running);
when(_vmDao.findById(10L)).thenReturn(vm);
List<Long> affinityGroupIds = new ArrayList<Long>();
affinityGroupIds.add(20L);
_affinityService.updateVMAffinityGroups(10L, affinityGroupIds);
}
}

View File

@ -0,0 +1,47 @@
<!-- 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. -->
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:context="http://www.springframework.org/schema/context"
xmlns:tx="http://www.springframework.org/schema/tx" xmlns:aop="http://www.springframework.org/schema/aop"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
http://www.springframework.org/schema/tx
http://www.springframework.org/schema/tx/spring-tx-3.0.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop-3.0.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-3.0.xsd">
<context:annotation-config />
<!-- @DB support -->
<bean id="componentContext" class="com.cloud.utils.component.ComponentContext" />
<bean id="transactionContextBuilder" class="com.cloud.utils.db.TransactionContextBuilder" />
<bean id="actionEventInterceptor" class="com.cloud.event.ActionEventInterceptor" />
<bean id="instantiatePostProcessor" class="com.cloud.utils.component.ComponentInstantiationPostProcessor">
<property name="Interceptors">
<list>
<ref bean="transactionContextBuilder" />
<ref bean="actionEventInterceptor" />
</list>
</property>
</bean>
<bean id="ConfigurationManager" class="com.cloud.configuration.ConfigurationManagerImpl">
<property name="name" value="ConfigurationManager"/>
</bean>
<bean class="org.apache.cloudstack.affinity.AffinityApiTestConfiguration" />
</beans>

View File

@ -142,9 +142,32 @@ CREATE TABLE `cloud`.`user_vm_clone_setting` (
INSERT IGNORE INTO `cloud`.`configuration` VALUES ('Advanced', 'DEFAULT', 'UserVmManager', 'vmware.create.full.clone' , 'false', 'If set to true, creates VMs as full clones on ESX hypervisor');
-- Re-enable foreign key checking, at the end of the upgrade path
SET foreign_key_checks = 1;
CREATE TABLE `cloud`.`affinity_group` (
`id` bigint unsigned NOT NULL auto_increment,
`name` varchar(255) NOT NULL,
`type` varchar(255) NOT NULL,
`uuid` varchar(40),
`description` varchar(4096) NULL,
`domain_id` bigint unsigned NOT NULL,
`account_id` bigint unsigned NOT NULL,
UNIQUE (`name`, `account_id`),
PRIMARY KEY (`id`),
CONSTRAINT `fk_affinity_group__account_id` FOREIGN KEY(`account_id`) REFERENCES `account`(`id`),
CONSTRAINT `fk_affinity_group__domain_id` FOREIGN KEY(`domain_id`) REFERENCES `domain`(`id`),
CONSTRAINT `uc_affinity_group__uuid` UNIQUE (`uuid`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
CREATE TABLE `cloud`.`affinity_group_vm_map` (
`id` bigint unsigned NOT NULL auto_increment,
`affinity_group_id` bigint unsigned NOT NULL,
`instance_id` bigint unsigned NOT NULL,
PRIMARY KEY (`id`),
CONSTRAINT `fk_agvm__group_id` FOREIGN KEY(`affinity_group_id`) REFERENCES `affinity_group`(`id`) ON DELETE CASCADE,
CONSTRAINT `fk_affinity_group_vm_map___instance_id` FOREIGN KEY(`instance_id`) REFERENCES `user_vm` (`id`) ON DELETE CASCADE
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
ALTER TABLE `cloud`.`service_offering` ADD COLUMN `deployment_planner` varchar(255) NOT NULL DEFAULT 'FirstFitPlanner' COMMENT 'Planner heuristics used to deploy a VM of this offering';
CREATE TABLE nic_secondary_ips (
`id` bigint unsigned NOT NULL UNIQUE AUTO_INCREMENT,
@ -455,3 +478,216 @@ ALTER TABLE `cloud`.`load_balancing_rules` ADD COLUMN `scheme` varchar(40) NOT N
UPDATE `cloud`.`load_balancing_rules` SET `scheme`='Public';
DROP VIEW IF EXISTS `cloud`.`user_vm_view`;
CREATE VIEW `cloud`.`user_vm_view` AS
select
vm_instance.id id,
vm_instance.name name,
user_vm.display_name display_name,
user_vm.user_data user_data,
account.id account_id,
account.uuid account_uuid,
account.account_name account_name,
account.type account_type,
domain.id domain_id,
domain.uuid domain_uuid,
domain.name domain_name,
domain.path domain_path,
projects.id project_id,
projects.uuid project_uuid,
projects.name project_name,
instance_group.id instance_group_id,
instance_group.uuid instance_group_uuid,
instance_group.name instance_group_name,
vm_instance.uuid uuid,
vm_instance.last_host_id last_host_id,
vm_instance.vm_type type,
vm_instance.vnc_password vnc_password,
vm_instance.limit_cpu_use limit_cpu_use,
vm_instance.created created,
vm_instance.state state,
vm_instance.removed removed,
vm_instance.ha_enabled ha_enabled,
vm_instance.hypervisor_type hypervisor_type,
vm_instance.instance_name instance_name,
vm_instance.guest_os_id guest_os_id,
guest_os.uuid guest_os_uuid,
vm_instance.pod_id pod_id,
host_pod_ref.uuid pod_uuid,
vm_instance.private_ip_address private_ip_address,
vm_instance.private_mac_address private_mac_address,
vm_instance.vm_type vm_type,
data_center.id data_center_id,
data_center.uuid data_center_uuid,
data_center.name data_center_name,
data_center.is_security_group_enabled security_group_enabled,
host.id host_id,
host.uuid host_uuid,
host.name host_name,
vm_template.id template_id,
vm_template.uuid template_uuid,
vm_template.name template_name,
vm_template.display_text template_display_text,
vm_template.enable_password password_enabled,
iso.id iso_id,
iso.uuid iso_uuid,
iso.name iso_name,
iso.display_text iso_display_text,
service_offering.id service_offering_id,
disk_offering.uuid service_offering_uuid,
service_offering.cpu cpu,
service_offering.speed speed,
service_offering.ram_size ram_size,
disk_offering.name service_offering_name,
storage_pool.id pool_id,
storage_pool.uuid pool_uuid,
storage_pool.pool_type pool_type,
volumes.id volume_id,
volumes.uuid volume_uuid,
volumes.device_id volume_device_id,
volumes.volume_type volume_type,
security_group.id security_group_id,
security_group.uuid security_group_uuid,
security_group.name security_group_name,
security_group.description security_group_description,
nics.id nic_id,
nics.uuid nic_uuid,
nics.network_id network_id,
nics.ip4_address ip_address,
nics.ip6_address ip6_address,
nics.ip6_gateway ip6_gateway,
nics.ip6_cidr ip6_cidr,
nics.default_nic is_default_nic,
nics.gateway gateway,
nics.netmask netmask,
nics.mac_address mac_address,
nics.broadcast_uri broadcast_uri,
nics.isolation_uri isolation_uri,
vpc.id vpc_id,
vpc.uuid vpc_uuid,
networks.uuid network_uuid,
networks.name network_name,
networks.traffic_type traffic_type,
networks.guest_type guest_type,
user_ip_address.id public_ip_id,
user_ip_address.uuid public_ip_uuid,
user_ip_address.public_ip_address public_ip_address,
ssh_keypairs.keypair_name keypair_name,
resource_tags.id tag_id,
resource_tags.uuid tag_uuid,
resource_tags.key tag_key,
resource_tags.value tag_value,
resource_tags.domain_id tag_domain_id,
resource_tags.account_id tag_account_id,
resource_tags.resource_id tag_resource_id,
resource_tags.resource_uuid tag_resource_uuid,
resource_tags.resource_type tag_resource_type,
resource_tags.customer tag_customer,
async_job.id job_id,
async_job.uuid job_uuid,
async_job.job_status job_status,
async_job.account_id job_account_id,
affinity_group.id affinity_group_id,
affinity_group.uuid affinity_group_uuid,
affinity_group.name affinity_group_name,
affinity_group.description affinity_group_description
from
`cloud`.`user_vm`
inner join
`cloud`.`vm_instance` ON vm_instance.id = user_vm.id
and vm_instance.removed is NULL
inner join
`cloud`.`account` ON vm_instance.account_id = account.id
inner join
`cloud`.`domain` ON vm_instance.domain_id = domain.id
left join
`cloud`.`guest_os` ON vm_instance.guest_os_id = guest_os.id
left join
`cloud`.`host_pod_ref` ON vm_instance.pod_id = host_pod_ref.id
left join
`cloud`.`projects` ON projects.project_account_id = account.id
left join
`cloud`.`instance_group_vm_map` ON vm_instance.id = instance_group_vm_map.instance_id
left join
`cloud`.`instance_group` ON instance_group_vm_map.group_id = instance_group.id
left join
`cloud`.`data_center` ON vm_instance.data_center_id = data_center.id
left join
`cloud`.`host` ON vm_instance.host_id = host.id
left join
`cloud`.`vm_template` ON vm_instance.vm_template_id = vm_template.id
left join
`cloud`.`vm_template` iso ON iso.id = user_vm.iso_id
left join
`cloud`.`service_offering` ON vm_instance.service_offering_id = service_offering.id
left join
`cloud`.`disk_offering` ON vm_instance.service_offering_id = disk_offering.id
left join
`cloud`.`volumes` ON vm_instance.id = volumes.instance_id
left join
`cloud`.`storage_pool` ON volumes.pool_id = storage_pool.id
left join
`cloud`.`security_group_vm_map` ON vm_instance.id = security_group_vm_map.instance_id
left join
`cloud`.`security_group` ON security_group_vm_map.security_group_id = security_group.id
left join
`cloud`.`nics` ON vm_instance.id = nics.instance_id
left join
`cloud`.`networks` ON nics.network_id = networks.id
left join
`cloud`.`vpc` ON networks.vpc_id = vpc.id
left join
`cloud`.`user_ip_address` ON user_ip_address.vm_id = vm_instance.id
left join
`cloud`.`user_vm_details` ON user_vm_details.vm_id = vm_instance.id
and user_vm_details.name = 'SSH.PublicKey'
left join
`cloud`.`ssh_keypairs` ON ssh_keypairs.public_key = user_vm_details.value
left join
`cloud`.`resource_tags` ON resource_tags.resource_id = vm_instance.id
and resource_tags.resource_type = 'UserVm'
left join
`cloud`.`async_job` ON async_job.instance_id = vm_instance.id
and async_job.instance_type = 'VirtualMachine'
and async_job.job_status = 0
left join
`cloud`.`affinity_group_vm_map` ON vm_instance.id = affinity_group_vm_map.instance_id
left join
`cloud`.`affinity_group` ON affinity_group_vm_map.affinity_group_id = affinity_group.id;
DROP VIEW IF EXISTS `cloud`.`affinity_group_view`;
CREATE VIEW `cloud`.`affinity_group_view` AS
select
affinity_group.id id,
affinity_group.name name,
affinity_group.description description,
affinity_group.uuid uuid,
account.id account_id,
account.uuid account_uuid,
account.account_name account_name,
account.type account_type,
domain.id domain_id,
domain.uuid domain_uuid,
domain.name domain_name,
domain.path domain_path,
vm_instance.id vm_id,
vm_instance.uuid vm_uuid,
vm_instance.name vm_name,
vm_instance.state vm_state,
user_vm.display_name vm_display_name
from
`cloud`.`affinity_group`
inner join
`cloud`.`account` ON affinity_group.account_id = account.id
inner join
`cloud`.`domain` ON affinity_group.domain_id = domain.id
left join
`cloud`.`affinity_group_vm_map` ON affinity_group.id = affinity_group_vm_map.affinity_group_id
left join
`cloud`.`vm_instance` ON vm_instance.id = affinity_group_vm_map.instance_id
left join
`cloud`.`user_vm` ON user_vm.id = vm_instance.id;
-- Re-enable foreign key checking, at the end of the upgrade path
SET foreign_key_checks = 1;

View File

@ -0,0 +1,194 @@
#!/usr/bin/env python
# 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.
from marvin.cloudstackTestCase import *
from marvin.cloudstackAPI import *
from marvin.integration.lib.utils import *
from marvin.integration.lib.base import *
from marvin.integration.lib.common import *
from marvin import remoteSSHClient
from nose.plugins.attrib import attr
class Services:
"""Test Account Services
"""
def __init__(self):
self.services = {
"domain": {
"name": "Domain",
},
"account": {
"email": "test@test.com",
"firstname": "Test",
"lastname": "User",
"username": "test",
# Random characters are appended for unique
# username
"password": "password",
},
"service_offering": {
"name": "Tiny Instance",
"displaytext": "Tiny Instance",
"cpunumber": 1,
"cpuspeed": 100,
# in MHz
"memory": 64,
# In MBs
},
"ostype": 'CentOS 5.3 (64-bit)',
"virtual_machine" : {
"affinity": {
"name": "webvms",
"type": "host anti-affinity",
},
"hypervisor" : "XenServer",
}
}
class TestDeployVmWithAffinityGroup(cloudstackTestCase):
"""
This test deploys a virtual machine into a user account
using the small service offering and builtin template
"""
@classmethod
def setUpClass(cls):
cls.api_client = super(TestDeployVmWithAffinityGroup, cls).getClsTestClient().getApiClient()
cls.services = Services().services
# Get Zone, Domain and templates
cls.domain = get_domain(cls.api_client, cls.services)
cls.zone = get_zone(cls.api_client, cls.services)
cls.template = get_template(
cls.api_client,
cls.zone.id,
cls.services["ostype"]
)
cls.services["virtual_machine"]["zoneid"] = cls.zone.id
cls.services["template"] = cls.template.id
cls.services["zoneid"] = cls.zone.id
cls.account = Account.create(
cls.api_client,
cls.services["account"],
domainid=cls.domain.id
)
cls.services["account"] = cls.account.account.name
cls.service_offering = ServiceOffering.create(
cls.api_client,
cls.services["service_offering"]
)
cls.ag = AffinityGroup.create(cls.api_client, cls.services["virtual_machine"]["affinity"],
account=cls.services["account"], domainid=cls.domain.id)
cls._cleanup = [
cls.service_offering,
cls.account,
]
return
@attr(tags=["simulator", "basic", "advanced", "multihost"])
def test_DeployVmAntiAffinityGroup(self):
"""
test DeployVM in anti-affinity groups
deploy VM1 and VM2 in the same host-anti-affinity groups
Verify that the vms are deployed on separate hosts
"""
#deploy VM1 in affinity group created in setUp
vm1 = VirtualMachine.create(
self.api_client,
self.services["virtual_machine"],
templateid=self.template.id,
accountid=self.account.account.name,
domainid=self.account.account.domainid,
serviceofferingid=self.service_offering.id,
affinitygroupnames=[self.ag.name]
)
list_vm1 = list_virtual_machines(
self.api_client,
id=vm1.id
)
self.assertEqual(
isinstance(list_vm1, list),
True,
"Check list response returns a valid list"
)
self.assertNotEqual(
len(list_vm1),
0,
"Check VM available in List Virtual Machines"
)
vm1_response = list_vm1[0]
self.assertEqual(
vm1_response.state,
'Running',
msg="VM is not in Running state"
)
host_of_vm1 = vm1_response.hostid
#deploy VM2 in affinity group created in setUp
vm2 = VirtualMachine.create(
self.api_client,
self.services["virtual_machine"],
templateid=self.template.id,
accountid=self.account.account.name,
domainid=self.account.account.domainid,
serviceofferingid=self.service_offering.id,
affinitygroupnames=[self.ag.name]
)
list_vm2 = list_virtual_machines(
self.api_client,
id=vm2.id
)
self.assertEqual(
isinstance(list_vm2, list),
True,
"Check list response returns a valid list"
)
self.assertNotEqual(
len(list_vm2),
0,
"Check VM available in List Virtual Machines"
)
vm2_response = list_vm2[0]
self.assertEqual(
vm2_response.state,
'Running',
msg="VM is not in Running state"
)
host_of_vm2 = vm2_response.hostid
self.assertNotEqual(host_of_vm1, host_of_vm2,
msg="Both VMs of affinity group %s are on the same host" % self.ag.name)
@classmethod
def tearDown(cls):
try:
cls.api_client = super(TestDeployVmWithAffinityGroup, cls).getClsTestClient().getApiClient()
#Clean up, terminate the created templates
cleanup_resources(cls.api_client, cls.cleanup)
except Exception as e:
raise Exception("Warning: Exception during cleanup : %s" % e)

View File

@ -1,4 +1,4 @@
#!/usr/bin/python
#!/cygdrive/c/Python27
# 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
@ -137,6 +137,7 @@ known_categories = {
'addIpToNic': 'Nic',
'removeIpFromNic': 'Nic',
'listNics':'Nic',
'AffinityGroup': 'Affinity Group',
}

View File

@ -90,10 +90,7 @@ class Account:
cmd.firstname = services["firstname"]
cmd.lastname = services["lastname"]
# Password Encoding
mdf = hashlib.md5()
mdf.update(services["password"])
cmd.password = mdf.hexdigest()
cmd.password = services["password"]
cmd.username = "-".join([services["username"], random_gen()])
if domainid:
@ -223,7 +220,7 @@ class VirtualMachine:
def create(cls, apiclient, services, templateid=None, accountid=None,
domainid=None, zoneid=None, networkids=None, serviceofferingid=None,
securitygroupids=None, projectid=None, startvm=None,
diskofferingid=None, hostid=None, mode='basic'):
diskofferingid=None, affinitygroupnames=None, hostid=None, mode='basic'):
"""Create the instance"""
cmd = deployVirtualMachine.deployVirtualMachineCmd()
@ -268,6 +265,11 @@ class VirtualMachine:
if "userdata" in services:
cmd.userdata = base64.b64encode(services["userdata"])
if "affinitygroupnames" in services:
cmd.affinitygroupnames = services["affinitygroupnames"]
elif affinitygroupnames:
cmd.affinitygroupnames = affinitygroupnames
if projectid:
cmd.projectid = projectid
@ -2424,3 +2426,33 @@ class VPC:
cmd = listVPCs.listVPCsCmd()
[setattr(cmd, k, v) for k, v in kwargs.items()]
return(apiclient.listVPCs(cmd))
class AffinityGroup:
def __init__(self, items):
self.__dict__.update(items)
@classmethod
def create(cls, apiclient, services, account=None, domainid=None):
agCmd = createAffinityGroup.createAffinityGroupCmd()
agCmd.name = services['name']
agCmd.displayText = services['displaytext'] if 'displaytext' in services else services['name']
agCmd.type = services['type']
agCmd.account = services['account'] if 'account' in services else account
agCmd.domainid = services['domainid'] if 'domainid' in services else domainid
return AffinityGroup(apiclient.createAffinityGroup(agCmd).__dict__)
def update(self, apiclient):
pass
def delete(self, apiclient):
cmd = deleteAffinityGroup.deleteAffinityGroupCmd()
cmd.id = self.id
return apiclient.deleteVPC(cmd)
@classmethod
def list(cls, apiclient, **kwargs):
cmd = listAffinityGroups.listAffinityGroupsCmd()
[setattr(cmd, k, v) for k, v in kwargs.items()]
return(apiclient.listVPCs(cmd))

View File

@ -56,7 +56,7 @@ under the License.
<!-- Password -->
<div class="field password">
<label for="password"><fmt:message key="label.password"/></label>
<input type="password" name="password" class="required" />
<input type="password" name="password" class="required" autocomplete="off" />
</div>
<!-- Domain -->
<div class="field domain">

View File

@ -255,11 +255,11 @@
array1.push("&domain=" + encodeURIComponent("/"));
}
g_loginCmdText = array1.join("");
var loginCmdText = array1.join("");
$.ajax({
type: "POST",
data: "command=login" + g_loginCmdText + "&response=json",
data: "command=login" + loginCmdText + "&response=json",
dataType: "json",
async: false,
success: function(json) {

View File

@ -1554,7 +1554,9 @@
data.queryasyncjobresultresponse.jobresult.nicsecondaryip,
{
zoneid: args.context.instances[0].zoneid,
virtualmachinedisplayname: args.context.instances[0].displayname
virtualmachinedisplayname: args.context.instances[0].displayname ?
args.context.instances[0].displayname :
args.context.instances[0].name
}
);
},
@ -1587,7 +1589,9 @@
data: $(ips).map(function(index, ip) {
return $.extend(ip, {
zoneid: args.context.instances[0].zoneid,
virtualmachinedisplayname: args.context.instances[0].displayname
virtualmachinedisplayname: args.context.instances[0].displayname ?
args.context.instances[0].displayname :
args.context.instances[0].name
});
})
});

View File

@ -214,8 +214,148 @@
id: 'GSLB',
label: 'GSLB',
fields: {
name: { label: 'label.name' }
name: { label: 'label.name' },
gslbdomainname: { label: 'GSLB Domain Name' },
gslblbmethod: { label: 'Algorithm' }
},
actions: {
add: {
label: 'Add GSLB',
messages: {
confirm: function(args) {
return 'Add GSLB';
},
notification: function(args) {
return 'Add GSLB';
}
},
createForm: {
title: 'Add GSLB',
fields: {
name: {
label: 'label.name',
validation: { required: true }
},
description: {
label: 'label.description'
},
/*
domainid: {
label: 'Domain',
select: function(args) {
if(isAdmin() || isDomainAdmin()) {
$.ajax({
url: createURL('listDomains'),
data: {
listAll: true,
details: 'min'
},
success: function(json) {
var array1 = [{id: '', description: ''}];
var domains = json.listdomainsresponse.domain;
if(domains != null && domains.length > 0) {
for(var i = 0; i < domains.length; i++) {
array1.push({id: domains[i].id, description: domains[i].path});
}
}
args.response.success({
data: array1
});
}
});
}
else {
args.response.success({
data: null
});
}
},
isHidden: function(args) {
if(isAdmin() || isDomainAdmin())
return false;
else
return true;
}
},
account: {
label: 'Account',
isHidden: function(args) {
if(isAdmin() || isDomainAdmin())
return false;
else
return true;
}
},
*/
gslblbmethod: {
label: 'Algorithm',
select: function(args) {
var array1 = [{id: 'roundrobin', description: 'roundrobin'}, {id: 'leastconn', description: 'leastconn'}, {id: 'proximity', description: 'proximity'}];
args.response.success({
data: array1
});
}
},
gslbdomainname: {
label: 'GSLB Domain Name',
validation: { required: true }
},
gslbservicetype: {
label: 'Service Type',
select: function(args) {
var array1 = [{id: 'tcp', description: 'tcp'}, {id: 'udp', description: 'udp'}];
args.response.success({
data: array1
});
},
validation: { required: true }
}
}
},
action: function(args) {
var data = {
name: args.data.name,
regionid: args.context.regions[0].id,
gslblbmethod: args.data.gslblbmethod,
gslbstickysessionmethodname: 'sourceip',
gslbdomainname: args.data.gslbdomainname,
gslbservicetype: args.data.gslbservicetype
};
if(args.data.description != null && args.data.description.length > 0)
$.extend(data, { description: args.data.description });
/*
if(args.data.domainid != null && args.data.domainid.length > 0)
$.extend(data, { domainid: args.data.domainid });
if(args.data.account != null && args.data.account.length > 0)
$.extend(data, { account: args.data.account });
*/
$.ajax({
url: createURL('createGlobalLoadBalancerRule'),
data: data,
success: function(json) {
var jid = json.creategloballoadbalancerruleresponse.jobid;
args.response.success(
{_custom:
{jobId: jid,
getUpdatedItem: function(json) {
return json.queryasyncjobresultresponse.jobresult.globalloadbalancerrule;
}
}
}
);
}
});
},
notification: {
poll: function(args) {
poll: pollAsyncJobResult
}
}
}
},
dataProvider: function(args) {
if('regions' in args.context) {
var data = {
@ -224,8 +364,7 @@
$.ajax({
url: createURL('listGlobalLoadBalancerRules'),
data: data,
success: function(json) {
debugger;
success: function(json) {
var items = json.listgloballoadbalancerrulesresponse.globalloadbalancerrule;
args.response.success({
data: items

View File

@ -89,7 +89,7 @@
closeRegionSelector({
complete: function() {
$('#container').prepend($('<div>').addClass('loading-overlay'));
window.name = g_loginCmdText;
//window.name = g_loginCmdText;
document.location.href = url;
}
});

View File

@ -863,16 +863,14 @@
var uiCustom = listViewArgs.uiCustom;
var subselect = uiCustom ? listViewArgs.listView.subselect : null;
if (!data || !data.length) {
if (!(data && data.length)) {
if (!$tbody.find('tr').size()) {
return [
$('<tr>').addClass('empty').append(
$('<tr>').addClass('empty last').append(
$('<td>').html(_l('label.no.data'))
).appendTo($tbody)
];
}
return $tbody.find('tr:last').addClass('last');
}
$tbody.find('tr.empty').remove();

View File

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