Files
DnsServer-TechnitiumSoftware/DnsServerCore/WebServiceClusterApi.cs

615 lines
30 KiB
C#

/*
Technitium DNS Server
Copyright (C) 2025 Shreyas Zare (shreyas@technitium.com)
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
using DnsServerCore.Auth;
using DnsServerCore.Cluster;
using Microsoft.AspNetCore.Http;
using System;
using System.Buffers.Text;
using System.Collections.Generic;
using System.Globalization;
using System.IO;
using System.Net;
using System.Net.NetworkInformation;
using System.Net.Sockets;
using System.Security.Cryptography.X509Certificates;
using System.Text.Json;
using System.Threading;
using System.Threading.Tasks;
namespace DnsServerCore
{
public partial class DnsWebService
{
sealed class WebServiceClusterApi
{
#region variables
readonly DnsWebService _dnsWebService;
#endregion
#region constructor
public WebServiceClusterApi(DnsWebService dnsWebService)
{
_dnsWebService = dnsWebService;
}
#endregion
#region private
private void WriteClusterState(Utf8JsonWriter jsonWriter, bool includeServerIpAddresses = false)
{
jsonWriter.WriteString("version", _dnsWebService.GetServerVersion());
jsonWriter.WriteString("dnsServerDomain", _dnsWebService._dnsServer.ServerDomain);
jsonWriter.WriteBoolean("clusterInitialized", _dnsWebService._clusterManager.ClusterInitialized);
if (_dnsWebService._clusterManager.ClusterInitialized)
{
jsonWriter.WriteString("clusterDomain", _dnsWebService._clusterManager.ClusterDomain);
jsonWriter.WriteNumber("heartbeatRefreshIntervalSeconds", _dnsWebService._clusterManager.HeartbeatRefreshIntervalSeconds);
jsonWriter.WriteNumber("heartbeatRetryIntervalSeconds", _dnsWebService._clusterManager.HeartBeatRetryIntervalSeconds);
jsonWriter.WriteNumber("configRefreshIntervalSeconds", _dnsWebService._clusterManager.ConfigRefreshIntervalSeconds);
jsonWriter.WriteNumber("configRetryIntervalSeconds", _dnsWebService._clusterManager.ConfigRetryIntervalSeconds);
WriteClusterNodes(jsonWriter);
}
if (includeServerIpAddresses)
{
jsonWriter.WriteStartArray("serverIpAddresses");
foreach (NetworkInterface networkInterface in NetworkInterface.GetAllNetworkInterfaces())
{
if (networkInterface.OperationalStatus != OperationalStatus.Up)
continue;
foreach (UnicastIPAddressInformation ip in networkInterface.GetIPProperties().UnicastAddresses)
{
if (IPAddress.IsLoopback(ip.Address))
continue;
switch (ip.Address.AddressFamily)
{
case AddressFamily.InterNetwork:
jsonWriter.WriteStringValue(ip.Address.ToString());
break;
case AddressFamily.InterNetworkV6:
if (ip.Address.IsIPv6LinkLocal || ip.Address.IsIPv6Teredo)
continue;
jsonWriter.WriteStringValue(ip.Address.ToString());
break;
}
}
}
jsonWriter.WriteEndArray();
}
}
internal void WriteClusterNodes(Utf8JsonWriter jsonWriter)
{
List<ClusterNode> sortedClusterNodes = [.. _dnsWebService._clusterManager.ClusterNodes.Values];
sortedClusterNodes.Sort();
jsonWriter.WriteStartArray("clusterNodes");
foreach (ClusterNode clusterNode in sortedClusterNodes)
{
jsonWriter.WriteStartObject();
jsonWriter.WriteNumber("id", clusterNode.Id);
jsonWriter.WriteString("name", clusterNode.Name);
jsonWriter.WriteString("url", clusterNode.Url.OriginalString);
jsonWriter.WriteStartArray("ipAddresses");
foreach (IPAddress ipAddress in clusterNode.IPAddresses)
jsonWriter.WriteStringValue(ipAddress.ToString());
jsonWriter.WriteEndArray();
jsonWriter.WriteString("type", clusterNode.Type.ToString());
jsonWriter.WriteString("state", clusterNode.State.ToString());
if (clusterNode.State == ClusterNodeState.Self)
{
jsonWriter.WriteString("upSince", clusterNode.UpSince);
if (clusterNode.Type == ClusterNodeType.Secondary)
{
if (_dnsWebService._clusterManager.ConfigLastSynced != default)
jsonWriter.WriteString("configLastSynced", _dnsWebService._clusterManager.ConfigLastSynced);
}
}
else
{
if (clusterNode.UpSince != default)
jsonWriter.WriteString("upSince", clusterNode.UpSince);
if (clusterNode.LastSeen != default)
jsonWriter.WriteString("lastSeen", clusterNode.LastSeen);
}
jsonWriter.WriteEndObject();
}
jsonWriter.WriteEndArray();
}
private void EnableWebServiceTlsWithSelfSignedCertificate()
{
_dnsWebService._webServiceEnableTls = true;
_dnsWebService._webServiceUseSelfSignedTlsCertificate = true;
_dnsWebService._webServiceTlsCertificatePath = null;
_dnsWebService._webServiceTlsCertificatePassword = null;
_dnsWebService.CheckAndLoadSelfSignedCertificate(false, true);
_dnsWebService.SaveConfigFile();
}
private void RestartWebService()
{
ThreadPool.QueueUserWorkItem(async delegate (object state)
{
try
{
await Task.Delay(2000); //wait for the current HTTP response to be delivered before restarting web server
_dnsWebService._log.Write("Attempting to restart web service.");
await _dnsWebService.StopWebServiceAsync();
await _dnsWebService.StartWebServiceAsync(false);
_dnsWebService._log.Write("Web service was restarted successfully.");
}
catch (Exception ex)
{
_dnsWebService._log.Write("Failed to restart web service.\r\n" + ex.ToString());
_dnsWebService._log.Write("Attempting to restart web service in HTTP only mode.");
try
{
await _dnsWebService.StopWebServiceAsync();
await _dnsWebService.StartWebServiceAsync(true);
}
catch (Exception ex2)
{
_dnsWebService._log.Write("Failed to restart web service in HTTP only mode.\r\n" + ex2.ToString());
}
}
});
}
#endregion
#region public
public void GetClusterState(HttpContext context)
{
User sessionUser = _dnsWebService.GetSessionUser(context);
if (!_dnsWebService._authManager.IsPermitted(PermissionSection.Administration, sessionUser, PermissionFlag.View))
throw new DnsWebServiceException("Access was denied.");
HttpRequest request = context.Request;
bool includeServerIpAddresses = request.GetQueryOrForm("includeServerIpAddresses", bool.Parse, false);
Utf8JsonWriter jsonWriter = context.GetCurrentJsonWriter();
WriteClusterState(jsonWriter, includeServerIpAddresses);
}
public void InitializeCluster(HttpContext context)
{
User sessionUser = _dnsWebService.GetSessionUser(context);
if (!_dnsWebService._authManager.IsPermitted(PermissionSection.Administration, sessionUser, PermissionFlag.Delete))
throw new DnsWebServiceException("Access was denied.");
HttpRequest request = context.Request;
string clusterDomain = request.GetQueryOrForm("clusterDomain").TrimEnd('.');
if (!request.TryGetQueryOrFormArray("primaryNodeIpAddresses", IPAddress.Parse, out IPAddress[] primaryNodeIpAddresses))
throw new DnsWebServiceException("Parameter 'primaryNodeIpAddresses' missing.");
bool restartWebService = false;
//enable TLS web service if not already enabled
if (!_dnsWebService.IsWebServiceTlsEnabled)
{
EnableWebServiceTlsWithSelfSignedCertificate();
restartWebService = true;
}
try
{
_dnsWebService._clusterManager.InitializeCluster(clusterDomain, primaryNodeIpAddresses, context.GetCurrentSession());
_dnsWebService._log.Write(context.GetRemoteEndPoint(_dnsWebService._webServiceRealIpHeader), "[" + sessionUser.Username + "] Cluster (" + _dnsWebService._clusterManager.ClusterDomain + ") was initialized successfully.");
Utf8JsonWriter jsonWriter = context.GetCurrentJsonWriter();
WriteClusterState(jsonWriter);
}
finally
{
//restart TLS web service to apply HTTPS changes
if (restartWebService)
RestartWebService();
}
}
public void DeleteCluster(HttpContext context)
{
User sessionUser = _dnsWebService.GetSessionUser(context);
if (!_dnsWebService._authManager.IsPermitted(PermissionSection.Administration, sessionUser, PermissionFlag.Delete))
throw new DnsWebServiceException("Access was denied.");
HttpRequest request = context.Request;
bool forceDelete = request.GetQueryOrForm("forceDelete", bool.Parse, false);
string clusterDomain = _dnsWebService._clusterManager.ClusterDomain;
_dnsWebService._clusterManager.DeleteCluster(forceDelete);
_dnsWebService._log.Write(context.GetRemoteEndPoint(_dnsWebService._webServiceRealIpHeader), "[" + sessionUser.Username + "] Cluster (" + clusterDomain + ") was deleted successfully.");
Utf8JsonWriter jsonWriter = context.GetCurrentJsonWriter();
WriteClusterState(jsonWriter);
}
public void JoinCluster(HttpContext context)
{
User sessionUser = _dnsWebService.GetSessionUser(context);
if (!_dnsWebService._authManager.IsPermitted(PermissionSection.Administration, sessionUser, PermissionFlag.Delete))
throw new DnsWebServiceException("Access was denied.");
HttpRequest request = context.Request;
int secondaryNodeId = request.GetQueryOrForm("secondaryNodeId", int.Parse);
Uri secondaryNodeUrl = new Uri(request.GetQueryOrForm("secondaryNodeUrl"));
if (!request.TryGetQueryOrFormArray("secondaryNodeIpAddresses", IPAddress.Parse, out IPAddress[] secondaryNodeIpAddresses))
throw new DnsWebServiceException("Parameter 'secondaryNodeIpAddresses' missing.");
X509Certificate2 secondaryNodeCertificate = X509CertificateLoader.LoadCertificate(Base64Url.DecodeFromChars(request.GetQueryOrForm("secondaryNodeCertificate")));
ClusterNode secondaryNode = _dnsWebService._clusterManager.JoinCluster(secondaryNodeId, secondaryNodeUrl, secondaryNodeIpAddresses, secondaryNodeCertificate);
_dnsWebService._log.Write(context.GetRemoteEndPoint(_dnsWebService._webServiceRealIpHeader), "[" + sessionUser.Username + "] Secondary node '" + secondaryNode.ToString() + "' joined the Cluster (" + _dnsWebService._clusterManager.ClusterDomain + ") successfully.");
Utf8JsonWriter jsonWriter = context.GetCurrentJsonWriter();
WriteClusterState(jsonWriter);
}
public async Task RemoveSecondaryNodeAsync(HttpContext context)
{
User sessionUser = _dnsWebService.GetSessionUser(context);
if (!_dnsWebService._authManager.IsPermitted(PermissionSection.Administration, sessionUser, PermissionFlag.Delete))
throw new DnsWebServiceException("Access was denied.");
HttpRequest request = context.Request;
int secondaryNodeId = request.GetQueryOrForm("secondaryNodeId", int.Parse);
ClusterNode secondaryNode = await _dnsWebService._clusterManager.AskSecondaryNodeToLeaveClusterAsync(secondaryNodeId);
_dnsWebService._log.Write(context.GetRemoteEndPoint(_dnsWebService._webServiceRealIpHeader), "[" + sessionUser.Username + "] Secondary node '" + secondaryNode.ToString() + "' was asked to leave the Cluster (" + _dnsWebService._clusterManager.ClusterDomain + ") successfully.");
Utf8JsonWriter jsonWriter = context.GetCurrentJsonWriter();
WriteClusterState(jsonWriter);
}
public void DeleteSecondaryNode(HttpContext context)
{
User sessionUser = _dnsWebService.GetSessionUser(context);
if (!_dnsWebService._authManager.IsPermitted(PermissionSection.Administration, sessionUser, PermissionFlag.Delete))
throw new DnsWebServiceException("Access was denied.");
HttpRequest request = context.Request;
int secondaryNodeId = request.GetQueryOrForm("secondaryNodeId", int.Parse);
ClusterNode secondaryNode = _dnsWebService._clusterManager.DeleteSecondaryNode(secondaryNodeId);
_dnsWebService._log.Write(context.GetRemoteEndPoint(_dnsWebService._webServiceRealIpHeader), "[" + sessionUser.Username + "] Secondary node '" + secondaryNode.ToString() + "' was deleted from the Cluster (" + _dnsWebService._clusterManager.ClusterDomain + ") successfully.");
Utf8JsonWriter jsonWriter = context.GetCurrentJsonWriter();
WriteClusterState(jsonWriter);
}
public void UpdateSecondaryNode(HttpContext context)
{
User sessionUser = _dnsWebService.GetSessionUser(context);
if (!_dnsWebService._authManager.IsPermitted(PermissionSection.Administration, sessionUser, PermissionFlag.Delete))
throw new DnsWebServiceException("Access was denied.");
HttpRequest request = context.Request;
int secondaryNodeId = request.GetQueryOrForm("secondaryNodeId", int.Parse);
Uri secondaryNodeUrl = new Uri(request.GetQueryOrForm("secondaryNodeUrl"));
if (!request.TryGetQueryOrFormArray("secondaryNodeIpAddresses", IPAddress.Parse, out IPAddress[] secondaryNodeIpAddresses))
throw new DnsWebServiceException("Parameter 'secondaryNodeIpAddresses' missing.");
X509Certificate2 secondaryNodeCertificate = X509CertificateLoader.LoadCertificate(Base64Url.DecodeFromChars(request.GetQueryOrForm("secondaryNodeCertificate")));
ClusterNode secondaryNode = _dnsWebService._clusterManager.UpdateSecondaryNode(secondaryNodeId, secondaryNodeUrl, secondaryNodeIpAddresses, secondaryNodeCertificate);
_dnsWebService._log.Write(context.GetRemoteEndPoint(_dnsWebService._webServiceRealIpHeader), "[" + sessionUser.Username + "] Secondary node '" + secondaryNode.ToString() + "' details were updated successfully.");
Utf8JsonWriter jsonWriter = context.GetCurrentJsonWriter();
WriteClusterState(jsonWriter);
}
public async Task TransferConfigAsync(HttpContext context)
{
User sessionUser = _dnsWebService.GetSessionUser(context);
if (!_dnsWebService._authManager.IsPermitted(PermissionSection.Administration, sessionUser, PermissionFlag.Delete))
throw new DnsWebServiceException("Access was denied.");
HttpRequest request = context.Request;
string ifModifiedSinceValue = request.Headers.IfModifiedSince;
string includeZonesValue = request.QueryOrForm("includeZones");
DateTime ifModifiedSince = string.IsNullOrEmpty(ifModifiedSinceValue) ? DateTime.UnixEpoch : DateTime.ParseExact(ifModifiedSinceValue, "R", CultureInfo.InvariantCulture);
string[] includeZones = string.IsNullOrEmpty(includeZonesValue) ? null : includeZonesValue.Split(',', StringSplitOptions.RemoveEmptyEntries | StringSplitOptions.TrimEntries);
string tmpFile = Path.GetTempFileName();
try
{
await using (FileStream configZipStream = new FileStream(tmpFile, FileMode.Create, FileAccess.ReadWrite))
{
//create config zip file
await _dnsWebService._clusterManager.TransferConfigAsync(configZipStream, ifModifiedSince, includeZones);
//send config zip file
configZipStream.Position = 0;
HttpResponse response = context.Response;
response.ContentType = "application/zip";
response.ContentLength = configZipStream.Length;
response.Headers.LastModified = DateTime.UtcNow.ToString("R");
response.Headers.Append("Content-Disposition", "attachment; filename=\"config.zip\"");
await using (Stream output = response.Body)
{
await configZipStream.CopyToAsync(output);
}
}
}
finally
{
try
{
File.Delete(tmpFile);
}
catch (Exception ex)
{
_dnsWebService._log.Write(ex);
}
}
_dnsWebService._log.Write(context.GetRemoteEndPoint(_dnsWebService._webServiceRealIpHeader), "[" + sessionUser.Username + "] Server configuration was transferred successfully.");
}
public void SetClusterOptions(HttpContext context)
{
User sessionUser = _dnsWebService.GetSessionUser(context);
if (!_dnsWebService._authManager.IsPermitted(PermissionSection.Administration, sessionUser, PermissionFlag.Modify))
throw new DnsWebServiceException("Access was denied.");
HttpRequest request = context.Request;
ushort heartbeatRefreshIntervalSeconds = request.GetQueryOrForm("heartbeatRefreshIntervalSeconds", ushort.Parse, _dnsWebService._clusterManager.HeartbeatRefreshIntervalSeconds);
ushort heartbeatRetryIntervalSeconds = request.GetQueryOrForm("heartbeatRetryIntervalSeconds", ushort.Parse, _dnsWebService._clusterManager.HeartBeatRetryIntervalSeconds);
ushort configRefreshIntervalSeconds = request.GetQueryOrForm("configRefreshIntervalSeconds", ushort.Parse, _dnsWebService._clusterManager.ConfigRefreshIntervalSeconds);
ushort configRetryIntervalSeconds = request.GetQueryOrForm("configRetryIntervalSeconds", ushort.Parse, _dnsWebService._clusterManager.ConfigRetryIntervalSeconds);
_dnsWebService._clusterManager.UpdateClusterOptions(heartbeatRefreshIntervalSeconds, heartbeatRetryIntervalSeconds, configRefreshIntervalSeconds, configRetryIntervalSeconds);
_dnsWebService._log.Write(context.GetRemoteEndPoint(_dnsWebService._webServiceRealIpHeader), "[" + sessionUser.Username + "] Cluster (" + _dnsWebService._clusterManager.ClusterDomain + ") options were updated successfully.");
Utf8JsonWriter jsonWriter = context.GetCurrentJsonWriter();
WriteClusterState(jsonWriter);
}
public async Task InitializeAndJoinClusterAsync(HttpContext context)
{
User sessionUser = _dnsWebService.GetSessionUser(context);
if (!_dnsWebService._authManager.IsPermitted(PermissionSection.Administration, sessionUser, PermissionFlag.Delete))
throw new DnsWebServiceException("Access was denied.");
HttpRequest request = context.Request;
if (!request.TryGetQueryOrFormArray("secondaryNodeIpAddresses", IPAddress.Parse, out IPAddress[] secondaryNodeIpAddresses))
throw new DnsWebServiceException("Parameter 'secondaryNodeIpAddresses' missing.");
Uri primaryNodeUrl = new Uri(request.GetQueryOrForm("primaryNodeUrl"));
IPAddress primaryNodeIpAddress = request.GetQueryOrForm("primaryNodeIpAddress", IPAddress.Parse, null);
string primaryNodeUsername = request.GetQueryOrForm("primaryNodeUsername");
string primaryNodePassword = request.GetQueryOrForm("primaryNodePassword");
string primaryNodeTotp = request.GetQueryOrForm("primaryNodeTotp", null);
bool ignoreCertificateErrors = request.GetQueryOrForm("ignoreCertificateErrors", bool.Parse, false);
bool restartWebService = false;
//enable TLS web service if not already enabled
if (!_dnsWebService.IsWebServiceTlsEnabled)
{
EnableWebServiceTlsWithSelfSignedCertificate();
restartWebService = true;
}
try
{
await _dnsWebService._clusterManager.InitializeAndJoinClusterAsync(secondaryNodeIpAddresses, primaryNodeUrl, primaryNodeUsername, primaryNodePassword, primaryNodeTotp, primaryNodeIpAddress is null ? null : [primaryNodeIpAddress], ignoreCertificateErrors);
_dnsWebService._log.Write(context.GetRemoteEndPoint(_dnsWebService._webServiceRealIpHeader), "[" + sessionUser.Username + "] Joined the Cluster (" + _dnsWebService._clusterManager.ClusterDomain + ") as a Secondary node successfully.");
Utf8JsonWriter jsonWriter = context.GetCurrentJsonWriter();
WriteClusterState(jsonWriter);
}
finally
{
//restart TLS web service to apply HTTPS changes
if (restartWebService)
RestartWebService();
}
}
public async Task LeaveClusterAsync(HttpContext context)
{
User sessionUser = _dnsWebService.GetSessionUser(context);
if (!_dnsWebService._authManager.IsPermitted(PermissionSection.Administration, sessionUser, PermissionFlag.Delete))
throw new DnsWebServiceException("Access was denied.");
HttpRequest request = context.Request;
bool forceLeave = request.GetQueryOrForm("forceLeave", bool.Parse, false);
string clusterDomain = _dnsWebService._clusterManager.ClusterDomain;
await _dnsWebService._clusterManager.LeaveClusterAsync(forceLeave);
_dnsWebService._log.Write(context.GetRemoteEndPoint(_dnsWebService._webServiceRealIpHeader), "[" + sessionUser.Username + "] Left the Cluster (" + clusterDomain + ") successfully.");
Utf8JsonWriter jsonWriter = context.GetCurrentJsonWriter();
WriteClusterState(jsonWriter);
}
public async Task ConfigUpdateNotificationAsync(HttpContext context)
{
User sessionUser = _dnsWebService.GetSessionUser(context);
if (!_dnsWebService._authManager.IsPermitted(PermissionSection.Administration, sessionUser, PermissionFlag.Delete))
throw new DnsWebServiceException("Access was denied.");
HttpRequest request = context.Request;
int primaryNodeId = request.GetQueryOrForm("primaryNodeId", int.Parse);
Uri primaryNodeUrl = new Uri(request.GetQueryOrForm("primaryNodeUrl"));
if (!request.TryGetQueryOrFormArray("primaryNodeIpAddresses", IPAddress.Parse, out IPAddress[] primaryNodeIpAddresses))
throw new DnsWebServiceException("Parameter 'primaryNodeIpAddresses' missing.");
//update primary node
ClusterNode primaryNode = await _dnsWebService._clusterManager.UpdatePrimaryNodeAsync(primaryNodeUrl, primaryNodeIpAddresses, primaryNodeId);
_dnsWebService._log.Write(context.GetRemoteEndPoint(_dnsWebService._webServiceRealIpHeader), "[" + sessionUser.Username + "] Notification for configuration update was received. Primary node '" + primaryNode.ToString() + "' details were updated successfully.");
}
public void ResyncCluster(HttpContext context)
{
User sessionUser = _dnsWebService.GetSessionUser(context);
if (!_dnsWebService._authManager.IsPermitted(PermissionSection.Administration, sessionUser, PermissionFlag.Modify))
throw new DnsWebServiceException("Access was denied.");
_dnsWebService._clusterManager.TriggerResyncForConfig();
_dnsWebService._log.Write(context.GetRemoteEndPoint(_dnsWebService._webServiceRealIpHeader), "[" + sessionUser.Username + "] Resync for configuration and Cluster Secondary zones was triggered successfully.");
}
public async Task UpdatePrimaryNodeAsync(HttpContext context)
{
User sessionUser = _dnsWebService.GetSessionUser(context);
if (!_dnsWebService._authManager.IsPermitted(PermissionSection.Administration, sessionUser, PermissionFlag.Modify))
throw new DnsWebServiceException("Access was denied.");
HttpRequest request = context.Request;
Uri primaryNodeUrl = new Uri(request.GetQueryOrForm("primaryNodeUrl"));
if (!request.TryGetQueryOrFormArray("primaryNodeIpAddresses", IPAddress.Parse, out IPAddress[] primaryNodeIpAddresses))
primaryNodeIpAddresses = null;
//update primary node
ClusterNode primaryNode = await _dnsWebService._clusterManager.UpdatePrimaryNodeAsync(primaryNodeUrl, primaryNodeIpAddresses);
_dnsWebService._log.Write(context.GetRemoteEndPoint(_dnsWebService._webServiceRealIpHeader), "[" + sessionUser.Username + "] Primary node '" + primaryNode.ToString() + "' details were updated successfully.");
Utf8JsonWriter jsonWriter = context.GetCurrentJsonWriter();
WriteClusterState(jsonWriter);
}
public async Task PromoteToPrimaryNodeAsync(HttpContext context)
{
User sessionUser = _dnsWebService.GetSessionUser(context);
if (!_dnsWebService._authManager.IsPermitted(PermissionSection.Administration, sessionUser, PermissionFlag.Delete))
throw new DnsWebServiceException("Access was denied.");
HttpRequest request = context.Request;
bool forceDeletePrimary = request.GetQueryOrForm("forceDeletePrimary", bool.Parse, false);
//promote to primary node
await _dnsWebService._clusterManager.PromoteToPrimaryNodeAsync(forceDeletePrimary);
_dnsWebService._log.Write(context.GetRemoteEndPoint(_dnsWebService._webServiceRealIpHeader), "[" + sessionUser.Username + "] This Secondary node was promoted to be a Primary node for the Cluster successfully.");
Utf8JsonWriter jsonWriter = context.GetCurrentJsonWriter();
WriteClusterState(jsonWriter);
}
public void UpdateSelfNodeIPAddress(HttpContext context)
{
User sessionUser = _dnsWebService.GetSessionUser(context);
if (!_dnsWebService._authManager.IsPermitted(PermissionSection.Administration, sessionUser, PermissionFlag.Modify))
throw new DnsWebServiceException("Access was denied.");
HttpRequest request = context.Request;
if (!request.TryGetQueryOrFormArray("ipAddresses", IPAddress.Parse, out IPAddress[] ipAddresses))
throw new DnsWebServiceException("Parameter 'ipAddresses' missing.");
//update self node IP address
ClusterNode selfNode = _dnsWebService._clusterManager.UpdateSelfNodeIPAddresses(ipAddresses);
_dnsWebService._log.Write(context.GetRemoteEndPoint(_dnsWebService._webServiceRealIpHeader), "[" + sessionUser.Username + "] " + selfNode.Type.ToString() + " node '" + selfNode.ToString() + "' IP address was updated successfully.");
Utf8JsonWriter jsonWriter = context.GetCurrentJsonWriter();
WriteClusterState(jsonWriter);
}
#endregion
}
}
}