Skip to content

Commit

Permalink
Add filtering by resource tags for snapshots (EUCA-4662)
Browse files Browse the repository at this point in the history
Snapshot filtering using tags is now supported via the new
SnapshotFilterSupport class. The SnapshotFilterSupportTest provides unit
test coverage of the tag filtering configuration. The SnapshotManager is
updated to use filters when describing snapshots.
  • Loading branch information
sjones4 committed Jan 10, 2013
1 parent b838204 commit 4687a78
Show file tree
Hide file tree
Showing 4 changed files with 54 additions and 25 deletions.
Expand Up @@ -76,6 +76,7 @@
import org.apache.log4j.Logger;
import com.eucalyptus.auth.AuthException;
import com.eucalyptus.auth.principal.AccountFullName;
import com.eucalyptus.cloud.CloudMetadatas;
import com.eucalyptus.cloud.util.DuplicateMetadataException;
import com.eucalyptus.component.NoSuchComponentException;
import com.eucalyptus.component.Partitions;
Expand All @@ -95,6 +96,8 @@
import com.eucalyptus.reporting.event.EventActionInfo;
import com.eucalyptus.reporting.event.SnapShotEvent;
import com.eucalyptus.system.Threads;
import com.eucalyptus.tags.Filter;
import com.eucalyptus.tags.Filters;
import com.eucalyptus.util.EucalyptusCloudException;
import com.eucalyptus.util.Exceptions;
import com.eucalyptus.util.RestrictedTypes;
Expand Down Expand Up @@ -227,29 +230,34 @@ public boolean apply( ServiceConfiguration arg0 ) {
return reply;
}

public DescribeSnapshotsResponseType describe( DescribeSnapshotsType request ) throws EucalyptusCloudException {
DescribeSnapshotsResponseType reply = ( DescribeSnapshotsResponseType ) request.getReply( );
Context ctx = Contexts.lookup( );
boolean showAll = request.getSnapshotSet( ).remove( "verbose" );
AccountFullName ownerFullName = ( ctx.hasAdministrativePrivileges( ) && showAll ) ? null : AccountFullName.getInstance( ctx.getAccount( ) );
EntityTransaction db = Entities.get( Snapshot.class );
public DescribeSnapshotsResponseType describe( final DescribeSnapshotsType request ) throws EucalyptusCloudException {
final DescribeSnapshotsResponseType reply = ( DescribeSnapshotsResponseType ) request.getReply( );
final Context ctx = Contexts.lookup( );
final boolean showAll = request.getSnapshotSet( ).remove( "verbose" );
final AccountFullName ownerFullName = ( ctx.hasAdministrativePrivileges( ) && showAll ) ?
null :
AccountFullName.getInstance( ctx.getAccount( ) );
final Filter filter = Filters.generate( request.getFilterSet(), Snapshot.class );
final EntityTransaction db = Entities.get( Snapshot.class );
try {
List<Snapshot> snapshots = Entities.query( Snapshot.named( ownerFullName, null ) );
for ( Snapshot snap : Iterables.filter( snapshots, RestrictedTypes.filterPrivileged( ) ) ) {
if ( request.getSnapshotSet( ).isEmpty( ) || request.getSnapshotSet( ).contains( snap.getDisplayName( ) ) ) {
try {
edu.ucsb.eucalyptus.msgs.Snapshot snapReply = snap.morph( new edu.ucsb.eucalyptus.msgs.Snapshot( ) );
snapReply.setVolumeId( snap.getParentVolume( ) );
snapReply.setOwnerId( snap.getOwnerAccountNumber( ) );
reply.getSnapshotSet( ).add( snapReply );
} catch ( NoSuchElementException e ) {
LOG.warn( "Error getting snapshot information from the Storage Controller: " + e );
LOG.debug( e, e );
}
final List<Snapshot> snapshots = Entities.query( Snapshot.named( ownerFullName, null ), true, filter.asCriterion(), filter.getAliases() );
final Predicate<? super Snapshot> requestedAndAccessible = CloudMetadatas.filteringFor(Snapshot.class)
.byId( request.getSnapshotSet() )
.byPredicate( filter.asPredicate() )
.byPrivileges()
.buildPredicate();
for ( final Snapshot snap : Iterables.filter( snapshots, requestedAndAccessible ) ) {
try {
final edu.ucsb.eucalyptus.msgs.Snapshot snapReply = snap.morph( new edu.ucsb.eucalyptus.msgs.Snapshot( ) );
snapReply.setVolumeId( snap.getParentVolume( ) );
snapReply.setOwnerId( snap.getOwnerAccountNumber( ) );
reply.getSnapshotSet( ).add( snapReply );
} catch ( NoSuchElementException e ) {
LOG.warn( "Error getting snapshot information from the Storage Controller: " + e );
LOG.debug( e, e );
}
}
db.rollback( );
} catch ( Exception e ) {
} finally {
db.rollback( );
}
return reply;
Expand Down
Expand Up @@ -93,6 +93,7 @@
import com.eucalyptus.event.Listeners;
import com.eucalyptus.records.Logs;
import com.eucalyptus.system.Threads;
import com.eucalyptus.tags.FilterSupport;
import com.eucalyptus.util.Callback;
import com.eucalyptus.util.EucalyptusCloudException;
import com.eucalyptus.util.Exceptions;
Expand Down Expand Up @@ -302,4 +303,9 @@ public static List<Snapshot> list( ) throws TransactionException {
return Transactions.findAll( Snapshot.named( null, null ) );
}

public static class SnapshotFilterSupport extends FilterSupport<Snapshot> {
public SnapshotFilterSupport() {
super( builderFor( Snapshot.class ).withTagFiltering( SnapshotTag.class, "snapshot" ) );
}
}
}
Expand Up @@ -498,7 +498,7 @@ public Filter generate( final Map<String, Set<String>> filters,
final String accountId ) {
// Construct collection filter
final List<Predicate<Object>> and = Lists.newArrayList();
for ( final Map.Entry<String,Set<String>> filter : Iterables.filter( filters.entrySet(), tagPredicate() ) ) {
for ( final Map.Entry<String,Set<String>> filter : Iterables.filter( filters.entrySet(), Predicates.not( isTagFilter() ) ) ) {
final List<Predicate<Object>> or = Lists.newArrayList();
for ( final String value : filter.getValue() ) {
final Function<? super String,Predicate<? super RT>> predicateFunction = predicateFunctions.get( filter.getKey() );
Expand All @@ -513,7 +513,7 @@ public Filter generate( final Map<String, Set<String>> filters,
// Construct database filter and aliases
final Junction conjunction = Restrictions.conjunction();
final Map<String,String> aliases = Maps.newHashMap();
for ( final Map.Entry<String,Set<String>> filter : Iterables.filter( filters.entrySet(), tagPredicate() ) ) {
for ( final Map.Entry<String,Set<String>> filter : Iterables.filter( filters.entrySet(), Predicates.not( isTagFilter() ) ) ) {
final Junction disjunction = Restrictions.disjunction();
for ( final String value : filter.getValue() ) {
final PersistenceFilter persistenceFilter = persistenceFilters.get( filter.getKey() );
Expand All @@ -533,7 +533,7 @@ public Filter generate( final Map<String, Set<String>> filters,
// Construct database filter and aliases for tags
boolean tagPresent = false;
final Junction tagConjunction = Restrictions.conjunction();
for ( final Map.Entry<String,Set<String>> filter : Iterables.filter( filters.entrySet(), Predicates.not( tagPredicate() ) ) ) {
for ( final Map.Entry<String,Set<String>> filter : Iterables.filter( filters.entrySet(), isTagFilter() ) ) {
tagPresent = true;
final Junction disjunction = Restrictions.disjunction();
final String filterName = filter.getKey();
Expand Down Expand Up @@ -668,8 +668,8 @@ private boolean isTagFilteringEnabled() {
return tagFieldName != null;
}

private Predicate<Map.Entry<String,?>> tagPredicate() {
return isTagFilteringEnabled() ?
private Predicate<Map.Entry<String,?>> isTagFilter() {
return !isTagFilteringEnabled() ?
Predicates.<Map.Entry<String,?>>alwaysFalse() :
new Predicate<Map.Entry<String,?>>() {
@Override
Expand Down
@@ -0,0 +1,15 @@
package com.eucalyptus.blockstorage

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

/**
* Unit tests for snapshot filter support
*/
class SnapshotFilterSupportTest extends FilterSupportTest.InstanceTest<Snapshot> {

@Test
void testFilteringSupport() {
assertValid( new Snapshots.SnapshotFilterSupport() )
}
}

0 comments on commit 4687a78

Please sign in to comment.