/*************************************************************************
* Copyright 2013 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.entities;
import java.util.NoSuchElementException;
import javax.persistence.EntityTransaction;
import org.apache.log4j.Logger;
import org.junit.Ignore;
import com.eucalyptus.entities.Entities;
import com.eucalyptus.entities.TransactionException;
import com.eucalyptus.util.EucalyptusCloudException;
import com.google.common.base.Function;
/**
* Tests for Volume-related entities
*/
@Ignore("Manual development test")
public class VolumeEntitiesTest {
private static final Logger LOG = Logger.getLogger(VolumeEntitiesTest.class);
private static final String fakeSC = "testing_non_sc";
public static VolumeInfo addFakeVolume(String volumeId) {
EntityTransaction db = Entities.get(VolumeInfo.class);
VolumeInfo vol = new VolumeInfo(volumeId);
vol.setScName(fakeSC);
vol.setSize(1);
vol.setStatus("available");
vol.updateTimeStamps();
Entities.persist(vol);
db.commit();
return vol;
}
public static VolumeToken createFakeToken(VolumeInfo srcVol) {
EntityTransaction db = Entities.get(VolumeInfo.class);
try {
LOG.info("Merging entity");
VolumeInfo volEntity = Entities.merge(srcVol);
LOG.info("Creating token");
VolumeToken tok = volEntity.getOrCreateAttachmentToken();
LOG.info("Got token: " + tok.getToken());
return tok;
} catch (Exception e) {
LOG.error(e);
} finally {
if (db.isActive()) {
db.commit();
} else {
db.rollback();
}
}
return null;
}
public static void testAdd(String volumeName) {
VolumeInfo volInfo = addFakeVolume(volumeName);
VolumeToken tok = createFakeToken(volInfo);
try {
tok.addExport("1.1.1.1", "iqn-123", "fake-connect-string");
} catch (Exception e) {
LOG.error(e);
}
}
public static void testRemove(String volumeName) {
VolumeInfo vol = new VolumeInfo();
vol.setVolumeId(volumeName);
vol.setScName(fakeSC);
EntityTransaction db = Entities.get(VolumeInfo.class);
try {
VolumeInfo volEntity = Entities.uniqueResult(vol);
VolumeToken tok = volEntity.getCurrentValidToken();
tok.invalidateExport("1.1.1.1", "iqn-123");
} catch (Exception e) {
LOG.error(e);
} finally {
db.commit();
}
}
public static void printVolume(String vol) {
EntityTransaction db = Entities.get(VolumeInfo.class);
try {
VolumeInfo example = new VolumeInfo();
example.setVolumeId(vol);
VolumeInfo volEntity = Entities.uniqueResult(example);
LOG.info("Volume - " + volEntity.getVolumeId() + " - " + volEntity.getStatus());
for (VolumeToken tok : volEntity.getAttachmentTokens()) {
LOG.info("Volume - " + tok.getVolume().getVolumeId() + " -- " + tok.getToken() + " - " + tok.getIsValid());
for (VolumeExportRecord rec : tok.getExportRecords()) {
LOG.info("Token - " + tok.getToken() + rec.getHostIp() + " - " + rec.getHostIqn() + " - " + rec.getConnectionString() + " - "
+ rec.getIsActive());
}
}
VolumeToken test = volEntity.getCurrentValidToken();
if (test == null) {
LOG.info("Null current valid token");
} else {
LOG.info("Current valid token : " + test.getToken());
}
} catch (Exception e) {
LOG.error(e);
} finally {
db.commit();
}
}
// TODO: testing only!
public static void TestExport(String volumeId) {
final String ip = "1.1.1.1";
final String iqn = "fake-iqn";
final String connectionString = "fake-connect-string-12-1223123";
Function<VolumeInfo, VolumeExportRecord> exportAndAttach = new Function<VolumeInfo, VolumeExportRecord>() {
@Override
public VolumeExportRecord apply(VolumeInfo volume) {
VolumeToken tokenInfo = null;
VolumeInfo volEntity = Entities.merge(volume);
LOG.info("TESTING#: Set of tokens");
for (VolumeToken tok : volEntity.getAttachmentTokens()) {
LOG.info("TESTING#: " + tok.getToken() + " - " + tok.getIsValid());
LOG.info("TESTING#: listing export records");
for (VolumeExportRecord rec : tok.getExportRecords()) {
LOG.info("TESTING#: " + rec.getHostIp() + " - " + rec.getHostIqn() + " - " + rec.getConnectionString() + " - " + rec.getIsActive());
}
LOG.info("TESTING#: done listing export records");
}
LOG.info("TESTING#: Done listing tokens");
try {
tokenInfo = volEntity.getCurrentValidToken();
if (tokenInfo == null) {
LOG.info("TESTING#: No valid token found");
LOG.info("TESTING#: Creating new token for testing");
tokenInfo = volEntity.getOrCreateAttachmentToken();
if (tokenInfo == null) {
throw new Exception("Failed to create new attachment token");
}
} else {
LOG.info("TESTING#: current valid token : " + tokenInfo.getToken());
}
} catch (Exception e) {
LOG.error("TESTING#: Could not check for valid token", e);
return null;
}
VolumeExportRecord export = null;
// Normally do the actual export here...
try {
// addExport must be idempotent, if one exists a new is not added with same data
LOG.info("TESTING#: adding export");
tokenInfo.addExport(ip, iqn, connectionString);
LOG.info("TESTING#: done adding export");
} catch (Exception e) {
LOG.error("TESTING#: Could not export volume " + volEntity.getVolumeId() + " failed to add export record");
return null;
}
try {
LOG.info("TESTING#: getting valid export");
export = tokenInfo.getValidExport(ip, iqn);
if (export != null) {
LOG.info("TESTING#: got valid export " + export.getHostIp() + " - " + export.getHostIqn() + " - " + export.getConnectionString());
} else {
throw new EucalyptusCloudException("Null valid export returned");
}
} catch (EucalyptusCloudException e) {
LOG.error("TESTING#: failed to get valid export", e);
}
return export;
}
};
Function<String, VolumeInfo> createFakeVolume = new Function<String, VolumeInfo>() {
@Override
public VolumeInfo apply(String volumeId) {
LOG.info("TESTING#: Creating fake volume record with id : " + volumeId);
VolumeInfo fakeVolume = new VolumeInfo(volumeId);
fakeVolume.setScName("fake_sc");
fakeVolume.setSize(1);
fakeVolume.setStatus("available");
fakeVolume.updateTimeStamps();
Entities.persist(fakeVolume);
LOG.info("TESTING#: done persisting fake volume");
return fakeVolume;
}
};
VolumeInfo searchVol = new VolumeInfo(volumeId);
searchVol.setScName("fake_sc");
EntityTransaction db = Entities.get(VolumeInfo.class);
VolumeInfo vol = null;
try {
vol = Entities.uniqueResult(searchVol);
db.commit();
} catch (NoSuchElementException e) {
LOG.info("TESTING#: No volume found, creating", e);
vol = Entities.asTransaction(VolumeInfo.class, createFakeVolume).apply(volumeId);
} catch (TransactionException e) {
LOG.error("TESTING#: Failed to Export due to db error", e);
return;
} finally {
if (db.isActive()) {
db.rollback();
}
}
try {
Entities.asTransaction(VolumeInfo.class, exportAndAttach).apply(vol);
} catch (Exception e) {
LOG.error("TESTING#: Failed ExportVolume transaction due to: " + e.getMessage(), e);
}
}
/**
* @param args
*/
public static void main(String[] args) {
String volName = "vol-fake";
if (args.length > 1) {
volName = args[1];
}
LOG.info("Testing add!");
testAdd(volName);
LOG.info("Testing remove!");
testRemove(volName);
LOG.info("Done with test!");
}
}