in plugins/hypervisors/hyperv/DotNet/ServerResource/HypervResource/HypervResourceController.cs [1516:1788]
public JContainer CopyCommand(dynamic cmd)
{
using (log4net.NDC.Push(Guid.NewGuid().ToString()))
{
// Log command *after* we've removed security details from the command.
logger.Info(CloudStackTypes.CopyCommand + Utils.CleanString(cmd.ToString()));
bool result = false;
string details = null;
object newData = null;
TemplateObjectTO destTemplateObjectTO = null;
VolumeObjectTO destVolumeObjectTO = null;
VolumeObjectTO srcVolumeObjectTO = null;
TemplateObjectTO srcTemplateObjectTO = null;
try
{
srcTemplateObjectTO = TemplateObjectTO.ParseJson(cmd.srcTO);
destTemplateObjectTO = TemplateObjectTO.ParseJson(cmd.destTO);
srcVolumeObjectTO = VolumeObjectTO.ParseJson(cmd.srcTO);
destVolumeObjectTO = VolumeObjectTO.ParseJson(cmd.destTO);
string destFile = null;
if (destTemplateObjectTO != null)
{
if (destTemplateObjectTO.path == null)
{
destTemplateObjectTO.path = System.Guid.NewGuid().ToString();
}
if (destTemplateObjectTO.primaryDataStore != null)
{
destFile = destTemplateObjectTO.FullFileName;
}
else if (destTemplateObjectTO.nfsDataStoreTO != null)
{
destFile = destTemplateObjectTO.FullFileName;
}
}
// Create local copy of a template?
if (srcTemplateObjectTO != null && destTemplateObjectTO != null)
{
// S3 download to primary storage?
// NFS provider download to primary storage?
if ((srcTemplateObjectTO.s3DataStoreTO != null || srcTemplateObjectTO.nfsDataStoreTO != null) && destTemplateObjectTO.primaryDataStore != null)
{
if (File.Exists(destFile))
{
logger.Info("Deleting existing file " + destFile);
File.Delete(destFile);
}
if (srcTemplateObjectTO.s3DataStoreTO != null)
{
// Download from S3 to destination data storage
DownloadS3ObjectToFile(srcTemplateObjectTO.path, srcTemplateObjectTO.s3DataStoreTO, destFile);
}
else if (srcTemplateObjectTO.nfsDataStoreTO != null)
{
// Download from S3 to destination data storage
Utils.DownloadCifsFileToLocalFile(srcTemplateObjectTO.path, srcTemplateObjectTO.nfsDataStoreTO, destFile);
}
// Uncompress, as required
if (srcTemplateObjectTO.path.EndsWith(".bz2"))
{
String uncompressedFile = destFile + ".tmp";
String compressedFile = destFile;
using (var uncompressedOutStrm = new FileStream(uncompressedFile, FileMode.CreateNew, FileAccess.Write))
{
using (var compressedInStrm = new FileStream(destFile, FileMode.Open, FileAccess.Read))
{
using (var bz2UncompressorStrm = new Ionic.BZip2.BZip2InputStream(compressedInStrm, true) /* outer 'using' statement will close FileStream*/ )
{
int count = 0;
int bufsize = 1024 * 1024;
byte[] buf = new byte[bufsize];
// EOF returns -1, see http://dotnetzip.codeplex.com/workitem/16069
while (0 < (count = bz2UncompressorStrm.Read(buf, 0, bufsize)))
{
uncompressedOutStrm.Write(buf, 0, count);
}
}
}
}
File.Delete(compressedFile);
File.Move(uncompressedFile, compressedFile);
if (File.Exists(uncompressedFile))
{
String errMsg = "Extra file left around called " + uncompressedFile + " when creating " + destFile;
logger.Error(errMsg);
throw new IOException(errMsg);
}
}
// assert
if (!File.Exists(destFile))
{
String errMsg = "Failed to create " + destFile + " , because the file is missing";
logger.Error(errMsg);
throw new IOException(errMsg);
}
FileInfo destFileInfo = new FileInfo(destFile);
destTemplateObjectTO.size = destFileInfo.Length.ToString();
JObject ansObj = Utils.CreateCloudStackObject(CloudStackTypes.TemplateObjectTO, destTemplateObjectTO);
newData = ansObj;
result = true;
}
else
{
details = "Data store combination not supported";
}
}
// Create volume from a template?
else if (srcTemplateObjectTO != null && destVolumeObjectTO != null)
{
// VolumeObjectTO guesses file extension based on existing files
// this can be wrong if the previous file had a different file type
var guessedDestFile = destVolumeObjectTO.FullFileName;
if (File.Exists(guessedDestFile))
{
logger.Info("Deleting existing file " + guessedDestFile);
File.Delete(guessedDestFile);
}
destVolumeObjectTO.format = srcTemplateObjectTO.format;
destFile = destVolumeObjectTO.FullFileName;
if (File.Exists(destFile))
{
logger.Info("Deleting existing file " + destFile);
File.Delete(destFile);
}
string srcFile = srcTemplateObjectTO.FullFileName;
if (!File.Exists(srcFile))
{
details = "Local template file missing from " + srcFile;
}
else
{
// TODO: thin provision instead of copying the full file.
File.Copy(srcFile, destFile);
destVolumeObjectTO.path = destVolumeObjectTO.uuid;
JObject ansObj = Utils.CreateCloudStackObject(CloudStackTypes.VolumeObjectTO, destVolumeObjectTO);
newData = ansObj;
result = true;
}
}
else if (srcVolumeObjectTO != null && destVolumeObjectTO != null)
{
var guessedDestFile = destVolumeObjectTO.FullFileName;
if (File.Exists(guessedDestFile))
{
logger.Info("Deleting existing file " + guessedDestFile);
File.Delete(guessedDestFile);
}
destVolumeObjectTO.format = srcVolumeObjectTO.format;
destFile = destVolumeObjectTO.FullFileName;
if (File.Exists(destFile))
{
logger.Info("Deleting existing file " + destFile);
File.Delete(destFile);
}
string srcFile = srcVolumeObjectTO.FullFileName;
if (!File.Exists(srcFile))
{
details = "Local template file missing from " + srcFile;
}
else
{
// Create the directory before copying the files. CreateDirectory
// doesn't do anything if the directory is already present.
Directory.CreateDirectory(Path.GetDirectoryName(destFile));
File.Copy(srcFile, destFile);
if (srcVolumeObjectTO.nfsDataStore != null && srcVolumeObjectTO.primaryDataStore == null)
{
logger.Info("Copied volume from secondary data store to primary. Path: " + destVolumeObjectTO.path);
}
else if (srcVolumeObjectTO.primaryDataStore != null && srcVolumeObjectTO.nfsDataStore == null)
{
destVolumeObjectTO.path = destVolumeObjectTO.path + "/" + destVolumeObjectTO.uuid;
if (destVolumeObjectTO.format != null)
{
destVolumeObjectTO.path += "." + destVolumeObjectTO.format.ToLower();
}
}
else
{
logger.Error("Destination volume path wasn't set. Unsupported source volume data store.");
}
// Create volumeto object deserialize and send it
JObject ansObj = Utils.CreateCloudStackObject(CloudStackTypes.VolumeObjectTO, destVolumeObjectTO);
newData = ansObj;
result = true;
}
}
else if (srcVolumeObjectTO != null && destTemplateObjectTO != null)
{
var guessedDestFile = destTemplateObjectTO.FullFileName;
if (File.Exists(guessedDestFile))
{
logger.Info("Deleting existing file " + guessedDestFile);
File.Delete(guessedDestFile);
}
destTemplateObjectTO.format = srcVolumeObjectTO.format;
destFile = destTemplateObjectTO.FullFileName;
if (File.Exists(destFile))
{
logger.Info("Deleting existing file " + destFile);
File.Delete(destFile);
}
string srcFile = srcVolumeObjectTO.FullFileName;
if (!File.Exists(srcFile))
{
details = "Local template file missing from " + srcFile;
}
else
{
// Create the directory before copying the files. CreateDirectory
// doesn't do anything if the directory is already present.
Directory.CreateDirectory(Path.GetDirectoryName(destFile));
File.Copy(srcFile, destFile);
FileInfo destFileInfo = new FileInfo(destFile);
// Write the template.properties file
PostCreateTemplate(Path.GetDirectoryName(destFile), destTemplateObjectTO.id, destTemplateObjectTO.name,
destFileInfo.Length.ToString(), srcVolumeObjectTO.size.ToString(), destTemplateObjectTO.format);
TemplateObjectTO destTemplateObject = new TemplateObjectTO();
destTemplateObject.size = srcVolumeObjectTO.size.ToString();
destTemplateObject.format = srcVolumeObjectTO.format;
destTemplateObject.path = destTemplateObjectTO.path + "/" + destTemplateObjectTO.uuid;
if (destTemplateObject.format != null)
{
destTemplateObject.path += "." + destTemplateObject.format.ToLower();
}
destTemplateObject.nfsDataStoreTO = destTemplateObjectTO.nfsDataStoreTO;
destTemplateObject.checksum = destTemplateObjectTO.checksum;
JObject ansObj = Utils.CreateCloudStackObject(CloudStackTypes.TemplateObjectTO, destTemplateObject);
newData = ansObj;
result = true;
}
}
else
{
details = "Data store combination not supported";
}
}
catch (Exception ex)
{
// Test by providing wrong key
details = CloudStackTypes.CopyCommand + " failed on exception, " + ex.Message;
logger.Error(details, ex);
}
object ansContent = new
{
result = result,
details = details,
newData = newData,
contextMap = contextMap
};
return ReturnCloudStackTypedJArray(ansContent, CloudStackTypes.CopyCmdAnswer);
}
}