CLOUDSTACK-3400: add swift support

This commit is contained in:
Edison Su 2013-07-13 01:51:55 -07:00
parent 0c1ae20e77
commit 8f4575e877
14 changed files with 279 additions and 393 deletions

View File

@ -17,26 +17,25 @@
package com.cloud.agent.api.to;
import com.cloud.storage.DataStoreRole;
import com.cloud.utils.SwiftUtil;
public class SwiftTO implements DataStoreTO {
public class SwiftTO implements DataStoreTO, SwiftUtil.SwiftClientCfg {
Long id;
String url;
String account;
String userName;
String key;
String container;
public SwiftTO() { }
public SwiftTO(Long id, String url, String account, String userName, String key,
String container) {
public SwiftTO(Long id, String url, String account, String userName, String key
) {
this.id = id;
this.url = url;
this.account = account;
this.userName = userName;
this.key = key;
this.container = container;
}
public Long getId() {
@ -64,9 +63,8 @@ public class SwiftTO implements DataStoreTO {
return DataStoreRole.Image;
}
public String getContainer() {
return this.container;
@Override
public String getEndPoint() {
return this.url;
}
}

View File

@ -316,7 +316,6 @@
<bean id="storagePoolHostDaoImpl" class="com.cloud.storage.dao.StoragePoolHostDaoImpl" />
<bean id="storagePoolJoinDaoImpl" class="com.cloud.api.query.dao.StoragePoolJoinDaoImpl" />
<bean id="storagePoolWorkDaoImpl" class="com.cloud.storage.dao.StoragePoolWorkDaoImpl" />
<bean id="swiftDaoImpl" class="com.cloud.storage.dao.SwiftDaoImpl" />
<bean id="syncQueueDaoImpl" class="com.cloud.async.dao.SyncQueueDaoImpl" />
<bean id="syncQueueItemDaoImpl" class="com.cloud.async.dao.SyncQueueItemDaoImpl" />
<bean id="templatePrimaryDataStoreDaoImpl" class="org.apache.cloudstack.storage.volume.db.TemplatePrimaryDataStoreDaoImpl" />
@ -356,7 +355,6 @@
<bean id="vMTemplateHostDaoImpl" class="com.cloud.storage.dao.VMTemplateHostDaoImpl" />
<bean id="vMTemplatePoolDaoImpl" class="com.cloud.storage.dao.VMTemplatePoolDaoImpl" />
<bean id="vMTemplateS3DaoImpl" class="com.cloud.storage.dao.VMTemplateS3DaoImpl" />
<bean id="vMTemplateSwiftDaoImpl" class="com.cloud.storage.dao.VMTemplateSwiftDaoImpl" />
<bean id="vMTemplateZoneDaoImpl" class="com.cloud.storage.dao.VMTemplateZoneDaoImpl" />
<bean id="versionDaoImpl" class="com.cloud.upgrade.dao.VersionDaoImpl" />
<bean id="virtualRouterProviderDaoImpl" class="com.cloud.network.dao.VirtualRouterProviderDaoImpl" />
@ -793,7 +791,6 @@
<bean id="snapshotManagerImpl" class="com.cloud.storage.snapshot.SnapshotManagerImpl" />
<bean id="snapshotSchedulerImpl" class="com.cloud.storage.snapshot.SnapshotSchedulerImpl" />
<bean id="storageNetworkManagerImpl" class="com.cloud.network.StorageNetworkManagerImpl" />
<bean id="swiftManagerImpl" class="com.cloud.storage.swift.SwiftManagerImpl" />
<bean id="syncQueueManagerImpl" class="com.cloud.async.SyncQueueManagerImpl" />
<bean id="taggedResourceManagerImpl" class="com.cloud.tags.TaggedResourceManagerImpl" />
<bean id="resourceMetaDataManagerImpl" class="com.cloud.metadata.ResourceMetaDataManagerImpl" />

View File

@ -241,10 +241,6 @@ deleteAlerts=1
#### system capacity commands
listCapacity=3
#### swift commands
addSwift=1
listSwifts=1
#### s3 commands
addS3=1
listS3s=1

View File

@ -45,6 +45,7 @@ public class DownloadCommand extends AbstractDownloadCommand implements Internal
private ResourceType resourceType = ResourceType.TEMPLATE;
private String installPath;
private DataStoreTO _store;
private DataStoreTO cacheStore;
protected DownloadCommand() {
}
@ -178,7 +179,11 @@ public class DownloadCommand extends AbstractDownloadCommand implements Internal
this.installPath = installPath;
}
public void setCacheStore(DataStoreTO cacheStore) {
this.cacheStore = cacheStore;
}
public DataStoreTO getCacheStore() {
return this.cacheStore;
}
}

View File

@ -1,108 +0,0 @@
// Licensed to the Apache Software Foundation (ASF) under one
// or more contributor license agreements. See the NOTICE file
// distributed with this work for additional information
// regarding copyright ownership. The ASF licenses this file
// to you under the Apache License, Version 2.0 (the
// "License"); you may not use this file except in compliance
// with the License. You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing,
// software distributed under the License is distributed on an
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
// KIND, either express or implied. See the License for the
// specific language governing permissions and limitations
// under the License.
package com.cloud.storage;
import java.util.Date;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.Table;
import com.cloud.utils.db.GenericDaoBase;
import org.apache.cloudstack.api.InternalIdentity;
/**
* Join table for swift and templates
*
*
*/
@Entity
@Table(name = "template_swift_ref")
public class VMTemplateSwiftVO implements InternalIdentity {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
Long id;
@Column(name = "swift_id")
private long swiftId;
@Column(name = "template_id")
private long templateId;
@Column(name = GenericDaoBase.CREATED_COLUMN)
private Date created = null;
@Column(name = "path")
private String path;
@Column(name = "size")
private long size;
@Column(name = "physical_size")
private long physicalSize;
public VMTemplateSwiftVO(long swiftId, long templateId, Date created, String path, long size, long physicalSize) {
this.swiftId = swiftId;
this.templateId = templateId;
this.created = created;
this.path = path;
this.size = size;
this.physicalSize = physicalSize;
}
protected VMTemplateSwiftVO() {
}
public long getTemplateId() {
return templateId;
}
public long getId() {
return id;
}
public Date getCreated() {
return created;
}
public String getPath() {
return path;
}
public long getSwiftId() {
return swiftId;
}
public long getSize() {
return size;
}
public long getPhysicalSize() {
return physicalSize;
}
@Override
public String toString() {
return new StringBuilder("TmplSwift[").append(id).append("-").append(templateId).append("-").append(swiftId)
.append("]").toString();
}
}

View File

@ -1,37 +0,0 @@
// Licensed to the Apache Software Foundation (ASF) under one
// or more contributor license agreements. See the NOTICE file
// distributed with this work for additional information
// regarding copyright ownership. The ASF licenses this file
// to you under the Apache License, Version 2.0 (the
// "License"); you may not use this file except in compliance
// with the License. You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing,
// software distributed under the License is distributed on an
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
// KIND, either express or implied. See the License for the
// specific language governing permissions and limitations
// under the License.
package com.cloud.storage.dao;
import java.util.List;
import com.cloud.storage.VMTemplateSwiftVO;
import com.cloud.utils.db.GenericDao;
/**
*
*
*/
public interface VMTemplateSwiftDao extends GenericDao<VMTemplateSwiftVO, Long> {
List<VMTemplateSwiftVO> listBySwiftId(long id);
List<VMTemplateSwiftVO> listByTemplateId(long templateId);
VMTemplateSwiftVO findBySwiftTemplate(long swiftId, long templateId);
VMTemplateSwiftVO findOneByTemplateId(long templateId);
}

View File

@ -1,87 +0,0 @@
// Licensed to the Apache Software Foundation (ASF) under one
// or more contributor license agreements. See the NOTICE file
// distributed with this work for additional information
// regarding copyright ownership. The ASF licenses this file
// to you under the Apache License, Version 2.0 (the
// "License"); you may not use this file except in compliance
// with the License. You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing,
// software distributed under the License is distributed on an
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
// KIND, either express or implied. See the License for the
// specific language governing permissions and limitations
// under the License.
package com.cloud.storage.dao;
import java.util.Collections;
import java.util.List;
import javax.ejb.Local;
import org.apache.log4j.Logger;
import org.springframework.stereotype.Component;
import com.cloud.storage.VMTemplateSwiftVO;
import com.cloud.utils.db.GenericDaoBase;
import com.cloud.utils.db.SearchBuilder;
import com.cloud.utils.db.SearchCriteria;
/**
*
*
*/
@Component
@Local(value = { VMTemplateSwiftDao.class })
public class VMTemplateSwiftDaoImpl extends GenericDaoBase<VMTemplateSwiftVO, Long> implements VMTemplateSwiftDao {
public static final Logger s_logger = Logger.getLogger(VMTemplateSwiftDaoImpl.class.getName());
protected final SearchBuilder<VMTemplateSwiftVO> AllFieldSearch;
public VMTemplateSwiftDaoImpl() {
AllFieldSearch = createSearchBuilder();
AllFieldSearch.and("swift_id", AllFieldSearch.entity().getSwiftId(), SearchCriteria.Op.EQ);
AllFieldSearch.and("template_id", AllFieldSearch.entity().getTemplateId(), SearchCriteria.Op.EQ);
AllFieldSearch.done();
}
@Override
public List<VMTemplateSwiftVO> listBySwiftId(long id) {
SearchCriteria<VMTemplateSwiftVO> sc = AllFieldSearch.create();
sc.setParameters("swift_id", id);
return listBy(sc);
}
@Override
public List<VMTemplateSwiftVO> listByTemplateId(long templateId) {
SearchCriteria<VMTemplateSwiftVO> sc = AllFieldSearch.create();
sc.setParameters("template_id", templateId);
return listBy(sc);
}
@Override
public VMTemplateSwiftVO findOneByTemplateId(long templateId) {
SearchCriteria<VMTemplateSwiftVO> sc = AllFieldSearch.create();
sc.setParameters("template_id", templateId);
List<VMTemplateSwiftVO> list = listBy(sc);
if (list == null || list.size() < 1) {
return null;
} else {
Collections.shuffle(list);
return list.get(0);
}
}
@Override
public VMTemplateSwiftVO findBySwiftTemplate(long swiftId, long templateId) {
SearchCriteria<VMTemplateSwiftVO> sc = AllFieldSearch.create();
sc.setParameters("swift_id", swiftId);
sc.setParameters("template_id", templateId);
return findOneBy(sc);
}
}

View File

@ -79,7 +79,6 @@ import com.cloud.storage.download.DownloadMonitorImpl;
import com.cloud.storage.s3.S3Manager;
import com.cloud.storage.secondary.SecondaryStorageVmManager;
import com.cloud.storage.snapshot.SnapshotManager;
import com.cloud.storage.swift.SwiftManager;
import com.cloud.tags.dao.ResourceTagsDaoImpl;
import com.cloud.template.TemplateManager;
import com.cloud.user.AccountManager;
@ -177,11 +176,6 @@ public class ChildTestConfiguration extends TestConfiguration {
return Mockito.mock(VolumeManager.class);
}
@Bean
public SwiftManager switfMgr() {
return Mockito.mock(SwiftManager.class);
}
@Bean
public ManagementServer server() {
return Mockito.mock(ManagementServer.class);

View File

@ -53,13 +53,15 @@ public class SwiftImageStoreDriverImpl extends BaseImageStoreDriverImpl {
ImageStoreDetailsDao _imageStoreDetailsDao;
@Inject
EndPointSelector _epSelector;
@Inject
StorageCacheManager cacheManager;
@Override
public DataStoreTO getStoreTO(DataStore store) {
ImageStoreImpl imgStore = (ImageStoreImpl) store;
Map<String, String> details = _imageStoreDetailsDao.getDetails(imgStore.getId());
return new SwiftTO(imgStore.getId(), imgStore.getUri(), details.get(ApiConstants.ACCOUNT),
details.get(ApiConstants.USERNAME), details.get(ApiConstants.KEY), details.get(ApiConstants.S3_BUCKET_NAME));
details.get(ApiConstants.USERNAME), details.get(ApiConstants.KEY));
}
@Override
@ -71,7 +73,9 @@ public class SwiftImageStoreDriverImpl extends BaseImageStoreDriverImpl {
public void createAsync(DataStore dataStore, DataObject data, AsyncCompletionCallback<CreateCmdResult> callback) {
Long maxTemplateSizeInBytes = getMaxTemplateSizeInBytes();
VirtualMachineTemplate tmpl = _templateDao.findById(data.getId());
DataStore cacheStore = cacheManager.getCacheStorage(dataStore.getScope());
DownloadCommand dcmd = new DownloadCommand((TemplateObjectTO)(data.getTO()), maxTemplateSizeInBytes);
dcmd.setCacheStore(cacheStore.getTO());
dcmd.setProxy(getHttpProxy());
EndPoint ep = _epSelector.select(data);

View File

@ -236,7 +236,6 @@ import com.cloud.storage.StorageStats;
import com.cloud.storage.UploadVO;
import com.cloud.storage.VMTemplateHostVO;
import com.cloud.storage.VMTemplateS3VO;
import com.cloud.storage.VMTemplateSwiftVO;
import com.cloud.storage.VMTemplateVO;
import com.cloud.storage.Volume;
import com.cloud.storage.Volume.Type;
@ -253,7 +252,6 @@ import com.cloud.storage.dao.VMTemplateDao;
import com.cloud.storage.dao.VMTemplateDetailsDao;
import com.cloud.storage.dao.VMTemplateHostDao;
import com.cloud.storage.dao.VMTemplateS3Dao;
import com.cloud.storage.dao.VMTemplateSwiftDao;
import com.cloud.storage.dao.VolumeDao;
import com.cloud.storage.dao.VolumeHostDao;
import com.cloud.storage.snapshot.SnapshotPolicy;
@ -336,7 +334,6 @@ public class ApiDBUtils {
static PrimaryDataStoreDao _storagePoolDao;
static VMTemplateDao _templateDao;
static VMTemplateDetailsDao _templateDetailsDao;
static VMTemplateSwiftDao _templateSwiftDao;
static VMTemplateS3Dao _templateS3Dao;
static UploadDao _uploadDao;
static UserDao _userDao;
@ -445,7 +442,6 @@ public class ApiDBUtils {
@Inject private PrimaryDataStoreDao storagePoolDao;
@Inject private VMTemplateDao templateDao;
@Inject private VMTemplateDetailsDao templateDetailsDao;
@Inject private VMTemplateSwiftDao templateSwiftDao;
@Inject private VMTemplateS3Dao templateS3Dao;
@Inject private UploadDao uploadDao;
@Inject private UserDao userDao;
@ -554,7 +550,6 @@ public class ApiDBUtils {
_storagePoolDao = storagePoolDao;
_templateDao = templateDao;
_templateDetailsDao = templateDetailsDao;
_templateSwiftDao = templateSwiftDao;
_templateS3Dao = templateS3Dao;
_uploadDao = uploadDao;
_userDao = userDao;
@ -894,10 +889,6 @@ public class ApiDBUtils {
return template;
}
public static VMTemplateSwiftVO findTemplateSwiftRef(long templateId) {
return _templateSwiftDao.findOneByTemplateId(templateId);
}
public static VMTemplateS3VO findTemplateS3Ref(long templateId) {
return _templateS3Dao.findOneByTemplateId(templateId);
}

View File

@ -139,7 +139,6 @@ import com.cloud.storage.dao.UploadDao;
import com.cloud.storage.dao.VMTemplateDao;
import com.cloud.storage.dao.VMTemplatePoolDao;
import com.cloud.storage.dao.VMTemplateS3Dao;
import com.cloud.storage.dao.VMTemplateSwiftDao;
import com.cloud.storage.dao.VolumeDao;
import com.cloud.storage.dao.VolumeDetailsDao;
import com.cloud.storage.download.DownloadMonitor;
@ -237,8 +236,6 @@ public class VolumeManagerImpl extends ManagerBase implements VolumeManager {
@Inject
protected VMTemplatePoolDao _vmTemplatePoolDao = null;
@Inject
protected VMTemplateSwiftDao _vmTemplateSwiftDao = null;
@Inject
protected VMTemplateS3Dao _vmTemplateS3Dao;
@Inject
protected S3Manager _s3Mgr;

View File

@ -151,7 +151,6 @@ import com.cloud.storage.dao.VMTemplateDao;
import com.cloud.storage.dao.VMTemplateDetailsDao;
import com.cloud.storage.dao.VMTemplatePoolDao;
import com.cloud.storage.dao.VMTemplateS3Dao;
import com.cloud.storage.dao.VMTemplateSwiftDao;
import com.cloud.storage.dao.VMTemplateZoneDao;
import com.cloud.storage.dao.VolumeDao;
import com.cloud.storage.download.DownloadMonitor;
@ -232,8 +231,6 @@ public class TemplateManagerImpl extends ManagerBase implements TemplateManager,
@Inject
SnapshotDao _snapshotDao;
@Inject
VMTemplateSwiftDao _tmpltSwiftDao;
@Inject
VMTemplateS3Dao _vmS3TemplateDao;
@Inject
ConfigurationDao _configDao;

View File

@ -23,12 +23,7 @@ import static java.lang.String.format;
import static java.util.Arrays.asList;
import static org.apache.commons.lang.StringUtils.substringAfterLast;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileWriter;
import java.io.IOException;
import java.io.InputStream;
import java.io.*;
import java.math.BigInteger;
import java.net.InetAddress;
import java.net.URI;
@ -43,6 +38,10 @@ import java.util.concurrent.Callable;
import javax.naming.ConfigurationException;
import com.cloud.agent.api.storage.*;
import com.cloud.storage.VMTemplateStorageResourceAssoc;
import com.cloud.storage.template.*;
import com.cloud.utils.SwiftUtil;
import org.apache.cloudstack.storage.command.CopyCmdAnswer;
import org.apache.cloudstack.storage.command.CopyCommand;
import org.apache.cloudstack.storage.command.DeleteCommand;
@ -56,7 +55,13 @@ import org.apache.cloudstack.storage.template.UploadManagerImpl;
import org.apache.cloudstack.storage.to.SnapshotObjectTO;
import org.apache.cloudstack.storage.to.TemplateObjectTO;
import org.apache.cloudstack.storage.to.VolumeObjectTO;
import org.apache.commons.codec.digest.DigestUtils;
import org.apache.commons.lang.StringUtils;
import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.client.HttpClient;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.log4j.Logger;
import com.amazonaws.services.s3.model.S3ObjectSummary;
@ -84,13 +89,6 @@ import com.cloud.agent.api.SecStorageVMSetupCommand;
import com.cloud.agent.api.StartupCommand;
import com.cloud.agent.api.StartupSecondaryStorageCommand;
import com.cloud.agent.api.UploadTemplateToSwiftFromSecondaryStorageCommand;
import com.cloud.agent.api.storage.CreateEntityDownloadURLCommand;
import com.cloud.agent.api.storage.DeleteEntityDownloadURLCommand;
import com.cloud.agent.api.storage.ListTemplateAnswer;
import com.cloud.agent.api.storage.ListTemplateCommand;
import com.cloud.agent.api.storage.ListVolumeAnswer;
import com.cloud.agent.api.storage.ListVolumeCommand;
import com.cloud.agent.api.storage.UploadCommand;
import com.cloud.agent.api.to.DataObjectType;
import com.cloud.agent.api.to.DataStoreTO;
import com.cloud.agent.api.to.DataTO;
@ -105,11 +103,7 @@ import com.cloud.resource.ServerResourceBase;
import com.cloud.storage.DataStoreRole;
import com.cloud.storage.Storage.ImageFormat;
import com.cloud.storage.StorageLayer;
import com.cloud.storage.template.Processor;
import com.cloud.storage.template.Processor.FormatInfo;
import com.cloud.storage.template.TemplateLocation;
import com.cloud.storage.template.TemplateProp;
import com.cloud.storage.template.VhdProcessor;
import com.cloud.utils.NumbersUtil;
import com.cloud.utils.S3Utils;
import com.cloud.utils.S3Utils.FileNamingStrategy;
@ -219,6 +213,86 @@ public class NfsSecondaryStorageResource extends ServerResourceBase implements S
}
}
protected CopyCmdAnswer postProcessing(File destFile, String downloadPath, String destPath, DataTO srcData, DataTO destData) throws ConfigurationException {
// do post processing to unzip the file if it is compressed
String scriptsDir = "scripts/storage/secondary";
String createTmpltScr = Script.findScript(scriptsDir, "createtmplt.sh");
if (createTmpltScr == null) {
throw new ConfigurationException("Unable to find createtmplt.sh");
}
s_logger.info("createtmplt.sh found in " + createTmpltScr);
String createVolScr = Script.findScript(scriptsDir, "createvolume.sh");
if (createVolScr == null) {
throw new ConfigurationException("Unable to find createvolume.sh");
}
s_logger.info("createvolume.sh found in " + createVolScr);
String script = srcData.getObjectType() == DataObjectType.TEMPLATE ? createTmpltScr : createVolScr;
int installTimeoutPerGig = 180 * 60 * 1000;
int imgSizeGigs = (int) Math.ceil(destFile.length() * 1.0d / (1024 * 1024 * 1024));
imgSizeGigs++; // add one just in case
long timeout = imgSizeGigs * installTimeoutPerGig;
String origPath = destFile.getAbsolutePath();
String extension = null;
if (srcData.getObjectType() == DataObjectType.TEMPLATE) {
extension = ((TemplateObjectTO) srcData).getFormat().getFileExtension();
} else {
extension = ((VolumeObjectTO) srcData).getFormat().getFileExtension();
}
String templateName = UUID.randomUUID().toString();
String templateFilename = templateName + "." + extension;
Script scr = new Script(script, timeout, s_logger);
scr.add("-s", Integer.toString(imgSizeGigs)); // not used for now
scr.add("-n", templateFilename);
scr.add("-t", downloadPath);
scr.add("-f", origPath); // this is the temporary
// template file downloaded
String result;
result = scr.execute();
if (result != null) {
// script execution failure
throw new CloudRuntimeException("Failed to run script " + script);
}
String finalFileName = templateFilename;
String finalDownloadPath = destPath + File.separator + templateFilename;
// compute the size of
long size = this._storage.getSize(downloadPath + File.separator + templateFilename);
DataTO newDestTO = null;
if (destData.getObjectType() == DataObjectType.TEMPLATE) {
TemplateObjectTO newTemplTO = new TemplateObjectTO();
newTemplTO.setPath(finalDownloadPath);
newTemplTO.setName(finalFileName);
newTemplTO.setSize(size);
newDestTO = newTemplTO;
} else {
return new CopyCmdAnswer("not implemented yet");
}
return new CopyCmdAnswer(newDestTO);
}
protected Answer copyFromSwiftToNfs(CopyCommand cmd, DataTO srcData, SwiftTO swiftTO, DataTO destData, NfsTO destImageStore) {
final String storagePath = destImageStore.getUrl();
final String destPath = destData.getPath();
try {
String downloadPath = determineStorageTemplatePath(storagePath, destPath);
final File downloadDirectory = _storage.getFile(downloadPath);
downloadDirectory.mkdirs();
File destFile = SwiftUtil.getObject(swiftTO, downloadDirectory, srcData.getPath());
return postProcessing(destFile,downloadPath,destPath,srcData,destData);
} catch (Exception e) {
s_logger.debug("Failed to copy swift to nfs", e);
return new CopyCmdAnswer(e.toString());
}
}
protected Answer copyFromS3ToNfs(CopyCommand cmd, DataTO srcData, S3TO s3, DataTO destData, NfsTO destImageStore) {
final String storagePath = destImageStore.getUrl();
final String destPath = destData.getPath();
@ -249,68 +323,7 @@ public class NfsSecondaryStorageResource extends ServerResourceBase implements S
return new CopyCmdAnswer("Can't find template");
}
// do post processing to unzip the file if it is compressed
String scriptsDir = "scripts/storage/secondary";
String createTmpltScr = Script.findScript(scriptsDir, "createtmplt.sh");
if (createTmpltScr == null) {
throw new ConfigurationException("Unable to find createtmplt.sh");
}
s_logger.info("createtmplt.sh found in " + createTmpltScr);
String createVolScr = Script.findScript(scriptsDir, "createvolume.sh");
if (createVolScr == null) {
throw new ConfigurationException("Unable to find createvolume.sh");
}
s_logger.info("createvolume.sh found in " + createVolScr);
String script = srcData.getObjectType() == DataObjectType.TEMPLATE ? createTmpltScr : createVolScr;
int installTimeoutPerGig = 180 * 60 * 1000;
int imgSizeGigs = (int) Math.ceil(destFile.length() * 1.0d / (1024 * 1024 * 1024));
imgSizeGigs++; // add one just in case
long timeout = imgSizeGigs * installTimeoutPerGig;
String origPath = destFile.getAbsolutePath();
String extension = null;
if (srcData.getObjectType() == DataObjectType.TEMPLATE) {
extension = ((TemplateObjectTO) srcData).getFormat().getFileExtension();
} else {
extension = ((VolumeObjectTO) srcData).getFormat().getFileExtension();
}
String templateName = UUID.randomUUID().toString();
String templateFilename = templateName + "." + extension;
Script scr = new Script(script, timeout, s_logger);
scr.add("-s", Integer.toString(imgSizeGigs)); // not used for now
scr.add("-n", templateFilename);
scr.add("-t", downloadPath);
scr.add("-f", origPath); // this is the temporary
// template file downloaded
String result;
result = scr.execute();
if (result != null) {
// script execution failure
throw new CloudRuntimeException("Failed to run script " + script);
}
String finalFileName = templateFilename;
String finalDownloadPath = destPath + File.separator + templateFilename;
// compute the size of
long size = this._storage.getSize(downloadPath + File.separator + templateFilename);
DataTO newDestTO = null;
if (destData.getObjectType() == DataObjectType.TEMPLATE) {
TemplateObjectTO newTemplTO = new TemplateObjectTO();
newTemplTO.setPath(finalDownloadPath);
newTemplTO.setName(finalFileName);
newTemplTO.setSize(size);
newDestTO = newTemplTO;
} else {
return new CopyCmdAnswer("not implemented yet");
}
return new CopyCmdAnswer(newDestTO);
return postProcessing(destFile,downloadPath,destPath,srcData,destData);
} catch (Exception e) {
final String errMsg = format("Failed to download" + "due to $2%s", e.getMessage());
@ -432,11 +445,15 @@ public class NfsSecondaryStorageResource extends ServerResourceBase implements S
return createTemplateFromSnapshot(cmd);
}
if (srcDataStore instanceof S3TO && destDataStore instanceof NfsTO
if (destDataStore instanceof NfsTO
&& destDataStore.getRole() == DataStoreRole.ImageCache) {
S3TO s3 = (S3TO) srcDataStore;
NfsTO destImageStore = (NfsTO) destDataStore;
return this.copyFromS3ToNfs(cmd, srcData, s3, destData, destImageStore);
if (srcDataStore instanceof S3TO) {
S3TO s3 = (S3TO) srcDataStore;
return this.copyFromS3ToNfs(cmd, srcData, s3, destData, destImageStore);
} else if (srcDataStore instanceof SwiftTO) {
return copyFromSwiftToNfs(cmd, srcData, (SwiftTO)srcDataStore, destData, destImageStore);
}
}
if (srcDataStore.getRole() == DataStoreRole.ImageCache && destDataStore.getRole() == DataStoreRole.Image) {
@ -519,51 +536,62 @@ public class NfsSecondaryStorageResource extends ServerResourceBase implements S
}
}
protected Answer registerTemplateOnSwift(DownloadCommand cmd) {
protected File downloadFromUrlToNfs(String url, NfsTO nfs, String path) {
HttpClient client = new DefaultHttpClient();
HttpGet get = new HttpGet(url);
try {
HttpResponse response = client.execute(get);
HttpEntity entity = response.getEntity();
if (entity == null) {
s_logger.debug("Faled to get entity");
throw new CloudRuntimeException("Failed to get url: " + url);
}
return null;
String nfsMountPath = getRootDir(nfs.getUrl());
String filePath = nfsMountPath + File.separator + path;
FileOutputStream outputStream = new FileOutputStream(filePath);
entity.writeTo(outputStream);
return new File(filePath);
} catch (IOException e) {
s_logger.debug("Faild to get url:"+ url + ", due to " + e.toString());
throw new CloudRuntimeException(e);
}
}
protected Answer registerTemplateOnSwift(DownloadCommand cmd) {
SwiftTO swiftTO = (SwiftTO)cmd.getDataStore();
String path = cmd.getInstallPath();
DataStoreTO cacheStore = cmd.getCacheStore();
if (cacheStore == null || !(cacheStore instanceof NfsTO)) {
return new DownloadAnswer("cache store can't be null", VMTemplateStorageResourceAssoc.Status.DOWNLOAD_ERROR);
}
try {
NfsTO nfsCacheStore = (NfsTO)cacheStore;
File file = downloadFromUrlToNfs(cmd.getUrl(), nfsCacheStore, path);
String swiftPath = SwiftUtil.putObject(swiftTO, file, "T-" + cmd.getId());
String md5sum = null;
try {
md5sum = DigestUtils.md5Hex(new FileInputStream(file));
} catch (IOException e) {
s_logger.debug("Failed to get md5sum: " + file.getAbsoluteFile());
}
file.delete();
return new DownloadAnswer(null, 100, null, VMTemplateStorageResourceAssoc.Status.DOWNLOADED,
swiftPath, swiftPath, file.length(), file.length(), md5sum
);
} catch (Exception e) {
s_logger.debug("Failed to register template into swift", e);
return new DownloadAnswer(e.toString(), VMTemplateStorageResourceAssoc.Status.DOWNLOAD_ERROR);
}
}
private Answer execute(DownloadCommand cmd) {
DataStoreTO dstore = cmd.getDataStore();
if (dstore instanceof NfsTO || dstore instanceof S3TO) {
return _dlMgr.handleDownloadCommand(this, cmd);
}
/*
* else if (dstore instanceof S3TO) { // TODO: start download job to
* handle this // TODO: how to handle download progress for S3 S3TO s3 =
* (S3TO) cmd.getDataStore(); String url = cmd.getUrl(); String user =
* null; String password = null; if (cmd.getAuth() != null) { user =
* cmd.getAuth().getUserName(); password = new
* String(cmd.getAuth().getPassword()); } // get input stream from the
* given url InputStream in = UriUtils.getInputStreamFromUrl(url, user,
* password); URI uri; URL urlObj; try { uri = new URI(url); urlObj =
* new URL(url); } catch (URISyntaxException e) { throw new
* CloudRuntimeException("URI is incorrect: " + url); } catch
* (MalformedURLException e) { throw new
* CloudRuntimeException("URL is incorrect: " + url); }
*
* final String bucket = s3.getBucketName(); String path = null; if
* (cmd.getResourceType() == ResourceType.TEMPLATE) { // convention is
* no / in the end for install path based on // S3Utils implementation.
* // template key is //
* TEMPLATE_ROOT_DIR/account_id/template_id/template_name, by // adding
* template_name in the key, I can avoid generating a //
* template.properties file // for listTemplateCommand. path =
* determineS3TemplateDirectory(cmd.getAccountId(), cmd.getResourceId(),
* cmd.getName()); } else { path =
* determineS3VolumeDirectory(cmd.getAccountId(), cmd.getResourceId());
* }
*
* String key = join(asList(path, urlObj.getFile()), S3Utils.SEPARATOR);
* S3Utils.putObject(s3, in, bucket, key); List<S3ObjectSummary> s3Obj =
* S3Utils.getDirectory(s3, bucket, path); if (s3Obj == null ||
* s3Obj.size() == 0) { return new Answer(cmd, false,
* "Failed to download to S3 bucket: " + bucket + " with key: " + key);
* } else { return new DownloadAnswer(null, 100, null,
* Status.DOWNLOADED, path, path, s3Obj.get(0).getSize(),
* s3Obj.get(0).getSize(), s3Obj .get(0).getETag()); } }
*/
else if (dstore instanceof SwiftTO) {
} else if (dstore instanceof SwiftTO) {
return registerTemplateOnSwift(cmd);
} else {
return new Answer(cmd, false, "Unsupported image data store: " + dstore);

View File

@ -0,0 +1,111 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package com.cloud.utils;
import com.cloud.utils.exception.CloudRuntimeException;
import com.cloud.utils.script.OutputInterpreter;
import com.cloud.utils.script.Script;
import org.apache.log4j.Logger;
import java.io.File;
public class SwiftUtil {
private static Logger logger = Logger.getLogger(SwiftUtil.class);
private static long SWIFT_MAX_SIZE = 5L * 1024L * 1024L * 1024L;
public interface SwiftClientCfg {
String getAccount();
String getUserName();
String getKey();
String getEndPoint();
}
private static String getSwiftCLIPath() {
String swiftCLI = Script.findScript("scripts/storage/secondary", "swift");
if (swiftCLI == null) {
logger.debug("Can't find swift cli at scripts/storage/secondary/swift");
throw new CloudRuntimeException("Can't find swift cli at scripts/storage/secondary/swift");
}
return swiftCLI;
}
public static String putObject(SwiftClientCfg cfg, File srcFile, String container) {
String swiftCli = getSwiftCLIPath();
String srcDirectory = srcFile.getParent();
Script command = new Script("/bin/bash", logger);
long size = srcFile.length();
if (size <= SWIFT_MAX_SIZE) {
command.add("cd " + srcDirectory
+ ";/usr/bin/python " + swiftCli + " -A "
+ cfg.getEndPoint() + " -U " + cfg.getAccount() + ":" + cfg.getUserName() + " -K "
+ cfg.getKey() + " upload " + container + " " + srcFile.getName());
} else {
command.add("cd " + srcDirectory
+ ";/usr/bin/python " + swiftCli + " -A "
+ cfg.getEndPoint() + " -U " + cfg.getAccount() + ":" + cfg.getUserName() + " -K "
+ cfg.getKey() + " upload -S " + SWIFT_MAX_SIZE + " " + container + " " + srcFile.getName());
}
OutputInterpreter.AllLinesParser parser = new OutputInterpreter.AllLinesParser();
String result = command.execute(parser);
if (result != null) {
throw new CloudRuntimeException("Failed to upload file: " + result);
}
if (parser.getLines() != null) {
String[] lines = parser.getLines().split("\\n");
for (String line : lines) {
if (line.contains("Errno") || line.contains("failed")) {
throw new CloudRuntimeException("Failed to upload file: " + lines.toString());
}
}
}
return container + File.separator + srcFile.getName();
}
public static File getObject(SwiftClientCfg cfg, File destDirectory, String swiftPath) {
int firstIndexOfSeparator = swiftPath.indexOf(File.separator);
String container = swiftPath.substring(0, firstIndexOfSeparator);
String srcPath = swiftPath.substring(firstIndexOfSeparator + 1);
String destFilePath = destDirectory.getAbsolutePath() + File.separator + srcPath;
String swiftCli = getSwiftCLIPath();
Script command = new Script("/bin/bash", logger);
command.add("-c");
command.add("/usr/bin/python " + swiftCli + " -A " + cfg.getEndPoint()
+ " -U " + cfg.getAccount() + ":" + cfg.getUserName() + " -K " + cfg.getKey() + " download "
+ container + " " + srcPath + " -o " + destFilePath);
OutputInterpreter.AllLinesParser parser = new OutputInterpreter.AllLinesParser();
String result = command.execute(parser);
if (result != null) {
String errMsg = "swiftDownload failed err=" + result;
logger.debug(errMsg);
throw new CloudRuntimeException("failed to get object: " + swiftPath);
}
if (parser.getLines() != null) {
String[] lines = parser.getLines().split("\\n");
for (String line : lines) {
if (line.contains("Errno") || line.contains("failed")) {
String errMsg = "swiftDownload failed , err=" + lines.toString();
logger.debug(errMsg);
throw new CloudRuntimeException("Failed to get object: " + swiftPath);
}
}
}
return new File(destFilePath);
}
}