mirror of
https://github.com/apache/cloudstack.git
synced 2025-11-02 20:02:29 +01:00
More changes for uploadVolume. Create framework for upload volume progress communication between MS and SSVM.
This commit is contained in:
parent
2e80fba2b6
commit
564cef8ddf
@ -14,6 +14,7 @@ package com.cloud.agent.api.storage;
|
|||||||
|
|
||||||
import java.net.URI;
|
import java.net.URI;
|
||||||
|
|
||||||
|
import com.cloud.storage.Volume;
|
||||||
import com.cloud.storage.Storage.ImageFormat;
|
import com.cloud.storage.Storage.ImageFormat;
|
||||||
import com.cloud.template.VirtualMachineTemplate;
|
import com.cloud.template.VirtualMachineTemplate;
|
||||||
|
|
||||||
@ -41,6 +42,10 @@ public class DownloadCommand extends AbstractDownloadCommand {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static enum ResourceType {
|
||||||
|
VOLUME, TEMPLATE
|
||||||
|
}
|
||||||
|
|
||||||
public static class Proxy {
|
public static class Proxy {
|
||||||
private String _host;
|
private String _host;
|
||||||
private int _port;
|
private int _port;
|
||||||
@ -97,6 +102,7 @@ public class DownloadCommand extends AbstractDownloadCommand {
|
|||||||
private Proxy _proxy;
|
private Proxy _proxy;
|
||||||
private Long maxDownloadSizeInBytes = null;
|
private Long maxDownloadSizeInBytes = null;
|
||||||
private long id;
|
private long id;
|
||||||
|
private ResourceType resourceType = ResourceType.TEMPLATE;
|
||||||
|
|
||||||
protected DownloadCommand() {
|
protected DownloadCommand() {
|
||||||
}
|
}
|
||||||
@ -123,6 +129,17 @@ public class DownloadCommand extends AbstractDownloadCommand {
|
|||||||
this.maxDownloadSizeInBytes = maxDownloadSizeInBytes;
|
this.maxDownloadSizeInBytes = maxDownloadSizeInBytes;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public DownloadCommand(String secUrl, Volume volume, Long maxDownloadSizeInBytes, String checkSum, String url) {
|
||||||
|
super(volume.getName(), url, ImageFormat.VHD, volume.getAccountId());
|
||||||
|
//this.hvm = volume.isRequiresHvm();
|
||||||
|
this.checksum = checkSum;
|
||||||
|
this.id = volume.getId();
|
||||||
|
//this.description = volume.get;
|
||||||
|
this.setSecUrl(secUrl);
|
||||||
|
this.maxDownloadSizeInBytes = maxDownloadSizeInBytes;
|
||||||
|
this.resourceType = ResourceType.VOLUME;
|
||||||
|
}
|
||||||
|
|
||||||
public DownloadCommand(String secUrl, String url, VirtualMachineTemplate template, String user, String passwd, Long maxDownloadSizeInBytes) {
|
public DownloadCommand(String secUrl, String url, VirtualMachineTemplate template, String user, String passwd, Long maxDownloadSizeInBytes) {
|
||||||
super(template.getUniqueName(), url, template.getFormat(), template.getAccountId());
|
super(template.getUniqueName(), url, template.getFormat(), template.getAccountId());
|
||||||
this.hvm = template.isRequiresHvm();
|
this.hvm = template.isRequiresHvm();
|
||||||
@ -187,4 +204,14 @@ public class DownloadCommand extends AbstractDownloadCommand {
|
|||||||
public Long getMaxDownloadSizeInBytes() {
|
public Long getMaxDownloadSizeInBytes() {
|
||||||
return maxDownloadSizeInBytes;
|
return maxDownloadSizeInBytes;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public ResourceType getResourceType() {
|
||||||
|
return resourceType;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public void setResourceType(ResourceType resourceType) {
|
||||||
|
this.resourceType = resourceType;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -21,6 +21,7 @@ import com.cloud.api.commands.CreateVolumeCmd;
|
|||||||
import com.cloud.api.commands.DeletePoolCmd;
|
import com.cloud.api.commands.DeletePoolCmd;
|
||||||
import com.cloud.api.commands.ListVolumesCmd;
|
import com.cloud.api.commands.ListVolumesCmd;
|
||||||
import com.cloud.api.commands.UpdateStoragePoolCmd;
|
import com.cloud.api.commands.UpdateStoragePoolCmd;
|
||||||
|
import com.cloud.api.commands.UploadVolumeCmd;
|
||||||
import com.cloud.exception.ConcurrentOperationException;
|
import com.cloud.exception.ConcurrentOperationException;
|
||||||
import com.cloud.exception.InsufficientCapacityException;
|
import com.cloud.exception.InsufficientCapacityException;
|
||||||
import com.cloud.exception.PermissionDeniedException;
|
import com.cloud.exception.PermissionDeniedException;
|
||||||
@ -108,4 +109,13 @@ public interface StorageService{
|
|||||||
|
|
||||||
List<? extends Volume> searchForVolumes(ListVolumesCmd cmd);
|
List<? extends Volume> searchForVolumes(ListVolumesCmd cmd);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Uploads the volume to secondary storage
|
||||||
|
*
|
||||||
|
* @param UploadVolumeCmd cmd
|
||||||
|
*
|
||||||
|
* @return Volume object
|
||||||
|
*/
|
||||||
|
Volume uploadVolume(UploadVolumeCmd cmd) throws ResourceAllocationException;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
283
core/src/com/cloud/storage/VolumeHostVO.java
Executable file
283
core/src/com/cloud/storage/VolumeHostVO.java
Executable file
@ -0,0 +1,283 @@
|
|||||||
|
package com.cloud.storage;
|
||||||
|
|
||||||
|
import java.util.Date;
|
||||||
|
|
||||||
|
import javax.persistence.Column;
|
||||||
|
import javax.persistence.Entity;
|
||||||
|
import javax.persistence.EnumType;
|
||||||
|
import javax.persistence.Enumerated;
|
||||||
|
import javax.persistence.GeneratedValue;
|
||||||
|
import javax.persistence.GenerationType;
|
||||||
|
import javax.persistence.Id;
|
||||||
|
import javax.persistence.Table;
|
||||||
|
import javax.persistence.Temporal;
|
||||||
|
import javax.persistence.TemporalType;
|
||||||
|
|
||||||
|
//import com.cloud.storage.VMVolumeStorageResourceAssoc.Status;
|
||||||
|
import com.cloud.storage.VMTemplateStorageResourceAssoc.Status;
|
||||||
|
import com.cloud.utils.db.GenericDaoBase;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Join table for storage hosts and volumes
|
||||||
|
* @author Nitin
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
@Entity
|
||||||
|
@Table(name="volume_host_ref")
|
||||||
|
public class VolumeHostVO {
|
||||||
|
@Id
|
||||||
|
@GeneratedValue(strategy=GenerationType.IDENTITY)
|
||||||
|
Long id;
|
||||||
|
|
||||||
|
@Column(name="host_id")
|
||||||
|
private long hostId;
|
||||||
|
|
||||||
|
@Column(name="volume_id")
|
||||||
|
private long volumeId;
|
||||||
|
|
||||||
|
@Column(name=GenericDaoBase.CREATED_COLUMN)
|
||||||
|
private Date created = null;
|
||||||
|
|
||||||
|
@Column(name="last_updated")
|
||||||
|
@Temporal(value=TemporalType.TIMESTAMP)
|
||||||
|
private Date lastUpdated = null;
|
||||||
|
|
||||||
|
@Column (name="download_pct")
|
||||||
|
private int downloadPercent;
|
||||||
|
|
||||||
|
@Column (name="size")
|
||||||
|
private long size;
|
||||||
|
|
||||||
|
@Column (name="physical_size")
|
||||||
|
private long physicalSize;
|
||||||
|
|
||||||
|
@Column (name="download_state")
|
||||||
|
@Enumerated(EnumType.STRING)
|
||||||
|
private Status downloadState;
|
||||||
|
|
||||||
|
@Column(name="checksum")
|
||||||
|
private String checksum;
|
||||||
|
|
||||||
|
@Column (name="local_path")
|
||||||
|
private String localDownloadPath;
|
||||||
|
|
||||||
|
@Column (name="error_str")
|
||||||
|
private String errorString;
|
||||||
|
|
||||||
|
@Column (name="job_id")
|
||||||
|
private String jobId;
|
||||||
|
|
||||||
|
@Column (name="install_path")
|
||||||
|
private String installPath;
|
||||||
|
|
||||||
|
@Column (name="url")
|
||||||
|
private String downloadUrl;
|
||||||
|
|
||||||
|
@Column(name="is_copy")
|
||||||
|
private boolean isCopy = false;
|
||||||
|
|
||||||
|
@Column(name="destroyed")
|
||||||
|
boolean destroyed = false;
|
||||||
|
|
||||||
|
|
||||||
|
public String getInstallPath() {
|
||||||
|
return installPath;
|
||||||
|
}
|
||||||
|
|
||||||
|
public long getHostId() {
|
||||||
|
return hostId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setHostId(long hostId) {
|
||||||
|
this.hostId = hostId;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public long getVolumeId() {
|
||||||
|
return volumeId;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public void setVolumeId(long volumeId) {
|
||||||
|
this.volumeId = volumeId;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public int getDownloadPercent() {
|
||||||
|
return downloadPercent;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public void setDownloadPercent(int downloadPercent) {
|
||||||
|
this.downloadPercent = downloadPercent;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public void setDownloadState(Status downloadState) {
|
||||||
|
this.downloadState = downloadState;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public long getId() {
|
||||||
|
return id;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public Date getCreated() {
|
||||||
|
return created;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public Date getLastUpdated() {
|
||||||
|
return lastUpdated;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public void setLastUpdated(Date date) {
|
||||||
|
lastUpdated = date;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public void setInstallPath(String installPath) {
|
||||||
|
this.installPath = installPath;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public Status getDownloadState() {
|
||||||
|
return downloadState;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getChecksum() {
|
||||||
|
return checksum;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setChecksum(String checksum) {
|
||||||
|
this.checksum = checksum;
|
||||||
|
}
|
||||||
|
|
||||||
|
public VolumeHostVO(long hostId, long volumeId) {
|
||||||
|
super();
|
||||||
|
this.hostId = hostId;
|
||||||
|
this.volumeId = volumeId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public VolumeHostVO(long hostId, long volumeId, Date lastUpdated,
|
||||||
|
int downloadPercent, Status downloadState,
|
||||||
|
String localDownloadPath, String errorString, String jobId,
|
||||||
|
String installPath, String downloadUrl, String checksum) {
|
||||||
|
//super();
|
||||||
|
this.hostId = hostId;
|
||||||
|
this.volumeId = volumeId;
|
||||||
|
this.lastUpdated = lastUpdated;
|
||||||
|
this.downloadPercent = downloadPercent;
|
||||||
|
this.downloadState = downloadState;
|
||||||
|
this.localDownloadPath = localDownloadPath;
|
||||||
|
this.errorString = errorString;
|
||||||
|
this.jobId = jobId;
|
||||||
|
this.installPath = installPath;
|
||||||
|
this.setDownloadUrl(downloadUrl);
|
||||||
|
this.checksum = checksum;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected VolumeHostVO() {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public void setLocalDownloadPath(String localPath) {
|
||||||
|
this.localDownloadPath = localPath;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public String getLocalDownloadPath() {
|
||||||
|
return localDownloadPath;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public void setErrorString(String errorString) {
|
||||||
|
this.errorString = errorString;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public String getErrorString() {
|
||||||
|
return errorString;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public void setJobId(String jobId) {
|
||||||
|
this.jobId = jobId;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public String getJobId() {
|
||||||
|
return jobId;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public boolean equals(Object obj) {
|
||||||
|
if (obj instanceof VolumeHostVO) {
|
||||||
|
VolumeHostVO other = (VolumeHostVO)obj;
|
||||||
|
return (this.volumeId==other.getVolumeId() && this.hostId==other.getHostId());
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public int hashCode() {
|
||||||
|
Long tid = new Long(volumeId);
|
||||||
|
Long hid = new Long(hostId);
|
||||||
|
return tid.hashCode()+hid.hashCode();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setSize(long size) {
|
||||||
|
this.size = size;
|
||||||
|
}
|
||||||
|
|
||||||
|
public long getSize() {
|
||||||
|
return size;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public void setPhysicalSize(long physicalSize) {
|
||||||
|
this.physicalSize = physicalSize;
|
||||||
|
}
|
||||||
|
|
||||||
|
public long getPhysicalSize() {
|
||||||
|
return physicalSize;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setDestroyed(boolean destroyed) {
|
||||||
|
this.destroyed = destroyed;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean getDestroyed() {
|
||||||
|
return destroyed;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setDownloadUrl(String downloadUrl) {
|
||||||
|
this.downloadUrl = downloadUrl;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getDownloadUrl() {
|
||||||
|
return downloadUrl;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setCopy(boolean isCopy) {
|
||||||
|
this.isCopy = isCopy;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isCopy() {
|
||||||
|
return isCopy;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public long getVolumeSize() {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public String toString() {
|
||||||
|
return new StringBuilder("VolumeHost[").append(id).append("-").append(volumeId).append("-").append(hostId).append(installPath).append("]").toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@ -18,6 +18,7 @@ import java.util.Map;
|
|||||||
import com.cloud.agent.api.storage.DownloadAnswer;
|
import com.cloud.agent.api.storage.DownloadAnswer;
|
||||||
import com.cloud.agent.api.storage.DownloadCommand;
|
import com.cloud.agent.api.storage.DownloadCommand;
|
||||||
import com.cloud.agent.api.storage.DownloadCommand.Proxy;
|
import com.cloud.agent.api.storage.DownloadCommand.Proxy;
|
||||||
|
import com.cloud.agent.api.storage.DownloadCommand.ResourceType;
|
||||||
import com.cloud.storage.VMTemplateHostVO;
|
import com.cloud.storage.VMTemplateHostVO;
|
||||||
import com.cloud.storage.Storage.ImageFormat;
|
import com.cloud.storage.Storage.ImageFormat;
|
||||||
import com.cloud.storage.resource.SecondaryStorageResource;
|
import com.cloud.storage.resource.SecondaryStorageResource;
|
||||||
@ -39,9 +40,10 @@ public interface DownloadManager extends Manager {
|
|||||||
* @param user username used for authentication to the server
|
* @param user username used for authentication to the server
|
||||||
* @param password password used for authentication to the server
|
* @param password password used for authentication to the server
|
||||||
* @param maxDownloadSizeInBytes (optional) max download size for the template, in bytes.
|
* @param maxDownloadSizeInBytes (optional) max download size for the template, in bytes.
|
||||||
|
* @param resourceType signifying the type of resource like template, volume etc.
|
||||||
* @return job-id that can be used to interrogate the status of the download.
|
* @return job-id that can be used to interrogate the status of the download.
|
||||||
*/
|
*/
|
||||||
public String downloadPublicTemplate(long id, String url, String name, ImageFormat format, boolean hvm, Long accountId, String descr, String cksum, String installPathPrefix, String userName, String passwd, long maxDownloadSizeInBytes, Proxy proxy);
|
public String downloadPublicTemplate(long id, String url, String name, ImageFormat format, boolean hvm, Long accountId, String descr, String cksum, String installPathPrefix, String userName, String passwd, long maxDownloadSizeInBytes, Proxy proxy, ResourceType resourceType);
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -85,10 +87,10 @@ public interface DownloadManager extends Manager {
|
|||||||
*/
|
*/
|
||||||
public DownloadAnswer handleDownloadCommand(SecondaryStorageResource resource, DownloadCommand cmd);
|
public DownloadAnswer handleDownloadCommand(SecondaryStorageResource resource, DownloadCommand cmd);
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
/**
|
/**
|
||||||
* @return list of template info for installed templates
|
* @return list of template info for installed templates
|
||||||
*/
|
*/
|
||||||
public Map<String, TemplateInfo> gatherTemplateInfo(String templateDir);
|
public Map<String, TemplateInfo> gatherTemplateInfo(String templateDir);
|
||||||
|
|
||||||
}
|
}
|
||||||
@ -43,6 +43,7 @@ import com.cloud.agent.api.Answer;
|
|||||||
import com.cloud.agent.api.storage.DownloadAnswer;
|
import com.cloud.agent.api.storage.DownloadAnswer;
|
||||||
import com.cloud.agent.api.storage.DownloadCommand;
|
import com.cloud.agent.api.storage.DownloadCommand;
|
||||||
import com.cloud.agent.api.storage.DownloadCommand.Proxy;
|
import com.cloud.agent.api.storage.DownloadCommand.Proxy;
|
||||||
|
import com.cloud.agent.api.storage.DownloadCommand.ResourceType;
|
||||||
import com.cloud.agent.api.storage.DownloadProgressCommand;
|
import com.cloud.agent.api.storage.DownloadProgressCommand;
|
||||||
import com.cloud.agent.api.storage.DownloadProgressCommand.RequestType;
|
import com.cloud.agent.api.storage.DownloadProgressCommand.RequestType;
|
||||||
import com.cloud.exception.InternalErrorException;
|
import com.cloud.exception.InternalErrorException;
|
||||||
@ -100,8 +101,9 @@ public class DownloadManagerImpl implements DownloadManager {
|
|||||||
private long templatesize;
|
private long templatesize;
|
||||||
private long templatePhysicalSize;
|
private long templatePhysicalSize;
|
||||||
private long id;
|
private long id;
|
||||||
|
private ResourceType resourceType;
|
||||||
|
|
||||||
public DownloadJob(TemplateDownloader td, String jobId, long id, String tmpltName, ImageFormat format, boolean hvm, Long accountId, String descr, String cksum, String installPathPrefix) {
|
public DownloadJob(TemplateDownloader td, String jobId, long id, String tmpltName, ImageFormat format, boolean hvm, Long accountId, String descr, String cksum, String installPathPrefix, ResourceType resourceType) {
|
||||||
super();
|
super();
|
||||||
this.td = td;
|
this.td = td;
|
||||||
this.jobId = jobId;
|
this.jobId = jobId;
|
||||||
@ -114,6 +116,7 @@ public class DownloadManagerImpl implements DownloadManager {
|
|||||||
this.installPathPrefix = installPathPrefix;
|
this.installPathPrefix = installPathPrefix;
|
||||||
this.templatesize = 0;
|
this.templatesize = 0;
|
||||||
this.id = id;
|
this.id = id;
|
||||||
|
this.resourceType = resourceType;
|
||||||
}
|
}
|
||||||
|
|
||||||
public TemplateDownloader getTd() {
|
public TemplateDownloader getTd() {
|
||||||
@ -156,6 +159,10 @@ public class DownloadManagerImpl implements DownloadManager {
|
|||||||
return id;
|
return id;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public ResourceType getResourceType() {
|
||||||
|
return resourceType;
|
||||||
|
}
|
||||||
|
|
||||||
public void setTmpltPath(String tmpltPath) {
|
public void setTmpltPath(String tmpltPath) {
|
||||||
this.tmpltPath = tmpltPath;
|
this.tmpltPath = tmpltPath;
|
||||||
}
|
}
|
||||||
@ -206,7 +213,9 @@ public class DownloadManagerImpl implements DownloadManager {
|
|||||||
|
|
||||||
public static final Logger s_logger = Logger.getLogger(DownloadManagerImpl.class);
|
public static final Logger s_logger = Logger.getLogger(DownloadManagerImpl.class);
|
||||||
private String _templateDir;
|
private String _templateDir;
|
||||||
|
private String _volumeDir;
|
||||||
private String createTmpltScr;
|
private String createTmpltScr;
|
||||||
|
private String createVolScr;
|
||||||
private Adapters<Processor> processors;
|
private Adapters<Processor> processors;
|
||||||
|
|
||||||
private ExecutorService threadPool;
|
private ExecutorService threadPool;
|
||||||
@ -310,17 +319,20 @@ public class DownloadManagerImpl implements DownloadManager {
|
|||||||
TemplateDownloader td = dnld.getTemplateDownloader();
|
TemplateDownloader td = dnld.getTemplateDownloader();
|
||||||
String templatePath = null;
|
String templatePath = null;
|
||||||
templatePath = dnld.getInstallPathPrefix() + dnld.getAccountId() + File.separator + dnld.getId() + File.separator;// dnld.getTmpltName();
|
templatePath = dnld.getInstallPathPrefix() + dnld.getAccountId() + File.separator + dnld.getId() + File.separator;// dnld.getTmpltName();
|
||||||
|
ResourceType resourceType = dnld.getResourceType();
|
||||||
|
|
||||||
_storage.mkdirs(templatePath);
|
_storage.mkdirs(templatePath);
|
||||||
|
|
||||||
// once template path is set, remove the parent dir so that the template is installed with a relative path
|
// once template path is set, remove the parent dir so that the template is installed with a relative path
|
||||||
String finalTemplatePath = _templateDir + File.separator + dnld.getAccountId() + File.separator + dnld.getId() + File.separator;
|
String finalTemplatePath = resourceType == ResourceType.TEMPLATE ? _templateDir : _volumeDir
|
||||||
|
+ File.separator + dnld.getAccountId() + File.separator + dnld.getId() + File.separator;
|
||||||
dnld.setTmpltPath(finalTemplatePath);
|
dnld.setTmpltPath(finalTemplatePath);
|
||||||
|
|
||||||
int imgSizeGigs = (int) Math.ceil(_storage.getSize(td.getDownloadLocalPath()) * 1.0d / (1024 * 1024 * 1024));
|
int imgSizeGigs = (int) Math.ceil(_storage.getSize(td.getDownloadLocalPath()) * 1.0d / (1024 * 1024 * 1024));
|
||||||
imgSizeGigs++; // add one just in case
|
imgSizeGigs++; // add one just in case
|
||||||
long timeout = imgSizeGigs * installTimeoutPerGig;
|
long timeout = imgSizeGigs * installTimeoutPerGig;
|
||||||
Script scr = null;
|
Script scr = null;
|
||||||
|
String script = resourceType == ResourceType.TEMPLATE ? createTmpltScr : createVolScr;
|
||||||
scr = new Script(createTmpltScr, timeout, s_logger);
|
scr = new Script(createTmpltScr, timeout, s_logger);
|
||||||
scr.add("-s", Integer.toString(imgSizeGigs));
|
scr.add("-s", Integer.toString(imgSizeGigs));
|
||||||
scr.add("-S", Long.toString(td.getMaxTemplateSizeInBytes()));
|
scr.add("-S", Long.toString(td.getMaxTemplateSizeInBytes()));
|
||||||
@ -417,7 +429,7 @@ public class DownloadManagerImpl implements DownloadManager {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String downloadPublicTemplate(long id, String url, String name, ImageFormat format, boolean hvm, Long accountId, String descr, String cksum, String installPathPrefix, String user, String password, long maxTemplateSizeInBytes, Proxy proxy) {
|
public String downloadPublicTemplate(long id, String url, String name, ImageFormat format, boolean hvm, Long accountId, String descr, String cksum, String installPathPrefix, String user, String password, long maxTemplateSizeInBytes, Proxy proxy, ResourceType resourceType) {
|
||||||
UUID uuid = UUID.randomUUID();
|
UUID uuid = UUID.randomUUID();
|
||||||
String jobId = uuid.toString();
|
String jobId = uuid.toString();
|
||||||
String tmpDir = installPathPrefix + File.separator + accountId + File.separator + id;
|
String tmpDir = installPathPrefix + File.separator + accountId + File.separator + id;
|
||||||
@ -428,8 +440,9 @@ public class DownloadManagerImpl implements DownloadManager {
|
|||||||
s_logger.warn("Unable to create " + tmpDir);
|
s_logger.warn("Unable to create " + tmpDir);
|
||||||
return "Unable to create " + tmpDir;
|
return "Unable to create " + tmpDir;
|
||||||
}
|
}
|
||||||
|
// TO DO - define constant for volume properties.
|
||||||
File file = _storage.getFile(tmpDir + File.separator + TemplateLocation.Filename);
|
File file = ResourceType.TEMPLATE == resourceType ? _storage.getFile(tmpDir + File.separator + TemplateLocation.Filename) :
|
||||||
|
_storage.getFile(tmpDir + File.separator + "volume.properties");
|
||||||
if ( file.exists() ) {
|
if ( file.exists() ) {
|
||||||
file.delete();
|
file.delete();
|
||||||
}
|
}
|
||||||
@ -448,7 +461,7 @@ public class DownloadManagerImpl implements DownloadManager {
|
|||||||
TemplateDownloader td;
|
TemplateDownloader td;
|
||||||
if ((uri != null) && (uri.getScheme() != null)) {
|
if ((uri != null) && (uri.getScheme() != null)) {
|
||||||
if (uri.getScheme().equalsIgnoreCase("http") || uri.getScheme().equalsIgnoreCase("https")) {
|
if (uri.getScheme().equalsIgnoreCase("http") || uri.getScheme().equalsIgnoreCase("https")) {
|
||||||
td = new HttpTemplateDownloader(_storage, url, tmpDir, new Completion(jobId), maxTemplateSizeInBytes, user, password, proxy);
|
td = new HttpTemplateDownloader(_storage, url, tmpDir, new Completion(jobId), maxTemplateSizeInBytes, user, password, proxy, resourceType);
|
||||||
} else if (uri.getScheme().equalsIgnoreCase("file")) {
|
} else if (uri.getScheme().equalsIgnoreCase("file")) {
|
||||||
td = new LocalTemplateDownloader(_storage, url, tmpDir, maxTemplateSizeInBytes, new Completion(jobId));
|
td = new LocalTemplateDownloader(_storage, url, tmpDir, maxTemplateSizeInBytes, new Completion(jobId));
|
||||||
} else if (uri.getScheme().equalsIgnoreCase("scp")) {
|
} else if (uri.getScheme().equalsIgnoreCase("scp")) {
|
||||||
@ -463,7 +476,7 @@ public class DownloadManagerImpl implements DownloadManager {
|
|||||||
} else {
|
} else {
|
||||||
throw new CloudRuntimeException("Unable to download from URL: " + url);
|
throw new CloudRuntimeException("Unable to download from URL: " + url);
|
||||||
}
|
}
|
||||||
DownloadJob dj = new DownloadJob(td, jobId, id, name, format, hvm, accountId, descr, cksum, installPathPrefix);
|
DownloadJob dj = new DownloadJob(td, jobId, id, name, format, hvm, accountId, descr, cksum, installPathPrefix, resourceType);
|
||||||
jobs.put(jobId, dj);
|
jobs.put(jobId, dj);
|
||||||
threadPool.execute(td);
|
threadPool.execute(td);
|
||||||
|
|
||||||
@ -555,12 +568,13 @@ public class DownloadManagerImpl implements DownloadManager {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public DownloadAnswer handleDownloadCommand(SecondaryStorageResource resource, DownloadCommand cmd) {
|
public DownloadAnswer handleDownloadCommand(SecondaryStorageResource resource, DownloadCommand cmd) {
|
||||||
|
ResourceType resourceType = cmd.getResourceType();
|
||||||
if (cmd instanceof DownloadProgressCommand) {
|
if (cmd instanceof DownloadProgressCommand) {
|
||||||
return handleDownloadProgressCmd( resource, (DownloadProgressCommand) cmd);
|
return handleDownloadProgressCmd( resource, (DownloadProgressCommand) cmd);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (cmd.getUrl() == null) {
|
if (cmd.getUrl() == null) {
|
||||||
return new DownloadAnswer("Template is corrupted on storage due to an invalid url , cannot download", VMTemplateStorageResourceAssoc.Status.DOWNLOAD_ERROR);
|
return new DownloadAnswer(resourceType.toString() + " is corrupted on storage due to an invalid url , cannot download", VMTemplateStorageResourceAssoc.Status.DOWNLOAD_ERROR);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (cmd.getName() == null) {
|
if (cmd.getName() == null) {
|
||||||
@ -568,7 +582,11 @@ public class DownloadManagerImpl implements DownloadManager {
|
|||||||
}
|
}
|
||||||
|
|
||||||
String installPathPrefix = null;
|
String installPathPrefix = null;
|
||||||
|
if (ResourceType.TEMPLATE == resourceType){
|
||||||
installPathPrefix = resource.getRootDir(cmd) + File.separator + _templateDir;
|
installPathPrefix = resource.getRootDir(cmd) + File.separator + _templateDir;
|
||||||
|
}else {
|
||||||
|
installPathPrefix = resource.getRootDir(cmd) + File.separator + _volumeDir;
|
||||||
|
}
|
||||||
|
|
||||||
String user = null;
|
String user = null;
|
||||||
String password = null;
|
String password = null;
|
||||||
@ -576,9 +594,9 @@ public class DownloadManagerImpl implements DownloadManager {
|
|||||||
user = cmd.getAuth().getUserName();
|
user = cmd.getAuth().getUserName();
|
||||||
password = new String(cmd.getAuth().getPassword());
|
password = new String(cmd.getAuth().getPassword());
|
||||||
}
|
}
|
||||||
|
//TO DO - Define Volume max size as well
|
||||||
long maxDownloadSizeInBytes = (cmd.getMaxDownloadSizeInBytes() == null) ? TemplateDownloader.DEFAULT_MAX_TEMPLATE_SIZE_IN_BYTES : (cmd.getMaxDownloadSizeInBytes());
|
long maxDownloadSizeInBytes = (cmd.getMaxDownloadSizeInBytes() == null) ? TemplateDownloader.DEFAULT_MAX_TEMPLATE_SIZE_IN_BYTES : (cmd.getMaxDownloadSizeInBytes());
|
||||||
String jobId = downloadPublicTemplate(cmd.getId(), cmd.getUrl(), cmd.getName(), cmd.getFormat(), cmd.isHvm(), cmd.getAccountId(), cmd.getDescription(), cmd.getChecksum(), installPathPrefix, user, password, maxDownloadSizeInBytes, cmd.getProxy());
|
String jobId = downloadPublicTemplate(cmd.getId(), cmd.getUrl(), cmd.getName(), cmd.getFormat(), cmd.isHvm(), cmd.getAccountId(), cmd.getDescription(), cmd.getChecksum(), installPathPrefix, user, password, maxDownloadSizeInBytes, cmd.getProxy(), resourceType);
|
||||||
sleep();
|
sleep();
|
||||||
if (jobId == null) {
|
if (jobId == null) {
|
||||||
return new DownloadAnswer("Internal Error", VMTemplateStorageResourceAssoc.Status.DOWNLOAD_ERROR);
|
return new DownloadAnswer("Internal Error", VMTemplateStorageResourceAssoc.Status.DOWNLOAD_ERROR);
|
||||||
@ -831,6 +849,12 @@ public class DownloadManagerImpl implements DownloadManager {
|
|||||||
}
|
}
|
||||||
s_logger.info("createtmplt.sh found in " + createTmpltScr);
|
s_logger.info("createtmplt.sh found in " + createTmpltScr);
|
||||||
|
|
||||||
|
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);
|
||||||
|
|
||||||
List<ComponentInfo<Adapter>> processors = new ArrayList<ComponentInfo<Adapter>>();
|
List<ComponentInfo<Adapter>> processors = new ArrayList<ComponentInfo<Adapter>>();
|
||||||
|
|
||||||
Processor processor = new VhdProcessor();
|
Processor processor = new VhdProcessor();
|
||||||
@ -860,6 +884,7 @@ public class DownloadManagerImpl implements DownloadManager {
|
|||||||
_templateDir = TemplateConstants.DEFAULT_TMPLT_ROOT_DIR;
|
_templateDir = TemplateConstants.DEFAULT_TMPLT_ROOT_DIR;
|
||||||
}
|
}
|
||||||
_templateDir += File.separator + TemplateConstants.DEFAULT_TMPLT_FIRST_LEVEL_DIR;
|
_templateDir += File.separator + TemplateConstants.DEFAULT_TMPLT_FIRST_LEVEL_DIR;
|
||||||
|
_volumeDir = TemplateConstants.DEFAULT_VOLUME_ROOT_DIR;
|
||||||
// Add more processors here.
|
// Add more processors here.
|
||||||
threadPool = Executors.newFixedThreadPool(numInstallThreads);
|
threadPool = Executors.newFixedThreadPool(numInstallThreads);
|
||||||
return true;
|
return true;
|
||||||
|
|||||||
@ -39,8 +39,10 @@ import org.apache.commons.httpclient.auth.AuthScope;
|
|||||||
import org.apache.commons.httpclient.methods.GetMethod;
|
import org.apache.commons.httpclient.methods.GetMethod;
|
||||||
import org.apache.commons.httpclient.params.HttpMethodParams;
|
import org.apache.commons.httpclient.params.HttpMethodParams;
|
||||||
import org.apache.log4j.Logger;
|
import org.apache.log4j.Logger;
|
||||||
|
import org.jnetpcap.util.resolver.Resolver.ResolverType;
|
||||||
|
|
||||||
import com.cloud.agent.api.storage.DownloadCommand.Proxy;
|
import com.cloud.agent.api.storage.DownloadCommand.Proxy;
|
||||||
|
import com.cloud.agent.api.storage.DownloadCommand.ResourceType;
|
||||||
import com.cloud.storage.StorageLayer;
|
import com.cloud.storage.StorageLayer;
|
||||||
import com.cloud.utils.exception.CloudRuntimeException;
|
import com.cloud.utils.exception.CloudRuntimeException;
|
||||||
import com.cloud.utils.Pair;
|
import com.cloud.utils.Pair;
|
||||||
@ -70,15 +72,17 @@ public class HttpTemplateDownloader implements TemplateDownloader {
|
|||||||
|
|
||||||
private String toDir;
|
private String toDir;
|
||||||
private long MAX_TEMPLATE_SIZE_IN_BYTES;
|
private long MAX_TEMPLATE_SIZE_IN_BYTES;
|
||||||
|
private ResourceType resourceType = ResourceType.TEMPLATE;
|
||||||
private final HttpMethodRetryHandler myretryhandler;
|
private final HttpMethodRetryHandler myretryhandler;
|
||||||
|
|
||||||
public HttpTemplateDownloader (StorageLayer storageLayer, String downloadUrl, String toDir, DownloadCompleteCallback callback, long maxTemplateSizeInBytes, String user, String password, Proxy proxy) {
|
|
||||||
|
|
||||||
|
public HttpTemplateDownloader (StorageLayer storageLayer, String downloadUrl, String toDir, DownloadCompleteCallback callback, long maxTemplateSizeInBytes, String user, String password, Proxy proxy, ResourceType resourceType) {
|
||||||
this._storage = storageLayer;
|
this._storage = storageLayer;
|
||||||
this.downloadUrl = downloadUrl;
|
this.downloadUrl = downloadUrl;
|
||||||
this.setToDir(toDir);
|
this.setToDir(toDir);
|
||||||
this.status = TemplateDownloader.Status.NOT_STARTED;
|
this.status = TemplateDownloader.Status.NOT_STARTED;
|
||||||
|
this.resourceType = resourceType;
|
||||||
this.MAX_TEMPLATE_SIZE_IN_BYTES = maxTemplateSizeInBytes;
|
this.MAX_TEMPLATE_SIZE_IN_BYTES = maxTemplateSizeInBytes;
|
||||||
|
|
||||||
this.totalBytes = 0;
|
this.totalBytes = 0;
|
||||||
@ -428,7 +432,7 @@ public class HttpTemplateDownloader implements TemplateDownloader {
|
|||||||
// TODO Auto-generated catch block
|
// TODO Auto-generated catch block
|
||||||
e.printStackTrace();
|
e.printStackTrace();
|
||||||
}
|
}
|
||||||
TemplateDownloader td = new HttpTemplateDownloader(null, url,"/tmp/mysql", null, TemplateDownloader.DEFAULT_MAX_TEMPLATE_SIZE_IN_BYTES, null, null, null);
|
TemplateDownloader td = new HttpTemplateDownloader(null, url,"/tmp/mysql", null, TemplateDownloader.DEFAULT_MAX_TEMPLATE_SIZE_IN_BYTES, null, null, null, null);
|
||||||
long bytes = td.download(true, null);
|
long bytes = td.download(true, null);
|
||||||
if (bytes > 0) {
|
if (bytes > 0) {
|
||||||
System.out.println("Downloaded (" + bytes + " bytes)" + " in " + td.getDownloadTime()/1000 + " secs");
|
System.out.println("Downloaded (" + bytes + " bytes)" + " in " + td.getDownloadTime()/1000 + " secs");
|
||||||
@ -450,4 +454,9 @@ public class HttpTemplateDownloader implements TemplateDownloader {
|
|||||||
return inited;
|
return inited;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public ResourceType getResourceType() {
|
||||||
|
return resourceType;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -18,6 +18,7 @@ package com.cloud.storage.template;
|
|||||||
*/
|
*/
|
||||||
public final class TemplateConstants {
|
public final class TemplateConstants {
|
||||||
public static final String DEFAULT_TMPLT_ROOT_DIR = "template";
|
public static final String DEFAULT_TMPLT_ROOT_DIR = "template";
|
||||||
|
public static final String DEFAULT_VOLUME_ROOT_DIR = "volume";
|
||||||
public static final String DEFAULT_TMPLT_FIRST_LEVEL_DIR = "tmpl/";
|
public static final String DEFAULT_TMPLT_FIRST_LEVEL_DIR = "tmpl/";
|
||||||
|
|
||||||
public static final String DEFAULT_SYSTEM_VM_TEMPLATE_PATH = "template/tmpl/1/";
|
public static final String DEFAULT_SYSTEM_VM_TEMPLATE_PATH = "template/tmpl/1/";
|
||||||
|
|||||||
229
scripts/storage/secondary/createvolume.sh
Executable file
229
scripts/storage/secondary/createvolume.sh
Executable file
@ -0,0 +1,229 @@
|
|||||||
|
#!/usr/bin/env bash
|
||||||
|
# Copyright (C) 2011 Citrix Systems, Inc. All rights reserved
|
||||||
|
#
|
||||||
|
# This software is licensed under the GNU General Public License v3 or later.
|
||||||
|
#
|
||||||
|
# It 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, either version 3 of the License, or any later version.
|
||||||
|
# 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/>.
|
||||||
|
#
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
# $Id: createtmplt.sh 9132 2010-06-04 20:17:43Z manuel $ $HeadURL: svn://svn.lab.vmops.com/repos/vmdev/java/scripts/storage/secondary/createtmplt.sh $
|
||||||
|
# createtmplt.sh -- install a volume
|
||||||
|
|
||||||
|
usage() {
|
||||||
|
printf "Usage: %s: -t <volume-fs> -n <volumename> -f <root disk file> -c <md5 cksum> -d <descr> -h [-u] [-v]\n" $(basename $0) >&2
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#set -x
|
||||||
|
ulimit -f 41943040 #40GiB in blocks
|
||||||
|
ulimit -c 0
|
||||||
|
|
||||||
|
rollback_if_needed() {
|
||||||
|
if [ $2 -gt 0 ]
|
||||||
|
then
|
||||||
|
printf "$3\n"
|
||||||
|
#back out all changes
|
||||||
|
rm -rf $1
|
||||||
|
exit 2
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
verify_cksum() {
|
||||||
|
echo "$1 $2" | md5sum -c --status
|
||||||
|
#printf "$1\t$2" | md5sum -c --status
|
||||||
|
if [ $? -gt 0 ]
|
||||||
|
then
|
||||||
|
printf "Checksum failed, not proceeding with install\n"
|
||||||
|
exit 3
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
untar() {
|
||||||
|
local ft=$(file $1| awk -F" " '{print $2}')
|
||||||
|
case $ft in
|
||||||
|
USTAR)
|
||||||
|
printf "tar archives not supported\n" >&2
|
||||||
|
return 1
|
||||||
|
;;
|
||||||
|
*) printf "$1"
|
||||||
|
return 0
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
is_compressed() {
|
||||||
|
local ft=$(file $1| awk -F" " '{print $2}')
|
||||||
|
local tmpfile=${1}.tmp
|
||||||
|
|
||||||
|
case $ft in
|
||||||
|
gzip) ctype="gzip"
|
||||||
|
;;
|
||||||
|
bzip2) ctype="bz2"
|
||||||
|
;;
|
||||||
|
ZIP) ctype="zip"
|
||||||
|
;;
|
||||||
|
*) echo "File $1 does not appear to be compressed" >&2
|
||||||
|
return 1
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
echo "Uncompressing to $tmpfile (type $ctype)...could take a long time" >&2
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
|
||||||
|
uncompress() {
|
||||||
|
local ft=$(file $1| awk -F" " '{print $2}')
|
||||||
|
local tmpfile=${1}.tmp
|
||||||
|
|
||||||
|
case $ft in
|
||||||
|
gzip) gunzip -q -c $1 > $tmpfile
|
||||||
|
;;
|
||||||
|
bzip2) bunzip2 -q -c $1 > $tmpfile
|
||||||
|
;;
|
||||||
|
ZIP) unzip -q -p $1 | cat > $tmpfile
|
||||||
|
;;
|
||||||
|
*) printf "$1"
|
||||||
|
return 0
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
|
||||||
|
if [ $? -gt 0 ]
|
||||||
|
then
|
||||||
|
printf "Failed to uncompress file (filetype=$ft), exiting "
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
rm -f $1
|
||||||
|
printf $tmpfile
|
||||||
|
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
|
||||||
|
create_from_file() {
|
||||||
|
local tmpltfs=$1
|
||||||
|
local tmpltimg=$2
|
||||||
|
local tmpltname=$3
|
||||||
|
|
||||||
|
[ -n "$verbose" ] && echo "Moving to $tmpltfs/$tmpltname...could take a while" >&2
|
||||||
|
mv $tmpltimg /$tmpltfs/$tmpltname
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
tflag=
|
||||||
|
nflag=
|
||||||
|
fflag=
|
||||||
|
sflag=
|
||||||
|
hflag=
|
||||||
|
hvm=false
|
||||||
|
cleanup=false
|
||||||
|
dflag=
|
||||||
|
cflag=
|
||||||
|
|
||||||
|
while getopts 'vuht:n:f:s:c:d:S:' OPTION
|
||||||
|
do
|
||||||
|
case $OPTION in
|
||||||
|
t) tflag=1
|
||||||
|
tmpltfs="$OPTARG"
|
||||||
|
;;
|
||||||
|
n) nflag=1
|
||||||
|
tmpltname="$OPTARG"
|
||||||
|
;;
|
||||||
|
f) fflag=1
|
||||||
|
tmpltimg="$OPTARG"
|
||||||
|
;;
|
||||||
|
s) sflag=1
|
||||||
|
;;
|
||||||
|
c) cflag=1
|
||||||
|
cksum="$OPTARG"
|
||||||
|
;;
|
||||||
|
d) dflag=1
|
||||||
|
descr="$OPTARG"
|
||||||
|
;;
|
||||||
|
S) Sflag=1
|
||||||
|
size=$OPTARG
|
||||||
|
let "size>>=10"
|
||||||
|
ulimit -f $size
|
||||||
|
;;
|
||||||
|
h) hflag=1
|
||||||
|
hvm="true"
|
||||||
|
;;
|
||||||
|
u) cleanup="true"
|
||||||
|
;;
|
||||||
|
v) verbose="true"
|
||||||
|
;;
|
||||||
|
?) usage
|
||||||
|
exit 2
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
done
|
||||||
|
|
||||||
|
if [ "$tflag$nflag$fflag$sflag" != "1111" ]
|
||||||
|
then
|
||||||
|
usage
|
||||||
|
exit 2
|
||||||
|
fi
|
||||||
|
|
||||||
|
mkdir -p $tmpltfs
|
||||||
|
|
||||||
|
if [ ! -f $tmpltimg ]
|
||||||
|
then
|
||||||
|
printf "root disk file $tmpltimg doesn't exist\n"
|
||||||
|
exit 3
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ -n "$cksum" ]
|
||||||
|
then
|
||||||
|
verify_cksum $cksum $tmpltimg
|
||||||
|
fi
|
||||||
|
[ -n "$verbose" ] && is_compressed $tmpltimg
|
||||||
|
tmpltimg2=$(uncompress $tmpltimg)
|
||||||
|
rollback_if_needed $tmpltfs $? "failed to uncompress $tmpltimg\n"
|
||||||
|
|
||||||
|
tmpltimg2=$(untar $tmpltimg2)
|
||||||
|
rollback_if_needed $tmpltfs $? "tar archives not supported\n"
|
||||||
|
|
||||||
|
if [ ${tmpltname%.vhd} != ${tmpltname} ]
|
||||||
|
then
|
||||||
|
if which vhd-util &>/dev/null
|
||||||
|
then
|
||||||
|
vhd-util check -n ${tmpltimg2} > /dev/null
|
||||||
|
rollback_if_needed $tmpltfs $? "vhd check of $tmpltimg2 failed\n"
|
||||||
|
vhd-util set -n ${tmpltimg2} -f "hidden" -v "0" > /dev/null
|
||||||
|
rollback_if_needed $tmpltfs $? "vhd remove $tmpltimg2 hidden failed\n"
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
imgsize=$(ls -l $tmpltimg2| awk -F" " '{print $5}')
|
||||||
|
|
||||||
|
create_from_file $tmpltfs $tmpltimg2 $tmpltname
|
||||||
|
|
||||||
|
touch /$tmpltfs/volume.properties
|
||||||
|
rollback_if_needed $tmpltfs $? "Failed to create volume.properties file"
|
||||||
|
echo -n "" > /$tmpltfs/volume.properties
|
||||||
|
|
||||||
|
today=$(date '+%m_%d_%Y')
|
||||||
|
echo "filename=$tmpltname" > /$tmpltfs/volume.properties
|
||||||
|
echo "description=$descr" >> /$tmpltfs/volume.properties
|
||||||
|
echo "checksum=$cksum" >> /$tmpltfs/volume.properties
|
||||||
|
echo "hvm=$hvm" >> /$tmpltfs/volume.properties
|
||||||
|
echo "size=$imgsize" >> /$tmpltfs/volume.properties
|
||||||
|
|
||||||
|
if [ "$cleanup" == "true" ]
|
||||||
|
then
|
||||||
|
rm -f $tmpltimg
|
||||||
|
fi
|
||||||
|
|
||||||
|
exit 0
|
||||||
@ -65,6 +65,7 @@ public enum Config {
|
|||||||
StorageOverprovisioningFactor("Storage", StoragePoolAllocator.class, String.class, "storage.overprovisioning.factor", "2", "Used for storage overprovisioning calculation; available storage will be (actualStorageSize * storage.overprovisioning.factor)", null),
|
StorageOverprovisioningFactor("Storage", StoragePoolAllocator.class, String.class, "storage.overprovisioning.factor", "2", "Used for storage overprovisioning calculation; available storage will be (actualStorageSize * storage.overprovisioning.factor)", null),
|
||||||
StorageStatsInterval("Storage", ManagementServer.class, String.class, "storage.stats.interval", "60000", "The interval (in milliseconds) when storage stats (per host) are retrieved from agents.", null),
|
StorageStatsInterval("Storage", ManagementServer.class, String.class, "storage.stats.interval", "60000", "The interval (in milliseconds) when storage stats (per host) are retrieved from agents.", null),
|
||||||
MaxVolumeSize("Storage", ManagementServer.class, Integer.class, "storage.max.volume.size", "2000", "The maximum size for a volume (in GB).", null),
|
MaxVolumeSize("Storage", ManagementServer.class, Integer.class, "storage.max.volume.size", "2000", "The maximum size for a volume (in GB).", null),
|
||||||
|
MaxUploadVolumeSize("Storage", ManagementServer.class, Integer.class, "storage.max.volume.upload.size", "50", "The maximum size for a uploaded volume(in GB).", null),
|
||||||
TotalRetries("Storage", AgentManager.class, Integer.class, "total.retries", "4", "The number of times each command sent to a host should be retried in case of failure.", null),
|
TotalRetries("Storage", AgentManager.class, Integer.class, "total.retries", "4", "The number of times each command sent to a host should be retried in case of failure.", null),
|
||||||
StoragePoolMaxWaitSeconds("Storage", ManagementServer.class, Integer.class, "storage.pool.max.waitseconds", "3600", "Timeout (in seconds) to synchronize storage pool operations.", null),
|
StoragePoolMaxWaitSeconds("Storage", ManagementServer.class, Integer.class, "storage.pool.max.waitseconds", "3600", "Timeout (in seconds) to synchronize storage pool operations.", null),
|
||||||
StorageTemplateCleanupEnabled("Storage", ManagementServer.class, Boolean.class, "storage.template.cleanup.enabled", "true", "Enable/disable template cleanup activity, only take effect when overall storage cleanup is enabled", null),
|
StorageTemplateCleanupEnabled("Storage", ManagementServer.class, Boolean.class, "storage.template.cleanup.enabled", "true", "Enable/disable template cleanup activity, only take effect when overall storage cleanup is enabled", null),
|
||||||
|
|||||||
@ -153,6 +153,7 @@ import com.cloud.storage.dao.VMTemplatePoolDaoImpl;
|
|||||||
import com.cloud.storage.dao.VMTemplateSwiftDaoImpl;
|
import com.cloud.storage.dao.VMTemplateSwiftDaoImpl;
|
||||||
import com.cloud.storage.dao.VMTemplateZoneDaoImpl;
|
import com.cloud.storage.dao.VMTemplateZoneDaoImpl;
|
||||||
import com.cloud.storage.dao.VolumeDaoImpl;
|
import com.cloud.storage.dao.VolumeDaoImpl;
|
||||||
|
import com.cloud.storage.dao.VolumeHostDaoImpl;
|
||||||
import com.cloud.storage.download.DownloadMonitorImpl;
|
import com.cloud.storage.download.DownloadMonitorImpl;
|
||||||
import com.cloud.storage.secondary.SecondaryStorageManagerImpl;
|
import com.cloud.storage.secondary.SecondaryStorageManagerImpl;
|
||||||
import com.cloud.storage.snapshot.SnapshotManagerImpl;
|
import com.cloud.storage.snapshot.SnapshotManagerImpl;
|
||||||
@ -249,6 +250,7 @@ public class DefaultComponentLibrary extends ComponentLibraryBase implements Com
|
|||||||
addDao("ResourceCountDao", ResourceCountDaoImpl.class);
|
addDao("ResourceCountDao", ResourceCountDaoImpl.class);
|
||||||
addDao("UserAccountDao", UserAccountDaoImpl.class);
|
addDao("UserAccountDao", UserAccountDaoImpl.class);
|
||||||
addDao("VMTemplateHostDao", VMTemplateHostDaoImpl.class);
|
addDao("VMTemplateHostDao", VMTemplateHostDaoImpl.class);
|
||||||
|
addDao("VolumeHostDao", VolumeHostDaoImpl.class);
|
||||||
addDao("VMTemplateSwiftDao", VMTemplateSwiftDaoImpl.class);
|
addDao("VMTemplateSwiftDao", VMTemplateSwiftDaoImpl.class);
|
||||||
addDao("UploadDao", UploadDaoImpl.class);
|
addDao("UploadDao", UploadDaoImpl.class);
|
||||||
addDao("VMTemplatePoolDao", VMTemplatePoolDaoImpl.class);
|
addDao("VMTemplatePoolDao", VMTemplatePoolDaoImpl.class);
|
||||||
|
|||||||
@ -193,9 +193,11 @@ public class ConfigurationServerImpl implements ConfigurationServer {
|
|||||||
createServiceOffering(User.UID_SYSTEM, "Small Instance", 1, 512, 500, "Small Instance", false, false, null);
|
createServiceOffering(User.UID_SYSTEM, "Small Instance", 1, 512, 500, "Small Instance", false, false, null);
|
||||||
createServiceOffering(User.UID_SYSTEM, "Medium Instance", 1, 1024, 1000, "Medium Instance", false, false, null);
|
createServiceOffering(User.UID_SYSTEM, "Medium Instance", 1, 1024, 1000, "Medium Instance", false, false, null);
|
||||||
// Save default disk offerings
|
// Save default disk offerings
|
||||||
createdefaultDiskOffering(null, "Small", "Small Disk, 5 GB", 5, null);
|
createdefaultDiskOffering(null, "Small", "Small Disk, 5 GB", 5, null, false);
|
||||||
createdefaultDiskOffering(null, "Medium", "Medium Disk, 20 GB", 20, null);
|
createdefaultDiskOffering(null, "Medium", "Medium Disk, 20 GB", 20, null, false);
|
||||||
createdefaultDiskOffering(null, "Large", "Large Disk, 100 GB", 100, null);
|
createdefaultDiskOffering(null, "Large", "Large Disk, 100 GB", 100, null, false);
|
||||||
|
createdefaultDiskOffering(null, "Large", "Large Disk, 100 GB", 100, null, false);
|
||||||
|
createdefaultDiskOffering(null, "Custom", "Custom Disk", 0, null, true);
|
||||||
|
|
||||||
// Save the mount parent to the configuration table
|
// Save the mount parent to the configuration table
|
||||||
String mountParent = getMountParent();
|
String mountParent = getMountParent();
|
||||||
@ -818,12 +820,12 @@ public class ConfigurationServerImpl implements ConfigurationServer {
|
|||||||
return pod;
|
return pod;
|
||||||
}
|
}
|
||||||
|
|
||||||
private DiskOfferingVO createdefaultDiskOffering(Long domainId, String name, String description, int numGibibytes, String tags) {
|
private DiskOfferingVO createdefaultDiskOffering(Long domainId, String name, String description, int numGibibytes, String tags, boolean isCustomized) {
|
||||||
long diskSize = numGibibytes;
|
long diskSize = numGibibytes;
|
||||||
diskSize = diskSize * 1024 * 1024 * 1024;
|
diskSize = diskSize * 1024 * 1024 * 1024;
|
||||||
tags = cleanupTags(tags);
|
tags = cleanupTags(tags);
|
||||||
|
|
||||||
DiskOfferingVO newDiskOffering = new DiskOfferingVO(domainId, name, description, diskSize, tags, false);
|
DiskOfferingVO newDiskOffering = new DiskOfferingVO(domainId, name, description, diskSize, tags, isCustomized);
|
||||||
newDiskOffering.setUniqueName("Cloud.Com-" + name);
|
newDiskOffering.setUniqueName("Cloud.Com-" + name);
|
||||||
newDiskOffering = _diskOfferingDao.persistDeafultDiskOffering(newDiskOffering);
|
newDiskOffering = _diskOfferingDao.persistDeafultDiskOffering(newDiskOffering);
|
||||||
return newDiskOffering;
|
return newDiskOffering;
|
||||||
|
|||||||
@ -144,6 +144,7 @@ import com.cloud.storage.dao.VMTemplateHostDao;
|
|||||||
import com.cloud.storage.dao.VMTemplatePoolDao;
|
import com.cloud.storage.dao.VMTemplatePoolDao;
|
||||||
import com.cloud.storage.dao.VMTemplateSwiftDao;
|
import com.cloud.storage.dao.VMTemplateSwiftDao;
|
||||||
import com.cloud.storage.dao.VolumeDao;
|
import com.cloud.storage.dao.VolumeDao;
|
||||||
|
import com.cloud.storage.download.DownloadMonitor;
|
||||||
import com.cloud.storage.listener.StoragePoolMonitor;
|
import com.cloud.storage.listener.StoragePoolMonitor;
|
||||||
import com.cloud.storage.secondary.SecondaryStorageVmManager;
|
import com.cloud.storage.secondary.SecondaryStorageVmManager;
|
||||||
import com.cloud.storage.snapshot.SnapshotManager;
|
import com.cloud.storage.snapshot.SnapshotManager;
|
||||||
@ -307,6 +308,8 @@ public class StorageManagerImpl implements StorageManager, Manager, ClusterManag
|
|||||||
protected ResourceManager _resourceMgr;
|
protected ResourceManager _resourceMgr;
|
||||||
@Inject
|
@Inject
|
||||||
protected CheckPointManager _checkPointMgr;
|
protected CheckPointManager _checkPointMgr;
|
||||||
|
@Inject
|
||||||
|
protected DownloadMonitor _downloadMonitor;
|
||||||
|
|
||||||
@Inject(adapter = StoragePoolAllocator.class)
|
@Inject(adapter = StoragePoolAllocator.class)
|
||||||
protected Adapters<StoragePoolAllocator> _storagePoolAllocators;
|
protected Adapters<StoragePoolAllocator> _storagePoolAllocators;
|
||||||
@ -1633,12 +1636,12 @@ public class StorageManagerImpl implements StorageManager, Manager, ClusterManag
|
|||||||
/*
|
/*
|
||||||
* Just allocate a volume in the database, don't send the createvolume cmd to hypervisor. The volume will be finally
|
* Just allocate a volume in the database, don't send the createvolume cmd to hypervisor. The volume will be finally
|
||||||
* created
|
* created
|
||||||
* only when it's attached to a VM.
|
*
|
||||||
*/
|
*/
|
||||||
// @Override
|
@Override
|
||||||
@DB
|
@DB
|
||||||
@ActionEvent(eventType = EventTypes.EVENT_VOLUME_CREATE, eventDescription = "creating volume", create = true)
|
@ActionEvent(eventType = EventTypes.EVENT_VOLUME_CREATE, eventDescription = "creating volume", create = true)
|
||||||
public VolumeVO createVolumeEntry(UploadVolumeCmd cmd) throws ResourceAllocationException{
|
public VolumeVO uploadVolume(UploadVolumeCmd cmd) throws ResourceAllocationException{
|
||||||
Account caller = UserContext.current().getCaller();
|
Account caller = UserContext.current().getCaller();
|
||||||
long ownerId = cmd.getEntityOwnerId();
|
long ownerId = cmd.getEntityOwnerId();
|
||||||
Long zoneId = cmd.getZoneId();
|
Long zoneId = cmd.getZoneId();
|
||||||
@ -1646,8 +1649,9 @@ public class StorageManagerImpl implements StorageManager, Manager, ClusterManag
|
|||||||
String url = cmd.getUrl();
|
String url = cmd.getUrl();
|
||||||
|
|
||||||
validateVolume(caller, ownerId, zoneId, volumeName, url, cmd.getFormat());
|
validateVolume(caller, ownerId, zoneId, volumeName, url, cmd.getFormat());
|
||||||
persistVolume();
|
VolumeVO volume = persistVolume(caller, ownerId, zoneId, volumeName, url, cmd.getFormat());
|
||||||
return null;
|
_downloadMonitor.downloadVolumeToStorage(volume, zoneId, url, cmd.getChecksum());
|
||||||
|
return volume;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1732,9 +1736,35 @@ public class StorageManagerImpl implements StorageManager, Manager, ClusterManag
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private boolean persistVolume() {
|
private VolumeVO persistVolume(Account caller, long ownerId, Long zoneId, String volumeName, String url, String format) {
|
||||||
|
|
||||||
return false;
|
Transaction txn = Transaction.currentTxn();
|
||||||
|
txn.start();
|
||||||
|
|
||||||
|
VolumeVO volume = new VolumeVO(volumeName, zoneId, -1, -1, -1, new Long(-1), null, null, 0, Volume.Type.DATADISK);
|
||||||
|
volume.setPoolId(null);
|
||||||
|
volume.setDataCenterId(zoneId);
|
||||||
|
volume.setPodId(null);
|
||||||
|
volume.setAccountId(ownerId);
|
||||||
|
volume.setDomainId(((caller == null) ? Domain.ROOT_DOMAIN : caller.getDomainId()));
|
||||||
|
long diskOfferingId = _diskOfferingDao.findByUniqueName("Cloud.com-Custom").getId();
|
||||||
|
volume.setDiskOfferingId(diskOfferingId);
|
||||||
|
//volume.setSize(size);
|
||||||
|
volume.setInstanceId(null);
|
||||||
|
volume.setUpdated(new Date());
|
||||||
|
volume.setDomainId((caller == null) ? Domain.ROOT_DOMAIN : caller.getDomainId());
|
||||||
|
|
||||||
|
volume = _volsDao.persist(volume);
|
||||||
|
UsageEventVO usageEvent = new UsageEventVO(EventTypes.EVENT_VOLUME_CREATE, volume.getAccountId(), volume.getDataCenterId(), volume.getId(), volume.getName(), diskOfferingId, null, 0l);
|
||||||
|
_usageEventDao.persist(usageEvent);
|
||||||
|
|
||||||
|
UserContext.current().setEventDetails("Volume Id: " + volume.getId());
|
||||||
|
|
||||||
|
// Increment resource count during allocation; if actual creation fails, decrement it
|
||||||
|
_resourceLimitMgr.incrementResourceCount(volume.getAccountId(), ResourceType.volume);
|
||||||
|
|
||||||
|
txn.commit();
|
||||||
|
return volume;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
10
server/src/com/cloud/storage/dao/VolumeHostDao.java
Executable file
10
server/src/com/cloud/storage/dao/VolumeHostDao.java
Executable file
@ -0,0 +1,10 @@
|
|||||||
|
package com.cloud.storage.dao;
|
||||||
|
|
||||||
|
import com.cloud.storage.VolumeHostVO;
|
||||||
|
import com.cloud.utils.db.GenericDao;
|
||||||
|
|
||||||
|
public interface VolumeHostDao extends GenericDao<VolumeHostVO, Long> {
|
||||||
|
|
||||||
|
VolumeHostVO findByHostVolume(long id, long id2);
|
||||||
|
|
||||||
|
}
|
||||||
34
server/src/com/cloud/storage/dao/VolumeHostDaoImpl.java
Executable file
34
server/src/com/cloud/storage/dao/VolumeHostDaoImpl.java
Executable file
@ -0,0 +1,34 @@
|
|||||||
|
package com.cloud.storage.dao;
|
||||||
|
|
||||||
|
|
||||||
|
import javax.ejb.Local;
|
||||||
|
|
||||||
|
import com.cloud.storage.VolumeHostVO;
|
||||||
|
import com.cloud.utils.db.GenericDaoBase;
|
||||||
|
import com.cloud.utils.db.SearchBuilder;
|
||||||
|
import com.cloud.utils.db.SearchCriteria;
|
||||||
|
@Local(value={VolumeHostDao.class})
|
||||||
|
public class VolumeHostDaoImpl extends GenericDaoBase<VolumeHostVO, Long> implements VolumeHostDao {
|
||||||
|
|
||||||
|
protected final SearchBuilder<VolumeHostVO> HostVolumeSearch;
|
||||||
|
|
||||||
|
VolumeHostDaoImpl(){
|
||||||
|
HostVolumeSearch = createSearchBuilder();
|
||||||
|
HostVolumeSearch.and("host_id", HostVolumeSearch.entity().getHostId(), SearchCriteria.Op.EQ);
|
||||||
|
HostVolumeSearch.and("volume_id", HostVolumeSearch.entity().getVolumeId(), SearchCriteria.Op.EQ);
|
||||||
|
HostVolumeSearch.and("destroyed", HostVolumeSearch.entity().getDestroyed(), SearchCriteria.Op.EQ);
|
||||||
|
HostVolumeSearch.done();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public VolumeHostVO findByHostVolume(long hostId, long volumeId) {
|
||||||
|
SearchCriteria<VolumeHostVO> sc = HostVolumeSearch.create();
|
||||||
|
sc.setParameters("host_id", hostId);
|
||||||
|
sc.setParameters("volume_id", volumeId);
|
||||||
|
sc.setParameters("destroyed", false);
|
||||||
|
return findOneIncludingRemovedBy(sc);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@ -37,12 +37,17 @@ import com.cloud.agent.api.storage.DownloadProgressCommand.RequestType;
|
|||||||
import com.cloud.exception.AgentUnavailableException;
|
import com.cloud.exception.AgentUnavailableException;
|
||||||
import com.cloud.exception.ConnectionException;
|
import com.cloud.exception.ConnectionException;
|
||||||
import com.cloud.host.HostVO;
|
import com.cloud.host.HostVO;
|
||||||
|
|
||||||
import com.cloud.storage.Storage;
|
import com.cloud.storage.Storage;
|
||||||
import com.cloud.storage.VMTemplateHostVO;
|
import com.cloud.storage.VMTemplateHostVO;
|
||||||
|
import com.cloud.storage.VolumeHostVO;
|
||||||
|
import com.cloud.storage.VolumeVO;
|
||||||
import com.cloud.storage.VMTemplateStorageResourceAssoc.Status;
|
import com.cloud.storage.VMTemplateStorageResourceAssoc.Status;
|
||||||
import com.cloud.storage.VMTemplateVO;
|
import com.cloud.storage.VMTemplateVO;
|
||||||
import com.cloud.storage.dao.VMTemplateDao;
|
import com.cloud.storage.dao.VMTemplateDao;
|
||||||
import com.cloud.storage.dao.VMTemplateHostDao;
|
import com.cloud.storage.dao.VMTemplateHostDao;
|
||||||
|
import com.cloud.storage.dao.VolumeDao;
|
||||||
|
import com.cloud.storage.dao.VolumeHostDao;
|
||||||
import com.cloud.storage.download.DownloadState.DownloadEvent;
|
import com.cloud.storage.download.DownloadState.DownloadEvent;
|
||||||
import com.cloud.utils.exception.CloudRuntimeException;
|
import com.cloud.utils.exception.CloudRuntimeException;
|
||||||
|
|
||||||
@ -98,9 +103,12 @@ public class DownloadListener implements Listener {
|
|||||||
private HostVO sserver;
|
private HostVO sserver;
|
||||||
private HostVO ssAgent;
|
private HostVO ssAgent;
|
||||||
private VMTemplateVO template;
|
private VMTemplateVO template;
|
||||||
|
private VolumeVO volume;
|
||||||
|
|
||||||
private boolean downloadActive = true;
|
private boolean downloadActive = true;
|
||||||
|
|
||||||
|
private VolumeHostDao volumeHostDao;
|
||||||
|
private VolumeDao _volumeDao;
|
||||||
private VMTemplateHostDao vmTemplateHostDao;
|
private VMTemplateHostDao vmTemplateHostDao;
|
||||||
private VMTemplateDao _vmTemplateDao;
|
private VMTemplateDao _vmTemplateDao;
|
||||||
|
|
||||||
@ -119,6 +127,7 @@ public class DownloadListener implements Listener {
|
|||||||
|
|
||||||
private final Map<String, DownloadState> stateMap = new HashMap<String, DownloadState>();
|
private final Map<String, DownloadState> stateMap = new HashMap<String, DownloadState>();
|
||||||
private Long templateHostId;
|
private Long templateHostId;
|
||||||
|
private Long volumeHostId;
|
||||||
|
|
||||||
public DownloadListener(HostVO ssAgent, HostVO host, VMTemplateVO template, Timer _timer, VMTemplateHostDao dao, Long templHostId, DownloadMonitorImpl downloadMonitor, DownloadCommand cmd, VMTemplateDao templateDao) {
|
public DownloadListener(HostVO ssAgent, HostVO host, VMTemplateVO template, Timer _timer, VMTemplateHostDao dao, Long templHostId, DownloadMonitorImpl downloadMonitor, DownloadCommand cmd, VMTemplateDao templateDao) {
|
||||||
this.ssAgent = ssAgent;
|
this.ssAgent = ssAgent;
|
||||||
@ -137,6 +146,24 @@ public class DownloadListener implements Listener {
|
|||||||
updateDatabase(Status.NOT_DOWNLOADED, "");
|
updateDatabase(Status.NOT_DOWNLOADED, "");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public DownloadListener(HostVO ssAgent, HostVO host, VolumeVO volume, Timer _timer, VolumeHostDao dao, Long volHostId, DownloadMonitorImpl downloadMonitor, DownloadCommand cmd, VolumeDao volumeDao) {
|
||||||
|
this.ssAgent = ssAgent;
|
||||||
|
this.sserver = host;
|
||||||
|
this.volume = volume;
|
||||||
|
this.volumeHostDao = dao;
|
||||||
|
this.downloadMonitor = downloadMonitor;
|
||||||
|
this.cmd = cmd;
|
||||||
|
this.volumeHostId = volHostId;
|
||||||
|
initStateMachine();
|
||||||
|
this.currState=getState(Status.NOT_DOWNLOADED.toString());
|
||||||
|
this.timer = _timer;
|
||||||
|
this.timeoutTask = new TimeoutTask(this);
|
||||||
|
this.timer.schedule(timeoutTask, 3*STATUS_POLL_INTERVAL);
|
||||||
|
this._volumeDao = volumeDao;
|
||||||
|
updateDatabase(Status.NOT_DOWNLOADED, "");
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
public void setCurrState(VMTemplateHostVO.Status currState) {
|
public void setCurrState(VMTemplateHostVO.Status currState) {
|
||||||
this.currState = getState(currState.toString());
|
this.currState = getState(currState.toString());
|
||||||
}
|
}
|
||||||
@ -181,15 +208,27 @@ public class DownloadListener implements Listener {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public synchronized void updateDatabase(Status state, String errorString) {
|
public synchronized void updateDatabase(Status state, String errorString) {
|
||||||
|
if (template != null){
|
||||||
VMTemplateHostVO vo = vmTemplateHostDao.createForUpdate();
|
VMTemplateHostVO vo = vmTemplateHostDao.createForUpdate();
|
||||||
vo.setDownloadState(state);
|
vo.setDownloadState(state);
|
||||||
vo.setLastUpdated(new Date());
|
vo.setLastUpdated(new Date());
|
||||||
vo.setErrorString(errorString);
|
vo.setErrorString(errorString);
|
||||||
vmTemplateHostDao.update(getTemplateHostId(), vo);
|
vmTemplateHostDao.update(getTemplateHostId(), vo);
|
||||||
|
}else {
|
||||||
|
VolumeHostVO vo = volumeHostDao.createForUpdate();
|
||||||
|
vo.setDownloadState(state);
|
||||||
|
vo.setLastUpdated(new Date());
|
||||||
|
vo.setErrorString(errorString);
|
||||||
|
volumeHostDao.update(getVolumeHostId(), vo);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void log(String message, Level level) {
|
public void log(String message, Level level) {
|
||||||
|
if (template != null){
|
||||||
s_logger.log(level, message + ", template=" + template.getName() + " at host " + sserver.getName());
|
s_logger.log(level, message + ", template=" + template.getName() + " at host " + sserver.getName());
|
||||||
|
}else {
|
||||||
|
s_logger.log(level, message + ", volume=" + volume.getName() + " at host " + sserver.getName());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private Long getTemplateHostId() {
|
private Long getTemplateHostId() {
|
||||||
@ -200,10 +239,20 @@ public class DownloadListener implements Listener {
|
|||||||
return templateHostId;
|
return templateHostId;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private Long getVolumeHostId() {
|
||||||
|
if (volumeHostId == null){
|
||||||
|
VolumeHostVO volHost = volumeHostDao.findByHostVolume(sserver.getId(), volume.getId());
|
||||||
|
volumeHostId = volHost.getId();
|
||||||
|
}
|
||||||
|
return volumeHostId;
|
||||||
|
}
|
||||||
|
|
||||||
public DownloadListener(DownloadMonitorImpl monitor) {
|
public DownloadListener(DownloadMonitorImpl monitor) {
|
||||||
downloadMonitor = monitor;
|
downloadMonitor = monitor;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean isRecurring() {
|
public boolean isRecurring() {
|
||||||
return false;
|
return false;
|
||||||
@ -247,6 +296,7 @@ public class DownloadListener implements Listener {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public synchronized void updateDatabase(DownloadAnswer answer) {
|
public synchronized void updateDatabase(DownloadAnswer answer) {
|
||||||
|
if (template != null){
|
||||||
VMTemplateHostVO updateBuilder = vmTemplateHostDao.createForUpdate();
|
VMTemplateHostVO updateBuilder = vmTemplateHostDao.createForUpdate();
|
||||||
updateBuilder.setDownloadPercent(answer.getDownloadPct());
|
updateBuilder.setDownloadPercent(answer.getDownloadPct());
|
||||||
updateBuilder.setDownloadState(answer.getDownloadStatus());
|
updateBuilder.setDownloadState(answer.getDownloadStatus());
|
||||||
@ -265,6 +315,26 @@ public class DownloadListener implements Listener {
|
|||||||
templateDaoBuilder.setChecksum(answer.getCheckSum());
|
templateDaoBuilder.setChecksum(answer.getCheckSum());
|
||||||
_vmTemplateDao.update(template.getId(), templateDaoBuilder);
|
_vmTemplateDao.update(template.getId(), templateDaoBuilder);
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
VolumeHostVO updateBuilder = volumeHostDao.createForUpdate();
|
||||||
|
updateBuilder.setDownloadPercent(answer.getDownloadPct());
|
||||||
|
updateBuilder.setDownloadState(answer.getDownloadStatus());
|
||||||
|
updateBuilder.setLastUpdated(new Date());
|
||||||
|
updateBuilder.setErrorString(answer.getErrorString());
|
||||||
|
updateBuilder.setJobId(answer.getJobId());
|
||||||
|
updateBuilder.setLocalDownloadPath(answer.getDownloadPath());
|
||||||
|
updateBuilder.setInstallPath(answer.getInstallPath());
|
||||||
|
updateBuilder.setSize(answer.getTemplateSize());
|
||||||
|
updateBuilder.setPhysicalSize(answer.getTemplatePhySicalSize());
|
||||||
|
|
||||||
|
volumeHostDao.update(getVolumeHostId(), updateBuilder);
|
||||||
|
|
||||||
|
/*if (answer.getCheckSum() != null) {
|
||||||
|
VMTemplateVO templateDaoBuilder = _vmTemplateDao.createForUpdate();
|
||||||
|
templateDaoBuilder.setChecksum(answer.getCheckSum());
|
||||||
|
_vmTemplateDao.update(template.getId(), templateDaoBuilder);
|
||||||
|
}*/
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -361,7 +431,11 @@ public class DownloadListener implements Listener {
|
|||||||
|
|
||||||
public void setDownloadInactive(Status reason) {
|
public void setDownloadInactive(Status reason) {
|
||||||
downloadActive=false;
|
downloadActive=false;
|
||||||
|
if (template != null){
|
||||||
downloadMonitor.handleDownloadEvent(sserver, template, reason);
|
downloadMonitor.handleDownloadEvent(sserver, template, reason);
|
||||||
|
}else {
|
||||||
|
downloadMonitor.handleDownloadEvent(sserver, volume, reason);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void cancelTimeoutTask() {
|
public void cancelTimeoutTask() {
|
||||||
|
|||||||
@ -17,6 +17,7 @@ import java.util.Map;
|
|||||||
import com.cloud.exception.StorageUnavailableException;
|
import com.cloud.exception.StorageUnavailableException;
|
||||||
import com.cloud.host.HostVO;
|
import com.cloud.host.HostVO;
|
||||||
import com.cloud.storage.VMTemplateVO;
|
import com.cloud.storage.VMTemplateVO;
|
||||||
|
import com.cloud.storage.VolumeVO;
|
||||||
import com.cloud.storage.template.TemplateInfo;
|
import com.cloud.storage.template.TemplateInfo;
|
||||||
import com.cloud.utils.component.Manager;
|
import com.cloud.utils.component.Manager;
|
||||||
|
|
||||||
@ -42,4 +43,6 @@ public interface DownloadMonitor extends Manager{
|
|||||||
|
|
||||||
void addSystemVMTemplatesToHost(HostVO host, Map<String, TemplateInfo> templateInfos);
|
void addSystemVMTemplatesToHost(HostVO host, Map<String, TemplateInfo> templateInfos);
|
||||||
|
|
||||||
|
boolean downloadVolumeToStorage(VolumeVO volume, Long zoneId, String url, String checkSum);
|
||||||
|
|
||||||
}
|
}
|
||||||
@ -60,6 +60,8 @@ import com.cloud.storage.Storage.ImageFormat;
|
|||||||
import com.cloud.storage.SwiftVO;
|
import com.cloud.storage.SwiftVO;
|
||||||
import com.cloud.storage.VMTemplateHostVO;
|
import com.cloud.storage.VMTemplateHostVO;
|
||||||
import com.cloud.storage.VMTemplateStorageResourceAssoc;
|
import com.cloud.storage.VMTemplateStorageResourceAssoc;
|
||||||
|
import com.cloud.storage.VolumeHostVO;
|
||||||
|
import com.cloud.storage.VolumeVO;
|
||||||
import com.cloud.storage.VMTemplateStorageResourceAssoc.Status;
|
import com.cloud.storage.VMTemplateStorageResourceAssoc.Status;
|
||||||
import com.cloud.storage.VMTemplateVO;
|
import com.cloud.storage.VMTemplateVO;
|
||||||
import com.cloud.storage.VMTemplateZoneVO;
|
import com.cloud.storage.VMTemplateZoneVO;
|
||||||
@ -70,6 +72,8 @@ import com.cloud.storage.dao.VMTemplateHostDao;
|
|||||||
import com.cloud.storage.dao.VMTemplatePoolDao;
|
import com.cloud.storage.dao.VMTemplatePoolDao;
|
||||||
import com.cloud.storage.dao.VMTemplateSwiftDao;
|
import com.cloud.storage.dao.VMTemplateSwiftDao;
|
||||||
import com.cloud.storage.dao.VMTemplateZoneDao;
|
import com.cloud.storage.dao.VMTemplateZoneDao;
|
||||||
|
import com.cloud.storage.dao.VolumeDao;
|
||||||
|
import com.cloud.storage.dao.VolumeHostDao;
|
||||||
import com.cloud.storage.secondary.SecondaryStorageVmManager;
|
import com.cloud.storage.secondary.SecondaryStorageVmManager;
|
||||||
import com.cloud.storage.swift.SwiftManager;
|
import com.cloud.storage.swift.SwiftManager;
|
||||||
import com.cloud.storage.template.TemplateConstants;
|
import com.cloud.storage.template.TemplateConstants;
|
||||||
@ -88,6 +92,8 @@ import com.cloud.vm.UserVmManager;
|
|||||||
import com.cloud.vm.VirtualMachine.State;
|
import com.cloud.vm.VirtualMachine.State;
|
||||||
import com.cloud.vm.dao.SecondaryStorageVmDao;
|
import com.cloud.vm.dao.SecondaryStorageVmDao;
|
||||||
|
|
||||||
|
import edu.emory.mathcs.backport.java.util.Collections;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -111,6 +117,10 @@ public class DownloadMonitorImpl implements DownloadMonitor {
|
|||||||
@Inject
|
@Inject
|
||||||
SecondaryStorageVmDao _secStorageVmDao;
|
SecondaryStorageVmDao _secStorageVmDao;
|
||||||
@Inject
|
@Inject
|
||||||
|
VolumeDao _volumeDao;
|
||||||
|
@Inject
|
||||||
|
VolumeHostDao _volumeHostDao;
|
||||||
|
@Inject
|
||||||
AlertManager _alertMgr;
|
AlertManager _alertMgr;
|
||||||
@Inject
|
@Inject
|
||||||
protected SwiftManager _swiftMgr;
|
protected SwiftManager _swiftMgr;
|
||||||
@ -151,6 +161,7 @@ public class DownloadMonitorImpl implements DownloadMonitor {
|
|||||||
Timer _timer;
|
Timer _timer;
|
||||||
|
|
||||||
final Map<VMTemplateHostVO, DownloadListener> _listenerMap = new ConcurrentHashMap<VMTemplateHostVO, DownloadListener>();
|
final Map<VMTemplateHostVO, DownloadListener> _listenerMap = new ConcurrentHashMap<VMTemplateHostVO, DownloadListener>();
|
||||||
|
final Map<VolumeHostVO, DownloadListener> _listenerVolumeMap = new ConcurrentHashMap<VolumeHostVO, DownloadListener>();
|
||||||
|
|
||||||
|
|
||||||
public void send(Long hostId, Command cmd, Listener listener) throws AgentUnavailableException {
|
public void send(Long hostId, Command cmd, Listener listener) throws AgentUnavailableException {
|
||||||
@ -396,6 +407,67 @@ public class DownloadMonitorImpl implements DownloadMonitor {
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean downloadVolumeToStorage(VolumeVO volume, Long zoneId, String url, String checkSum) {
|
||||||
|
|
||||||
|
List<HostVO> ssHosts = _ssvmMgr.listAllTypesSecondaryStorageHostsInOneZone(zoneId);
|
||||||
|
Collections.shuffle(ssHosts);
|
||||||
|
HostVO ssHost = ssHosts.get(0);
|
||||||
|
downloadVolumeToStorage(volume, ssHost, url, checkSum);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void downloadVolumeToStorage(VolumeVO volume, HostVO sserver, String url, String checkSum) {
|
||||||
|
boolean downloadJobExists = false;
|
||||||
|
VolumeHostVO volumeHost = null;
|
||||||
|
|
||||||
|
volumeHost = _volumeHostDao.findByHostVolume(sserver.getId(), volume.getId());
|
||||||
|
if (volumeHost == null) {
|
||||||
|
volumeHost = new VolumeHostVO(sserver.getId(), volume.getId(), new Date(), 0, VMTemplateStorageResourceAssoc.Status.NOT_DOWNLOADED, null, null, "jobid0000", null, url, checkSum);
|
||||||
|
_volumeHostDao.persist(volumeHost);
|
||||||
|
} else if ((volumeHost.getJobId() != null) && (volumeHost.getJobId().length() > 2)) {
|
||||||
|
downloadJobExists = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
Long maxVolumeSizeInBytes = getMaxVolumeSizeInBytes();
|
||||||
|
String secUrl = sserver.getStorageUrl();
|
||||||
|
if(volumeHost != null) {
|
||||||
|
start();
|
||||||
|
DownloadCommand dcmd = new DownloadCommand(secUrl, volume, maxVolumeSizeInBytes, checkSum, url);
|
||||||
|
dcmd.setProxy(getHttpProxy());
|
||||||
|
if (downloadJobExists) {
|
||||||
|
dcmd = new DownloadProgressCommand(dcmd, volumeHost.getJobId(), RequestType.GET_OR_RESTART);
|
||||||
|
}
|
||||||
|
|
||||||
|
HostVO ssvm = _ssvmMgr.pickSsvmHost(sserver);
|
||||||
|
if( ssvm == null ) {
|
||||||
|
s_logger.warn("There is no secondary storage VM for secondary storage host " + sserver.getName());
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
DownloadListener dl = new DownloadListener(ssvm, sserver, volume, _timer, _volumeHostDao, volumeHost.getId(), this, dcmd, _volumeDao);
|
||||||
|
|
||||||
|
if (downloadJobExists) {
|
||||||
|
dl.setCurrState(volumeHost.getDownloadState());
|
||||||
|
}
|
||||||
|
DownloadListener old = null;
|
||||||
|
synchronized (_listenerVolumeMap) {
|
||||||
|
old = _listenerVolumeMap.put(volumeHost, dl);
|
||||||
|
}
|
||||||
|
if( old != null ) {
|
||||||
|
old.abandon();
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
send(ssvm.getId(), dcmd, dl);
|
||||||
|
} catch (AgentUnavailableException e) {
|
||||||
|
s_logger.warn("Unable to start /resume download of template " + volume.getName() + " to " + sserver.getName(), e);
|
||||||
|
dl.setDisconnected();
|
||||||
|
dl.scheduleStatusCheck(RequestType.GET_OR_RESTART);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
private void initiateTemplateDownload(Long templateId, HostVO ssHost) {
|
private void initiateTemplateDownload(Long templateId, HostVO ssHost) {
|
||||||
VMTemplateVO template = _templateDao.findById(templateId);
|
VMTemplateVO template = _templateDao.findById(templateId);
|
||||||
if (template != null && (template.getUrl() != null)) {
|
if (template != null && (template.getUrl() != null)) {
|
||||||
@ -439,6 +511,37 @@ public class DownloadMonitorImpl implements DownloadMonitor {
|
|||||||
txn.commit();
|
txn.commit();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@DB
|
||||||
|
public void handleDownloadEvent(HostVO host, VolumeVO volume, Status dnldStatus) {
|
||||||
|
if ((dnldStatus == VMTemplateStorageResourceAssoc.Status.DOWNLOADED) || (dnldStatus==Status.ABANDONED)){
|
||||||
|
VolumeHostVO volumeHost = new VolumeHostVO(host.getId(), volume.getId());
|
||||||
|
synchronized (_listenerVolumeMap) {
|
||||||
|
_listenerVolumeMap.remove(volumeHost);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
VolumeHostVO volumeHost = _volumeHostDao.findByHostVolume(host.getId(), volume.getId());
|
||||||
|
|
||||||
|
Transaction txn = Transaction.currentTxn();
|
||||||
|
txn.start();
|
||||||
|
|
||||||
|
if (dnldStatus == Status.DOWNLOADED) {
|
||||||
|
long size = -1;
|
||||||
|
if(volumeHost!=null){
|
||||||
|
size = volumeHost.getPhysicalSize();
|
||||||
|
}
|
||||||
|
else{
|
||||||
|
s_logger.warn("Failed to get size for volume" + volume.getName());
|
||||||
|
}
|
||||||
|
String eventType = EventTypes.EVENT_VOLUME_CREATE;
|
||||||
|
if(volume.getAccountId() != Account.ACCOUNT_ID_SYSTEM){
|
||||||
|
UsageEventVO usageEvent = new UsageEventVO(eventType, volume.getAccountId(), host.getDataCenterId(), volume.getId(), volume.getName(), null, 0l , size);
|
||||||
|
_usageEventDao.persist(usageEvent);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
txn.commit();
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void handleSysTemplateDownload(HostVO host) {
|
public void handleSysTemplateDownload(HostVO host) {
|
||||||
List<HypervisorType> hypers = _resourceMgr.listAvailHypervisorInZone(host.getId(), host.getDataCenterId());
|
List<HypervisorType> hypers = _resourceMgr.listAvailHypervisorInZone(host.getId(), host.getDataCenterId());
|
||||||
@ -752,6 +855,14 @@ public class DownloadMonitorImpl implements DownloadMonitor {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private Long getMaxVolumeSizeInBytes() {
|
||||||
|
try {
|
||||||
|
return Long.parseLong(_configDao.getValue("storage.max.volume.upload.size")) * 1024L * 1024L * 1024L;
|
||||||
|
} catch (NumberFormatException e) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private Proxy getHttpProxy() {
|
private Proxy getHttpProxy() {
|
||||||
if (_proxy == null) {
|
if (_proxy == null) {
|
||||||
return null;
|
return null;
|
||||||
|
|||||||
@ -506,15 +506,6 @@ public class UserVmManagerImpl implements UserVmManager, UserVmService, Manager
|
|||||||
throw new InvalidParameterValueException("Please specify a valid data volume.");
|
throw new InvalidParameterValueException("Please specify a valid data volume.");
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check that the volume is stored on shared storage
|
|
||||||
if (!(Volume.State.Allocated.equals(volume.getState())) && !_storageMgr.volumeOnSharedStoragePool(volume)) {
|
|
||||||
throw new InvalidParameterValueException("Please specify a volume that has been created on a shared storage pool.");
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!(Volume.State.Allocated.equals(volume.getState()) || Volume.State.Ready.equals(volume.getState()))) {
|
|
||||||
throw new InvalidParameterValueException("Volume state must be in Allocated or Ready state");
|
|
||||||
}
|
|
||||||
|
|
||||||
// Check that the volume is not currently attached to any VM
|
// Check that the volume is not currently attached to any VM
|
||||||
if (volume.getInstanceId() != null) {
|
if (volume.getInstanceId() != null) {
|
||||||
throw new InvalidParameterValueException("Please specify a volume that is not attached to any VM.");
|
throw new InvalidParameterValueException("Please specify a volume that is not attached to any VM.");
|
||||||
@ -557,6 +548,16 @@ public class UserVmManagerImpl implements UserVmManager, UserVmService, Manager
|
|||||||
//permission check
|
//permission check
|
||||||
_accountMgr.checkAccess(caller, null, true, volume, vm);
|
_accountMgr.checkAccess(caller, null, true, volume, vm);
|
||||||
|
|
||||||
|
|
||||||
|
// Check that the volume is stored on shared storage
|
||||||
|
if (!(Volume.State.Allocated.equals(volume.getState())) && !_storageMgr.volumeOnSharedStoragePool(volume)) {
|
||||||
|
throw new InvalidParameterValueException("Please specify a volume that has been created on a shared storage pool.");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!(Volume.State.Allocated.equals(volume.getState()) || Volume.State.Ready.equals(volume.getState()))) {
|
||||||
|
throw new InvalidParameterValueException("Volume state must be in Allocated or Ready state");
|
||||||
|
}
|
||||||
|
|
||||||
VolumeVO rootVolumeOfVm = null;
|
VolumeVO rootVolumeOfVm = null;
|
||||||
List<VolumeVO> rootVolumesOfVm = _volsDao.findByInstanceAndType(vmId, Volume.Type.ROOT);
|
List<VolumeVO> rootVolumesOfVm = _volsDao.findByInstanceAndType(vmId, Volume.Type.ROOT);
|
||||||
if (rootVolumesOfVm.size() != 1) {
|
if (rootVolumesOfVm.size() != 1) {
|
||||||
|
|||||||
@ -38,6 +38,7 @@ DROP TABLE IF EXISTS `cloud`.`pricing`;
|
|||||||
DROP TABLE IF EXISTS `cloud`.`sequence`;
|
DROP TABLE IF EXISTS `cloud`.`sequence`;
|
||||||
DROP TABLE IF EXISTS `cloud`.`user_vm`;
|
DROP TABLE IF EXISTS `cloud`.`user_vm`;
|
||||||
DROP TABLE IF EXISTS `cloud`.`template_host_ref`;
|
DROP TABLE IF EXISTS `cloud`.`template_host_ref`;
|
||||||
|
DROP TABLE IF EXISTS `cloud`.`volume_host_ref`;
|
||||||
DROP TABLE IF EXISTS `cloud`.`upload`;
|
DROP TABLE IF EXISTS `cloud`.`upload`;
|
||||||
DROP TABLE IF EXISTS `cloud`.`template_zone_ref`;
|
DROP TABLE IF EXISTS `cloud`.`template_zone_ref`;
|
||||||
DROP TABLE IF EXISTS `cloud`.`dc_vnet_alloc`;
|
DROP TABLE IF EXISTS `cloud`.`dc_vnet_alloc`;
|
||||||
@ -1125,6 +1126,30 @@ CREATE TABLE `cloud`.`template_host_ref` (
|
|||||||
INDEX `i_template_host_ref__template_id`(`template_id`)
|
INDEX `i_template_host_ref__template_id`(`template_id`)
|
||||||
) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8;
|
) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8;
|
||||||
|
|
||||||
|
CREATE TABLE `cloud`.`volume_host_ref` (
|
||||||
|
`id` bigint unsigned NOT NULL auto_increment,
|
||||||
|
`host_id` bigint unsigned NOT NULL,
|
||||||
|
`volume_id` bigint unsigned NOT NULL,
|
||||||
|
`created` DATETIME NOT NULL,
|
||||||
|
`last_updated` DATETIME,
|
||||||
|
`job_id` varchar(255),
|
||||||
|
`download_pct` int(10) unsigned,
|
||||||
|
`size` bigint unsigned,
|
||||||
|
`physical_size` bigint unsigned DEFAULT 0,
|
||||||
|
`download_state` varchar(255),
|
||||||
|
`checksum` varchar(255) COMMENT 'checksum for the data disk',
|
||||||
|
`error_str` varchar(255),
|
||||||
|
`local_path` varchar(255),
|
||||||
|
`install_path` varchar(255),
|
||||||
|
`url` varchar(255),
|
||||||
|
`destroyed` tinyint(1) COMMENT 'indicates whether the volume_host entry was destroyed by the user or not',
|
||||||
|
PRIMARY KEY (`id`),
|
||||||
|
CONSTRAINT `fk_volume_host_ref__host_id` FOREIGN KEY `fk_volume_host_ref__host_id` (`host_id`) REFERENCES `host` (`id`) ON DELETE CASCADE,
|
||||||
|
INDEX `i_volume_host_ref__host_id`(`host_id`),
|
||||||
|
CONSTRAINT `fk_volume_host_ref__volume_id` FOREIGN KEY `fk_volume_host_ref__volume_id` (`volume_id`) REFERENCES `volumes` (`id`),
|
||||||
|
INDEX `i_volume_host_ref__volume_id`(`volume_id`)
|
||||||
|
) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8;
|
||||||
|
|
||||||
CREATE TABLE `cloud`.`template_swift_ref` (
|
CREATE TABLE `cloud`.`template_swift_ref` (
|
||||||
`id` bigint unsigned NOT NULL auto_increment,
|
`id` bigint unsigned NOT NULL auto_increment,
|
||||||
`swift_id` bigint unsigned NOT NULL,
|
`swift_id` bigint unsigned NOT NULL,
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user