mirror of
https://github.com/apache/cloudstack.git
synced 2025-10-26 08:42:29 +01:00
CLOUDSTACK-2056: DeploymentPlanner choice via ServiceOffering
- Changes merged from planner_reserve branch - Exposing deploymentplanner as an optional parameter while creating a service offering - changes to DeploymentPlanningManagerImpl to make sure host reserve-release happens between conflicting planner usages.
This commit is contained in:
parent
15be97772e
commit
a2eb7bab1e
45
api/src/com/cloud/deploy/DeploymentClusterPlanner.java
Normal file
45
api/src/com/cloud/deploy/DeploymentClusterPlanner.java
Normal 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 java.util.List;
|
||||
|
||||
import com.cloud.exception.InsufficientServerCapacityException;
|
||||
import com.cloud.vm.VirtualMachine;
|
||||
import com.cloud.vm.VirtualMachineProfile;
|
||||
|
||||
/**
|
||||
*/
|
||||
public interface DeploymentClusterPlanner extends DeploymentPlanner {
|
||||
/**
|
||||
* This is called to determine list of possible clusters where a virtual
|
||||
* machine can be deployed.
|
||||
*
|
||||
* @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.
|
||||
* @return DeployDestination for that virtual machine.
|
||||
*/
|
||||
List<Long> orderClusters(VirtualMachineProfile<? extends VirtualMachine> vm, DeploymentPlan plan, ExcludeList avoid)
|
||||
throws InsufficientServerCapacityException;
|
||||
|
||||
PlannerResourceUsage getResourceUsage();
|
||||
|
||||
}
|
||||
@ -35,6 +35,7 @@ import com.cloud.vm.VirtualMachineProfile;
|
||||
/**
|
||||
*/
|
||||
public interface DeploymentPlanner extends Adapter {
|
||||
|
||||
/**
|
||||
* plan is called to determine where a virtual machine should be running.
|
||||
*
|
||||
@ -46,6 +47,7 @@ public interface DeploymentPlanner extends Adapter {
|
||||
* avoid these data centers, pods, clusters, or hosts.
|
||||
* @return DeployDestination for that virtual machine.
|
||||
*/
|
||||
@Deprecated
|
||||
DeployDestination plan(VirtualMachineProfile<? extends VirtualMachine> vm, DeploymentPlan plan, ExcludeList avoid) throws InsufficientServerCapacityException;
|
||||
|
||||
/**
|
||||
@ -88,6 +90,10 @@ public interface DeploymentPlanner extends Adapter {
|
||||
userconcentratedpod_firstfit;
|
||||
}
|
||||
|
||||
public enum PlannerResourceUsage {
|
||||
Shared, Dedicated;
|
||||
}
|
||||
|
||||
public static class ExcludeList {
|
||||
private Set<Long> _dcIds;
|
||||
private Set<Long> _podIds;
|
||||
@ -99,10 +105,22 @@ public interface DeploymentPlanner extends Adapter {
|
||||
}
|
||||
|
||||
public ExcludeList(Set<Long> _dcIds, Set<Long> _podIds, Set<Long> _clusterIds, Set<Long> _hostIds, Set<Long> _poolIds) {
|
||||
this._dcIds = _dcIds;
|
||||
this._podIds = _podIds;
|
||||
this._clusterIds = _clusterIds;
|
||||
this._poolIds = _poolIds;
|
||||
if (_dcIds != null) {
|
||||
this._dcIds = new HashSet<Long>(_dcIds);
|
||||
}
|
||||
if (_podIds != null) {
|
||||
this._podIds = new HashSet<Long>(_podIds);
|
||||
}
|
||||
if (_clusterIds != null) {
|
||||
this._clusterIds = new HashSet<Long>(_clusterIds);
|
||||
}
|
||||
|
||||
if (_hostIds != null) {
|
||||
this._hostIds = new HashSet<Long>(_hostIds);
|
||||
}
|
||||
if (_poolIds != null) {
|
||||
this._poolIds = new HashSet<Long>(_poolIds);
|
||||
}
|
||||
}
|
||||
|
||||
public boolean add(InsufficientCapacityException e) {
|
||||
|
||||
@ -423,6 +423,7 @@ public class EventTypes {
|
||||
public static final String EVENT_INTERNAL_LB_VM_START = "INTERNALLBVM.START";
|
||||
public static final String EVENT_INTERNAL_LB_VM_STOP = "INTERNALLBVM.STOP";
|
||||
|
||||
public static final String EVENT_HOST_RESERVATION_RELEASE = "HOST.RESERVATION.RELEASE";
|
||||
// Dedicated guest vlan range
|
||||
public static final String EVENT_GUEST_VLAN_RANGE_DEDICATE = "GUESTVLANRANGE.DEDICATE";
|
||||
public static final String EVENT_DEDICATED_GUEST_VLAN_RANGE_RELEASE = "GUESTVLANRANGE.RELEASE";
|
||||
@ -728,7 +729,6 @@ public class EventTypes {
|
||||
entityEventDetails.put(EVENT_AUTOSCALEVMGROUP_UPDATE, AutoScaleVmGroup.class.getName());
|
||||
entityEventDetails.put(EVENT_AUTOSCALEVMGROUP_ENABLE, AutoScaleVmGroup.class.getName());
|
||||
entityEventDetails.put(EVENT_AUTOSCALEVMGROUP_DISABLE, AutoScaleVmGroup.class.getName());
|
||||
|
||||
entityEventDetails.put(EVENT_GUEST_VLAN_RANGE_DEDICATE, GuestVlan.class.getName());
|
||||
entityEventDetails.put(EVENT_DEDICATED_GUEST_VLAN_RANGE_RELEASE, GuestVlan.class.getName());
|
||||
}
|
||||
|
||||
@ -108,4 +108,6 @@ public interface ServiceOffering extends InfrastructureEntity, InternalIdentity,
|
||||
boolean getDefaultUse();
|
||||
|
||||
String getSystemVmType();
|
||||
|
||||
String getDeploymentPlanner();
|
||||
}
|
||||
|
||||
@ -100,11 +100,13 @@ public interface ResourceService {
|
||||
Swift discoverSwift(AddSwiftCmd addSwiftCmd) throws DiscoveryException;
|
||||
|
||||
S3 discoverS3(AddS3Cmd cmd) throws DiscoveryException;
|
||||
|
||||
|
||||
List<HypervisorType> getSupportedHypervisorTypes(long zoneId, boolean forVirtualRouter, Long podId);
|
||||
|
||||
Pair<List<? extends Swift>, Integer> listSwifts(ListSwiftsCmd cmd);
|
||||
|
||||
List<? extends S3> listS3s(ListS3sCmd cmd);
|
||||
|
||||
boolean releaseHostReservation(Long hostId);
|
||||
|
||||
}
|
||||
|
||||
@ -419,5 +419,7 @@ public interface ManagementService {
|
||||
* @return List of capacities
|
||||
*/
|
||||
List<? extends Capacity> listTopConsumedResources(ListCapacityCmd cmd);
|
||||
|
||||
List<String> listDeploymentPlanners();
|
||||
|
||||
}
|
||||
|
||||
@ -496,6 +496,7 @@ public class ApiConstants {
|
||||
public static final String AFFINITY_GROUP_NAMES = "affinitygroupnames";
|
||||
public static final String ASA_INSIDE_PORT_PROFILE = "insideportprofile";
|
||||
public static final String AFFINITY_GROUP_ID = "affinitygroupid";
|
||||
public static final String DEPLOYMENT_PLANNER = "deploymentplanner";
|
||||
public static final String ACL_ID = "aclid";
|
||||
public static final String NUMBER = "number";
|
||||
|
||||
|
||||
@ -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);
|
||||
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,105 @@
|
||||
// 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.host;
|
||||
|
||||
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.HostResponse;
|
||||
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.user.Account;
|
||||
import com.cloud.user.UserContext;
|
||||
|
||||
@APICommand(name = "releaseHostReservation", description = "Releases host reservation.", responseObject = SuccessResponse.class)
|
||||
public class ReleaseHostReservationCmd extends BaseAsyncCmd {
|
||||
public static final Logger s_logger = Logger.getLogger(ReleaseHostReservationCmd.class.getName());
|
||||
|
||||
private static final String s_name = "releasehostreservationresponse";
|
||||
|
||||
/////////////////////////////////////////////////////
|
||||
//////////////// API parameters /////////////////////
|
||||
/////////////////////////////////////////////////////
|
||||
|
||||
@Parameter(name=ApiConstants.ID, type=CommandType.UUID, entityType=HostResponse.class,
|
||||
required=true, description="the host ID")
|
||||
private Long id;
|
||||
|
||||
/////////////////////////////////////////////////////
|
||||
/////////////////// Accessors ///////////////////////
|
||||
/////////////////////////////////////////////////////
|
||||
|
||||
public Long getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////
|
||||
/////////////// API Implementation///////////////////
|
||||
/////////////////////////////////////////////////////
|
||||
|
||||
@Override
|
||||
public String getCommandName() {
|
||||
return s_name;
|
||||
}
|
||||
|
||||
@Override
|
||||
public long getEntityOwnerId() {
|
||||
Account account = UserContext.current().getCaller();
|
||||
if (account != null) {
|
||||
return account.getId();
|
||||
}
|
||||
|
||||
return Account.ACCOUNT_ID_SYSTEM;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getEventType() {
|
||||
return EventTypes.EVENT_HOST_RESERVATION_RELEASE;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getEventDescription() {
|
||||
return "releasing reservation for host: " + getId();
|
||||
}
|
||||
|
||||
@Override
|
||||
public AsyncJob.Type getInstanceType() {
|
||||
return AsyncJob.Type.Host;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Long getInstanceId() {
|
||||
return getId();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void execute(){
|
||||
boolean result = _resourceService.releaseHostReservation(getId());
|
||||
if (result) {
|
||||
SuccessResponse response = new SuccessResponse(getCommandName());
|
||||
this.setResponseObject(response);
|
||||
} else {
|
||||
throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, "Failed to release host reservation");
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -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. If null, value of global config vm.deployment.planner is used")
|
||||
private String deploymentPlanner;
|
||||
|
||||
/////////////////////////////////////////////////////
|
||||
/////////////////// Accessors ///////////////////////
|
||||
/////////////////////////////////////////////////////
|
||||
@ -148,6 +151,9 @@ public class CreateServiceOfferingCmd extends BaseCmd {
|
||||
return networkRate;
|
||||
}
|
||||
|
||||
public String getDeploymentPlanner() {
|
||||
return deploymentPlanner;
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////
|
||||
/////////////// API Implementation///////////////////
|
||||
|
||||
@ -18,6 +18,8 @@ package org.apache.cloudstack.api.response;
|
||||
|
||||
import java.util.Date;
|
||||
|
||||
import javax.persistence.Column;
|
||||
|
||||
import org.apache.cloudstack.api.ApiConstants;
|
||||
import org.apache.cloudstack.api.BaseResponse;
|
||||
import org.apache.cloudstack.api.EntityReference;
|
||||
@ -82,6 +84,8 @@ public class ServiceOfferingResponse extends BaseResponse {
|
||||
@SerializedName(ApiConstants.NETWORKRATE) @Param(description="data transfer rate in megabits per second allowed.")
|
||||
private Integer networkRate;
|
||||
|
||||
@SerializedName(ApiConstants.DEPLOYMENT_PLANNER) @Param(description="deployment strategy used to deploy VM.")
|
||||
private String deploymentPlanner;
|
||||
|
||||
public String getId() {
|
||||
return id;
|
||||
@ -225,4 +229,12 @@ public class ServiceOfferingResponse extends BaseResponse {
|
||||
public void setNetworkRate(Integer networkRate) {
|
||||
this.networkRate = networkRate;
|
||||
}
|
||||
|
||||
public String getDeploymentPlanner() {
|
||||
return deploymentPlanner;
|
||||
}
|
||||
|
||||
public void setDeploymentPlanner(String deploymentPlanner) {
|
||||
this.deploymentPlanner = deploymentPlanner;
|
||||
}
|
||||
}
|
||||
|
||||
@ -540,15 +540,11 @@
|
||||
Deployment planners
|
||||
-->
|
||||
<bean id="UserDispersingPlanner" class="com.cloud.deploy.UserDispersingPlanner">
|
||||
<property name="name" value="UserDispersing"/>
|
||||
<property name="StoragePoolAllocators" value="#{storagePoolAllocators.Adapters}" />
|
||||
<property name="HostAllocators" value="#{hostAllocators.Adapters}" />
|
||||
<property name="name" value="UserDispersingPlanner"/>
|
||||
</bean>
|
||||
|
||||
<bean id="UserConcentratedPodPlanner" class="com.cloud.deploy.UserConcentratedPodPlanner">
|
||||
<property name="name" value="UserConcentratedPod"/>
|
||||
<property name="StoragePoolAllocators" value="#{storagePoolAllocators.Adapters}" />
|
||||
<property name="HostAllocators" value="#{hostAllocators.Adapters}" />
|
||||
<property name="name" value="UserConcentratedPodPlanner"/>
|
||||
</bean>
|
||||
|
||||
<bean id="clusterBasedAgentLoadBalancerPlanner" class="com.cloud.cluster.agentlb.ClusterBasedAgentLoadBalancerPlanner">
|
||||
@ -605,10 +601,6 @@
|
||||
<property name="name" value="OvmGuru"/>
|
||||
</bean>
|
||||
|
||||
<bean id="HypervisorPlannerSelector" class="com.cloud.deploy.HypervisorVmPlannerSelector">
|
||||
<property name="name" value="HypervisorPlannerSelector"/>
|
||||
</bean>
|
||||
|
||||
<!--
|
||||
Managers
|
||||
-->
|
||||
@ -623,6 +615,7 @@
|
||||
<property name="UserPasswordEncoders" value="#{userPasswordEncoders.Adapters}" />
|
||||
<property name="HostAllocators" value="#{hostAllocators.Adapters}" />
|
||||
<property name="AffinityGroupProcessors" value="#{affinityProcessors.Adapters}" />
|
||||
<property name="Planners" value="#{deploymentPlanners.Adapters}" />
|
||||
</bean>
|
||||
|
||||
<bean id="storageManagerImpl" class="com.cloud.storage.StorageManagerImpl">
|
||||
@ -630,9 +623,7 @@
|
||||
</bean>
|
||||
|
||||
<bean id="FirstFitPlanner" class="com.cloud.deploy.FirstFitPlanner">
|
||||
<property name="name" value="First Fit"/>
|
||||
<property name="StoragePoolAllocators" value="#{storagePoolAllocators.Adapters}" />
|
||||
<property name="HostAllocators" value="#{hostAllocators.Adapters}" />
|
||||
<property name="name" value="FirstFitPlanner"/>
|
||||
</bean>
|
||||
|
||||
<bean id="resourceManagerImpl" class="com.cloud.resource.ResourceManagerImpl" >
|
||||
@ -833,17 +824,13 @@
|
||||
</bean>
|
||||
|
||||
<bean id="BareMetalPlanner" class="com.cloud.baremetal.manager.BareMetalPlanner">
|
||||
<property name="name" value="BareMetal Fit"/>
|
||||
<property name="name" value="BareMetalPlanner"/>
|
||||
</bean>
|
||||
|
||||
<bean id="BaremetalGuru" class="com.cloud.baremetal.manager.BareMetalGuru">
|
||||
<property name="name" value="BaremetalGuru"/>
|
||||
</bean>
|
||||
|
||||
<bean id="BaremetalPlannerSelector" class="com.cloud.baremetal.manager.BaremetalPlannerSelector">
|
||||
<property name="name" value="BaremetalPlannerSelector"/>
|
||||
</bean>
|
||||
|
||||
<bean id="BaremetalManager" class="com.cloud.baremetal.manager.BaremetalManagerImpl"/>
|
||||
<bean id="BaremetalDhcpManager" class="com.cloud.baremetal.networkservice.BaremetalDhcpManagerImpl"/>
|
||||
<bean id="BaremetalKickStartPxeService" class="com.cloud.baremetal.networkservice.BaremetalKickStartServiceImpl"/>
|
||||
@ -859,6 +846,8 @@
|
||||
<bean id="DeploymentPlanningManager" class="com.cloud.deploy.DeploymentPlanningManagerImpl">
|
||||
<property name="Planners" value="#{deploymentPlanners.Adapters}" />
|
||||
<property name="AffinityGroupProcessors" value="#{affinityProcessors.Adapters}" />
|
||||
<property name="StoragePoolAllocators" value="#{storagePoolAllocators.Adapters}" />
|
||||
<property name="HostAllocators" value="#{hostAllocators.Adapters}" />
|
||||
</bean>
|
||||
|
||||
<bean id="AffinityGroupJoinDaoImpl" class="com.cloud.api.query.dao.AffinityGroupJoinDaoImpl">
|
||||
@ -868,4 +857,7 @@
|
||||
<bean id="AffinityGroupVMMapDaoImpl" class="org.apache.cloudstack.affinity.dao.AffinityGroupVMMapDaoImpl">
|
||||
</bean>
|
||||
|
||||
<bean id="PlannerHostReservationDaoImpl" class="com.cloud.deploy.dao.PlannerHostReservationDaoImpl">
|
||||
</bean>
|
||||
|
||||
</beans>
|
||||
|
||||
@ -212,6 +212,7 @@ listConfigurations=1
|
||||
ldapConfig=1
|
||||
ldapRemove=1
|
||||
listCapabilities=15
|
||||
listDeploymentPlanners=1
|
||||
|
||||
#### pod commands
|
||||
createPod=1
|
||||
@ -261,6 +262,7 @@ listHosts=3
|
||||
findHostsForMigration=1
|
||||
addSecondaryStorage=1
|
||||
updateHostPassword=1
|
||||
releaseHostReservation=1
|
||||
|
||||
#### volume commands
|
||||
attachVolume=15
|
||||
|
||||
@ -174,5 +174,10 @@ public class ServiceOffering21VO extends DiskOffering21VO implements ServiceOffe
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getDeploymentPlanner() {
|
||||
// TODO Auto-generated method stub
|
||||
return null;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@ -68,6 +68,9 @@ public class ServiceOfferingVO extends DiskOfferingVO implements ServiceOffering
|
||||
@Column(name="sort_key")
|
||||
int sortKey;
|
||||
|
||||
@Column(name = "deployment_planner")
|
||||
private String deploymentPlanner = null;
|
||||
|
||||
protected ServiceOfferingVO() {
|
||||
super();
|
||||
}
|
||||
@ -104,6 +107,15 @@ public class ServiceOfferingVO extends DiskOfferingVO implements ServiceOffering
|
||||
this.hostTag = hostTag;
|
||||
}
|
||||
|
||||
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);
|
||||
this.deploymentPlanner = deploymentPlanner;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean getOfferHA() {
|
||||
return offerHA;
|
||||
@ -208,4 +220,9 @@ public class ServiceOfferingVO extends DiskOfferingVO implements ServiceOffering
|
||||
return volatileVm;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getDeploymentPlanner() {
|
||||
return deploymentPlanner;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@ -17,6 +17,10 @@
|
||||
|
||||
package com.cloud.upgrade.dao;
|
||||
|
||||
import com.cloud.deploy.DeploymentPlanner;
|
||||
import com.cloud.utils.exception.CloudRuntimeException;
|
||||
import com.cloud.utils.script.Script;
|
||||
import org.apache.log4j.Logger;
|
||||
import java.io.File;
|
||||
import java.sql.Connection;
|
||||
import java.sql.Date;
|
||||
@ -25,12 +29,7 @@ import java.sql.ResultSet;
|
||||
import java.sql.SQLException;
|
||||
import java.sql.Types;
|
||||
import java.util.UUID;
|
||||
|
||||
import com.cloud.network.vpc.NetworkACL;
|
||||
import org.apache.log4j.Logger;
|
||||
|
||||
import com.cloud.utils.exception.CloudRuntimeException;
|
||||
import com.cloud.utils.script.Script;
|
||||
|
||||
public class Upgrade410to420 implements DbUpgrade {
|
||||
final static Logger s_logger = Logger.getLogger(Upgrade410to420.class);
|
||||
@ -70,6 +69,7 @@ public class Upgrade410to420 implements DbUpgrade {
|
||||
updatePrimaryStore(conn);
|
||||
addEgressFwRulesForSRXGuestNw(conn);
|
||||
upgradeEIPNetworkOfferings(conn);
|
||||
updateGlobalDeploymentPlanner(conn);
|
||||
upgradeDefaultVpcOffering(conn);
|
||||
upgradePhysicalNtwksWithInternalLbProvider(conn);
|
||||
updateNetworkACLs(conn);
|
||||
@ -563,6 +563,53 @@ public class Upgrade410to420 implements DbUpgrade {
|
||||
}
|
||||
}
|
||||
|
||||
private void updateGlobalDeploymentPlanner(Connection conn) {
|
||||
PreparedStatement pstmt = null;
|
||||
ResultSet rs = null;
|
||||
|
||||
try {
|
||||
pstmt = conn
|
||||
.prepareStatement("select value from `cloud`.`configuration` where name = 'vm.allocation.algorithm'");
|
||||
rs = pstmt.executeQuery();
|
||||
while (rs.next()) {
|
||||
String globalValue = rs.getString(1);
|
||||
String plannerName = "FirstFitPlanner";
|
||||
|
||||
if (globalValue != null) {
|
||||
if (globalValue.equals(DeploymentPlanner.AllocationAlgorithm.random.toString())) {
|
||||
plannerName = "FirstFitPlanner";
|
||||
} else if (globalValue.equals(DeploymentPlanner.AllocationAlgorithm.firstfit.toString())) {
|
||||
plannerName = "FirstFitPlanner";
|
||||
} else if (globalValue.equals(DeploymentPlanner.AllocationAlgorithm.userconcentratedpod_firstfit
|
||||
.toString())) {
|
||||
plannerName = "UserConcentratedPodPlanner";
|
||||
} else if (globalValue.equals(DeploymentPlanner.AllocationAlgorithm.userconcentratedpod_random
|
||||
.toString())) {
|
||||
plannerName = "UserConcentratedPodPlanner";
|
||||
} else if (globalValue.equals(DeploymentPlanner.AllocationAlgorithm.userdispersing.toString())) {
|
||||
plannerName = "UserDispersingPlanner";
|
||||
}
|
||||
}
|
||||
// update vm.deployment.planner global config
|
||||
pstmt = conn.prepareStatement("UPDATE `cloud`.`configuration` set value=? where name = 'vm.deployment.planner'");
|
||||
pstmt.setString(1, plannerName);
|
||||
pstmt.executeUpdate();
|
||||
}
|
||||
} catch (SQLException e) {
|
||||
throw new CloudRuntimeException("Unable to set vm.deployment.planner global config", e);
|
||||
} finally {
|
||||
try {
|
||||
if (rs != null) {
|
||||
rs.close();
|
||||
}
|
||||
if (pstmt != null) {
|
||||
pstmt.close();
|
||||
}
|
||||
} catch (SQLException e) {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private void upgradeDefaultVpcOffering(Connection conn) {
|
||||
PreparedStatement pstmt = null;
|
||||
@ -596,8 +643,6 @@ public class Upgrade410to420 implements DbUpgrade {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
private void upgradePhysicalNtwksWithInternalLbProvider(Connection conn) {
|
||||
|
||||
PreparedStatement pstmt = null;
|
||||
@ -644,7 +689,6 @@ public class Upgrade410to420 implements DbUpgrade {
|
||||
} catch (SQLException e) {
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private void addHostDetailsIndex(Connection conn) {
|
||||
|
||||
@ -38,14 +38,14 @@ public interface VMInstanceDao extends GenericDao<VMInstanceVO, Long>, StateDao<
|
||||
* @return list of VMInstanceVO running on that host.
|
||||
*/
|
||||
List<VMInstanceVO> listByHostId(long hostId);
|
||||
|
||||
|
||||
/**
|
||||
* List VMs by zone ID
|
||||
* @param zoneId
|
||||
* @return list of VMInstanceVO in the specified zone
|
||||
*/
|
||||
List<VMInstanceVO> listByZoneId(long zoneId);
|
||||
|
||||
|
||||
/**
|
||||
* List VMs by pod ID
|
||||
* @param podId
|
||||
@ -59,32 +59,32 @@ public interface VMInstanceDao extends GenericDao<VMInstanceVO, Long>, StateDao<
|
||||
* @return list of VMInstanceVO in the specified zone, deployed from the specified template, that are not expunged
|
||||
*/
|
||||
public List<VMInstanceVO> listNonExpungedByZoneAndTemplate(long zoneId, long templateId);
|
||||
|
||||
|
||||
/**
|
||||
* Find vm instance with names like.
|
||||
*
|
||||
*
|
||||
* @param name name that fits SQL like.
|
||||
* @return list of VMInstanceVO
|
||||
*/
|
||||
List<VMInstanceVO> findVMInstancesLike(String name);
|
||||
|
||||
|
||||
List<VMInstanceVO> findVMInTransition(Date time, State... states);
|
||||
|
||||
List<VMInstanceVO> listByTypes(VirtualMachine.Type... types);
|
||||
|
||||
|
||||
VMInstanceVO findByIdTypes(long id, VirtualMachine.Type... types);
|
||||
|
||||
|
||||
VMInstanceVO findVMByInstanceName(String name);
|
||||
|
||||
void updateProxyId(long id, Long proxyId, Date time);
|
||||
|
||||
List<VMInstanceVO> listByHostIdTypes(long hostid, VirtualMachine.Type... types);
|
||||
|
||||
|
||||
List<VMInstanceVO> listUpByHostIdTypes(long hostid, VirtualMachine.Type... types);
|
||||
List<VMInstanceVO> listByZoneIdAndType(long zoneId, VirtualMachine.Type type);
|
||||
List<VMInstanceVO> listUpByHostId(Long hostId);
|
||||
List<VMInstanceVO> listByLastHostId(Long hostId);
|
||||
|
||||
|
||||
List<VMInstanceVO> listByTypeAndState(VirtualMachine.Type type, State state);
|
||||
|
||||
List<VMInstanceVO> listByAccountId(long accountId);
|
||||
@ -92,9 +92,9 @@ public interface VMInstanceDao extends GenericDao<VMInstanceVO, Long>, StateDao<
|
||||
|
||||
List<VMInstanceVO> listByClusterId(long clusterId); // this does not pull up VMs which are starting
|
||||
List<VMInstanceVO> listLHByClusterId(long clusterId); // get all the VMs even starting one on this cluster
|
||||
|
||||
|
||||
List<VMInstanceVO> listVmsMigratingFromHost(Long hostId);
|
||||
|
||||
|
||||
public Long countRunningByHostId(long hostId);
|
||||
|
||||
Pair<List<Long>, Map<Long, Double>> listClusterIdsInZoneByVmCount(long zoneId, long accountId);
|
||||
@ -106,7 +106,7 @@ public interface VMInstanceDao extends GenericDao<VMInstanceVO, Long>, StateDao<
|
||||
List<Long> listHostIdsByVmCount(long dcId, Long podId, Long clusterId, long accountId);
|
||||
|
||||
Long countRunningByAccount(long accountId);
|
||||
|
||||
|
||||
List<VMInstanceVO> listNonRemovedVmsByTypeAndNetwork(long networkId, VirtualMachine.Type... types);
|
||||
|
||||
/**
|
||||
@ -116,4 +116,8 @@ public interface VMInstanceDao extends GenericDao<VMInstanceVO, Long>, StateDao<
|
||||
*/
|
||||
List<String> listDistinctHostNames(long networkId, VirtualMachine.Type... types);
|
||||
|
||||
List<VMInstanceVO> findByHostInStates(Long hostId, State... states);
|
||||
|
||||
List<VMInstanceVO> listStartingWithNoHostId();
|
||||
|
||||
}
|
||||
|
||||
@ -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,
|
||||
@ -83,30 +83,32 @@ public class VMInstanceDaoImpl extends GenericDaoBase<VMInstanceVO, Long> implem
|
||||
protected GenericSearchBuilder<VMInstanceVO, Long> CountRunningByAccount;
|
||||
protected SearchBuilder<VMInstanceVO> NetworkTypeSearch;
|
||||
protected GenericSearchBuilder<VMInstanceVO, String> DistinctHostNameSearch;
|
||||
|
||||
protected SearchBuilder<VMInstanceVO> HostAndStateSearch;
|
||||
protected SearchBuilder<VMInstanceVO> StartingWithNoHostSearch;
|
||||
|
||||
@Inject ResourceTagDao _tagsDao;
|
||||
@Inject NicDao _nicDao;
|
||||
|
||||
|
||||
protected Attribute _updateTimeAttr;
|
||||
|
||||
private static final String ORDER_CLUSTERS_NUMBER_OF_VMS_FOR_ACCOUNT_PART1 =
|
||||
|
||||
private static final String ORDER_CLUSTERS_NUMBER_OF_VMS_FOR_ACCOUNT_PART1 =
|
||||
"SELECT host.cluster_id, SUM(IF(vm.state='Running' AND vm.account_id = ?, 1, 0)) FROM `cloud`.`host` host LEFT JOIN `cloud`.`vm_instance` vm ON host.id = vm.host_id WHERE ";
|
||||
private static final String ORDER_CLUSTERS_NUMBER_OF_VMS_FOR_ACCOUNT_PART2 =
|
||||
" AND host.type = 'Routing' GROUP BY host.cluster_id ORDER BY 2 ASC ";
|
||||
|
||||
|
||||
private static final String ORDER_PODS_NUMBER_OF_VMS_FOR_ACCOUNT = "SELECT pod.id, SUM(IF(vm.state='Running' AND vm.account_id = ?, 1, 0)) FROM `cloud`.`host_pod_ref` pod LEFT JOIN `cloud`.`vm_instance` vm ON pod.id = vm.pod_id WHERE pod.data_center_id = ? " +
|
||||
" GROUP BY pod.id ORDER BY 2 ASC ";
|
||||
|
||||
|
||||
private static final String ORDER_HOSTS_NUMBER_OF_VMS_FOR_ACCOUNT =
|
||||
"SELECT host.id, SUM(IF(vm.state='Running' AND vm.account_id = ?, 1, 0)) FROM `cloud`.`host` host LEFT JOIN `cloud`.`vm_instance` vm ON host.id = vm.host_id WHERE host.data_center_id = ? " +
|
||||
" AND host.pod_id = ? AND host.cluster_id = ? AND host.type = 'Routing' " +
|
||||
" GROUP BY host.id ORDER BY 2 ASC ";
|
||||
|
||||
@Inject protected HostDao _hostDao;
|
||||
|
||||
|
||||
public VMInstanceDaoImpl() {
|
||||
}
|
||||
|
||||
|
||||
@PostConstruct
|
||||
protected void init() {
|
||||
|
||||
@ -114,14 +116,14 @@ public class VMInstanceDaoImpl extends GenericDaoBase<VMInstanceVO, Long> implem
|
||||
IdStatesSearch.and("id", IdStatesSearch.entity().getId(), Op.EQ);
|
||||
IdStatesSearch.and("states", IdStatesSearch.entity().getState(), Op.IN);
|
||||
IdStatesSearch.done();
|
||||
|
||||
|
||||
VMClusterSearch = createSearchBuilder();
|
||||
SearchBuilder<HostVO> hostSearch = _hostDao.createSearchBuilder();
|
||||
VMClusterSearch.join("hostSearch", hostSearch, hostSearch.entity().getId(), VMClusterSearch.entity().getHostId(), JoinType.INNER);
|
||||
hostSearch.and("clusterId", hostSearch.entity().getClusterId(), SearchCriteria.Op.EQ);
|
||||
VMClusterSearch.done();
|
||||
|
||||
|
||||
|
||||
LHVMClusterSearch = createSearchBuilder();
|
||||
SearchBuilder<HostVO> hostSearch1 = _hostDao.createSearchBuilder();
|
||||
LHVMClusterSearch.join("hostSearch1", hostSearch1, hostSearch1.entity().getId(), LHVMClusterSearch.entity().getLastHostId(), JoinType.INNER);
|
||||
@ -129,7 +131,7 @@ public class VMInstanceDaoImpl extends GenericDaoBase<VMInstanceVO, Long> implem
|
||||
hostSearch1.and("clusterId", hostSearch1.entity().getClusterId(), SearchCriteria.Op.EQ);
|
||||
LHVMClusterSearch.done();
|
||||
|
||||
|
||||
|
||||
AllFieldsSearch = createSearchBuilder();
|
||||
AllFieldsSearch.and("host", AllFieldsSearch.entity().getHostId(), Op.EQ);
|
||||
AllFieldsSearch.and("lastHost", AllFieldsSearch.entity().getLastHostId(), Op.EQ);
|
||||
@ -169,23 +171,23 @@ public class VMInstanceDaoImpl extends GenericDaoBase<VMInstanceVO, Long> implem
|
||||
IdTypesSearch.and("id", IdTypesSearch.entity().getId(), Op.EQ);
|
||||
IdTypesSearch.and("types", IdTypesSearch.entity().getType(), Op.IN);
|
||||
IdTypesSearch.done();
|
||||
|
||||
|
||||
HostIdTypesSearch = createSearchBuilder();
|
||||
HostIdTypesSearch.and("hostid", HostIdTypesSearch.entity().getHostId(), Op.EQ);
|
||||
HostIdTypesSearch.and("types", HostIdTypesSearch.entity().getType(), Op.IN);
|
||||
HostIdTypesSearch.done();
|
||||
|
||||
|
||||
HostIdUpTypesSearch = createSearchBuilder();
|
||||
HostIdUpTypesSearch.and("hostid", HostIdUpTypesSearch.entity().getHostId(), Op.EQ);
|
||||
HostIdUpTypesSearch.and("types", HostIdUpTypesSearch.entity().getType(), Op.IN);
|
||||
HostIdUpTypesSearch.and("states", HostIdUpTypesSearch.entity().getState(), Op.NIN);
|
||||
HostIdUpTypesSearch.done();
|
||||
|
||||
|
||||
HostUpSearch = createSearchBuilder();
|
||||
HostUpSearch.and("host", HostUpSearch.entity().getHostId(), Op.EQ);
|
||||
HostUpSearch.and("states", HostUpSearch.entity().getState(), Op.IN);
|
||||
HostUpSearch.done();
|
||||
|
||||
|
||||
InstanceNameSearch = createSearchBuilder();
|
||||
InstanceNameSearch.and("instanceName", InstanceNameSearch.entity().getInstanceName(), Op.EQ);
|
||||
InstanceNameSearch.done();
|
||||
@ -194,21 +196,31 @@ public class VMInstanceDaoImpl extends GenericDaoBase<VMInstanceVO, Long> implem
|
||||
CountVirtualRoutersByAccount.select(null, Func.COUNT, null);
|
||||
CountVirtualRoutersByAccount.and("account", CountVirtualRoutersByAccount.entity().getAccountId(), SearchCriteria.Op.EQ);
|
||||
CountVirtualRoutersByAccount.and("type", CountVirtualRoutersByAccount.entity().getType(), SearchCriteria.Op.EQ);
|
||||
CountVirtualRoutersByAccount.and("state", CountVirtualRoutersByAccount.entity().getState(), SearchCriteria.Op.NIN);
|
||||
CountVirtualRoutersByAccount.and("state", CountVirtualRoutersByAccount.entity().getState(), SearchCriteria.Op.NIN);
|
||||
CountVirtualRoutersByAccount.done();
|
||||
|
||||
|
||||
CountRunningByHost = createSearchBuilder(Long.class);
|
||||
CountRunningByHost.select(null, Func.COUNT, null);
|
||||
CountRunningByHost.and("host", CountRunningByHost.entity().getHostId(), SearchCriteria.Op.EQ);
|
||||
CountRunningByHost.and("state", CountRunningByHost.entity().getState(), SearchCriteria.Op.EQ);
|
||||
CountRunningByHost.done();
|
||||
CountRunningByHost.done();
|
||||
|
||||
CountRunningByAccount = createSearchBuilder(Long.class);
|
||||
CountRunningByAccount.select(null, Func.COUNT, null);
|
||||
CountRunningByAccount.and("account", CountRunningByAccount.entity().getAccountId(), SearchCriteria.Op.EQ);
|
||||
CountRunningByAccount.and("state", CountRunningByAccount.entity().getState(), SearchCriteria.Op.EQ);
|
||||
CountRunningByAccount.done();
|
||||
|
||||
CountRunningByAccount.done();
|
||||
|
||||
HostAndStateSearch = createSearchBuilder();
|
||||
HostAndStateSearch.and("host", HostAndStateSearch.entity().getHostId(), Op.EQ);
|
||||
HostAndStateSearch.and("states", HostAndStateSearch.entity().getState(), Op.IN);
|
||||
HostAndStateSearch.done();
|
||||
|
||||
StartingWithNoHostSearch = createSearchBuilder();
|
||||
StartingWithNoHostSearch.and("state", StartingWithNoHostSearch.entity().getState(), Op.EQ);
|
||||
StartingWithNoHostSearch.and("host", StartingWithNoHostSearch.entity().getHostId(), Op.NULL);
|
||||
StartingWithNoHostSearch.done();
|
||||
|
||||
_updateTimeAttr = _allAttributes.get("updateTime");
|
||||
assert _updateTimeAttr != null : "Couldn't get this updateTime attribute";
|
||||
}
|
||||
@ -219,7 +231,7 @@ public class VMInstanceDaoImpl extends GenericDaoBase<VMInstanceVO, Long> implem
|
||||
sc.setParameters("account", accountId);
|
||||
return listBy(sc);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public List<VMInstanceVO> findVMInstancesLike(String name) {
|
||||
SearchCriteria<VMInstanceVO> sc = NameLikeSearch.create();
|
||||
@ -234,7 +246,7 @@ public class VMInstanceDaoImpl extends GenericDaoBase<VMInstanceVO, Long> implem
|
||||
|
||||
return listBy(sc);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public List<VMInstanceVO> listByZoneId(long zoneId) {
|
||||
SearchCriteria<VMInstanceVO> sc = AllFieldsSearch.create();
|
||||
@ -242,7 +254,7 @@ public class VMInstanceDaoImpl extends GenericDaoBase<VMInstanceVO, Long> implem
|
||||
|
||||
return listBy(sc);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public List<VMInstanceVO> listByPodId(long podId) {
|
||||
SearchCriteria<VMInstanceVO> sc = AllFieldsSearch.create();
|
||||
@ -263,7 +275,7 @@ public class VMInstanceDaoImpl extends GenericDaoBase<VMInstanceVO, Long> implem
|
||||
sc.setJoinParameters("hostSearch1", "clusterId", clusterId);
|
||||
return listBy(sc);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public List<VMInstanceVO> listByZoneIdAndType(long zoneId, VirtualMachine.Type type) {
|
||||
SearchCriteria<VMInstanceVO> sc = AllFieldsSearch.create();
|
||||
@ -271,8 +283,8 @@ public class VMInstanceDaoImpl extends GenericDaoBase<VMInstanceVO, Long> implem
|
||||
sc.setParameters("type", type.toString());
|
||||
return listBy(sc);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
@Override
|
||||
public List<VMInstanceVO> listNonExpungedByZoneAndTemplate(long zoneId, long templateId) {
|
||||
SearchCriteria<VMInstanceVO> sc = ZoneTemplateNonExpungedSearch.create();
|
||||
@ -310,7 +322,7 @@ public class VMInstanceDaoImpl extends GenericDaoBase<VMInstanceVO, Long> implem
|
||||
sc.setParameters("states", new Object[] {State.Destroyed, State.Stopped, State.Expunging});
|
||||
return listBy(sc);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public List<VMInstanceVO> listUpByHostId(Long hostId) {
|
||||
SearchCriteria<VMInstanceVO> sc = HostUpSearch.create();
|
||||
@ -318,14 +330,14 @@ public class VMInstanceDaoImpl extends GenericDaoBase<VMInstanceVO, Long> implem
|
||||
sc.setParameters("states", new Object[] {State.Starting, State.Running});
|
||||
return listBy(sc);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public List<VMInstanceVO> listByTypes(Type... types) {
|
||||
SearchCriteria<VMInstanceVO> sc = TypesSearch.create();
|
||||
sc.setParameters("types", (Object[]) types);
|
||||
return listBy(sc);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public List<VMInstanceVO> listByTypeAndState(VirtualMachine.Type type, State state) {
|
||||
SearchCriteria<VMInstanceVO> sc = AllFieldsSearch.create();
|
||||
@ -348,7 +360,7 @@ public class VMInstanceDaoImpl extends GenericDaoBase<VMInstanceVO, Long> implem
|
||||
sc.setParameters("instanceName", name);
|
||||
return findOneBy(sc);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void updateProxyId(long id, Long proxyId, Date time) {
|
||||
VMInstanceVO vo = createForUpdate();
|
||||
@ -369,12 +381,12 @@ public class VMInstanceDaoImpl extends GenericDaoBase<VMInstanceVO, Long> implem
|
||||
@SuppressWarnings("unchecked")
|
||||
Pair<Long, Long> hosts = (Pair<Long,Long>)opaque;
|
||||
Long newHostId = hosts.second();
|
||||
|
||||
|
||||
VMInstanceVO vmi = (VMInstanceVO)vm;
|
||||
Long oldHostId = vmi.getHostId();
|
||||
Long oldUpdated = vmi.getUpdated();
|
||||
Date oldUpdateDate = vmi.getUpdateTime();
|
||||
|
||||
|
||||
SearchCriteria<VMInstanceVO> sc = StateChangeSearch.create();
|
||||
sc.setParameters("id", vmi.getId());
|
||||
sc.setParameters("states", oldState);
|
||||
@ -383,7 +395,7 @@ public class VMInstanceDaoImpl extends GenericDaoBase<VMInstanceVO, Long> implem
|
||||
|
||||
vmi.incrUpdated();
|
||||
UpdateBuilder ub = getUpdateBuilder(vmi);
|
||||
|
||||
|
||||
ub.set(vmi, "state", newState);
|
||||
ub.set(vmi, "hostId", newHostId);
|
||||
ub.set(vmi, "podIdToDeployIn", vmi.getPodIdToDeployIn());
|
||||
@ -393,7 +405,7 @@ public class VMInstanceDaoImpl extends GenericDaoBase<VMInstanceVO, Long> implem
|
||||
if (result == 0 && s_logger.isDebugEnabled()) {
|
||||
|
||||
VMInstanceVO vo = findByIdIncludingRemoved(vm.getId());
|
||||
|
||||
|
||||
if (vo != null) {
|
||||
StringBuilder str = new StringBuilder("Unable to update ").append(vo.toString());
|
||||
str.append(": DB Data={Host=").append(vo.getHostId()).append("; State=").append(vo.getState().toString()).append("; updated=").append(vo.getUpdated()).append("; time=").append(vo.getUpdateTime());
|
||||
@ -407,7 +419,7 @@ public class VMInstanceDaoImpl extends GenericDaoBase<VMInstanceVO, Long> implem
|
||||
}
|
||||
return result > 0;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public List<VMInstanceVO> listByLastHostId(Long hostId) {
|
||||
SearchCriteria<VMInstanceVO> sc = AllFieldsSearch.create();
|
||||
@ -415,7 +427,7 @@ public class VMInstanceDaoImpl extends GenericDaoBase<VMInstanceVO, Long> implem
|
||||
sc.setParameters("state", State.Stopped);
|
||||
return listBy(sc);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public Long countAllocatedVirtualRoutersForAccount(long accountId) {
|
||||
SearchCriteria<Long> sc = CountVirtualRoutersByAccount.create();
|
||||
@ -424,7 +436,7 @@ public class VMInstanceDaoImpl extends GenericDaoBase<VMInstanceVO, Long> implem
|
||||
sc.setParameters("state", new Object[] {State.Destroyed, State.Error, State.Expunging});
|
||||
return customSearch(sc, null).get(0);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public List<VMInstanceVO> listVmsMigratingFromHost(Long hostId) {
|
||||
SearchCriteria<VMInstanceVO> sc = AllFieldsSearch.create();
|
||||
@ -432,7 +444,7 @@ public class VMInstanceDaoImpl extends GenericDaoBase<VMInstanceVO, Long> implem
|
||||
sc.setParameters("state", State.Migrating);
|
||||
return listBy(sc);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public Long countRunningByHostId(long hostId){
|
||||
SearchCriteria<Long> sc = CountRunningByHost.create();
|
||||
@ -455,7 +467,7 @@ public class VMInstanceDaoImpl extends GenericDaoBase<VMInstanceVO, Long> implem
|
||||
pstmt = txn.prepareAutoCloseStatement(sql.toString());
|
||||
pstmt.setLong(1, accountId);
|
||||
pstmt.setLong(2, zoneId);
|
||||
|
||||
|
||||
ResultSet rs = pstmt.executeQuery();
|
||||
while (rs.next()) {
|
||||
Long clusterId = rs.getLong(1);
|
||||
@ -484,11 +496,11 @@ public class VMInstanceDaoImpl extends GenericDaoBase<VMInstanceVO, Long> implem
|
||||
pstmt = txn.prepareAutoCloseStatement(sql.toString());
|
||||
pstmt.setLong(1, accountId);
|
||||
pstmt.setLong(2, podId);
|
||||
|
||||
|
||||
ResultSet rs = pstmt.executeQuery();
|
||||
while (rs.next()) {
|
||||
Long clusterId = rs.getLong(1);
|
||||
result.add(clusterId);
|
||||
result.add(clusterId);
|
||||
clusterVmCountMap.put(clusterId, rs.getDouble(2));
|
||||
}
|
||||
return new Pair<List<Long>, Map<Long, Double>>(result, clusterVmCountMap);
|
||||
@ -511,11 +523,11 @@ public class VMInstanceDaoImpl extends GenericDaoBase<VMInstanceVO, Long> implem
|
||||
pstmt = txn.prepareAutoCloseStatement(sql);
|
||||
pstmt.setLong(1, accountId);
|
||||
pstmt.setLong(2, dataCenterId);
|
||||
|
||||
|
||||
ResultSet rs = pstmt.executeQuery();
|
||||
while (rs.next()) {
|
||||
Long podId = rs.getLong(1);
|
||||
result.add(podId);
|
||||
result.add(podId);
|
||||
podVmCountMap.put(podId, rs.getDouble(2));
|
||||
}
|
||||
return new Pair<List<Long>, Map<Long, Double>>(result, podVmCountMap);
|
||||
@ -523,7 +535,7 @@ public class VMInstanceDaoImpl extends GenericDaoBase<VMInstanceVO, Long> implem
|
||||
throw new CloudRuntimeException("DB Exception on: " + ORDER_PODS_NUMBER_OF_VMS_FOR_ACCOUNT, e);
|
||||
} catch (Throwable e) {
|
||||
throw new CloudRuntimeException("Caught: " + ORDER_PODS_NUMBER_OF_VMS_FOR_ACCOUNT, e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -538,7 +550,7 @@ public class VMInstanceDaoImpl extends GenericDaoBase<VMInstanceVO, Long> implem
|
||||
pstmt.setLong(2, dcId);
|
||||
pstmt.setLong(3, podId);
|
||||
pstmt.setLong(4, clusterId);
|
||||
|
||||
|
||||
ResultSet rs = pstmt.executeQuery();
|
||||
while (rs.next()) {
|
||||
result.add(rs.getLong(1));
|
||||
@ -548,9 +560,9 @@ public class VMInstanceDaoImpl extends GenericDaoBase<VMInstanceVO, Long> implem
|
||||
throw new CloudRuntimeException("DB Exception on: " + ORDER_PODS_NUMBER_OF_VMS_FOR_ACCOUNT, e);
|
||||
} catch (Throwable e) {
|
||||
throw new CloudRuntimeException("Caught: " + ORDER_PODS_NUMBER_OF_VMS_FOR_ACCOUNT, e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public Long countRunningByAccount(long accountId){
|
||||
SearchCriteria<Long> sc = CountRunningByAccount.create();
|
||||
@ -558,18 +570,18 @@ public class VMInstanceDaoImpl extends GenericDaoBase<VMInstanceVO, Long> implem
|
||||
sc.setParameters("state", State.Running);
|
||||
return customSearch(sc, null).get(0);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public List<VMInstanceVO> listNonRemovedVmsByTypeAndNetwork(long networkId, VirtualMachine.Type... types) {
|
||||
if (NetworkTypeSearch == null) {
|
||||
|
||||
|
||||
SearchBuilder<NicVO> nicSearch = _nicDao.createSearchBuilder();
|
||||
nicSearch.and("networkId", nicSearch.entity().getNetworkId(), SearchCriteria.Op.EQ);
|
||||
|
||||
NetworkTypeSearch = createSearchBuilder();
|
||||
NetworkTypeSearch.and("types", NetworkTypeSearch.entity().getType(), SearchCriteria.Op.IN);
|
||||
NetworkTypeSearch.and("removed", NetworkTypeSearch.entity().getRemoved(), SearchCriteria.Op.NULL);
|
||||
NetworkTypeSearch.join("nicSearch", nicSearch, NetworkTypeSearch.entity().getId(),
|
||||
NetworkTypeSearch.join("nicSearch", nicSearch, NetworkTypeSearch.entity().getId(),
|
||||
nicSearch.entity().getInstanceId(), JoinBuilder.JoinType.INNER);
|
||||
NetworkTypeSearch.done();
|
||||
}
|
||||
@ -577,27 +589,27 @@ public class VMInstanceDaoImpl extends GenericDaoBase<VMInstanceVO, Long> implem
|
||||
SearchCriteria<VMInstanceVO> sc = NetworkTypeSearch.create();
|
||||
if (types != null && types.length != 0) {
|
||||
sc.setParameters("types", (Object[]) types);
|
||||
}
|
||||
}
|
||||
sc.setJoinParameters("nicSearch", "networkId", networkId);
|
||||
|
||||
return listBy(sc);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@Override
|
||||
public List<String> listDistinctHostNames(long networkId, VirtualMachine.Type... types) {
|
||||
if (DistinctHostNameSearch == null) {
|
||||
|
||||
|
||||
SearchBuilder<NicVO> nicSearch = _nicDao.createSearchBuilder();
|
||||
nicSearch.and("networkId", nicSearch.entity().getNetworkId(), SearchCriteria.Op.EQ);
|
||||
|
||||
DistinctHostNameSearch = createSearchBuilder(String.class);
|
||||
DistinctHostNameSearch.selectField(DistinctHostNameSearch.entity().getHostName());
|
||||
|
||||
|
||||
DistinctHostNameSearch.and("types", DistinctHostNameSearch.entity().getType(), SearchCriteria.Op.IN);
|
||||
DistinctHostNameSearch.and("removed", DistinctHostNameSearch.entity().getRemoved(), SearchCriteria.Op.NULL);
|
||||
DistinctHostNameSearch.join("nicSearch", nicSearch, DistinctHostNameSearch.entity().getId(),
|
||||
DistinctHostNameSearch.join("nicSearch", nicSearch, DistinctHostNameSearch.entity().getId(),
|
||||
nicSearch.entity().getInstanceId(), JoinBuilder.JoinType.INNER);
|
||||
DistinctHostNameSearch.done();
|
||||
}
|
||||
@ -605,12 +617,12 @@ public class VMInstanceDaoImpl extends GenericDaoBase<VMInstanceVO, Long> implem
|
||||
SearchCriteria<String> sc = DistinctHostNameSearch.create();
|
||||
if (types != null && types.length != 0) {
|
||||
sc.setParameters("types", (Object[]) types);
|
||||
}
|
||||
}
|
||||
sc.setJoinParameters("nicSearch", "networkId", networkId);
|
||||
|
||||
return customSearch(sc, null);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
@DB
|
||||
public boolean remove(Long id) {
|
||||
@ -625,4 +637,19 @@ public class VMInstanceDaoImpl extends GenericDaoBase<VMInstanceVO, Long> implem
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<VMInstanceVO> findByHostInStates(Long hostId, State... states) {
|
||||
SearchCriteria<VMInstanceVO> sc = HostAndStateSearch.create();
|
||||
sc.setParameters("host", hostId);
|
||||
sc.setParameters("states", (Object[]) states);
|
||||
return listBy(sc);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<VMInstanceVO> listStartingWithNoHostId() {
|
||||
SearchCriteria<VMInstanceVO> sc = StartingWithNoHostSearch.create();
|
||||
sc.setParameters("state", State.Starting);
|
||||
return listBy(sc);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@ -50,7 +50,7 @@ public class ClusterScopeStoragePoolAllocator extends AbstractStoragePoolAllocat
|
||||
|
||||
@Override
|
||||
protected List<StoragePool> select(DiskProfile dskCh, VirtualMachineProfile<? extends VirtualMachine> vmProfile, DeploymentPlan plan, ExcludeList avoid, int returnUpTo) {
|
||||
|
||||
|
||||
s_logger.debug("ClusterScopeStoragePoolAllocator looking for storage pool");
|
||||
List<StoragePool> suitablePools = new ArrayList<StoragePool>();
|
||||
|
||||
@ -65,6 +65,14 @@ public class ClusterScopeStoragePoolAllocator extends AbstractStoragePoolAllocat
|
||||
}
|
||||
|
||||
List<StoragePoolVO> pools = _storagePoolDao.findPoolsByTags(dcId, podId, clusterId, dskCh.getTags());
|
||||
|
||||
// add remaining pools in cluster, that did not match tags, to avoid set
|
||||
List<StoragePoolVO> allPools = _storagePoolDao.findPoolsByTags(dcId, podId, clusterId, null);
|
||||
allPools.removeAll(pools);
|
||||
for (StoragePoolVO pool : allPools) {
|
||||
avoid.addPool(pool.getId());
|
||||
}
|
||||
|
||||
if (pools.size() == 0) {
|
||||
if (s_logger.isDebugEnabled()) {
|
||||
String storageType = dskCh.useLocalStorage() ? ServiceOffering.StorageType.local.toString() : ServiceOffering.StorageType.shared.toString();
|
||||
@ -72,7 +80,7 @@ public class ClusterScopeStoragePoolAllocator extends AbstractStoragePoolAllocat
|
||||
}
|
||||
return suitablePools;
|
||||
}
|
||||
|
||||
|
||||
for (StoragePoolVO pool: pools) {
|
||||
if(suitablePools.size() == returnUpTo){
|
||||
break;
|
||||
@ -80,13 +88,15 @@ public class ClusterScopeStoragePoolAllocator extends AbstractStoragePoolAllocat
|
||||
StoragePool pol = (StoragePool)this.dataStoreMgr.getPrimaryDataStore(pool.getId());
|
||||
if (filter(avoid, pol, dskCh, plan)) {
|
||||
suitablePools.add(pol);
|
||||
} else {
|
||||
avoid.addPool(pool.getId());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if (s_logger.isDebugEnabled()) {
|
||||
s_logger.debug("FirstFitStoragePoolAllocator returning "+suitablePools.size() +" suitable storage pools");
|
||||
}
|
||||
|
||||
|
||||
return suitablePools;
|
||||
}
|
||||
|
||||
|
||||
@ -74,7 +74,7 @@ public class LocalStoragePoolAllocator extends AbstractStoragePoolAllocator {
|
||||
if (!dskCh.useLocalStorage()) {
|
||||
return suitablePools;
|
||||
}
|
||||
|
||||
|
||||
// data disk and host identified from deploying vm (attach volume case)
|
||||
if (dskCh.getType() == Volume.Type.DATADISK && plan.getHostId() != null) {
|
||||
List<StoragePoolHostVO> hostPools = _poolHostDao.listByHostId(plan.getHostId());
|
||||
@ -85,7 +85,9 @@ public class LocalStoragePoolAllocator extends AbstractStoragePoolAllocator {
|
||||
if (filter(avoid, pol, dskCh, plan)) {
|
||||
s_logger.debug("Found suitable local storage pool " + pool.getId() + ", adding to list");
|
||||
suitablePools.add(pol);
|
||||
}
|
||||
} else {
|
||||
avoid.addPool(pool.getId());
|
||||
}
|
||||
}
|
||||
|
||||
if (suitablePools.size() == returnUpTo) {
|
||||
@ -101,8 +103,19 @@ public class LocalStoragePoolAllocator extends AbstractStoragePoolAllocator {
|
||||
StoragePool pol = (StoragePool)this.dataStoreMgr.getPrimaryDataStore(pool.getId());
|
||||
if (filter(avoid, pol, dskCh, plan)) {
|
||||
suitablePools.add(pol);
|
||||
}
|
||||
} else {
|
||||
avoid.addPool(pool.getId());
|
||||
}
|
||||
}
|
||||
|
||||
// add remaining pools in cluster, that did not match tags, to avoid
|
||||
// set
|
||||
List<StoragePoolVO> allPools = _storagePoolDao.findLocalStoragePoolsByTags(plan.getDataCenterId(),
|
||||
plan.getPodId(), plan.getClusterId(), null);
|
||||
allPools.removeAll(availablePools);
|
||||
for (StoragePoolVO pool : allPools) {
|
||||
avoid.addPool(pool.getId());
|
||||
}
|
||||
}
|
||||
|
||||
if (s_logger.isDebugEnabled()) {
|
||||
@ -111,7 +124,7 @@ public class LocalStoragePoolAllocator extends AbstractStoragePoolAllocator {
|
||||
|
||||
return suitablePools;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public boolean configure(String name, Map<String, Object> params) throws ConfigurationException {
|
||||
super.configure(name, params);
|
||||
|
||||
@ -39,18 +39,18 @@ import com.cloud.vm.VirtualMachineProfile;
|
||||
@Component
|
||||
public class ZoneWideStoragePoolAllocator extends AbstractStoragePoolAllocator {
|
||||
private static final Logger s_logger = Logger.getLogger(ZoneWideStoragePoolAllocator.class);
|
||||
@Inject PrimaryDataStoreDao _storagePoolDao;
|
||||
@Inject DataStoreManager dataStoreMgr;
|
||||
|
||||
@Inject PrimaryDataStoreDao _storagePoolDao;
|
||||
@Inject DataStoreManager dataStoreMgr;
|
||||
|
||||
@Override
|
||||
protected boolean filter(ExcludeList avoid, StoragePool pool, DiskProfile dskCh,
|
||||
protected boolean filter(ExcludeList avoid, StoragePool pool, DiskProfile dskCh,
|
||||
DeploymentPlan plan) {
|
||||
Volume volume = _volumeDao.findById(dskCh.getVolumeId());
|
||||
List<Volume> requestVolumes = new ArrayList<Volume>();
|
||||
requestVolumes.add(volume);
|
||||
return storageMgr.storagePoolHasEnoughSpace(requestVolumes, pool);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
protected List<StoragePool> select(DiskProfile dskCh,
|
||||
VirtualMachineProfile<? extends VirtualMachine> vmProfile,
|
||||
@ -64,9 +64,16 @@ public class ZoneWideStoragePoolAllocator extends AbstractStoragePoolAllocator {
|
||||
return suitablePools;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
List<StoragePoolVO> storagePools = _storagePoolDao.findZoneWideStoragePoolsByTags(plan.getDataCenterId(), dskCh.getTags());
|
||||
|
||||
|
||||
// add remaining pools in zone, that did not match tags, to avoid set
|
||||
List<StoragePoolVO> allPools = _storagePoolDao.findZoneWideStoragePoolsByTags(plan.getDataCenterId(), null);
|
||||
allPools.removeAll(storagePools);
|
||||
for (StoragePoolVO pool : allPools) {
|
||||
avoid.addPool(pool.getId());
|
||||
}
|
||||
|
||||
for (StoragePoolVO storage : storagePools) {
|
||||
if (suitablePools.size() == returnUpTo) {
|
||||
break;
|
||||
@ -74,7 +81,9 @@ public class ZoneWideStoragePoolAllocator extends AbstractStoragePoolAllocator {
|
||||
StoragePool pol = (StoragePool)this.dataStoreMgr.getPrimaryDataStore(storage.getId());
|
||||
if (filter(avoid, pol, dskCh, plan)) {
|
||||
suitablePools.add(pol);
|
||||
}
|
||||
} else {
|
||||
avoid.addPool(pol.getId());
|
||||
}
|
||||
}
|
||||
return suitablePools;
|
||||
}
|
||||
|
||||
@ -11,7 +11,7 @@
|
||||
// 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
|
||||
// KIND, either express or implied. See the License for the
|
||||
// specific language governing permissions and limitations
|
||||
// under the License.
|
||||
package com.cloud.deploy;
|
||||
@ -24,18 +24,17 @@ import javax.ejb.Local;
|
||||
|
||||
import org.apache.log4j.Logger;
|
||||
|
||||
import com.cloud.hypervisor.Hypervisor.HypervisorType;
|
||||
import com.cloud.utils.Pair;
|
||||
import com.cloud.vm.VirtualMachine;
|
||||
import com.cloud.vm.VirtualMachineProfile;
|
||||
|
||||
@Local(value=DeploymentPlanner.class)
|
||||
public class UserConcentratedPodPlanner extends FirstFitPlanner implements DeploymentPlanner {
|
||||
public class UserConcentratedPodPlanner extends FirstFitPlanner implements DeploymentClusterPlanner {
|
||||
|
||||
private static final Logger s_logger = Logger.getLogger(UserConcentratedPodPlanner.class);
|
||||
|
||||
|
||||
/**
|
||||
* This method should reorder the given list of Cluster Ids by applying any necessary heuristic
|
||||
* This method should reorder the given list of Cluster Ids by applying any necessary heuristic
|
||||
* for this planner
|
||||
* For UserConcentratedPodPlanner we need to order the clusters in a zone across pods, by considering those pods first which have more number of VMs for this account
|
||||
* This reordering is not done incase the clusters within single pod are passed when the allocation is applied at pod-level.
|
||||
@ -49,7 +48,7 @@ public class UserConcentratedPodPlanner extends FirstFitPlanner implements Deplo
|
||||
}
|
||||
return applyUserConcentrationPodHeuristicToClusters(id, clusterIdsByCapacity, vmProfile.getOwner().getAccountId());
|
||||
}
|
||||
|
||||
|
||||
private List<Long> applyUserConcentrationPodHeuristicToClusters(long zoneId, List<Long> prioritizedClusterIds, long accountId){
|
||||
//user has VMs in certain pods. - prioritize those pods first
|
||||
//UserConcentratedPod strategy
|
||||
@ -61,8 +60,8 @@ public class UserConcentratedPodPlanner extends FirstFitPlanner implements Deplo
|
||||
clusterList = prioritizedClusterIds;
|
||||
}
|
||||
return clusterList;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private List<Long> reorderClustersByPods(List<Long> clusterIds, List<Long> podIds) {
|
||||
|
||||
if (s_logger.isDebugEnabled()) {
|
||||
@ -111,11 +110,11 @@ public class UserConcentratedPodPlanner extends FirstFitPlanner implements Deplo
|
||||
|
||||
return prioritizedPods;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* This method should reorder the given list of Pod Ids by applying any necessary heuristic
|
||||
* This method should reorder the given list of Pod Ids by applying any necessary heuristic
|
||||
* for this planner
|
||||
* For UserConcentratedPodPlanner we need to order the pods by considering those pods first which have more number of VMs for this account
|
||||
* For UserConcentratedPodPlanner we need to order the pods by considering those pods first which have more number of VMs for this account
|
||||
* @return List<Long> ordered list of Pod Ids
|
||||
*/
|
||||
@Override
|
||||
@ -124,7 +123,7 @@ public class UserConcentratedPodPlanner extends FirstFitPlanner implements Deplo
|
||||
if(vmProfile.getOwner() == null){
|
||||
return podIdsByCapacity;
|
||||
}
|
||||
long accountId = vmProfile.getOwner().getAccountId();
|
||||
long accountId = vmProfile.getOwner().getAccountId();
|
||||
|
||||
//user has VMs in certain pods. - prioritize those pods first
|
||||
//UserConcentratedPod strategy
|
||||
@ -138,18 +137,7 @@ public class UserConcentratedPodPlanner extends FirstFitPlanner implements Deplo
|
||||
}else{
|
||||
return podIdsByCapacity;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean canHandle(VirtualMachineProfile<? extends VirtualMachine> vm, DeploymentPlan plan, ExcludeList avoid) {
|
||||
if(vm.getHypervisorType() != HypervisorType.BareMetal){
|
||||
//check the allocation strategy
|
||||
if (_allocationAlgorithm != null && (_allocationAlgorithm.equals(AllocationAlgorithm.userconcentratedpod_random.toString()) || _allocationAlgorithm.equals(AllocationAlgorithm.userconcentratedpod_firstfit.toString()))){
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@ -29,14 +29,13 @@ import javax.naming.ConfigurationException;
|
||||
import org.apache.log4j.Logger;
|
||||
|
||||
import com.cloud.configuration.Config;
|
||||
import com.cloud.hypervisor.Hypervisor.HypervisorType;
|
||||
import com.cloud.utils.NumbersUtil;
|
||||
import com.cloud.utils.Pair;
|
||||
import com.cloud.vm.VirtualMachine;
|
||||
import com.cloud.vm.VirtualMachineProfile;
|
||||
|
||||
@Local(value=DeploymentPlanner.class)
|
||||
public class UserDispersingPlanner extends FirstFitPlanner implements DeploymentPlanner {
|
||||
public class UserDispersingPlanner extends FirstFitPlanner implements DeploymentClusterPlanner {
|
||||
|
||||
private static final Logger s_logger = Logger.getLogger(UserDispersingPlanner.class);
|
||||
|
||||
@ -191,17 +190,6 @@ public class UserDispersingPlanner extends FirstFitPlanner implements Deployment
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public boolean canHandle(VirtualMachineProfile<? extends VirtualMachine> vm, DeploymentPlan plan, ExcludeList avoid) {
|
||||
if(vm.getHypervisorType() != HypervisorType.BareMetal){
|
||||
//check the allocation strategy
|
||||
if (_allocationAlgorithm != null && _allocationAlgorithm.equals(AllocationAlgorithm.userdispersing.toString())) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
float _userDispersionWeight;
|
||||
|
||||
|
||||
|
||||
@ -1,39 +0,0 @@
|
||||
// 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.baremetal.manager;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
import javax.ejb.Local;
|
||||
import javax.naming.ConfigurationException;
|
||||
|
||||
import com.cloud.deploy.AbstractDeployPlannerSelector;
|
||||
import com.cloud.deploy.DeployPlannerSelector;
|
||||
import com.cloud.hypervisor.Hypervisor.HypervisorType;
|
||||
import com.cloud.vm.UserVmVO;
|
||||
@Local(value = {DeployPlannerSelector.class})
|
||||
public class BaremetalPlannerSelector extends AbstractDeployPlannerSelector{
|
||||
|
||||
@Override
|
||||
public String selectPlanner(UserVmVO vm) {
|
||||
if (vm.getHypervisorType() == HypervisorType.BareMetal) {
|
||||
return "BareMetalPlanner";
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
}
|
||||
@ -90,6 +90,11 @@
|
||||
<artifactId>cloud-api</artifactId>
|
||||
<version>${project.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.apache.cloudstack</groupId>
|
||||
<artifactId>cloud-framework-ipc</artifactId>
|
||||
<version>${project.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.apache.cloudstack</groupId>
|
||||
<artifactId>cloud-framework-events</artifactId>
|
||||
|
||||
@ -78,7 +78,7 @@ public class FirstFitAllocator extends AdapterBase implements HostAllocator {
|
||||
@Inject ConsoleProxyDao _consoleProxyDao = null;
|
||||
@Inject SecondaryStorageVmDao _secStorgaeVmDao = null;
|
||||
@Inject ConfigurationDao _configDao = null;
|
||||
@Inject GuestOSDao _guestOSDao = null;
|
||||
@Inject GuestOSDao _guestOSDao = null;
|
||||
@Inject GuestOSCategoryDao _guestOSCategoryDao = null;
|
||||
@Inject VMInstanceDao _vmInstanceDao = null;
|
||||
@Inject ResourceManager _resourceMgr;
|
||||
@ -88,17 +88,17 @@ public class FirstFitAllocator extends AdapterBase implements HostAllocator {
|
||||
boolean _checkHvm = true;
|
||||
protected String _allocationAlgorithm = "random";
|
||||
@Inject CapacityManager _capacityMgr;
|
||||
|
||||
|
||||
|
||||
|
||||
@Override
|
||||
public List<Host> allocateTo(VirtualMachineProfile<? extends VirtualMachine> vmProfile, DeploymentPlan plan, Type type,
|
||||
ExcludeList avoid, int returnUpTo) {
|
||||
return allocateTo(vmProfile, plan, type, avoid, returnUpTo, true);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public List<Host> allocateTo(VirtualMachineProfile<? extends VirtualMachine> vmProfile, DeploymentPlan plan, Type type, ExcludeList avoid, int returnUpTo, boolean considerReservedCapacity) {
|
||||
|
||||
|
||||
long dcId = plan.getDataCenterId();
|
||||
Long podId = plan.getPodId();
|
||||
Long clusterId = plan.getClusterId();
|
||||
@ -110,19 +110,19 @@ public class FirstFitAllocator extends AdapterBase implements HostAllocator {
|
||||
// FirstFitAllocator should be used for user VMs only since it won't care whether the host is capable of routing or not
|
||||
return new ArrayList<Host>();
|
||||
}
|
||||
|
||||
|
||||
if(s_logger.isDebugEnabled()){
|
||||
s_logger.debug("Looking for hosts in dc: " + dcId + " pod:" + podId + " cluster:" + clusterId );
|
||||
}
|
||||
|
||||
|
||||
String hostTagOnOffering = offering.getHostTag();
|
||||
String hostTagOnTemplate = template.getTemplateTag();
|
||||
|
||||
|
||||
boolean hasSvcOfferingTag = hostTagOnOffering != null ? true : false;
|
||||
boolean hasTemplateTag = hostTagOnTemplate != null ? true : false;
|
||||
|
||||
|
||||
List<HostVO> clusterHosts = new ArrayList<HostVO>();
|
||||
|
||||
|
||||
String haVmTag = (String)vmProfile.getParameter(VirtualMachineProfile.Param.HaTag);
|
||||
if (haVmTag != null) {
|
||||
clusterHosts = _hostDao.listByHostTag(type, clusterId, podId, dcId, haVmTag);
|
||||
@ -133,31 +133,31 @@ public class FirstFitAllocator extends AdapterBase implements HostAllocator {
|
||||
List<HostVO> hostsMatchingOfferingTag = new ArrayList<HostVO>();
|
||||
List<HostVO> hostsMatchingTemplateTag = new ArrayList<HostVO>();
|
||||
if (hasSvcOfferingTag){
|
||||
if (s_logger.isDebugEnabled()){
|
||||
if (s_logger.isDebugEnabled()){
|
||||
s_logger.debug("Looking for hosts having tag specified on SvcOffering:" + hostTagOnOffering);
|
||||
}
|
||||
hostsMatchingOfferingTag = _hostDao.listByHostTag(type, clusterId, podId, dcId, hostTagOnOffering);
|
||||
if (s_logger.isDebugEnabled()){
|
||||
if (s_logger.isDebugEnabled()){
|
||||
s_logger.debug("Hosts with tag '" + hostTagOnOffering + "' are:" + hostsMatchingOfferingTag);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (hasTemplateTag){
|
||||
if (s_logger.isDebugEnabled()){
|
||||
if (s_logger.isDebugEnabled()){
|
||||
s_logger.debug("Looking for hosts having tag specified on Template:" + hostTagOnTemplate);
|
||||
}
|
||||
hostsMatchingTemplateTag = _hostDao.listByHostTag(type, clusterId, podId, dcId, hostTagOnTemplate);
|
||||
if (s_logger.isDebugEnabled()){
|
||||
hostsMatchingTemplateTag = _hostDao.listByHostTag(type, clusterId, podId, dcId, hostTagOnTemplate);
|
||||
if (s_logger.isDebugEnabled()){
|
||||
s_logger.debug("Hosts with tag '" + hostTagOnTemplate+"' are:" + hostsMatchingTemplateTag);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if (hasSvcOfferingTag && hasTemplateTag){
|
||||
hostsMatchingOfferingTag.retainAll(hostsMatchingTemplateTag);
|
||||
clusterHosts = _hostDao.listByHostTag(type, clusterId, podId, dcId, hostTagOnTemplate);
|
||||
if (s_logger.isDebugEnabled()){
|
||||
clusterHosts = _hostDao.listByHostTag(type, clusterId, podId, dcId, hostTagOnTemplate);
|
||||
if (s_logger.isDebugEnabled()){
|
||||
s_logger.debug("Found "+ hostsMatchingOfferingTag.size() +" Hosts satisfying both tags, host ids are:" + hostsMatchingOfferingTag);
|
||||
}
|
||||
|
||||
|
||||
clusterHosts = hostsMatchingOfferingTag;
|
||||
} else {
|
||||
if (hasSvcOfferingTag){
|
||||
@ -168,7 +168,14 @@ public class FirstFitAllocator extends AdapterBase implements HostAllocator {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// add all hosts that we are not considering to the avoid list
|
||||
List<HostVO> allhostsInCluster = _hostDao.listAllUpAndEnabledNonHAHosts(type, clusterId, podId, dcId, null);
|
||||
allhostsInCluster.removeAll(clusterHosts);
|
||||
for (HostVO host : allhostsInCluster) {
|
||||
avoid.addHost(host.getId());
|
||||
}
|
||||
|
||||
return allocateTo(plan, offering, template, avoid, clusterHosts, returnUpTo, considerReservedCapacity, account);
|
||||
}
|
||||
|
||||
@ -226,11 +233,11 @@ public class FirstFitAllocator extends AdapterBase implements HostAllocator {
|
||||
}else if(_allocationAlgorithm.equals("userdispersing")){
|
||||
hosts = reorderHostsByNumberOfVms(plan, hosts, account);
|
||||
}
|
||||
|
||||
|
||||
if (s_logger.isDebugEnabled()) {
|
||||
s_logger.debug("FirstFitAllocator has " + hosts.size() + " hosts to check for allocation: "+hosts);
|
||||
}
|
||||
|
||||
|
||||
// We will try to reorder the host lists such that we give priority to hosts that have
|
||||
// the minimums to support a VM's requirements
|
||||
hosts = prioritizeHosts(template, hosts);
|
||||
@ -242,7 +249,7 @@ public class FirstFitAllocator extends AdapterBase implements HostAllocator {
|
||||
if (s_logger.isDebugEnabled()) {
|
||||
s_logger.debug("Looking for speed=" + (offering.getCpu() * offering.getSpeed()) + "Mhz, Ram=" + offering.getRamSize());
|
||||
}
|
||||
|
||||
|
||||
List<Host> suitableHosts = new ArrayList<Host>();
|
||||
|
||||
for (HostVO host : hosts) {
|
||||
@ -255,7 +262,7 @@ public class FirstFitAllocator extends AdapterBase implements HostAllocator {
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
|
||||
//find number of guest VMs occupying capacity on this host.
|
||||
if (_capacityMgr.checkIfHostReachMaxGuestLimit(host)){
|
||||
if (s_logger.isDebugEnabled()) {
|
||||
@ -285,13 +292,14 @@ public class FirstFitAllocator extends AdapterBase implements HostAllocator {
|
||||
if (s_logger.isDebugEnabled()) {
|
||||
s_logger.debug("Not using host " + host.getId() + "; numCpusGood: " + numCpusGood + "; cpuFreqGood: " + cpuFreqGood + ", host has capacity?" + hostHasCapacity);
|
||||
}
|
||||
avoid.addHost(host.getId());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if (s_logger.isDebugEnabled()) {
|
||||
s_logger.debug("Host Allocator returning "+suitableHosts.size() +" suitable hosts");
|
||||
}
|
||||
|
||||
|
||||
return suitableHosts;
|
||||
}
|
||||
|
||||
@ -302,26 +310,26 @@ public class FirstFitAllocator extends AdapterBase implements HostAllocator {
|
||||
long dcId = plan.getDataCenterId();
|
||||
Long podId = plan.getPodId();
|
||||
Long clusterId = plan.getClusterId();
|
||||
|
||||
|
||||
List<Long> hostIdsByVmCount = _vmInstanceDao.listHostIdsByVmCount(dcId, podId, clusterId, account.getAccountId());
|
||||
if (s_logger.isDebugEnabled()) {
|
||||
s_logger.debug("List of hosts in ascending order of number of VMs: "+ hostIdsByVmCount);
|
||||
}
|
||||
|
||||
|
||||
//now filter the given list of Hosts by this ordered list
|
||||
Map<Long, HostVO> hostMap = new HashMap<Long, HostVO>();
|
||||
Map<Long, HostVO> hostMap = new HashMap<Long, HostVO>();
|
||||
for (HostVO host : hosts) {
|
||||
hostMap.put(host.getId(), host);
|
||||
}
|
||||
List<Long> matchingHostIds = new ArrayList<Long>(hostMap.keySet());
|
||||
|
||||
|
||||
hostIdsByVmCount.retainAll(matchingHostIds);
|
||||
|
||||
|
||||
List<HostVO> reorderedHosts = new ArrayList<HostVO>();
|
||||
for(Long id: hostIdsByVmCount){
|
||||
reorderedHosts.add(hostMap.get(id));
|
||||
}
|
||||
|
||||
|
||||
return reorderedHosts;
|
||||
}
|
||||
|
||||
@ -336,13 +344,13 @@ public class FirstFitAllocator extends AdapterBase implements HostAllocator {
|
||||
if (template == null) {
|
||||
return hosts;
|
||||
}
|
||||
|
||||
|
||||
// Determine the guest OS category of the template
|
||||
String templateGuestOSCategory = getTemplateGuestOSCategory(template);
|
||||
|
||||
|
||||
List<HostVO> prioritizedHosts = new ArrayList<HostVO>();
|
||||
List<HostVO> noHvmHosts = new ArrayList<HostVO>();
|
||||
|
||||
|
||||
// If a template requires HVM and a host doesn't support HVM, remove it from consideration
|
||||
List<HostVO> hostsToCheck = new ArrayList<HostVO>();
|
||||
if (template.isRequiresHvm()) {
|
||||
@ -356,7 +364,7 @@ public class FirstFitAllocator extends AdapterBase implements HostAllocator {
|
||||
} else {
|
||||
hostsToCheck.addAll(hosts);
|
||||
}
|
||||
|
||||
|
||||
if (s_logger.isDebugEnabled()) {
|
||||
if (noHvmHosts.size() > 0) {
|
||||
s_logger.debug("Not considering hosts: " + noHvmHosts + " to deploy template: " + template +" as they are not HVM enabled");
|
||||
@ -376,10 +384,10 @@ public class FirstFitAllocator extends AdapterBase implements HostAllocator {
|
||||
lowPriorityHosts.add(host);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
hostsToCheck.removeAll(highPriorityHosts);
|
||||
hostsToCheck.removeAll(lowPriorityHosts);
|
||||
|
||||
|
||||
// Prioritize the remaining hosts by HVM capability
|
||||
for (HostVO host : hostsToCheck) {
|
||||
if (!template.isRequiresHvm() && !hostSupportsHVM(host)) {
|
||||
@ -390,21 +398,21 @@ public class FirstFitAllocator extends AdapterBase implements HostAllocator {
|
||||
prioritizedHosts.add(host);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Merge the lists
|
||||
prioritizedHosts.addAll(0, highPriorityHosts);
|
||||
prioritizedHosts.addAll(lowPriorityHosts);
|
||||
|
||||
|
||||
return prioritizedHosts;
|
||||
}
|
||||
|
||||
|
||||
protected boolean hostSupportsHVM(HostVO host) {
|
||||
if ( !_checkHvm ) {
|
||||
return true;
|
||||
}
|
||||
// Determine host capabilities
|
||||
String caps = host.getCapabilities();
|
||||
|
||||
|
||||
if (caps != null) {
|
||||
String[] tokens = caps.split(",");
|
||||
for (String token : tokens) {
|
||||
@ -413,24 +421,24 @@ public class FirstFitAllocator extends AdapterBase implements HostAllocator {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
protected String getHostGuestOSCategory(HostVO host) {
|
||||
DetailVO hostDetail = _hostDetailsDao.findDetail(host.getId(), "guest.os.category.id");
|
||||
if (hostDetail != null) {
|
||||
String guestOSCategoryIdString = hostDetail.getValue();
|
||||
long guestOSCategoryId;
|
||||
|
||||
|
||||
try {
|
||||
guestOSCategoryId = Long.parseLong(guestOSCategoryIdString);
|
||||
} catch (Exception e) {
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
GuestOSCategoryVO guestOSCategory = _guestOSCategoryDao.findById(guestOSCategoryId);
|
||||
|
||||
|
||||
if (guestOSCategory != null) {
|
||||
return guestOSCategory.getName();
|
||||
} else {
|
||||
@ -440,7 +448,7 @@ public class FirstFitAllocator extends AdapterBase implements HostAllocator {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
protected String getTemplateGuestOSCategory(VMTemplateVO template) {
|
||||
long guestOSId = template.getGuestOSId();
|
||||
GuestOSVO guestOS = _guestOSDao.findById(guestOSId);
|
||||
@ -455,7 +463,7 @@ public class FirstFitAllocator extends AdapterBase implements HostAllocator {
|
||||
Map<String, String> configs = _configDao.getConfiguration(params);
|
||||
String opFactor = configs.get("cpu.overprovisioning.factor");
|
||||
_factor = NumbersUtil.parseFloat(opFactor, 1);
|
||||
|
||||
|
||||
String allocationAlgorithm = configs.get("vm.allocation.algorithm");
|
||||
if (allocationAlgorithm != null) {
|
||||
_allocationAlgorithm = allocationAlgorithm;
|
||||
|
||||
@ -73,6 +73,7 @@ public class ServiceOfferingJoinDaoImpl extends GenericDaoBase<ServiceOfferingJo
|
||||
offeringResponse.setDomainId(offering.getDomainUuid());
|
||||
offeringResponse.setNetworkRate(offering.getRateMbps());
|
||||
offeringResponse.setHostTag(offering.getHostTag());
|
||||
offeringResponse.setDeploymentPlanner(offering.getDeploymentPlanner());
|
||||
offeringResponse.setObjectName("serviceoffering");
|
||||
|
||||
return offeringResponse;
|
||||
|
||||
@ -106,6 +106,9 @@ public class ServiceOfferingJoinVO extends BaseViewVO implements InternalIdentit
|
||||
@Column(name="domain_path")
|
||||
private String domainPath = null;
|
||||
|
||||
@Column(name = "deployment_planner")
|
||||
private String deploymentPlanner;
|
||||
|
||||
|
||||
public ServiceOfferingJoinVO() {
|
||||
}
|
||||
@ -307,5 +310,13 @@ public class ServiceOfferingJoinVO extends BaseViewVO implements InternalIdentit
|
||||
this.vm_type = vm_type;
|
||||
}
|
||||
|
||||
public String getDeploymentPlanner() {
|
||||
return deploymentPlanner;
|
||||
}
|
||||
|
||||
public void setDeploymentPlanner(String deploymentPlanner) {
|
||||
this.deploymentPlanner = deploymentPlanner;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
@ -27,6 +27,8 @@ import javax.ejb.Local;
|
||||
import javax.inject.Inject;
|
||||
import javax.naming.ConfigurationException;
|
||||
|
||||
import org.apache.cloudstack.framework.messagebus.MessageBus;
|
||||
import org.apache.cloudstack.framework.messagebus.PublishScope;
|
||||
import org.apache.cloudstack.storage.datastore.db.StoragePoolVO;
|
||||
import org.apache.log4j.Logger;
|
||||
import org.springframework.stereotype.Component;
|
||||
@ -77,11 +79,14 @@ import com.cloud.utils.db.DB;
|
||||
import com.cloud.utils.db.SearchCriteria;
|
||||
import com.cloud.utils.db.Transaction;
|
||||
import com.cloud.utils.fsm.StateListener;
|
||||
import com.cloud.vm.UserVmDetailVO;
|
||||
import com.cloud.vm.UserVmVO;
|
||||
import com.cloud.vm.VMInstanceVO;
|
||||
import com.cloud.vm.VirtualMachine;
|
||||
import com.cloud.vm.VirtualMachine.Event;
|
||||
import com.cloud.vm.VirtualMachine.State;
|
||||
import com.cloud.vm.dao.UserVmDao;
|
||||
import com.cloud.vm.dao.UserVmDetailsDao;
|
||||
import com.cloud.vm.dao.VMInstanceDao;
|
||||
import com.cloud.vm.snapshot.VMSnapshot;
|
||||
import com.cloud.vm.snapshot.VMSnapshotVO;
|
||||
@ -121,6 +126,8 @@ public class CapacityManagerImpl extends ManagerBase implements CapacityManager,
|
||||
protected VMSnapshotDao _vmSnapshotDao;
|
||||
@Inject
|
||||
protected UserVmDao _userVMDao;
|
||||
@Inject
|
||||
protected UserVmDetailsDao _userVmDetailsDao;
|
||||
|
||||
@Inject
|
||||
ClusterDetailsDao _clusterDetailsDao;
|
||||
@ -132,6 +139,11 @@ public class CapacityManagerImpl extends ManagerBase implements CapacityManager,
|
||||
long _extraBytesPerVolume = 0;
|
||||
private float _storageOverProvisioningFactor = 1.0f;
|
||||
|
||||
@Inject
|
||||
MessageBus _messageBus;
|
||||
|
||||
private static final String MESSAGE_RESERVED_CAPACITY_FREED_FLAG = "Message.ReservedCapacityFreed.Flag";
|
||||
|
||||
@Override
|
||||
public boolean configure(String name, Map<String, Object> params) throws ConfigurationException {
|
||||
_vmCapacityReleaseInterval = NumbersUtil.parseInt(_configDao.getValue(Config.CapacitySkipcountingHours.key()), 3600);
|
||||
@ -552,6 +564,20 @@ public class CapacityManagerImpl extends ManagerBase implements CapacityManager,
|
||||
ServiceOffering so = offeringsMap.get(vm.getServiceOfferingId());
|
||||
reservedMemory += so.getRamSize() * 1024L * 1024L;
|
||||
reservedCpu += so.getCpu() * so.getSpeed();
|
||||
} else {
|
||||
// signal if not done already, that the VM has been stopped for skip.counting.hours,
|
||||
// hence capacity will not be reserved anymore.
|
||||
UserVmDetailVO messageSentFlag = _userVmDetailsDao.findDetail(vm.getId(), MESSAGE_RESERVED_CAPACITY_FREED_FLAG);
|
||||
if (messageSentFlag == null || !Boolean.valueOf(messageSentFlag.getValue())) {
|
||||
_messageBus.publish(_name, "VM_ReservedCapacity_Free", PublishScope.LOCAL, vm);
|
||||
|
||||
if (vm.getType() == VirtualMachine.Type.User) {
|
||||
UserVmVO userVM = _userVMDao.findById(vm.getId());
|
||||
_userVMDao.loadDetails(userVM);
|
||||
userVM.setDetail(MESSAGE_RESERVED_CAPACITY_FREED_FLAG, "true");
|
||||
_userVMDao.saveDetails(userVM);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -688,6 +714,18 @@ public class CapacityManagerImpl extends ManagerBase implements CapacityManager,
|
||||
allocateVmCapacity(vm, fromLastHost);
|
||||
}
|
||||
|
||||
if (newState == State.Stopped) {
|
||||
if (vm.getType() == VirtualMachine.Type.User) {
|
||||
|
||||
UserVmVO userVM = _userVMDao.findById(vm.getId());
|
||||
_userVMDao.loadDetails(userVM);
|
||||
// free the message sent flag if it exists
|
||||
userVM.setDetail(MESSAGE_RESERVED_CAPACITY_FREED_FLAG, "false");
|
||||
_userVMDao.saveDetails(userVM);
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
@ -214,6 +214,8 @@ public enum Config {
|
||||
SecStorageProxy("Advanced", AgentManager.class, String.class, "secstorage.proxy", null, "http proxy used by ssvm, in http://username:password@proxyserver:port format", null),
|
||||
AlertPurgeInterval("Advanced", ManagementServer.class, Integer.class, "alert.purge.interval", "86400", "The interval (in seconds) to wait before running the alert purge thread", null),
|
||||
AlertPurgeDelay("Advanced", ManagementServer.class, Integer.class, "alert.purge.delay", "0", "Alerts older than specified number days will be purged. Set this value to 0 to never delete alerts", null),
|
||||
HostReservationReleasePeriod("Advanced", ManagementServer.class, Integer.class, "host.reservation.release.period", "300000", "The interval in milliseconds between host reservation release checks", null),
|
||||
|
||||
|
||||
// LB HealthCheck Interval.
|
||||
LBHealthCheck("Advanced", ManagementServer.class, String.class, "healthcheck.update.interval", "600",
|
||||
@ -235,6 +237,7 @@ public enum Config {
|
||||
ApplyAllocationAlgorithmToPods("Advanced", ManagementServer.class, Boolean.class, "apply.allocation.algorithm.to.pods", "false", "If true, deployment planner applies the allocation heuristics at pods first in the given datacenter during VM resource allocation", "true,false"),
|
||||
VmUserDispersionWeight("Advanced", ManagementServer.class, Float.class, "vm.user.dispersion.weight", "1", "Weight for user dispersion heuristic (as a value between 0 and 1) applied to resource allocation during vm deployment. Weight for capacity heuristic will be (1 - weight of user dispersion)", null),
|
||||
VmAllocationAlgorithm("Advanced", ManagementServer.class, String.class, "vm.allocation.algorithm", "random", "'random', 'firstfit', 'userdispersing', 'userconcentratedpod_random', 'userconcentratedpod_firstfit' : Order in which hosts within a cluster will be considered for VM/volume allocation.", null),
|
||||
VmDeploymentPlanner("Advanced", ManagementServer.class, String.class, "vm.deployment.planner", "FirstFitPlanner", "'FirstFitPlanner', 'UserDispersingPlanner', 'UserConcentratedPodPlanner': DeploymentPlanner heuristic that will be used for VM deployment.", null),
|
||||
EndpointeUrl("Advanced", ManagementServer.class, String.class, "endpointe.url", "http://localhost:8080/client/api", "Endpointe Url", null),
|
||||
ElasticLoadBalancerEnabled("Advanced", ManagementServer.class, String.class, "network.loadbalancer.basiczone.elb.enabled", "false", "Whether the load balancing service is enabled for basic zones", "true,false"),
|
||||
ElasticLoadBalancerNetwork("Advanced", ManagementServer.class, String.class, "network.loadbalancer.basiczone.elb.network", "guest", "Whether the elastic load balancing service public ips are taken from the public or guest network", "guest,public"),
|
||||
|
||||
@ -79,10 +79,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
|
||||
|
||||
@ -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,
|
||||
@ -162,6 +162,7 @@ import com.cloud.org.Grouping.AllocationState;
|
||||
import com.cloud.projects.Project;
|
||||
import com.cloud.projects.ProjectManager;
|
||||
import com.cloud.server.ConfigurationServer;
|
||||
import com.cloud.server.ManagementService;
|
||||
import com.cloud.service.ServiceOfferingVO;
|
||||
import com.cloud.service.dao.ServiceOfferingDao;
|
||||
import com.cloud.storage.DiskOfferingVO;
|
||||
@ -302,7 +303,7 @@ public class ConfigurationManagerImpl extends ManagerBase implements Configurati
|
||||
@Inject
|
||||
AlertManager _alertMgr;
|
||||
// @com.cloud.utils.component.Inject(adapter = SecurityChecker.class)
|
||||
@Inject
|
||||
@Inject
|
||||
List<SecurityChecker> _secChecker;
|
||||
|
||||
@Inject
|
||||
@ -346,6 +347,9 @@ public class ConfigurationManagerImpl extends ManagerBase implements Configurati
|
||||
@Inject
|
||||
NicIpAliasDao _nicIpAliasDao;
|
||||
|
||||
@Inject
|
||||
public ManagementService _mgr;
|
||||
|
||||
// FIXME - why don't we have interface for DataCenterLinkLocalIpAddressDao?
|
||||
@Inject protected DataCenterLinkLocalIpAddressDao _LinkLocalIpAllocDao;
|
||||
|
||||
@ -356,11 +360,11 @@ public class ConfigurationManagerImpl extends ManagerBase implements Configurati
|
||||
@Override
|
||||
public boolean configure(final String name, final Map<String, Object> params) throws ConfigurationException {
|
||||
String maxVolumeSizeInGbString = _configDao.getValue(Config.MaxVolumeSize.key());
|
||||
_maxVolumeSizeInGb = NumbersUtil.parseInt(maxVolumeSizeInGbString,
|
||||
_maxVolumeSizeInGb = NumbersUtil.parseInt(maxVolumeSizeInGbString,
|
||||
Integer.parseInt(Config.MaxVolumeSize.getDefaultValue()));
|
||||
|
||||
String defaultPageSizeString = _configDao.getValue(Config.DefaultPageSize.key());
|
||||
_defaultPageSize = NumbersUtil.parseLong(defaultPageSizeString,
|
||||
_defaultPageSize = NumbersUtil.parseLong(defaultPageSizeString,
|
||||
Long.parseLong(Config.DefaultPageSize.getDefaultValue()));
|
||||
|
||||
populateConfigValuesForValidationSet();
|
||||
@ -920,7 +924,7 @@ public class ConfigurationManagerImpl extends ManagerBase implements Configurati
|
||||
checkPodCidrSubnets(zoneId, podId, cidr);
|
||||
/*
|
||||
* Commenting out due to Bug 11593 - CIDR conflicts with zone when extending pod but not when creating it
|
||||
*
|
||||
*
|
||||
* checkCidrVlanOverlap(zoneId, cidr);
|
||||
*/
|
||||
}
|
||||
@ -1713,7 +1717,7 @@ public class ConfigurationManagerImpl extends ManagerBase implements Configurati
|
||||
if (internalDns2 == null) {
|
||||
internalDns2 = zone.getInternalDns2();
|
||||
}
|
||||
|
||||
|
||||
if (guestCidr == null) {
|
||||
guestCidr = zone.getGuestNetworkCidr();
|
||||
}
|
||||
@ -2034,17 +2038,29 @@ public class ConfigurationManagerImpl extends ManagerBase implements Configurati
|
||||
throw new InvalidParameterValueException("Network rate can be specified only for non-System offering and system offerings having \"domainrouter\" systemvmtype");
|
||||
}
|
||||
|
||||
if (cmd.getDeploymentPlanner() != null) {
|
||||
List<String> planners = _mgr.listDeploymentPlanners();
|
||||
if (planners != null && !planners.isEmpty()) {
|
||||
if (!planners.contains(cmd.getDeploymentPlanner())) {
|
||||
throw new InvalidParameterValueException(
|
||||
"Invalid name for Deployment Planner specified, please use listDeploymentPlanners to get the valid set");
|
||||
}
|
||||
} else {
|
||||
throw new InvalidParameterValueException("No deployment planners found");
|
||||
}
|
||||
}
|
||||
|
||||
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());
|
||||
@ -2328,9 +2344,9 @@ public class ConfigurationManagerImpl extends ManagerBase implements Configurati
|
||||
String endIPv6 = cmd.getEndIpv6();
|
||||
String ip6Gateway = cmd.getIp6Gateway();
|
||||
String ip6Cidr = cmd.getIp6Cidr();
|
||||
|
||||
|
||||
Account vlanOwner = null;
|
||||
|
||||
|
||||
boolean ipv4 = (startIP != null);
|
||||
boolean ipv6 = (startIPv6 != null);
|
||||
|
||||
@ -2387,7 +2403,7 @@ public class ConfigurationManagerImpl extends ManagerBase implements Configurati
|
||||
} else if (ipv6) {
|
||||
throw new InvalidParameterValueException("Only support IPv6 on extending existed network");
|
||||
}
|
||||
|
||||
|
||||
// Verify that zone exists
|
||||
DataCenterVO zone = _zoneDao.findById(zoneId);
|
||||
if (zone == null) {
|
||||
@ -2434,18 +2450,18 @@ public class ConfigurationManagerImpl extends ManagerBase implements Configurati
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
// Check if zone is enabled
|
||||
Account caller = UserContext.current().getCaller();
|
||||
if (Grouping.AllocationState.Disabled == zone.getAllocationState() && !_accountMgr.isRootAdmin(caller.getType())) {
|
||||
throw new PermissionDeniedException("Cannot perform this operation, Zone is currently disabled: " + zoneId);
|
||||
}
|
||||
}
|
||||
|
||||
if (zone.isSecurityGroupEnabled() && zone.getNetworkType() != DataCenter.NetworkType.Basic && forVirtualNetwork) {
|
||||
throw new InvalidParameterValueException("Can't add virtual ip range into a zone with security group enabled");
|
||||
}
|
||||
|
||||
|
||||
// If networkId is not specified, and vlan is Virtual or Direct Untagged, try to locate default networks
|
||||
if (forVirtualNetwork) {
|
||||
if (network == null) {
|
||||
@ -2604,35 +2620,35 @@ public class ConfigurationManagerImpl extends ManagerBase implements Configurati
|
||||
String startIP, String endIP, String vlanGateway, String vlanNetmask,
|
||||
String vlanId, Account vlanOwner, String startIPv6, String endIPv6, String vlanIp6Gateway, String vlanIp6Cidr) {
|
||||
Network network = _networkModel.getNetwork(networkId);
|
||||
|
||||
|
||||
boolean ipv4 = false, ipv6 = false;
|
||||
|
||||
|
||||
if (startIP != null) {
|
||||
ipv4 = true;
|
||||
}
|
||||
|
||||
|
||||
if (startIPv6 != null) {
|
||||
ipv6 = true;
|
||||
}
|
||||
|
||||
|
||||
if (!ipv4 && !ipv6) {
|
||||
throw new InvalidParameterValueException("Please specify IPv4 or IPv6 address.");
|
||||
}
|
||||
|
||||
|
||||
//Validate the zone
|
||||
DataCenterVO zone = _zoneDao.findById(zoneId);
|
||||
if (zone == null) {
|
||||
throw new InvalidParameterValueException("Please specify a valid zone.");
|
||||
}
|
||||
|
||||
|
||||
// ACL check
|
||||
checkZoneAccess(UserContext.current().getCaller(), zone);
|
||||
|
||||
|
||||
//Validate the physical network
|
||||
if (_physicalNetworkDao.findById(physicalNetworkId) == null) {
|
||||
throw new InvalidParameterValueException("Please specify a valid physical network id");
|
||||
}
|
||||
|
||||
|
||||
//Validate the pod
|
||||
if (podId != null) {
|
||||
Pod pod = _podDao.findById(podId);
|
||||
@ -2644,11 +2660,11 @@ public class ConfigurationManagerImpl extends ManagerBase implements Configurati
|
||||
}
|
||||
//pod vlans can be created in basic zone only
|
||||
if (zone.getNetworkType() != NetworkType.Basic || network.getTrafficType() != TrafficType.Guest) {
|
||||
throw new InvalidParameterValueException("Pod id can be specified only for the networks of type "
|
||||
+ TrafficType.Guest + " in zone of type " + NetworkType.Basic);
|
||||
throw new InvalidParameterValueException("Pod id can be specified only for the networks of type "
|
||||
+ TrafficType.Guest + " in zone of type " + NetworkType.Basic);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//1) if vlan is specified for the guest network range, it should be the same as network's vlan
|
||||
//2) if vlan is missing, default it to the guest network's vlan
|
||||
if (network.getTrafficType() == TrafficType.Guest) {
|
||||
@ -2660,7 +2676,7 @@ public class ConfigurationManagerImpl extends ManagerBase implements Configurati
|
||||
//For pvlan
|
||||
networkVlanId = networkVlanId.split("-")[0];
|
||||
}
|
||||
|
||||
|
||||
if (vlanId != null) {
|
||||
// if vlan is specified, throw an error if it's not equal to network's vlanId
|
||||
if (networkVlanId != null && !networkVlanId.equalsIgnoreCase(vlanId)) {
|
||||
@ -2673,14 +2689,14 @@ public class ConfigurationManagerImpl extends ManagerBase implements Configurati
|
||||
//vlan id is required for public network
|
||||
throw new InvalidParameterValueException("Vlan id is required when add ip range to the public network");
|
||||
}
|
||||
|
||||
|
||||
if (vlanId == null) {
|
||||
vlanId = Vlan.UNTAGGED;
|
||||
}
|
||||
|
||||
VlanType vlanType = forVirtualNetwork ? VlanType.VirtualNetwork : VlanType.DirectAttached;
|
||||
|
||||
|
||||
|
||||
|
||||
if (vlanOwner != null && zone.getNetworkType() != NetworkType.Advanced) {
|
||||
throw new InvalidParameterValueException("Vlan owner can be defined only in the zone of type " + NetworkType.Advanced);
|
||||
}
|
||||
@ -2696,7 +2712,7 @@ public class ConfigurationManagerImpl extends ManagerBase implements Configurati
|
||||
throw new InvalidParameterValueException("Please specify a valid netmask");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if (ipv6) {
|
||||
if (!NetUtils.isValidIpv6(vlanIp6Gateway)) {
|
||||
throw new InvalidParameterValueException("Please specify a valid IPv6 gateway");
|
||||
@ -2751,7 +2767,7 @@ public class ConfigurationManagerImpl extends ManagerBase implements Configurati
|
||||
List<VlanVO> vlans = _vlanDao.listByZone(zone.getId());
|
||||
for (VlanVO vlan : vlans) {
|
||||
String otherVlanGateway = vlan.getVlanGateway();
|
||||
// Continue if it's not IPv4
|
||||
// Continue if it's not IPv4
|
||||
if (otherVlanGateway == null) {
|
||||
continue;
|
||||
}
|
||||
@ -2787,14 +2803,14 @@ public class ConfigurationManagerImpl extends ManagerBase implements Configurati
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
String ipv6Range = null;
|
||||
if (ipv6) {
|
||||
ipv6Range = startIPv6;
|
||||
if (endIPv6 != null) {
|
||||
ipv6Range += "-" + endIPv6;
|
||||
}
|
||||
|
||||
|
||||
List<VlanVO> vlans = _vlanDao.listByZone(zone.getId());
|
||||
for (VlanVO vlan : vlans) {
|
||||
if (vlan.getIp6Gateway() == null) {
|
||||
@ -2820,14 +2836,14 @@ public class ConfigurationManagerImpl extends ManagerBase implements Configurati
|
||||
}
|
||||
|
||||
String ipRange = null;
|
||||
|
||||
|
||||
if (ipv4) {
|
||||
ipRange = startIP;
|
||||
if (endIP != null) {
|
||||
ipRange += "-" + endIP;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Everything was fine, so persist the VLAN
|
||||
Transaction txn = Transaction.currentTxn();
|
||||
txn.start();
|
||||
@ -2839,7 +2855,7 @@ public class ConfigurationManagerImpl extends ManagerBase implements Configurati
|
||||
// IPv6 use a used ip map, is different from ipv4, no need to save public ip range
|
||||
if (ipv4) {
|
||||
if (!savePublicIPRange(startIP, endIP, zoneId, vlan.getId(), networkId, physicalNetworkId)) {
|
||||
throw new CloudRuntimeException("Failed to save IPv4 range. Please contact Cloud Support.");
|
||||
throw new CloudRuntimeException("Failed to save IPv4 range. Please contact Cloud Support.");
|
||||
}
|
||||
}
|
||||
|
||||
@ -2875,7 +2891,7 @@ public class ConfigurationManagerImpl extends ManagerBase implements Configurati
|
||||
if (vlanRange == null) {
|
||||
throw new InvalidParameterValueException("Please specify a valid IP range id.");
|
||||
}
|
||||
|
||||
|
||||
boolean isAccountSpecific = false;
|
||||
List<AccountVlanMapVO> acctVln = _accountVlanMapDao.listAccountVlanMapsByVlan(vlanRange.getId());
|
||||
// Check for account wide pool. It will have an entry for account_vlan_map.
|
||||
@ -2888,7 +2904,7 @@ public class ConfigurationManagerImpl extends ManagerBase implements Configurati
|
||||
List<IPAddressVO> ips = _publicIpAddressDao.listByVlanId(vlanDbId);
|
||||
boolean success = true;
|
||||
if (allocIpCount > 0) {
|
||||
if (isAccountSpecific) {
|
||||
if (isAccountSpecific) {
|
||||
try {
|
||||
vlanRange = _vlanDao.acquireInLockTable(vlanDbId, 30);
|
||||
if (vlanRange == null) {
|
||||
@ -2901,7 +2917,7 @@ public class ConfigurationManagerImpl extends ManagerBase implements Configurati
|
||||
|
||||
for (IPAddressVO ip : ips) {
|
||||
if (ip.isOneToOneNat()) {
|
||||
throw new InvalidParameterValueException("Can't delete account specific vlan " + vlanDbId +
|
||||
throw new InvalidParameterValueException("Can't delete account specific vlan " + vlanDbId +
|
||||
" as ip " + ip + " belonging to the range is used for static nat purposes. Cleanup the rules first");
|
||||
}
|
||||
|
||||
@ -2910,9 +2926,9 @@ public class ConfigurationManagerImpl extends ManagerBase implements Configurati
|
||||
" as ip " + ip + " belonging to the range is a source nat ip for the network id=" + ip.getSourceNetworkId() +
|
||||
". IP range with the source nat ip address can be removed either as a part of Network, or account removal");
|
||||
}
|
||||
|
||||
|
||||
if (_firewallDao.countRulesByIpId(ip.getId()) > 0) {
|
||||
throw new InvalidParameterValueException("Can't delete account specific vlan " + vlanDbId +
|
||||
throw new InvalidParameterValueException("Can't delete account specific vlan " + vlanDbId +
|
||||
" as ip " + ip + " belonging to the range has firewall rules applied. Cleanup the rules first");
|
||||
}
|
||||
//release public ip address here
|
||||
@ -3268,7 +3284,7 @@ public class ConfigurationManagerImpl extends ManagerBase implements Configurati
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
|
||||
@DB
|
||||
protected boolean savePublicIPRange(String startIP, String endIP, long zoneId, long vlanDbId, long sourceNetworkid, long physicalNetworkId) {
|
||||
@ -3471,7 +3487,7 @@ public class ConfigurationManagerImpl extends ManagerBase implements Configurati
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
private boolean validPod(long podId) {
|
||||
return (_podDao.findById(podId) != null);
|
||||
}
|
||||
@ -3690,7 +3706,7 @@ public class ConfigurationManagerImpl extends ManagerBase implements Configurati
|
||||
if (provider == Provider.JuniperSRX || provider == Provider.CiscoVnmc) {
|
||||
firewallProvider = provider;
|
||||
}
|
||||
|
||||
|
||||
if ((service == Service.PortForwarding || service == Service.StaticNat) && provider == Provider.VirtualRouter){
|
||||
firewallProvider = Provider.VirtualRouter;
|
||||
}
|
||||
@ -3890,7 +3906,7 @@ public class ConfigurationManagerImpl extends ManagerBase implements Configurati
|
||||
if (!specifyVlan && type == GuestType.Shared) {
|
||||
throw new InvalidParameterValueException("SpecifyVlan should be true if network offering's type is " + type);
|
||||
}
|
||||
|
||||
|
||||
//specifyIpRanges should always be true for Shared networks
|
||||
//specifyIpRanges can only be true for Isolated networks with no Source Nat service
|
||||
if (specifyIpRanges) {
|
||||
@ -3914,7 +3930,7 @@ public class ConfigurationManagerImpl extends ManagerBase implements Configurati
|
||||
if (availability == NetworkOffering.Availability.Required) {
|
||||
boolean canOffBeRequired = (type == GuestType.Isolated && serviceProviderMap.containsKey(Service.SourceNat));
|
||||
if (!canOffBeRequired) {
|
||||
throw new InvalidParameterValueException("Availability can be " + NetworkOffering.Availability.Required
|
||||
throw new InvalidParameterValueException("Availability can be " + NetworkOffering.Availability.Required
|
||||
+ " only for networkOfferings of type " + GuestType.Isolated + " and with "
|
||||
+ Service.SourceNat.getName() + " enabled");
|
||||
}
|
||||
@ -3922,11 +3938,11 @@ public class ConfigurationManagerImpl extends ManagerBase implements Configurati
|
||||
// only one network offering in the system can be Required
|
||||
List<NetworkOfferingVO> offerings = _networkOfferingDao.listByAvailability(Availability.Required, false);
|
||||
if (!offerings.isEmpty()) {
|
||||
throw new InvalidParameterValueException("System already has network offering id=" + offerings.get(0).getId()
|
||||
throw new InvalidParameterValueException("System already has network offering id=" + offerings.get(0).getId()
|
||||
+ " with availability " + Availability.Required);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
boolean dedicatedLb = false;
|
||||
boolean elasticLb = false;
|
||||
boolean sharedSourceNat = false;
|
||||
@ -3938,7 +3954,7 @@ public class ConfigurationManagerImpl extends ManagerBase implements Configurati
|
||||
boolean internalLb = false;
|
||||
if (serviceCapabilityMap != null && !serviceCapabilityMap.isEmpty()) {
|
||||
Map<Capability, String> lbServiceCapabilityMap = serviceCapabilityMap.get(Service.Lb);
|
||||
|
||||
|
||||
if ((lbServiceCapabilityMap != null) && (!lbServiceCapabilityMap.isEmpty())) {
|
||||
String isolationCapability = lbServiceCapabilityMap.get(Capability.SupportedLBIsolation);
|
||||
if (isolationCapability != null) {
|
||||
@ -3952,7 +3968,7 @@ public class ConfigurationManagerImpl extends ManagerBase implements Configurati
|
||||
if (param != null) {
|
||||
elasticLb = param.contains("true");
|
||||
}
|
||||
|
||||
|
||||
String inlineMode = lbServiceCapabilityMap.get(Capability.InlineMode);
|
||||
if (inlineMode != null) {
|
||||
_networkModel.checkCapabilityForProvider(serviceProviderMap.get(Service.Lb), Service.Lb, Capability.InlineMode, inlineMode);
|
||||
@ -3983,14 +3999,14 @@ public class ConfigurationManagerImpl extends ManagerBase implements Configurati
|
||||
if ((sourceNatServiceCapabilityMap != null) && (!sourceNatServiceCapabilityMap.isEmpty())) {
|
||||
String sourceNatType = sourceNatServiceCapabilityMap.get(Capability.SupportedSourceNatTypes);
|
||||
if (sourceNatType != null) {
|
||||
_networkModel.checkCapabilityForProvider(serviceProviderMap.get(Service.SourceNat), Service.SourceNat,
|
||||
_networkModel.checkCapabilityForProvider(serviceProviderMap.get(Service.SourceNat), Service.SourceNat,
|
||||
Capability.SupportedSourceNatTypes, sourceNatType);
|
||||
sharedSourceNat = sourceNatType.contains("perzone");
|
||||
}
|
||||
|
||||
String param = sourceNatServiceCapabilityMap.get(Capability.RedundantRouter);
|
||||
if (param != null) {
|
||||
_networkModel.checkCapabilityForProvider(serviceProviderMap.get(Service.SourceNat), Service.SourceNat,
|
||||
_networkModel.checkCapabilityForProvider(serviceProviderMap.get(Service.SourceNat), Service.SourceNat,
|
||||
Capability.RedundantRouter, param);
|
||||
redundantRouter = param.contains("true");
|
||||
}
|
||||
@ -4009,7 +4025,7 @@ public class ConfigurationManagerImpl extends ManagerBase implements Configurati
|
||||
}
|
||||
}
|
||||
|
||||
NetworkOfferingVO offering = new NetworkOfferingVO(name, displayText, trafficType, systemOnly, specifyVlan,
|
||||
NetworkOfferingVO offering = new NetworkOfferingVO(name, displayText, trafficType, systemOnly, specifyVlan,
|
||||
networkRate, multicastRate, isDefault, availability, tags, type, conserveMode, dedicatedLb,
|
||||
sharedSourceNat, redundantRouter, elasticIp, elasticLb, specifyIpRanges, inline, isPersistent, associatePublicIp, publicLb, internalLb);
|
||||
|
||||
@ -4041,7 +4057,7 @@ public class ConfigurationManagerImpl extends ManagerBase implements Configurati
|
||||
_ntwkOffServiceMapDao.persist(offService);
|
||||
s_logger.trace("Added service for the network offering: " + offService + " with provider " + provider.getName());
|
||||
}
|
||||
|
||||
|
||||
if (vpcOff) {
|
||||
List<Service> supportedSvcs = new ArrayList<Service>();
|
||||
supportedSvcs.addAll(serviceProviderMap.keySet());
|
||||
@ -4251,7 +4267,7 @@ public class ConfigurationManagerImpl extends ManagerBase implements Configurati
|
||||
// filter by supported services
|
||||
boolean listBySupportedServices = (supportedServicesStr != null && !supportedServicesStr.isEmpty() && !offerings.isEmpty());
|
||||
boolean checkIfProvidersAreEnabled = (zoneId != null);
|
||||
boolean parseOfferings = (listBySupportedServices || sourceNatSupported != null || checkIfProvidersAreEnabled
|
||||
boolean parseOfferings = (listBySupportedServices || sourceNatSupported != null || checkIfProvidersAreEnabled
|
||||
|| forVpc != null || network != null);
|
||||
|
||||
if (parseOfferings) {
|
||||
@ -4299,7 +4315,7 @@ public class ConfigurationManagerImpl extends ManagerBase implements Configurati
|
||||
if (sourceNatSupported != null) {
|
||||
addOffering = addOffering && (_networkModel.areServicesSupportedByNetworkOffering(offering.getId(), Network.Service.SourceNat) == sourceNatSupported);
|
||||
}
|
||||
|
||||
|
||||
if (forVpc != null) {
|
||||
addOffering = addOffering && (isOfferingForVpc(offering) == forVpc.booleanValue());
|
||||
} else if (network != null){
|
||||
@ -4418,14 +4434,14 @@ public class ConfigurationManagerImpl extends ManagerBase implements Configurati
|
||||
}
|
||||
}
|
||||
if (availability == null) {
|
||||
throw new InvalidParameterValueException("Invalid value for Availability. Supported types: "
|
||||
throw new InvalidParameterValueException("Invalid value for Availability. Supported types: "
|
||||
+ Availability.Required + ", " + Availability.Optional);
|
||||
} else {
|
||||
if (availability == NetworkOffering.Availability.Required) {
|
||||
boolean canOffBeRequired = (offeringToUpdate.getGuestType() == GuestType.Isolated
|
||||
boolean canOffBeRequired = (offeringToUpdate.getGuestType() == GuestType.Isolated
|
||||
&& _networkModel.areServicesSupportedByNetworkOffering(offeringToUpdate.getId(), Service.SourceNat));
|
||||
if (!canOffBeRequired) {
|
||||
throw new InvalidParameterValueException("Availability can be " +
|
||||
throw new InvalidParameterValueException("Availability can be " +
|
||||
NetworkOffering.Availability.Required + " only for networkOfferings of type " + GuestType.Isolated + " and with "
|
||||
+ Service.SourceNat.getName() + " enabled");
|
||||
}
|
||||
@ -4433,7 +4449,7 @@ public class ConfigurationManagerImpl extends ManagerBase implements Configurati
|
||||
// only one network offering in the system can be Required
|
||||
List<NetworkOfferingVO> offerings = _networkOfferingDao.listByAvailability(Availability.Required, false);
|
||||
if (!offerings.isEmpty() && offerings.get(0).getId() != offeringToUpdate.getId()) {
|
||||
throw new InvalidParameterValueException("System already has network offering id=" +
|
||||
throw new InvalidParameterValueException("System already has network offering id=" +
|
||||
offerings.get(0).getId() + " with availability " + Availability.Required);
|
||||
}
|
||||
}
|
||||
@ -4452,7 +4468,7 @@ public class ConfigurationManagerImpl extends ManagerBase implements Configurati
|
||||
@ActionEvent(eventType = EventTypes.EVENT_ACCOUNT_MARK_DEFAULT_ZONE, eventDescription = "Marking account with the " +
|
||||
"default zone", async=true)
|
||||
public AccountVO markDefaultZone(String accountName, long domainId, long defaultZoneId) {
|
||||
|
||||
|
||||
// Check if the account exists
|
||||
Account account = _accountDao.findEnabledAccount(accountName, domainId);
|
||||
if (account == null) {
|
||||
@ -4466,9 +4482,9 @@ public class ConfigurationManagerImpl extends ManagerBase implements Configurati
|
||||
}
|
||||
|
||||
AccountVO acctForUpdate = _accountDao.findById(account.getId());
|
||||
|
||||
|
||||
acctForUpdate.setDefaultZoneId(defaultZoneId);
|
||||
|
||||
|
||||
if (_accountDao.update(account.getId(), acctForUpdate)) {
|
||||
UserContext.current().setEventDetails("Default zone id= " + defaultZoneId);
|
||||
return _accountDao.findById(account.getId());
|
||||
@ -4476,7 +4492,7 @@ public class ConfigurationManagerImpl extends ManagerBase implements Configurati
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Note: This method will be used for entity name validations in the coming
|
||||
// releases (place holder for now)
|
||||
private void validateEntityName(String str) {
|
||||
@ -4604,10 +4620,10 @@ public class ConfigurationManagerImpl extends ManagerBase implements Configurati
|
||||
public ClusterVO getCluster(long id) {
|
||||
return _clusterDao.findById(id);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public AllocationState findClusterAllocationState(ClusterVO cluster){
|
||||
|
||||
|
||||
if(cluster.getAllocationState() == AllocationState.Disabled){
|
||||
return AllocationState.Disabled;
|
||||
}else if(ApiDBUtils.findPodById(cluster.getPodId()).getAllocationState() == AllocationState.Disabled){
|
||||
@ -4615,20 +4631,20 @@ public class ConfigurationManagerImpl extends ManagerBase implements Configurati
|
||||
}else {
|
||||
DataCenterVO zone = ApiDBUtils.findZoneById(cluster.getDataCenterId());
|
||||
return zone.getAllocationState();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public AllocationState findPodAllocationState(HostPodVO pod){
|
||||
|
||||
|
||||
if(pod.getAllocationState() == AllocationState.Disabled){
|
||||
return AllocationState.Disabled;
|
||||
}else {
|
||||
DataCenterVO zone = ApiDBUtils.findZoneById(pod.getDataCenterId());
|
||||
return zone.getAllocationState();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private boolean allowIpRangeOverlap(VlanVO vlan, boolean forVirtualNetwork, long networkId) {
|
||||
// FIXME - delete restriction for virtual network in the future
|
||||
if (vlan.getVlanType() == VlanType.DirectAttached && !forVirtualNetwork) {
|
||||
|
||||
@ -1,84 +0,0 @@
|
||||
// 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.Map;
|
||||
|
||||
import javax.inject.Inject;
|
||||
import javax.naming.ConfigurationException;
|
||||
|
||||
import com.cloud.configuration.Config;
|
||||
import com.cloud.configuration.dao.ConfigurationDao;
|
||||
import com.cloud.utils.component.AdapterBase;
|
||||
import com.cloud.vm.UserVmVO;
|
||||
|
||||
public abstract class AbstractDeployPlannerSelector extends AdapterBase implements DeployPlannerSelector {
|
||||
protected Map<String, Object> params;
|
||||
protected String name;
|
||||
protected int runLevel;
|
||||
|
||||
@Inject
|
||||
protected ConfigurationDao _configDao;
|
||||
protected String _allocationAlgorithm = "random";
|
||||
|
||||
@Override
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setName(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setConfigParams(Map<String, Object> params) {
|
||||
this.params = params;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Map<String, Object> getConfigParams() {
|
||||
return params;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getRunLevel() {
|
||||
return runLevel;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setRunLevel(int level) {
|
||||
this.runLevel = level;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean configure(String name, Map<String, Object> params) throws ConfigurationException {
|
||||
super.configure(name, params);
|
||||
_allocationAlgorithm = _configDao.getValue(Config.VmAllocationAlgorithm.key());
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean start() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean stop() {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
@ -49,6 +49,7 @@ import com.cloud.dc.Pod;
|
||||
import com.cloud.dc.dao.ClusterDao;
|
||||
import com.cloud.dc.dao.DataCenterDao;
|
||||
import com.cloud.dc.dao.HostPodDao;
|
||||
import com.cloud.deploy.DeploymentPlanner.ExcludeList;
|
||||
import com.cloud.exception.InsufficientServerCapacityException;
|
||||
import com.cloud.host.Host;
|
||||
import com.cloud.host.HostVO;
|
||||
@ -81,7 +82,7 @@ import com.cloud.vm.dao.UserVmDao;
|
||||
import com.cloud.vm.dao.VMInstanceDao;
|
||||
|
||||
@Local(value=DeploymentPlanner.class)
|
||||
public class FirstFitPlanner extends PlannerBase implements DeploymentPlanner {
|
||||
public class FirstFitPlanner extends PlannerBase implements DeploymentClusterPlanner {
|
||||
private static final Logger s_logger = Logger.getLogger(FirstFitPlanner.class);
|
||||
@Inject protected HostDao _hostDao;
|
||||
@Inject protected DataCenterDao _dcDao;
|
||||
@ -103,28 +104,13 @@ public class FirstFitPlanner extends PlannerBase implements DeploymentPlanner {
|
||||
@Inject DataStoreManager dataStoreMgr;
|
||||
@Inject protected ClusterDetailsDao _clusterDetailsDao;
|
||||
|
||||
protected List<StoragePoolAllocator> _storagePoolAllocators;
|
||||
public List<StoragePoolAllocator> getStoragePoolAllocators() {
|
||||
return _storagePoolAllocators;
|
||||
}
|
||||
public void setStoragePoolAllocators(
|
||||
List<StoragePoolAllocator> _storagePoolAllocators) {
|
||||
this._storagePoolAllocators = _storagePoolAllocators;
|
||||
}
|
||||
|
||||
protected List<HostAllocator> _hostAllocators;
|
||||
public List<HostAllocator> getHostAllocators() {
|
||||
return _hostAllocators;
|
||||
}
|
||||
public void setHostAllocators(List<HostAllocator> _hostAllocators) {
|
||||
this._hostAllocators = _hostAllocators;
|
||||
}
|
||||
|
||||
protected String _allocationAlgorithm = "random";
|
||||
protected String _globalDeploymentPlanner = "FirstFitPlanner";
|
||||
|
||||
|
||||
@Override
|
||||
public DeployDestination plan(VirtualMachineProfile<? extends VirtualMachine> vmProfile,
|
||||
public List<Long> orderClusters(VirtualMachineProfile<? extends VirtualMachine> vmProfile,
|
||||
DeploymentPlan plan, ExcludeList avoid)
|
||||
throws InsufficientServerCapacityException {
|
||||
VirtualMachine vm = vmProfile.getVirtualMachine();
|
||||
@ -138,136 +124,19 @@ public class FirstFitPlanner extends PlannerBase implements DeploymentPlanner {
|
||||
return null;
|
||||
}
|
||||
|
||||
ServiceOffering offering = vmProfile.getServiceOffering();
|
||||
int cpu_requested = offering.getCpu() * offering.getSpeed();
|
||||
long ram_requested = offering.getRamSize() * 1024L * 1024L;
|
||||
|
||||
|
||||
if (s_logger.isDebugEnabled()) {
|
||||
s_logger.debug("DeploymentPlanner allocation algorithm: "+_allocationAlgorithm);
|
||||
|
||||
s_logger.debug("Trying to allocate a host and storage pools from dc:" + plan.getDataCenterId() + ", pod:" + plan.getPodId() + ",cluster:" + plan.getClusterId() +
|
||||
", requested cpu: " + cpu_requested + ", requested ram: " + ram_requested);
|
||||
|
||||
s_logger.debug("Is ROOT volume READY (pool already allocated)?: " + (plan.getPoolId()!=null ? "Yes": "No"));
|
||||
}
|
||||
|
||||
String haVmTag = (String)vmProfile.getParameter(VirtualMachineProfile.Param.HaTag);
|
||||
|
||||
if(plan.getHostId() != null && haVmTag == null){
|
||||
Long hostIdSpecified = plan.getHostId();
|
||||
if (s_logger.isDebugEnabled()){
|
||||
s_logger.debug("DeploymentPlan has host_id specified, choosing this host and making no checks on this host: "
|
||||
+ hostIdSpecified);
|
||||
}
|
||||
HostVO host = _hostDao.findById(hostIdSpecified);
|
||||
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());
|
||||
|
||||
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);
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
||||
}
|
||||
s_logger.debug("Cannnot deploy to specified host, returning.");
|
||||
return null;
|
||||
}
|
||||
|
||||
if (vm.getLastHostId() != null && haVmTag == null) {
|
||||
s_logger.debug("This VM has last host_id specified, trying to choose the same host: " +vm.getLastHostId());
|
||||
|
||||
HostVO host = _hostDao.findById(vm.getLastHostId());
|
||||
if(host == null){
|
||||
s_logger.debug("The last host of this VM cannot be found");
|
||||
}else if(avoid.shouldAvoid(host)){
|
||||
s_logger.debug("The last host of this VM is in avoid set");
|
||||
}else if(_capacityMgr.checkIfHostReachMaxGuestLimit(host)){
|
||||
s_logger.debug("The last Host, hostId: "+ host.getId() +" already has max Running VMs(count includes system VMs), skipping this and trying other available hosts");
|
||||
}else{
|
||||
if (host.getStatus() == Status.Up && host.getResourceState() == ResourceState.Enabled) {
|
||||
long cluster_id = host.getClusterId();
|
||||
ClusterDetailsVO cluster_detail_cpu = _clusterDetailsDao.findDetail(cluster_id,"cpuOvercommitRatio");
|
||||
ClusterDetailsVO cluster_detail_ram = _clusterDetailsDao.findDetail(cluster_id,"memoryOvercommitRatio");
|
||||
Float cpuOvercommitRatio = Float.parseFloat(cluster_detail_cpu.getValue());
|
||||
Float memoryOvercommitRatio = Float.parseFloat(cluster_detail_ram.getValue());
|
||||
if(_capacityMgr.checkIfHostHasCapacity(host.getId(), cpu_requested, ram_requested, true, cpuOvercommitRatio, memoryOvercommitRatio, true)){
|
||||
s_logger.debug("The last host of this VM is UP and has enough capacity");
|
||||
s_logger.debug("Now checking for suitable pools under zone: "+host.getDataCenterId() +", pod: "+ host.getPodId()+", cluster: "+ host.getClusterId());
|
||||
//search for storage under the zone, pod, cluster of the last host.
|
||||
DataCenterDeployment lastPlan = new DataCenterDeployment(host.getDataCenterId(), host.getPodId(), host.getClusterId(), host.getId(), plan.getPoolId(), null);
|
||||
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);
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
||||
}else{
|
||||
s_logger.debug("The last host of this VM does not have enough capacity");
|
||||
}
|
||||
}else{
|
||||
s_logger.debug("The last host of this VM is not UP or is not enabled, host status is: "+host.getStatus().name() + ", host resource state is: "+host.getResourceState());
|
||||
}
|
||||
}
|
||||
s_logger.debug("Cannot choose the last host to deploy this VM ");
|
||||
}
|
||||
|
||||
|
||||
List<Long> clusterList = new ArrayList<Long>();
|
||||
if (plan.getClusterId() != null) {
|
||||
Long clusterIdSpecified = plan.getClusterId();
|
||||
s_logger.debug("Searching resources only under specified Cluster: "+ clusterIdSpecified);
|
||||
ClusterVO cluster = _clusterDao.findById(plan.getClusterId());
|
||||
if (cluster != null ){
|
||||
clusterList.add(clusterIdSpecified);
|
||||
return checkClustersforDestination(clusterList, vmProfile, plan, avoid, dc);
|
||||
if (avoid.shouldAvoid(cluster)) {
|
||||
s_logger.debug("The specified cluster is in avoid set, returning.");
|
||||
} else {
|
||||
clusterList.add(clusterIdSpecified);
|
||||
removeClustersCrossingThreshold(clusterList, avoid, vmProfile, plan);
|
||||
}
|
||||
return clusterList;
|
||||
}else{
|
||||
s_logger.debug("The specified cluster cannot be found, returning.");
|
||||
avoid.addCluster(plan.getClusterId());
|
||||
@ -280,11 +149,15 @@ public class FirstFitPlanner extends PlannerBase implements DeploymentPlanner {
|
||||
|
||||
HostPodVO pod = _podDao.findById(podIdSpecified);
|
||||
if (pod != null) {
|
||||
DeployDestination dest = scanClustersForDestinationInZoneOrPod(podIdSpecified, false, vmProfile, plan, avoid);
|
||||
if(dest == null){
|
||||
avoid.addPod(plan.getPodId());
|
||||
if (avoid.shouldAvoid(pod)) {
|
||||
s_logger.debug("The specified pod is in avoid set, returning.");
|
||||
} else {
|
||||
clusterList = scanClustersForDestinationInZoneOrPod(podIdSpecified, false, vmProfile, plan, avoid);
|
||||
if (clusterList == null) {
|
||||
avoid.addPod(plan.getPodId());
|
||||
}
|
||||
}
|
||||
return dest;
|
||||
return clusterList;
|
||||
} else {
|
||||
s_logger.debug("The specified Pod cannot be found, returning.");
|
||||
avoid.addPod(plan.getPodId());
|
||||
@ -305,7 +178,7 @@ public class FirstFitPlanner extends PlannerBase implements DeploymentPlanner {
|
||||
|
||||
}
|
||||
|
||||
private DeployDestination scanPodsForDestination(VirtualMachineProfile<? extends VirtualMachine> vmProfile, DeploymentPlan plan, ExcludeList avoid){
|
||||
private List<Long> scanPodsForDestination(VirtualMachineProfile<? extends VirtualMachine> vmProfile, DeploymentPlan plan, ExcludeList avoid){
|
||||
|
||||
ServiceOffering offering = vmProfile.getServiceOffering();
|
||||
int requiredCpu = offering.getCpu() * offering.getSpeed();
|
||||
@ -341,20 +214,24 @@ public class FirstFitPlanner extends PlannerBase implements DeploymentPlanner {
|
||||
if(!podsWithCapacity.isEmpty()){
|
||||
|
||||
prioritizedPodIds = reorderPods(podCapacityInfo, vmProfile, plan);
|
||||
if (prioritizedPodIds == null || prioritizedPodIds.isEmpty()) {
|
||||
if (s_logger.isDebugEnabled()) {
|
||||
s_logger.debug("No Pods found for destination, returning.");
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
List<Long> clusterList = new ArrayList<Long>();
|
||||
//loop over pods
|
||||
for(Long podId : prioritizedPodIds){
|
||||
s_logger.debug("Checking resources under Pod: "+podId);
|
||||
DeployDestination dest = scanClustersForDestinationInZoneOrPod(podId, false, vmProfile, plan, avoid);
|
||||
if(dest != null){
|
||||
return dest;
|
||||
List<Long> clustersUnderPod = scanClustersForDestinationInZoneOrPod(podId, false, vmProfile, plan,
|
||||
avoid);
|
||||
if (clustersUnderPod != null) {
|
||||
clusterList.addAll(clustersUnderPod);
|
||||
}
|
||||
avoid.addPod(podId);
|
||||
}
|
||||
if (s_logger.isDebugEnabled()) {
|
||||
s_logger.debug("No Pods found for destination, returning.");
|
||||
}
|
||||
return null;
|
||||
return clusterList;
|
||||
}else{
|
||||
if (s_logger.isDebugEnabled()) {
|
||||
s_logger.debug("No Pods found after removing disabled pods and pods in avoid list, returning.");
|
||||
@ -363,7 +240,69 @@ public class FirstFitPlanner extends PlannerBase implements DeploymentPlanner {
|
||||
}
|
||||
}
|
||||
|
||||
private DeployDestination scanClustersForDestinationInZoneOrPod(long id, boolean isZone, VirtualMachineProfile<? extends VirtualMachine> vmProfile, DeploymentPlan plan, ExcludeList avoid){
|
||||
private Map<Short, Float> getCapacityThresholdMap() {
|
||||
// Lets build this real time so that the admin wont have to restart MS
|
||||
// if he changes these values
|
||||
Map<Short, Float> disableThresholdMap = new HashMap<Short, Float>();
|
||||
|
||||
String cpuDisableThresholdString = _configDao.getValue(Config.CPUCapacityDisableThreshold.key());
|
||||
float cpuDisableThreshold = NumbersUtil.parseFloat(cpuDisableThresholdString, 0.85F);
|
||||
disableThresholdMap.put(Capacity.CAPACITY_TYPE_CPU, cpuDisableThreshold);
|
||||
|
||||
String memoryDisableThresholdString = _configDao.getValue(Config.MemoryCapacityDisableThreshold.key());
|
||||
float memoryDisableThreshold = NumbersUtil.parseFloat(memoryDisableThresholdString, 0.85F);
|
||||
disableThresholdMap.put(Capacity.CAPACITY_TYPE_MEMORY, memoryDisableThreshold);
|
||||
|
||||
return disableThresholdMap;
|
||||
}
|
||||
|
||||
private List<Short> getCapacitiesForCheckingThreshold() {
|
||||
List<Short> capacityList = new ArrayList<Short>();
|
||||
capacityList.add(Capacity.CAPACITY_TYPE_CPU);
|
||||
capacityList.add(Capacity.CAPACITY_TYPE_MEMORY);
|
||||
return capacityList;
|
||||
}
|
||||
|
||||
private void removeClustersCrossingThreshold(List<Long> clusterListForVmAllocation, ExcludeList avoid,
|
||||
VirtualMachineProfile<? extends VirtualMachine> vmProfile, DeploymentPlan plan) {
|
||||
|
||||
List<Short> capacityList = getCapacitiesForCheckingThreshold();
|
||||
List<Long> clustersCrossingThreshold = new ArrayList<Long>();
|
||||
|
||||
ServiceOffering offering = vmProfile.getServiceOffering();
|
||||
int cpu_requested = offering.getCpu() * offering.getSpeed();
|
||||
long ram_requested = offering.getRamSize() * 1024L * 1024L;
|
||||
|
||||
// For each capacity get the cluster list crossing the threshold and
|
||||
// remove it from the clusterList that will be used for vm allocation.
|
||||
for (short capacity : capacityList) {
|
||||
|
||||
if (clusterListForVmAllocation == null || clusterListForVmAllocation.size() == 0) {
|
||||
return;
|
||||
}
|
||||
if (capacity == Capacity.CAPACITY_TYPE_CPU) {
|
||||
clustersCrossingThreshold = _capacityDao.listClustersCrossingThreshold(capacity,
|
||||
plan.getDataCenterId(), Config.CPUCapacityDisableThreshold.key(), cpu_requested);
|
||||
} else if (capacity == Capacity.CAPACITY_TYPE_MEMORY) {
|
||||
clustersCrossingThreshold = _capacityDao.listClustersCrossingThreshold(capacity,
|
||||
plan.getDataCenterId(), Config.MemoryCapacityDisableThreshold.key(), ram_requested);
|
||||
}
|
||||
|
||||
if (clustersCrossingThreshold != null && clustersCrossingThreshold.size() != 0) {
|
||||
// addToAvoid Set
|
||||
avoid.addClusterList(clustersCrossingThreshold);
|
||||
// Remove clusters crossing disabled threshold
|
||||
clusterListForVmAllocation.removeAll(clustersCrossingThreshold);
|
||||
|
||||
s_logger.debug("Cannot allocate cluster list " + clustersCrossingThreshold.toString() + " for vm creation since their allocated percentage" +
|
||||
" crosses the disable capacity threshold defined at each cluster/ at global value for capacity Type : " + capacity + ", skipping these clusters");
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
private List<Long> scanClustersForDestinationInZoneOrPod(long id, boolean isZone,
|
||||
VirtualMachineProfile<? extends VirtualMachine> vmProfile, DeploymentPlan plan, ExcludeList avoid) {
|
||||
|
||||
VirtualMachine vm = vmProfile.getVirtualMachine();
|
||||
ServiceOffering offering = vmProfile.getServiceOffering();
|
||||
@ -396,6 +335,9 @@ public class FirstFitPlanner extends PlannerBase implements DeploymentPlanner {
|
||||
prioritizedClusterIds.removeAll(disabledClusters);
|
||||
}
|
||||
}
|
||||
|
||||
removeClustersCrossingThreshold(prioritizedClusterIds, avoid, vmProfile, plan);
|
||||
|
||||
}else{
|
||||
if (s_logger.isDebugEnabled()) {
|
||||
s_logger.debug("No clusters found having a host with enough capacity, returning.");
|
||||
@ -404,7 +346,7 @@ public class FirstFitPlanner extends PlannerBase implements DeploymentPlanner {
|
||||
}
|
||||
if(!prioritizedClusterIds.isEmpty()){
|
||||
List<Long> clusterList = reorderClusters(id, isZone, clusterCapacityInfo, vmProfile, plan);
|
||||
return checkClustersforDestination(clusterList, vmProfile, plan, avoid, dc);
|
||||
return clusterList; //return checkClustersforDestination(clusterList, vmProfile, plan, avoid, dc);
|
||||
}else{
|
||||
if (s_logger.isDebugEnabled()) {
|
||||
s_logger.debug("No clusters found after removing disabled clusters and clusters in avoid list, returning.");
|
||||
@ -452,114 +394,6 @@ public class FirstFitPlanner extends PlannerBase implements DeploymentPlanner {
|
||||
return disabledPods;
|
||||
}
|
||||
|
||||
private List<Short> getCapacitiesForCheckingThreshold(){
|
||||
List<Short> capacityList = new ArrayList<Short>();
|
||||
capacityList.add(Capacity.CAPACITY_TYPE_CPU);
|
||||
capacityList.add(Capacity.CAPACITY_TYPE_MEMORY);
|
||||
return capacityList;
|
||||
}
|
||||
|
||||
private void removeClustersCrossingThreshold(List<Long> clusterListForVmAllocation, ExcludeList avoid, VirtualMachineProfile<? extends VirtualMachine> vmProfile, DeploymentPlan plan){
|
||||
|
||||
List<Short> capacityList = getCapacitiesForCheckingThreshold();
|
||||
List<Long> clustersCrossingThreshold = new ArrayList<Long>();
|
||||
|
||||
ServiceOffering offering = vmProfile.getServiceOffering();
|
||||
int cpu_requested = offering.getCpu() * offering.getSpeed();
|
||||
long ram_requested = offering.getRamSize() * 1024L * 1024L;
|
||||
|
||||
// For each capacity get the cluster list crossing the threshold and remove it from the clusterList that will be used for vm allocation.
|
||||
for(short capacity : capacityList){
|
||||
|
||||
if (clusterListForVmAllocation == null || clusterListForVmAllocation.size() == 0){
|
||||
return;
|
||||
}
|
||||
if (capacity == Capacity.CAPACITY_TYPE_CPU) {
|
||||
clustersCrossingThreshold = _capacityDao.listClustersCrossingThreshold(capacity, plan.getDataCenterId(), Config.CPUCapacityDisableThreshold.key(), cpu_requested);
|
||||
}
|
||||
else if (capacity == Capacity.CAPACITY_TYPE_MEMORY ) {
|
||||
clustersCrossingThreshold = _capacityDao.listClustersCrossingThreshold(capacity, plan.getDataCenterId(),
|
||||
Config.MemoryCapacityDisableThreshold.key(), ram_requested );
|
||||
}
|
||||
|
||||
|
||||
if (clustersCrossingThreshold != null && clustersCrossingThreshold.size() != 0){
|
||||
// addToAvoid Set
|
||||
avoid.addClusterList(clustersCrossingThreshold);
|
||||
// Remove clusters crossing disabled threshold
|
||||
clusterListForVmAllocation.removeAll(clustersCrossingThreshold);
|
||||
|
||||
s_logger.debug("Cannot allocate cluster list " + clustersCrossingThreshold.toString() + " for vm creation since their allocated percentage" +
|
||||
" crosses the disable capacity threshold defined at each cluster/ at global value for capacity Type : " + capacity + ", skipping these clusters");
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
private DeployDestination checkClustersforDestination(List<Long> clusterList, VirtualMachineProfile<? extends VirtualMachine> vmProfile,
|
||||
DeploymentPlan plan, ExcludeList avoid, DataCenter dc){
|
||||
|
||||
if (s_logger.isTraceEnabled()) {
|
||||
s_logger.trace("ClusterId List to consider: " + clusterList);
|
||||
}
|
||||
|
||||
removeClustersCrossingThreshold(clusterList, avoid, vmProfile, plan);
|
||||
|
||||
for(Long clusterId : clusterList){
|
||||
Cluster clusterVO = _clusterDao.findById(clusterId);
|
||||
|
||||
if (clusterVO.getHypervisorType() != vmProfile.getHypervisorType()) {
|
||||
s_logger.debug("Cluster: "+clusterId + " has HyperVisorType that does not match the VM, skipping this cluster");
|
||||
avoid.addCluster(clusterVO.getId());
|
||||
continue;
|
||||
}
|
||||
|
||||
s_logger.debug("Checking resources in Cluster: "+clusterId + " under Pod: "+clusterVO.getPodId());
|
||||
//search for resources(hosts and storage) under this zone, pod, cluster.
|
||||
DataCenterDeployment potentialPlan = new DataCenterDeployment(plan.getDataCenterId(), clusterVO.getPodId(), clusterVO.getId(), null, plan.getPoolId(), null, plan.getReservationContext());
|
||||
|
||||
//find suitable hosts under this cluster, need as many hosts as we get.
|
||||
List<Host> suitableHosts = findSuitableHosts(vmProfile, potentialPlan, avoid, HostAllocator.RETURN_UPTO_ALL);
|
||||
//if found suitable hosts in this cluster, find suitable storage pools for each volume of the VM
|
||||
if(suitableHosts != null && !suitableHosts.isEmpty()){
|
||||
if (vmProfile.getHypervisorType() == HypervisorType.BareMetal) {
|
||||
Pod pod = _podDao.findById(clusterVO.getPodId());
|
||||
DeployDestination dest = new DeployDestination(dc, pod, clusterVO, suitableHosts.get(0));
|
||||
return dest;
|
||||
}
|
||||
|
||||
Pair<Map<Volume, List<StoragePool>>, List<Volume>> result = findSuitablePoolsForVolumes(vmProfile, potentialPlan, avoid, StoragePoolAllocator.RETURN_UPTO_ALL);
|
||||
Map<Volume, List<StoragePool>> suitableVolumeStoragePools = result.first();
|
||||
List<Volume> readyAndReusedVolumes = result.second();
|
||||
|
||||
//choose the potential host and pool for the VM
|
||||
if(!suitableVolumeStoragePools.isEmpty()){
|
||||
Pair<Host, Map<Volume, StoragePool>> potentialResources = findPotentialDeploymentResources(suitableHosts, suitableVolumeStoragePools);
|
||||
|
||||
if(potentialResources != null){
|
||||
Pod pod = _podDao.findById(clusterVO.getPodId());
|
||||
Host host = _hostDao.findById(potentialResources.first().getId());
|
||||
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, clusterVO, host, storageVolMap );
|
||||
s_logger.debug("Returning Deployment Destination: "+ dest);
|
||||
return dest;
|
||||
}
|
||||
}else{
|
||||
s_logger.debug("No suitable storagePools found under this Cluster: "+clusterId);
|
||||
}
|
||||
}else{
|
||||
s_logger.debug("No suitable hosts found under this Cluster: "+clusterId);
|
||||
}
|
||||
avoid.addCluster(clusterVO.getId());
|
||||
}
|
||||
s_logger.debug("Could not find suitable Deployment Destination for this VM under any clusters, returning. ");
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
protected Pair<List<Long>, Map<Long, Double>> listClustersByCapacity(long id, int requiredCpu, long requiredRam, ExcludeList avoid, boolean isZone){
|
||||
//look at the aggregate available cpu and ram per cluster
|
||||
@ -630,215 +464,6 @@ public class FirstFitPlanner extends PlannerBase implements DeploymentPlanner {
|
||||
|
||||
}
|
||||
|
||||
|
||||
protected Pair<Host, Map<Volume, StoragePool>> findPotentialDeploymentResources(List<Host> suitableHosts, Map<Volume, List<StoragePool>> suitableVolumeStoragePools){
|
||||
s_logger.debug("Trying to find a potenial host and associated storage pools from the suitable host/pool lists for this VM");
|
||||
|
||||
boolean hostCanAccessPool = false;
|
||||
boolean haveEnoughSpace = false;
|
||||
Map<Volume, StoragePool> storage = new HashMap<Volume, StoragePool>();
|
||||
TreeSet<Volume> volumesOrderBySizeDesc = new TreeSet<Volume>(new Comparator<Volume>() {
|
||||
@Override
|
||||
public int compare(Volume v1, Volume v2) {
|
||||
if(v1.getSize() < v2.getSize())
|
||||
return 1;
|
||||
else
|
||||
return -1;
|
||||
}
|
||||
});
|
||||
volumesOrderBySizeDesc.addAll(suitableVolumeStoragePools.keySet());
|
||||
boolean multipleVolume = volumesOrderBySizeDesc.size() > 1;
|
||||
for(Host potentialHost : suitableHosts){
|
||||
Map<StoragePool,List<Volume>> volumeAllocationMap = new HashMap<StoragePool,List<Volume>>();
|
||||
for(Volume vol : volumesOrderBySizeDesc){
|
||||
haveEnoughSpace = false;
|
||||
s_logger.debug("Checking if host: "+potentialHost.getId() +" can access any suitable storage pool for volume: "+ vol.getVolumeType());
|
||||
List<StoragePool> volumePoolList = suitableVolumeStoragePools.get(vol);
|
||||
hostCanAccessPool = false;
|
||||
for(StoragePool potentialSPool : volumePoolList){
|
||||
if(hostCanAccessSPool(potentialHost, potentialSPool)){
|
||||
hostCanAccessPool = true;
|
||||
if(multipleVolume){
|
||||
List<Volume> requestVolumes = null;
|
||||
if(volumeAllocationMap.containsKey(potentialSPool))
|
||||
requestVolumes = volumeAllocationMap.get(potentialSPool);
|
||||
else
|
||||
requestVolumes = new ArrayList<Volume>();
|
||||
requestVolumes.add(vol);
|
||||
|
||||
if(!_storageMgr.storagePoolHasEnoughSpace(requestVolumes, potentialSPool))
|
||||
continue;
|
||||
volumeAllocationMap.put(potentialSPool,requestVolumes);
|
||||
}
|
||||
storage.put(vol, potentialSPool);
|
||||
haveEnoughSpace = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if(!hostCanAccessPool){
|
||||
break;
|
||||
}
|
||||
if(!haveEnoughSpace) {
|
||||
s_logger.warn("insufficient capacity to allocate all volumes");
|
||||
break;
|
||||
}
|
||||
}
|
||||
if(hostCanAccessPool && haveEnoughSpace){
|
||||
s_logger.debug("Found a potential host " + "id: "+potentialHost.getId() + " name: " +potentialHost.getName() + " and associated storage pools for this VM");
|
||||
return new Pair<Host, Map<Volume, StoragePool>>(potentialHost, storage);
|
||||
}
|
||||
}
|
||||
s_logger.debug("Could not find a potential host that has associated storage pools from the suitable host/pool lists for this VM");
|
||||
return null;
|
||||
}
|
||||
|
||||
protected boolean hostCanAccessSPool(Host host, StoragePool pool){
|
||||
boolean hostCanAccessSPool = false;
|
||||
|
||||
StoragePoolHostVO hostPoolLinkage = _poolHostDao.findByPoolHost(pool.getId(), host.getId());
|
||||
if(hostPoolLinkage != null){
|
||||
hostCanAccessSPool = true;
|
||||
}
|
||||
|
||||
s_logger.debug("Host: "+ host.getId() + (hostCanAccessSPool ?" can" : " cannot") + " access pool: "+ pool.getId());
|
||||
return hostCanAccessSPool;
|
||||
}
|
||||
|
||||
protected List<Host> findSuitableHosts(VirtualMachineProfile<? extends VirtualMachine> vmProfile, DeploymentPlan plan, ExcludeList avoid, int returnUpTo){
|
||||
List<Host> suitableHosts = new ArrayList<Host>();
|
||||
for(HostAllocator allocator : _hostAllocators) {
|
||||
suitableHosts = allocator.allocateTo(vmProfile, plan, Host.Type.Routing, avoid, returnUpTo);
|
||||
if (suitableHosts != null && !suitableHosts.isEmpty()) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if(suitableHosts.isEmpty()){
|
||||
s_logger.debug("No suitable hosts found");
|
||||
}
|
||||
return suitableHosts;
|
||||
}
|
||||
|
||||
protected Pair<Map<Volume, List<StoragePool>>, List<Volume>> findSuitablePoolsForVolumes(VirtualMachineProfile<? extends VirtualMachine> vmProfile, DeploymentPlan plan, ExcludeList avoid, int returnUpTo){
|
||||
List<VolumeVO> volumesTobeCreated = _volsDao.findUsableVolumesForInstance(vmProfile.getId());
|
||||
Map<Volume, List<StoragePool>> suitableVolumeStoragePools = new HashMap<Volume, List<StoragePool>>();
|
||||
List<Volume> readyAndReusedVolumes = new ArrayList<Volume>();
|
||||
|
||||
//for each volume find list of suitable storage pools by calling the allocators
|
||||
for (VolumeVO toBeCreated : volumesTobeCreated) {
|
||||
s_logger.debug("Checking suitable pools for volume (Id, Type): ("+toBeCreated.getId() +"," +toBeCreated.getVolumeType().name() + ")");
|
||||
|
||||
//If the plan specifies a poolId, it means that this VM's ROOT volume is ready and the pool should be reused.
|
||||
//In this case, also check if rest of the volumes are ready and can be reused.
|
||||
if(plan.getPoolId() != null){
|
||||
s_logger.debug("Volume has pool(" + plan.getPoolId() + ") already allocated, checking if pool can be reused, poolId: "+toBeCreated.getPoolId());
|
||||
List<StoragePool> suitablePools = new ArrayList<StoragePool>();
|
||||
StoragePool pool = null;
|
||||
if(toBeCreated.getPoolId() != null){
|
||||
s_logger.debug("finding pool by id '" + toBeCreated.getPoolId() + "'");
|
||||
pool = (StoragePool)this.dataStoreMgr.getPrimaryDataStore(toBeCreated.getPoolId());
|
||||
}else{
|
||||
s_logger.debug("finding pool by id '" + plan.getPoolId() + "'");
|
||||
pool = (StoragePool)this.dataStoreMgr.getPrimaryDataStore(plan.getPoolId());
|
||||
}
|
||||
|
||||
if(pool != null){
|
||||
if(!pool.isInMaintenance()){
|
||||
if(!avoid.shouldAvoid(pool)){
|
||||
long exstPoolDcId = pool.getDataCenterId();
|
||||
|
||||
long exstPoolPodId = pool.getPodId() != null ? pool.getPodId() : -1;
|
||||
long exstPoolClusterId = pool.getClusterId() != null ? pool.getClusterId() : -1;
|
||||
if(plan.getDataCenterId() == exstPoolDcId && plan.getPodId() == exstPoolPodId && plan.getClusterId() == exstPoolClusterId){
|
||||
s_logger.debug("Planner need not allocate a pool for this volume since its READY");
|
||||
suitablePools.add(pool);
|
||||
suitableVolumeStoragePools.put(toBeCreated, suitablePools);
|
||||
if (!(toBeCreated.getState() == Volume.State.Allocated || toBeCreated.getState() == Volume.State.Creating)) {
|
||||
readyAndReusedVolumes.add(toBeCreated);
|
||||
}
|
||||
continue;
|
||||
}else{
|
||||
s_logger.debug("Pool of the volume does not fit the specified plan, need to reallocate a pool for this volume");
|
||||
}
|
||||
}else{
|
||||
s_logger.debug("Pool of the volume is in avoid set, need to reallocate a pool for this volume");
|
||||
}
|
||||
}else{
|
||||
s_logger.debug("Pool of the volume is in maintenance, need to reallocate a pool for this volume");
|
||||
}
|
||||
}else{
|
||||
s_logger.debug("Unable to find pool by provided id");
|
||||
}
|
||||
}
|
||||
|
||||
if(s_logger.isDebugEnabled()){
|
||||
s_logger.debug("We need to allocate new storagepool for this volume");
|
||||
}
|
||||
if(!isRootAdmin(plan.getReservationContext())){
|
||||
if(!isEnabledForAllocation(plan.getDataCenterId(), plan.getPodId(), plan.getClusterId())){
|
||||
if(s_logger.isDebugEnabled()){
|
||||
s_logger.debug("Cannot allocate new storagepool for this volume in this cluster, allocation state is disabled");
|
||||
s_logger.debug("Cannot deploy to this specified plan, allocation state is disabled, returning.");
|
||||
}
|
||||
//Cannot find suitable storage pools under this cluster for this volume since allocation_state is disabled.
|
||||
//- remove any suitable pools found for other volumes.
|
||||
//All volumes should get suitable pools under this cluster; else we cant use this cluster.
|
||||
suitableVolumeStoragePools.clear();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
s_logger.debug("Calling StoragePoolAllocators to find suitable pools");
|
||||
|
||||
DiskOfferingVO diskOffering = _diskOfferingDao.findById(toBeCreated.getDiskOfferingId());
|
||||
DiskProfile diskProfile = new DiskProfile(toBeCreated, diskOffering, vmProfile.getHypervisorType());
|
||||
|
||||
boolean useLocalStorage = false;
|
||||
if (vmProfile.getType() != VirtualMachine.Type.User) {
|
||||
String ssvmUseLocalStorage = _configDao.getValue(Config.SystemVMUseLocalStorage.key());
|
||||
if (ssvmUseLocalStorage.equalsIgnoreCase("true")) {
|
||||
useLocalStorage = true;
|
||||
}
|
||||
} else {
|
||||
useLocalStorage = diskOffering.getUseLocalStorage();
|
||||
|
||||
// TODO: this is a hacking fix for the problem of deploy ISO-based VM on local storage
|
||||
// when deploying VM based on ISO, we have a service offering and an additional disk offering, use-local storage flag is actually
|
||||
// saved in service offering, overrde the flag from service offering when it is a ROOT disk
|
||||
if(!useLocalStorage && vmProfile.getServiceOffering().getUseLocalStorage()) {
|
||||
if(toBeCreated.getVolumeType() == Volume.Type.ROOT)
|
||||
useLocalStorage = true;
|
||||
}
|
||||
}
|
||||
diskProfile.setUseLocalStorage(useLocalStorage);
|
||||
|
||||
boolean foundPotentialPools = false;
|
||||
for(StoragePoolAllocator allocator : _storagePoolAllocators) {
|
||||
final List<StoragePool> suitablePools = allocator.allocateToPool(diskProfile, vmProfile, plan, avoid, returnUpTo);
|
||||
if (suitablePools != null && !suitablePools.isEmpty()) {
|
||||
suitableVolumeStoragePools.put(toBeCreated, suitablePools);
|
||||
foundPotentialPools = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if(!foundPotentialPools){
|
||||
s_logger.debug("No suitable pools found for volume: "+toBeCreated +" under cluster: "+plan.getClusterId());
|
||||
//No suitable storage pools found under this cluster for this volume. - remove any suitable pools found for other volumes.
|
||||
//All volumes should get suitable pools under this cluster; else we cant use this cluster.
|
||||
suitableVolumeStoragePools.clear();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if(suitableVolumeStoragePools.isEmpty()){
|
||||
s_logger.debug("No suitable pools found");
|
||||
}
|
||||
|
||||
return new Pair<Map<Volume, List<StoragePool>>, List<Volume>>(suitableVolumeStoragePools, readyAndReusedVolumes);
|
||||
}
|
||||
|
||||
|
||||
private boolean isRootAdmin(ReservationContext reservationContext) {
|
||||
if(reservationContext != null){
|
||||
if(reservationContext.getAccount() != null){
|
||||
@ -859,10 +484,17 @@ public class FirstFitPlanner extends PlannerBase implements DeploymentPlanner {
|
||||
|
||||
@Override
|
||||
public boolean canHandle(VirtualMachineProfile<? extends VirtualMachine> vm, DeploymentPlan plan, ExcludeList avoid) {
|
||||
if(vm.getHypervisorType() != HypervisorType.BareMetal){
|
||||
//check the allocation strategy
|
||||
if (_allocationAlgorithm != null && (_allocationAlgorithm.equals(AllocationAlgorithm.random.toString()) || _allocationAlgorithm.equals(AllocationAlgorithm.firstfit.toString()))) {
|
||||
return true;
|
||||
// check what the ServiceOffering says. If null, check the global config
|
||||
ServiceOffering offering = vm.getServiceOffering();
|
||||
if (vm.getHypervisorType() != HypervisorType.BareMetal) {
|
||||
if (offering != null && offering.getDeploymentPlanner() != null) {
|
||||
if (offering.getDeploymentPlanner().equals(this.getName())) {
|
||||
return true;
|
||||
}
|
||||
} else {
|
||||
if (_globalDeploymentPlanner != null && _globalDeploymentPlanner.equals(this._name)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
@ -872,29 +504,20 @@ public class FirstFitPlanner extends PlannerBase implements DeploymentPlanner {
|
||||
public boolean configure(String name, Map<String, Object> params) throws ConfigurationException {
|
||||
super.configure(name, params);
|
||||
_allocationAlgorithm = _configDao.getValue(Config.VmAllocationAlgorithm.key());
|
||||
_globalDeploymentPlanner = _configDao.getValue(Config.VmDeploymentPlanner.key());
|
||||
return true;
|
||||
}
|
||||
|
||||
private boolean isEnabledForAllocation(long zoneId, Long podId, Long clusterId){
|
||||
// Check if the zone exists in the system
|
||||
DataCenterVO zone = _dcDao.findById(zoneId);
|
||||
if(zone != null && Grouping.AllocationState.Disabled == zone.getAllocationState()){
|
||||
s_logger.info("Zone is currently disabled, cannot allocate to this zone: "+ zoneId);
|
||||
return false;
|
||||
}
|
||||
|
||||
Pod pod = _podDao.findById(podId);
|
||||
if(pod != null && Grouping.AllocationState.Disabled == pod.getAllocationState()){
|
||||
s_logger.info("Pod is currently disabled, cannot allocate to this pod: "+ podId);
|
||||
return false;
|
||||
}
|
||||
@Override
|
||||
public DeployDestination plan(VirtualMachineProfile<? extends VirtualMachine> vm, DeploymentPlan plan,
|
||||
ExcludeList avoid) throws InsufficientServerCapacityException {
|
||||
// TODO Auto-generated method stub
|
||||
return null;
|
||||
}
|
||||
|
||||
Cluster cluster = _clusterDao.findById(clusterId);
|
||||
if(cluster != null && Grouping.AllocationState.Disabled == cluster.getAllocationState()){
|
||||
s_logger.info("Cluster is currently disabled, cannot allocate to this cluster: "+ clusterId);
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
@Override
|
||||
public PlannerResourceUsage getResourceUsage() {
|
||||
return PlannerResourceUsage.Shared;
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,54 +0,0 @@
|
||||
// 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 javax.ejb.Local;
|
||||
|
||||
import org.apache.log4j.Logger;
|
||||
|
||||
import com.cloud.deploy.DeploymentPlanner.AllocationAlgorithm;
|
||||
import com.cloud.hypervisor.Hypervisor.HypervisorType;
|
||||
import com.cloud.vm.UserVmVO;
|
||||
|
||||
@Local(value = {DeployPlannerSelector.class})
|
||||
public class HypervisorVmPlannerSelector extends AbstractDeployPlannerSelector {
|
||||
private static final Logger s_logger = Logger.getLogger(HypervisorVmPlannerSelector.class);
|
||||
|
||||
@Override
|
||||
public String selectPlanner(UserVmVO vm) {
|
||||
if (vm.getHypervisorType() != HypervisorType.BareMetal) {
|
||||
//check the allocation strategy
|
||||
if (_allocationAlgorithm != null) {
|
||||
if (_allocationAlgorithm.equals(AllocationAlgorithm.random.toString())
|
||||
|| _allocationAlgorithm.equals(AllocationAlgorithm.firstfit.toString())) {
|
||||
return "FirstFitPlanner";
|
||||
} else if (_allocationAlgorithm.equals(AllocationAlgorithm.userdispersing.toString())) {
|
||||
return "UserDispersingPlanner";
|
||||
} else if (_allocationAlgorithm.equals(AllocationAlgorithm.userconcentratedpod_random.toString())
|
||||
|| _allocationAlgorithm.equals(AllocationAlgorithm.userconcentratedpod_firstfit.toString())) {
|
||||
return "UserConcentratedPodPlanner";
|
||||
}
|
||||
} else {
|
||||
if (s_logger.isDebugEnabled()) {
|
||||
s_logger.debug("The allocation algorithm is null, cannot select the planner");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
}
|
||||
117
server/src/com/cloud/deploy/PlannerHostReservationVO.java
Normal file
117
server/src/com/cloud/deploy/PlannerHostReservationVO.java
Normal file
@ -0,0 +1,117 @@
|
||||
// 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 javax.persistence.Column;
|
||||
import javax.persistence.Entity;
|
||||
import javax.persistence.EnumType;
|
||||
import javax.persistence.Enumerated;
|
||||
import javax.persistence.GeneratedValue;
|
||||
import javax.persistence.GenerationType;
|
||||
import javax.persistence.Id;
|
||||
import javax.persistence.Table;
|
||||
import org.apache.cloudstack.api.InternalIdentity;
|
||||
|
||||
import com.cloud.deploy.DeploymentPlanner.PlannerResourceUsage;
|
||||
|
||||
@Entity
|
||||
@Table(name = "op_host_planner_reservation")
|
||||
public class PlannerHostReservationVO implements InternalIdentity {
|
||||
@Id
|
||||
@GeneratedValue(strategy=GenerationType.IDENTITY)
|
||||
@Column(name="id")
|
||||
private long id;
|
||||
|
||||
@Column(name="host_id")
|
||||
private Long hostId;
|
||||
|
||||
@Column(name="data_center_id")
|
||||
private Long dataCenterId;
|
||||
|
||||
@Column(name="pod_id")
|
||||
private Long podId;
|
||||
|
||||
@Column(name="cluster_id")
|
||||
private Long clusterId;
|
||||
|
||||
@Column(name = "resource_usage")
|
||||
@Enumerated(EnumType.STRING)
|
||||
private PlannerResourceUsage resourceUsage;
|
||||
|
||||
public PlannerHostReservationVO() {
|
||||
}
|
||||
|
||||
public PlannerHostReservationVO(Long hostId, Long dataCenterId, Long podId, Long clusterId) {
|
||||
this.hostId = hostId;
|
||||
this.dataCenterId = dataCenterId;
|
||||
this.podId = podId;
|
||||
this.clusterId = clusterId;
|
||||
}
|
||||
|
||||
public PlannerHostReservationVO(Long hostId, Long dataCenterId, Long podId, Long clusterId,
|
||||
PlannerResourceUsage resourceUsage) {
|
||||
this.hostId = hostId;
|
||||
this.dataCenterId = dataCenterId;
|
||||
this.podId = podId;
|
||||
this.clusterId = clusterId;
|
||||
this.resourceUsage = resourceUsage;
|
||||
}
|
||||
|
||||
@Override
|
||||
public long getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
public Long getHostId() {
|
||||
return hostId;
|
||||
}
|
||||
|
||||
public void setHostId(Long hostId) {
|
||||
this.hostId = hostId;
|
||||
}
|
||||
|
||||
public Long getDataCenterId() {
|
||||
return dataCenterId;
|
||||
}
|
||||
public void setDataCenterId(Long dataCenterId) {
|
||||
this.dataCenterId = dataCenterId;
|
||||
}
|
||||
|
||||
public Long getPodId() {
|
||||
return podId;
|
||||
}
|
||||
public void setPodId(long podId) {
|
||||
this.podId = new Long(podId);
|
||||
}
|
||||
|
||||
public Long getClusterId() {
|
||||
return clusterId;
|
||||
}
|
||||
public void setClusterId(long clusterId) {
|
||||
this.clusterId = new Long(clusterId);
|
||||
}
|
||||
|
||||
public PlannerResourceUsage getResourceUsage() {
|
||||
return resourceUsage;
|
||||
}
|
||||
|
||||
public void setResourceUsage(PlannerResourceUsage resourceType) {
|
||||
this.resourceUsage = resourceType;
|
||||
}
|
||||
|
||||
}
|
||||
54
server/src/com/cloud/deploy/DeployPlannerSelector.java → server/src/com/cloud/deploy/dao/PlannerHostReservationDao.java
Executable file → Normal file
54
server/src/com/cloud/deploy/DeployPlannerSelector.java → server/src/com/cloud/deploy/dao/PlannerHostReservationDao.java
Executable file → Normal file
@ -1,24 +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 com.cloud.deploy;
|
||||
|
||||
import com.cloud.utils.component.Adapter;
|
||||
import com.cloud.vm.UserVmVO;
|
||||
|
||||
public interface DeployPlannerSelector extends Adapter {
|
||||
String selectPlanner(UserVmVO vm);
|
||||
}
|
||||
// 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.dao;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import com.cloud.deploy.PlannerHostReservationVO;
|
||||
import com.cloud.utils.db.GenericDao;
|
||||
|
||||
public interface PlannerHostReservationDao extends GenericDao<PlannerHostReservationVO, Long> {
|
||||
|
||||
PlannerHostReservationVO findByHostId(long hostId);
|
||||
|
||||
List<PlannerHostReservationVO> listAllReservedHosts();
|
||||
|
||||
}
|
||||
@ -0,0 +1,63 @@
|
||||
// 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.dao;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import javax.annotation.PostConstruct;
|
||||
import javax.ejb.Local;
|
||||
import com.cloud.deploy.PlannerHostReservationVO;
|
||||
import com.cloud.utils.db.GenericDaoBase;
|
||||
import com.cloud.utils.db.SearchBuilder;
|
||||
import com.cloud.utils.db.SearchCriteria;
|
||||
|
||||
@Local(value = { PlannerHostReservationDao.class })
|
||||
public class PlannerHostReservationDaoImpl extends GenericDaoBase<PlannerHostReservationVO, Long> implements
|
||||
PlannerHostReservationDao {
|
||||
|
||||
private SearchBuilder<PlannerHostReservationVO> _hostIdSearch;
|
||||
private SearchBuilder<PlannerHostReservationVO> _reservedHostSearch;
|
||||
|
||||
public PlannerHostReservationDaoImpl() {
|
||||
|
||||
}
|
||||
|
||||
@PostConstruct
|
||||
protected void init() {
|
||||
_hostIdSearch = createSearchBuilder();
|
||||
_hostIdSearch.and("hostId", _hostIdSearch.entity().getHostId(), SearchCriteria.Op.EQ);
|
||||
_hostIdSearch.done();
|
||||
|
||||
_reservedHostSearch = createSearchBuilder();
|
||||
_reservedHostSearch.and("usage", _reservedHostSearch.entity().getResourceUsage(), SearchCriteria.Op.NNULL);
|
||||
_reservedHostSearch.done();
|
||||
}
|
||||
|
||||
@Override
|
||||
public PlannerHostReservationVO findByHostId(long hostId) {
|
||||
SearchCriteria<PlannerHostReservationVO> sc = _hostIdSearch.create();
|
||||
sc.setParameters("hostId", hostId);
|
||||
return findOneBy(sc);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<PlannerHostReservationVO> listAllReservedHosts() {
|
||||
SearchCriteria<PlannerHostReservationVO> sc = _reservedHostSearch.create();
|
||||
return listBy(sc);
|
||||
}
|
||||
|
||||
}
|
||||
@ -85,6 +85,10 @@ import com.cloud.dc.dao.ClusterVSMMapDao;
|
||||
import com.cloud.dc.dao.DataCenterDao;
|
||||
import com.cloud.dc.dao.DataCenterIpAddressDao;
|
||||
import com.cloud.dc.dao.HostPodDao;
|
||||
import com.cloud.deploy.PlannerHostReservationVO;
|
||||
import com.cloud.deploy.dao.PlannerHostReservationDao;
|
||||
import com.cloud.event.ActionEvent;
|
||||
import com.cloud.event.EventTypes;
|
||||
import com.cloud.exception.AgentUnavailableException;
|
||||
import com.cloud.exception.DiscoveryException;
|
||||
import com.cloud.exception.InvalidParameterValueException;
|
||||
@ -212,6 +216,8 @@ public class ResourceManagerImpl extends ManagerBase implements ResourceManager,
|
||||
protected HighAvailabilityManager _haMgr;
|
||||
@Inject
|
||||
protected StorageService _storageSvr;
|
||||
@Inject
|
||||
PlannerHostReservationDao _plannerHostReserveDao;
|
||||
|
||||
protected List<? extends Discoverer> _discoverers;
|
||||
public List<? extends Discoverer> getDiscoverers() {
|
||||
@ -2851,4 +2857,41 @@ public class ResourceManagerImpl extends ManagerBase implements ResourceManager,
|
||||
ResourceState.Enabled);
|
||||
return sc.list();
|
||||
}
|
||||
|
||||
@Override
|
||||
@DB
|
||||
@ActionEvent(eventType = EventTypes.EVENT_HOST_RESERVATION_RELEASE, eventDescription = "releasing host reservation", async = true)
|
||||
public boolean releaseHostReservation(Long hostId) {
|
||||
Transaction txn = Transaction.currentTxn();
|
||||
try {
|
||||
txn.start();
|
||||
PlannerHostReservationVO reservationEntry = _plannerHostReserveDao.findByHostId(hostId);
|
||||
if (reservationEntry != null) {
|
||||
long id = reservationEntry.getId();
|
||||
PlannerHostReservationVO hostReservation = _plannerHostReserveDao.lockRow(id, true);
|
||||
if (hostReservation == null) {
|
||||
if (s_logger.isDebugEnabled()) {
|
||||
s_logger.debug("Host reservation for host: " + hostId + " does not even exist. Release reservartion call is ignored.");
|
||||
}
|
||||
txn.rollback();
|
||||
return false;
|
||||
}
|
||||
hostReservation.setResourceUsage(null);
|
||||
_plannerHostReserveDao.persist(hostReservation);
|
||||
txn.commit();
|
||||
return true;
|
||||
}
|
||||
if (s_logger.isDebugEnabled()) {
|
||||
s_logger.debug("Host reservation for host: " + hostId
|
||||
+ " does not even exist. Release reservartion call is ignored.");
|
||||
}
|
||||
return false;
|
||||
} catch (CloudRuntimeException e) {
|
||||
throw e;
|
||||
} catch (Throwable t) {
|
||||
s_logger.error("Unable to release host reservation for host: " + hostId, t);
|
||||
txn.rollback();
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -78,6 +78,7 @@ import org.apache.cloudstack.api.command.admin.host.FindHostsForMigrationCmd;
|
||||
import org.apache.cloudstack.api.command.admin.host.ListHostsCmd;
|
||||
import org.apache.cloudstack.api.command.admin.host.PrepareForMaintenanceCmd;
|
||||
import org.apache.cloudstack.api.command.admin.host.ReconnectHostCmd;
|
||||
import org.apache.cloudstack.api.command.admin.host.ReleaseHostReservationCmd;
|
||||
import org.apache.cloudstack.api.command.admin.host.UpdateHostCmd;
|
||||
import org.apache.cloudstack.api.command.admin.host.UpdateHostPasswordCmd;
|
||||
import org.apache.cloudstack.api.command.admin.internallb.ConfigureInternalLoadBalancerElementCmd;
|
||||
@ -462,6 +463,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;
|
||||
@ -589,6 +591,7 @@ import com.cloud.vm.dao.VMInstanceDao;
|
||||
|
||||
import edu.emory.mathcs.backport.java.util.Arrays;
|
||||
import edu.emory.mathcs.backport.java.util.Collections;
|
||||
import org.apache.cloudstack.api.command.admin.config.ListDeploymentPlannersCmd;
|
||||
|
||||
|
||||
public class ManagementServerImpl extends ManagerBase implements ManagementServer {
|
||||
@ -726,11 +729,21 @@ public class ManagementServerImpl extends ManagerBase implements ManagementServe
|
||||
private List<UserAuthenticator> _userAuthenticators;
|
||||
private List<UserAuthenticator> _userPasswordEncoders;
|
||||
|
||||
protected List<DeploymentPlanner> _planners;
|
||||
|
||||
public List<DeploymentPlanner> getPlanners() {
|
||||
return _planners;
|
||||
}
|
||||
|
||||
public void setPlanners(List<DeploymentPlanner> _planners) {
|
||||
this._planners = _planners;
|
||||
}
|
||||
|
||||
@Inject ClusterManager _clusterMgr;
|
||||
private String _hashKey = null;
|
||||
private String _encryptionKey = null;
|
||||
private String _encryptionIV = null;
|
||||
|
||||
|
||||
@Inject
|
||||
protected AffinityGroupVMMapDao _affinityGroupVMMapDao;
|
||||
|
||||
@ -976,29 +989,29 @@ public class ManagementServerImpl extends ManagerBase implements ManagementServe
|
||||
String zoneType = cmd.getZoneType();
|
||||
String keyword = cmd.getKeyword();
|
||||
zoneId = _accountMgr.checkAccessAndSpecifyAuthority(UserContext.current().getCaller(), zoneId);
|
||||
|
||||
|
||||
|
||||
|
||||
Filter searchFilter = new Filter(ClusterVO.class, "id", true, cmd.getStartIndex(), cmd.getPageSizeVal());
|
||||
|
||||
SearchBuilder<ClusterVO> sb = _clusterDao.createSearchBuilder();
|
||||
sb.and("id", sb.entity().getId(), SearchCriteria.Op.EQ);
|
||||
sb.and("name", sb.entity().getName(), SearchCriteria.Op.LIKE);
|
||||
sb.and("podId", sb.entity().getPodId(), SearchCriteria.Op.EQ);
|
||||
sb.and("dataCenterId", sb.entity().getDataCenterId(), SearchCriteria.Op.EQ);
|
||||
|
||||
SearchBuilder<ClusterVO> sb = _clusterDao.createSearchBuilder();
|
||||
sb.and("id", sb.entity().getId(), SearchCriteria.Op.EQ);
|
||||
sb.and("name", sb.entity().getName(), SearchCriteria.Op.LIKE);
|
||||
sb.and("podId", sb.entity().getPodId(), SearchCriteria.Op.EQ);
|
||||
sb.and("dataCenterId", sb.entity().getDataCenterId(), SearchCriteria.Op.EQ);
|
||||
sb.and("hypervisorType", sb.entity().getHypervisorType(), SearchCriteria.Op.EQ);
|
||||
sb.and("clusterType", sb.entity().getClusterType(), SearchCriteria.Op.EQ);
|
||||
sb.and("allocationState", sb.entity().getAllocationState(), SearchCriteria.Op.EQ);
|
||||
|
||||
|
||||
if(zoneType != null) {
|
||||
SearchBuilder<DataCenterVO> zoneSb = _dcDao.createSearchBuilder();
|
||||
zoneSb.and("zoneNetworkType", zoneSb.entity().getNetworkType(), SearchCriteria.Op.EQ);
|
||||
zoneSb.and("zoneNetworkType", zoneSb.entity().getNetworkType(), SearchCriteria.Op.EQ);
|
||||
sb.join("zoneSb", zoneSb, sb.entity().getDataCenterId(), zoneSb.entity().getId(), JoinBuilder.JoinType.INNER);
|
||||
}
|
||||
|
||||
|
||||
SearchCriteria<ClusterVO> sc = sb.create();
|
||||
|
||||
|
||||
SearchCriteria<ClusterVO> sc = sb.create();
|
||||
if (id != null) {
|
||||
sc.setParameters("id", id);
|
||||
sc.setParameters("id", id);
|
||||
}
|
||||
|
||||
if (name != null) {
|
||||
@ -1026,9 +1039,9 @@ public class ManagementServerImpl extends ManagerBase implements ManagementServe
|
||||
}
|
||||
|
||||
if(zoneType != null) {
|
||||
sc.setJoinParameters("zoneSb", "zoneNetworkType", zoneType);
|
||||
sc.setJoinParameters("zoneSb", "zoneNetworkType", zoneType);
|
||||
}
|
||||
|
||||
|
||||
if (keyword != null) {
|
||||
SearchCriteria<ClusterVO> ssc = _clusterDao.createSearchCriteria();
|
||||
ssc.addOr("name", SearchCriteria.Op.LIKE, "%" + keyword + "%");
|
||||
@ -1441,26 +1454,26 @@ public class ManagementServerImpl extends ManagerBase implements ManagementServe
|
||||
public Pair<List<? extends Pod>, Integer> searchForPods(ListPodsByCmd cmd) {
|
||||
String podName = cmd.getPodName();
|
||||
Long id = cmd.getId();
|
||||
Long zoneId = cmd.getZoneId();
|
||||
Long zoneId = cmd.getZoneId();
|
||||
Object keyword = cmd.getKeyword();
|
||||
Object allocationState = cmd.getAllocationState();
|
||||
String zoneType = cmd.getZoneType();
|
||||
zoneId = _accountMgr.checkAccessAndSpecifyAuthority(UserContext.current().getCaller(), zoneId);
|
||||
|
||||
|
||||
|
||||
Filter searchFilter = new Filter(HostPodVO.class, "dataCenterId", true, cmd.getStartIndex(), cmd.getPageSizeVal());
|
||||
SearchBuilder<HostPodVO> sb = _hostPodDao.createSearchBuilder();
|
||||
SearchBuilder<HostPodVO> sb = _hostPodDao.createSearchBuilder();
|
||||
sb.and("id", sb.entity().getId(), SearchCriteria.Op.EQ);
|
||||
sb.and("name", sb.entity().getName(), SearchCriteria.Op.LIKE);
|
||||
sb.and("dataCenterId", sb.entity().getDataCenterId(), SearchCriteria.Op.EQ);
|
||||
sb.and("name", sb.entity().getName(), SearchCriteria.Op.LIKE);
|
||||
sb.and("dataCenterId", sb.entity().getDataCenterId(), SearchCriteria.Op.EQ);
|
||||
sb.and("allocationState", sb.entity().getAllocationState(), SearchCriteria.Op.EQ);
|
||||
|
||||
|
||||
if(zoneType != null) {
|
||||
SearchBuilder<DataCenterVO> zoneSb = _dcDao.createSearchBuilder();
|
||||
zoneSb.and("zoneNetworkType", zoneSb.entity().getNetworkType(), SearchCriteria.Op.EQ);
|
||||
zoneSb.and("zoneNetworkType", zoneSb.entity().getNetworkType(), SearchCriteria.Op.EQ);
|
||||
sb.join("zoneSb", zoneSb, sb.entity().getDataCenterId(), zoneSb.entity().getId(), JoinBuilder.JoinType.INNER);
|
||||
}
|
||||
|
||||
|
||||
SearchCriteria<HostPodVO> sc = sb.create();
|
||||
if (keyword != null) {
|
||||
SearchCriteria<HostPodVO> ssc = _hostPodDao.createSearchCriteria();
|
||||
@ -1473,23 +1486,23 @@ public class ManagementServerImpl extends ManagerBase implements ManagementServe
|
||||
if (id != null) {
|
||||
sc.setParameters("id", id);
|
||||
}
|
||||
|
||||
|
||||
if (podName != null) {
|
||||
sc.setParameters("name", "%" + podName + "%");
|
||||
}
|
||||
|
||||
|
||||
if (zoneId != null) {
|
||||
sc.setParameters("dataCenterId", zoneId);
|
||||
}
|
||||
|
||||
|
||||
if (allocationState != null) {
|
||||
sc.setParameters("allocationState", allocationState);
|
||||
}
|
||||
|
||||
if(zoneType != null) {
|
||||
sc.setJoinParameters("zoneSb", "zoneNetworkType", zoneType);
|
||||
}
|
||||
|
||||
|
||||
if(zoneType != null) {
|
||||
sc.setJoinParameters("zoneSb", "zoneNetworkType", zoneType);
|
||||
}
|
||||
|
||||
Pair<List<HostPodVO>, Integer> result = _hostPodDao.searchAndCount(sc, searchFilter);
|
||||
return new Pair<List<? extends Pod>, Integer>(result.first(), result.second());
|
||||
}
|
||||
@ -2903,7 +2916,8 @@ public class ManagementServerImpl extends ManagerBase implements ManagementServe
|
||||
cmdList.add(ListAffinityGroupsCmd.class);
|
||||
cmdList.add(UpdateVMAffinityGroupCmd.class);
|
||||
cmdList.add(ListAffinityGroupTypesCmd.class);
|
||||
|
||||
cmdList.add(ListDeploymentPlannersCmd.class);
|
||||
cmdList.add(ReleaseHostReservationCmd.class);
|
||||
cmdList.add(AddResourceDetailCmd.class);
|
||||
cmdList.add(RemoveResourceDetailCmd.class);
|
||||
cmdList.add(ListResourceDetailsCmd.class);
|
||||
@ -3105,10 +3119,10 @@ public class ManagementServerImpl extends ManagerBase implements ManagementServe
|
||||
|
||||
if(zoneType != null) {
|
||||
SearchBuilder<DataCenterVO> zoneSb = _dcDao.createSearchBuilder();
|
||||
zoneSb.and("zoneNetworkType", zoneSb.entity().getNetworkType(), SearchCriteria.Op.EQ);
|
||||
zoneSb.and("zoneNetworkType", zoneSb.entity().getNetworkType(), SearchCriteria.Op.EQ);
|
||||
sb.join("zoneSb", zoneSb, sb.entity().getDataCenterId(), zoneSb.entity().getId(), JoinBuilder.JoinType.INNER);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
SearchCriteria<VMInstanceVO> sc = sb.create();
|
||||
|
||||
if (keyword != null) {
|
||||
@ -3150,9 +3164,9 @@ public class ManagementServerImpl extends ManagerBase implements ManagementServe
|
||||
}
|
||||
|
||||
if(zoneType != null) {
|
||||
sc.setJoinParameters("zoneSb", "zoneNetworkType", zoneType);
|
||||
sc.setJoinParameters("zoneSb", "zoneNetworkType", zoneType);
|
||||
}
|
||||
|
||||
|
||||
Pair<List<VMInstanceVO>, Integer> result = _vmInstanceDao.searchAndCount(sc, searchFilter);
|
||||
return new Pair<List<? extends VirtualMachine>, Integer>(result.first(), result.second());
|
||||
}
|
||||
@ -3677,7 +3691,7 @@ public class ManagementServerImpl extends ManagerBase implements ManagementServe
|
||||
// although we may have race conditioning here, database transaction serialization should
|
||||
// give us the same key
|
||||
if (_hashKey == null) {
|
||||
_hashKey = _configDao.getValueAndInitIfNotExist(Config.HashKey.key(), Config.HashKey.getCategory(),
|
||||
_hashKey = _configDao.getValueAndInitIfNotExist(Config.HashKey.key(), Config.HashKey.getCategory(),
|
||||
getBase64EncodedRandomKey(128));
|
||||
}
|
||||
return _hashKey;
|
||||
@ -3686,41 +3700,41 @@ public class ManagementServerImpl extends ManagerBase implements ManagementServe
|
||||
@Override
|
||||
public String getEncryptionKey() {
|
||||
if (_encryptionKey == null) {
|
||||
_encryptionKey = _configDao.getValueAndInitIfNotExist(Config.EncryptionKey.key(),
|
||||
Config.EncryptionKey.getCategory(),
|
||||
_encryptionKey = _configDao.getValueAndInitIfNotExist(Config.EncryptionKey.key(),
|
||||
Config.EncryptionKey.getCategory(),
|
||||
getBase64EncodedRandomKey(128));
|
||||
}
|
||||
return _encryptionKey;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public String getEncryptionIV() {
|
||||
if (_encryptionIV == null) {
|
||||
_encryptionIV = _configDao.getValueAndInitIfNotExist(Config.EncryptionIV.key(),
|
||||
Config.EncryptionIV.getCategory(),
|
||||
_encryptionIV = _configDao.getValueAndInitIfNotExist(Config.EncryptionIV.key(),
|
||||
Config.EncryptionIV.getCategory(),
|
||||
getBase64EncodedRandomKey(128));
|
||||
}
|
||||
return _encryptionIV;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
@DB
|
||||
public void resetEncryptionKeyIV() {
|
||||
|
||||
|
||||
SearchBuilder<ConfigurationVO> sb = _configDao.createSearchBuilder();
|
||||
sb.and("name1", sb.entity().getName(), SearchCriteria.Op.EQ);
|
||||
sb.or("name2", sb.entity().getName(), SearchCriteria.Op.EQ);
|
||||
sb.done();
|
||||
|
||||
|
||||
SearchCriteria<ConfigurationVO> sc = sb.create();
|
||||
sc.setParameters("name1", Config.EncryptionKey.key());
|
||||
sc.setParameters("name2", Config.EncryptionIV.key());
|
||||
|
||||
|
||||
_configDao.expunge(sc);
|
||||
_encryptionKey = null;
|
||||
_encryptionIV = null;
|
||||
}
|
||||
|
||||
|
||||
private static String getBase64EncodedRandomKey(int nBits) {
|
||||
SecureRandom random;
|
||||
try {
|
||||
@ -4056,4 +4070,15 @@ 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;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@ -98,7 +98,6 @@ import com.cloud.dc.dao.DataCenterDao;
|
||||
import com.cloud.dc.dao.HostPodDao;
|
||||
import com.cloud.deploy.DataCenterDeployment;
|
||||
import com.cloud.deploy.DeployDestination;
|
||||
import com.cloud.deploy.DeployPlannerSelector;
|
||||
import com.cloud.deploy.DeploymentPlanner.ExcludeList;
|
||||
import com.cloud.domain.DomainVO;
|
||||
import com.cloud.domain.dao.DomainDao;
|
||||
@ -402,9 +401,6 @@ public class UserVmManagerImpl extends ManagerBase implements UserVmManager, Use
|
||||
@Inject
|
||||
AffinityGroupDao _affinityGroupDao;
|
||||
|
||||
@Inject
|
||||
List<DeployPlannerSelector> plannerSelectors;
|
||||
|
||||
protected ScheduledExecutorService _executor = null;
|
||||
protected int _expungeInterval;
|
||||
protected int _expungeDelay;
|
||||
@ -2836,7 +2832,7 @@ public class UserVmManagerImpl extends ManagerBase implements UserVmManager, Use
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public boolean finalizeDeployment(Commands cmds,
|
||||
VirtualMachineProfile<UserVmVO> profile, DeployDestination dest,
|
||||
@ -3036,7 +3032,7 @@ public class UserVmManagerImpl extends ManagerBase implements UserVmManager, Use
|
||||
+ " stop due to exception ", ex);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
VMInstanceVO vm = profile.getVirtualMachine();
|
||||
List<NicVO> nics = _nicDao.listByVmId(vm.getId());
|
||||
for (NicVO nic : nics) {
|
||||
@ -3174,15 +3170,15 @@ public class UserVmManagerImpl extends ManagerBase implements UserVmManager, Use
|
||||
|
||||
VirtualMachineEntity vmEntity = _orchSrvc.getVirtualMachine(vm.getUuid());
|
||||
|
||||
String plannerName = null;
|
||||
for (DeployPlannerSelector dps : plannerSelectors) {
|
||||
plannerName = dps.selectPlanner(vm);
|
||||
if (plannerName != null) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
// Get serviceOffering for Virtual Machine
|
||||
ServiceOfferingVO offering = _serviceOfferingDao.findByIdIncludingRemoved(vm.getServiceOfferingId());
|
||||
String plannerName = offering.getDeploymentPlanner();
|
||||
if (plannerName == null) {
|
||||
throw new CloudRuntimeException(String.format("cannot find DeployPlannerSelector for vm[uuid:%s, hypervisorType:%s]", vm.getUuid(), vm.getHypervisorType()));
|
||||
if (vm.getHypervisorType() == HypervisorType.BareMetal) {
|
||||
plannerName = "BareMetalPlanner";
|
||||
} else {
|
||||
plannerName = _configDao.getValue(Config.VmDeploymentPlanner.key());
|
||||
}
|
||||
}
|
||||
|
||||
String reservationId = vmEntity.reserve(plannerName, plan, new ExcludeList(), new Long(callerUser.getId()).toString());
|
||||
@ -3826,7 +3822,7 @@ public class UserVmManagerImpl extends ManagerBase implements UserVmManager, Use
|
||||
+ cmd.getAccountName() + " is disabled.");
|
||||
}
|
||||
|
||||
//check caller has access to both the old and new account
|
||||
//check caller has access to both the old and new account
|
||||
_accountMgr.checkAccess(caller, null, true, oldAccount);
|
||||
_accountMgr.checkAccess(caller, null, true, newAccount);
|
||||
|
||||
|
||||
@ -608,4 +608,10 @@ public class MockResourceManagerImpl extends ManagerBase implements ResourceMana
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean releaseHostReservation(Long hostId) {
|
||||
// TODO Auto-generated method stub
|
||||
return false;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
359
server/test/com/cloud/vm/DeploymentPlanningManagerImplTest.java
Normal file
359
server/test/com/cloud/vm/DeploymentPlanningManagerImplTest.java
Normal file
@ -0,0 +1,359 @@
|
||||
// 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.vm;
|
||||
|
||||
import static org.junit.Assert.*;
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import javax.inject.Inject;
|
||||
import javax.naming.ConfigurationException;
|
||||
|
||||
import com.cloud.service.ServiceOfferingVO;
|
||||
import com.cloud.storage.StorageManager;
|
||||
import com.cloud.storage.dao.DiskOfferingDao;
|
||||
import com.cloud.storage.dao.GuestOSCategoryDao;
|
||||
import com.cloud.storage.dao.GuestOSDao;
|
||||
import com.cloud.storage.dao.StoragePoolHostDao;
|
||||
import com.cloud.storage.dao.VolumeDao;
|
||||
import com.cloud.capacity.CapacityManager;
|
||||
import com.cloud.capacity.dao.CapacityDao;
|
||||
import com.cloud.configuration.dao.ConfigurationDao;
|
||||
import com.cloud.deploy.DeploymentPlanner.ExcludeList;
|
||||
import com.cloud.agent.AgentManager;
|
||||
import com.cloud.dc.ClusterDetailsDao;
|
||||
import com.cloud.dc.ClusterVO;
|
||||
import com.cloud.dc.DataCenterVO;
|
||||
import com.cloud.dc.dao.ClusterDao;
|
||||
import com.cloud.dc.dao.DataCenterDao;
|
||||
import com.cloud.dc.dao.HostPodDao;
|
||||
import com.cloud.deploy.DataCenterDeployment;
|
||||
import com.cloud.deploy.DeployDestination;
|
||||
import com.cloud.deploy.DeploymentClusterPlanner;
|
||||
import com.cloud.deploy.DeploymentPlanner;
|
||||
import com.cloud.deploy.DeploymentPlanner.PlannerResourceUsage;
|
||||
import com.cloud.deploy.DeploymentPlanningManagerImpl;
|
||||
import com.cloud.deploy.FirstFitPlanner;
|
||||
import com.cloud.deploy.PlannerHostReservationVO;
|
||||
import com.cloud.deploy.dao.PlannerHostReservationDao;
|
||||
import org.apache.cloudstack.affinity.AffinityGroupProcessor;
|
||||
import org.apache.cloudstack.affinity.dao.AffinityGroupDao;
|
||||
import org.apache.cloudstack.affinity.dao.AffinityGroupVMMapDao;
|
||||
import org.apache.cloudstack.engine.subsystem.api.storage.DataStoreManager;
|
||||
import org.apache.cloudstack.framework.messagebus.MessageBus;
|
||||
import org.apache.cloudstack.storage.datastore.db.PrimaryDataStoreDao;
|
||||
import org.apache.cloudstack.test.utils.SpringUtils;
|
||||
import org.junit.Before;
|
||||
import org.junit.BeforeClass;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
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 org.springframework.test.context.ContextConfiguration;
|
||||
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
|
||||
import org.springframework.test.context.support.AnnotationConfigContextLoader;
|
||||
|
||||
import com.cloud.exception.AffinityConflictException;
|
||||
import com.cloud.exception.InsufficientServerCapacityException;
|
||||
import com.cloud.host.dao.HostDao;
|
||||
import com.cloud.hypervisor.Hypervisor.HypervisorType;
|
||||
import com.cloud.user.AccountManager;
|
||||
import com.cloud.utils.component.ComponentContext;
|
||||
import com.cloud.vm.dao.UserVmDao;
|
||||
import com.cloud.vm.dao.VMInstanceDao;
|
||||
|
||||
@RunWith(SpringJUnit4ClassRunner.class)
|
||||
@ContextConfiguration(loader = AnnotationConfigContextLoader.class)
|
||||
public class DeploymentPlanningManagerImplTest {
|
||||
|
||||
@Inject
|
||||
DeploymentPlanningManagerImpl _dpm;
|
||||
|
||||
@Inject
|
||||
PlannerHostReservationDao _plannerHostReserveDao;
|
||||
|
||||
@Inject VirtualMachineProfileImpl vmProfile;
|
||||
|
||||
@Inject
|
||||
AffinityGroupVMMapDao _affinityGroupVMMapDao;
|
||||
|
||||
@Inject
|
||||
ExcludeList avoids;
|
||||
|
||||
@Inject
|
||||
DataCenterVO dc;
|
||||
|
||||
@Inject
|
||||
DataCenterDao _dcDao;
|
||||
|
||||
@Inject
|
||||
FirstFitPlanner _planner;
|
||||
|
||||
@Inject
|
||||
ClusterDao _clusterDao;
|
||||
|
||||
private static long domainId = 5L;
|
||||
|
||||
private static long dataCenterId = 1L;
|
||||
|
||||
|
||||
@BeforeClass
|
||||
public static void setUp() throws ConfigurationException {
|
||||
}
|
||||
|
||||
@Before
|
||||
public void testSetUp() {
|
||||
ComponentContext.initComponentsLifeCycle();
|
||||
|
||||
PlannerHostReservationVO reservationVO = new PlannerHostReservationVO(200L, 1L, 2L, 3L, PlannerResourceUsage.Shared);
|
||||
Mockito.when(_plannerHostReserveDao.persist(Mockito.any(PlannerHostReservationVO.class))).thenReturn(reservationVO);
|
||||
Mockito.when(_plannerHostReserveDao.findById(Mockito.anyLong())).thenReturn(reservationVO);
|
||||
Mockito.when(_affinityGroupVMMapDao.countAffinityGroupsForVm(Mockito.anyLong())).thenReturn(0L);
|
||||
|
||||
VMInstanceVO vm = new VMInstanceVO();
|
||||
Mockito.when(vmProfile.getVirtualMachine()).thenReturn(vm);
|
||||
|
||||
Mockito.when(_dcDao.findById(Mockito.anyLong())).thenReturn(dc);
|
||||
Mockito.when(dc.getId()).thenReturn(dataCenterId);
|
||||
|
||||
ClusterVO clusterVO = new ClusterVO();
|
||||
clusterVO.setHypervisorType(HypervisorType.XenServer.toString());
|
||||
Mockito.when(_clusterDao.findById(Mockito.anyLong())).thenReturn(clusterVO);
|
||||
|
||||
Mockito.when(_planner.getName()).thenReturn("FirstFitPlanner");
|
||||
List<DeploymentPlanner> planners = new ArrayList<DeploymentPlanner>();
|
||||
planners.add(_planner);
|
||||
_dpm.setPlanners(planners);
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
public void dataCenterAvoidTest() throws InsufficientServerCapacityException, AffinityConflictException {
|
||||
ServiceOfferingVO svcOffering = new ServiceOfferingVO("testOffering", 1, 512, 500, 1, 1, false, false, false,
|
||||
"test dpm", false, false, null, false, VirtualMachine.Type.User, domainId, null, "FirstFitPlanner");
|
||||
Mockito.when(vmProfile.getServiceOffering()).thenReturn(svcOffering);
|
||||
|
||||
DataCenterDeployment plan = new DataCenterDeployment(dataCenterId);
|
||||
|
||||
Mockito.when(avoids.shouldAvoid((DataCenterVO) Mockito.anyObject())).thenReturn(true);
|
||||
DeployDestination dest = _dpm.planDeployment(vmProfile, plan, avoids);
|
||||
assertNull("DataCenter is in avoid set, destination should be null! ", dest);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void plannerCannotHandleTest() throws InsufficientServerCapacityException, AffinityConflictException {
|
||||
ServiceOfferingVO svcOffering = new ServiceOfferingVO("testOffering", 1, 512, 500, 1, 1, false, false, false,
|
||||
"test dpm", false, false, null, false, VirtualMachine.Type.User, domainId, null,
|
||||
"UserDispersingPlanner");
|
||||
Mockito.when(vmProfile.getServiceOffering()).thenReturn(svcOffering);
|
||||
|
||||
DataCenterDeployment plan = new DataCenterDeployment(dataCenterId);
|
||||
Mockito.when(avoids.shouldAvoid((DataCenterVO) Mockito.anyObject())).thenReturn(false);
|
||||
|
||||
Mockito.when(_planner.canHandle(vmProfile, plan, avoids)).thenReturn(false);
|
||||
DeployDestination dest = _dpm.planDeployment(vmProfile, plan, avoids);
|
||||
assertNull("Planner cannot handle, destination should be null! ", dest);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void emptyClusterListTest() throws InsufficientServerCapacityException, AffinityConflictException {
|
||||
ServiceOfferingVO svcOffering = new ServiceOfferingVO("testOffering", 1, 512, 500, 1, 1, false, false, false,
|
||||
"test dpm", false, false, null, false, VirtualMachine.Type.User, domainId, null, "FirstFitPlanner");
|
||||
Mockito.when(vmProfile.getServiceOffering()).thenReturn(svcOffering);
|
||||
|
||||
DataCenterDeployment plan = new DataCenterDeployment(dataCenterId);
|
||||
Mockito.when(avoids.shouldAvoid((DataCenterVO) Mockito.anyObject())).thenReturn(false);
|
||||
Mockito.when(_planner.canHandle(vmProfile, plan, avoids)).thenReturn(true);
|
||||
|
||||
Mockito.when(((DeploymentClusterPlanner) _planner).orderClusters(vmProfile, plan, avoids)).thenReturn(null);
|
||||
DeployDestination dest = _dpm.planDeployment(vmProfile, plan, avoids);
|
||||
assertNull("Planner cannot handle, destination should be null! ", dest);
|
||||
}
|
||||
|
||||
|
||||
@Configuration
|
||||
@ComponentScan(basePackageClasses = { DeploymentPlanningManagerImpl.class }, includeFilters = { @Filter(value = TestConfiguration.Library.class, type = FilterType.CUSTOM) }, useDefaultFilters = false)
|
||||
public static class TestConfiguration extends SpringUtils.CloudStackTestConfiguration {
|
||||
|
||||
@Bean
|
||||
public FirstFitPlanner firstFitPlanner() {
|
||||
return Mockito.mock(FirstFitPlanner.class);
|
||||
}
|
||||
|
||||
@Bean
|
||||
public DeploymentPlanner deploymentPlanner() {
|
||||
return Mockito.mock(DeploymentPlanner.class);
|
||||
}
|
||||
|
||||
@Bean
|
||||
public DataCenterVO dataCenter() {
|
||||
return Mockito.mock(DataCenterVO.class);
|
||||
}
|
||||
|
||||
@Bean
|
||||
public ExcludeList excludeList() {
|
||||
return Mockito.mock(ExcludeList.class);
|
||||
}
|
||||
|
||||
@Bean
|
||||
public VirtualMachineProfileImpl virtualMachineProfileImpl() {
|
||||
return Mockito.mock(VirtualMachineProfileImpl.class);
|
||||
}
|
||||
|
||||
@Bean
|
||||
public ClusterDetailsDao clusterDetailsDao() {
|
||||
return Mockito.mock(ClusterDetailsDao.class);
|
||||
}
|
||||
|
||||
@Bean
|
||||
public DataStoreManager cataStoreManager() {
|
||||
return Mockito.mock(DataStoreManager.class);
|
||||
}
|
||||
|
||||
@Bean
|
||||
public StorageManager storageManager() {
|
||||
return Mockito.mock(StorageManager.class);
|
||||
}
|
||||
|
||||
@Bean
|
||||
public HostDao hostDao() {
|
||||
return Mockito.mock(HostDao.class);
|
||||
}
|
||||
|
||||
@Bean
|
||||
public HostPodDao hostPodDao() {
|
||||
return Mockito.mock(HostPodDao.class);
|
||||
}
|
||||
|
||||
@Bean
|
||||
public ClusterDao clusterDao() {
|
||||
return Mockito.mock(ClusterDao.class);
|
||||
}
|
||||
|
||||
@Bean
|
||||
public GuestOSDao guestOSDao() {
|
||||
return Mockito.mock(GuestOSDao.class);
|
||||
}
|
||||
|
||||
@Bean
|
||||
public GuestOSCategoryDao guestOSCategoryDao() {
|
||||
return Mockito.mock(GuestOSCategoryDao.class);
|
||||
}
|
||||
|
||||
@Bean
|
||||
public CapacityManager capacityManager() {
|
||||
return Mockito.mock(CapacityManager.class);
|
||||
}
|
||||
|
||||
@Bean
|
||||
public StoragePoolHostDao storagePoolHostDao() {
|
||||
return Mockito.mock(StoragePoolHostDao.class);
|
||||
}
|
||||
|
||||
@Bean
|
||||
public VolumeDao volumeDao() {
|
||||
return Mockito.mock(VolumeDao.class);
|
||||
}
|
||||
|
||||
@Bean
|
||||
public ConfigurationDao configurationDao() {
|
||||
return Mockito.mock(ConfigurationDao.class);
|
||||
}
|
||||
|
||||
@Bean
|
||||
public DiskOfferingDao diskOfferingDao() {
|
||||
return Mockito.mock(DiskOfferingDao.class);
|
||||
}
|
||||
|
||||
@Bean
|
||||
public PrimaryDataStoreDao primaryDataStoreDao() {
|
||||
return Mockito.mock(PrimaryDataStoreDao.class);
|
||||
}
|
||||
|
||||
@Bean
|
||||
public CapacityDao capacityDao() {
|
||||
return Mockito.mock(CapacityDao.class);
|
||||
}
|
||||
|
||||
@Bean
|
||||
public PlannerHostReservationDao plannerHostReservationDao() {
|
||||
return Mockito.mock(PlannerHostReservationDao.class);
|
||||
}
|
||||
|
||||
@Bean
|
||||
public AffinityGroupProcessor affinityGroupProcessor() {
|
||||
return Mockito.mock(AffinityGroupProcessor.class);
|
||||
}
|
||||
|
||||
@Bean
|
||||
public AffinityGroupDao affinityGroupDao() {
|
||||
return Mockito.mock(AffinityGroupDao.class);
|
||||
}
|
||||
|
||||
@Bean
|
||||
public AffinityGroupVMMapDao affinityGroupVMMapDao() {
|
||||
return Mockito.mock(AffinityGroupVMMapDao.class);
|
||||
}
|
||||
|
||||
@Bean
|
||||
public AccountManager accountManager() {
|
||||
return Mockito.mock(AccountManager.class);
|
||||
}
|
||||
|
||||
@Bean
|
||||
public AgentManager agentManager() {
|
||||
return Mockito.mock(AgentManager.class);
|
||||
}
|
||||
|
||||
@Bean
|
||||
public MessageBus messageBus() {
|
||||
return Mockito.mock(MessageBus.class);
|
||||
}
|
||||
|
||||
|
||||
@Bean
|
||||
public UserVmDao userVMDao() {
|
||||
return Mockito.mock(UserVmDao.class);
|
||||
}
|
||||
|
||||
@Bean
|
||||
public VMInstanceDao vmInstanceDao() {
|
||||
return Mockito.mock(VMInstanceDao.class);
|
||||
}
|
||||
|
||||
@Bean
|
||||
public DataCenterDao dataCenterDao() {
|
||||
return Mockito.mock(DataCenterDao.class);
|
||||
}
|
||||
|
||||
public static class Library implements TypeFilter {
|
||||
|
||||
@Override
|
||||
public boolean match(MetadataReader mdr, MetadataReaderFactory arg1) throws IOException {
|
||||
ComponentScan cs = TestConfiguration.class.getAnnotation(ComponentScan.class);
|
||||
return SpringUtils.includedInBasePackageClasses(mdr.getClassMetadata().getClassName(), cs);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -431,7 +431,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;
|
||||
}
|
||||
|
||||
@ -82,6 +82,7 @@ import com.cloud.offerings.dao.NetworkOfferingDao;
|
||||
import com.cloud.offerings.dao.NetworkOfferingServiceMapDao;
|
||||
import com.cloud.offerings.dao.NetworkOfferingServiceMapDaoImpl;
|
||||
import com.cloud.projects.ProjectManager;
|
||||
import com.cloud.server.ManagementService;
|
||||
import com.cloud.service.dao.ServiceOfferingDaoImpl;
|
||||
import com.cloud.storage.dao.DiskOfferingDaoImpl;
|
||||
import com.cloud.storage.dao.S3DaoImpl;
|
||||
@ -155,162 +156,167 @@ useDefaultFilters=false
|
||||
)
|
||||
|
||||
public class ChildTestConfiguration {
|
||||
|
||||
|
||||
@Bean
|
||||
public ManagementService managementService() {
|
||||
return Mockito.mock(ManagementService.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 UserContext userContext() {
|
||||
return Mockito.mock(UserContext.class);
|
||||
}
|
||||
|
||||
|
||||
@Bean
|
||||
public UserContextInitializer userContextInitializer() {
|
||||
return Mockito.mock(UserContextInitializer.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);
|
||||
}
|
||||
|
||||
|
||||
@Bean
|
||||
public DataCenterLinkLocalIpAddressDao datacenterLinkLocalIpAddressDao() {
|
||||
return Mockito.mock(DataCenterLinkLocalIpAddressDao.class);
|
||||
@ -342,5 +348,5 @@ public class ChildTestConfiguration {
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
42
server/test/resources/affinityContext.xml
Normal file
42
server/test/resources/affinityContext.xml
Normal file
@ -0,0 +1,42 @@
|
||||
<!-- 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 class="org.apache.cloudstack.affinity.AffinityApiTestConfiguration" />
|
||||
|
||||
|
||||
</beans>
|
||||
@ -973,9 +973,61 @@ CREATE TABLE `cloud`.`network_asa1000v_map` (
|
||||
|
||||
ALTER TABLE `cloud`.`network_offerings` ADD COLUMN `eip_associate_public_ip` int(1) unsigned NOT NULL DEFAULT 0 COMMENT 'true if public IP is associated with user VM creation by default when EIP service is enabled.' AFTER `elastic_ip_service`;
|
||||
|
||||
-- Re-enable foreign key checking, at the end of the upgrade path
|
||||
SET foreign_key_checks = 1;
|
||||
|
||||
CREATE TABLE `cloud`.`op_host_planner_reservation` (
|
||||
`id` bigint unsigned NOT NULL auto_increment,
|
||||
`data_center_id` bigint unsigned NOT NULL,
|
||||
`pod_id` bigint unsigned,
|
||||
`cluster_id` bigint unsigned,
|
||||
`host_id` bigint unsigned,
|
||||
`resource_usage` varchar(255) COMMENT 'Shared(between planners) Vs Dedicated (exclusive usage to a planner)',
|
||||
PRIMARY KEY (`id`),
|
||||
INDEX `i_op_host_planner_reservation__host_resource_usage`(`host_id`, `resource_usage`),
|
||||
CONSTRAINT `fk_planner_reservation__host_id` FOREIGN KEY (`host_id`) REFERENCES `host`(`id`) ON DELETE CASCADE,
|
||||
CONSTRAINT `fk_planner_reservation__data_center_id` FOREIGN KEY (`data_center_id`) REFERENCES `cloud`.`data_center`(`id`) ON DELETE CASCADE,
|
||||
CONSTRAINT `fk_planner_reservation__pod_id` FOREIGN KEY (`pod_id`) REFERENCES `cloud`.`host_pod_ref`(`id`) ON DELETE CASCADE,
|
||||
CONSTRAINT `fk_planner_reservation__cluster_id` FOREIGN KEY (`cluster_id`) REFERENCES `cloud`.`cluster`(`id`) ON DELETE CASCADE
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
|
||||
|
||||
ALTER TABLE `cloud`.`service_offering` ADD COLUMN `deployment_planner` varchar(255) COMMENT 'Planner heuristics used to deploy a VM of this offering; if null global config vm.deployment.planner is used';
|
||||
|
||||
INSERT IGNORE INTO `cloud`.`configuration` VALUES ('Advanced', 'DEFAULT', 'management-server', 'vm.deployment.planner', 'FirstFitPlanner', '[''FirstFitPlanner'', ''UserDispersingPlanner'', ''UserConcentratedPodPlanner'']: DeploymentPlanner heuristic that will be used for VM deployment.');
|
||||
INSERT IGNORE INTO `cloud`.`configuration` VALUES ('Advanced', 'DEFAULT', 'management-server', 'host.reservation.release.period', '300000', 'The interval in milliseconds between host reservation release checks');
|
||||
|
||||
DROP VIEW IF EXISTS `cloud`.`service_offering_view`;
|
||||
CREATE VIEW `cloud`.`service_offering_view` AS
|
||||
select
|
||||
service_offering.id,
|
||||
disk_offering.uuid,
|
||||
disk_offering.name,
|
||||
disk_offering.display_text,
|
||||
disk_offering.created,
|
||||
disk_offering.tags,
|
||||
disk_offering.removed,
|
||||
disk_offering.use_local_storage,
|
||||
disk_offering.system_use,
|
||||
service_offering.cpu,
|
||||
service_offering.speed,
|
||||
service_offering.ram_size,
|
||||
service_offering.nw_rate,
|
||||
service_offering.mc_rate,
|
||||
service_offering.ha_enabled,
|
||||
service_offering.limit_cpu_use,
|
||||
service_offering.host_tag,
|
||||
service_offering.default_use,
|
||||
service_offering.vm_type,
|
||||
service_offering.sort_key,
|
||||
service_offering.deployment_planner,
|
||||
domain.id domain_id,
|
||||
domain.uuid domain_uuid,
|
||||
domain.name domain_name,
|
||||
domain.path domain_path
|
||||
from
|
||||
`cloud`.`service_offering`
|
||||
inner join
|
||||
`cloud`.`disk_offering` ON service_offering.id = disk_offering.id
|
||||
left join
|
||||
`cloud`.`domain` ON disk_offering.domain_id = domain.id;
|
||||
|
||||
-- Add "default" field to account/user tables
|
||||
ALTER TABLE `cloud`.`account` ADD COLUMN `default` int(1) unsigned NOT NULL DEFAULT '0' COMMENT '1 if account is default';
|
||||
@ -1605,3 +1657,8 @@ CREATE TABLE `cloud`.`nic_ip_alias` (
|
||||
|
||||
alter table `cloud`.`vpc_gateways` add column network_acl_id bigint unsigned default 1 NOT NULL;
|
||||
update `cloud`.`vpc_gateways` set network_acl_id = 2;
|
||||
|
||||
-- Re-enable foreign key checking, at the end of the upgrade path
|
||||
SET foreign_key_checks = 1;
|
||||
|
||||
|
||||
|
||||
@ -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.
|
||||
|
||||
#!/usr/bin/env python
|
||||
|
||||
import marvin
|
||||
from marvin import cloudstackTestCase
|
||||
from marvin.cloudstackTestCase import *
|
||||
|
||||
import unittest
|
||||
import hashlib
|
||||
import random
|
||||
|
||||
class TestDeployVmWithVariedPlanners(cloudstackTestCase):
|
||||
"""
|
||||
This test tests that we can create serviceOfferings with different deployment Planners and deploy virtual machines into a user account
|
||||
using these service offerings and builtin template
|
||||
"""
|
||||
def setUp(self):
|
||||
"""
|
||||
CloudStack internally saves its passwords in md5 form and that is how we
|
||||
specify it in the API. Python's hashlib library helps us to quickly hash
|
||||
strings as follows
|
||||
"""
|
||||
mdf = hashlib.md5()
|
||||
mdf.update('password')
|
||||
mdf_pass = mdf.hexdigest()
|
||||
|
||||
self.apiClient = self.testClient.getApiClient() #Get ourselves an API client
|
||||
|
||||
self.acct = createAccount.createAccountCmd() #The createAccount command
|
||||
self.acct.accounttype = 0 #We need a regular user. admins have accounttype=1
|
||||
self.acct.firstname = 'test'
|
||||
self.acct.lastname = 'user' #What's up doc?
|
||||
self.acct.username = 'testuser'
|
||||
self.acct.password = mdf_pass #The md5 hashed password string
|
||||
self.acct.email = 'test@domain.com'
|
||||
self.acct.account = 'testacct'
|
||||
self.acct.domainid = 1 #The default ROOT domain
|
||||
self.acctResponse = self.apiClient.createAccount(self.acct)
|
||||
# And upon successful creation we'll log a helpful message in our logs
|
||||
# using the default debug logger of the test framework
|
||||
self.debug("successfully created account: %s, id: \
|
||||
%s"%(self.acctResponse.name, \
|
||||
self.acctResponse.id))
|
||||
|
||||
#Create service offerings with varied planners
|
||||
self.svcOfferingFirstFit = createServiceOffering.createServiceOfferingCmd()
|
||||
self.svcOfferingFirstFit.name = 'Tiny Instance FirstFit'
|
||||
self.svcOfferingFirstFit.displaytext = 'Tiny Instance with FirstFitPlanner'
|
||||
self.svcOfferingFirstFit.cpuspeed = 100
|
||||
self.svcOfferingFirstFit.cpunumber = 1
|
||||
self.svcOfferingFirstFit.memory = 256
|
||||
self.svcOfferingFirstFit.deploymentplanner = 'FirstFitPlanner'
|
||||
self.svcOfferingFirstFitResponse = self.apiClient.createServiceOffering(self.svcOfferingFirstFit)
|
||||
|
||||
self.debug("successfully created serviceofferring name: %s, id: \
|
||||
%s, deploymentPlanner: %s"%(self.svcOfferingFirstFitResponse.name, \
|
||||
self.svcOfferingFirstFitResponse.id,self.svcOfferingFirstFitResponse.deploymentplanner))
|
||||
|
||||
#Create service offerings with varied planners
|
||||
self.svcOfferingUserDispersing = createServiceOffering.createServiceOfferingCmd()
|
||||
self.svcOfferingUserDispersing.name = 'Tiny Instance UserDispersing'
|
||||
self.svcOfferingUserDispersing.displaytext = 'Tiny Instance with UserDispersingPlanner'
|
||||
self.svcOfferingUserDispersing.cpuspeed = 100
|
||||
self.svcOfferingUserDispersing.cpunumber = 1
|
||||
self.svcOfferingUserDispersing.memory = 256
|
||||
self.svcOfferingUserDispersing.deploymentplanner = 'FirstFitPlanner'
|
||||
self.svcOfferingUserDispersingResponse = self.apiClient.createServiceOffering(self.svcOfferingUserDispersing)
|
||||
|
||||
self.debug("successfully created serviceofferring name: %s, id: \
|
||||
%s, deploymentPlanner: %s"%(self.svcOfferingUserDispersingResponse.name, \
|
||||
self.svcOfferingUserDispersingResponse.id,self.svcOfferingUserDispersingResponse.deploymentplanner))
|
||||
|
||||
def test_DeployVm(self):
|
||||
"""
|
||||
Let's start by defining the attributes of our VM that we will be
|
||||
deploying on CloudStack. We will be assuming a single zone is available
|
||||
and is configured and all templates are Ready
|
||||
|
||||
The hardcoded values are used only for brevity.
|
||||
"""
|
||||
deployVmCmd = deployVirtualMachine.deployVirtualMachineCmd()
|
||||
deployVmCmd.zoneid = 1
|
||||
deployVmCmd.account = self.acct.account
|
||||
deployVmCmd.domainid = self.acct.domainid
|
||||
deployVmCmd.templateid = 5 #For default template- CentOS 5.6(64 bit)
|
||||
deployVmCmd.serviceofferingid = self.svcOfferingFirstFitResponse.id
|
||||
|
||||
deployVmResponse = self.apiClient.deployVirtualMachine(deployVmCmd)
|
||||
self.debug("VM %s was deployed in the job %s"%(deployVmResponse.id, deployVmResponse.jobid))
|
||||
|
||||
# At this point our VM is expected to be Running. Let's find out what
|
||||
# listVirtualMachines tells us about VMs in this account
|
||||
|
||||
listVmCmd = listVirtualMachines.listVirtualMachinesCmd()
|
||||
listVmCmd.id = deployVmResponse.id
|
||||
listVmResponse = self.apiClient.listVirtualMachines(listVmCmd)
|
||||
|
||||
self.assertNotEqual(len(listVmResponse), 0, "Check if the list API \
|
||||
returns a non-empty response")
|
||||
|
||||
vm1 = listVmResponse[0]
|
||||
|
||||
self.assertEqual(vm1.id, deployVmResponse.id, "Check if the VM returned \
|
||||
is the same as the one we deployed")
|
||||
self.assertEqual(vm1.state, "Running", "Check if VM has reached \
|
||||
a state of running")
|
||||
|
||||
|
||||
deployVm2Cmd = deployVirtualMachine.deployVirtualMachineCmd()
|
||||
deployVm2Cmd.zoneid = 1
|
||||
deployVm2Cmd.account = self.acct.account
|
||||
deployVm2Cmd.domainid = self.acct.domainid
|
||||
deployVm2Cmd.templateid = 5 #For default template- CentOS 5.6(64 bit)
|
||||
deployVm2Cmd.serviceofferingid = self.svcOfferingFirstFitResponse.id
|
||||
|
||||
deployVm2Response = self.apiClient.deployVirtualMachine(deployVm2Cmd)
|
||||
self.debug("VM %s was deployed in the job %s"%(deployVm2Response.id, deployVm2Response.jobid))
|
||||
|
||||
# At this point our VM is expected to be Running. Let's find out what
|
||||
# listVirtualMachines tells us about VMs in this account
|
||||
|
||||
listVm2Cmd = listVirtualMachines.listVirtualMachinesCmd()
|
||||
listVm2Cmd.id = deployVm2Response.id
|
||||
listVm2Response = self.apiClient.listVirtualMachines(listVm2Cmd)
|
||||
self.assertNotEqual(len(listVm2Response), 0, "Check if the list API \
|
||||
returns a non-empty response")
|
||||
vm2 = listVm2Response[0]
|
||||
self.assertEqual(vm2.id, deployVm2Response.id, "Check if the VM returned \
|
||||
is the same as the one we deployed")
|
||||
self.assertEqual(vm2.state, "Running", "Check if VM has reached \
|
||||
a state of running")
|
||||
|
||||
|
||||
def tearDown(self): # Teardown will delete the Account as well as the VM once the VM reaches "Running" state
|
||||
"""
|
||||
And finally let us cleanup the resources we created by deleting the
|
||||
account. All good unittests are atomic and rerunnable this way
|
||||
"""
|
||||
deleteAcct = deleteAccount.deleteAccountCmd()
|
||||
deleteAcct.id = self.acctResponse.id
|
||||
self.apiClient.deleteAccount(deleteAcct)
|
||||
deleteSvcOfferingFirstFit = deleteServiceOffering.deleteServiceOfferingCmd()
|
||||
deleteSvcOfferingFirstFit.id = self.svcOfferingFirstFitResponse.id
|
||||
self.apiClient.deleteServiceOffering(deleteSvcOfferingFirstFit);
|
||||
deleteSvcOfferingUserDispersing = deleteServiceOffering.deleteServiceOfferingCmd()
|
||||
deleteSvcOfferingUserDispersing.id = self.svcOfferingUserDispersingResponse.id
|
||||
self.apiClient.deleteServiceOffering(deleteSvcOfferingUserDispersing);
|
||||
|
||||
@ -142,6 +142,7 @@ known_categories = {
|
||||
'listNics':'Nic',
|
||||
'AffinityGroup': 'Affinity Group',
|
||||
'InternalLoadBalancer': 'Internal LB',
|
||||
'DeploymentPlanners': 'Configuration',
|
||||
}
|
||||
|
||||
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user