| // Licensed to the Apache Software Foundation (ASF) under one | |
| // or more contributor license agreements. See the NOTICE file | |
| // distributed with this work for additional information | |
| // regarding copyright ownership. The ASF licenses this file | |
| // to you under the Apache License, Version 2.0 (the | |
| // "License"); you may not use this file except in compliance | |
| // with the License. You may obtain a copy of the License at | |
| // | |
| // http://www.apache.org/licenses/LICENSE-2.0 | |
| // | |
| // Unless required by applicable law or agreed to in writing, | |
| // software distributed under the License is distributed on an | |
| // "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY | |
| // KIND, either express or implied. See the License for the | |
| // specific language governing permissions and limitations | |
| // under the License. | |
| using log4net; | |
| using Newtonsoft.Json.Linq; | |
| using System; | |
| using System.Collections.Generic; | |
| using System.IO; | |
| using System.Linq; | |
| using System.Runtime.InteropServices; | |
| using System.Security.Principal; | |
| using System.Text; | |
| using System.Threading.Tasks; | |
| using System.Diagnostics; | |
| using System.Reflection; | |
| namespace HypervResource | |
| { | |
| public class Utils | |
| { | |
| private static ILog s_logger = LogManager.GetLogger(typeof(Utils)); | |
| private const string TASK_PREFIX = "cloudstack-heartbeat-"; | |
| private const string BATCH_FILE = "heartbeat.bat"; | |
| /// <summary> | |
| /// Associate CloudStack object's content with a fully qualified type name. | |
| /// </summary> | |
| /// <param name="objType">Fully qualified type name, e.g. "org.apache.cloudstack.storage.to.TemplateObjectTO"</param> | |
| /// <param name="objValue">Object's data, can be an anonymous object, e.g. </param> | |
| /// <returns></returns> | |
| public static JObject CreateCloudStackObject(string objType, object objValue) | |
| { | |
| JToken objContent = JToken.FromObject(objValue); | |
| JProperty objTypeValuePairing = new JProperty(objType, objContent); | |
| return new JObject(objTypeValuePairing); | |
| } | |
| /// <summary> | |
| /// serialize dictonary to map json type | |
| /// </summary> | |
| /// <param name="objValue">Object's data, can be an anonymous object, e.g. </param> | |
| /// <returns></returns> | |
| public static JToken CreateCloudStackMapObject(object objValue) | |
| { | |
| JToken objContent = JToken.FromObject(objValue); | |
| return objContent; | |
| } | |
| public static string NormalizePath(string path) | |
| { | |
| if (!String.IsNullOrEmpty(path)) | |
| { | |
| path = path.Replace('/', Path.DirectorySeparatorChar); | |
| } | |
| return path; | |
| } | |
| /// <summary> | |
| /// Copy file on network share to local volume. | |
| /// </summary> | |
| /// <remarks> | |
| /// Access to the network share is acheived by logging into the domain corresponding to the user credentials provided. | |
| /// Windows impersonation does not suffice, because impersonation is limited to domains with an established trust relationship. | |
| /// We have had to import Win32 API calls to allow login. There are a number of examples online. We follow the | |
| /// one at http://stackoverflow.com/a/2541569/939250 </remarks> | |
| /// <param name="filePathRelativeToShare"></param> | |
| /// <param name="cifsShareDetails"></param> | |
| /// <param name="destFile"></param> | |
| public static void DownloadCifsFileToLocalFile(string filePathRelativeToShare, NFSTO cifsShareDetails, string destFile) | |
| { | |
| String dest = ""; | |
| if (filePathRelativeToShare.EndsWith(".iso") || filePathRelativeToShare.EndsWith(".vhd") || filePathRelativeToShare.EndsWith(".vhdx")) | |
| { | |
| dest = Path.Combine(cifsShareDetails.UncPath, filePathRelativeToShare); | |
| dest = Utils.NormalizePath(dest); | |
| } | |
| // if the filePathRelativeToShare string don't have filename and only a dir point then find the vhd files in that folder and use | |
| // In the clean setup, first copy command won't be having the filename it contains onlyu dir path. | |
| // we need to scan the folder point and then copy the file to destination. | |
| else if (!filePathRelativeToShare.EndsWith(".vhd") || !filePathRelativeToShare.EndsWith(".vhdx")) | |
| { | |
| // scan the folder and get the vhd filename. | |
| String uncPath = Path.Combine(cifsShareDetails.UncPath, Path.Combine(filePathRelativeToShare.Split('/'))); | |
| //uncPath = uncPath.Replace("/", "\\"); | |
| DirectoryInfo dir = new DirectoryInfo(uncPath); | |
| FileInfo[] vhdFiles = dir.GetFiles("*.vhd*"); | |
| if (vhdFiles.Length > 0) | |
| { | |
| FileInfo file = vhdFiles[0]; | |
| dest = file.FullName; | |
| } | |
| } | |
| s_logger.Info(CloudStackTypes.CopyCommand + ": copy " + Path.Combine(cifsShareDetails.UncPath, filePathRelativeToShare) + " to " + destFile); | |
| File.Copy(dest, destFile, true); | |
| } | |
| public static void GetShareDetails(string remoteUNC, out long capacity, out long available) | |
| { | |
| ulong freeBytesAvailable; | |
| ulong totalNumberOfBytes; | |
| ulong totalNumberOfFreeBytes; | |
| if (!GetDiskFreeSpaceEx(remoteUNC, out freeBytesAvailable, out totalNumberOfBytes, out totalNumberOfFreeBytes)) | |
| { | |
| throw new ArgumentException("Not able to retrieve the capcity details of the share " + remoteUNC); | |
| } | |
| available = freeBytesAvailable > 0 ? (long)freeBytesAvailable : 0; | |
| capacity = totalNumberOfBytes > 0 ? (long)totalNumberOfBytes : 0; | |
| } | |
| public static string CleanString(string stringToClean) | |
| { | |
| string cleanString = null; | |
| string regexQueryString = "(&|%26)?(password|accesskey|secretkey|Password)(=|%3D).*?(?=(%26|[&'\"]))"; | |
| string regexJson = "\"(password|accesskey|secretkey|Password)\":\\s?\".*?\",?"; | |
| cleanString = System.Text.RegularExpressions.Regex.Replace(stringToClean, regexQueryString, ""); | |
| cleanString = System.Text.RegularExpressions.Regex.Replace(cleanString, regexJson, ""); | |
| return cleanString; | |
| } | |
| public static void AddHeartBeatTask(string poolGuid, string poolPath, string hostPrivateIp) | |
| { | |
| string taskName = TASK_PREFIX + poolGuid; | |
| UriBuilder uri = new UriBuilder(Assembly.GetExecutingAssembly().CodeBase); | |
| string alocation = Uri.UnescapeDataString(uri.Path); | |
| string batchFileLocation = Path.Combine(Path.GetDirectoryName(alocation), BATCH_FILE); | |
| string hbFile = Path.Combine(poolPath, "hb-" + hostPrivateIp); | |
| ExecuteTask("schtasks.exe", "/Create /RU \"SYSTEM\" /SC MINUTE /MO 1 /TN " + taskName + " /F /TR \"" + batchFileLocation + " " + hbFile + "\""); | |
| } | |
| public static void RemoveHeartBeatTask(string poolGuid) | |
| { | |
| string taskName = TASK_PREFIX + poolGuid; | |
| ExecuteTask("schtasks.exe", "/Delete /TN " + taskName + " /F"); | |
| } | |
| public static void ExecuteTask(string command, string args) | |
| { | |
| ProcessStartInfo startInfo = new ProcessStartInfo(); | |
| startInfo.CreateNoWindow = false; | |
| startInfo.UseShellExecute = true; | |
| startInfo.FileName = command; | |
| startInfo.WindowStyle = ProcessWindowStyle.Hidden; | |
| startInfo.Arguments = args; | |
| try | |
| { | |
| using (Process exeProcess = Process.Start(startInfo)) | |
| { | |
| exeProcess.WaitForExit(); | |
| } | |
| } | |
| catch (Exception e) | |
| { | |
| s_logger.Error("Error occurred in deleting or adding a scheduled task " + e.Message); | |
| } | |
| } | |
| // from http://stackoverflow.com/a/2541569/939250 | |
| #region imports | |
| [DllImport("kernel32.dll", SetLastError = true, CharSet = CharSet.Auto)] | |
| private static extern bool GetDiskFreeSpaceEx(string lpDirectoryName, | |
| out ulong lpFreeBytesAvailable, | |
| out ulong lpTotalNumberOfBytes, | |
| out ulong lpTotalNumberOfFreeBytes); | |
| #endregion | |
| } | |
| } |