~ubuntu-branches/ubuntu/raring/eucalyptus/raring

« back to all changes in this revision

Viewing changes to clc/modules/storage-controller/src/main/java/com/eucalyptus/storage/OverlayManager.java

  • Committer: Package Import Robot
  • Author(s): Brian Thomason
  • Date: 2011-11-29 13:17:52 UTC
  • mfrom: (1.2.1 upstream)
  • mto: This revision was merged to the branch mainline in revision 185.
  • Revision ID: package-import@ubuntu.com-20111129131752-rq31al3ntutv2vvl
Tags: upstream-3.0.999beta1
ImportĀ upstreamĀ versionĀ 3.0.999beta1

Show diffs side-by-side

added added

removed removed

Lines of Context:
53
53
 *    SOFTWARE, AND IF ANY SUCH MATERIAL IS DISCOVERED THE PARTY DISCOVERING
54
54
 *    IT MAY INFORM DR. RICH WOLSKI AT THE UNIVERSITY OF CALIFORNIA, SANTA
55
55
 *    BARBARA WHO WILL THEN ASCERTAIN THE MOST APPROPRIATE REMEDY, WHICH IN
56
 
 *    THE REGENTSā€™ DISCRETION MAY INCLUDE, WITHOUT LIMITATION, REPLACEMENT
 
56
 *    THE REGENTS' DISCRETION MAY INCLUDE, WITHOUT LIMITATION, REPLACEMENT
57
57
 *    OF THE CODE SO IDENTIFIED, LICENSING OF THE CODE SO IDENTIFIED, OR
58
58
 *    WITHDRAWAL OF THE CODE CAPABILITY TO THE EXTENT NEEDED TO COMPLY WITH
59
59
 *    ANY SUCH LICENSES OR RIGHTS.
80
80
import org.apache.log4j.Logger;
81
81
import org.bouncycastle.util.encoders.Base64;
82
82
 
83
 
import com.eucalyptus.auth.ClusterCredentials;
84
 
import com.eucalyptus.auth.Authentication;
85
 
import com.eucalyptus.auth.SystemCredentialProvider;
86
 
import com.eucalyptus.auth.X509Cert;
87
83
import com.eucalyptus.auth.util.Hashes;
 
84
import com.eucalyptus.auth.util.X509CertHelper;
 
85
import com.eucalyptus.component.Partitions;
 
86
import com.eucalyptus.component.ServiceConfiguration;
 
87
import com.eucalyptus.component.ServiceConfigurations;
 
88
import com.eucalyptus.component.id.ClusterController;
88
89
import com.eucalyptus.config.StorageControllerBuilder;
89
90
import com.eucalyptus.configurable.ConfigurableClass;
90
91
import com.eucalyptus.configurable.ConfigurableProperty;
91
92
import com.eucalyptus.configurable.PropertyDirectory;
92
93
import com.eucalyptus.entities.EntityWrapper;
93
94
import com.eucalyptus.util.EucalyptusCloudException;
94
 
import com.eucalyptus.util.ExecutionException;
95
95
import com.eucalyptus.util.StorageProperties;
96
96
import com.eucalyptus.util.WalrusProperties;
97
97
 
147
147
                                exportManager = new ISCSIManager();
148
148
                        }
149
149
                        exportManager.checkPreconditions();
150
 
                } catch(ExecutionException ex) {
 
150
                } catch(EucalyptusCloudException ex) {
151
151
                        String error = "Unable to run command: " + ex.getMessage();
152
152
                        LOG.error(error);
153
153
                        throw new EucalyptusCloudException(error);
154
154
                }
155
155
        }
156
156
 
157
 
        private String getLvmVersion() throws ExecutionException {
 
157
        private String getLvmVersion() throws EucalyptusCloudException {
158
158
                return SystemUtil.run(new String[]{eucaHome + StorageProperties.EUCA_ROOT_WRAPPER, "lvm", "version"});
159
159
        }
160
160
 
161
 
        private String findFreeLoopback() throws ExecutionException {
 
161
        private String findFreeLoopback() throws EucalyptusCloudException {
162
162
                return SystemUtil.run(new String[]{eucaHome + StorageProperties.EUCA_ROOT_WRAPPER, "losetup", "-f"}).replaceAll("\n", "");
163
163
        }
164
164
 
165
 
        private  String getLoopback(String loDevName) throws ExecutionException {
 
165
        private  String getLoopback(String loDevName) throws EucalyptusCloudException {
166
166
                return SystemUtil.run(new String[]{eucaHome + StorageProperties.EUCA_ROOT_WRAPPER, "losetup", loDevName});
167
167
        }
168
168
 
169
 
        private String createPhysicalVolume(String loDevName) throws ExecutionException {
 
169
        private String createPhysicalVolume(String loDevName) throws EucalyptusCloudException {
170
170
                return SystemUtil.run(new String[]{eucaHome + StorageProperties.EUCA_ROOT_WRAPPER, "pvcreate", loDevName});
171
171
        }
172
172
 
173
 
        private String createVolumeGroup(String pvName, String vgName) throws ExecutionException {
 
173
        private String createVolumeGroup(String pvName, String vgName) throws EucalyptusCloudException {
174
174
                return SystemUtil.run(new String[]{eucaHome + StorageProperties.EUCA_ROOT_WRAPPER, "vgcreate", vgName, pvName});
175
175
        }
176
176
 
177
 
        private String extendVolumeGroup(String pvName, String vgName) throws ExecutionException {
 
177
        private String extendVolumeGroup(String pvName, String vgName) throws EucalyptusCloudException {
178
178
                return SystemUtil.run(new String[]{eucaHome + StorageProperties.EUCA_ROOT_WRAPPER, "vgextend", vgName, pvName});
179
179
        }
180
180
 
181
 
        private String scanVolumeGroups() throws ExecutionException {
 
181
        private String scanVolumeGroups() throws EucalyptusCloudException {
182
182
                return SystemUtil.run(new String[]{eucaHome + StorageProperties.EUCA_ROOT_WRAPPER, "vgscan"});
183
183
        }
184
184
 
185
 
        private String createLogicalVolume(String vgName, String lvName) throws ExecutionException {
 
185
        private String createLogicalVolume(String vgName, String lvName) throws EucalyptusCloudException {
186
186
                return SystemUtil.run(new String[]{eucaHome + StorageProperties.EUCA_ROOT_WRAPPER, "lvcreate", "-n", lvName, "-l", "100%FREE", vgName});
187
187
        }
188
188
 
189
 
        private String createSnapshotLogicalVolume(String lvName, String snapLvName) throws ExecutionException {
 
189
        private String createSnapshotLogicalVolume(String lvName, String snapLvName) throws EucalyptusCloudException {
190
190
                return SystemUtil.run(new String[]{eucaHome + StorageProperties.EUCA_ROOT_WRAPPER, "lvcreate", "-n", snapLvName, "-s", "-l", "100%FREE", lvName});
191
191
        }
192
192
 
193
 
        private String removeLogicalVolume(String lvName) throws ExecutionException {
 
193
        private String removeLogicalVolume(String lvName) throws EucalyptusCloudException {
194
194
                return SystemUtil.run(new String[]{eucaHome + StorageProperties.EUCA_ROOT_WRAPPER, "lvremove", "-f", lvName});
195
195
        }
196
196
 
197
 
        private String removeVolumeGroup(String vgName) throws ExecutionException {
 
197
        private String removeVolumeGroup(String vgName) throws EucalyptusCloudException {
198
198
                return SystemUtil.run(new String[]{eucaHome + StorageProperties.EUCA_ROOT_WRAPPER, "vgremove", vgName});
199
199
        }
200
200
 
201
 
        private String removePhysicalVolume(String loDevName) throws ExecutionException {
 
201
        private String removePhysicalVolume(String loDevName) throws EucalyptusCloudException {
202
202
                return SystemUtil.run(new String[]{eucaHome + StorageProperties.EUCA_ROOT_WRAPPER, "pvremove", loDevName});
203
203
        }
204
204
 
205
 
        private String removeLoopback(String loDevName) throws ExecutionException {
 
205
        private String removeLoopback(String loDevName) throws EucalyptusCloudException {
206
206
                return SystemUtil.run(new String[]{eucaHome + StorageProperties.EUCA_ROOT_WRAPPER, "losetup", "-d", loDevName});
207
207
        }
208
208
 
209
 
        private String reduceVolumeGroup(String vgName, String pvName) throws ExecutionException {
 
209
        private String reduceVolumeGroup(String vgName, String pvName) throws EucalyptusCloudException {
210
210
                return SystemUtil.run(new String[]{eucaHome + StorageProperties.EUCA_ROOT_WRAPPER, "vgreduce", vgName, pvName});
211
211
        }
212
212
 
213
 
        private String enableLogicalVolume(String lvName) throws ExecutionException {
 
213
        private String enableLogicalVolume(String lvName) throws EucalyptusCloudException {
214
214
                return SystemUtil.run(new String[]{eucaHome + StorageProperties.EUCA_ROOT_WRAPPER, "lvchange", "-ay", lvName});
215
215
        }
216
216
 
 
217
        private boolean logicalVolumeExists(String lvName) {
 
218
                boolean success = false;
 
219
                String returnValue = SystemUtil.run(new String[]{eucaHome + StorageProperties.EUCA_ROOT_WRAPPER, "lvdisplay", lvName});
 
220
                if(returnValue.length() > 0) {
 
221
                        success = true;
 
222
                }
 
223
                return success;
 
224
        }
 
225
 
 
226
        private boolean volumeGroupExists(String vgName) {
 
227
                boolean success = false;
 
228
                String returnValue = SystemUtil.run(new String[]{eucaHome + StorageProperties.EUCA_ROOT_WRAPPER, "vgdisplay", vgName});
 
229
                if(returnValue.length() > 0) {
 
230
                        success = true;
 
231
                }
 
232
                return success;
 
233
        }
 
234
 
 
235
        private boolean physicalVolumeExists(String pvName) {
 
236
                boolean success = false;
 
237
                String returnValue = SystemUtil.run(new String[]{eucaHome + StorageProperties.EUCA_ROOT_WRAPPER, "pvdisplay", pvName});
 
238
                if(returnValue.length() > 0) {
 
239
                        success = true;
 
240
                }
 
241
                return success;
 
242
        }
 
243
 
217
244
        private int losetup(String absoluteFileName, String loDevName) {
218
245
                try
219
246
                {
229
256
                        LOG.info(output.getReturnValue());
230
257
                        LOG.info(error.getReturnValue());
231
258
                        return errorCode;
232
 
                } catch (Throwable t) {
 
259
                } catch (Exception t) {
233
260
                        LOG.error(t);
234
261
                }
235
262
                return -1;
236
263
        }
237
264
 
238
 
        private String duplicateLogicalVolume(String oldLvName, String newLvName) throws ExecutionException {
 
265
        private String duplicateLogicalVolume(String oldLvName, String newLvName) throws EucalyptusCloudException {
239
266
                return SystemUtil.run(new String[]{eucaHome + StorageProperties.EUCA_ROOT_WRAPPER, "dd", "if=" + oldLvName, "of=" + newLvName, "bs=" + StorageProperties.blockSize});
240
267
        }
241
268
 
242
 
        private String createFile(String fileName, long size) throws ExecutionException {
 
269
        private String createFile(String fileName, long size) throws EucalyptusCloudException {
243
270
                if(!DirectStorageInfo.getStorageInfo().getZeroFillVolumes())
244
271
                        return SystemUtil.run(new String[]{eucaHome + StorageProperties.EUCA_ROOT_WRAPPER, "dd", "if=/dev/zero", "of=" + fileName, "count=1", "bs=" + StorageProperties.blockSize, "seek=" + (size -1)});
245
272
                else
246
273
                        return SystemUtil.run(new String[]{eucaHome + StorageProperties.EUCA_ROOT_WRAPPER, "dd", "if=/dev/zero", "of=" + fileName, "count=" + size, "bs=" + StorageProperties.blockSize});
247
274
        }
248
275
 
249
 
        private String createEmptyFile(String fileName, int size) throws ExecutionException {
 
276
        private String createEmptyFile(String fileName, int size) throws EucalyptusCloudException {
250
277
                long fileSize = size * 1024;
251
278
                return createFile(fileName, fileSize);
252
279
        }
253
280
 
254
 
        public String createAbsoluteEmptyFile(String fileName, long size) throws ExecutionException {
 
281
        public String createAbsoluteEmptyFile(String fileName, long size) throws EucalyptusCloudException {
255
282
                size = size / WalrusProperties.M;
256
283
                return createFile(fileName, size);
257
284
        }
258
285
 
259
286
 
260
 
        public void initialize() {
 
287
        public void initialize() throws EucalyptusCloudException {
 
288
                File storageRootDir = new File(getStorageRootDirectory());
 
289
                if(!storageRootDir.exists()) {
 
290
                        if(!storageRootDir.mkdirs()) {
 
291
                                throw new EucalyptusCloudException("Unable to make volume root directory: " + getStorageRootDirectory());
 
292
                        }
 
293
                }
 
294
                //The following should be executed only once during the entire lifetime of the VM.
261
295
                if(!initialized) {
262
296
                        System.loadLibrary("lvm2control");
263
297
                        registerSignals();
264
 
                        File storageRootDir = new File(getStorageRootDirectory());
265
 
                        if(!storageRootDir.exists()) {
266
 
                                if(!storageRootDir.mkdirs()) {
267
 
                                        LOG.fatal("Unable to make volume root directory: " + getStorageRootDirectory());
268
 
                                }
269
 
                        }
270
298
                        initialized = true;
271
299
                }
272
300
        }
273
301
 
274
 
        public void configure() {
 
302
        public void configure() throws EucalyptusCloudException {
275
303
                exportManager.configure();
276
304
                //First call to StorageInfo.getStorageInfo will add entity if it does not exist
277
 
                LOG.info(StorageInfo.getStorageInfo().getName());
 
305
                LOG.info(""+StorageInfo.getStorageInfo().getName());
278
306
                checkVolumesDir();
279
307
        }
280
308
 
283
311
        }
284
312
 
285
313
        private void checkVolumesDir() {
286
 
                File volumeDir = new File(DirectStorageInfo.getStorageInfo().getVolumesDir());
287
 
                if(!volumeDir.exists()) {
288
 
                        if(!volumeDir.mkdirs()) {
289
 
                                LOG.fatal("Unable to make volume root directory: " + DirectStorageInfo.getStorageInfo().getVolumesDir());
 
314
                String volumesDir = DirectStorageInfo.getStorageInfo().getVolumesDir();
 
315
                File volumes = new File(volumesDir);
 
316
                if(!volumes.exists()) {
 
317
                        if(!volumes.mkdirs()) {
 
318
                                LOG.fatal("Unable to make volume root directory: " + volumesDir);
290
319
                        }
291
 
                } else if(!volumeDir.canWrite()) {
292
 
                        LOG.fatal("Cannot write to volume root directory: " + DirectStorageInfo.getStorageInfo().getVolumesDir());
 
320
                } else if(!volumes.canWrite()) {
 
321
                        LOG.fatal("Cannot write to volume root directory: " + volumesDir);
 
322
                }
 
323
                try {
 
324
                        SystemUtil.setEucaReadWriteOnly(volumesDir);
 
325
                } catch (EucalyptusCloudException ex) {
 
326
                        LOG.fatal(ex);
293
327
                }
294
328
        }
295
329
 
308
342
                                returnValue = removeVolumeGroup(vgName);
309
343
                                returnValue = removePhysicalVolume(loDevName);
310
344
                                removeLoopback(loDevName);
311
 
                        } catch(ExecutionException ex) {
 
345
                        } catch(EucalyptusCloudException ex) {
312
346
                                volumeManager.abort();
313
347
                                String error = "Unable to run command: " + ex.getMessage();
314
348
                                LOG.error(error);
374
408
                }
375
409
        }
376
410
 
377
 
        public String createDuplicateLoopback(String oldRawFileName, String rawFileName) throws EucalyptusCloudException, ExecutionException {
 
411
        public String createDuplicateLoopback(String oldRawFileName, String rawFileName) throws EucalyptusCloudException {
378
412
                dupFile(oldRawFileName, rawFileName);
379
413
                return createLoopback(rawFileName);
380
414
        }
381
415
 
382
 
        public String createLoopback(String fileName, int size) throws EucalyptusCloudException, ExecutionException {
 
416
        public String createLoopback(String fileName, int size) throws EucalyptusCloudException {
383
417
                createEmptyFile(fileName, size);
384
418
                if(!(new File(fileName).exists()))
385
419
                        throw new EucalyptusCloudException("Unable to create file " + fileName);
386
420
                return createLoopback(fileName);
387
421
        }
388
422
 
389
 
        public synchronized String createLoopback(String fileName) throws EucalyptusCloudException, ExecutionException {
 
423
        public synchronized String createLoopback(String fileName) throws EucalyptusCloudException {
390
424
                int number_of_retries = 0;
391
425
                int status = -1;
392
426
                String loDevName;
410
444
                return losetup(absoluteFileName, loDevName);
411
445
        }
412
446
 
413
 
        public String createLoopback(String fileName, long size) throws EucalyptusCloudException, ExecutionException {
 
447
        public String createLoopback(String fileName, long size) throws EucalyptusCloudException {
414
448
                createAbsoluteEmptyFile(fileName, size);
415
449
                if(!(new File(fileName).exists()))
416
450
                        throw new EucalyptusCloudException("Unable to create file " + fileName);
418
452
        }
419
453
 
420
454
        //creates a logical volume (and a new physical volume and volume group)
421
 
        public void createLogicalVolume(String loDevName, String vgName, String lvName) throws EucalyptusCloudException, ExecutionException {
 
455
        public void createLogicalVolume(String loDevName, String vgName, String lvName) throws EucalyptusCloudException {
422
456
                String returnValue = createPhysicalVolume(loDevName);
423
457
                if(returnValue.length() == 0) {
424
458
                        throw new EucalyptusCloudException("Unable to create physical volume for " + loDevName);
433
467
                }
434
468
        }
435
469
 
436
 
        public  void createSnapshotLogicalVolume(String loDevName, String vgName, String lvName, String snapLvName) throws EucalyptusCloudException, ExecutionException {
 
470
        public  void createSnapshotLogicalVolume(String loDevName, String vgName, String lvName, String snapLvName) throws EucalyptusCloudException {
437
471
                String returnValue = createPhysicalVolume(loDevName);
438
472
                if(returnValue.length() == 0) {
439
473
                        throw new EucalyptusCloudException("Unable to create physical volume for " + loDevName);
489
523
                        volumeManager = new VolumeEntityWrapperManager();
490
524
                        volumeManager.add(lvmVolumeInfo);
491
525
                        volumeManager.finish();
492
 
                } catch(ExecutionException ex) {
 
526
                } catch(EucalyptusCloudException ex) {
493
527
                        String error = "Unable to run command: " + ex.getMessage();
494
528
                        volumeManager.abort();
495
529
                        LOG.error(error);
547
581
                                        volumeManager = new VolumeEntityWrapperManager();
548
582
                                        volumeManager.add(lvmVolumeInfo);
549
583
                                        volumeManager.finish();
550
 
                                }  catch(ExecutionException ex) {
 
584
                                }  catch(EucalyptusCloudException ex) {
551
585
                                        volumeManager.abort();
552
586
                                        String error = "Unable to run command: " + ex.getMessage();
553
587
                                        LOG.error(error);
561
595
                return size;
562
596
        }
563
597
 
 
598
        public void cloneVolume(String volumeId, String parentVolumeId)
 
599
        throws EucalyptusCloudException {
 
600
                VolumeEntityWrapperManager volumeManager = new VolumeEntityWrapperManager();
 
601
                LVMVolumeInfo foundVolumeInfo = volumeManager.getVolumeInfo(parentVolumeId);
 
602
                if(foundVolumeInfo != null) {
 
603
                        String vgName = "vg-" + Hashes.getRandom(4);
 
604
                        String lvName = "lv-" + Hashes.getRandom(4);
 
605
                        String parentVgName = foundVolumeInfo.getVgName();
 
606
                        String parentLvName = foundVolumeInfo.getLvName();
 
607
                        LVMVolumeInfo lvmVolumeInfo = volumeManager.getVolumeInfo();
 
608
                        int size = foundVolumeInfo.getSize();
 
609
                        volumeManager.finish();
 
610
                        try {
 
611
                                String rawFileName = DirectStorageInfo.getStorageInfo().getVolumesDir() + "/" + volumeId;
 
612
                                //create file and attach to loopback device
 
613
                                File parentVolumeFile = new File(DirectStorageInfo.getStorageInfo().getVolumesDir() + PATH_SEPARATOR + parentVolumeId);
 
614
                                assert(parentVolumeFile.exists());
 
615
                                long absoluteSize = parentVolumeFile.length();
 
616
 
 
617
                                String loDevName = createLoopback(rawFileName, absoluteSize);
 
618
                                //create physical volume, volume group and logical volume
 
619
                                createLogicalVolume(loDevName, vgName, lvName);
 
620
                                //duplicate snapshot volume
 
621
                                String absoluteLVName = lvmRootDirectory + PATH_SEPARATOR + vgName + PATH_SEPARATOR + lvName;
 
622
                                String absoluteParentLVName = lvmRootDirectory + PATH_SEPARATOR + parentVgName + PATH_SEPARATOR + parentLvName;
 
623
                                duplicateLogicalVolume(absoluteParentLVName, absoluteLVName);
 
624
                                //export logical volume
 
625
                                try {
 
626
                                        volumeManager.exportVolume(lvmVolumeInfo, vgName, lvName);
 
627
                                } catch(EucalyptusCloudException ex) {
 
628
                                        String returnValue = removeLogicalVolume(absoluteLVName);
 
629
                                        returnValue = removeVolumeGroup(vgName);
 
630
                                        returnValue = removePhysicalVolume(loDevName);
 
631
                                        removeLoopback(loDevName);
 
632
                                        throw ex;
 
633
                                }
 
634
                                lvmVolumeInfo.setVolumeId(volumeId);
 
635
                                lvmVolumeInfo.setLoDevName(loDevName);
 
636
                                lvmVolumeInfo.setPvName(loDevName);
 
637
                                lvmVolumeInfo.setVgName(vgName);
 
638
                                lvmVolumeInfo.setLvName(lvName);
 
639
                                lvmVolumeInfo.setStatus(StorageProperties.Status.available.toString());
 
640
                                lvmVolumeInfo.setSize(size);
 
641
                                volumeManager = new VolumeEntityWrapperManager();
 
642
                                volumeManager.add(lvmVolumeInfo);
 
643
                                volumeManager.finish();
 
644
                        }  catch(EucalyptusCloudException ex) {
 
645
                                volumeManager.abort();
 
646
                                String error = "Unable to run command: " + ex.getMessage();
 
647
                                LOG.error(error);
 
648
                                throw new EucalyptusCloudException(error);
 
649
                        }                       
 
650
                } else {
 
651
                        volumeManager.abort();
 
652
                        throw new EucalyptusCloudException("Unable to find volume: " + parentVolumeId);
 
653
                }
 
654
        }
 
655
 
564
656
        public void addSnapshot(String snapshotId) throws EucalyptusCloudException {
565
657
                String snapshotRawFileName = DirectStorageInfo.getStorageInfo().getVolumesDir() + "/" + snapshotId;
566
658
                File snapshotFile = new File(snapshotRawFileName);
582
674
                VolumeEntityWrapperManager volumeManager = new VolumeEntityWrapperManager();
583
675
                LVMVolumeInfo foundLVMVolumeInfo = volumeManager.getVolumeInfo(volumeId);
584
676
                if(foundLVMVolumeInfo != null) {
585
 
                        //remove aoe export
586
677
                        String loDevName = foundLVMVolumeInfo.getLoDevName();
587
678
                        String vgName = foundLVMVolumeInfo.getVgName();
588
679
                        String lvName = foundLVMVolumeInfo.getLvName();
589
680
                        String absoluteLVName = lvmRootDirectory + PATH_SEPARATOR + vgName + PATH_SEPARATOR + lvName;
590
681
                        volumeManager.unexportVolume(foundLVMVolumeInfo);
591
682
                        try {
592
 
                                String returnValue = removeLogicalVolume(absoluteLVName);
593
 
                                if(returnValue.length() == 0) {
594
 
                                        throw new EucalyptusCloudException("Unable to remove logical volume " + absoluteLVName);
595
 
                                }
596
 
                                returnValue = removeVolumeGroup(vgName);
597
 
                                if(returnValue.length() == 0) {
598
 
                                        throw new EucalyptusCloudException("Unable to remove volume group " + vgName);
599
 
                                }
600
 
                                returnValue = removePhysicalVolume(loDevName);
601
 
                                if(returnValue.length() == 0) {
602
 
                                        throw new EucalyptusCloudException("Unable to remove physical volume " + loDevName);
603
 
                                }
604
 
                                returnValue = removeLoopback(loDevName);
605
 
                                File rawFile = new File(DirectStorageInfo.getStorageInfo().getVolumesDir() + "/" + volumeId);
606
 
                                if (rawFile.exists()) {
607
 
                                        if(!rawFile.delete()) {
608
 
                                                throw new EucalyptusCloudException("Unable to delete: " + rawFile.getAbsolutePath());
 
683
                                String returnValue;
 
684
                                deleteLogicalVolume(loDevName, vgName, absoluteLVName);
 
685
                                removeLoopback(loDevName);
 
686
                                if(getLoopback(loDevName).length() != 0) {
 
687
                                        throw new EucalyptusCloudException("Unable to remove loopback device: " + loDevName);
 
688
                                } else {
 
689
                                        LOG.info(loDevName + "was removed.");
 
690
                                }
 
691
                                volumeManager.remove(foundLVMVolumeInfo);
 
692
                                volumeManager.finish();
 
693
                                File volFile = new File (DirectStorageInfo.getStorageInfo().getVolumesDir() + File.separator + volumeId);
 
694
                                if (volFile.exists()) {
 
695
                                        if(!volFile.delete()) {
 
696
                                                LOG.error("Unable to delete: " + volFile.getAbsolutePath());
609
697
                                        }
610
698
                                }
611
 
                                volumeManager.remove(foundLVMVolumeInfo);                               
612
 
                                volumeManager.finish();
613
 
                        } catch(ExecutionException ex) {
 
699
 
 
700
                        } catch(EucalyptusCloudException ex) {
614
701
                                volumeManager.abort();
615
702
                                String error = "Unable to run command: " + ex.getMessage();
616
703
                                LOG.error(error);
622
709
                }
623
710
        }
624
711
 
 
712
        /*LVM is flaky when there are a large number of concurrent removal requests. This workaround serializes lvm cleanup*/
 
713
        private synchronized void deleteLogicalVolume(String loDevName, String vgName,
 
714
                        String absoluteLVName) throws EucalyptusCloudException,
 
715
                        EucalyptusCloudException {
 
716
                if(logicalVolumeExists(absoluteLVName)) {
 
717
                        String returnValue = removeLogicalVolume(absoluteLVName);
 
718
                        if(returnValue.length() == 0) {
 
719
                                throw new EucalyptusCloudException("Unable to remove logical volume " + absoluteLVName + " " + returnValue);
 
720
                        }
 
721
                }
 
722
                if(volumeGroupExists(vgName)) {
 
723
                        String returnValue = removeVolumeGroup(vgName);
 
724
                        if(returnValue.length() == 0) {
 
725
                                throw new EucalyptusCloudException("Unable to remove volume group " + vgName + " " + returnValue);
 
726
                        }
 
727
                }
 
728
                if(physicalVolumeExists(loDevName)) { 
 
729
                        String returnValue = removePhysicalVolume(loDevName);
 
730
                        if(returnValue.length() == 0) {
 
731
                                throw new EucalyptusCloudException("Unable to remove physical volume " + loDevName + " " + returnValue);
 
732
                        }
 
733
                }
 
734
        }
625
735
 
626
 
        public List<String> createSnapshot(String volumeId, String snapshotId) throws EucalyptusCloudException {
 
736
        public List<String> createSnapshot(String volumeId, String snapshotId, Boolean shouldTransferSnapshot) throws EucalyptusCloudException {
627
737
                VolumeEntityWrapperManager volumeManager = new VolumeEntityWrapperManager();
628
738
                LVMVolumeInfo foundLVMVolumeInfo = volumeManager.getVolumeInfo(volumeId);
629
739
                ArrayList<String> returnValues = new ArrayList<String>();
674
784
                                volumeManager = new VolumeEntityWrapperManager();
675
785
                                volumeManager.add(snapshotInfo);
676
786
                                volumeManager.finish();
677
 
                        } catch(ExecutionException ex) {
 
787
                        } catch(EucalyptusCloudException ex) {
678
788
                                if(volumeManager != null)
679
789
                                        volumeManager.abort();
680
790
                                String error = "Unable to run command: " + ex.getMessage();
705
815
                LVMVolumeInfo foundLVMVolumeInfo = volumeManager.getVolumeInfo(snapshotId);
706
816
 
707
817
                if(foundLVMVolumeInfo != null) {
708
 
                        volumeManager.remove(foundLVMVolumeInfo);                       
 
818
                        volumeManager.remove(foundLVMVolumeInfo);
709
819
                        File snapFile = new File (DirectStorageInfo.getStorageInfo().getVolumesDir() + File.separator + foundLVMVolumeInfo.getVolumeId());
 
820
                        volumeManager.finish();
710
821
                        if (snapFile.exists()) {
711
822
                                if(!snapFile.delete()) {
712
823
                                        throw new EucalyptusCloudException("Unable to delete: " + snapFile.getAbsolutePath());
716
827
                        volumeManager.abort();
717
828
                        throw new EucalyptusCloudException("Unable to find snapshot: " + snapshotId);
718
829
                }
719
 
                volumeManager.finish();
720
830
        }
721
831
 
722
832
        public String getVolumeProperty(String volumeId) throws EucalyptusCloudException {
738
848
                                lvmVolumeInfo.setLoDevName(loDevName);
739
849
                                lvmVolumeInfo.setStatus(StorageProperties.Status.available.toString());
740
850
                                volumeManager.add(lvmVolumeInfo);
741
 
                        } catch(ExecutionException ex) {
 
851
                        } catch(EucalyptusCloudException ex) {
742
852
                                volumeManager.abort();
743
853
                                String error = "Unable to run command: " + ex.getMessage();
744
854
                                LOG.error(error);
767
877
                                        if(returnValue.length() <= 0) {
768
878
                                                createLoopback(absoluteLoFileName, loDevName);
769
879
                                        }
770
 
                                } catch(ExecutionException ex) {
 
880
                                } catch(EucalyptusCloudException ex) {
771
881
                                        String error = "Unable to run command: " + ex.getMessage();
772
882
                                        LOG.error(error);
773
883
                                }
775
885
                }
776
886
                //now enable them
777
887
                try {
 
888
                        LOG.info("Scanning volume groups. This might take a little while...");
778
889
                        scanVolumeGroups();
779
 
                } catch (ExecutionException e) {
 
890
                } catch (EucalyptusCloudException e) {
780
891
                        LOG.error(e);
781
892
                }
782
893
                for(LVMVolumeInfo foundVolumeInfo : volumeInfos) {
783
894
                        try {
784
 
                                LOG.info("Scanning volume groups. This might take a little while...");
785
 
                                volumeManager.exportVolume(foundVolumeInfo);
 
895
                                if (foundVolumeInfo.getVgName() != null) {
 
896
                                        volumeManager.exportVolume(foundVolumeInfo);
 
897
                                }
786
898
                        } catch(EucalyptusCloudException ex) {
787
899
                                LOG.error("Unable to reload volume: " + foundVolumeInfo.getVolumeId() + ex);
788
900
                        }               
857
969
                                                String absoluteLVName = lvmRootDirectory + PATH_SEPARATOR + aoeVolumeInfo.getVgName() + PATH_SEPARATOR + aoeVolumeInfo.getLvName();
858
970
                                                try {
859
971
                                                        enableLogicalVolume(absoluteLVName);
860
 
                                                } catch(ExecutionException ex) {
 
972
                                                } catch(EucalyptusCloudException ex) {
861
973
                                                        String error = "Unable to run command: " + ex.getMessage();
862
974
                                                        LOG.error(error);
863
 
                                                        return;
 
975
                                                        throw new EucalyptusCloudException(ex);
864
976
                                                }
865
977
                                                String returnValue = aoeStatus(pid);
866
978
                                                if(returnValue.length() == 0) {
903
1015
                                if(lvmVolumeInfo instanceof ISCSIVolumeInfo) {
904
1016
                                        ISCSIVolumeInfo iscsiVolumeInfo = (ISCSIVolumeInfo) lvmVolumeInfo;
905
1017
                                        String absoluteLVName = lvmRootDirectory + PATH_SEPARATOR + iscsiVolumeInfo.getVgName() + PATH_SEPARATOR + iscsiVolumeInfo.getLvName();
 
1018
                                        try {
 
1019
                                                enableLogicalVolume(absoluteLVName);
 
1020
                                        } catch(EucalyptusCloudException ex) {
 
1021
                                                String error = "Unable to run command: " + ex.getMessage();
 
1022
                                                LOG.error(error);
 
1023
                                                throw new EucalyptusCloudException(ex);
 
1024
                                        }
906
1025
                                        ((ISCSIManager)exportManager).exportTarget(iscsiVolumeInfo.getTid(), iscsiVolumeInfo.getStoreName(), iscsiVolumeInfo.getLun(), absoluteLVName, iscsiVolumeInfo.getStoreUser());
907
 
                                } else {
908
 
                                        ISCSIVolumeInfo volumeInfo = new ISCSIVolumeInfo();
909
 
                                        convertVolumeInfo(lvmVolumeInfo, volumeInfo);
910
 
                                        try {
911
 
                                                unexportVolume(lvmVolumeInfo);
912
 
                                                exportVolume(volumeInfo, volumeInfo.getVgName(), volumeInfo.getLvName());
913
 
                                                add(volumeInfo);
914
 
                                                remove(lvmVolumeInfo);
915
 
                                        } catch(EucalyptusCloudException ex) {
916
 
                                                LOG.error(ex);
917
 
                                        }
 
1026
                                }
 
1027
                        } else {
 
1028
                                ISCSIVolumeInfo volumeInfo = new ISCSIVolumeInfo();
 
1029
                                convertVolumeInfo(lvmVolumeInfo, volumeInfo);
 
1030
                                try {
 
1031
                                        unexportVolume(lvmVolumeInfo);
 
1032
                                        exportVolume(volumeInfo, volumeInfo.getVgName(), volumeInfo.getLvName());
 
1033
                                        add(volumeInfo);
 
1034
                                        remove(lvmVolumeInfo);
 
1035
                                } catch(EucalyptusCloudException ex) {
 
1036
                                        LOG.error(ex);
918
1037
                                }
919
1038
                        }       
920
1039
                }
948
1067
                                                LOG.error(e);
949
1068
                                                return null;
950
1069
                                        }
951
 
                                        return System.getProperty("euca.home") + "," + StorageProperties.STORAGE_HOST + "," + storeName + "," + encryptedPassword;
 
1070
                                        return StorageProperties.STORAGE_HOST + "," + storeName + "," + encryptedPassword;
952
1071
                                }
953
1072
                        }
954
1073
                        return null;
972
1091
                                                if(vbladePidFile.exists()) {
973
1092
                                                        vbladePidFile.delete();
974
1093
                                                }
 
1094
                                                while(aoeStatus(pid).length() > 0) {
 
1095
                                                        LOG.info("Waiting for volume to be unexported...");
 
1096
                                                        try {
 
1097
                                                                Thread.sleep(300);
 
1098
                                                        } catch (InterruptedException e) {
 
1099
                                                                LOG.error(e);
 
1100
                                                        }
 
1101
                                                }
975
1102
                                        }
976
1103
                                }
977
1104
                        } else if(volumeInfo instanceof ISCSIVolumeInfo) {
984
1111
                }
985
1112
 
986
1113
                private void finish() {
987
 
                        entityWrapper.commit();
 
1114
                        try {
 
1115
                                entityWrapper.commit();
 
1116
                        } catch (Exception ex) {
 
1117
                                LOG.error(ex, ex);
 
1118
                                entityWrapper.rollback();
 
1119
                        }
988
1120
                }
989
1121
 
990
1122
                private void abort() {
1038
1170
                }
1039
1171
 
1040
1172
                private String encryptTargetPassword(String password) throws EucalyptusCloudException {
1041
 
                        EntityWrapper<ClusterCredentials> credDb = Authentication.getEntityWrapper( );
1042
1173
                        try {
1043
 
                                ClusterCredentials credentials = credDb.getUnique( new ClusterCredentials( StorageProperties.NAME ) );
1044
 
                                PublicKey ncPublicKey = X509Cert.toCertificate(credentials.getNodeCertificate()).getPublicKey();
1045
 
                                credDb.commit();
 
1174
                                List<ServiceConfiguration> partitionConfigs = ServiceConfigurations.listPartition( ClusterController.class, StorageProperties.NAME );
 
1175
                                ServiceConfiguration clusterConfig = partitionConfigs.get( 0 );
 
1176
                                PublicKey ncPublicKey = Partitions.lookup( clusterConfig ).getNodeCertificate( ).getPublicKey();
1046
1177
                                Cipher cipher = Cipher.getInstance("RSA/ECB/PKCS1Padding");
1047
1178
                                cipher.init(Cipher.ENCRYPT_MODE, ncPublicKey);
1048
1179
                                return new String(Base64.encode(cipher.doFinal(password.getBytes())));        
1049
1180
                        } catch ( Exception e ) {
1050
1181
                                LOG.error( "Unable to encrypt storage target password" );
1051
 
                                credDb.rollback( );
1052
1182
                                throw new EucalyptusCloudException(e.getMessage(), e);
1053
1183
                        }
1054
1184
                }
1055
1185
 
1056
 
                private int exportVolume(LVMVolumeInfo lvmVolumeInfo, String vgName, String lvName) throws EucalyptusCloudException {
 
1186
                private void exportVolume(LVMVolumeInfo lvmVolumeInfo, String vgName, String lvName) throws EucalyptusCloudException {
1057
1187
                        if(exportManager instanceof AOEManager) {
1058
1188
                                AOEVolumeInfo aoeVolumeInfo = (AOEVolumeInfo) lvmVolumeInfo;
1059
1189
                                exportManager.allocateTarget(aoeVolumeInfo);
1102
1232
                                if(pid < 0)
1103
1233
                                        throw new EucalyptusCloudException("invalid vblade pid: " + pid);
1104
1234
                                aoeVolumeInfo.setVbladePid(pid);
1105
 
                                return pid;
1106
1235
                        } else if(exportManager instanceof ISCSIManager) {
1107
1236
                                ISCSIVolumeInfo iscsiVolumeInfo = (ISCSIVolumeInfo) lvmVolumeInfo;
1108
 
                                exportManager.allocateTarget(iscsiVolumeInfo);
 
1237
 
1109
1238
                                String absoluteLVName = lvmRootDirectory + PATH_SEPARATOR + vgName + PATH_SEPARATOR + lvName;
1110
 
                                ((ISCSIManager)exportManager).exportTarget(iscsiVolumeInfo.getTid(), iscsiVolumeInfo.getStoreName(), iscsiVolumeInfo.getLun(), absoluteLVName, iscsiVolumeInfo.getStoreUser());
 
1239
                                int max_tries = 10;
 
1240
                                int i = 0;
 
1241
                                do {
 
1242
                                        exportManager.allocateTarget(iscsiVolumeInfo);
 
1243
                                        try {
 
1244
                                                ((ISCSIManager)exportManager).exportTarget(iscsiVolumeInfo.getTid(), iscsiVolumeInfo.getStoreName(), iscsiVolumeInfo.getLun(), absoluteLVName, iscsiVolumeInfo.getStoreUser());
 
1245
                                                //it worked. break out.
 
1246
                                                i = max_tries;
 
1247
                                        } catch (EucalyptusCloudException e) {
 
1248
                                                LOG.error(e);                           
 
1249
                                        }
 
1250
                                } while (i++ < max_tries);
1111
1251
                        }
1112
 
                        return 0;
1113
1252
                }
1114
1253
        }
1115
1254
 
1192
1331
                volumeManager = new VolumeEntityWrapperManager();
1193
1332
                LVMVolumeInfo volumeInfo = volumeManager.getVolumeInfo(volumeId);
1194
1333
                if(volumeInfo != null) {
1195
 
                        try {
1196
 
                                SystemUtil.run(new String[]{eucaHome + StorageProperties.EUCA_ROOT_WRAPPER, 
1197
 
                                                "dd", "if=" + volumePath, 
1198
 
                                                "of=" + lvmRootDirectory + File.separator + volumeInfo.getVgName() + 
1199
 
                                                File.separator + volumeInfo.getLvName(), "bs=" + StorageProperties.blockSize});                 
1200
 
                        } catch (ExecutionException e) {
1201
 
                                LOG.error(e);
1202
 
                                throw new EucalyptusCloudException(e);
1203
 
                        }
 
1334
                        SystemUtil.run(new String[]{eucaHome + StorageProperties.EUCA_ROOT_WRAPPER, 
 
1335
                                        "dd", "if=" + volumePath, 
 
1336
                                        "of=" + lvmRootDirectory + File.separator + volumeInfo.getVgName() + 
 
1337
                                        File.separator + volumeInfo.getLvName(), "bs=" + StorageProperties.blockSize});
1204
1338
                } else {
1205
1339
                        volumeManager.abort();
1206
1340
                        throw new EucalyptusCloudException("Unable to find volume with id: " + volumeId);
1233
1367
                }
1234
1368
                volumeManager.finish();
1235
1369
                String snapFileName = getStorageRootDirectory() + File.separator + snapshotId;
1236
 
                try {
1237
 
                        SystemUtil.run(new String[]{eucaHome + StorageProperties.EUCA_ROOT_WRAPPER, 
1238
 
                                        "dd", "if=" + snapPath, 
1239
 
                                        "of=" + snapFileName, "bs=" + StorageProperties.blockSize});                    
1240
 
                } catch (ExecutionException e) {
1241
 
                        LOG.error(e);
1242
 
                        throw new EucalyptusCloudException(e);
1243
 
                }
 
1370
                SystemUtil.run(new String[]{eucaHome + StorageProperties.EUCA_ROOT_WRAPPER, 
 
1371
                                "dd", "if=" + snapPath, 
 
1372
                                "of=" + snapFileName, "bs=" + StorageProperties.blockSize});
1244
1373
                volumeManager = new VolumeEntityWrapperManager();
1245
1374
                LVMVolumeInfo snapshotInfo = volumeManager.getVolumeInfo();
1246
1375
                snapshotInfo.setVolumeId(snapshotId);
1250
1379
                volumeManager.add(snapshotInfo);
1251
1380
                volumeManager.finish();
1252
1381
        }
 
1382
 
 
1383
        @Override
 
1384
        public String attachVolume(String volumeId, List<String> nodeIqns)
 
1385
        throws EucalyptusCloudException {
 
1386
                return getVolumeProperty(volumeId);
 
1387
        }
 
1388
 
 
1389
        @Override
 
1390
        public void detachVolume(String volumeId, String nodeIqn)
 
1391
        throws EucalyptusCloudException {
 
1392
        }
 
1393
 
 
1394
        @Override
 
1395
        public void checkReady() throws EucalyptusCloudException {
 
1396
                //check if binaries exist, commands can be executed, etc.
 
1397
                String eucaHomeDir = System.getProperty("euca.home");
 
1398
                if(eucaHomeDir == null) {
 
1399
                        throw new EucalyptusCloudException("euca.home not set");
 
1400
                }
 
1401
                eucaHome = eucaHomeDir;
 
1402
                if(!new File(eucaHome + StorageProperties.EUCA_ROOT_WRAPPER).exists()) {
 
1403
                        throw new EucalyptusCloudException("root wrapper (euca_rootwrap) does not exist in " + eucaHome + StorageProperties.EUCA_ROOT_WRAPPER);
 
1404
                }
 
1405
                File varDir = new File(eucaHome + EUCA_VAR_RUN_PATH);
 
1406
                if(!varDir.exists()) {
 
1407
                        varDir.mkdirs();
 
1408
                }
 
1409
        }
 
1410
 
 
1411
        @Override
 
1412
        public void stop() throws EucalyptusCloudException {
 
1413
                // TODO Auto-generated method stub
 
1414
 
 
1415
        }
 
1416
 
 
1417
        @Override
 
1418
        public void disable() throws EucalyptusCloudException {
 
1419
                // TODO Auto-generated method stub
 
1420
 
 
1421
        }
 
1422
 
 
1423
        @Override
 
1424
        public void enable() throws EucalyptusCloudException {
 
1425
                // TODO Auto-generated method stub
 
1426
 
 
1427
        }
1253
1428
}