Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Browse files

Changes EBS attachments to be initiated from NC instead of CLC. Fixes…

… EUCA-5179.

Changes EBS message flow signifcantly and adds a new required network path from each
NC to the SCs in the cluster regardless of which backend the SC is using.

Prior to this commit the CLC would call attachVolume() on the SC an pass it the
list of IQNs for each NC in the cluster for BfEBS instances or the single specific
NCs IQN for EBS volume attachments. The SC returned the connection string and the
CLC would pass it down to the NC(s) via the CC.

This commit adds the concept of an attachment token to the EBS architecture. A single
EBS attachment (for BfEBS or regular EBS) has an associated token that is requested by
the CLC prior to the call to the NC to do the attachment. That token is opaque and sent
to any/all NCs involved in the attachment. Each NC then calls the ExportVolume() operation
on the SC to resolve the token and get a host-specific connection string used to connect
the EBS volume to the NC host.

This commit adds:
1. New SOAP interface for SC to NC using a new XML namespace: storagecontroller.eucalyptus.com
2. ExportVolume/UnexportVolume operations to be invoked by the NC on the SC
3. GetVolumeToken operation invoked by the CLC on the SC to get a new token for a volume attachment
4. A C client to make calls to the SC from the NC. And the associated eucalyptus_sc.wsdl
5. New VolumeToken and VolumeExportRecord entities in eucalyptus_storage db to persist tokens and exports
6. Refactoring of ebs volume operations in the NC into the single ebs_utils.c/h module to isolate ebs ops
  • Loading branch information...
commit 431e43094de0275ecd0393d66c8911e3d4d832df 1 parent 67a1e4d
@zhill zhill authored
Showing with 4,241 additions and 445 deletions.
  1. +2 −0  .gitignore
  2. +62 −12 clc/modules/cluster-manager/src/main/java/com/eucalyptus/blockstorage/VolumeManager.java
  3. +93 −71 clc/modules/cluster-manager/src/main/java/com/eucalyptus/cloud/run/ClusterAllocator.java
  4. +1 −0  clc/modules/cluster-manager/src/main/java/com/eucalyptus/vm/VmInstances.java
  5. +34 −0 clc/modules/core/src/main/java/com/eucalyptus/util/BlockStorageUtil.java
  6. +1 −1  clc/modules/core/src/main/java/com/eucalyptus/util/StorageProperties.java
  7. +195 −0 clc/modules/core/src/main/java/edu/ucsb/eucalyptus/cloud/entities/VolumeExportRecord.java
  8. +171 −0 clc/modules/core/src/main/java/edu/ucsb/eucalyptus/cloud/entities/VolumeToken.java
  9. +2 −2 clc/modules/msgs/src/main/java/com/eucalyptus/auth/principal/Principals.java
  10. +140 −0 clc/modules/msgs/src/main/java/com/eucalyptus/ws/handlers/NodeWsSecHandler.java
  11. +51 −11 clc/modules/msgs/src/main/java/edu/ucsb/eucalyptus/msgs/StorageController.groovy
  12. +21 −61 clc/modules/msgs/src/main/resources/storage-controller-binding.xml
  13. +318 −0 clc/modules/storage-controller/src/main/java/com/eucalyptus/storage/VolumeExports.java
  14. +103 −0 clc/modules/storage-controller/src/main/java/com/eucalyptus/storage/VolumeTokenService.java
  15. +142 −2 clc/modules/storage-controller/src/main/java/edu/ucsb/eucalyptus/cloud/ws/BlockStorage.java
  16. +1 −0  clc/modules/wsstack/src/main/java/com/eucalyptus/ws/client/pipeline/ClusterClientPipelineFactory.java
  17. +104 −0 clc/modules/wsstack/src/main/java/com/eucalyptus/ws/server/ExternalStorageControllerSoapPipeline.java
  18. +24 −0 clc/modules/wsstack/src/main/java/com/eucalyptus/ws/stages/ExternalSCAuthenticationStage.java
  19. +1 −1  cluster/Makefile
  20. +100 −36 cluster/handlers.c
  21. +3 −0  cluster/handlers.h
  22. +7 −7 cluster/server-marshal.c
  23. +1 −1  configure
  24. +1 −1  configure.ac
  25. +21 −7 node/Makefile
  26. +1 −1  node/NCclient.c
  27. +214 −15 node/handlers.c
  28. +21 −4 node/handlers.h
  29. +112 −70 node/handlers_default.c
  30. +37 −25 node/handlers_kvm.c
  31. +14 −14 node/test.c
  32. +0 −1  project/cluster
  33. +1 −0  project/cluster
  34. +0 −1  project/devel
  35. +1 −0  project/devel
  36. +0 −1  project/gatherlog
  37. +1 −0  project/gatherlog
  38. +0 −1  project/net
  39. +1 −0  project/net
  40. +0 −1  project/node
  41. +1 −0  project/node
  42. +1 −0  project/sc
  43. +0 −1  project/storage
  44. +1 −0  project/storage
  45. +0 −1  project/tools
  46. +1 −0  project/tools
  47. +0 −1  project/util
  48. +1 −0  project/util
  49. +0 −1  project/wsdl
  50. +1 −0  project/wsdl
  51. +56 −10 storage/Makefile
  52. +335 −0 storage/SCclient.c
  53. +12 −5 storage/backing.c
  54. +378 −0 storage/ebs_utils.c
  55. +52 −0 storage/ebs_utils.h
  56. +8 −3 storage/iscsi.c
  57. +1 −1  storage/iscsi.h
  58. +383 −0 storage/sc-client-marshal-adb.c
  59. +149 −0 storage/sc-client-marshal.h
  60. +285 −0 storage/storage-controller.c
  61. +10 −0 storage/storage-controller.h
  62. +88 −48 storage/vbr.c
  63. +14 −0 storage/vbr.h
  64. +12 −4 tools/disconnect_iscsitarget_main.pl
  65. +3 −0  tools/get_iscsitarget.pl
  66. +6 −0 tools/iscsitarget_common.pl
  67. +2 −3 util/adb-helpers.h
  68. +201 −0 util/adb-service-helpers.h
  69. +10 −5 util/data.c
  70. +25 −15 util/data.h
  71. +1 −0  util/eucalyptus.h
  72. +202 −0 wsdl/eucalyptus_sc.wsdl
View
2  .gitignore
@@ -61,6 +61,7 @@ gatherlog/libEucalyptusGL.so
Makedefs
storage/euca_imager
storage/Wclient
+storage/SCclient
tools/euca_conf
tools/eucalyptus-cc
tools/eucalyptus-cloud
@@ -78,6 +79,7 @@ clc/eucadmin/eucadmin/__init__.py
storage/euca-blobs
storage/test_blobstore
storage/test_vbr
+storage/test_ebs
TAGS
cluster/CCclient_full
cluster/cc-client-policy.xml
View
74 clc/modules/cluster-manager/src/main/java/com/eucalyptus/blockstorage/VolumeManager.java
@@ -91,7 +91,6 @@
import com.eucalyptus.entities.Entities;
import com.eucalyptus.entities.TransactionException;
import com.eucalyptus.entities.Transactions;
-import com.eucalyptus.node.Nodes;
import com.eucalyptus.records.EventClass;
import com.eucalyptus.records.EventRecord;
import com.eucalyptus.records.EventType;
@@ -105,20 +104,19 @@
import com.eucalyptus.util.EucalyptusCloudException;
import com.eucalyptus.util.Exceptions;
import com.eucalyptus.util.RestrictedTypes;
+import com.eucalyptus.util.StorageProperties;
import com.eucalyptus.util.async.AsyncRequests;
import com.eucalyptus.vm.MigrationState;
import com.eucalyptus.vm.VmInstance;
import com.eucalyptus.vm.VmInstance.VmState;
import com.eucalyptus.vm.VmInstances;
import com.eucalyptus.vm.VmVolumeAttachment;
+import com.eucalyptus.vm.VmVolumeAttachment.AttachmentState;
import com.google.common.base.Function;
import com.google.common.base.Predicate;
import com.google.common.collect.Iterables;
import com.google.common.collect.Sets;
import com.google.common.primitives.Ints;
-
-import edu.ucsb.eucalyptus.msgs.AttachStorageVolumeResponseType;
-import edu.ucsb.eucalyptus.msgs.AttachStorageVolumeType;
import edu.ucsb.eucalyptus.msgs.AttachVolumeResponseType;
import edu.ucsb.eucalyptus.msgs.AttachVolumeType;
import edu.ucsb.eucalyptus.msgs.AttachedVolume;
@@ -133,10 +131,15 @@
import edu.ucsb.eucalyptus.msgs.DetachStorageVolumeType;
import edu.ucsb.eucalyptus.msgs.DetachVolumeResponseType;
import edu.ucsb.eucalyptus.msgs.DetachVolumeType;
+import edu.ucsb.eucalyptus.msgs.ExportVolumeResponseType;
+import edu.ucsb.eucalyptus.msgs.ExportVolumeType;
+import edu.ucsb.eucalyptus.msgs.GetVolumeTokenResponseType;
+import edu.ucsb.eucalyptus.msgs.GetVolumeTokenType;
import edu.ucsb.eucalyptus.msgs.ResourceTag;
public class VolumeManager {
private static final int VOL_CREATE_RETRIES = 10;
+
private static Logger LOG = Logger.getLogger( VolumeManager.class );
public CreateVolumeResponseType CreateVolume( final CreateVolumeType request ) throws EucalyptusCloudException, AuthException {
@@ -356,6 +359,43 @@ public Volume apply( String input ) {
return reply;
}
+ /* TODO: zhill DEVELOPMENT AND DEBUG ONLY! REMOVE!!! */
+ public String TestVolumeToken(String volumeId, String partition) throws EucalyptusCloudException {
+ Partition volPartition = Partitions.lookupByName( partition );
+ ServiceConfiguration sc = Topology.lookup( Storage.class, volPartition );
+
+ GetVolumeTokenResponseType scTokenResponse;
+ try {
+ GetVolumeTokenType req = new GetVolumeTokenType(volumeId);
+ scTokenResponse = AsyncRequests.sendSync( sc, req );
+ } catch ( Exception e ) {
+ LOG.debug( e, e );
+ throw new EucalyptusCloudException( e.getMessage( ), e );
+ }
+ return scTokenResponse.getToken();
+ }
+
+ /* TODO: zhill DEVELOPMENT AND DEBUG ONLY! REMOVE!!! */
+ public String TestExportVolume(String partition, String volumeId, String token, String hostIP, String hostIqn) throws EucalyptusCloudException {
+ Partition volPartition = Partitions.lookupByName( partition );
+ ServiceConfiguration sc = Topology.lookup( Storage.class, volPartition );
+
+ ExportVolumeResponseType scTokenResponse = null;
+ try {
+ ExportVolumeType req = new ExportVolumeType();
+ req.setToken(token);
+ req.setVolumeId(volumeId);
+ req.setIp(hostIP);
+ req.setIqn(hostIqn);
+ scTokenResponse = AsyncRequests.sendSync( sc, req );
+ } catch ( Exception e ) {
+ LOG.debug( e, e );
+ throw new EucalyptusCloudException( e.getMessage( ), e );
+ }
+ return scTokenResponse.getConnectionString();
+ }
+
+
public AttachVolumeResponseType AttachVolume( AttachVolumeType request ) throws EucalyptusCloudException {
AttachVolumeResponseType reply = ( AttachVolumeResponseType ) request.getReply( );
final String deviceName = request.getDevice( );
@@ -407,18 +447,22 @@ public AttachVolumeResponseType AttachVolume( AttachVolumeType request ) throws
throw new EucalyptusCloudException( "Can only attach volumes in the same zone: " + request.getVolumeId( ) );
}
ServiceConfiguration ccConfig = Topology.lookup( ClusterController.class, vm.lookupPartition( ) );
- AttachStorageVolumeResponseType scAttachResponse;
+ GetVolumeTokenResponseType scGetTokenResponse;
try {
- AttachStorageVolumeType req = new AttachStorageVolumeType( Nodes.lookupIqn( vm ), volume.getDisplayName( ) );
- scAttachResponse = AsyncRequests.sendSync( sc, req );
+ GetVolumeTokenType req = new GetVolumeTokenType(volume.getDisplayName());
+ scGetTokenResponse = AsyncRequests.sendSync(sc, req);
} catch ( Exception e ) {
LOG.debug( e, e );
throw new EucalyptusCloudException( e.getMessage( ), e );
}
- request.setRemoteDevice( scAttachResponse.getRemoteDeviceString( ) );
+
+ //TODO: zhill, this is a messaging change. The SC should not know the format, so the CLC must construct the special format
+ String token = StorageProperties.TOKEN_PREFIX + scGetTokenResponse.getVolumeId() + "," + scGetTokenResponse.getToken();
+
+ request.setRemoteDevice(token);
AttachedVolume attachVol = new AttachedVolume( volume.getDisplayName( ), vm.getInstanceId( ), request.getDevice( ), request.getRemoteDevice( ) );
- vm.addTransientVolume( deviceName, scAttachResponse.getRemoteDeviceString( ), volume );
+ vm.addTransientVolume( deviceName, token, volume );
AsyncRequests.newRequest( new VolumeAttachCallback( request ) ).dispatch( ccConfig );
EventRecord.here( VolumeManager.class, EventClass.VOLUME, EventType.VOLUME_ATTACH )
@@ -479,6 +523,7 @@ public DetachVolumeResponseType detach( DetachVolumeType request ) throws Eucaly
throw new EucalyptusCloudException( "Failed to lookup SC for partition: " + vm.getPartition( ), ex );
}
if ( VmState.STOPPED.equals( vm.getState( ) ) ) {
+ //Ensure that the volume is not attached
try {
AsyncRequests.sendSync( scVm, new DetachStorageVolumeType( volume.getVolumeId( ) ) );
} catch ( Exception e ) {
@@ -502,16 +547,21 @@ public DetachVolumeResponseType detach( DetachVolumeType request ) throws Eucaly
request.setDevice( volume.getDevice( ).replaceAll( "unknown,requested:", "" ) );
request.setInstanceId( vm.getInstanceId( ) );
VolumeDetachCallback ncDetach = new VolumeDetachCallback( request );
- try {
+ /* No SC action required, send directly to NC
+ * try {
AsyncRequests.sendSync( scVm, new DetachStorageVolumeType( volume.getVolumeId( ) ) );
} catch ( Exception e ) {
LOG.debug( e );
Logs.extreme( ).debug( e, e );
//GRZE: attach is idempotent, failure here is ok, throw new EucalyptusCloudException( e.getMessage( ) );
- }
+ }*/
AsyncRequests.newRequest( ncDetach ).dispatch( cluster.getConfiguration( ) );
}
- volume.setStatus( "detaching" );
+
+ //Update the state of the attachment to 'detaching'
+ vm.updateVolumeAttachment(request.getVolumeId(), AttachmentState.detaching);
+
+ volume.setStatus( "detaching" );
reply.setDetachedVolume( volume );
Volumes.fireUsageEvent(vol, VolumeEvent.forVolumeDetach(vm.getInstanceUuid(), vm.getInstanceId()));
return reply;
View
164 clc/modules/cluster-manager/src/main/java/com/eucalyptus/cloud/run/ClusterAllocator.java
@@ -97,7 +97,6 @@
import com.eucalyptus.keys.SshKeyPair;
import com.eucalyptus.network.NetworkGroup;
import com.eucalyptus.network.NetworkGroups;
-import com.eucalyptus.node.Nodes;
import com.eucalyptus.records.EventRecord;
import com.eucalyptus.records.EventType;
import com.eucalyptus.records.Logs;
@@ -120,16 +119,18 @@
import edu.ucsb.eucalyptus.cloud.VirtualBootRecord;
import edu.ucsb.eucalyptus.cloud.VmKeyInfo;
import edu.ucsb.eucalyptus.cloud.VmRunResponseType;
-import edu.ucsb.eucalyptus.msgs.AttachStorageVolumeResponseType;
-import edu.ucsb.eucalyptus.msgs.AttachStorageVolumeType;
import edu.ucsb.eucalyptus.msgs.BlockDeviceMappingItemType;
import edu.ucsb.eucalyptus.msgs.DescribeStorageVolumesResponseType;
import edu.ucsb.eucalyptus.msgs.DescribeStorageVolumesType;
+import edu.ucsb.eucalyptus.msgs.GetVolumeTokenResponseType;
+import edu.ucsb.eucalyptus.msgs.GetVolumeTokenType;
import edu.ucsb.eucalyptus.msgs.StorageVolume;
import edu.ucsb.eucalyptus.msgs.VmTypeInfo;
public class ClusterAllocator implements Runnable {
private static final long BYTES_PER_GB = ( 1024L * 1024L * 1024L );
+ private static final String VOLUME_TOKEN_PREFIX = "sc://"; //Used for designating EBS volumes in the VBR
+
private static Logger LOG = Logger.getLogger( ClusterAllocator.class );
enum State {
@@ -354,74 +355,95 @@ private void setupVmMessages( final ResourceToken token ) throws Exception {
private VmTypeInfo makeVmTypeInfo( final VmTypeInfo vmInfo, final ResourceToken token ) throws Exception {
VmTypeInfo childVmInfo = vmInfo.child( );
- if ( this.allocInfo.getBootSet( ).getMachine( ) instanceof BlockStorageImageInfo ) {
-
- String instanceId = token.getInstanceId();
-
- // Deal with the root volume first
- VirtualBootRecord rootVbr = childVmInfo.lookupRoot();
- Volume rootVolume = token.getRootVolume();
-
- // Wait for root volume
- LOG.debug("Wait for root ebs volume " + rootVolume.getDisplayName() + " to become available");
- final ServiceConfiguration scConfig = waitForVolume(rootVolume);
-
- // Attach root volume
- try {
- LOG.debug("About to attach volume " + rootVolume.getDisplayName() + " to instance " + instanceId);
- AttachStorageVolumeType attachMsg = new AttachStorageVolumeType(Nodes.lookupIqns(this.cluster.getConfiguration()), rootVolume.getDisplayName());
- final AttachStorageVolumeResponseType scAttachResponse = AsyncRequests.sendSync(scConfig, attachMsg);
- LOG.debug("Attach response from SC for volume " + rootVolume.getDisplayName() + " and instance " + instanceId + "\n" + scAttachResponse);
- String remoteDeviceString = scAttachResponse.getRemoteDeviceString();
- if (remoteDeviceString == null) {
- throw new EucalyptusCloudException("Failed to get remote device string for root volume " + rootVolume.getDisplayName() + " while running instance " + instanceId);
- } else {
- rootVbr.setResourceLocation(remoteDeviceString);
- rootVbr.setSize(rootVolume.getSize() * BYTES_PER_GB);
- //vm.updatePersistantVolume(remoteDeviceString, rootVolume); Skipping this step for now as no one seems to be using it
- }
- } catch (final Exception ex) {
- LOG.error(ex);
- Logs.extreme().error(ex, ex);
- throw ex;
- }
-
- // Deal with the remaining ebs volumes
- for (Entry<String, Volume> mapping : token.getEbsVolumes().entrySet()) {
- Volume volume = mapping.getValue();
- if (volume.getSize() <= 0) {
- volume = Volumes.lookup(this.allocInfo.getOwnerFullName(), mapping.getValue().getDisplayName());
- }
- String volumeId = volume.getDisplayName();
-
- LOG.debug("Wait for volume " + volumeId + " to become available");
- final ServiceConfiguration scConfigLocal = waitForVolume(volume);
-
- try {
- LOG.debug("About to attach volume " + volume.getDisplayName() + " to instance " + instanceId);
- AttachStorageVolumeType attachMsg = new AttachStorageVolumeType(Nodes.lookupIqns(this.cluster.getConfiguration()), volumeId);
- final AttachStorageVolumeResponseType scAttachResponse = AsyncRequests.sendSync(scConfigLocal, attachMsg);
- LOG.debug("Attach response from SC for volume " + volumeId + " and instance " + instanceId + scAttachResponse);
- String remoteDeviceString = scAttachResponse.getRemoteDeviceString();
- if (remoteDeviceString == null) {
- throw new EucalyptusCloudException("Failed to get remote device string for root volume " + volumeId + " while running instance " + instanceId);
- } else {
- VirtualBootRecord vbr = new VirtualBootRecord(volumeId, remoteDeviceString, "ebs", mapping.getKey(), (volume.getSize() * BYTES_PER_GB), "none");
- childVmInfo.getVirtualBootRecord().add(vbr);
- //vm.updatePersistantVolume(remoteDeviceString, volume); Skipping this step for now as no one seems to be using it
- }
- } catch (final Exception ex) {
- LOG.error(ex);
- Logs.extreme().error(ex, ex);
- throw ex;
- }
- }
-
- for( String deviceName : token.getEphemeralDisks().keySet() ) {
- childVmInfo.setEphemeral( 0, deviceName, (this.allocInfo.getVmType().getDisk( ) * BYTES_PER_GB), "none" );
- }
-
- LOG.debug("Instance information: " + childVmInfo.dump());
+ if ( this.allocInfo.getBootSet( ).getMachine( ) instanceof BlockStorageImageInfo ) {
+ String instanceId = token.getInstanceId();
+
+ // Deal with the root volume first
+ VirtualBootRecord rootVbr = childVmInfo.lookupRoot();
+ Volume rootVolume = token.getRootVolume();
+ String volumeId = rootVolume.getDisplayName( );
+ String volumeToken = null;
+
+ // Wait for root volume
+ LOG.debug("Wait for root ebs volume " + rootVolume.getDisplayName() + " to become available");
+ final ServiceConfiguration scConfig = waitForVolume(rootVolume);
+
+ // Attach root volume
+ try {
+ LOG.debug("About to get attachment token for volume " + rootVolume.getDisplayName() + " to instance " + instanceId);
+ GetVolumeTokenResponseType scGetTokenResponse;
+ try {
+ GetVolumeTokenType req = new GetVolumeTokenType(volumeId);
+ scGetTokenResponse = AsyncRequests.sendSync(scConfig, req);
+ } catch ( Exception e ) {
+ LOG.debug( e, e );
+ throw new EucalyptusCloudException( e.getMessage( ), e );
+ }
+ LOG.debug("Got volume token response from SC for volume " + rootVolume.getDisplayName() + " and instance " + instanceId + "\n" + scGetTokenResponse);
+ volumeToken = scGetTokenResponse.getToken();
+ if ( volumeToken == null ) {
+ throw new EucalyptusCloudException( "Failed to get remote device string for " + volumeId + " while running instance " + token.getInstanceId( ) );
+ } else {
+ //Do formatting here since formatting is for messaging only.
+ //sc://vol-X,<token>
+ volumeToken = VOLUME_TOKEN_PREFIX + volumeId + "," + volumeToken;
+ rootVbr.setResourceLocation(volumeToken);
+ rootVbr.setSize(rootVolume.getSize() * BYTES_PER_GB);
+ //vm.updatePersistantVolume(remoteDeviceString, rootVolume); Skipping this step for now as no one seems to be using it
+ }
+ } catch (final Exception ex) {
+ LOG.error(ex);
+ Logs.extreme().error(ex, ex);
+ throw ex;
+ }
+
+ // Deal with the remaining ebs volumes
+ for (Entry<String, Volume> mapping : token.getEbsVolumes().entrySet()) {
+ Volume volume = mapping.getValue();
+ if (volume.getSize() <= 0) {
+ volume = Volumes.lookup(this.allocInfo.getOwnerFullName(), mapping.getValue().getDisplayName());
+ }
+ volumeId = volume.getDisplayName();
+
+ LOG.debug("Wait for volume " + volumeId + " to become available");
+ final ServiceConfiguration scConfigLocal = waitForVolume(volume);
+
+ // Attach root volume
+ try {
+ LOG.debug("About to get attachment token for volume " + rootVolume.getDisplayName() + " to instance " + instanceId);
+ GetVolumeTokenResponseType scGetTokenResponse;
+ try {
+ GetVolumeTokenType req = new GetVolumeTokenType(volumeId);
+ scGetTokenResponse = AsyncRequests.sendSync(scConfig, req);
+ } catch ( Exception e ) {
+ LOG.debug( e, e );
+ throw new EucalyptusCloudException( e.getMessage( ), e );
+ }
+
+ LOG.debug("Got volume token response from SC for volume " + rootVolume.getDisplayName() + " and instance " + instanceId + "\n" + scGetTokenResponse);
+ volumeToken = scGetTokenResponse.getToken();
+ if ( volumeToken == null ) {
+ throw new EucalyptusCloudException( "Failed to get remote device string for " + volumeId + " while running instance " + token.getInstanceId( ) );
+ } else {
+ //Do formatting here since formatting is for messaging only.
+ //sc://vol-X,<token>
+ volumeToken = VOLUME_TOKEN_PREFIX + volumeId + "," + volumeToken;
+ VirtualBootRecord vbr = new VirtualBootRecord(volumeId, volumeToken, "ebs", mapping.getKey(), (volume.getSize() * BYTES_PER_GB), "none");
+ childVmInfo.getVirtualBootRecord().add(vbr);
+ //vm.updatePersistantVolume(remoteDeviceString, volume); Skipping this step for now as no one seems to be using it
+ }
+ } catch (final Exception ex) {
+ LOG.error(ex);
+ Logs.extreme().error(ex, ex);
+ throw ex;
+ }
+ }
+
+ for( String deviceName : token.getEphemeralDisks().keySet() ) {
+ childVmInfo.setEphemeral( 0, deviceName, (this.allocInfo.getVmType().getDisk( ) * BYTES_PER_GB), "none" );
+ }
+
+ LOG.debug("Instance information: " + childVmInfo.dump());
}
return childVmInfo;
}
View
1  clc/modules/cluster-manager/src/main/java/com/eucalyptus/vm/VmInstances.java
@@ -545,6 +545,7 @@ public boolean apply( final VmVolumeAttachment arg0 ) {
}
try {
+ //TODO: zhill - still send a cleanup to SC to guarantee cleanup?
final ServiceConfiguration sc = Topology.lookup( Storage.class, vm.lookupPartition( ) );
AsyncRequests.sendSync( sc, new DetachStorageVolumeType( arg0.getVolumeId( ) ) );
} catch ( Exception ex ) {
View
34 clc/modules/core/src/main/java/com/eucalyptus/util/BlockStorageUtil.java
@@ -76,6 +76,7 @@
import com.eucalyptus.component.ServiceConfigurations;
import com.eucalyptus.component.auth.SystemCredentials;
import com.eucalyptus.component.id.ClusterController;
+import com.eucalyptus.component.id.Eucalyptus;
import com.eucalyptus.component.id.Storage;
import com.eucalyptus.crypto.Ciphers;
@@ -125,4 +126,37 @@ public static String decryptSCTargetPassword(String encryptedPassword) throws Eu
throw new EucalyptusCloudException("Unable to decrypt storage target password", ex);
}
}
+
+ //Encrypt data using the node public key
+ public static String encryptForNode(String data) throws EucalyptusCloudException {
+ try {
+ List<ServiceConfiguration> clusterList = ServiceConfigurations.listPartition( ClusterController.class, StorageProperties.NAME );
+ if( clusterList.size() < 1 ) {
+ String msg = "Failed to find a cluster with the corresponding partition name for this SC: " + StorageProperties.NAME + "\nFound: " + clusterList.toString( ).replaceAll( ", ", ",\n" );
+ throw new EucalyptusCloudException(msg);
+ } else {
+ ServiceConfiguration clusterConfig = clusterList.get( 0 );
+ PublicKey ncPublicKey = Partitions.lookup( clusterConfig ).getNodeCertificate( ).getPublicKey();
+ Cipher cipher = Ciphers.RSA_PKCS1.get();
+ cipher.init(Cipher.ENCRYPT_MODE, ncPublicKey);
+ return new String(Base64.encode(cipher.doFinal(data.getBytes())));
+ }
+ } catch ( Exception e ) {
+ LOG.error( "Unable to encrypt storage target password: " + e.getMessage( ), e );
+ throw new EucalyptusCloudException("Unable to encrypt storage target password: " + e.getMessage(), e);
+ }
+ }
+
+ //Decrypt data encrypted with the Cloud public key
+ public static String decryptWithCloud(String data) throws EucalyptusCloudException {
+ PrivateKey scPrivateKey = SystemCredentials.lookup(Eucalyptus.class).getPrivateKey();
+ try {
+ Cipher cipher = Ciphers.RSA_PKCS1.get();
+ cipher.init(Cipher.DECRYPT_MODE, scPrivateKey);
+ return new String(cipher.doFinal(Base64.decode(data)));
+ } catch(Exception ex) {
+ LOG.error(ex);
+ throw new EucalyptusCloudException("Unable to decrypt storage target password", ex);
+ }
+ }
}
View
2  clc/modules/core/src/main/java/com/eucalyptus/util/StorageProperties.java
@@ -114,7 +114,7 @@
public static String DAS_DEVICE = "/dev/blockdev";
public static final String STORAGE_CLASS_PREFIX = "com.eucalyptus.storage.";
public static final long SNAP_POINT_MAX_TIME_MS = 15000; //15 sec turnaround
-
+ public static final String TOKEN_PREFIX = "sc://"; //Used to indicate a token should be resolved to an SC. The holder shoul replace 'sc://' with the service url for the enabled SC
public static final String COMMON_IQN = "ALL";
static { Groovyness.loadConfig("storageprops.groovy"); }
View
195 clc/modules/core/src/main/java/edu/ucsb/eucalyptus/cloud/entities/VolumeExportRecord.java
@@ -0,0 +1,195 @@
+/*************************************************************************
+ * Copyright 2009-2012 Eucalyptus Systems, Inc.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 3 of the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see http://www.gnu.org/licenses/.
+ *
+ * Please contact Eucalyptus Systems, Inc., 6755 Hollister Ave., Goleta
+ * CA 93117, USA or visit http://www.eucalyptus.com/licenses/ if you need
+ * additional information or have any questions.
+ *
+ * This file may incorporate work covered under the following copyright
+ * and permission notice:
+ *
+ * Software License Agreement (BSD License)
+ *
+ * Copyright (c) 2008, Regents of the University of California
+ * All rights reserved.
+ *
+ * Redistribution and use of this software in source and binary forms,
+ * with or without modification, are permitted provided that the
+ * following conditions are met:
+ *
+ * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+ * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE. USERS OF THIS SOFTWARE ACKNOWLEDGE
+ * THE POSSIBLE PRESENCE OF OTHER OPEN SOURCE LICENSED MATERIAL,
+ * COPYRIGHTED MATERIAL OR PATENTED MATERIAL IN THIS SOFTWARE,
+ * AND IF ANY SUCH MATERIAL IS DISCOVERED THE PARTY DISCOVERING
+ * IT MAY INFORM DR. RICH WOLSKI AT THE UNIVERSITY OF CALIFORNIA,
+ * SANTA BARBARA WHO WILL THEN ASCERTAIN THE MOST APPROPRIATE REMEDY,
+ * WHICH IN THE REGENTS' DISCRETION MAY INCLUDE, WITHOUT LIMITATION,
+ * REPLACEMENT OF THE CODE SO IDENTIFIED, LICENSING OF THE CODE SO
+ * IDENTIFIED, OR WITHDRAWAL OF THE CODE CAPABILITY TO THE EXTENT
+ * NEEDED TO COMPLY WITH ANY SUCH LICENSES OR RIGHTS.
+ ************************************************************************/
+
+package edu.ucsb.eucalyptus.cloud.entities;
+
+import javax.persistence.Column;
+import javax.persistence.DiscriminatorValue;
+import javax.persistence.Embeddable;
+import javax.persistence.FetchType;
+import javax.persistence.JoinColumn;
+import javax.persistence.ManyToOne;
+import javax.persistence.PersistenceContext;
+import javax.persistence.Table;
+
+import org.hibernate.annotations.Cache;
+import org.hibernate.annotations.CacheConcurrencyStrategy;
+import org.hibernate.annotations.Entity;
+import org.hibernate.annotations.Parent;
+
+import com.eucalyptus.entities.AbstractPersistent;
+
+/*@Entity @javax.persistence.Entity
+@PersistenceContext(name="eucalyptus_storage")
+@Table( name = "volume_exports")
+@Cache( usage = CacheConcurrencyStrategy.TRANSACTIONAL )*/
+
+@Entity
+@javax.persistence.Entity
+@PersistenceContext(name="eucalyptus_storage")
+@Table( name = "volume_exports" )
+@Cache( usage = CacheConcurrencyStrategy.TRANSACTIONAL )
+@DiscriminatorValue( "token" )
+public class VolumeExportRecord extends AbstractPersistent {
+ private static final long serialVersionUID = 1L;
+
+ @JoinColumn( name = "token", updatable = false, nullable = false )
+ @ManyToOne( fetch = FetchType.LAZY )
+ private VolumeToken token;
+
+ @Column(name="host_ip")
+ private String hostIp;
+
+ @Column(name="host_iqn")
+ private String hostIqn;
+
+ @Column(name="is_active")
+ private Boolean isActive;
+
+ @Column(name="volumeId")
+ private String volumeId;
+
+ public String getVolumeId() {
+ return volumeId;
+ }
+
+ public void setVolumeId(String volumeId) {
+ this.volumeId = volumeId;
+ }
+
+ public VolumeExportRecord() {
+ token = null;
+ hostIp = null;
+ hostIqn = null;
+ }
+
+ public VolumeExportRecord(String volumeId, VolumeToken tok, String ip, String iqn) {
+ this.volumeId = volumeId;
+ this.token = tok;
+ this.hostIp = ip;
+ this.hostIqn = iqn;
+ }
+
+ public Boolean getIsActive() {
+ return isActive;
+ }
+
+ public void setIsActive(Boolean isActive) {
+ this.isActive = isActive;
+ }
+
+
+ public VolumeToken getToken() {
+ return token;
+ }
+
+ public void setToken(VolumeToken token) {
+ this.token = token;
+ }
+
+ public String getHostIp() {
+ return hostIp;
+ }
+
+ public void setHostIp(String hostIp) {
+ this.hostIp = hostIp;
+ }
+
+ public String getHostIqn() {
+ return hostIqn;
+ }
+
+ public void setHostIqn(String hostIqn) {
+ this.hostIqn = hostIqn;
+ }
+
+ @Override
+ public int hashCode( ) {
+ final int prime = 31;
+ int result = 1;
+ result = prime * result + ( ( this.volumeId == null ) ? 0 : this.volumeId.hashCode( ) );
+ return result;
+ }
+
+ @Override
+ public boolean equals( Object obj ) {
+ if ( this == obj ) {
+ return true;
+ }
+ if ( obj == null ) {
+ return false;
+ }
+ if ( getClass( ) != obj.getClass( ) ) {
+ return false;
+ }
+ VolumeExportRecord other = ( VolumeExportRecord ) obj;
+ if ( this.volumeId == null ) {
+ if ( other.volumeId != null ) {
+ return false;
+ }
+ } else if ( !this.volumeId.equals( other.volumeId ) || !this.hostIqn.equals(other.hostIqn) ||!this.hostIp.equals(other.hostIp) || !this.isActive == other.isActive) {
+ return false;
+ }
+ return true;
+ }
+
+}
View
171 clc/modules/core/src/main/java/edu/ucsb/eucalyptus/cloud/entities/VolumeToken.java
@@ -0,0 +1,171 @@
+/*************************************************************************
+ * Copyright 2009-2012 Eucalyptus Systems, Inc.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 3 of the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see http://www.gnu.org/licenses/.
+ *
+ * Please contact Eucalyptus Systems, Inc., 6755 Hollister Ave., Goleta
+ * CA 93117, USA or visit http://www.eucalyptus.com/licenses/ if you need
+ * additional information or have any questions.
+ *
+ * This file may incorporate work covered under the following copyright
+ * and permission notice:
+ *
+ * Software License Agreement (BSD License)
+ *
+ * Copyright (c) 2008, Regents of the University of California
+ * All rights reserved.
+ *
+ * Redistribution and use of this software in source and binary forms,
+ * with or without modification, are permitted provided that the
+ * following conditions are met:
+ *
+ * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+ * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE. USERS OF THIS SOFTWARE ACKNOWLEDGE
+ * THE POSSIBLE PRESENCE OF OTHER OPEN SOURCE LICENSED MATERIAL,
+ * COPYRIGHTED MATERIAL OR PATENTED MATERIAL IN THIS SOFTWARE,
+ * AND IF ANY SUCH MATERIAL IS DISCOVERED THE PARTY DISCOVERING
+ * IT MAY INFORM DR. RICH WOLSKI AT THE UNIVERSITY OF CALIFORNIA,
+ * SANTA BARBARA WHO WILL THEN ASCERTAIN THE MOST APPROPRIATE REMEDY,
+ * WHICH IN THE REGENTS' DISCRETION MAY INCLUDE, WITHOUT LIMITATION,
+ * REPLACEMENT OF THE CODE SO IDENTIFIED, LICENSING OF THE CODE SO
+ * IDENTIFIED, OR WITHDRAWAL OF THE CODE CAPABILITY TO THE EXTENT
+ * NEEDED TO COMPLY WITH ANY SUCH LICENSES OR RIGHTS.
+ ************************************************************************/
+
+package edu.ucsb.eucalyptus.cloud.entities;
+
+import java.util.Collection;
+import java.util.Set;
+
+import javax.persistence.CascadeType;
+import javax.persistence.Column;
+import javax.persistence.Embedded;
+import javax.persistence.FetchType;
+import javax.persistence.JoinColumn;
+import javax.persistence.OneToMany;
+import javax.persistence.PersistenceContext;
+import javax.persistence.Table;
+
+import org.hibernate.annotations.Cache;
+import org.hibernate.annotations.CacheConcurrencyStrategy;
+import org.hibernate.annotations.Entity;
+import org.hibernate.annotations.NotFound;
+import org.hibernate.annotations.NotFoundAction;
+
+import com.eucalyptus.entities.AbstractPersistent;
+
+@Entity
+@javax.persistence.Entity
+@PersistenceContext(name="eucalyptus_storage")
+@Table( name = "volume_tokens" )
+@Cache( usage = CacheConcurrencyStrategy.TRANSACTIONAL )
+public class VolumeToken extends AbstractPersistent {
+ private static final long serialVersionUID = 1L;
+
+ @Column(name="token", unique=true, nullable = false)
+ private String token;
+
+ @Column(name="volume_id")
+ private String volumeId;
+
+ @Column(name="is_valid")
+ private Boolean isValid;
+
+ @OneToMany( fetch = FetchType.LAZY, cascade = CascadeType.REMOVE, orphanRemoval = true, mappedBy = "token" )
+ private Set<VolumeExportRecord> exportRecords;
+
+ public VolumeToken() {
+ volumeId = null;
+ token = null;
+ }
+
+ public VolumeToken(String volId) {
+ this.volumeId = volId;
+ this.token = null;
+ this.exportRecords = null;
+ this.isValid = null;
+ }
+
+ public VolumeToken(String volId, String token, boolean valid) {
+ this.volumeId = volId;
+ this.token = token;
+ this.exportRecords = null;
+ this.isValid = valid;
+ }
+
+ public VolumeToken(boolean isValid) {
+ this.volumeId = null;
+ this.token = null;
+ this.exportRecords = null;
+ this.isValid = isValid;
+ }
+
+ public String getVolumeId() {
+ return volumeId;
+ }
+
+ public void setVolumeId(String volumeId) {
+ this.volumeId = volumeId;
+ }
+
+ public String getToken() {
+ return token;
+ }
+
+ public void setToken(String token) {
+ this.token = token;
+ }
+
+ public Boolean getIsValid() {
+ return isValid;
+ }
+
+ public void setIsValid(Boolean isValid) {
+ this.isValid = isValid;
+ }
+
+ public Set<VolumeExportRecord> getExportRecords() {
+ return exportRecords;
+ }
+
+ public void setExportRecords(Set<VolumeExportRecord> exportRecords) {
+ this.exportRecords = exportRecords;
+ }
+
+ public void addExportRecord(VolumeExportRecord record) {
+ this.exportRecords.add(record);
+ }
+
+ public void removeExportRecord(VolumeExportRecord record) {
+ this.exportRecords.remove(record);
+ }
+
+}
View
4 clc/modules/msgs/src/main/java/com/eucalyptus/auth/principal/Principals.java
@@ -317,7 +317,7 @@ public void removePolicy( String name ) throws AuthException {}
@Override
public void removeInfo(String key) throws AuthException {}
};
-
+
private static final User NOBODY_USER = new User( ) {
private final Certificate cert = new Certificate( ) {
@@ -568,7 +568,7 @@ public static User systemUser( ) {
public static User nobodyUser( ) {
return NOBODY_USER;
}
-
+
public static Account nobodyAccount( ) {
return NOBODY_ACCOUNT;
}
View
140 clc/modules/msgs/src/main/java/com/eucalyptus/ws/handlers/NodeWsSecHandler.java
@@ -0,0 +1,140 @@
+/*************************************************************************
+ * Copyright 2009-2012 Eucalyptus Systems, Inc.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 3 of the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see http://www.gnu.org/licenses/.
+ *
+ * Please contact Eucalyptus Systems, Inc., 6755 Hollister Ave., Goleta
+ * CA 93117, USA or visit http://www.eucalyptus.com/licenses/ if you need
+ * additional information or have any questions.
+ *
+ * This file may incorporate work covered under the following copyright
+ * and permission notice:
+ *
+ * Software License Agreement (BSD License)
+ *
+ * Copyright (c) 2008, Regents of the University of California
+ * All rights reserved.
+ *
+ * Redistribution and use of this software in source and binary forms,
+ * with or without modification, are permitted provided that the
+ * following conditions are met:
+ *
+ * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+ * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE. USERS OF THIS SOFTWARE ACKNOWLEDGE
+ * THE POSSIBLE PRESENCE OF OTHER OPEN SOURCE LICENSED MATERIAL,
+ * COPYRIGHTED MATERIAL OR PATENTED MATERIAL IN THIS SOFTWARE,
+ * AND IF ANY SUCH MATERIAL IS DISCOVERED THE PARTY DISCOVERING
+ * IT MAY INFORM DR. RICH WOLSKI AT THE UNIVERSITY OF CALIFORNIA,
+ * SANTA BARBARA WHO WILL THEN ASCERTAIN THE MOST APPROPRIATE REMEDY,
+ * WHICH IN THE REGENTS' DISCRETION MAY INCLUDE, WITHOUT LIMITATION,
+ * REPLACEMENT OF THE CODE SO IDENTIFIED, LICENSING OF THE CODE SO
+ * IDENTIFIED, OR WITHDRAWAL OF THE CODE CAPABILITY TO THE EXTENT
+ * NEEDED TO COMPLY WITH ANY SUCH LICENSES OR RIGHTS.
+ ************************************************************************/
+
+package com.eucalyptus.ws.handlers;
+
+import java.security.cert.X509Certificate;
+import java.util.Collection;
+import org.apache.axiom.soap.SOAP11Constants;
+import org.apache.axiom.soap.SOAPConstants;
+import org.apache.axiom.soap.SOAPEnvelope;
+import org.apache.log4j.Logger;
+import org.apache.ws.security.WSConstants;
+import org.apache.ws.security.WSEncryptionPart;
+import org.jboss.netty.channel.MessageEvent;
+import com.eucalyptus.auth.principal.Principals;
+import com.eucalyptus.component.Partition;
+import com.eucalyptus.component.Partitions;
+import com.eucalyptus.component.auth.SystemCredentials;
+import com.eucalyptus.component.id.Eucalyptus;
+import com.eucalyptus.context.Contexts;
+import com.eucalyptus.crypto.util.WSSecurity;
+import com.eucalyptus.http.MappingHttpMessage;
+import com.eucalyptus.http.MappingHttpRequest;
+import com.eucalyptus.ws.WebServicesException;
+import com.eucalyptus.ws.util.CredentialProxy;
+import com.google.common.collect.Lists;
+
+public class NodeWsSecHandler extends WsSecHandler {
+ private static final String WSA_NAMESPACE = "http://www.w3.org/2005/08/addressing";
+ private static Logger LOG = Logger.getLogger( NodeWsSecHandler.class );
+
+ public NodeWsSecHandler( ) {
+ super( new CredentialProxy( Eucalyptus.class ) );
+ }
+
+ @Override
+ public Collection<WSEncryptionPart> getSignatureParts( ) {
+ return Lists.newArrayList(
+ //TODO: removed this because on out-bound it is just a response..need to verify this with grze
+ //new WSEncryptionPart( "To", WSA_NAMESPACE, "Content" ),
+ //new WSEncryptionPart( "MessageID", WSA_NAMESPACE, "Content" ),
+ //new WSEncryptionPart( "Action", WSA_NAMESPACE, "Content" ),
+ new WSEncryptionPart( WSConstants.TIMESTAMP_TOKEN_LN, WSConstants.WSU_NS, "Content" ),
+ new WSEncryptionPart( SOAPConstants.BODY_LOCAL_NAME, SOAP11Constants.SOAP_ENVELOPE_NAMESPACE_URI, "Content" ) );
+
+ }
+
+ @Override
+ public boolean shouldTimeStamp( ) {
+ return true;
+ }
+
+ @Override
+ public void incomingMessage( MessageEvent event ) throws Exception {
+ final Object o = event.getMessage( );
+ if ( o instanceof MappingHttpRequest ) {
+ final MappingHttpMessage httpRequest = ( MappingHttpMessage ) o;
+ final SOAPEnvelope envelope = httpRequest.getSoapEnvelope( );
+
+ X509Certificate cert = WSSecurity.verifyWSSec( envelope );
+
+ if ( cert == null) {
+ throw new WebServicesException( "Authentication failed: Certificate is null");
+ } else {
+ boolean nodeCertFound = false;
+ for(Partition p : Partitions.list()) {
+ if(cert.equals(p.getNodeCertificate())) {
+ nodeCertFound = true;
+ break;
+ }
+ }
+
+ if(!nodeCertFound) {
+ throw new WebServicesException( "Authentication failed: The following certificate is not trusted:\n " + cert );
+ }
+ }
+
+ Contexts.lookup( ( ( MappingHttpMessage ) o ).getCorrelationId( ) ).setUser( Principals.systemUser() );
+ }
+ }
+}
View
62 clc/modules/msgs/src/main/java/edu/ucsb/eucalyptus/msgs/StorageController.groovy
@@ -61,19 +61,18 @@
************************************************************************/
package edu.ucsb.eucalyptus.msgs;
-
-import com.eucalyptus.component.ComponentId.ComponentMessage
-import com.eucalyptus.component.id.Storage
-
-public class StorageResponseType extends BaseMessage {
- def StorageResponseType() {}
-}
+import com.eucalyptus.component.id.Storage;
+import com.eucalyptus.component.ComponentId.ComponentMessage;
@ComponentMessage(Storage.class)
public class StorageRequestType extends BaseMessage {
def StorageRequestType() {}
}
+public class StorageResponseType extends BaseMessage {
+ def StorageResponseType() {}
+}
+
public class StorageErrorMessageType extends BaseMessage {
def StorageErrorMessageType() {
}
@@ -90,6 +89,34 @@ public class StorageErrorMessageType extends BaseMessage {
}
}
+public class ExportVolumeType extends StorageRequestType {
+ String volumeId;
+ String token;
+ String ip;
+ String iqn;
+
+ def ExportVolumeType() {}
+}
+
+public class ExportVolumeResponseType extends StorageResponseType {
+ String volumeId;
+ String connectionString;
+ def ExportVolumeResponseType() {}
+
+}
+
+public class UnexportVolumeType extends StorageRequestType {
+ String volumeId;
+ String token;
+ String ip;
+ String iqn;
+ def UnexportVolumeType() {}
+}
+
+public class UnexportVolumeResponseType extends StorageResponseType {
+}
+
+
public class GetStorageVolumeType extends StorageRequestType {
String volumeId;
}
@@ -104,6 +131,21 @@ public class GetStorageVolumeResponseType extends StorageResponseType {
String actualDeviceName;
}
+public class GetVolumeTokenType extends StorageRequestType {
+ String volumeId;
+
+ def GetVolumeTokenType() {}
+
+ def GetVolumeTokenType(String vol) {
+ this.volumeId = vol;
+ }
+}
+
+public class GetVolumeTokenResponseType extends StorageResponseType {
+ String volumeId;
+ String token;
+}
+
public class UpdateStorageConfigurationType extends StorageRequestType {
String name;
ArrayList<ComponentProperty> storageParams;
@@ -361,11 +403,9 @@ public class StorageUsageStatsRecord extends StatEventRecord {
public class CloneVolumeType extends StorageRequestType {
String volumeId;
- def CloneVolumeType() {
- }
+ def CloneVolumeType() {}
}
public class CloneVolumeResponseType extends StorageResponseType {
- def CloneVolumeResponseType() {
- }
+ def CloneVolumeResponseType() {}
}
View
82 clc/modules/msgs/src/main/resources/storage-controller-binding.xml
@@ -73,71 +73,31 @@
<mapping class="edu.ucsb.eucalyptus.msgs.StorageResponseType"
abstract="true">
</mapping>
- <mapping name="CreateStorageVolume"
- class="edu.ucsb.eucalyptus.msgs.CreateStorageVolumeType" extends="edu.ucsb.eucalyptus.msgs.StorageRequestType">
- <value name="VolumeId" field="volumeId" />
- <value name="Size" field="size" />
- <value name="SnapshotId" field="snapshotId" />
+
+ <mapping name="ExportVolume" class="edu.ucsb.eucalyptus.msgs.ExportVolumeType"
+ extends="edu.ucsb.eucalyptus.msgs.StorageRequestType">
+ <value name="volumeId" field="volumeId" />
+ <value name="token" field="token"/>
+ <value name="ip" field="ip"/>
+ <value name="iqn" field="iqn"/>
</mapping>
- <mapping name="CreateStorageVolumeResponse"
- class="edu.ucsb.eucalyptus.msgs.CreateStorageVolumeResponseType"
- extends="edu.ucsb.eucalyptus.msgs.StorageResponseType">
- <value name="VolumeId" field="volumeId" />
- <value name="Size" field="size" />
- <value name="SnapshotId" field="snapshotId" />
- <value name="Status" field="status" />
- <value name="CreateTime" field="createTime" />
+ <mapping name="ExportVolumeResponse" class="edu.ucsb.eucalyptus.msgs.ExportVolumeResponseType"
+ extends="edu.ucsb.eucalyptus.msgs.StorageResponseType">
+ <value name="volumeId" field="volumeId" />
+ <value name="connectionString" field="connectionString" />
</mapping>
-
- <mapping name="GetStorageVolume" class="edu.ucsb.eucalyptus.msgs.GetStorageVolumeType"
- extends="edu.ucsb.eucalyptus.msgs.StorageRequestType">
- <value name="VolumeId" field="volumeId" />
- </mapping>
-
- <mapping name="GetStorageVolumeResponse"
- class="edu.ucsb.eucalyptus.msgs.GetStorageVolumeResponseType" extends="edu.ucsb.eucalyptus.msgs.StorageResponseType">
- <value name="VolumeId" field="volumeId" />
- <value name="Size" field="size" />
- <value name="SnapshotId" field="snapshotId" />
- <value name="Status" field="status" />
- <value name="CreateTime" field="createTime" />
- <value name="ActualDeviceName" field="actualDeviceName" />
- </mapping>
-
- <mapping name="DeleteStorageVolume"
- class="edu.ucsb.eucalyptus.msgs.DeleteStorageVolumeType" extends="edu.ucsb.eucalyptus.msgs.StorageRequestType">
- <value name="VolumeId" field="volumeId" />
- </mapping>
-
- <mapping name="DeleteStorageVolumeResponse"
- class="edu.ucsb.eucalyptus.msgs.DeleteStorageVolumeResponseType"
- extends="edu.ucsb.eucalyptus.msgs.StorageResponseType">
- </mapping>
-
- <mapping name="CreateStorageSnapshot"
- class="edu.ucsb.eucalyptus.msgs.CreateStorageSnapshotType" extends="edu.ucsb.eucalyptus.msgs.StorageRequestType">
- <value name="VolumeId" field="volumeId" />
- <value name="SnapshotId" field="snapshotId" />
- </mapping>
-
- <mapping name="CreateStorageSnapshotResponse"
- class="edu.ucsb.eucalyptus.msgs.CreateStorageSnapshotResponseType"
- extends="edu.ucsb.eucalyptus.msgs.StorageResponseType">
- <value name="VolumeId" field="volumeId" />
- <value name="SnapshotId" field="snapshotId" />
- <value name="Status" field="status" />
- <value name="StartTime" field="startTime" />
- <value name="Progress" field="progress" />
- </mapping>
-
- <mapping name="DeleteStorageSnapshot"
- class="edu.ucsb.eucalyptus.msgs.DeleteStorageSnapshotType" extends="edu.ucsb.eucalyptus.msgs.StorageRequestType">
- <value name="SnapshotId" field="snapshotId" />
+
+<mapping name="UnexportVolume" class="edu.ucsb.eucalyptus.msgs.UnexportVolumeType"
+ extends="edu.ucsb.eucalyptus.msgs.StorageRequestType">
+ <value name="volumeId" field="volumeId" />
+ <value name="token" field="token"/>
+ <value name="ip" field="ip"/>
+ <value name="iqn" field="iqn"/>
</mapping>
- <mapping name="DeleteStorageSnapshotResponse"
- class="edu.ucsb.eucalyptus.msgs.DeleteStorageSnapshotResponseType"
- extends="edu.ucsb.eucalyptus.msgs.StorageResponseType">
+ <mapping name="UnexportVolumeResponse" class="edu.ucsb.eucalyptus.msgs.UnexportVolumeResponseType"
+ extends="edu.ucsb.eucalyptus.msgs.StorageResponseType">
</mapping>
+
</binding>
View
318 clc/modules/storage-controller/src/main/java/com/eucalyptus/storage/VolumeExports.java
@@ -0,0 +1,318 @@
+/*************************************************************************
+ * Copyright 2009-2012 Eucalyptus Systems, Inc.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 3 of the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see http://www.gnu.org/licenses/.
+ *
+ * Please contact Eucalyptus Systems, Inc., 6755 Hollister Ave., Goleta
+ * CA 93117, USA or visit http://www.eucalyptus.com/licenses/ if you need
+ * additional information or have any questions.
+ *
+ * This file may incorporate work covered under the following copyright
+ * and permission notice:
+ *
+ * Software License Agreement (BSD License)
+ *
+ * Copyright (c) 2008, Regents of the University of California
+ * All rights reserved.
+ *
+ * Redistribution and use of this software in source and binary forms,
+ * with or without modification, are permitted provided that the
+ * following conditions are met:
+ *
+ * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+ * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE. USERS OF THIS SOFTWARE ACKNOWLEDGE
+ * THE POSSIBLE PRESENCE OF OTHER OPEN SOURCE LICENSED MATERIAL,
+ * COPYRIGHTED MATERIAL OR PATENTED MATERIAL IN THIS SOFTWARE,
+ * AND IF ANY SUCH MATERIAL IS DISCOVERED THE PARTY DISCOVERING
+ * IT MAY INFORM DR. RICH WOLSKI AT THE UNIVERSITY OF CALIFORNIA,
+ * SANTA BARBARA WHO WILL THEN ASCERTAIN THE MOST APPROPRIATE REMEDY,
+ * WHICH IN THE REGENTS' DISCRETION MAY INCLUDE, WITHOUT LIMITATION,
+ * REPLACEMENT OF THE CODE SO IDENTIFIED, LICENSING OF THE CODE SO
+ * IDENTIFIED, OR WITHDRAWAL OF THE CODE CAPABILITY TO THE EXTENT
+ * NEEDED TO COMPLY WITH ANY SUCH LICENSES OR RIGHTS.
+ ************************************************************************/
+
+package com.eucalyptus.storage;
+
+import java.util.List;
+import java.util.NoSuchElementException;
+import java.util.concurrent.Executors;
+import java.util.concurrent.ScheduledExecutorService;
+import java.util.concurrent.TimeUnit;
+
+import javax.persistence.EntityTransaction;
+
+import org.apache.log4j.Logger;
+
+import com.eucalyptus.crypto.Crypto;
+import com.eucalyptus.entities.Entities;
+import com.eucalyptus.entities.TransactionException;
+import com.eucalyptus.util.EucalyptusCloudException;
+import com.google.common.base.Function;
+
+import edu.ucsb.eucalyptus.cloud.entities.VolumeExportRecord;
+import edu.ucsb.eucalyptus.cloud.entities.VolumeToken;
+
+/**
+ * Manages the collection of Volume Exports and their associated entity state and tokens.
+ * This is the interface point for the SC to the volume export metadata.
+ * @author zhill
+ *
+ */
+public class VolumeExports {
+ private static final Logger LOG = Logger.getLogger(VolumeExports.class);
+
+ private static ScheduledExecutorService cleanupService = null;
+ private static final VolumeToken exampleInvalidToken = new VolumeToken(false); //Use the same example, no need to regen each time.
+
+ public static void initialize() {
+ cleanupService= Executors.newSingleThreadScheduledExecutor();
+
+ //Run in 1 minute and every 5 minutes thereafter
+ cleanupService.scheduleAtFixedRate(new Runnable () {
+ @Override
+ public void run() {
+ //Query the DB for invalid tokens, then delete them.
+ EntityTransaction db = Entities.get(VolumeToken.class);
+ List<VolumeToken> tokens = Entities.query(exampleInvalidToken);
+ try {
+ boolean skip = false;
+ //Could also use Entities.deleteAllMatching()...need to look at that as well
+ for(VolumeToken t : tokens) {
+ skip = false;
+ for(VolumeExportRecord r : t.getExportRecords()) {
+ //Ensure all records are inactive
+ if(r.getIsActive()) {
+ skip=true;
+ }
+ }
+ if(!skip) {
+ Entities.delete(t);
+ }
+ }
+ } finally {
+ if(db.isActive()) {
+ try {
+ db.commit();
+ } catch(final Throwable t) {
+ LOG.error("VolumeExport cleanup thread commit failed: " + t.getMessage());
+ db.rollback();
+ }
+ }
+ }
+
+ }
+ }, 1, 5, TimeUnit.MINUTES);
+ }
+
+ public static void shutdown() {
+ LOG.trace("Shutting down VolumeExport checker threads");
+ //cleanupService.shutdown();
+ }
+
+ /*
+ * TODO:
+ * Implement a state machine for a volume export
+ *
+ * States:
+ * 1. initialized
+ * 2. exported
+ * 3. unexported
+ *
+ * Transitions:
+ * Start -> initialized (do Issue)
+ * initialized -> exported (add valid export)
+ * exported -> exported (invalidate export, but count(ExtantExports) > 0)
+ * exported -> unexported (invalidate export(s), count(ExtantExports) == 0)
+ * unexported -> unexported (attempt export)
+ * unexported -> unexported (attampt unexport)
+ * Valid_issued -> Invalid (invalidate all exports and token)
+ */
+
+
+
+ public static VolumeToken issueToken(String volumeId) {
+ EntityTransaction db = Entities.get(VolumeToken.class);
+ try {
+ VolumeToken token = new VolumeToken();
+ token.setToken(Crypto.generateSessionToken());
+ token.setVolumeId(volumeId);
+ token.setIsValid(true);
+ Entities.persist(token);
+ db.commit();
+ return token;
+ } catch(Exception e) {
+ LOG.error("Error creating new volume token for " + volumeId);
+ } finally {
+ if(db.isActive()) {
+ db.rollback();
+ }
+ }
+ return null;
+ }
+
+ /**
+ * Add/request a new export record added for the specified token. Will return false if not possible due to token invalid
+ * @param volumeId
+ * @param token
+ * @param ip
+ * @param iqn
+ * @return
+ * @throws EucalyptusCloudException
+ */
+ public static boolean addExport(final String volumeId, final String token, final String ip, final String iqn) throws EucalyptusCloudException {
+ final VolumeToken requestToken = new VolumeToken(volumeId);
+ requestToken.setToken(token);
+
+ Function<VolumeToken, VolumeToken> checkToken = new Function<VolumeToken, VolumeToken>() {
+ @Override
+ public VolumeToken apply(VolumeToken reqToken) {
+ VolumeToken tok = null;
+ EntityTransaction db = Entities.get(VolumeToken.class);
+ try {
+ tok = Entities.uniqueResult(reqToken);
+ Entities.merge(tok);
+ //Do the update of export.
+ VolumeExportRecord record = new VolumeExportRecord();
+ record.setToken(tok);
+ record.setHostIp(ip);
+ record.setHostIqn(iqn);
+ tok.addExportRecord(new VolumeExportRecord(volumeId, tok, ip, iqn));
+ Entities.persist(record);
+ return tok;
+ } catch (TransactionException e) {
+ LOG.error("Volume Export: " + volumeId + " Transaction error. Rolling back");
+
+ } catch (NoSuchElementException e) {
+ LOG.error("Invalid Token received for volume " + volumeId);
+
+ } finally {
+ if(db.isActive()) {
+ db.rollback();
+ }
+ }
+
+ return tok;
+ }
+ };
+
+ try {
+ Entities.asTransaction(VolumeToken.class, checkToken).apply(requestToken);
+ return true;
+ } catch(Exception e) {
+ return false;
+ }
+ }
+
+ /**
+ * Remove an extant export record
+ * @param volumeId
+ * @param token
+ * @param hostIp
+ * @param hostIqn
+ * @return
+ */
+ public static boolean removeExport(String volumeId, String token, String hostIp, String hostIqn) {
+ EntityTransaction db = Entities.get(VolumeToken.class);
+ try {
+ VolumeToken foundToken = Entities.uniqueResult(new VolumeToken(volumeId, token, true));
+ if(foundToken.getIsValid()) {
+ //TODO: make this cleaner, but still should not delete token after use, semantics are for token to follow vm attachment lifecycle
+ LOG.debug("Valid token found, invalidating token on unexport " + volumeId);
+ foundToken.setIsValid(Boolean.FALSE);
+ db.commit();
+ return true;
+ } else {
+ LOG.warn("Attempted to remove export with invalid token for volume " + volumeId);
+ }
+ } catch(Exception e) {
+ LOG.error("Error checking token for volume " + volumeId + " : " + e.getMessage());
+ LOG.debug("Exception caught invalidating token for vol: " + volumeId,e);
+ } finally {
+ if(db.isActive()) {
+ db.rollback();
+ }
+ }
+ LOG.warn("Cannot remove export for volume " + volumeId);
+ return false;
+ }
+
+ //For admin stuff
+ public static void flushAllTokens() {
+ EntityTransaction db = Entities.get(VolumeToken.class);
+ try {
+ Entities.deleteAll(VolumeToken.class);
+ } catch(Throwable e) {
+ LOG.error("Error flushing volume tokens: " + e.getMessage());
+ } finally {
+ db.commit();
+ }
+ }
+
+ public boolean checkToken(String volumeId, String token) throws EucalyptusCloudException {
+ EntityTransaction db = Entities.get(VolumeToken.class);
+ try {
+ VolumeToken tok = new VolumeToken();
+ tok.setToken(token);
+ VolumeToken t = Entities.uniqueResult(tok);
+ return t.getIsValid();
+ } catch(TransactionException e) {
+ LOG.error("Transaction exception checking", e);
+ throw new EucalyptusCloudException(e);
+ } catch(NoSuchElementException e) {
+ return false;
+ } finally {
+ db.rollback();
+ }
+ }
+
+ public boolean invalidateToken(String volumeId, String token) throws EucalyptusCloudException {
+ EntityTransaction db = Entities.get(VolumeToken.class);
+ try {
+ VolumeToken foundToken = Entities.uniqueResult(new VolumeToken(volumeId, token, true));
+ if(foundToken.getIsValid()) {
+ //TODO: make this cleaner, but still should not delete token after use, semantics are for token to follow vm attachment lifecycle
+ //LOG.debug("Valid token found, invalidating after one use for volume " + volumeId);
+ //Entities.delete(foundToken);
+ db.commit();
+ return true;
+ }
+ } catch(Exception e) {
+ LOG.error("Error checking token for volume " + volumeId + " : " + e.getMessage());
+ LOG.debug("Exception caught invalidating token for vol: " + volumeId,e);
+ } finally {
+ if(db.isActive()) {
+ db.rollback();
+ }
+ }
+ return false;
+ }
+}
View
103 clc/modules/storage-controller/src/main/java/com/eucalyptus/storage/VolumeTokenService.java
@@ -0,0 +1,103 @@
+/*************************************************************************
+ * Copyright 2009-2012 Eucalyptus Systems, Inc.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 3 of the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see http://www.gnu.org/licenses/.
+ *
+ * Please contact Eucalyptus Systems, Inc., 6755 Hollister Ave., Goleta
+ * CA 93117, USA or visit http://www.eucalyptus.com/licenses/ if you need
+ * additional information or have any questions.
+ *
+ * This file may incorporate work covered under the following copyright
+ * and permission notice:
+ *
+ * Software License Agreement (BSD License)
+ *
+ * Copyright (c) 2008, Regents of the University of California
+ * All rights reserved.
+ *
+ * Redistribution and use of this software in source and binary forms,
+ * with or without modification, are permitted provided that the
+ * following conditions are met:
+ *
+ * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+ * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE. USERS OF THIS SOFTWARE ACKNOWLEDGE
+ * THE POSSIBLE PRESENCE OF OTHER OPEN SOURCE LICENSED MATERIAL,
+ * COPYRIGHTED MATERIAL OR PATENTED MATERIAL IN THIS SOFTWARE,
+ * AND IF ANY SUCH MATERIAL IS DISCOVERED THE PARTY DISCOVERING
+ * IT MAY INFORM DR. RICH WOLSKI AT THE UNIVERSITY OF CALIFORNIA,
+ * SANTA BARBARA WHO WILL THEN ASCERTAIN THE MOST APPROPRIATE REMEDY,
+ * WHICH IN THE REGENTS' DISCRETION MAY INCLUDE, WITHOUT LIMITATION,
+ * REPLACEMENT OF THE CODE SO IDENTIFIED, LICENSING OF THE CODE SO
+ * IDENTIFIED, OR WITHDRAWAL OF THE CODE CAPABILITY TO THE EXTENT
+ * NEEDED TO COMPLY WITH ANY SUCH LICENSES OR RIGHTS.
+ ************************************************************************/
+
+package com.eucalyptus.storage;
+
+import com.eucalyptus.util.EucalyptusCloudException;
+
+import edu.ucsb.eucalyptus.cloud.entities.VolumeToken;
+
+/**
+ * A token issuing and resolving service.
+ * @author zhill
+ *
+ */
+public interface VolumeTokenService {
+
+ /**
+ * Generate a new token for the specified resource
+ * @param resource
+ * @return
+ */
+ public VolumeToken issueToken(String resource) throws EucalyptusCloudException;
+
+ /**
+ * Check the token but do not invalidate
+ * @param token
+ * @return
+ */
+ public boolean checkToken(String resource, String token) throws EucalyptusCloudException;
+
+ /**
+ * If the token is invalid will return false, if was valid returns true.
+ * Sets the token to invalid. Subsequent checks/invalidations will return false
+ * @param token
+ * @return
+ */
+ public boolean invalidateToken(String resource, String token) throws EucalyptusCloudException;
+
+ /**
+ * Invalidates all tokens and removes them.
+ */
+ public void flushTokens() throws EucalyptusCloudException;
+
+}
View
144 clc/modules/storage-controller/src/main/java/edu/ucsb/eucalyptus/cloud/ws/BlockStorage.java
@@ -88,6 +88,7 @@
import com.eucalyptus.context.Context;
import com.eucalyptus.context.Contexts;
import com.eucalyptus.context.NoSuchContextException;
+import com.eucalyptus.crypto.Crypto;
import com.eucalyptus.entities.Entities;
import com.eucalyptus.entities.EntityWrapper;
import com.eucalyptus.entities.Transactions;
@@ -97,8 +98,11 @@
import com.eucalyptus.storage.CheckerTask;
import com.eucalyptus.storage.LogicalStorageManager;
import com.eucalyptus.storage.StorageManagers;
+import com.eucalyptus.storage.VolumeExports;
+import com.eucalyptus.util.BlockStorageUtil;
import com.eucalyptus.util.EucalyptusCloudException;
import com.eucalyptus.util.StorageProperties;
+import com.google.common.collect.Lists;
import edu.ucsb.eucalyptus.cloud.AccessDeniedException;
import edu.ucsb.eucalyptus.cloud.EntityTooLargeException;
@@ -111,6 +115,7 @@
import edu.ucsb.eucalyptus.cloud.entities.SnapshotInfo;
import edu.ucsb.eucalyptus.cloud.entities.StorageInfo;
import edu.ucsb.eucalyptus.cloud.entities.VolumeInfo;
+import edu.ucsb.eucalyptus.cloud.entities.VolumeToken;
import edu.ucsb.eucalyptus.cloud.entities.WalrusInfo;
import edu.ucsb.eucalyptus.msgs.AttachStorageVolumeResponseType;
import edu.ucsb.eucalyptus.msgs.AttachStorageVolumeType;
@@ -133,12 +138,18 @@
import edu.ucsb.eucalyptus.msgs.DescribeStorageVolumesType;
import edu.ucsb.eucalyptus.msgs.DetachStorageVolumeResponseType;
import edu.ucsb.eucalyptus.msgs.DetachStorageVolumeType;
+import edu.ucsb.eucalyptus.msgs.ExportVolumeResponseType;
+import edu.ucsb.eucalyptus.msgs.ExportVolumeType;
import edu.ucsb.eucalyptus.msgs.GetStorageConfigurationResponseType;
import edu.ucsb.eucalyptus.msgs.GetStorageConfigurationType;
import edu.ucsb.eucalyptus.msgs.GetStorageVolumeResponseType;
import edu.ucsb.eucalyptus.msgs.GetStorageVolumeType;
+import edu.ucsb.eucalyptus.msgs.GetVolumeTokenResponseType;
+import edu.ucsb.eucalyptus.msgs.GetVolumeTokenType;
import edu.ucsb.eucalyptus.msgs.StorageSnapshot;
import edu.ucsb.eucalyptus.msgs.StorageVolume;
+import edu.ucsb.eucalyptus.msgs.UnexportVolumeResponseType;
+import edu.ucsb.eucalyptus.msgs.UnexportVolumeType;
import edu.ucsb.eucalyptus.msgs.UpdateStorageConfigurationResponseType;
import edu.ucsb.eucalyptus.msgs.UpdateStorageConfigurationType;
import edu.ucsb.eucalyptus.storage.StorageCheckerService;
@@ -155,7 +166,9 @@
static VolumeService volumeService;
static SnapshotService snapshotService;
static StorageCheckerService checkerService;
-
+
+ private static final boolean ENCRYPT_TOKEN = false;
+
//TODO: zhill, this can be added later for snapshot abort capabilities
//static ConcurrentHashMap<String,HttpTransfer> httpTransferMap; //To keep track of current transfers to support aborting
@@ -292,6 +305,133 @@ public GetStorageConfigurationResponseType GetStorageConfiguration(GetStorageCon
return reply;
}
+ public GetVolumeTokenResponseType GetVolumeToken(GetVolumeTokenType request) throws EucalyptusCloudException {
+ GetVolumeTokenResponseType reply = (GetVolumeTokenResponseType) request.getReply();
+ String volumeId = request.getVolumeId();
+
+ if(null == volumeId) {
+ LOG.error("Cannot get token for a null-valued volumeId");
+ throw new EucalyptusCloudException("No volumeId specified in token request");
+ }
+
+ VolumeToken token = VolumeExports.issueToken(volumeId);
+
+ if(ENCRYPT_TOKEN) {
+ //Encrypt the token with the NC's private key. token.getToken();
+ String encryptedToken = BlockStorageUtil.encryptForNode(token.getToken());
+ reply.setToken(encryptedToken);
+ } else {
+ reply.setToken(token.getToken());
+ }
+ reply.setVolumeId(volumeId);
+ return reply;
+ }
+
+ /**
+ * Removes connection authorization for the specified iqn/ip pair in the request using
+ * the specified token. Only performs the operation if the token is valid for the specified volume.
+ *
+ * Invalidates the token upon successful de-authorization.
+ * @param request
+ * @return
+ * @throws EucalyptusCloudException
+ */
+ public UnexportVolumeResponseType UnexportVolume(UnexportVolumeType request) throws EucalyptusCloudException {
+ UnexportVolumeResponseType reply = request.getReply();
+ String token = request.getToken();
+ String volumeId = request.getVolumeId();
+ String nodeIqn = request.getIqn();
+ String nodeIp = request.getIp();
+
+ if(token.startsWith(StorageProperties.TOKEN_PREFIX)) {
+ //Strip off prefix if not already done.
+ token = token.substring(StorageProperties.TOKEN_PREFIX.length(), token.length());
+ }
+
+ if(ENCRYPT_TOKEN) {
+ //Encrypt the token with the NC's private key. token.getToken();
+ token = BlockStorageUtil.decryptWithCloud(token);
+ }
+
+ EntityWrapper<VolumeInfo> db = StorageProperties.getEntityWrapper();
+ try {
+ VolumeInfo volumeInfo = db.getUnique(new VolumeInfo(volumeId));
+ } catch (EucalyptusCloudException ex) {
+ LOG.error("Unable to find volume: " + volumeId + ex);
+ throw new NoSuchEntityException("Unable to find volume: " + volumeId + ex);
+ } finally {
+ db.commit();
+ }
+ try {
+ //Check first, don't invalidate unless success.
+ if(VolumeExports.removeExport(volumeId, token, nodeIp, nodeIqn)){
+ blockManager.detachVolume(volumeId, nodeIqn);
+ } else {
+ LOG.error("Could not remove export for volume " + volumeId + " invalid token indicated");
+ }
+ } catch (EucalyptusCloudException ex) {
+ LOG.error("Could not detach volume " + volumeId);
+ throw ex;
+ }
+
+ return reply;
+ }
+
+ /**
+ * Perform a volume export validated by the token presented in the request.
+ * Upon completion of the Export operation, the identified host (by ip and iqn) will
+ * have access to connect to the requested volume. No connection is made, just the authorization.
+ * @param request
+ * @return
+ * @throws EucalyptusCloudException
+ */
+ public ExportVolumeResponseType ExportVolume(ExportVolumeType request) throws EucalyptusCloudException {
+ ExportVolumeResponseType reply = (ExportVolumeResponseType) request.getReply();
+
+ String volumeId = request.getVolumeId();
+ String token = request.getToken();
+ String ip = request.getIp();
+ String iqn = request.getIqn();
+
+ if(token.startsWith(StorageProperties.TOKEN_PREFIX)) {
+ //Strip off prefix if not already done.
+ token = token.substring(StorageProperties.TOKEN_PREFIX.length(), token.length());
+ }
+
+ if(ENCRYPT_TOKEN) {
+ //Encrypt the token with the NC's private key. token.getToken();
+ token = BlockStorageUtil.decryptWithCloud(token);
+ }
+
+ reply.setVolumeId(volumeId);
+ ArrayList<String> nodeIqns = Lists.newArrayList(iqn);
+ EntityWrapper<VolumeInfo> db = StorageProperties.getEntityWrapper();
+ try {
+ VolumeInfo volumeInfo = db.getUnique(new VolumeInfo(volumeId));
+ if(volumeInfo == null) {
+ throw new EucalyptusCloudException("Volume " + volumeId + " not found");
+ }
+ } catch (EucalyptusCloudException ex) {
+ LOG.error("Unable to find volume: " + volumeId + ex);
+ throw new NoSuchEntityException("Unable to find volume: " + volumeId + ex);
+ } finally {
+ db.commit();
+ }
+ try {
+ if(VolumeExports.addExport(volumeId, token, ip, iqn)) {
+ String deviceConnectString = blockManager.attachVolume(volumeId, nodeIqns);
+ reply.setConnectionString(deviceConnectString);
+
+ } else {
+ throw new EucalyptusCloudException("Invalid token " + token + " received for volume " + volumeId);
+ }
+ } catch (EucalyptusCloudException ex) {
+ LOG.error(ex, ex);
+ throw ex;
+ }
+ return reply;
+ }
+
public GetStorageVolumeResponseType GetStorageVolume(GetStorageVolumeType request) throws EucalyptusCloudException {
GetStorageVolumeResponseType reply = (GetStorageVolumeResponseType) request.getReply();
if(!StorageProperties.enableStorage) {
@@ -920,7 +1060,7 @@ public DetachStorageVolumeResponseType detachVolume(DetachStorageVolumeType requ
EntityWrapper<VolumeInfo> db = StorageProperties.getEntityWrapper();
try {
- VolumeInfo volumeInfo = db.getUnique(new VolumeInfo(volumeId));
+ VolumeInfo volumeInfo = db.getUnique(new VolumeInfo(volumeId));
} catch (EucalyptusCloudException ex) {
LOG.error("Unable to find volume: " + volumeId + ex);
throw new NoSuchEntityException("Unable to find volume: " + volumeId + ex);
View
1  ...wsstack/src/main/java/com/eucalyptus/ws/client/pipeline/ClusterClientPipelineFactory.java
@@ -84,6 +84,7 @@
@Override
public ChannelHandler get( ) {
return new ClusterWsSecHandler( );
+
}
};
View
104 ...wsstack/src/main/java/com/eucalyptus/ws/server/ExternalStorageControllerSoapPipeline.java
@@ -0,0 +1,104 @@
+/*************************************************************************
+ * Copyright 2009-2012 Eucalyptus Systems, Inc.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 3 of the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see http://www.gnu.org/licenses/.
+ *
+ * Please contact Eucalyptus Systems, Inc., 6755 Hollister Ave., Goleta
+ * CA 93117, USA or visit http://www.eucalyptus.com/licenses/ if you need
+ * additional information or have any questions.
+ *
+ * This file may incorporate work covered under the following copyright
+ * and permission notice:
+ *
+ * Software License Agreement (BSD License)
+ *
+ * Copyright (c) 2008, Regents of the University of California
+ * All rights reserved.
+ *
+ * Redistribution and use of this software in source and binary forms,
+ * with or without modification, are permitted provided that the
+ * following conditions are met:
+ *
+ * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+ * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE. USERS OF THIS SOFTWARE ACKNOWLEDGE
+ * THE POSSIBLE PRESENCE OF OTHER OPEN SOURCE LICENSED MATERIAL,
+ * COPYRIGHTED MATERIAL OR PATENTED MATERIAL IN THIS SOFTWARE,
+ * AND IF ANY SUCH MATERIAL IS DISCOVERED THE PARTY DISCOVERING
+ * IT MAY INFORM DR. RICH WOLSKI AT THE UNIVERSITY OF CALIFORNIA,
+ * SANTA BARBARA WHO WILL THEN ASCERTAIN THE MOST APPROPRIATE REMEDY,
+ * WHICH IN THE REGENTS' DISCRETION MAY INCLUDE, WITHOUT LIMITATION,
+ * REPLACEMENT OF THE CODE SO IDENTIFIED, LICENSING OF THE CODE SO
+ * IDENTIFIED, OR WITHDRAWAL OF THE CODE CAPABILITY TO THE EXTENT
+ * NEEDED TO COMPLY WITH ANY SUCH LICENSES OR RIGHTS.
+ ************************************************************************/
+
+package com.eucalyptus.ws.server;
+
+import org.jboss.netty.channel.ChannelPipeline;
+import org.jboss.netty.handler.codec.http.HttpRequest;
+import com.eucalyptus.binding.BindingManager;
+import com.eucalyptus.component.ComponentId.ComponentPart;
+import com.eucalyptus.component.id.Storage;
+import com.eucalyptus.ws.Handlers;
+import com.eucalyptus.ws.handlers.BindingHandler;
+import com.eucalyptus.ws.stages.ExternalSCAuthenticationStage;
+import com.eucalyptus.ws.stages.UnrollableStage;
+
+
+@ComponentPart( Storage.class )
+public class ExternalStorageControllerSoapPipeline extends FilteredPipeline {
+ private static final String SC_EXTERNAL_SOAP_NAMESPACE = "storagecontroller_eucalyptus_ucsb_edu";
+
+ private final UnrollableStage auth = new ExternalSCAuthenticationStage( );
+
+ @Override
+ public boolean checkAccepts( final HttpRequest message ) {
+ return (message.getUri( ).endsWith( "/services/Storage" ) || message.getUri( ).endsWith( "/services/Storage/" )) && message.getHeaderNames().contains( "SOAPAction" ) && message.getHeader("SOAPAction").trim().startsWith("\"EucalyptusSC#");
+ }
+
+ @Override
+ public String getName( ) {
+ return "storage-controller-external-soap";
+ }
+
+ @Override
+ public ChannelPipeline addHandlers( ChannelPipeline pipeline ) {
+ pipeline.addLast( "deserialize", Handlers.soapMarshalling( ) );
+ //pipeline.addLast( "ws-security", Handlers.internalWsSecHandler() );
+ auth.unrollStage(pipeline);
+ pipeline.addLast( "ws-addressing", Handlers.newAddressingHandler( "EucalyptusSC#" ) );
+ pipeline.addLast( "build-soap-envelope", Handlers.soapHandler( ) );
+ //pipeline.addLast( "binding", Handlers.bindingHandler( ) ); //
+ pipeline.addLast( "binding", new BindingHandler( BindingManager.getBinding(SC_EXTERNAL_SOAP_NAMESPACE)));
+ return pipeline;
+ }
+
+}
View
24 ...modules/wsstack/src/main/java/com/eucalyptus/ws/stages/ExternalSCAuthenticationStage.java
@@ -0,0 +1,24 @@
+package com.eucalyptus.ws.stages;
+
+import org.jboss.netty.channel.ChannelPipeline;
+
+import com.eucalyptus.ws.handlers.NodeWsSecHandler;
+
+public class ExternalSCAuthenticationStage implements UnrollableStage {
+
+ @Override
+ public int compareTo(UnrollableStage o) {
+ return this.getName( ).compareTo( o.getName( ) );
+ }
+
+ @Override
+ public void unrollStage(ChannelPipeline pipeline) {
+ pipeline.addLast( "node-soap-authentication", new NodeWsSecHandler( ) );
+ }
+
+ @Override
+ public String getName() {
+ return "external-sc-soap-authentication";
+ }
+
+}
View
2  cluster/Makefile
@@ -77,7 +77,7 @@ SHUTDOWNCC=shutdownCC
#WSDL2C=${AXIS2C_HOME}/bin/tools/wsdl2c/WSDL2C.sh
NCLIBS=../util/data.o ../node/client-marshal-adb.o ../util/ipc.o ../util/sensor.o
NC_FAKE_LIBS=../util/data.o ../node/client-marshal-fake.o ../util/ipc.o
-SCLIBS=../storage/storage-windows.o ../storage/walrus.o ../storage/http.o
+SCLIBS=../storage/storage-windows.o ../storage/walrus.o ../storage/http.o ../storage/ebs_utils.o
VNLIBS=../net/vnetwork.o ../util/log.o ../util/fault.o ../util/wc.o ../util/utf8.o ../util/misc.o ../util/euca_string.o ../storage/diskutil.o ../util/hash.o
WSSECLIBS=../util/euca_axis.o ../util/euca_auth.o
CC_LIBS = ../util/config.o ${LIBS} ${LDFLAGS} -lcurl -lssl -lcrypto -lrampart
View
136 cluster/handlers.c
@@ -112,6 +112,8 @@
#include <euca_string.h>
#include <axutil_error.h>
+#include <ebs_utils.h>
+
/*----------------------------------------------------------------------------*\
| |
| DEFINES |
@@ -250,7 +252,7 @@ char *SCHEDPOLICIES[SCHEDLAST] = {
\*----------------------------------------------------------------------------*/
static int migration_handler(ccInstance * myInstance, char *host, char *src, char *dst, migration_states migration_state, char **node, char **instance, char **action);
-
+static int populateOutboundMeta(ncMetadata *pMeta);
/*----------------------------------------------------------------------------*\
| |
| MACROS |
@@ -509,6 +511,38 @@ int doCancelBundleTask(ncMetadata * pMeta, char *instanceId)
return (ret);
}
+//! Remove cluster and storage services from other partitions so NCs only get globals and cluster-local services
+//! Modifies the meta in-place
+void filter_services(ncMetadata *meta, char *filter_partition) {
+ int i = 0, j = 0;
+ serviceInfoType tmp;
+ int copySize = sizeof(serviceInfoType);
+ for(i = 0; i < meta->servicesLen; i++) {
+ //Only filter cluster controllers and storage controllers.
+ if((!strcmp(meta->services[i].type,"cluster") || !strcmp(meta->services[i].type,"storage")) && strcmp(meta->services[i].partition, filter_partition)) {
+ //Not equal, remove by making string len 0.
+ LOGTRACE("Filtering out service: %s , %s\n", meta->services[i].name, meta->services[i].partition);
+
+ //Null the strings.
+ meta->services[i].name[0]='\0';
+ meta->services[i].partition[0]='\0';
+ meta->services[i].type[0]='\0';
+ for(j = 0; j < meta->services[i].urisLen; j++)
+ {
+ meta->services[i].uris[j][0]='\0';
+ }
+ meta->services[i].urisLen = 0;
+
+ //Swap this one and the one at the end and decrement the length.
+ memcpy(&tmp, &(meta->services[i]),copySize);
+ memcpy(&(meta->services[i]),&(meta->services[meta->servicesLen-1]),copySize);
+ memcpy(&(meta->services[meta->servicesLen-1]),&(tmp),copySize);
+ meta->servicesLen--;
+ }
+ }
+}
+
+
//!
//!
//!
@@ -566,6 +600,15 @@ int ncClientCall(ncMetadata * pMeta, int timeout, int ncLock, char *ncURL, char
localmeta->userId = strdup("eucalyptus");
}
+ //TODO: zhill, change this to only be invoked on DescribeInstances and/or DescribeResources?
+ //Update meta from config
+ if(populateOutboundMeta(localmeta)) {
+ LOGERROR("Failed to update output service metadata\n");
+ }
+
+ //Don't need to filter, CC should only have received.
+ //filter_services(localmeta, config->ccStatus.serviceId.partition);
+
close(filedes[0]);
ncs = ncStubCreate(ncURL, NULL, NULL);
if (config->use_wssec) {
@@ -1201,7 +1244,7 @@ int doAttachVolume(ncMetadata * pMeta, char *volumeId, char *instanceId, char *r
LOGINFO("[%s][%s] attaching volume\n", SP(instanceId), SP(volumeId));
LOGDEBUG("invoked: userId=%s, volumeId=%s, instanceId=%s, remoteDev=%s, localDev=%s\n", SP(pMeta ? pMeta->userId : "UNSET"),
- SP(volumeId), SP(instanceId), SP(remoteDev), SP(localDev));
+ SP(volumeId), SP(instanceId), SP(remoteDev), SP(localDev));
if (!volumeId || !instanceId || !remoteDev || !localDev) {
LOGERROR("bad input params\n");
return (1);
@@ -1229,15 +1272,8 @@ int doAttachVolume(ncMetadata * pMeta, char *volumeId, char *instanceId, char *r
timeout = ncGetTimeout(op_start, OP_TIMEOUT, stop - start, i);
timeout = maxint(timeout, ATTACH_VOL_TIMEOUT_SECONDS);
- // pick out the right LUN from the remove device string
- char remoteDevForNC[VERY_BIG_CHAR_BUFFER_SIZE];
- if (get_remoteDevForNC(resourceCacheLocal.resources[i].iqn, remoteDev, remoteDevForNC, sizeof(remoteDevForNC))) {
- LOGERROR("failed to parse remote dev string in request\n");
- rc = 1;
- } else {
- rc = ncClientCall(pMeta, timeout, resourceCacheLocal.resources[i].lockidx, resourceCacheLocal.resources[i].ncURL, "ncAttachVolume",
- instanceId, volumeId, remoteDevForNC, localDev);
- }
+ rc = ncClientCall(pMeta, timeout, resourceCacheLocal.resources[i].lockidx, resourceCacheLocal.resources[i].ncURL, "ncAttachVolume",
+ instanceId, volumeId, remoteDev, localDev);
if (rc) {
ret = 1;
@@ -1276,6 +1312,7 @@ int doDetachVolume(ncMetadata * pMeta, char *volumeId, char *instanceId, char *r
ccInstance *myInstance;
time_t op_start;
ccResourceCache resourceCacheLocal;
+
i = 0;
myInstance = NULL;
op_start = time(NULL);
@@ -1313,15 +1350,8 @@ int doDetachVolume(ncMetadata * pMeta, char *volumeId, char *instanceId, char *r
timeout = ncGetTimeout(op_start, OP_TIMEOUT, stop - start, i);
timeout = maxint(timeout, DETACH_VOL_TIMEOUT_SECONDS);
- // pick out the right LUN from the remove device string
- char remoteDevForNC[VERY_BIG_CHAR_BUFFER_SIZE];
- if (get_remoteDevForNC(resourceCacheLocal.resources[i].iqn, remoteDev, remoteDevForNC, sizeof(remoteDevForNC))) {
- LOGERROR("failed to parse remote dev string in request\n");
- rc = 1;
- } else {
- rc = ncClientCall(pMeta, timeout, resourceCacheLocal.resources[i].lockidx, resourceCacheLocal.resources[i].ncURL, "ncDetachVolume",
- instanceId, volumeId, remoteDevForNC, localDev, force);
- }
+ rc = ncClientCall(pMeta, timeout, resourceCacheLocal.resources[i].lockidx, resourceCacheLocal.resources[i].ncURL, "ncDetachVolume",
+ instanceId, volumeId, remoteDev, localDev, force);
if (rc) {
ret = 1;
} else {
@@ -3467,18 +3497,6 @@ int doRunInstances(ncMetadata * pMeta, char *amiId, char *kernelId, char *ramdis
sem_mypost(CONFIG);
res = &(resourceCache->resources[resid]);
-
- // pick out the right LUN from the long version of the remote device string and create the remote dev string that NC expects
- for (int i = 0; i < EUCA_MAX_VBRS && i < ncvm.virtualBootRecordLen; i++) {
- virtualBootRecord *vbr = &(ncvm.virtualBootRecord[i]);
- if (strcmp(vbr->typeName, "ebs")) // skip all except EBS entries
- continue;
- if (get_remoteDevForNC(res->iqn, vbr->resourceLocationPtr, vbr->resourceLocation, sizeof(vbr->resourceLocation))) {
- LOGERROR("failed to parse remote dev string in VBR[%d]\n", i);
- rc = 1;
- }
- }
-
if (rc) {
// could not find resource
LOGERROR("scheduler could not find resource to run the instance on\n");
@@ -4519,6 +4537,48 @@ int setup_shared_buffer(void **buf, char *bufname, size_t bytes, sem_t ** lock,
return (ret);
}
+//copy from cc config into message metadata.
+