mirror of
https://github.com/apache/cloudstack.git
synced 2025-10-26 08:42:29 +01:00
CLOUDSTACK-6401: [hyper-v] fixed correct host state, if host is up and hyper-v agent is down then the host state will be shown as up(actual host state) in cloudstack
This commit is contained in:
parent
3ec7497e1e
commit
55f53e13e8
@ -87,6 +87,11 @@
|
||||
<None Include="packages.config" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<None Include="heartbeat.bat">
|
||||
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
|
||||
</None>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\WmiWrappers\WmiWrappers.csproj">
|
||||
<Project>{db824727-bdc3-437c-a364-7a811d8a160f}</Project>
|
||||
<Name>WmiWrappers</Name>
|
||||
|
||||
@ -107,6 +107,21 @@ namespace HypervResource
|
||||
config.Save(ConfigurationSaveMode.Modified);
|
||||
ConfigurationManager.RefreshSection("appSettings");
|
||||
}
|
||||
|
||||
public List<string> getAllPrimaryStorages()
|
||||
{
|
||||
List<string> poolPaths = new List<string>();
|
||||
Configuration config = ConfigurationManager.OpenExeConfiguration(ConfigurationUserLevel.None);
|
||||
KeyValueConfigurationCollection settings = config.AppSettings.Settings;
|
||||
foreach (string key in settings.AllKeys)
|
||||
{
|
||||
if (key.Contains("primary_storage_"))
|
||||
{
|
||||
poolPaths.Add(settings[key].Value);
|
||||
}
|
||||
}
|
||||
return poolPaths;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@ -775,16 +790,67 @@ namespace HypervResource
|
||||
using (log4net.NDC.Push(Guid.NewGuid().ToString()))
|
||||
{
|
||||
logger.Info(CloudStackTypes.CheckOnHostCommand + Utils.CleanString(cmd.ToString()));
|
||||
string details = "host is not alive";
|
||||
bool result = true;
|
||||
try
|
||||
{
|
||||
foreach (string poolPath in config.getAllPrimaryStorages())
|
||||
{
|
||||
if (IsHostAlive(poolPath, (string)cmd.host.privateNetwork.ip))
|
||||
{
|
||||
result = false;
|
||||
details = "host is alive";
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
logger.Error("Error Occurred in " + CloudStackTypes.CheckOnHostCommand + " : " + e.Message);
|
||||
}
|
||||
|
||||
object ansContent = new
|
||||
{
|
||||
result = true,
|
||||
details = "resource is alive",
|
||||
result = result,
|
||||
details = details,
|
||||
contextMap = contextMap
|
||||
};
|
||||
return ReturnCloudStackTypedJArray(ansContent, CloudStackTypes.CheckOnHostAnswer);
|
||||
}
|
||||
}
|
||||
|
||||
private bool IsHostAlive(string poolPath, string privateIp)
|
||||
{
|
||||
bool hostAlive = false;
|
||||
try
|
||||
{
|
||||
string hbFile = Path.Combine(poolPath, "hb-" + privateIp);
|
||||
FileInfo file = new FileInfo(hbFile);
|
||||
using (StreamReader sr = file.OpenText())
|
||||
{
|
||||
string epoch = sr.ReadLine();
|
||||
string[] dateTime = epoch.Split('@');
|
||||
string[] date = dateTime[0].Split('-');
|
||||
string[] time = dateTime[1].Split(':');
|
||||
DateTime epochTime = new DateTime(Convert.ToInt32(date[0]), Convert.ToInt32(date[1]), Convert.ToInt32(date[2]), Convert.ToInt32(time[0]),
|
||||
Convert.ToInt32(time[1]), Convert.ToInt32(time[2]), DateTimeKind.Utc);
|
||||
DateTime currentTime = DateTime.UtcNow;
|
||||
DateTime ThreeMinuteLaterEpoch = epochTime.AddMinutes(3);
|
||||
if (currentTime.CompareTo(ThreeMinuteLaterEpoch) < 0)
|
||||
{
|
||||
hostAlive = true;
|
||||
}
|
||||
sr.Close();
|
||||
}
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
logger.Info("Exception occurred in verifying host " + e.Message);
|
||||
}
|
||||
|
||||
return hostAlive;
|
||||
}
|
||||
|
||||
// POST api/HypervResource/CheckSshCommand
|
||||
// TODO: create test
|
||||
[HttpPost]
|
||||
@ -956,6 +1022,27 @@ namespace HypervResource
|
||||
contextMap = contextMap
|
||||
};
|
||||
|
||||
if (result)
|
||||
{
|
||||
try
|
||||
{
|
||||
if ((bool)cmd.add)
|
||||
{
|
||||
logger.Info("Adding HeartBeat Task to task scheduler for pool " + (string)cmd.pool.uuid);
|
||||
Utils.AddHeartBeatTask((string)cmd.pool.uuid, hostPath, config.PrivateIpAddress);
|
||||
}
|
||||
else
|
||||
{
|
||||
logger.Info("Deleting HeartBeat Task from task scheduler for pool " + (string)cmd.pool.uuid);
|
||||
Utils.RemoveHeartBeatTask(cmd.pool.uuid);
|
||||
}
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
logger.Error("Error occurred in adding/delete HeartBeat Task to/from Task Scheduler : " + e.Message);
|
||||
}
|
||||
}
|
||||
|
||||
return ReturnCloudStackTypedJArray(ansContent, CloudStackTypes.ModifyStoragePoolAnswer);
|
||||
}
|
||||
}
|
||||
@ -2151,6 +2238,7 @@ namespace HypervResource
|
||||
|
||||
// Insert networking details
|
||||
string privateIpAddress = strtRouteCmd.privateIpAddress;
|
||||
config.PrivateIpAddress = privateIpAddress;
|
||||
string subnet;
|
||||
System.Net.NetworkInformation.NetworkInterface privateNic = GetNicInfoFromIpAddress(privateIpAddress, out subnet);
|
||||
strtRouteCmd.privateIpAddress = privateIpAddress;
|
||||
|
||||
@ -24,6 +24,8 @@ using System.Runtime.InteropServices;
|
||||
using System.Security.Principal;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using System.Diagnostics;
|
||||
using System.Reflection;
|
||||
|
||||
namespace HypervResource
|
||||
{
|
||||
@ -31,6 +33,9 @@ namespace HypervResource
|
||||
{
|
||||
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>
|
||||
@ -174,6 +179,44 @@ namespace HypervResource
|
||||
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("advapi32.dll", SetLastError = true)]
|
||||
|
||||
@ -0,0 +1,23 @@
|
||||
@REM Licensed to the Apache Software Foundation (ASF) under one
|
||||
@REM or more contributor license agreements. See the NOTICE file
|
||||
@REM distributed with this work for additional information
|
||||
@REM regarding copyright ownership. The ASF licenses this file
|
||||
@REM to you under the Apache License, Version 2.0 (the
|
||||
@REM "License"); you may not use this file except in compliance
|
||||
@REM with the License. You may obtain a copy of the License at
|
||||
@REM
|
||||
@REM http://www.apache.org/licenses/LICENSE-2.0
|
||||
@REM
|
||||
@REM Unless required by applicable law or agreed to in writing,
|
||||
@REM software distributed under the License is distributed on an
|
||||
@REM "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
@REM KIND, either express or implied. See the License for the
|
||||
@REM specific language governing permissions and limitations
|
||||
@REM under the License.
|
||||
@REM
|
||||
@echo off
|
||||
@REM This script is based on:
|
||||
@REM http://stackoverflow.com/questions/9871499/how-to-get-utc-time-with-windows-batch-file
|
||||
|
||||
for /f %%x in ('wmic path win32_utctime get /format:list ^| findstr "="') do set %%x
|
||||
echo %Year%-%Month%-%Day%@%Hour%:%Minute%:%Second%>%1
|
||||
Loading…
x
Reference in New Issue
Block a user