Permalink
Browse files

use proper async messaging to update volume state

move commit on delete to the right place
actually apply volume attachment transactions
only send volume creation event on successfully submitting it to SC
fix to system/static mode network group lookup
tx functions for volume state additions to vm instance
  • Loading branch information...
grze committed Jan 9, 2012
2 parents b4e1f39 + 0440deb commit 8898c81f9464aa49915db3aeea013011853f4dae
@@ -83,6 +83,7 @@
import com.eucalyptus.entities.EntityWrapper;
import com.eucalyptus.records.Logs;
import com.eucalyptus.util.EucalyptusCloudException;
+import com.eucalyptus.util.async.AsyncRequests;
import com.eucalyptus.vm.VmInstance;
import com.eucalyptus.vm.VmInstances;
import com.eucalyptus.vm.VmVolumeAttachment;
@@ -109,20 +110,12 @@
}
ArrayList<edu.ucsb.eucalyptus.msgs.Volume> reply = Lists.newArrayList( );
for ( String partition : partitionVolumeMap.keySet( ) ) {
- try {
- Map<String, StorageVolume> idStorageVolumeMap = updateVolumesInPartition( partitionVolumeMap, partition );
- for ( Volume v : partitionVolumeMap.get( partition ) ) {
- try {
- reply.add( volumeStateTransform( idStorageVolumeMap, v ) );
- } catch ( Exception ex ) {
- Logs.extreme( ).error( ex );
- reply.add( v.morph( new edu.ucsb.eucalyptus.msgs.Volume( ) ) );
- }
- }
- } catch ( EucalyptusCloudException ex ) {
- LOG.error( ex );
- Logs.extreme( ).error( ex, ex );
- for ( Volume v : partitionVolumeMap.get( partition ) ) {
+ Map<String, StorageVolume> idStorageVolumeMap = updateVolumesInPartition( partitionVolumeMap, partition );
+ for ( Volume v : partitionVolumeMap.get( partition ) ) {
+ try {
+ reply.add( volumeStateTransform( idStorageVolumeMap, v ) );
+ } catch ( Exception ex ) {
+ Logs.extreme( ).error( ex );
reply.add( v.morph( new edu.ucsb.eucalyptus.msgs.Volume( ) ) );
}
}
@@ -178,7 +171,7 @@
return aVolume;
}
- private static Map<String, StorageVolume> updateVolumesInPartition( Multimap<String, Volume> partitionVolumeMap, String partition ) throws EucalyptusCloudException {
+ private static Map<String, StorageVolume> updateVolumesInPartition( Multimap<String, Volume> partitionVolumeMap, String partition ) {
Map<String, StorageVolume> idStorageVolumeMap = Maps.newHashMap( );
ServiceConfiguration scConfig = Topology.lookup( Storage.class, Partitions.lookupByName( partition ) );
Iterator<String> volumeNames = Iterators.transform( partitionVolumeMap.get( partition ).iterator( ), new Function<Volume, String>( ) {
@@ -188,10 +181,15 @@ public String apply( Volume arg0 ) {
}
} );
DescribeStorageVolumesType descVols = new DescribeStorageVolumesType( Lists.newArrayList( volumeNames ) );
- Dispatcher sc = ServiceDispatcher.lookup( scConfig );
- DescribeStorageVolumesResponseType volState = sc.send( descVols );
- for ( StorageVolume vol : volState.getVolumeSet( ) ) {
- idStorageVolumeMap.put( vol.getVolumeId( ), vol );
+ try {
+ DescribeStorageVolumesResponseType volState = AsyncRequests.sendSync( scConfig, descVols );
+ for ( StorageVolume vol : volState.getVolumeSet( ) ) {
+ LOG.debug( "Volume states: " + vol.getVolumeId( ) + " " + vol.getStatus( ) + " " + vol.getActualDeviceName( ) );
+ idStorageVolumeMap.put( vol.getVolumeId( ), vol );
+ }
+ } catch ( Exception ex ) {
+ LOG.error( ex );
+ Logs.extreme( ).error( ex, ex );
}
return idStorageVolumeMap;
}
@@ -385,12 +385,12 @@ public DetachVolumeResponseType detach( DetachVolumeType request ) throws Eucaly
EntityWrapper<Volume> db = EntityWrapper.get( Volume.class );
try {
vol = db.getUnique( Volume.named( ctx.getUserFullName( ).asAccountFullName( ), request.getVolumeId( ) ) );
+ db.commit( );
} catch ( EucalyptusCloudException e ) {
LOG.debug( e, e );
db.rollback( );
throw new EucalyptusCloudException( "Volume does not exist: " + request.getVolumeId( ) );
}
- db.commit( );
if ( !RestrictedTypes.filterPrivileged( ).apply( vol ) ) {
throw new EucalyptusCloudException( "Not authorized to detach volume " + request.getVolumeId( ) + " by " + ctx.getUser( ).getName( ) );
}
@@ -63,14 +63,11 @@
package com.eucalyptus.blockstorage;
-import java.util.HashMap;
import java.util.List;
-import java.util.NoSuchElementException;
import java.util.concurrent.ExecutionException;
import javax.persistence.EntityTransaction;
import org.apache.log4j.Logger;
import org.hibernate.criterion.Example;
-import org.hibernate.exception.ConstraintViolationException;
import com.eucalyptus.auth.principal.UserFullName;
import com.eucalyptus.cloud.CloudMetadata.VolumeMetadata;
import com.eucalyptus.component.Partitions;
@@ -80,7 +77,6 @@
import com.eucalyptus.crypto.Crypto;
import com.eucalyptus.entities.Entities;
import com.eucalyptus.entities.EntityWrapper;
-import com.eucalyptus.entities.TransactionException;
import com.eucalyptus.entities.Transactions;
import com.eucalyptus.event.ListenerRegistry;
import com.eucalyptus.reporting.event.StorageEvent;
@@ -94,8 +90,8 @@
import com.eucalyptus.ws.client.ServiceDispatcher;
import com.google.common.base.Function;
import com.google.common.collect.Lists;
-import edu.ucsb.eucalyptus.msgs.AttachedVolume;
import edu.ucsb.eucalyptus.msgs.BaseMessage;
+import edu.ucsb.eucalyptus.msgs.CreateStorageVolumeResponseType;
import edu.ucsb.eucalyptus.msgs.CreateStorageVolumeType;
import edu.ucsb.eucalyptus.msgs.DescribeStorageVolumesResponseType;
import edu.ucsb.eucalyptus.msgs.DescribeStorageVolumesType;
@@ -196,12 +192,18 @@ public static Volume createStorageVolume( final ServiceConfiguration sc, final U
public void fire( final Volume t ) {
t.setState( State.GENERATING );
try {
+ final CreateStorageVolumeType req = new CreateStorageVolumeType( t.getDisplayName( ), t.getSize( ), snapId, null ).regardingUserRequest( request );
+ final CreateStorageVolumeResponseType ret = AsyncRequests.sendSync( sc, req );
+ LOG.debug( "Volume created: CreateStorageVolumeResponse: " +
+ ret.getVolumeId( ) + " " +
+ ret.getStatus( ) + " " +
+ ret.getSize( ) + " " +
+ ret.getSnapshotId( ) + " " +
+ ret.getCreateTime( ) );
ListenerRegistry.getInstance( ).fireEvent( new StorageEvent( StorageEvent.EventType.EbsVolume, true, t.getSize( ),
t.getOwnerUserId( ), t.getOwnerUserName( ),
t.getOwnerAccountNumber( ), t.getOwnerAccountName( ),
t.getScName( ), t.getPartition( ) ) );
- final CreateStorageVolumeType req = new CreateStorageVolumeType( t.getDisplayName( ), t.getSize( ), snapId, null ).regardingUserRequest( request );
- AsyncRequests.sendSync( sc, req );
} catch ( final Exception ex ) {
LOG.error( "Failed to create volume: " + t.toString( ), ex );
throw Exceptions.toUndeclared( ex );
@@ -275,7 +275,7 @@ private void setupVmMessages( final ResourceToken token ) throws Exception {
final String networkName = NetworkGroups.networkingConfiguration( ).hasNetworking( )
? this.allocInfo.getPrimaryNetwork( ).getNaturalId( )
: NetworkGroups.lookup(
- this.allocInfo.getOwnerFullName( ),
+ this.allocInfo.getOwnerFullName( ).asAccountFullName( ),
NetworkGroups.defaultNetworkName( ) ).getNaturalId( );
final SshKeyPair keyInfo = this.allocInfo.getSshKeyPair( );
@@ -1353,48 +1353,44 @@ public VmVolumeAttachment lookupVolumeAttachment( final String volumeId ) {
/**
* @param attachVol
*/
- public void addTransientVolume( String deviceName, String remoteDevice, Volume vol ) {
- final EntityTransaction db = Entities.get( VmInstance.class );
- try {
- final VmInstance entity = Entities.merge( this );
- final Volume volEntity = Entities.merge( vol );
- VmVolumeAttachment attachVol = new VmVolumeAttachment( entity, vol.getDisplayName( ), deviceName, remoteDevice, AttachmentState.attaching.name( ), new Date( ), false );
- volEntity.setState( State.BUSY );
- entity.getTransientVolumeState( ).addVolumeAttachment( attachVol );
- db.commit( );
- } catch ( final RuntimeException ex ) {
- Logs.extreme( ).error( ex, ex );
- db.rollback( );
- throw ex;
- }
+ public void addTransientVolume( final String deviceName, final String remoteDevice, final Volume vol ) {
+ final Function<Volume, Volume> attachmentFunction = new Function<Volume, Volume>( ) {
+ public Volume apply( final Volume input ) {
+ final VmInstance entity = Entities.merge( VmInstance.this );
+ final Volume volEntity = Entities.merge( vol );
+ VmVolumeAttachment attachVol = new VmVolumeAttachment( entity, volEntity.getDisplayName( ), deviceName, remoteDevice, AttachmentState.attaching.name( ), new Date( ), false );
+ volEntity.setState( State.BUSY );
+ entity.getTransientVolumeState( ).addVolumeAttachment( attachVol );
+ return volEntity;
+ }
+ };
+ Entities.asTransaction( VmInstance.class, attachmentFunction, VmInstances.TX_RETRIES ).apply( vol );
}
public void addPersistentVolume( final String deviceName, final Volume vol ) {
- final EntityTransaction db = Entities.get( VmInstance.class );
- try {
- final VmInstance entity = Entities.merge( this );
- final VmVolumeAttachment volumeAttachment = new VmVolumeAttachment( entity, vol.getDisplayName( ), deviceName, vol.getRemoteDevice( ), AttachmentState.attached.name( ), new Date( ), true );
- entity.bootRecord.getPersistentVolumes( ).add( volumeAttachment );
- db.commit( );
- } catch ( final RuntimeException ex ) {
- Logs.extreme( ).error( ex, ex );
- db.rollback( );
- throw ex;
- }
+ final Function<Volume, Volume> attachmentFunction = new Function<Volume, Volume>( ) {
+ public Volume apply( final Volume input ) {
+ final VmInstance entity = Entities.merge( VmInstance.this );
+ final Volume volEntity = Entities.merge( vol );
+ final VmVolumeAttachment volumeAttachment = new VmVolumeAttachment( entity, vol.getDisplayName( ), deviceName, vol.getRemoteDevice( ), AttachmentState.attached.name( ), new Date( ), true );
+ entity.bootRecord.getPersistentVolumes( ).add( volumeAttachment );
+ return volEntity;
+ }
+ };
+ Entities.asTransaction( VmInstance.class, attachmentFunction, VmInstances.TX_RETRIES ).apply( vol );
}
public void addPermanentVolume( final String deviceName, final Volume vol ) {
- final EntityTransaction db = Entities.get( VmInstance.class );
- try {
- final VmInstance entity = Entities.merge( this );
- final VmVolumeAttachment volumeAttachment = new VmVolumeAttachment( entity, vol.getDisplayName( ), deviceName, vol.getRemoteDevice( ), AttachmentState.attached.name( ), new Date( ), false );
- entity.bootRecord.getPersistentVolumes( ).add( volumeAttachment );
- db.commit( );
- } catch ( final RuntimeException ex ) {
- Logs.extreme( ).error( ex, ex );
- db.rollback( );
- throw ex;
- }
+ final Function<Volume, Volume> attachmentFunction = new Function<Volume, Volume>( ) {
+ public Volume apply( final Volume input ) {
+ final VmInstance entity = Entities.merge( VmInstance.this );
+ final Volume volEntity = Entities.merge( vol );
+ final VmVolumeAttachment volumeAttachment = new VmVolumeAttachment( entity, vol.getDisplayName( ), deviceName, vol.getRemoteDevice( ), AttachmentState.attached.name( ), new Date( ), false );
+ entity.bootRecord.getPersistentVolumes( ).add( volumeAttachment );
+ return volEntity;
+ }
+ };
+ Entities.asTransaction( VmInstance.class, attachmentFunction, VmInstances.TX_RETRIES ).apply( vol );
}
/**
@@ -318,7 +318,7 @@ public static VmVolumeAttachment lookupVolumeAttachment( final String volumeId )
db.commit( );
return ret;
} catch ( Exception ex ) {
- Logs.exhaust( ).error( ex, ex );
+ Logs.extreme( ).error( ex, ex );
db.rollback( );
throw new NoSuchElementException( ex.getMessage( ) );
}

0 comments on commit 8898c81

Please sign in to comment.