69
69
import java.io.FileInputStream;
70
70
import java.io.FileOutputStream;
71
71
import java.io.IOException;
72
import java.net.InetAddress;
73
72
import java.nio.channels.FileChannel;
73
import java.security.PublicKey;
74
74
import java.util.ArrayList;
75
75
import java.util.List;
77
import javax.crypto.Cipher;
77
79
import org.apache.log4j.Logger;
80
import org.bouncycastle.util.encoders.Base64;
82
import com.eucalyptus.auth.ClusterCredentials;
83
import com.eucalyptus.auth.Credentials;
84
import com.eucalyptus.auth.SystemCredentialProvider;
85
import com.eucalyptus.auth.X509Cert;
79
86
import com.eucalyptus.auth.util.Hashes;
87
import com.eucalyptus.bootstrap.Component;
88
import com.eucalyptus.config.ClusterConfiguration;
80
89
import com.eucalyptus.util.EntityWrapper;
81
90
import com.eucalyptus.util.EucalyptusCloudException;
82
91
import com.eucalyptus.util.ExecutionException;
83
92
import com.eucalyptus.util.StorageProperties;
84
93
import com.eucalyptus.util.WalrusProperties;
86
import edu.ucsb.eucalyptus.cloud.entities.LVMMetaInfo;
95
import edu.ucsb.eucalyptus.cloud.entities.AOEMetaInfo;
96
import edu.ucsb.eucalyptus.cloud.entities.AOEVolumeInfo;
97
import edu.ucsb.eucalyptus.cloud.entities.ISCSIMetaInfo;
98
import edu.ucsb.eucalyptus.cloud.entities.ISCSIVolumeInfo;
87
99
import edu.ucsb.eucalyptus.cloud.entities.LVMVolumeInfo;
100
import edu.ucsb.eucalyptus.cloud.ws.VolumeManager;
88
101
import edu.ucsb.eucalyptus.ic.StorageController;
89
102
import edu.ucsb.eucalyptus.util.StreamConsumer;
90
103
import edu.ucsb.eucalyptus.util.SystemUtil;
92
105
public class LVM2Manager implements LogicalStorageManager {
95
107
public static final String lvmRootDirectory = "/dev";
96
108
public static final String PATH_SEPARATOR = "/";
97
109
public static boolean initialized = false;
98
110
public static final int MAX_LOOP_DEVICES = 256;
99
public static final int MAX_MINOR_NUMBER = 16;
100
111
private static final String blockSize = "1M";
101
112
public static final String EUCA_ROOT_WRAPPER = "/usr/lib/eucalyptus/euca_rootwrap";
102
113
public static final String EUCA_VAR_RUN_PATH = "/var/run/eucalyptus";
103
114
private static Logger LOG = Logger.getLogger(LVM2Manager.class);
104
115
public static String eucaHome = System.getProperty("euca.home");
105
private static final String IFACE_CONFIG_STRING = "VNET_INTERFACE";
106
private static final boolean ifaceDiscovery = false;
107
116
private static final long LVM_HEADER_LENGTH = 4 * StorageProperties.MB;
108
public StorageExportManager exportManager;
117
public static StorageExportManager exportManager;
110
119
public void checkPreconditions() throws EucalyptusCloudException {
111
120
//check if binaries exist, commands can be executed, etc.
324
284
returnValue = removePhysicalVolume(loDevName);
325
285
removeLoopback(loDevName);
326
286
} catch(ExecutionException ex) {
287
volumeManager.abort();
328
288
String error = "Unable to run command: " + ex.getMessage();
329
289
LOG.error(error);
331
db.delete(lvmVolInfo);
291
volumeManager.remove(lvmVolInfo);
292
volumeManager.finish();
336
296
public void cleanSnapshot(String snapshotId) {
337
EntityWrapper<LVMVolumeInfo> db = StorageController.getEntityWrapper();
338
LVMVolumeInfo lvmVolumeInfo = new LVMVolumeInfo(snapshotId);
339
List<LVMVolumeInfo> lvmVolumeInfos = db.query(lvmVolumeInfo);
340
if(lvmVolumeInfos.size() > 0) {
341
LVMVolumeInfo lvmVolInfo = lvmVolumeInfos.get(0);
342
db.delete(lvmVolInfo);
297
VolumeEntityWrapperManager volumeManager = new VolumeEntityWrapperManager();
298
LVMVolumeInfo lvmVolInfo = volumeManager.getVolumeInfo(snapshotId);
299
if(lvmVolInfo != null) {
300
volumeManager.remove(lvmVolInfo);
302
volumeManager.finish();
347
305
public native void registerSignals();
349
private synchronized List<Integer> allocateDeviceNumbers() throws EucalyptusCloudException {
350
int majorNumber = -1;
351
int minorNumber = -1;
352
List<Integer> deviceNumbers = new ArrayList<Integer>();
353
LVMMetaInfo metaInfo = new LVMMetaInfo();
354
EntityWrapper<LVMMetaInfo> db = StorageController.getEntityWrapper();
355
List<LVMMetaInfo> metaInfoList = db.query(metaInfo);
356
if(metaInfoList.size() > 0) {
357
LVMMetaInfo foundMetaInfo = metaInfoList.get(0);
358
majorNumber = foundMetaInfo.getMajorNumber();
359
minorNumber = foundMetaInfo.getMinorNumber();
361
if(minorNumber >= MAX_MINOR_NUMBER - 1) {
364
minorNumber = (minorNumber + 1) % MAX_MINOR_NUMBER;
365
LOG.info("Trying e" + majorNumber + "." + minorNumber);
366
} while(new File(StorageProperties.ETHERD_PREFIX + majorNumber + "." + minorNumber).exists());
367
foundMetaInfo.setMajorNumber(majorNumber);
368
foundMetaInfo.setMinorNumber(minorNumber);
370
deviceNumbers.add(majorNumber);
371
deviceNumbers.add(minorNumber);
373
return deviceNumbers;
376
public int exportVolume(LVMVolumeInfo lvmVolumeInfo, String vgName, String lvName) throws EucalyptusCloudException {
377
List<Integer> deviceNumbers = allocateDeviceNumbers();
378
int majorNumber = deviceNumbers.get(0);
379
int minorNumber = deviceNumbers.get(1);
380
String absoluteLVName = lvmRootDirectory + PATH_SEPARATOR + vgName + PATH_SEPARATOR + lvName;
381
int pid = exportManager.exportVolume(StorageProperties.iface, absoluteLVName, majorNumber, minorNumber);
382
boolean success = false;
383
String returnValue = "";
386
for(int i=0; i < 5; ++i) {
387
returnValue = aoeStatus(pid);
388
if(returnValue.length() == 0) {
391
Thread.sleep(timeout);
392
} catch(InterruptedException ie) {
403
throw new EucalyptusCloudException("Could not export AoE device " + absoluteLVName + " iface: " + StorageProperties.iface + " pid: " + pid + " returnValue: " + returnValue);
406
File vbladePidFile = new File(eucaHome + EUCA_VAR_RUN_PATH + "/vblade-" + majorNumber + minorNumber + ".pid");
407
FileOutputStream fileOutStream = null;
409
fileOutStream = new FileOutputStream(vbladePidFile);
410
String pidString = String.valueOf(pid);
411
fileOutStream.write(pidString.getBytes());
412
} catch (Exception ex) {
413
LOG.error("Could not write pid file vblade-" + majorNumber + minorNumber + ".pid");
415
if(fileOutStream != null)
417
fileOutStream.close();
418
} catch (IOException e) {
422
lvmVolumeInfo.setVbladePid(pid);
423
lvmVolumeInfo.setMajorNumber(majorNumber);
424
lvmVolumeInfo.setMinorNumber(minorNumber);
428
307
public void dupFile(String oldFileName, String newFileName) {
429
308
FileOutputStream fileOutputStream = null;
430
309
FileChannel out = null;
644
522
String snapshotRawFileName = StorageProperties.storageRootDirectory + "/" + snapshotId;
645
523
File snapshotFile = new File(snapshotRawFileName);
646
524
if(snapshotFile.exists()) {
647
EntityWrapper<LVMVolumeInfo> db = StorageController.getEntityWrapper();
648
LVMVolumeInfo lvmVolumeInfo = new LVMVolumeInfo(snapshotId);
525
VolumeEntityWrapperManager volumeManager = new VolumeEntityWrapperManager();
526
LVMVolumeInfo lvmVolumeInfo = volumeManager.getVolumeInfo();
527
lvmVolumeInfo.setVolumeId(snapshotId);
649
528
lvmVolumeInfo.setLoFileName(snapshotRawFileName);
650
529
lvmVolumeInfo.setStatus(StorageProperties.Status.available.toString());
651
530
lvmVolumeInfo.setSize((int)(snapshotFile.length() / StorageProperties.GB));
652
lvmVolumeInfo.setVbladePid(-1);
653
db.add(lvmVolumeInfo);
531
volumeManager.add(lvmVolumeInfo);
532
volumeManager.finish();
656
534
throw new EucalyptusCloudException("Snapshot backing file does not exist for: " + snapshotId);
660
538
public void dupVolume(String volumeId, String dupVolumeId) throws EucalyptusCloudException {
661
EntityWrapper<LVMVolumeInfo> db = StorageController.getEntityWrapper();
662
LVMVolumeInfo lvmVolumeInfo = new LVMVolumeInfo(volumeId);
663
LVMVolumeInfo foundVolumeInfo = db.getUnique(lvmVolumeInfo);
539
VolumeEntityWrapperManager volumeManager = new VolumeEntityWrapperManager();
541
LVMVolumeInfo foundVolumeInfo = volumeManager.getVolumeInfo(volumeId);
664
542
if(foundVolumeInfo != null) {
665
543
String vgName = "vg-" + Hashes.getRandom(4);
666
544
String lvName = "lv-" + Hashes.getRandom(4);
667
lvmVolumeInfo = new LVMVolumeInfo();
545
LVMVolumeInfo lvmVolumeInfo = volumeManager.getVolumeInfo();
669
547
File volumeFile = new File(StorageProperties.storageRootDirectory + PATH_SEPARATOR + foundVolumeInfo.getVolumeId());
688
566
lvmVolumeInfo.setLvName(lvName);
689
567
lvmVolumeInfo.setStatus(StorageProperties.Status.available.toString());
690
568
lvmVolumeInfo.setSize(size);
691
lvmVolumeInfo.setVbladePid(-1);
692
db.add(lvmVolumeInfo);
569
volumeManager.add(lvmVolumeInfo);
570
volumeManager.finish();
694
571
} catch(ExecutionException ex) {
572
volumeManager.abort();
696
573
String error = "Unable to run command: " + ex.getMessage();
697
574
LOG.error(error);
698
575
throw new EucalyptusCloudException(error);
578
volumeManager.abort();
702
579
throw new EucalyptusCloudException("Could not dup volume " + volumeId);
707
584
public List<String> getStatus(List<String> volumeSet) throws EucalyptusCloudException {
708
EntityWrapper<LVMVolumeInfo> db = StorageController.getEntityWrapper();
585
VolumeEntityWrapperManager volumeManager = new VolumeEntityWrapperManager();
709
586
ArrayList<String> status = new ArrayList<String>();
710
587
for(String volumeSetEntry: volumeSet) {
711
LVMVolumeInfo lvmVolumeInfo = new LVMVolumeInfo();
712
lvmVolumeInfo.setVolumeId(volumeSetEntry);
713
LVMVolumeInfo foundLvmVolumeInfo = db.getUnique(lvmVolumeInfo);
714
if(foundLvmVolumeInfo != null) {
715
status.add(foundLvmVolumeInfo.getStatus());
588
LVMVolumeInfo lvmVolumeInfo = volumeManager.getVolumeInfo(volumeSetEntry);
589
if(lvmVolumeInfo != null) {
590
status.add(lvmVolumeInfo.getStatus());
592
volumeManager.abort();
718
593
throw new EucalyptusCloudException("Unable to find entry: " + volumeSetEntry);
596
volumeManager.finish();
725
600
public void deleteVolume(String volumeId) throws EucalyptusCloudException {
726
EntityWrapper<LVMVolumeInfo> db = StorageController.getEntityWrapper();
727
LVMVolumeInfo lvmVolumeInfo = new LVMVolumeInfo(volumeId);
728
LVMVolumeInfo foundLVMVolumeInfo = db.getUnique(lvmVolumeInfo);
601
VolumeEntityWrapperManager volumeManager = new VolumeEntityWrapperManager();
602
LVMVolumeInfo foundLVMVolumeInfo = volumeManager.getVolumeInfo(volumeId);
730
603
if(foundLVMVolumeInfo != null) {
731
604
//remove aoe export
732
605
String loDevName = foundLVMVolumeInfo.getLoDevName();
733
606
String vgName = foundLVMVolumeInfo.getVgName();
734
607
String lvName = foundLVMVolumeInfo.getLvName();
735
608
String absoluteLVName = lvmRootDirectory + PATH_SEPARATOR + vgName + PATH_SEPARATOR + lvName;
738
Integer pid = foundLVMVolumeInfo.getVbladePid();
740
String returnValue = aoeStatus(pid);
741
if(returnValue.length() > 0) {
742
exportManager.unexportVolume(pid);
743
int majorNumber = foundLVMVolumeInfo.getMajorNumber();
744
int minorNumber = foundLVMVolumeInfo.getMinorNumber();
745
File vbladePidFile = new File(eucaHome + EUCA_VAR_RUN_PATH + "/vblade-" + majorNumber + minorNumber + ".pid");
746
if(vbladePidFile.exists()) {
747
vbladePidFile.delete();
609
volumeManager.unexportVolume(foundLVMVolumeInfo);
752
611
String returnValue = removeLogicalVolume(absoluteLVName);
753
612
if(returnValue.length() == 0) {
825
683
snapshotInfo.setLoFileName(snapRawFileName);
826
684
snapshotInfo.setStatus(StorageProperties.Status.available.toString());
827
snapshotInfo.setVbladePid(-1);
828
685
snapshotInfo.setSize(size);
829
686
returnValues.add(vgName);
830
687
returnValues.add(lvName);
831
db.add(snapshotInfo);
688
volumeManager.add(snapshotInfo);
832
689
} catch(ExecutionException ex) {
690
volumeManager.abort();
834
691
String error = "Unable to run command: " + ex.getMessage();
835
692
LOG.error(error);
836
693
throw new EucalyptusCloudException(error);
697
volumeManager.finish();
841
698
return returnValues;
844
701
public List<String> prepareForTransfer(String snapshotId) throws EucalyptusCloudException {
845
EntityWrapper<LVMVolumeInfo> db = StorageController.getEntityWrapper();
846
LVMVolumeInfo lvmVolumeInfo = new LVMVolumeInfo(snapshotId);
847
LVMVolumeInfo foundLVMVolumeInfo = db.getUnique(lvmVolumeInfo);
702
VolumeEntityWrapperManager volumeManager = new VolumeEntityWrapperManager();
703
LVMVolumeInfo foundLVMVolumeInfo = volumeManager.getVolumeInfo(snapshotId);
848
704
ArrayList<String> returnValues = new ArrayList<String>();
850
706
if(foundLVMVolumeInfo != null) {
851
707
returnValues.add(StorageProperties.storageRootDirectory + PATH_SEPARATOR + foundLVMVolumeInfo.getVolumeId());
708
volumeManager.finish();
710
volumeManager.abort();
855
711
throw new EucalyptusCloudException("Unable to find snapshot: " + snapshotId);
857
713
return returnValues;
860
716
public void deleteSnapshot(String snapshotId) throws EucalyptusCloudException {
861
EntityWrapper<LVMVolumeInfo> db = StorageController.getEntityWrapper();
862
LVMVolumeInfo lvmVolumeInfo = new LVMVolumeInfo(snapshotId);
863
LVMVolumeInfo foundLVMVolumeInfo = db.getUnique(lvmVolumeInfo);
717
VolumeEntityWrapperManager volumeManager = new VolumeEntityWrapperManager();
718
LVMVolumeInfo foundLVMVolumeInfo = volumeManager.getVolumeInfo(snapshotId);
865
720
if(foundLVMVolumeInfo != null) {
866
db.delete(foundLVMVolumeInfo);
721
volumeManager.remove(foundLVMVolumeInfo);
723
volumeManager.abort();
870
724
throw new EucalyptusCloudException("Unable to find snapshot: " + snapshotId);
726
volumeManager.finish();
874
public List<String> getVolume(String volumeId) throws EucalyptusCloudException {
875
ArrayList<String> returnValues = new ArrayList<String>();
877
EntityWrapper<LVMVolumeInfo> db = StorageController.getEntityWrapper();
878
LVMVolumeInfo lvmVolumeInfo = new LVMVolumeInfo(volumeId);
879
List<LVMVolumeInfo> foundLvmVolumeInfos = db.query(lvmVolumeInfo);
880
if(foundLvmVolumeInfos.size() > 0) {
881
LVMVolumeInfo foundLvmVolumeInfo = foundLvmVolumeInfos.get(0);
882
returnValues.add(String.valueOf(foundLvmVolumeInfo.getMajorNumber()));
883
returnValues.add(String.valueOf(foundLvmVolumeInfo.getMinorNumber()));
729
public String getVolumeProperty(String volumeId) throws EucalyptusCloudException {
730
VolumeEntityWrapperManager volumeManager = new VolumeEntityWrapperManager();
731
String returnValue = volumeManager.getVolumeProperty(volumeId);
732
volumeManager.finish();
889
736
public void loadSnapshots(List<String> snapshotSet, List<String> snapshotFileNames) throws EucalyptusCloudException {
890
EntityWrapper<LVMVolumeInfo> db = StorageController.getEntityWrapper();
737
VolumeEntityWrapperManager volumeManager = new VolumeEntityWrapperManager();
891
738
assert(snapshotSet.size() == snapshotFileNames.size());
893
740
for(String snapshotFileName: snapshotFileNames) {
895
742
String loDevName = createLoopback(snapshotFileName);
896
LVMVolumeInfo lvmVolumeInfo = new LVMVolumeInfo(snapshotSet.get(i++));
743
LVMVolumeInfo lvmVolumeInfo = volumeManager.getVolumeInfo();
744
lvmVolumeInfo.setVolumeId(snapshotSet.get(i++));
897
745
lvmVolumeInfo.setLoDevName(loDevName);
898
lvmVolumeInfo.setMajorNumber(-1);
899
lvmVolumeInfo.setMinorNumber(-1);
900
746
lvmVolumeInfo.setStatus(StorageProperties.Status.available.toString());
901
db.add(lvmVolumeInfo);
747
volumeManager.add(lvmVolumeInfo);
902
748
} catch(ExecutionException ex) {
749
volumeManager.abort();
904
750
String error = "Unable to run command: " + ex.getMessage();
905
751
LOG.error(error);
906
752
throw new EucalyptusCloudException(error);
756
volumeManager.finish();
913
759
public void reload() {
914
EntityWrapper<LVMVolumeInfo> db = StorageController.getEntityWrapper();
915
LVMVolumeInfo volumeInfo = new LVMVolumeInfo();
916
List<LVMVolumeInfo> volumeInfos = db.query(volumeInfo);
760
VolumeEntityWrapperManager volumeManager = new VolumeEntityWrapperManager();
761
List<LVMVolumeInfo> volumeInfos = volumeManager.getAllVolumeInfos();
917
762
for(LVMVolumeInfo foundVolumeInfo : volumeInfos) {
918
763
String loDevName = foundVolumeInfo.getLoDevName();
919
764
if(loDevName != null) {
939
783
//now enable them
940
784
for(LVMVolumeInfo foundVolumeInfo : volumeInfos) {
941
int pid = foundVolumeInfo.getVbladePid();
943
//enable logical volumes
944
String absoluteLVName = lvmRootDirectory + PATH_SEPARATOR + foundVolumeInfo.getVgName() + PATH_SEPARATOR + foundVolumeInfo.getLvName();
946
enableLogicalVolume(absoluteLVName);
947
} catch(ExecutionException ex) {
948
String error = "Unable to run command: " + ex.getMessage();
952
String returnValue = aoeStatus(pid);
953
if(returnValue.length() == 0) {
954
int majorNumber = foundVolumeInfo.getMajorNumber();
955
int minorNumber = foundVolumeInfo.getMinorNumber();
956
pid = exportManager.exportVolume(StorageProperties.iface, absoluteLVName, majorNumber, minorNumber);
957
foundVolumeInfo.setVbladePid(pid);
958
File vbladePidFile = new File(eucaHome + EUCA_VAR_RUN_PATH + "/vblade-" + majorNumber + minorNumber + ".pid");
959
FileOutputStream fileOutStream = null;
961
fileOutStream = new FileOutputStream(vbladePidFile);
962
String pidString = String.valueOf(pid);
963
fileOutStream.write(pidString.getBytes());
964
fileOutStream.close();
965
} catch (Exception ex) {
966
if(fileOutStream != null)
968
fileOutStream.close();
969
} catch (IOException e) {
972
LOG.error("Could not write pid file vblade-" + majorNumber + minorNumber + ".pid");
786
volumeManager.exportVolume(foundVolumeInfo);
787
} catch(EucalyptusCloudException ex) {
788
LOG.error("Unable to reload volume: " + foundVolumeInfo.getVolumeId() + ex);
791
volumeManager.finish();
980
794
public List<String> getSnapshotValues(String snapshotId) throws EucalyptusCloudException {
981
ArrayList<String> returnValues = new ArrayList<String>();
983
EntityWrapper<LVMVolumeInfo> db = StorageController.getEntityWrapper();
984
LVMVolumeInfo lvmVolumeInfo = new LVMVolumeInfo(snapshotId);
985
List<LVMVolumeInfo> lvmVolumeInfos = db.query(lvmVolumeInfo);
986
if(lvmVolumeInfos.size() > 0) {
987
LVMVolumeInfo foundLVMVolumeInfo = lvmVolumeInfos.get(0);
988
returnValues.add(foundLVMVolumeInfo.getVgName());
989
returnValues.add(foundLVMVolumeInfo.getLvName());
795
VolumeEntityWrapperManager volumeManager = new VolumeEntityWrapperManager();
796
List<String> returnValues = volumeManager.getSnapshotValues(snapshotId);
797
volumeManager.finish();
992
798
return returnValues;
995
801
public int getSnapshotSize(String snapshotId) throws EucalyptusCloudException {
996
EntityWrapper<LVMVolumeInfo> db = StorageController.getEntityWrapper();
997
LVMVolumeInfo lvmVolumeInfo = new LVMVolumeInfo(snapshotId);
998
List<LVMVolumeInfo> lvmVolumeInfos = db.query(lvmVolumeInfo);
999
if(lvmVolumeInfos.size() > 0) {
1000
LVMVolumeInfo foundLVMVolumeInfo = lvmVolumeInfos.get(0);
1001
int snapSize = foundLVMVolumeInfo.getSize();
802
VolumeEntityWrapperManager volumeManager = new VolumeEntityWrapperManager();
803
LVMVolumeInfo lvmVolumeInfo = volumeManager.getVolumeInfo(snapshotId);
804
if(lvmVolumeInfo != null) {
805
int snapSize = lvmVolumeInfo.getSize();
806
volumeManager.finish();
1003
807
return snapSize;
809
volumeManager.abort();
1033
837
return returnString;
840
private class VolumeEntityWrapperManager {
841
private EntityWrapper entityWrapper;
843
private VolumeEntityWrapperManager() {
844
entityWrapper = StorageController.getEntityWrapper();
847
public List<String> getSnapshotValues(String snapshotId) {
848
ArrayList<String> returnValues = new ArrayList<String>();
849
LVMVolumeInfo lvmVolumeInfo = getVolumeInfo(snapshotId);
850
if(lvmVolumeInfo instanceof AOEVolumeInfo) {
851
returnValues.add(lvmVolumeInfo.getVgName());
852
returnValues.add(lvmVolumeInfo.getLvName());
857
public void exportVolume(LVMVolumeInfo lvmVolumeInfo) throws EucalyptusCloudException {
858
if(exportManager instanceof AOEManager) {
859
AOEVolumeInfo aoeVolumeInfo = (AOEVolumeInfo) lvmVolumeInfo;
861
int pid = aoeVolumeInfo.getVbladePid();
863
//enable logical volumes
864
String absoluteLVName = lvmRootDirectory + PATH_SEPARATOR + aoeVolumeInfo.getVgName() + PATH_SEPARATOR + aoeVolumeInfo.getLvName();
866
enableLogicalVolume(absoluteLVName);
867
} catch(ExecutionException ex) {
868
String error = "Unable to run command: " + ex.getMessage();
872
String returnValue = aoeStatus(pid);
873
if(returnValue.length() == 0) {
874
int majorNumber = aoeVolumeInfo.getMajorNumber();
875
int minorNumber = aoeVolumeInfo.getMinorNumber();
876
pid = exportManager.exportVolume(StorageProperties.iface, absoluteLVName, majorNumber, minorNumber);
877
aoeVolumeInfo.setVbladePid(pid);
878
File vbladePidFile = new File(eucaHome + EUCA_VAR_RUN_PATH + "/vblade-" + majorNumber + minorNumber + ".pid");
879
FileOutputStream fileOutStream = null;
881
fileOutStream = new FileOutputStream(vbladePidFile);
882
String pidString = String.valueOf(pid);
883
fileOutStream.write(pidString.getBytes());
884
fileOutStream.close();
885
} catch (Exception ex) {
886
if(fileOutStream != null)
888
fileOutStream.close();
889
} catch (IOException e) {
892
LOG.error("Could not write pid file vblade-" + majorNumber + minorNumber + ".pid");
896
} else if(exportManager instanceof ISCSIManager) {
897
ISCSIVolumeInfo iscsiVolumeInfo = (ISCSIVolumeInfo) lvmVolumeInfo;
898
String password = Hashes.getRandom(16);
899
iscsiVolumeInfo.setEncryptedPassword(encryptTargetPassword(password));
900
String absoluteLVName = lvmRootDirectory + PATH_SEPARATOR + iscsiVolumeInfo.getVgName() + PATH_SEPARATOR + iscsiVolumeInfo.getLvName();
901
((ISCSIManager)exportManager).exportTarget(iscsiVolumeInfo.getTid(), iscsiVolumeInfo.getStoreName(), iscsiVolumeInfo.getLun(), absoluteLVName, iscsiVolumeInfo.getStoreUser(), password);
905
public String getVolumeProperty(String volumeId) {
906
LVMVolumeInfo lvmVolumeInfo = getVolumeInfo(volumeId);
907
if(lvmVolumeInfo != null) {
908
if(exportManager instanceof AOEManager) {
909
AOEVolumeInfo aoeVolumeInfo = (AOEVolumeInfo) lvmVolumeInfo;
910
return StorageProperties.ETHERD_PREFIX + aoeVolumeInfo.getMajorNumber() + "." + aoeVolumeInfo.getMinorNumber();
911
} else if(exportManager instanceof ISCSIManager) {
912
ISCSIVolumeInfo iscsiVolumeInfo = (ISCSIVolumeInfo) lvmVolumeInfo;
913
String storeName = iscsiVolumeInfo.getStoreName();
914
String encryptedPassword = iscsiVolumeInfo.getEncryptedPassword();
915
return StorageProperties.STORAGE_HOST + "," + storeName + "," + encryptedPassword;
921
public void unexportVolume(LVMVolumeInfo volumeInfo) {
922
if(volumeInfo instanceof AOEVolumeInfo) {
923
AOEVolumeInfo aoeVolumeInfo = (AOEVolumeInfo) volumeInfo;
924
int pid = aoeVolumeInfo.getVbladePid();
926
String returnValue = aoeStatus(pid);
927
if(returnValue.length() > 0) {
928
exportManager.unexportVolume(pid);
929
int majorNumber = aoeVolumeInfo.getMajorNumber();
930
int minorNumber = aoeVolumeInfo.getMinorNumber();
931
File vbladePidFile = new File(eucaHome + EUCA_VAR_RUN_PATH + "/vblade-" + majorNumber + minorNumber + ".pid");
932
if(vbladePidFile.exists()) {
933
vbladePidFile.delete();
937
} else if(volumeInfo instanceof ISCSIVolumeInfo) {
938
ISCSIVolumeInfo iscsiVolumeInfo = (ISCSIVolumeInfo) volumeInfo;
939
((ISCSIManager)exportManager).unexportTarget(iscsiVolumeInfo.getTid(), iscsiVolumeInfo.getLun());
943
private void finish() {
944
entityWrapper.commit();
947
private void abort() {
948
entityWrapper.rollback();
952
private LVMVolumeInfo getVolumeInfo(String volumeId) {
953
if(exportManager instanceof AOEManager) {
954
AOEVolumeInfo AOEVolumeInfo = new AOEVolumeInfo(volumeId);
955
List<AOEVolumeInfo> AOEVolumeInfos = entityWrapper.query(AOEVolumeInfo);
956
if(AOEVolumeInfos.size() > 0) {
957
return AOEVolumeInfos.get(0);
959
} else if(exportManager instanceof ISCSIManager) {
960
ISCSIVolumeInfo ISCSIVolumeInfo = new ISCSIVolumeInfo(volumeId);
961
List<ISCSIVolumeInfo> ISCSIVolumeInfos = entityWrapper.query(ISCSIVolumeInfo);
962
if(ISCSIVolumeInfos.size() > 0) {
963
return ISCSIVolumeInfos.get(0);
969
private LVMVolumeInfo getVolumeInfo() {
970
if(exportManager instanceof AOEManager) {
971
AOEVolumeInfo aoeVolumeInfo = new AOEVolumeInfo();
972
aoeVolumeInfo.setVbladePid(-1);
973
aoeVolumeInfo.setMajorNumber(-1);
974
aoeVolumeInfo.setMinorNumber(-1);
975
return aoeVolumeInfo;
976
} else if(exportManager instanceof ISCSIManager) {
977
return new ISCSIVolumeInfo();
982
private List<LVMVolumeInfo> getAllVolumeInfos() {
983
if(exportManager instanceof AOEManager) {
984
AOEVolumeInfo AOEVolumeInfo = new AOEVolumeInfo();
985
return entityWrapper.query(AOEVolumeInfo);
986
} else if(exportManager instanceof ISCSIManager) {
987
ISCSIVolumeInfo ISCSIVolumeInfo = new ISCSIVolumeInfo();
988
return entityWrapper.query(ISCSIVolumeInfo);
993
private void add(LVMVolumeInfo volumeInfo) {
994
entityWrapper.add(volumeInfo);
997
private void remove(LVMVolumeInfo volumeInfo) {
998
entityWrapper.delete(volumeInfo);
1001
private String encryptTargetPassword(String password) throws EucalyptusCloudException {
1002
EntityWrapper<ClusterCredentials> credDb = Credentials.getEntityWrapper( );
1004
ClusterCredentials credentials = credDb.getUnique( new ClusterCredentials( StorageProperties.NAME ) );
1005
PublicKey ncPublicKey = X509Cert.toCertificate(credentials.getNodeCertificate()).getPublicKey();
1007
Cipher cipher = Cipher.getInstance("RSA/ECB/PKCS1Padding");
1008
cipher.init(Cipher.ENCRYPT_MODE, ncPublicKey);
1009
return new String(Base64.encode(cipher.doFinal(password.getBytes())));
1010
} catch ( Exception e ) {
1011
LOG.error( "Unable to encrypt storage target password" );
1013
throw new EucalyptusCloudException(e.getMessage(), e);
1017
private int exportVolume(LVMVolumeInfo lvmVolumeInfo, String vgName, String lvName) throws EucalyptusCloudException {
1018
if(exportManager instanceof AOEManager) {
1019
AOEVolumeInfo aoeVolumeInfo = (AOEVolumeInfo) lvmVolumeInfo;
1020
exportManager.allocateTarget(aoeVolumeInfo);
1021
int majorNumber = aoeVolumeInfo.getMajorNumber();
1022
int minorNumber = aoeVolumeInfo.getMinorNumber();
1023
String absoluteLVName = lvmRootDirectory + PATH_SEPARATOR + vgName + PATH_SEPARATOR + lvName;
1024
int pid = exportManager.exportVolume(StorageProperties.iface, absoluteLVName, majorNumber, minorNumber);
1025
boolean success = false;
1026
String returnValue = "";
1029
for(int i=0; i < 5; ++i) {
1030
returnValue = aoeStatus(pid);
1031
if(returnValue.length() == 0) {
1034
Thread.sleep(timeout);
1035
} catch(InterruptedException ie) {
1046
throw new EucalyptusCloudException("Could not export AoE device " + absoluteLVName + " iface: " + StorageProperties.iface + " pid: " + pid + " returnValue: " + returnValue);
1049
File vbladePidFile = new File(eucaHome + EUCA_VAR_RUN_PATH + "/vblade-" + majorNumber + minorNumber + ".pid");
1050
FileOutputStream fileOutStream = null;
1052
fileOutStream = new FileOutputStream(vbladePidFile);
1053
String pidString = String.valueOf(pid);
1054
fileOutStream.write(pidString.getBytes());
1055
} catch (Exception ex) {
1056
LOG.error("Could not write pid file vblade-" + majorNumber + minorNumber + ".pid");
1058
if(fileOutStream != null)
1060
fileOutStream.close();
1061
} catch (IOException e) {
1066
throw new EucalyptusCloudException("invalid vblade pid: " + pid);
1067
aoeVolumeInfo.setVbladePid(pid);
1069
} else if(exportManager instanceof ISCSIManager) {
1070
ISCSIVolumeInfo iscsiVolumeInfo = (ISCSIVolumeInfo) lvmVolumeInfo;
1071
exportManager.allocateTarget(iscsiVolumeInfo);
1072
String password = Hashes.getRandom(16);
1073
iscsiVolumeInfo.setEncryptedPassword(encryptTargetPassword(password));
1074
String absoluteLVName = lvmRootDirectory + PATH_SEPARATOR + vgName + PATH_SEPARATOR + lvName;
1075
((ISCSIManager)exportManager).exportTarget(iscsiVolumeInfo.getTid(), iscsiVolumeInfo.getStoreName(), iscsiVolumeInfo.getLun(), absoluteLVName, iscsiVolumeInfo.getStoreUser(), password);