// 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"; /// /// Associate CloudStack object's content with a fully qualified type name. /// /// Fully qualified type name, e.g. "org.apache.cloudstack.storage.to.TemplateObjectTO" /// Object's data, can be an anonymous object, e.g. /// public static JObject CreateCloudStackObject(string objType, object objValue) { JToken objContent = JToken.FromObject(objValue); JProperty objTypeValuePairing = new JProperty(objType, objContent); return new JObject(objTypeValuePairing); } /// /// serialize dictonary to map json type /// /// Object's data, can be an anonymous object, e.g. /// 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; } /// /// Copy file on network share to local volume. /// /// /// 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 /// /// /// 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 } }