package com.eucalyptus.sla;
import java.util.List;
import java.util.NavigableMap;
import java.util.NoSuchElementException;
import com.eucalyptus.auth.principal.Authorization;
import com.eucalyptus.cluster.Cluster;
import com.eucalyptus.cluster.Clusters;
import com.eucalyptus.cluster.VmTypeAvailability;
import com.eucalyptus.context.Context;
import com.eucalyptus.context.Contexts;
import com.eucalyptus.util.NotEnoughResourcesAvailable;
import com.google.common.base.Predicate;
import com.google.common.collect.Iterables;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import edu.ucsb.eucalyptus.cloud.ResourceToken;
import edu.ucsb.eucalyptus.cloud.VmAllocationInfo;
public class NodeResourceAllocator implements ResourceAllocator {
private static String ALLOCATOR = "euca.cluster.allocator";
@Override
public void allocate( VmAllocationInfo vmInfo ) throws Exception {
String clusterName = vmInfo.getRequest( ).getAvailabilityZone( );
String vmTypeName = vmInfo.getRequest( ).getInstanceType( );
Integer amount = vmInfo.getRequest( ).getMinCount( );
Cluster authorizedCluster = this.doPrivilegedLookup( clusterName, vmTypeName );
VmTypeAvailability vmAvailability = authorizedCluster.getNodeState( ).getAvailability( vmTypeName );
if ( vmAvailability.getAvailable( ) < amount ) {
throw new NotEnoughResourcesAvailable( "Not enough resources (" + vmAvailability.getAvailable( ) + " < " + amount + ": vm instances." );
}
Context ctx = Contexts.lookup( );
ResourceToken token = authorizedCluster.getNodeState( ).getResourceAllocation( ctx.getCorrelationId( ), ctx.getUser( ).getName( ), vmTypeName, amount );
vmInfo.getAllocationTokens( ).add( token );
}
private Cluster doPrivilegedLookup( String clusterName, String vmTypeName ) throws NotEnoughResourcesAvailable {
if ( clusterName != null && !"default".equals( clusterName ) ) {
try {
final Cluster cluster = Clusters.getInstance( ).lookup( clusterName );
return cluster;
} catch ( NoSuchElementException e ) {
throw new NotEnoughResourcesAvailable( "Not enough resources: request cluster does not exist " + clusterName );
}
} else {
Iterable<Cluster> authorizedClusters = Clusters.getInstance( ).listValues( );
NavigableMap<VmTypeAvailability, Cluster> sorted = Maps.newTreeMap( );
for ( Cluster c : authorizedClusters ) {
sorted.put( c.getNodeState( ).getAvailability( vmTypeName ), c );
}
if( sorted.isEmpty( ) ) {
throw new NotEnoughResourcesAvailable( "Not enough resources: no cluster is available on which you have permissions to run instances." );
} else {
return sorted.firstEntry( ).getValue( );
}
}
}
@Override
public void fail( VmAllocationInfo vmInfo, Throwable t ) {
for ( ResourceToken token : vmInfo.getAllocationTokens( ) ) {
Clusters.getInstance( ).lookup( token.getCluster( ) ).getNodeState( ).releaseToken( token );
}
}
}