moved out user dispsersing deployment planner

This commit is contained in:
Alex Huang 2012-06-20 16:03:04 -07:00
parent 04b92c9315
commit 6e48383ef8
5 changed files with 382 additions and 0 deletions

View File

@ -0,0 +1,10 @@
<?xml version="1.0" encoding="UTF-8"?>
<classpath>
<classpathentry kind="src" path="src"/>
<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-1.7"/>
<classpathentry combineaccessrules="false" kind="src" path="/api"/>
<classpathentry combineaccessrules="false" kind="src" path="/core"/>
<classpathentry combineaccessrules="false" kind="src" path="/server"/>
<classpathentry combineaccessrules="false" kind="src" path="/utils"/>
<classpathentry kind="output" path="bin"/>
</classpath>

View File

@ -0,0 +1,17 @@
<?xml version="1.0" encoding="UTF-8"?>
<projectDescription>
<name>user-dispersing</name>
<comment></comment>
<projects>
</projects>
<buildSpec>
<buildCommand>
<name>org.eclipse.jdt.core.javabuilder</name>
<arguments>
</arguments>
</buildCommand>
</buildSpec>
<natures>
<nature>org.eclipse.jdt.core.javanature</nature>
</natures>
</projectDescription>

View File

@ -0,0 +1,12 @@
#Tue Jun 19 15:34:37 PDT 2012
eclipse.preferences.version=1
org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled
org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.7
org.eclipse.jdt.core.compiler.codegen.unusedLocal=preserve
org.eclipse.jdt.core.compiler.compliance=1.7
org.eclipse.jdt.core.compiler.debug.lineNumber=generate
org.eclipse.jdt.core.compiler.debug.localVariable=generate
org.eclipse.jdt.core.compiler.debug.sourceFile=generate
org.eclipse.jdt.core.compiler.problem.assertIdentifier=error
org.eclipse.jdt.core.compiler.problem.enumIdentifier=error
org.eclipse.jdt.core.compiler.source=1.7

View File

@ -0,0 +1,128 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
Licensed to the Apache Software Foundation (ASF) under one or more
contributor license agreements. See the NOTICE file distributed with
this work for additional information regarding copyright ownership.
The ASF licenses this file to You under the Apache License, Version 2.0
(the "License"); you may not use this file except in compliance with
the License. You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
-->
<project name="Cloud Stack User Dispersing Deployment Planner" default="help" basedir=".">
<description>
Cloud Stack ant build file
</description>
<dirname property="dp-user-dispersing.base.dir" file="${ant.file.Cloud Stack User Dispersing Deployment Planner}/"/>
<!-- This directory must be set -->
<property name="top.dir" location="${dp-user-dispersing.base.dir}/../../.."/>
<property name="build.dir" location="${top.dir}/build"/>
<echo message="build.dir=${build.dir}; top.dir=${top.dir}; dp-user-dispersing.base.dir=${dp-user-dispersing.base.dir}"/>
<!-- Import anything that the user wants to set-->
<!-- Import properties files and environment variables here -->
<property environment="env" />
<condition property="build-cloud.properties.file" value="${build.dir}/override/build-cloud.properties" else="${build.dir}/build-cloud.properties">
<available file="${build.dir}/override/build-cloud.properties" />
</condition>
<condition property="cloud.properties.file" value="${build.dir}/override/cloud.properties" else="${build.dir}/cloud.properties">
<available file="${build.dir}/override/cloud.properties" />
</condition>
<condition property="override.file" value="${build.dir}/override/replace.properties" else="${build.dir}/replace.properties">
<available file="${build.dir}/override/replace.properties" />
</condition>
<echo message="Using build parameters from ${build-cloud.properties.file}" />
<property file="${build-cloud.properties.file}" />
<echo message="Using company info from ${cloud.properties.file}" />
<property file="${cloud.properties.file}" />
<echo message="Using override file from ${override.file}" />
<property file="${override.file}" />
<property file="${build.dir}/build.number" />
<!-- In case these didn't get defined in the build-cloud.properties -->
<property name="branding.name" value="default" />
<property name="deprecation" value="off" />
<property name="target.compat.version" value="1.6" />
<property name="source.compat.version" value="1.6" />
<property name="debug" value="true" />
<property name="debuglevel" value="lines,source"/>
<echo message="target.dir=${target.dir}; top.dir=${top.dir}"/>
<!-- directories for build and distribution -->
<property name="target.dir" location="${top.dir}/target" />
<property name="classes.dir" location="${target.dir}/classes" />
<property name="jar.dir" location="${target.dir}/jar" />
<property name="dep.cache.dir" location="${target.dir}/dep-cache" />
<property name="build.log" location="${target.dir}/ant_verbose.txt" />
<property name="deps.dir" location="${top.dir}/deps" />
<property name="dp-user-dispersing.jar" value="cloud-dp-user-dispersing.jar" />
<property name="dp-user-dispersing-scripts.dir" location="${dp-user-dispersing.base.dir}/scripts" />
<import file="${build.dir}/build-common.xml"/>
<echo message="target.dir=${target.dir}; top.dir=${top.dir}"/>
<!-- This section needs to be replaced by some kind of dependency library-->
<path id="deps.classpath">
<!--filelist files="${deps.classpath}" /-->
<fileset dir="${deps.dir}" erroronmissingdir="false">
<include name="*.jar" />
</fileset>
</path>
<path id="cloudstack.classpath">
<fileset dir="${jar.dir}">
<include name="*.jar"/>
</fileset>
</path>
<path id="dp-user-dispersing.classpath">
<path refid="deps.classpath"/>
<path refid="cloudstack.classpath"/>
</path>
<!-- This section needs to be replaced by some kind of dependency library-->
<target name="init" description="Initialize binaries directory">
<mkdir dir="${classes.dir}/${dp-user-dispersing.jar}"/>
<mkdir dir="${jar.dir}"/>
</target>
<target name="compile-dp-user-dispersing" depends="init" description="Compile dp-user-dispersing">
<compile-java jar.name="${dp-user-dispersing.jar}" top.dir="${dp-user-dispersing.base.dir}" classpath="dp-user-dispersing.classpath" />
</target>
<target name="help" description="help">
<echo level="info" message="This is the build file for dp-user-dispersing"/>
<echo level="info" message="You can do a build by doing ant build or clean by ant clean" />
</target>
<target name="clean-dp-user-dispersing">
<delete dir="${classes.dir}/${dp-user-dispersing.jar}"/>
</target>
<target name="build" depends="compile-dp-user-dispersing"/>
<target name="clean" depends="clean-dp-user-dispersing"/>
</project>

View File

@ -0,0 +1,215 @@
// Copyright 2012 Citrix Systems, Inc. Licensed under the
// Apache License, Version 2.0 (the "License"); you may not use this
// file except in compliance with the License. Citrix Systems, Inc.
// reserves all rights not expressly granted by 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.
//
// Automatically generated by addcopyright.py at 04/03/2012
package com.cloud.deploy;
import java.util.ArrayList;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.SortedMap;
import java.util.TreeMap;
import javax.ejb.Local;
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 {
private static final Logger s_logger = Logger.getLogger(UserDispersingPlanner.class);
/**
* This method should reorder the given list of Cluster Ids by applying any necessary heuristic
* for this planner
* For UserDispersingPlanner we need to order the clusters by considering the number of VMs for this account
* @return List<Long> ordered list of Cluster Ids
*/
@Override
protected List<Long> reorderClusters(long id, boolean isZone, Pair<List<Long>, Map<Long, Double>> clusterCapacityInfo, VirtualMachineProfile<? extends VirtualMachine> vmProfile, DeploymentPlan plan){
List<Long> clusterIdsByCapacity = clusterCapacityInfo.first();
if(vmProfile.getOwner() == null){
return clusterIdsByCapacity;
}
long accountId = vmProfile.getOwner().getAccountId();
Pair<List<Long>, Map<Long, Double>> clusterIdsVmCountInfo = listClustersByUserDispersion(id, isZone, accountId);
//now we have 2 cluster lists - one ordered by capacity and the other by number of VMs for this account
//need to apply weights to these to find the correct ordering to follow
if(_userDispersionWeight == 1.0f){
List<Long> clusterIds = clusterIdsVmCountInfo.first();
clusterIds.retainAll(clusterIdsByCapacity);
return clusterIds;
}else{
//apply weights to the two lists
return orderByApplyingWeights(clusterCapacityInfo, clusterIdsVmCountInfo, accountId);
}
}
/**
* This method should reorder the given list of Pod Ids by applying any necessary heuristic
* for this planner
* For UserDispersingPlanner we need to order the pods by considering the number of VMs for this account
* @return List<Long> ordered list of Pod Ids
*/
@Override
protected List<Long> reorderPods(Pair<List<Long>, Map<Long, Double>> podCapacityInfo, VirtualMachineProfile<? extends VirtualMachine> vmProfile, DeploymentPlan plan){
List<Long> podIdsByCapacity = podCapacityInfo.first();
if(vmProfile.getOwner() == null){
return podIdsByCapacity;
}
long accountId = vmProfile.getOwner().getAccountId();
Pair<List<Long>, Map<Long, Double>> podIdsVmCountInfo = listPodsByUserDispersion(plan.getDataCenterId(), accountId);
//now we have 2 pod lists - one ordered by capacity and the other by number of VMs for this account
//need to apply weights to these to find the correct ordering to follow
if(_userDispersionWeight == 1.0f){
List<Long> podIds = podIdsVmCountInfo.first();
podIds.retainAll(podIdsByCapacity);
return podIds;
}else{
//apply weights to the two lists
return orderByApplyingWeights(podCapacityInfo, podIdsVmCountInfo, accountId);
}
}
protected Pair<List<Long>, Map<Long, Double>> listClustersByUserDispersion(long id, boolean isZone, long accountId){
if (s_logger.isDebugEnabled()) {
s_logger.debug("Applying Userdispersion heuristic to clusters for account: "+ accountId);
}
Pair<List<Long>, Map<Long, Double>> clusterIdsVmCountInfo;
if(isZone){
clusterIdsVmCountInfo = _vmInstanceDao.listClusterIdsInZoneByVmCount(id, accountId);
}else{
clusterIdsVmCountInfo = _vmInstanceDao.listClusterIdsInPodByVmCount(id, accountId);
}
if (s_logger.isTraceEnabled()) {
s_logger.trace("List of clusters in ascending order of number of VMs: "+ clusterIdsVmCountInfo.first());
}
return clusterIdsVmCountInfo;
}
protected Pair<List<Long>, Map<Long, Double>> listPodsByUserDispersion(long dataCenterId, long accountId) {
if (s_logger.isDebugEnabled()) {
s_logger.debug("Applying Userdispersion heuristic to pods for account: "+ accountId);
}
Pair<List<Long>, Map<Long, Double>> podIdsVmCountInfo = _vmInstanceDao.listPodIdsInZoneByVmCount(dataCenterId, accountId);
if (s_logger.isTraceEnabled()) {
s_logger.trace("List of pods in ascending order of number of VMs: "+ podIdsVmCountInfo.first());
}
return podIdsVmCountInfo;
}
private List<Long> orderByApplyingWeights(Pair<List<Long>, Map<Long, Double>> capacityInfo, Pair<List<Long>, Map<Long, Double>> vmCountInfo, long accountId){
List<Long> capacityOrderedIds = capacityInfo.first();
List<Long> vmCountOrderedIds = vmCountInfo.first();
Map<Long, Double> capacityMap = capacityInfo.second();
Map<Long, Double> vmCountMap = vmCountInfo.second();
if (s_logger.isTraceEnabled()) {
s_logger.trace("Capacity Id list: "+ capacityOrderedIds + " , capacityMap:"+capacityMap);
}
if (s_logger.isTraceEnabled()) {
s_logger.trace("Vm Count Id list: "+ vmCountOrderedIds + " , vmCountMap:"+vmCountMap);
}
List<Long> idsReorderedByWeights = new ArrayList<Long>();
float capacityWeight = (1.0f -_userDispersionWeight);
if (s_logger.isDebugEnabled()) {
s_logger.debug("Applying userDispersionWeight: "+ _userDispersionWeight);
}
//normalize the vmCountMap
LinkedHashMap<Long, Double> normalisedVmCountIdMap= new LinkedHashMap<Long, Double>();
Long totalVmsOfAccount = _vmInstanceDao.countRunningByAccount(accountId);
if (s_logger.isDebugEnabled()) {
s_logger.debug("Total VMs for account: "+ totalVmsOfAccount);
}
for(Long id : vmCountOrderedIds){
Double normalisedCount = vmCountMap.get(id) / totalVmsOfAccount;
normalisedVmCountIdMap.put(id, normalisedCount);
}
//consider only those ids that are in capacity map.
SortedMap<Double, List<Long>> sortedMap= new TreeMap<Double, List<Long>>();
for(Long id : capacityOrderedIds){
Double weightedCapacityValue = capacityMap.get(id) * capacityWeight;
Double weightedVmCountValue = normalisedVmCountIdMap.get(id) * _userDispersionWeight;
Double totalWeight = weightedCapacityValue + weightedVmCountValue;
if(sortedMap.containsKey(totalWeight)){
List<Long> idList = sortedMap.get(totalWeight);
idList.add(id);
sortedMap.put(totalWeight, idList);
}else{
List<Long> idList = new ArrayList<Long>();
idList.add(id);
sortedMap.put(totalWeight, idList);
}
}
for(List<Long> idList : sortedMap.values()){
idsReorderedByWeights.addAll(idList);
}
if (s_logger.isTraceEnabled()) {
s_logger.trace("Reordered Id list: "+ idsReorderedByWeights);
}
return idsReorderedByWeights;
}
@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;
@Override
public boolean configure(String name, Map<String, Object> params) throws ConfigurationException {
super.configure(name, params);
String weight = _configDao.getValue(Config.VmUserDispersionWeight.key());
_userDispersionWeight = NumbersUtil.parseFloat(weight, 1.0f);
return true;
}
}