diff --git a/plugins/hypervisors/hyperv/DotNet/ServerResource/HypervResource/CloudStackTypes.cs b/plugins/hypervisors/hyperv/DotNet/ServerResource/HypervResource/CloudStackTypes.cs index eb20d7fd082..896a3247441 100644 --- a/plugins/hypervisors/hyperv/DotNet/ServerResource/HypervResource/CloudStackTypes.cs +++ b/plugins/hypervisors/hyperv/DotNet/ServerResource/HypervResource/CloudStackTypes.cs @@ -153,14 +153,33 @@ namespace HypervResource get { string fileName = null; - if (this.primaryDataStore.isLocal) + if (this.primaryDataStore != null) { - fileName = Path.Combine(this.primaryDataStore.Path, this.name); + PrimaryDataStoreTO store = this.primaryDataStore; + if (store.isLocal) + { + fileName = Path.Combine(store.Path, this.name); + } + else + { + fileName = @"\\" + store.uri.Host + store.uri.LocalPath + @"\" + this.name; + fileName = Utils.NormalizePath(fileName); + } + } + else if (this.nfsDataStore != null) + { + fileName = this.nfsDataStore.UncPath; + if (this.path != null) + { + fileName += @"\" + this.path; + } + fileName = Utils.NormalizePath(fileName + @"\" + this.name); } else { - fileName = @"\\" + this.primaryDataStore.uri.Host + this.primaryDataStore.uri.LocalPath + @"\" + this.name; - fileName = Utils.NormalizePath(fileName); + String errMsg = "Invalid dataStore in VolumeObjectTO spec"; + logger.Error(errMsg); + throw new InvalidDataException(errMsg); } if (this.format != null) @@ -175,9 +194,11 @@ namespace HypervResource public dynamic dataStore; public string format; public string name; + public string path; public string uuid; public ulong size; public PrimaryDataStoreTO primaryDataStore; + public NFSTO nfsDataStore; public static VolumeObjectTO ParseJson(dynamic json) { @@ -196,15 +217,17 @@ namespace HypervResource dataStore = volumeObjectTOJson.dataStore, format = ((string)volumeObjectTOJson.format), name = (string)volumeObjectTOJson.name, + path = volumeObjectTOJson.path, uuid = (string)volumeObjectTOJson.uuid, size = (ulong)volumeObjectTOJson.size }; result.primaryDataStore = PrimaryDataStoreTO.ParseJson(volumeObjectTOJson.dataStore); + result.nfsDataStore = NFSTO.ParseJson(volumeObjectTOJson.dataStore); // Assert - if (result.dataStore == null || result.primaryDataStore == null) + if (result.dataStore == null || (result.primaryDataStore == null && result.nfsDataStore == null)) { - String errMsg = "VolumeObjectTO missing primary dataStore in spec " + volumeObjectTOJson.ToString(); + String errMsg = "VolumeObjectTO missing dataStore in spec " + volumeObjectTOJson.ToString(); logger.Error(errMsg); throw new ArgumentNullException(errMsg); } @@ -220,22 +243,48 @@ namespace HypervResource { logger.Info("No image format in VolumeObjectTO, going to use format from first file that matches " + volInfo.FullFileName); - string path = volInfo.primaryDataStore.Path; - if (!volInfo.primaryDataStore.isLocal) + string path = null; + if (volInfo.primaryDataStore != null) { - path = volInfo.primaryDataStore.UncPath; + if (volInfo.primaryDataStore.isLocal) + { + path = volInfo.primaryDataStore.Path; + } + else + { + path = volInfo.primaryDataStore.UncPath; + } } - - string[] choices = choices = Directory.GetFiles(path, volInfo.name + ".vhd*"); - if (choices.Length != 1) + else if (volInfo.nfsDataStore != null) { - String errMsg = "Tried to guess file extension, but cannot find file corresponding to " + Path.Combine(volInfo.primaryDataStore.Path, volInfo.name); // format being guessed. - logger.Debug(errMsg); + path = volInfo.nfsDataStore.UncPath; + if (volInfo.path != null) + { + path += @"\" + volInfo.path; + } } else { - string[] splitFileName = choices[0].Split(new char[] { '.' }); - volInfo.format = splitFileName[splitFileName.Length - 1]; + String errMsg = "VolumeObjectTO missing dataStore in spec " + volInfo.ToString(); + logger.Error(errMsg); + throw new ArgumentNullException(errMsg); + } + + path = Utils.NormalizePath(path); + if (Directory.Exists(path)) + { + string[] choices = choices = Directory.GetFiles(path, volInfo.name + ".vhd*"); + if (choices.Length != 1) + { + String errMsg = "Tried to guess file extension, but cannot find file corresponding to " + + Path.Combine(volInfo.primaryDataStore.Path, volInfo.name); + logger.Debug(errMsg); + } + else + { + string[] splitFileName = choices[0].Split(new char[] { '.' }); + volInfo.format = splitFileName[splitFileName.Length - 1]; + } } logger.Debug("Going to use file " + volInfo.FullFileName); } diff --git a/plugins/hypervisors/hyperv/DotNet/ServerResource/HypervResource/HypervResourceController.cs b/plugins/hypervisors/hyperv/DotNet/ServerResource/HypervResource/HypervResourceController.cs index f48a6f021f8..35bce5d42f5 100644 --- a/plugins/hypervisors/hyperv/DotNet/ServerResource/HypervResource/HypervResourceController.cs +++ b/plugins/hypervisors/hyperv/DotNet/ServerResource/HypervResource/HypervResourceController.cs @@ -688,7 +688,6 @@ namespace HypervResource } // POST api/HypervResource/CheckHealthCommand - // TODO: create test [HttpPost] [ActionName(CloudStackTypes.CheckHealthCommand)] public JContainer CheckHealthCommand([FromBody]dynamic cmd) @@ -706,6 +705,24 @@ namespace HypervResource } } + // POST api/HypervResource/CheckOnHostCommand + [HttpPost] + [ActionName(CloudStackTypes.CheckOnHostCommand)] + public JContainer CheckOnHostCommand([FromBody]dynamic cmd) + { + using (log4net.NDC.Push(Guid.NewGuid().ToString())) + { + logger.Info(CloudStackTypes.CheckOnHostCommand + cmd.ToString()); + object ansContent = new + { + result = true, + details = "resource is alive", + contextMap = contextMap + }; + return ReturnCloudStackTypedJArray(ansContent, CloudStackTypes.CheckOnHostAnswer); + } + } + // POST api/HypervResource/CheckSshCommand // TODO: create test [HttpPost] @@ -1229,6 +1246,7 @@ namespace HypervResource using (log4net.NDC.Push(Guid.NewGuid().ToString())) { // Log command *after* we've removed security details from the command. + logger.Info(CloudStackTypes.CopyCommand + cmd.ToString()); bool result = false; string details = null; @@ -1240,10 +1258,9 @@ namespace HypervResource TemplateObjectTO srcTemplateObjectTO = TemplateObjectTO.ParseJson(cmd.srcTO); TemplateObjectTO destTemplateObjectTO = TemplateObjectTO.ParseJson(cmd.destTO); + VolumeObjectTO srcVolumeObjectTO = VolumeObjectTO.ParseJson(cmd.srcTO); VolumeObjectTO destVolumeObjectTO = VolumeObjectTO.ParseJson(cmd.destTO); - logger.Info(CloudStackTypes.CopyCommand + cmd.ToString()); - string destFile = null; if (destTemplateObjectTO != null && destTemplateObjectTO.primaryDataStore != null) { @@ -1379,6 +1396,38 @@ namespace HypervResource 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); + newData = cmd.destTO; + result = true; + } + } else { details = "Data store combination not supported";