/************************************************************************* * Copyright 2009-2014 Eucalyptus Systems, Inc. * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; version 3 of the License. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see http://www.gnu.org/licenses/. * * Please contact Eucalyptus Systems, Inc., 6755 Hollister Ave., Goleta * CA 93117, USA or visit http://www.eucalyptus.com/licenses/ if you need * additional information or have any questions. ************************************************************************/ package com.eucalyptus.blockstorage; import static org.junit.Assert.assertTrue; import java.util.Calendar; import java.util.Date; import java.util.List; import org.jmock.Expectations; import org.jmock.integration.junit4.JUnitRuleMockery; import org.junit.After; import org.junit.AfterClass; import org.junit.BeforeClass; import org.junit.Rule; import org.junit.Test; import com.eucalyptus.blockstorage.async.ExpiredVolumeCleaner; import com.eucalyptus.blockstorage.async.FailedVolumeCleaner; import com.eucalyptus.blockstorage.async.VolumeDeleter; import com.eucalyptus.blockstorage.entities.VolumeInfo; import com.eucalyptus.blockstorage.util.StorageProperties; import com.eucalyptus.entities.Entities; import com.eucalyptus.entities.TransactionResource; /** * Created by wesw on 6/20/14. */ public class VolumeCleanupTest { @Rule public JUnitRuleMockery context = new JUnitRuleMockery(); @BeforeClass public static void setupClass() { try { BlockStorageUnitTestSupport.setupBlockStoragePersistenceContext(); BlockStorageUnitTestSupport.setupAuthPersistenceContext(); BlockStorageUnitTestSupport.initializeAuth(1, 1); } catch (Exception e) { e.printStackTrace(); } } @After public void teardown() { BlockStorageUnitTestSupport.flushBlockStorageEntities(); } @AfterClass public static void teardownClass() { BlockStorageUnitTestSupport.tearDownBlockStoragePersistenceContext(); BlockStorageUnitTestSupport.tearDownAuthPersistenceContext(); } @Test public void cleanDeletingVolumes() throws Exception { Calendar twoDaysAgo = Calendar.getInstance(); twoDaysAgo.add(Calendar.HOUR, -48); VolumeInfo good = new VolumeInfo(); good.setStatus(StorageProperties.Status.deleted.toString()); good.setSize(new Integer(1)); good.setUserName("unittestuser0"); good.setVolumeId("vol-0000"); good.setSnapshotId("snap-0000"); good.setCreateTime(twoDaysAgo.getTime()); good.setDeletionTime(twoDaysAgo.getTime()); good.setZone("eucalyptus"); VolumeInfo failOne = new VolumeInfo(); failOne.setStatus(StorageProperties.Status.deleting.toString()); failOne.setSize(new Integer(1)); failOne.setUserName("unittestuser0"); failOne.setVolumeId("vol-0001"); failOne.setSnapshotId("snap-0001"); failOne.setCreateTime(new Date()); failOne.setZone("eucalyptus"); VolumeInfo failTwo = new VolumeInfo(); failTwo.setStatus(StorageProperties.Status.deleting.toString()); failTwo.setSize(new Integer(1)); failTwo.setUserName("unittestuser0"); failTwo.setVolumeId("vol-0002"); failTwo.setSnapshotId("snap-0002"); failTwo.setCreateTime(new Date()); failTwo.setZone("eucalyptus"); try (TransactionResource tran = Entities.transactionFor(VolumeInfo.class)) { Entities.persist(good); Entities.persist(failOne); Entities.persist(failTwo); tran.commit(); } final LogicalStorageManager storageManager = context.mock(LogicalStorageManager.class); context.checking(new Expectations() { { exactly(2).of(storageManager).deleteVolume(with(any(String.class))); } }); // Test VolumeDeleter VolumeDeleter vct = new VolumeDeleter(storageManager); vct.run(); List<VolumeInfo> remaining; try (TransactionResource tran = Entities.transactionFor(VolumeInfo.class)) { remaining = Entities.query(new VolumeInfo()); tran.commit(); } assertTrue("expected to have a result set querying the eucalyptus_storage persistence context", remaining != null); assertTrue("expected 3 VolumeInfos to still exist but found " + remaining.size(), remaining.size() == 3); try (TransactionResource tran = Entities.transactionFor(VolumeInfo.class)) { VolumeInfo example = new VolumeInfo(); example.setStatus(StorageProperties.Status.deleted.toString()); remaining = Entities.query(example); tran.commit(); } assertTrue("expected to have a result set querying the eucalyptus_storage persistence context for deleted volumeinfos", remaining != null); assertTrue("expected 3 VolumeInfos with deleted status to exist but found " + remaining.size(), remaining.size() == 3); // Test ExpiredVolumeCleaner ExpiredVolumeCleaner evc = new ExpiredVolumeCleaner(); evc.run(); try (TransactionResource tran = Entities.transactionFor(VolumeInfo.class)) { remaining = Entities.query(new VolumeInfo()); tran.commit(); } assertTrue("expected to have a result set querying the eucalyptus_storage persistence context", remaining != null); assertTrue("expected 2 VolumeInfos to still exist but found " + remaining.size(), remaining.size() == 2); try (TransactionResource tran = Entities.transactionFor(VolumeInfo.class)) { VolumeInfo example = new VolumeInfo(); example.setStatus(StorageProperties.Status.deleted.toString()); remaining = Entities.query(example); tran.commit(); } assertTrue("expected to have a result set querying the eucalyptus_storage persistence context for deleted volumeinfos", remaining != null); assertTrue("expected two VolumeInfos with deleted status to exist but found " + remaining.size(), remaining.size() == 2); } @Test public void cleanFailedVolumesTest() throws Exception { Calendar twoDaysAgo = Calendar.getInstance(); twoDaysAgo.add(Calendar.HOUR, -48); VolumeInfo good = new VolumeInfo(); good.setStatus(StorageProperties.Status.available.toString()); good.setSize(new Integer(1)); good.setUserName("unittestuser0"); good.setVolumeId("vol-0000"); good.setSnapshotId("snap-0000"); good.setCreateTime(new Date()); good.setZone("eucalyptus"); VolumeInfo failOne = new VolumeInfo(); failOne.setStatus(StorageProperties.Status.failed.toString()); failOne.setSize(new Integer(1)); failOne.setUserName("unittestuser0"); failOne.setVolumeId("vol-0001"); failOne.setSnapshotId("snap-0001"); failOne.setCreateTime(new Date()); failOne.setZone("eucalyptus"); VolumeInfo failTwo = new VolumeInfo(); failTwo.setStatus(StorageProperties.Status.failed.toString()); failTwo.setSize(new Integer(1)); failTwo.setUserName("unittestuser0"); failTwo.setVolumeId("vol-0002"); failTwo.setSnapshotId("snap-0002"); failTwo.setCreateTime(new Date()); failTwo.setZone("eucalyptus"); failTwo.setDeletionTime(twoDaysAgo.getTime()); try (TransactionResource tran = Entities.transactionFor(VolumeInfo.class)) { good = Entities.persist(good); failOne = Entities.persist(failOne); failTwo = Entities.persist(failTwo); tran.commit(); } final LogicalStorageManager storageManager = context.mock(LogicalStorageManager.class); context.checking(new Expectations() { { oneOf(storageManager).cleanVolume(with(any(String.class))); } }); // Test FailedVolumeCleaner FailedVolumeCleaner fvc = new FailedVolumeCleaner(storageManager); fvc.run(); List<VolumeInfo> remaining; try (TransactionResource tran = Entities.transactionFor(VolumeInfo.class)) { remaining = Entities.query(new VolumeInfo()); tran.commit(); } assertTrue("expected to have a result set querying the eucalyptus_storage persistence context", remaining != null); assertTrue("expected 3 VolumeInfos to still exist, but found " + remaining.size(), remaining.size() == 3); try (TransactionResource tran = Entities.transactionFor(VolumeInfo.class)) { VolumeInfo example = new VolumeInfo(); example.setStatus(StorageProperties.Status.failed.toString()); remaining = Entities.query(example); tran.commit(); } assertTrue("expected to have a result set querying the eucalyptus_storage persistence context for deleted volumeinfos", remaining != null); assertTrue("expected two VolumeInfos with failed status to exist but found " + remaining.size(), remaining.size() == 2); // Test ExpiredVolumeCleaner ExpiredVolumeCleaner evc = new ExpiredVolumeCleaner(); evc.run(); try (TransactionResource tran = Entities.transactionFor(VolumeInfo.class)) { remaining = Entities.query(new VolumeInfo()); tran.commit(); } assertTrue("expected to have a result set querying the eucalyptus_storage persistence context", remaining != null); assertTrue("expected 2 VolumeInfos to still exist, but found " + remaining.size(), remaining.size() == 2); try (TransactionResource tran = Entities.transactionFor(VolumeInfo.class)) { VolumeInfo example = new VolumeInfo(); example.setStatus(StorageProperties.Status.failed.toString()); remaining = Entities.query(example); tran.commit(); } assertTrue("expected to have a result set querying the eucalyptus_storage persistence context", remaining != null); assertTrue("expected one VolumeInfo in failed state to exist, but found " + remaining.size(), remaining.size() == 1); assertTrue("expected a valid deletionTime but got null", remaining.get(0).getDeletionTime() != null); assertTrue("expected snapshot id to be snap-0001 but got " + remaining.get(0).getSnapshotId(), remaining.get(0).getSnapshotId().equals("snap-0001")); } }