~ubuntu-branches/ubuntu/natty/eucalyptus/natty-updates

« back to all changes in this revision

Viewing changes to clc/modules/storage-controller/src/main/java/edu/ucsb/eucalyptus/storage/LVM2Manager.java

  • Committer: Bazaar Package Importer
  • Author(s): Dustin Kirkland
  • Date: 2009-12-17 18:22:02 UTC
  • mto: This revision was merged to the branch mainline in revision 83.
  • Revision ID: james.westby@ubuntu.com-20091217182202-0v2v09ry3cxrvh84
Tags: upstream-1.6.2~bzr1103
ImportĀ upstreamĀ versionĀ 1.6.2~bzr1103

Show diffs side-by-side

added added

removed removed

Lines of Context:
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;
76
76
 
 
77
import javax.crypto.Cipher;
 
78
 
77
79
import org.apache.log4j.Logger;
 
80
import org.bouncycastle.util.encoders.Base64;
78
81
 
 
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;
85
94
 
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;
91
104
 
92
105
public class LVM2Manager implements LogicalStorageManager {
93
106
 
94
 
 
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;
109
118
 
110
119
        public void checkPreconditions() throws EucalyptusCloudException {
111
120
                //check if binaries exist, commands can be executed, etc.
128
137
                        } else {
129
138
                                LOG.info(returnValue);
130
139
                        }
131
 
                        returnValue = getVblade();
132
 
                        if(returnValue.length() == 0) {
133
 
                                throw new EucalyptusCloudException("vblade not found: Is it installed?");
 
140
                        if(System.getProperty("euca.disable.iscsi") != null) {
 
141
                                exportManager = new AOEManager();
134
142
                        } else {
135
 
                                LOG.info(returnValue);
 
143
                                exportManager = new ISCSIManager();
136
144
                        }
 
145
                        exportManager.checkPreconditions();
137
146
                } catch(ExecutionException ex) {
138
147
                        String error = "Unable to run command: " + ex.getMessage();
139
148
                        LOG.error(error);
177
186
                return SystemUtil.run(new String[]{eucaHome + EUCA_ROOT_WRAPPER, "lvremove", "-f", lvName});
178
187
        }
179
188
 
180
 
        private String disableLogicalVolume(String lvName) throws ExecutionException {
181
 
                return SystemUtil.run(new String[]{eucaHome + EUCA_ROOT_WRAPPER, "lvchange", "-an", lvName});
182
 
        }
183
 
 
184
189
        private String removeVolumeGroup(String vgName) throws ExecutionException {
185
190
                return SystemUtil.run(new String[]{eucaHome + EUCA_ROOT_WRAPPER, "vgremove", vgName});
186
191
        }
197
202
                return SystemUtil.run(new String[]{eucaHome + EUCA_ROOT_WRAPPER, "vgreduce", vgName, pvName});
198
203
        }
199
204
 
200
 
        private String suspendDevice(String deviceName) throws ExecutionException {
201
 
                return SystemUtil.run(new String[]{eucaHome + EUCA_ROOT_WRAPPER, "dmsetup", "-v", "suspend", deviceName});
202
 
        }
203
 
 
204
 
        private String resumeDevice(String deviceName) throws ExecutionException {
205
 
                return SystemUtil.run(new String[]{eucaHome + EUCA_ROOT_WRAPPER, "dmsetup", "-v", "resume", deviceName});
206
 
        }
207
 
 
208
 
        private String getAoEStatus(String pid) throws ExecutionException {
209
 
                return SystemUtil.run(new String[]{eucaHome + EUCA_ROOT_WRAPPER, "cat", "/proc/", pid, "/cmdline"});
210
 
        }
211
 
 
212
205
        private String enableLogicalVolume(String lvName) throws ExecutionException {
213
206
                return SystemUtil.run(new String[]{eucaHome + EUCA_ROOT_WRAPPER, "lvchange", "-ay", lvName});
214
207
        }
215
208
 
216
 
        private String getVblade() throws ExecutionException {
217
 
                return SystemUtil.run(new String[]{eucaHome + EUCA_ROOT_WRAPPER, "which", "vblade"});
218
 
        }
219
 
 
220
209
        private int losetup(String absoluteFileName, String loDevName) {
221
210
                try
222
211
                {
263
252
        public void initialize() {
264
253
                if(!initialized) {
265
254
                        System.loadLibrary("lvm2control");
266
 
                        exportManager = new AOEManager();
267
255
                        initialized = true;
268
256
                }
269
257
        }
270
258
 
271
259
        public void configure() {
272
 
                try {
273
 
                        EntityWrapper<LVMMetaInfo> db = StorageController.getEntityWrapper();
274
 
                        LVMMetaInfo metaInfo = new LVMMetaInfo();
275
 
                        List<LVMMetaInfo> metaInfoList = db.query(metaInfo);
276
 
                        if(metaInfoList.size() <= 0) {
277
 
                                metaInfo.setHostName(StorageProperties.NAME);
278
 
                                metaInfo.setMajorNumber(0);
279
 
                                metaInfo.setMinorNumber(0);
280
 
                                db.add(metaInfo);
281
 
                        }
282
 
                        db.commit();
283
 
                } catch(Exception ex) {
284
 
                        ex.printStackTrace();
285
 
                }
 
260
                exportManager.configure();
286
261
        }
287
262
 
288
263
        public void startupChecks() {
294
269
        }
295
270
 
296
271
        public void cleanVolume(String volumeId) {
297
 
                EntityWrapper<LVMVolumeInfo> db = StorageController.getEntityWrapper();
298
 
                LVMVolumeInfo lvmVolumeInfo = new LVMVolumeInfo(volumeId);
299
 
                List<LVMVolumeInfo> lvmVolumeInfos = db.query(lvmVolumeInfo);
300
 
                if(lvmVolumeInfos.size() > 0) {
301
 
                        LVMVolumeInfo lvmVolInfo = lvmVolumeInfos.get(0);
302
 
                        //remove aoe export
 
272
                VolumeEntityWrapperManager volumeManager = new VolumeEntityWrapperManager();
 
273
                LVMVolumeInfo lvmVolInfo = volumeManager.getVolumeInfo(volumeId);
 
274
                if(lvmVolInfo != null) {
303
275
                        String loDevName = lvmVolInfo.getLoDevName();
304
 
                        int pid = lvmVolInfo.getVbladePid();
305
 
                        if(pid > 0) {
306
 
                                String returnValue = aoeStatus(pid);
307
 
                                if(returnValue.length() > 0) {
308
 
                                        exportManager.unexportVolume(pid);
309
 
                                        int majorNumber = lvmVolInfo.getMajorNumber();
310
 
                                        int minorNumber = lvmVolInfo.getMinorNumber();
311
 
                                        File vbladePidFile = new File(eucaHome + EUCA_VAR_RUN_PATH + "/vblade-" + majorNumber + minorNumber + ".pid");
312
 
                                        if(vbladePidFile.exists()) {
313
 
                                                vbladePidFile.delete();
314
 
                                        }
315
 
                                }
316
 
                        }
 
276
                        volumeManager.unexportVolume(lvmVolInfo);
317
277
                        String vgName = lvmVolInfo.getVgName();
318
278
                        String lvName = lvmVolInfo.getLvName();
319
279
                        String absoluteLVName = lvmRootDirectory + PATH_SEPARATOR + vgName + PATH_SEPARATOR + lvName;
324
284
                                returnValue = removePhysicalVolume(loDevName);
325
285
                                removeLoopback(loDevName);
326
286
                        } catch(ExecutionException ex) {
327
 
                                db.rollback();
 
287
                                volumeManager.abort();
328
288
                                String error = "Unable to run command: " + ex.getMessage();
329
289
                                LOG.error(error);
330
290
                        }
331
 
                        db.delete(lvmVolInfo);
332
 
                        db.commit();
 
291
                        volumeManager.remove(lvmVolInfo);
 
292
                        volumeManager.finish();
333
293
                }
334
294
        }
335
295
 
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);
343
 
                        db.commit();
 
297
                VolumeEntityWrapperManager volumeManager = new VolumeEntityWrapperManager();
 
298
                LVMVolumeInfo lvmVolInfo = volumeManager.getVolumeInfo(snapshotId);
 
299
                if(lvmVolInfo != null) {
 
300
                        volumeManager.remove(lvmVolInfo);
344
301
                }
 
302
                volumeManager.finish();
345
303
        }
346
304
 
347
305
        public native void registerSignals();
348
306
 
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();
360
 
                        do {
361
 
                                if(minorNumber >= MAX_MINOR_NUMBER - 1) {
362
 
                                        ++majorNumber;
363
 
                                }
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);
369
 
                }
370
 
                deviceNumbers.add(majorNumber);
371
 
                deviceNumbers.add(minorNumber);
372
 
                db.commit();
373
 
                return deviceNumbers;
374
 
        }
375
 
 
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 = "";
384
 
                int timeout = 300;
385
 
                if(pid > 0) {
386
 
                        for(int i=0; i < 5; ++i) {
387
 
                                returnValue = aoeStatus(pid);
388
 
                                if(returnValue.length() == 0) {
389
 
                                        success = false;
390
 
                                        try {
391
 
                                                Thread.sleep(timeout);
392
 
                                        } catch(InterruptedException ie) {
393
 
                                                LOG.error(ie);
394
 
                                        }
395
 
                                        timeout += 300;
396
 
                                } else {
397
 
                                        success = true;
398
 
                                        break;
399
 
                                }
400
 
                        }
401
 
                }
402
 
                if(!success) {
403
 
                        throw new EucalyptusCloudException("Could not export AoE device " + absoluteLVName + " iface: " + StorageProperties.iface + " pid: " + pid + " returnValue: " + returnValue);
404
 
                }
405
 
 
406
 
                File vbladePidFile = new File(eucaHome + EUCA_VAR_RUN_PATH + "/vblade-" + majorNumber + minorNumber + ".pid");
407
 
                FileOutputStream fileOutStream = null;
408
 
                try {
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");
414
 
                } finally {
415
 
                        if(fileOutStream != null)
416
 
                                try {
417
 
                                        fileOutStream.close();
418
 
                                } catch (IOException e) {
419
 
                                        LOG.error(e);
420
 
                                }
421
 
                }
422
 
                lvmVolumeInfo.setVbladePid(pid);
423
 
                lvmVolumeInfo.setMajorNumber(majorNumber);
424
 
                lvmVolumeInfo.setMinorNumber(minorNumber);
425
 
                return pid;
426
 
        }
427
 
 
428
307
        public void dupFile(String oldFileName, String newFileName) {
429
308
                FileOutputStream fileOutputStream = null;
430
309
                FileChannel out = null;
535
414
        public void createVolume(String volumeId, int size) throws EucalyptusCloudException {
536
415
                File volumeDir = new File(StorageProperties.storageRootDirectory);
537
416
                volumeDir.mkdirs();
 
417
                VolumeEntityWrapperManager volumeManager = new VolumeEntityWrapperManager();
538
418
 
539
419
                String vgName = "vg-" + Hashes.getRandom(4);
540
420
                String lvName = "lv-" + Hashes.getRandom(4);
541
 
                LVMVolumeInfo lvmVolumeInfo = new LVMVolumeInfo();
 
421
                LVMVolumeInfo lvmVolumeInfo = null;
 
422
                if(exportManager instanceof AOEManager) {
 
423
                        lvmVolumeInfo = new AOEVolumeInfo();
 
424
                } else {
 
425
                        lvmVolumeInfo = new ISCSIVolumeInfo();
 
426
                }
542
427
 
543
428
                String rawFileName = StorageProperties.storageRootDirectory + "/" + volumeId;
544
429
                //create file and attach to loopback device
549
434
                        createLogicalVolume(loDevName, vgName, lvName);
550
435
                        //export logical volume
551
436
                        try {
552
 
                                int vbladePid = exportVolume(lvmVolumeInfo, vgName, lvName);
553
 
                                if(vbladePid < 0) {
554
 
                                        throw new EucalyptusCloudException("Unable to export volume: " + volumeId);
555
 
                                }
 
437
                                volumeManager.exportVolume(lvmVolumeInfo, vgName, lvName);
556
438
                        } catch(EucalyptusCloudException ex) {
557
439
                                LOG.error(ex);
558
440
                                String absoluteLVName = lvmRootDirectory + PATH_SEPARATOR + vgName + PATH_SEPARATOR + lvName;
571
453
                        lvmVolumeInfo.setSize(size);
572
454
                } catch(ExecutionException ex) {
573
455
                        String error = "Unable to run command: " + ex.getMessage();
 
456
                        volumeManager.abort();
574
457
                        LOG.error(error);
575
458
                        throw new EucalyptusCloudException(error);
576
459
                }
577
 
                EntityWrapper<LVMVolumeInfo> db = StorageController.getEntityWrapper();
578
 
                db.add(lvmVolumeInfo);
579
 
                db.commit();
 
460
                volumeManager.add(lvmVolumeInfo);
 
461
                volumeManager.finish();
580
462
        }
581
463
 
582
464
        public int createVolume(String volumeId, String snapshotId) throws EucalyptusCloudException {
583
 
                EntityWrapper<LVMVolumeInfo> db = StorageController.getEntityWrapper();
584
 
                LVMVolumeInfo lvmVolumeInfo = new LVMVolumeInfo(snapshotId);
585
 
                LVMVolumeInfo foundSnapshotInfo = db.getUnique(lvmVolumeInfo);
 
465
                VolumeEntityWrapperManager volumeManager = new VolumeEntityWrapperManager();
 
466
                LVMVolumeInfo foundSnapshotInfo = volumeManager.getVolumeInfo(snapshotId);
586
467
                int size = -1;
587
468
                if(foundSnapshotInfo != null) {
588
469
                        String status = foundSnapshotInfo.getStatus();
589
470
                        if(status.equals(StorageProperties.Status.available.toString())) {
590
471
                                String vgName = "vg-" + Hashes.getRandom(4);
591
472
                                String lvName = "lv-" + Hashes.getRandom(4);
592
 
                                lvmVolumeInfo = new LVMVolumeInfo();
 
473
                                LVMVolumeInfo lvmVolumeInfo = volumeManager.getVolumeInfo();
593
474
 
594
475
                                try {
595
476
                                        String rawFileName = StorageProperties.storageRootDirectory + "/" + volumeId;
606
487
                                        duplicateLogicalVolume(foundSnapshotInfo.getLoFileName(), absoluteLVName);
607
488
                                        //export logical volume
608
489
                                        try {
609
 
                                                int vbladePid = exportVolume(lvmVolumeInfo, vgName, lvName);
610
 
                                                if(vbladePid < 0) {
611
 
                                                        throw new EucalyptusCloudException("Unable to export volume: " + volumeId);
612
 
                                                }
 
490
                                                volumeManager.exportVolume(lvmVolumeInfo, vgName, lvName);
613
491
                                        } catch(EucalyptusCloudException ex) {
614
492
                                                String returnValue = removeLogicalVolume(absoluteLVName);
615
493
                                                returnValue = removeVolumeGroup(vgName);
624
502
                                        lvmVolumeInfo.setLvName(lvName);
625
503
                                        lvmVolumeInfo.setStatus(StorageProperties.Status.available.toString());
626
504
                                        lvmVolumeInfo.setSize(size);
627
 
                                        db.add(lvmVolumeInfo);
628
 
                                        db.commit();
 
505
                                        volumeManager.add(lvmVolumeInfo);
 
506
                                        volumeManager.finish();
629
507
                                }  catch(ExecutionException ex) {
630
 
                                        db.rollback();
 
508
                                        volumeManager.abort();
631
509
                                        String error = "Unable to run command: " + ex.getMessage();
632
510
                                        LOG.error(error);
633
511
                                        throw new EucalyptusCloudException(error);
634
512
                                }
635
513
                        }
636
514
                } else {
637
 
                        db.rollback();
 
515
                        volumeManager.abort();
638
516
                        throw new EucalyptusCloudException("Unable to find snapshot: " + snapshotId);
639
517
                }
640
518
                return size;
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);
654
 
                        db.commit();                    
 
531
                        volumeManager.add(lvmVolumeInfo);
 
532
                        volumeManager.finish();
655
533
                } else {
656
534
                        throw new EucalyptusCloudException("Snapshot backing file does not exist for: " + snapshotId);
657
535
                }
658
536
        }
659
537
 
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();
 
540
 
 
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();
668
546
 
669
547
                        File volumeFile = new File(StorageProperties.storageRootDirectory + PATH_SEPARATOR + foundVolumeInfo.getVolumeId());
670
548
 
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);
693
 
                                db.commit();
 
569
                                volumeManager.add(lvmVolumeInfo);
 
570
                                volumeManager.finish();
694
571
                        } catch(ExecutionException ex) {
695
 
                                db.rollback();
 
572
                                volumeManager.abort();
696
573
                                String error = "Unable to run command: " + ex.getMessage();
697
574
                                LOG.error(error);
698
575
                                throw new EucalyptusCloudException(error);
699
576
                        }
700
577
                } else {
701
 
                        db.rollback();
 
578
                        volumeManager.abort();
702
579
                        throw new EucalyptusCloudException("Could not dup volume " + volumeId);
703
580
                }
704
581
 
705
582
        }
706
583
 
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());
716
591
                        } else {
717
 
                                db.rollback();
 
592
                                volumeManager.abort();
718
593
                                throw new EucalyptusCloudException("Unable to find entry: " + volumeSetEntry);
719
594
                        }
720
595
                }
721
 
                db.commit();
 
596
                volumeManager.finish();
722
597
                return status;
723
598
        }
724
599
 
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);
729
 
 
 
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;
736
 
 
737
 
 
738
 
                        Integer pid = foundLVMVolumeInfo.getVbladePid();
739
 
                        if(pid > 0) {
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();
748
 
                                        }
749
 
                                }
750
 
                        }
 
609
                        volumeManager.unexportVolume(foundLVMVolumeInfo);
751
610
                        try {
752
611
                                String returnValue = removeLogicalVolume(absoluteLVName);
753
612
                                if(returnValue.length() == 0) {
762
621
                                        throw new EucalyptusCloudException("Unable to remove physical volume " + loDevName);
763
622
                                }
764
623
                                returnValue = removeLoopback(loDevName);
765
 
                                db.delete(foundLVMVolumeInfo);
766
 
                                db.commit();
 
624
                                volumeManager.remove(foundLVMVolumeInfo);
 
625
                                volumeManager.finish();
767
626
                        } catch(ExecutionException ex) {
768
 
                                db.rollback();
 
627
                                volumeManager.abort();
769
628
                                String error = "Unable to run command: " + ex.getMessage();
770
629
                                LOG.error(error);
771
630
                                throw new EucalyptusCloudException(error);
772
631
                        }
773
632
                }  else {
774
 
                        db.rollback();
 
633
                        volumeManager.abort();
775
634
                        throw new EucalyptusCloudException("Unable to find volume: " + volumeId);
776
635
                }
777
636
        }
778
637
 
779
638
 
780
639
        public List<String> createSnapshot(String volumeId, String snapshotId) throws EucalyptusCloudException {
781
 
                EntityWrapper<LVMVolumeInfo> db = StorageController.getEntityWrapper();
782
 
                LVMVolumeInfo lvmVolumeInfo = new LVMVolumeInfo(volumeId);
783
 
                LVMVolumeInfo foundLVMVolumeInfo = db.getUnique(lvmVolumeInfo);
 
640
                VolumeEntityWrapperManager volumeManager = new VolumeEntityWrapperManager();
 
641
                LVMVolumeInfo foundLVMVolumeInfo = volumeManager.getVolumeInfo(volumeId);
784
642
                ArrayList<String> returnValues = new ArrayList<String>();
785
643
                if(foundLVMVolumeInfo != null) {
786
 
                        LVMVolumeInfo snapshotInfo = new LVMVolumeInfo(snapshotId);
787
 
                        snapshotInfo.setSnapshotOf(volumeId);
 
644
                        LVMVolumeInfo snapshotInfo = volumeManager.getVolumeInfo();
 
645
                        snapshotInfo.setVolumeId(snapshotId);
788
646
                        File snapshotDir = new File(StorageProperties.storageRootDirectory);
789
647
                        snapshotDir.mkdirs();
790
648
 
824
682
                                }
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) {
833
 
                                db.rollback();
 
690
                                volumeManager.abort();
834
691
                                String error = "Unable to run command: " + ex.getMessage();
835
692
                                LOG.error(error);
836
693
                                throw new EucalyptusCloudException(error);
837
694
                        }
838
695
 
839
696
                }
840
 
                db.commit();
 
697
                volumeManager.finish();
841
698
                return returnValues;
842
699
        }
843
700
 
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>();
849
705
 
850
706
                if(foundLVMVolumeInfo != null) {
851
707
                        returnValues.add(StorageProperties.storageRootDirectory + PATH_SEPARATOR + foundLVMVolumeInfo.getVolumeId());
852
 
                        db.commit();
 
708
                        volumeManager.finish();
853
709
                } else {
854
 
                        db.rollback();
 
710
                        volumeManager.abort();
855
711
                        throw new EucalyptusCloudException("Unable to find snapshot: " + snapshotId);
856
712
                }
857
713
                return returnValues;
858
714
        }
859
715
 
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);
864
719
 
865
720
                if(foundLVMVolumeInfo != null) {
866
 
                        db.delete(foundLVMVolumeInfo);
867
 
                        db.commit();
 
721
                        volumeManager.remove(foundLVMVolumeInfo);
868
722
                }  else {
869
 
                        db.rollback();
 
723
                        volumeManager.abort();
870
724
                        throw new EucalyptusCloudException("Unable to find snapshot: " + snapshotId);
871
725
                }
 
726
                volumeManager.finish();
872
727
        }
873
728
 
874
 
        public List<String> getVolume(String volumeId) throws EucalyptusCloudException {
875
 
                ArrayList<String> returnValues = new ArrayList<String>();
876
 
 
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()));
884
 
                }
885
 
                db.commit();
886
 
                return returnValues;
 
729
        public String getVolumeProperty(String volumeId) throws EucalyptusCloudException {
 
730
                VolumeEntityWrapperManager volumeManager = new VolumeEntityWrapperManager();
 
731
                String returnValue = volumeManager.getVolumeProperty(volumeId);
 
732
                volumeManager.finish();
 
733
                return returnValue;
887
734
        }
888
735
 
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());
892
739
                int i = 0;
893
740
                for(String snapshotFileName: snapshotFileNames) {
894
741
                        try {
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) {
903
 
                                db.rollback();
 
749
                                volumeManager.abort();
904
750
                                String error = "Unable to run command: " + ex.getMessage();
905
751
                                LOG.error(error);
906
752
                                throw new EucalyptusCloudException(error);
907
753
                        }
908
754
 
909
755
                }
910
 
                db.commit();
 
756
                volumeManager.finish();
911
757
        }
912
758
 
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) {
922
767
                                if(!new File(absoluteLoFileName).exists()) {
923
768
                                        LOG.error("Backing volume: " + absoluteLoFileName + " not found. Invalidating volume."); 
924
769
                                        foundVolumeInfo.setStatus(StorageProperties.Status.failed.toString());
925
 
                                        foundVolumeInfo.setVbladePid(-1);
926
770
                                        continue;
927
771
                                }
928
772
                                try {
938
782
                }
939
783
                //now enable them
940
784
                for(LVMVolumeInfo foundVolumeInfo : volumeInfos) {
941
 
                        int pid = foundVolumeInfo.getVbladePid();
942
 
                        if(pid > 0) {
943
 
                                //enable logical volumes
944
 
                                String absoluteLVName = lvmRootDirectory + PATH_SEPARATOR + foundVolumeInfo.getVgName() + PATH_SEPARATOR + foundVolumeInfo.getLvName();
945
 
                                try {
946
 
                                        enableLogicalVolume(absoluteLVName);
947
 
                                } catch(ExecutionException ex) {
948
 
                                        String error = "Unable to run command: " + ex.getMessage();
949
 
                                        LOG.error(error);
950
 
                                        continue;
951
 
                                }
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;
960
 
                                        try {
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)
967
 
                                                        try {
968
 
                                                                fileOutStream.close();
969
 
                                                        } catch (IOException e) {
970
 
                                                                LOG.error(e);
971
 
                                                        }
972
 
                                                        LOG.error("Could not write pid file vblade-" + majorNumber + minorNumber + ".pid");
973
 
                                        }
974
 
                                }
975
 
                        }
 
785
                        try {
 
786
                                volumeManager.exportVolume(foundVolumeInfo);
 
787
                        } catch(EucalyptusCloudException ex) {
 
788
                                LOG.error("Unable to reload volume: " + foundVolumeInfo.getVolumeId() + ex);
 
789
                        }               
976
790
                }
977
 
                db.commit();
 
791
                volumeManager.finish();
978
792
        }
979
793
 
980
794
        public List<String> getSnapshotValues(String snapshotId) throws EucalyptusCloudException {
981
 
                ArrayList<String> returnValues = new ArrayList<String>();
982
 
 
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());
990
 
                }
991
 
                db.commit();
 
795
                VolumeEntityWrapperManager volumeManager = new VolumeEntityWrapperManager();
 
796
                List<String> returnValues = volumeManager.getSnapshotValues(snapshotId);
 
797
                volumeManager.finish();
992
798
                return returnValues;
993
799
        }
994
800
 
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();
1002
 
                        db.commit();
 
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;
1004
808
                } else {
1005
 
                        db.rollback();
 
809
                        volumeManager.abort();
1006
810
                        return 0;
1007
811
                }
1008
812
        }
1032
836
                }
1033
837
                return returnString;
1034
838
        }
 
839
 
 
840
        private class VolumeEntityWrapperManager {
 
841
                private EntityWrapper entityWrapper;
 
842
 
 
843
                private VolumeEntityWrapperManager() {
 
844
                        entityWrapper = StorageController.getEntityWrapper();
 
845
                }
 
846
 
 
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());
 
853
                        }
 
854
                        return returnValues;
 
855
                }
 
856
 
 
857
                public void exportVolume(LVMVolumeInfo lvmVolumeInfo) throws EucalyptusCloudException {
 
858
                        if(exportManager instanceof AOEManager) {
 
859
                                AOEVolumeInfo aoeVolumeInfo = (AOEVolumeInfo) lvmVolumeInfo;
 
860
 
 
861
                                int pid = aoeVolumeInfo.getVbladePid();
 
862
                                if(pid > 0) {
 
863
                                        //enable logical volumes
 
864
                                        String absoluteLVName = lvmRootDirectory + PATH_SEPARATOR + aoeVolumeInfo.getVgName() + PATH_SEPARATOR + aoeVolumeInfo.getLvName();
 
865
                                        try {
 
866
                                                enableLogicalVolume(absoluteLVName);
 
867
                                        } catch(ExecutionException ex) {
 
868
                                                String error = "Unable to run command: " + ex.getMessage();
 
869
                                                LOG.error(error);
 
870
                                                return;
 
871
                                        }
 
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;
 
880
                                                try {
 
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)
 
887
                                                                try {
 
888
                                                                        fileOutStream.close();
 
889
                                                                } catch (IOException e) {
 
890
                                                                        LOG.error(e);
 
891
                                                                }
 
892
                                                                LOG.error("Could not write pid file vblade-" + majorNumber + minorNumber + ".pid");
 
893
                                                }
 
894
                                        }
 
895
                                }
 
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);
 
902
                        }       
 
903
                }
 
904
 
 
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;
 
916
                                }
 
917
                        }
 
918
                        return null;
 
919
                }
 
920
 
 
921
                public void unexportVolume(LVMVolumeInfo volumeInfo) {
 
922
                        if(volumeInfo instanceof AOEVolumeInfo) {
 
923
                                AOEVolumeInfo aoeVolumeInfo = (AOEVolumeInfo) volumeInfo;
 
924
                                int pid = aoeVolumeInfo.getVbladePid();
 
925
                                if(pid > 0) {
 
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();
 
934
                                                }
 
935
                                        }
 
936
                                }
 
937
                        } else if(volumeInfo instanceof ISCSIVolumeInfo) {
 
938
                                ISCSIVolumeInfo iscsiVolumeInfo = (ISCSIVolumeInfo) volumeInfo;
 
939
                                ((ISCSIManager)exportManager).unexportTarget(iscsiVolumeInfo.getTid(), iscsiVolumeInfo.getLun());
 
940
                        }                       
 
941
                }
 
942
 
 
943
                private void finish() {
 
944
                        entityWrapper.commit();
 
945
                }
 
946
 
 
947
                private void abort() {
 
948
                        entityWrapper.rollback();
 
949
                }
 
950
 
 
951
 
 
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);
 
958
                                }
 
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);
 
964
                                }
 
965
                        }
 
966
                        return null;
 
967
                }
 
968
 
 
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();
 
978
                        }
 
979
                        return null;
 
980
                }
 
981
 
 
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);
 
989
                        }
 
990
                        return null;
 
991
                }
 
992
 
 
993
                private void add(LVMVolumeInfo volumeInfo) {
 
994
                        entityWrapper.add(volumeInfo);
 
995
                }
 
996
 
 
997
                private void remove(LVMVolumeInfo volumeInfo) {
 
998
                        entityWrapper.delete(volumeInfo);
 
999
                }
 
1000
 
 
1001
                private String encryptTargetPassword(String password) throws EucalyptusCloudException {
 
1002
                        EntityWrapper<ClusterCredentials> credDb = Credentials.getEntityWrapper( );
 
1003
                        try {
 
1004
                                ClusterCredentials credentials = credDb.getUnique( new ClusterCredentials( StorageProperties.NAME ) );
 
1005
                                PublicKey ncPublicKey = X509Cert.toCertificate(credentials.getNodeCertificate()).getPublicKey();
 
1006
                                credDb.commit();
 
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" );
 
1012
                                credDb.rollback( );
 
1013
                                throw new EucalyptusCloudException(e.getMessage(), e);
 
1014
                        }
 
1015
                }
 
1016
 
 
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 = "";
 
1027
                                int timeout = 300;
 
1028
                                if(pid > 0) {
 
1029
                                        for(int i=0; i < 5; ++i) {
 
1030
                                                returnValue = aoeStatus(pid);
 
1031
                                                if(returnValue.length() == 0) {
 
1032
                                                        success = false;
 
1033
                                                        try {
 
1034
                                                                Thread.sleep(timeout);
 
1035
                                                        } catch(InterruptedException ie) {
 
1036
                                                                LOG.error(ie);
 
1037
                                                        }
 
1038
                                                        timeout += 300;
 
1039
                                                } else {
 
1040
                                                        success = true;
 
1041
                                                        break;
 
1042
                                                }
 
1043
                                        }
 
1044
                                }
 
1045
                                if(!success) {
 
1046
                                        throw new EucalyptusCloudException("Could not export AoE device " + absoluteLVName + " iface: " + StorageProperties.iface + " pid: " + pid + " returnValue: " + returnValue);
 
1047
                                }
 
1048
 
 
1049
                                File vbladePidFile = new File(eucaHome + EUCA_VAR_RUN_PATH + "/vblade-" + majorNumber + minorNumber + ".pid");
 
1050
                                FileOutputStream fileOutStream = null;
 
1051
                                try {
 
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");
 
1057
                                } finally {
 
1058
                                        if(fileOutStream != null)
 
1059
                                                try {
 
1060
                                                        fileOutStream.close();
 
1061
                                                } catch (IOException e) {
 
1062
                                                        LOG.error(e);
 
1063
                                                }
 
1064
                                }
 
1065
                                if(pid < 0)
 
1066
                                        throw new EucalyptusCloudException("invalid vblade pid: " + pid);
 
1067
                                aoeVolumeInfo.setVbladePid(pid);
 
1068
                                return 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);
 
1076
                        }
 
1077
                        return 0;
 
1078
                }
 
1079
        }
1035
1080
}
 
1081