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" />
|
<None Include="packages.config" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
|
<None Include="heartbeat.bat">
|
||||||
|
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
|
||||||
|
</None>
|
||||||
|
</ItemGroup>
|
||||||
|
<ItemGroup>
|
||||||
<ProjectReference Include="..\WmiWrappers\WmiWrappers.csproj">
|
<ProjectReference Include="..\WmiWrappers\WmiWrappers.csproj">
|
||||||
<Project>{db824727-bdc3-437c-a364-7a811d8a160f}</Project>
|
<Project>{db824727-bdc3-437c-a364-7a811d8a160f}</Project>
|
||||||
<Name>WmiWrappers</Name>
|
<Name>WmiWrappers</Name>
|
||||||
|
|||||||
@ -107,6 +107,21 @@ namespace HypervResource
|
|||||||
config.Save(ConfigurationSaveMode.Modified);
|
config.Save(ConfigurationSaveMode.Modified);
|
||||||
ConfigurationManager.RefreshSection("appSettings");
|
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>
|
/// <summary>
|
||||||
@ -775,16 +790,67 @@ namespace HypervResource
|
|||||||
using (log4net.NDC.Push(Guid.NewGuid().ToString()))
|
using (log4net.NDC.Push(Guid.NewGuid().ToString()))
|
||||||
{
|
{
|
||||||
logger.Info(CloudStackTypes.CheckOnHostCommand + Utils.CleanString(cmd.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
|
object ansContent = new
|
||||||
{
|
{
|
||||||
result = true,
|
result = result,
|
||||||
details = "resource is alive",
|
details = details,
|
||||||
contextMap = contextMap
|
contextMap = contextMap
|
||||||
};
|
};
|
||||||
return ReturnCloudStackTypedJArray(ansContent, CloudStackTypes.CheckOnHostAnswer);
|
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
|
// POST api/HypervResource/CheckSshCommand
|
||||||
// TODO: create test
|
// TODO: create test
|
||||||
[HttpPost]
|
[HttpPost]
|
||||||
@ -956,6 +1022,27 @@ namespace HypervResource
|
|||||||
contextMap = contextMap
|
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);
|
return ReturnCloudStackTypedJArray(ansContent, CloudStackTypes.ModifyStoragePoolAnswer);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -2151,6 +2238,7 @@ namespace HypervResource
|
|||||||
|
|
||||||
// Insert networking details
|
// Insert networking details
|
||||||
string privateIpAddress = strtRouteCmd.privateIpAddress;
|
string privateIpAddress = strtRouteCmd.privateIpAddress;
|
||||||
|
config.PrivateIpAddress = privateIpAddress;
|
||||||
string subnet;
|
string subnet;
|
||||||
System.Net.NetworkInformation.NetworkInterface privateNic = GetNicInfoFromIpAddress(privateIpAddress, out subnet);
|
System.Net.NetworkInformation.NetworkInterface privateNic = GetNicInfoFromIpAddress(privateIpAddress, out subnet);
|
||||||
strtRouteCmd.privateIpAddress = privateIpAddress;
|
strtRouteCmd.privateIpAddress = privateIpAddress;
|
||||||
|
|||||||
@ -24,6 +24,8 @@ using System.Runtime.InteropServices;
|
|||||||
using System.Security.Principal;
|
using System.Security.Principal;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
|
using System.Diagnostics;
|
||||||
|
using System.Reflection;
|
||||||
|
|
||||||
namespace HypervResource
|
namespace HypervResource
|
||||||
{
|
{
|
||||||
@ -31,6 +33,9 @@ namespace HypervResource
|
|||||||
{
|
{
|
||||||
private static ILog s_logger = LogManager.GetLogger(typeof(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>
|
/// <summary>
|
||||||
/// Associate CloudStack object's content with a fully qualified type name.
|
/// Associate CloudStack object's content with a fully qualified type name.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@ -174,6 +179,44 @@ namespace HypervResource
|
|||||||
return cleanString;
|
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
|
// from http://stackoverflow.com/a/2541569/939250
|
||||||
#region imports
|
#region imports
|
||||||
[DllImport("advapi32.dll", SetLastError = true)]
|
[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