441 lines
18 KiB
C#
441 lines
18 KiB
C#
using Step.CmsConnectManager.Events;
|
|
using Step.CmsConnectManager.Exceptions;
|
|
using System;
|
|
using System.Collections.Generic;
|
|
using System.Linq;
|
|
using System.Net;
|
|
using System.Text.RegularExpressions;
|
|
using System.Threading.Tasks;
|
|
using static Step.CmsConnectManager.CMSConnectConstants;
|
|
|
|
|
|
namespace Step.CmsConnectManager
|
|
{
|
|
public class GatewayController
|
|
{
|
|
private SSHAdapter SSHAdapter;
|
|
|
|
//---------------------------------------------------------------------------------------------------
|
|
#region Public_methods
|
|
|
|
/// <summary>
|
|
/// Simple constructor.
|
|
/// Create an instance with this configuration: hostname: localhost, username: root, password: root.
|
|
/// </summary>
|
|
public GatewayController()
|
|
{
|
|
SSHAdapter = new SSHAdapter("localhost", "root", "root");
|
|
}
|
|
|
|
|
|
/// <summary>
|
|
/// Advanced constructor.
|
|
/// Create an instance with the configuration passed by arguments
|
|
/// </summary>
|
|
/// <param name="hostname">Name (or IP-Address) of the gateway</param>
|
|
/// <param name="username">Username for Gateway Login</param>
|
|
/// <param name="password">Password for Gateway Login</param>
|
|
/// <exception cref="System.NullReferenceException">Thrown when one parameter is null</exception>
|
|
public GatewayController(string hostname, string username, string password)
|
|
{
|
|
SSHAdapter = new SSHAdapter(hostname, username, password);
|
|
}
|
|
|
|
/// <summary>
|
|
/// Write Proxy-Configuration on Gateway.
|
|
/// <para />See <see cref="GatewayProxyConfigurationBuilder"/> for generate the configuration.
|
|
/// </summary>
|
|
/// <param name="proxyConfiguration">Configuration of the proxy.</param>
|
|
/// <exception cref="GatewayException"></exception>
|
|
public void WriteGatewayProxyConfiguration(GatewayProxyConfiguration proxyConfiguration)
|
|
{
|
|
string Command = SSHAdapter.GenerateSshProxyCommand(proxyConfiguration);
|
|
SSHAdapter.SendSSHCommand(Command);
|
|
}
|
|
|
|
|
|
/// <summary>
|
|
/// Write Newtork-Configuration on Gateway.
|
|
/// <para />See <see cref="GatewayNetworkConfigurationBuilder"/> for generate the configuration.
|
|
/// </summary>
|
|
/// <param name="networkConfiguration">Configuration of the network.</param>
|
|
/// <exception cref="GatewayException"></exception>
|
|
public void WriteGatewayNetworkConfiguration(GatewayNetworkConfiguration networkConfiguration)
|
|
{
|
|
string NetworkCommand = SSHAdapter.GenerateSshNetworkCommand(networkConfiguration);
|
|
string DnsIpCommand = SSHAdapter.GenerateSshDnsCommand(networkConfiguration);
|
|
string DnsSuffixCommand = SSHAdapter.GenerateSshDnsSuffxCommand(networkConfiguration);
|
|
|
|
SSHAdapter.SendSSHCommand(new List<string>() { NetworkCommand, DnsIpCommand, DnsSuffixCommand });
|
|
}
|
|
|
|
|
|
/// <summary>
|
|
/// Read Newtork-Configuration saved on Gateway.
|
|
/// </summary>
|
|
/// <returns>See <see cref="GatewayNetworkConfiguration"/>
|
|
/// </returns>
|
|
/// <exception cref="GatewayException"></exception>
|
|
public GatewayNetworkConfiguration ReadGatewayNetworkConfiguration()
|
|
{
|
|
return ElaborateConfigFromSshNetworkCommand( SSHAdapter.SendSSHCommand(SSH_GET_NETWORK_COMMAND) );
|
|
}
|
|
|
|
|
|
/// <summary>
|
|
/// Read Proxy-Configuration saved on Gateway.
|
|
/// </summary>
|
|
/// <returns>See <see cref="GatewayProxyConfiguration"/>
|
|
/// </returns>
|
|
/// <exception cref="GatewayException"></exception>
|
|
public GatewayProxyConfiguration ReadGatewayProxyConfiguration()
|
|
{
|
|
return ElaborateConfigFromSshProxyCommand( SSHAdapter.SendSSHCommand(SSH_GET_PROXY_COMMAND));
|
|
}
|
|
|
|
|
|
/// <summary>
|
|
/// Test connection to SCM/CMS Server, on Gateway.
|
|
/// </summary>
|
|
/// <param name="timeout">Seconds timeout for the request</param>
|
|
/// <exception cref="GatewayException"></exception>
|
|
public GatewayConnectionStatus TestGatewayConnection(int timeout)
|
|
{
|
|
if (timeout < 0)
|
|
throw new ArgumentOutOfRangeException("Timeout must be > 0");
|
|
|
|
return ElaborateTestConnectionCommand(SSHAdapter.SendSSHCommand(SSH_TEST_CONNECTION_COMMAND + timeout));
|
|
}
|
|
|
|
|
|
/// <summary>
|
|
/// Reboot asynchronously the Gateway.
|
|
/// </summary>
|
|
/// <param name="delay">Serconds to delay before reboot</param>
|
|
/// <param name="handler">Handler Callback when the operation is finished or an error occours.
|
|
/// See <see cref="GatewayRebootEventHandlerArgs"/>
|
|
/// </param>
|
|
public void RebootGatewayAsync(int delay, EventHandler<GatewayRebootEventHandlerArgs> handler)
|
|
{
|
|
if (delay < 0)
|
|
throw new ArgumentOutOfRangeException("Delay must be > 0");
|
|
|
|
//Create the Action
|
|
Action<int, EventHandler<GatewayRebootEventHandlerArgs>> action = (int del, EventHandler<GatewayRebootEventHandlerArgs> hand) =>
|
|
{
|
|
GatewayRebootEventHandlerArgs ev = new GatewayRebootEventHandlerArgs();
|
|
try
|
|
{
|
|
SSHAdapter.SendSSHReboot(del);
|
|
}
|
|
catch (Exception e)
|
|
{
|
|
ev.ErrorStatus = true;
|
|
ev.ErrorMessage = e.Message;
|
|
}
|
|
|
|
hand(this, ev);
|
|
};
|
|
|
|
// Create a task and not start it.
|
|
Task t = new Task (() => action(delay, handler));
|
|
t.Start();
|
|
}
|
|
|
|
|
|
/// <summary>
|
|
/// Reboot and wait a new session of the Gateway.
|
|
/// </summary>
|
|
/// <param name="delay">Seconds to delay before reboot</param>
|
|
/// <exception cref="GatewayException"></exception>
|
|
public void RebootGateway(int delay)
|
|
{
|
|
if (delay < 0)
|
|
throw new ArgumentOutOfRangeException("Delay must be > 0");
|
|
|
|
// Send Command
|
|
SSHAdapter.SendSSHReboot(delay);
|
|
}
|
|
|
|
#endregion
|
|
|
|
//---------------------------------------------------------------------------------------------------
|
|
#region SSH_commands_preparations_sub_methods
|
|
|
|
|
|
#endregion
|
|
|
|
//---------------------------------------------------------------------------------------------------
|
|
#region elaborate_SSH_values_sub_methods
|
|
|
|
private GatewayNetworkConfiguration ElaborateConfigFromSshNetworkCommand(List<string> lines)
|
|
{
|
|
GatewayNetworkConfiguration configuration = new GatewayNetworkConfiguration();
|
|
foreach (string line in lines)
|
|
{
|
|
if (line.StartsWith(IP_ADDR_LABEL))
|
|
DecodeNetworkIPAddress(line.Remove(0, IP_ADDR_LABEL.Length).Trim(), ref configuration);
|
|
else if (line.StartsWith(GATEWAY_LABEL))
|
|
DecodeNetworkDefGateway(line.Remove(0, GATEWAY_LABEL.Length).Trim(), ref configuration);
|
|
else if (line.StartsWith(DNSIP_LABEL))
|
|
DecodeNetworkDnsIp(line.Remove(0, DNSIP_LABEL.Length).Trim(), ref configuration);
|
|
else if (line.StartsWith(DNSPREFIX_LABEL))
|
|
DecodeNetworkDnsPrefix(line.Remove(0, DNSPREFIX_LABEL.Length).Trim(), ref configuration);
|
|
}
|
|
|
|
return configuration;
|
|
}
|
|
|
|
private GatewayProxyConfiguration ElaborateConfigFromSshProxyCommand(List<string> lines)
|
|
{
|
|
GatewayProxyConfiguration configuration = new GatewayProxyConfiguration();
|
|
foreach (string line in lines)
|
|
{
|
|
if (line.StartsWith(PROXY_ADDR_LABEL))
|
|
DecodeProxyAddress(line.Remove(0, PROXY_ADDR_LABEL.Length).Trim(), ref configuration);
|
|
else if (line.StartsWith(NO_PROXY_LABEL))
|
|
DecodeNoProxyUrls(line.Remove(0, NO_PROXY_LABEL.Length).Trim(), ref configuration);
|
|
}
|
|
|
|
return configuration;
|
|
}
|
|
|
|
private GatewayConnectionStatus ElaborateTestConnectionCommand(List<string> lines)
|
|
{
|
|
GatewayConnectionStatus status = new GatewayConnectionStatus();
|
|
foreach (string line in lines)
|
|
{
|
|
if (!string.IsNullOrWhiteSpace(line))
|
|
DecodeConnectionStatus(line.Trim(), ref status);
|
|
}
|
|
|
|
return status;
|
|
}
|
|
|
|
#endregion
|
|
|
|
//---------------------------------------------------------------------------------------------------
|
|
#region decode_SSH_values_sub_methods
|
|
|
|
private void DecodeNetworkIPAddress(string stringValue, ref GatewayNetworkConfiguration configuration)
|
|
{
|
|
//Check if has DHCP
|
|
if (stringValue == "DHCP")
|
|
configuration.hasDhcp = true;
|
|
else
|
|
{
|
|
configuration.hasDhcp = false;
|
|
|
|
//Check if has / for netmask
|
|
if (!stringValue.Contains('/'))
|
|
throw new GatewayException("Internal Gateway Error during read (bad format): " + IP_ADDR_LABEL + stringValue);
|
|
|
|
string [] tempAddr = stringValue.Split('/');
|
|
//Check if has lenght == 2
|
|
if (tempAddr.Length != 2)
|
|
throw new GatewayException("Internal Gateway Error during read (bad format): " + IP_ADDR_LABEL + stringValue);
|
|
|
|
|
|
//Set the IPAddress / Netmask
|
|
IPAddress tempIp;
|
|
if (!EvaluateIPV4(tempAddr[0], out tempIp))
|
|
throw new GatewayException("Internal Gateway Error during read (bad format): " + IP_ADDR_LABEL + stringValue);
|
|
|
|
IPNetwork tempIpNetw;
|
|
if (!IPNetwork.TryParse(stringValue, out tempIpNetw))
|
|
throw new GatewayException("Internal Gateway Error during read (bad format): " + IP_ADDR_LABEL + stringValue);
|
|
|
|
|
|
configuration.ipAddress = tempIp;
|
|
configuration.netMaskAddress = tempIpNetw.Netmask;
|
|
}
|
|
}
|
|
|
|
|
|
private void DecodeNetworkDefGateway(string stringValue, ref GatewayNetworkConfiguration configuration)
|
|
{
|
|
//check if is defined
|
|
if (stringValue == UNDEF_VALUE)
|
|
configuration.defaultGatewayAddress = null;
|
|
else
|
|
{
|
|
if (!EvaluateIPV4(stringValue, out IPAddress tempIp))
|
|
throw new GatewayException("Internal Gateway Error during read (bad format): " + GATEWAY_LABEL + stringValue);
|
|
configuration.defaultGatewayAddress = tempIp;
|
|
}
|
|
}
|
|
|
|
|
|
private void DecodeNetworkDnsIp(string stringValue, ref GatewayNetworkConfiguration configuration)
|
|
{
|
|
//check if is defined
|
|
if (stringValue == UNDEF_VALUE)
|
|
configuration.dnsAddresses = null;
|
|
else
|
|
{
|
|
string[] tempStr = stringValue.Split(' ');
|
|
if (tempStr.Length == 0)
|
|
configuration.dnsAddresses = null;
|
|
else
|
|
{
|
|
IPAddress tempIp;
|
|
List<IPAddress> tempDns = new List<IPAddress>();
|
|
foreach (string str in tempStr)
|
|
{
|
|
if (string.IsNullOrEmpty(str))
|
|
continue;
|
|
if (!EvaluateIPV4(str, out tempIp))
|
|
throw new GatewayException("Internal Gateway Error during read (bad format): " + DNSIP_LABEL + stringValue);
|
|
tempDns.Add(tempIp);
|
|
}
|
|
configuration.dnsAddresses = tempDns;
|
|
}
|
|
|
|
}
|
|
}
|
|
|
|
|
|
private void DecodeNetworkDnsPrefix(string stringValue, ref GatewayNetworkConfiguration configuration)
|
|
{
|
|
// Check if is defined
|
|
if (stringValue == UNDEF_VALUE)
|
|
configuration.dnsPrefixes = null;
|
|
else
|
|
{
|
|
string[] tempStr = stringValue.Split(' ');
|
|
if (tempStr.Length == 0)
|
|
configuration.dnsPrefixes = null;
|
|
else
|
|
configuration.dnsPrefixes = tempStr.Where(X=> !string.IsNullOrEmpty(X)).ToList();
|
|
}
|
|
}
|
|
|
|
|
|
private void DecodeProxyAddress(string stringValue, ref GatewayProxyConfiguration configuration)
|
|
{
|
|
// Check if is defined
|
|
if (stringValue == UNDEF_VALUE)
|
|
configuration.hasProxy = false;
|
|
else
|
|
{
|
|
configuration.hasProxy = true;
|
|
|
|
/* Must be one of these:
|
|
* - Address:Port
|
|
* - User:Password@Address:Port
|
|
*/
|
|
if (!stringValue.Contains("@"))
|
|
{
|
|
// Set username & password
|
|
configuration.username = null;
|
|
configuration.password = null;
|
|
|
|
// Check if has :
|
|
if (!stringValue.Contains(':'))
|
|
throw new GatewayException("Internal Gateway Error during read (bad format): " + PROXY_ADDR_LABEL + stringValue);
|
|
string[] tempAddr = stringValue.Split(':');
|
|
|
|
// Check if has lenght == 2
|
|
if (tempAddr.Length != 2)
|
|
throw new GatewayException("Internal Gateway Error during read (bad format): " + PROXY_ADDR_LABEL + stringValue);
|
|
|
|
// Set the address
|
|
configuration.address = tempAddr[0];
|
|
|
|
// Set the port
|
|
if (!uint.TryParse(tempAddr[1], out uint tempPort))
|
|
throw new GatewayException("Internal Gateway Error during read (bad format): " + PROXY_ADDR_LABEL + stringValue);
|
|
configuration.port = tempPort;
|
|
|
|
}
|
|
else
|
|
{
|
|
string[] splitted = stringValue.Split('@');
|
|
|
|
//Check if has lenght == 2
|
|
if (splitted.Length != 2)
|
|
throw new GatewayException("Internal Gateway Error during read (bad format): " + PROXY_ADDR_LABEL + stringValue);
|
|
|
|
//Check if has :
|
|
if (!splitted[0].Contains(':'))
|
|
throw new GatewayException("Internal Gateway Error during read (bad format): " + PROXY_ADDR_LABEL + stringValue);
|
|
if (!splitted[1].Contains(':'))
|
|
throw new GatewayException("Internal Gateway Error during read (bad format): " + PROXY_ADDR_LABEL + stringValue);
|
|
|
|
string[] tempLogin = splitted[0].Split(':');
|
|
string[] tempAddr = splitted[1].Split(':');
|
|
|
|
//Check if has lenght == 2
|
|
if (tempLogin.Length != 2)
|
|
throw new GatewayException("Internal Gateway Error during read (bad format): " + PROXY_ADDR_LABEL + stringValue);
|
|
if (tempAddr.Length != 2)
|
|
throw new GatewayException("Internal Gateway Error during read (bad format): " + PROXY_ADDR_LABEL + stringValue);
|
|
|
|
// Set the username
|
|
configuration.username = tempLogin[0];
|
|
// Set the password
|
|
configuration.password = tempLogin[1];
|
|
// Set the address
|
|
configuration.address = tempAddr[0];
|
|
|
|
// Set the port
|
|
if (!uint.TryParse(tempAddr[1], out uint tempPort))
|
|
throw new GatewayException("Internal Gateway Error during read (bad format): " + PROXY_ADDR_LABEL + stringValue);
|
|
configuration.port = tempPort;
|
|
}
|
|
|
|
}
|
|
}
|
|
|
|
|
|
private void DecodeNoProxyUrls(string stringValue, ref GatewayProxyConfiguration configuration)
|
|
{
|
|
// Check if is defined
|
|
if (stringValue == UNDEF_VALUE)
|
|
configuration.noproxyAddresses = null;
|
|
else
|
|
{
|
|
string[] tempStr = stringValue.Trim('"').Split(',');
|
|
|
|
for (int i=0;i<tempStr.Length;i++)
|
|
tempStr[i] = tempStr[i].Trim();
|
|
|
|
if (tempStr.Length == 0)
|
|
configuration.noproxyAddresses = null;
|
|
else
|
|
configuration.noproxyAddresses = tempStr.ToList();
|
|
}
|
|
}
|
|
|
|
|
|
private void DecodeConnectionStatus(string stringValue, ref GatewayConnectionStatus status)
|
|
{
|
|
if (stringValue == CONNECTION_OK_VALUE)
|
|
status = GatewayConnectionStatus.OK;
|
|
else if (stringValue == CONNECTION_NOWEB_VALUE)
|
|
status = GatewayConnectionStatus.WEB_ERROR;
|
|
else if (stringValue == CONNECTION_NOPORT_VALUE)
|
|
status = GatewayConnectionStatus.PORT_ERROR;
|
|
else
|
|
throw new GatewayException("Internal Gateway Error during Connection-Test (bad format): " + stringValue);
|
|
}
|
|
|
|
|
|
private bool EvaluateIPV4(string stringValue,out IPAddress address)
|
|
{
|
|
Regex rgx = new Regex(@"^((25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.){3}(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)$");
|
|
|
|
if (rgx.IsMatch(stringValue))
|
|
{
|
|
IPAddress.TryParse(stringValue, out address);
|
|
return true;
|
|
}
|
|
|
|
address = new IPAddress(0);
|
|
return false;
|
|
}
|
|
|
|
#endregion
|
|
}
|
|
}
|