Navigation Menu

Skip to content

Commit

Permalink
Add filtering on resource tags for instances (EUCA-4655)
Browse files Browse the repository at this point in the history
Instance filtering using tags is now supported via the new
VmInstanceFilterSupport class. The VmInstanceFilterSupportTest provides
unit test coverage of the tag filtering configuration. VmControl is
updated to use filters when describing instances. VmInstances is updated
to allow use of a Criteria / alias Map for instance lookup (for database
filters)
  • Loading branch information
sjones4 committed Jan 11, 2013
1 parent 162933e commit 9362a1c
Show file tree
Hide file tree
Showing 6 changed files with 96 additions and 30 deletions.
Expand Up @@ -38,23 +38,28 @@ public class Filter {
@Nonnull private final Map<String,String> aliases;
@Nonnull private final Criterion criterion;
@Nonnull private final Predicate<Object> predicate;
private final boolean filteringOnTags;

Filter( @Nonnull final Map<String,String> aliases,
@Nonnull final Criterion criterion,
@Nonnull final Predicate<Object> predicate ) {
@Nonnull final Predicate<Object> predicate,
final boolean filteringOnTags ) {
this.aliases = aliases;
this.criterion = criterion;
this.predicate = predicate;
this.filteringOnTags = filteringOnTags;
}

Filter( @Nonnull final Predicate<Object> predicate ) {
Filter( @Nonnull final Predicate<Object> predicate,
final boolean filteringOnTags ) {
this( Collections.<String,String>emptyMap(),
Restrictions.conjunction(),
predicate );
predicate,
filteringOnTags );
}

private Filter() {
this( Predicates.alwaysTrue() );
this( Predicates.alwaysTrue(), false );
}

/**
Expand Down Expand Up @@ -87,6 +92,15 @@ public Predicate<Object> asPredicate() {
return predicate;
}

/**
* Does the filter use tags?
*
* @return True if the filter uses any tags
*/
public boolean isFilteringOnTags() {
return filteringOnTags;
}

/**
* Create a Filter that will always pass (filters out nothing)
*/
Expand Down
Expand Up @@ -550,7 +550,7 @@ public Filter generate( final Map<String, Set<String>> filters,
}
if ( tagPresent ) conjunction.add( tagCriterion( accountId, tagConjunction ) );

return new Filter( aliases, conjunction, Predicates.and( and ) );
return new Filter( aliases, conjunction, Predicates.and( and ), tagPresent );
}

public static FilterSupport forResource( @Nonnull final Class<? extends CloudMetadata> metadataClass ) {
Expand Down
Expand Up @@ -22,7 +22,6 @@
import java.util.Map;
import java.util.Set;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
import com.eucalyptus.cloud.CloudMetadata;
import com.google.common.base.Function;
import com.google.common.collect.ImmutableMap;
Expand Down
Expand Up @@ -99,6 +99,8 @@
import com.eucalyptus.records.EventRecord;
import com.eucalyptus.records.EventType;
import com.eucalyptus.records.Logs;
import com.eucalyptus.tags.Filter;
import com.eucalyptus.tags.Filters;
import com.eucalyptus.util.EucalyptusCloudException;
import com.eucalyptus.util.Exceptions;
import com.eucalyptus.util.OwnerFullName;
Expand Down Expand Up @@ -193,13 +195,19 @@ public DescribeInstancesResponseType describeInstances( final DescribeInstancesT
boolean showAll = msg.getInstancesSet( ).remove( "verbose" );
final ArrayList<String> instancesSet = msg.getInstancesSet( );
final Multimap<String, RunningInstancesItemType> instanceMap = TreeMultimap.create( );
final Map<String, ReservationInfoType> reservations = Maps.newHashMap( );
Predicate<VmInstance> filter = CloudMetadatas.filterPrivilegesById( msg.getInstancesSet( ) );
final Map<String, ReservationInfoType> reservations = Maps.newHashMap();
final Filter filter = Filters.generate( msg.getFilterSet(), VmInstance.class );
final Predicate<? super VmInstance> requestedAndAccessible = CloudMetadatas.filteringFor( VmInstance.class )
.byId( msg.getInstancesSet( ) )
.byPredicate( filter.asPredicate() )
.byPredicate( filter.isFilteringOnTags() ? Predicates.not( VmState.TERMINATED ) : Predicates.<VmInstance>alwaysTrue() ) // terminated instances have no tags
.byPrivileges()
.buildPredicate();
OwnerFullName ownerFullName = ( ctx.hasAdministrativePrivileges( ) && showAll )
? null
: ctx.getUserFullName( ).asAccountFullName( );
try {
for ( final VmInstance vm : VmInstances.list( ownerFullName, filter ) ) {
for ( final VmInstance vm : VmInstances.list( ownerFullName, filter.asCriterion(), filter.getAliases(), requestedAndAccessible ) ) {
if ( !instancesSet.isEmpty( ) && !instancesSet.contains( vm.getInstanceId( ) ) ) {
continue;
}
Expand Down
Expand Up @@ -75,8 +75,11 @@
import java.util.NoSuchElementException;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
import javax.persistence.EntityTransaction;
import org.apache.log4j.Logger;
import org.hibernate.criterion.Criterion;
import org.hibernate.criterion.Example;
import org.hibernate.criterion.MatchMode;
import org.hibernate.criterion.Projections;
Expand Down Expand Up @@ -112,6 +115,7 @@
import com.eucalyptus.records.EventType;
import com.eucalyptus.records.Logs;
import com.eucalyptus.reporting.event.ResourceAvailabilityEvent;
import com.eucalyptus.tags.FilterSupport;
import com.eucalyptus.util.Callback;
import com.eucalyptus.util.HasNaturalId;
import com.eucalyptus.util.LogUtil;
Expand All @@ -129,6 +133,8 @@
import com.google.common.base.Function;
import com.google.common.base.Functions;
import com.google.common.base.Predicate;
import com.google.common.base.Predicates;
import com.google.common.base.Supplier;
import com.google.common.collect.Collections2;
import com.google.common.collect.Iterables;
import com.google.common.collect.Lists;
Expand Down Expand Up @@ -654,30 +660,56 @@ public static List<VmInstance> list( ) {
return list( null );
}

public static List<VmInstance> list( Predicate<VmInstance> predicate ) {
public static List<VmInstance> list( @Nullable Predicate<? super VmInstance> predicate ) {
return list( null, null, predicate );
}

public static List<VmInstance> list( OwnerFullName ownerFullName, Predicate<VmInstance> predicate ) {
public static List<VmInstance> list( @Nullable OwnerFullName ownerFullName,
@Nullable Predicate<? super VmInstance> predicate ) {
return list( ownerFullName, null, predicate );
}

public static List<VmInstance> list( String instanceId, Predicate<VmInstance> predicate ) {

public static List<VmInstance> list( @Nullable final OwnerFullName ownerFullName,
final Criterion criterion,
final Map<String,String> aliases,
@Nullable final Predicate<? super VmInstance> predicate ) {
return list( new Supplier<List<VmInstance>>() {
@Override
public List<VmInstance> get() {
return Entities.query( VmInstance.named( ownerFullName, null ), false, criterion, aliases );
}
}, predicate );
}

public static List<VmInstance> list( @Nullable String instanceId,
@Nullable Predicate<? super VmInstance> predicate ) {
return list( null, instanceId, predicate );
}

public static List<VmInstance> list( OwnerFullName ownerFullName, String instanceId, Predicate<VmInstance> predicate ) {
public static List<VmInstance> list( @Nullable final OwnerFullName ownerFullName,
@Nullable final String instanceId,
@Nullable Predicate<? super VmInstance> predicate ) {
return list( new Supplier<List<VmInstance>>() {
@Override
public List<VmInstance> get() {
return Entities.query( VmInstance.named( ownerFullName, instanceId ) );
}
}, predicate );
}

private static List<VmInstance> list( @Nonnull Supplier<List<VmInstance>> instancesSupplier,
@Nullable Predicate<? super VmInstance> predicate ) {
predicate = checkPredicate( predicate );
List<VmInstance> ret = listPersistent( ownerFullName, instanceId, predicate );
List<VmInstance> ret = listPersistent( instancesSupplier, predicate );
ret.addAll( Collections2.filter( terminateCache.values( ), predicate ) );
return ret;
}
private static List<VmInstance> listPersistent( OwnerFullName ownerFullName, String instanceId, Predicate<VmInstance> predicate ) {
predicate = checkPredicate( predicate );

private static List<VmInstance> listPersistent( @Nonnull Supplier<List<VmInstance>> instancesSupplier,
@Nonnull Predicate<? super VmInstance> predicate ) {
final EntityTransaction db = Entities.get( VmInstance.class );
try {
final Iterable<VmInstance> vms = Iterables.filter( Entities.query( VmInstance.named( ownerFullName, instanceId ) ), predicate );
final Iterable<VmInstance> vms = Iterables.filter( instancesSupplier.get(), predicate );
db.commit( );
return Lists.newArrayList( vms );
} catch ( final Exception ex ) {
Expand All @@ -688,17 +720,10 @@ private static List<VmInstance> listPersistent( OwnerFullName ownerFullName, Str
}
}

private static Predicate<VmInstance> checkPredicate( Predicate<VmInstance> predicate ) {
if ( predicate == null ) {
predicate = new Predicate<VmInstance>( ) {

@Override
public boolean apply( VmInstance input ) {
return true;
}
};
}
return predicate;
private static <T> Predicate<T> checkPredicate( Predicate<T> predicate ) {
return predicate == null ?
Predicates.<T>alwaysTrue() :
predicate;
}

public static boolean contains( final String name ) {
Expand Down Expand Up @@ -852,4 +877,9 @@ public void fireEvent( final ClockTick event ) {
}
}

public static class VmInstanceFilterSupport extends FilterSupport<VmInstance> {
public VmInstanceFilterSupport() {
super( builderFor( VmInstance.class ).withTagFiltering( VmInstanceTag.class, "instance" ) );
}
}
}
@@ -0,0 +1,15 @@
package com.eucalyptus.vm

import org.junit.Test
import com.eucalyptus.tags.FilterSupportTest

/**
* Unit tests for instance filter support
*/
class VmInstanceFilterSupport extends FilterSupportTest.InstanceTest<VmInstance> {

@Test
void testFilteringSupport() {
assertValid( new VmInstances.VmInstanceFilterSupport() )
}
}

0 comments on commit 9362a1c

Please sign in to comment.