mirror of
https://github.com/ckaczor/sqltoolsservice.git
synced 2026-01-26 17:24:21 -05:00
Create remote file browser service (#448)
* code refactoring * Add filebrowser service and tests * change dataset reference * Address pr comments * add more tests * address pr comments * address pr comments and added more tests * minor change * minor fix * Fix test break and add dataset result check
This commit is contained in:
@@ -0,0 +1,162 @@
|
||||
//
|
||||
// Copyright (c) Microsoft. All rights reserved.
|
||||
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
|
||||
//
|
||||
|
||||
using System;
|
||||
using System.Data;
|
||||
using System.Data.Common;
|
||||
using System.Data.SqlClient;
|
||||
using System.Globalization;
|
||||
using System.IO;
|
||||
using Microsoft.SqlServer.Management.Sdk.Sfc;
|
||||
using Microsoft.SqlServer.Management.Smo;
|
||||
using Microsoft.SqlTools.ServiceLayer.Connection;
|
||||
using Microsoft.SqlTools.ServiceLayer.Connection.ReliableConnection;
|
||||
using Microsoft.SqlTools.ServiceLayer.FileBrowser;
|
||||
|
||||
namespace Microsoft.SqlTools.ServiceLayer.DisasterRecovery
|
||||
{
|
||||
/// <summary>
|
||||
/// Validate selected file paths for backup/restore operations
|
||||
/// </summary>
|
||||
public static class DisasterRecoveryFileValidator
|
||||
{
|
||||
internal const string LocalSqlServer = "(local)";
|
||||
internal const string LocalMachineName = ".";
|
||||
|
||||
public static bool ValidatePaths(FileBrowserValidateEventArgs args, out string errorMessage)
|
||||
{
|
||||
errorMessage = string.Empty;
|
||||
bool result = true;
|
||||
SqlConnection connection = null;
|
||||
|
||||
if (args != null)
|
||||
{
|
||||
ConnectionInfo connInfo;
|
||||
ConnectionService.Instance.TryFindConnection(args.OwnerUri, out connInfo);
|
||||
if (connInfo != null)
|
||||
{
|
||||
DbConnection dbConnection = null;
|
||||
connInfo.TryGetConnection(Connection.ConnectionType.Default, out dbConnection);
|
||||
if (dbConnection != null)
|
||||
{
|
||||
connection = ReliableConnectionHelper.GetAsSqlConnection(dbConnection);
|
||||
}
|
||||
}
|
||||
|
||||
if (connection != null)
|
||||
{
|
||||
bool isLocal = false;
|
||||
if (string.Compare(GetMachineName(connection.DataSource), Environment.MachineName, StringComparison.OrdinalIgnoreCase) == 0)
|
||||
{
|
||||
isLocal = true;
|
||||
}
|
||||
|
||||
foreach (string filePath in args.FilePaths)
|
||||
{
|
||||
bool isFolder;
|
||||
bool existing = IsPathExisting(connection, filePath, out isFolder);
|
||||
|
||||
if (existing)
|
||||
{
|
||||
if (isFolder)
|
||||
{
|
||||
errorMessage = string.Format(SR.BackupPathIsFolderError, filePath);
|
||||
result = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// If the file path doesn't exist, check if the folder exists
|
||||
string folderPath = PathWrapper.GetDirectoryName(filePath);
|
||||
if (isLocal)
|
||||
{
|
||||
if (!string.IsNullOrEmpty(folderPath) && !Directory.Exists(folderPath))
|
||||
{
|
||||
errorMessage = string.Format(SR.InvalidBackupPathError, folderPath);
|
||||
result = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
bool isFolderOnRemote;
|
||||
bool existsOnRemote = IsPathExisting(connection, folderPath, out isFolderOnRemote);
|
||||
if (!existsOnRemote)
|
||||
{
|
||||
errorMessage = string.Format(SR.InvalidBackupPathError, folderPath);
|
||||
result = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
result = false;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
result = false;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
#region private methods
|
||||
|
||||
internal static bool IsPathExisting(SqlConnection connection, string path, out bool isFolder)
|
||||
{
|
||||
Request req = new Request
|
||||
{
|
||||
Urn = "Server/File[@FullName='" + Urn.EscapeString(path) + "']",
|
||||
Fields = new[] { "IsFile" }
|
||||
};
|
||||
|
||||
Enumerator en = new Enumerator();
|
||||
bool isExisting = false;
|
||||
isFolder = false;
|
||||
|
||||
using (DataSet ds = en.Process(connection, req))
|
||||
{
|
||||
if (FileBrowserBase.IsValidDataSet(ds))
|
||||
{
|
||||
isFolder = !(Convert.ToBoolean(ds.Tables[0].Rows[0]["IsFile"], CultureInfo.InvariantCulture));
|
||||
isExisting = true;
|
||||
}
|
||||
}
|
||||
|
||||
return isExisting;
|
||||
}
|
||||
|
||||
internal static string GetMachineName(string sqlServerName)
|
||||
{
|
||||
string machineName = string.Empty;
|
||||
if (sqlServerName != null)
|
||||
{
|
||||
string serverName = sqlServerName.ToLowerInvariant().Trim();
|
||||
if ((serverName == LocalSqlServer) || (serverName == LocalMachineName))
|
||||
{
|
||||
machineName = System.Environment.MachineName;
|
||||
}
|
||||
else
|
||||
{
|
||||
machineName = sqlServerName;
|
||||
if (sqlServerName.Trim().Length != 0)
|
||||
{
|
||||
// [0] = machine, [1] = instance
|
||||
return sqlServerName.Split('\\')[0];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return machineName;
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
@@ -9,12 +9,11 @@ using Microsoft.SqlTools.Hosting.Protocol;
|
||||
using Microsoft.SqlTools.ServiceLayer.Admin;
|
||||
using Microsoft.SqlTools.ServiceLayer.Admin.Contracts;
|
||||
using Microsoft.SqlTools.ServiceLayer.Connection;
|
||||
using Microsoft.SqlTools.ServiceLayer.DisasterRecovery.Contracts;
|
||||
using Microsoft.SqlTools.ServiceLayer.TaskServices;
|
||||
using System.Threading;
|
||||
using Microsoft.SqlTools.ServiceLayer.DisasterRecovery.RestoreOperation;
|
||||
using System.Globalization;
|
||||
using Microsoft.SqlTools.ServiceLayer.Connection.Contracts;
|
||||
using Microsoft.SqlTools.ServiceLayer.DisasterRecovery.Contracts;
|
||||
using Microsoft.SqlTools.ServiceLayer.DisasterRecovery.RestoreOperation;
|
||||
using Microsoft.SqlTools.ServiceLayer.FileBrowser;
|
||||
using Microsoft.SqlTools.ServiceLayer.TaskServices;
|
||||
|
||||
namespace Microsoft.SqlTools.ServiceLayer.DisasterRecovery
|
||||
{
|
||||
@@ -26,6 +25,7 @@ namespace Microsoft.SqlTools.ServiceLayer.DisasterRecovery
|
||||
private static readonly Lazy<DisasterRecoveryService> instance = new Lazy<DisasterRecoveryService>(() => new DisasterRecoveryService());
|
||||
private static ConnectionService connectionService = null;
|
||||
private SqlTaskManager sqlTaskManagerInstance = null;
|
||||
private FileBrowserService fileBrowserService = null;
|
||||
private RestoreDatabaseHelper restoreDatabaseService = new RestoreDatabaseHelper();
|
||||
|
||||
/// <summary>
|
||||
@@ -78,6 +78,25 @@ namespace Microsoft.SqlTools.ServiceLayer.DisasterRecovery
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the current filebrowser service instance
|
||||
/// </summary>
|
||||
internal FileBrowserService FileBrowserServiceInstance
|
||||
{
|
||||
get
|
||||
{
|
||||
if (fileBrowserService == null)
|
||||
{
|
||||
fileBrowserService = FileBrowserService.Instance;
|
||||
}
|
||||
return fileBrowserService;
|
||||
}
|
||||
set
|
||||
{
|
||||
fileBrowserService = value;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Initializes the service instance
|
||||
/// </summary>
|
||||
@@ -89,14 +108,18 @@ namespace Microsoft.SqlTools.ServiceLayer.DisasterRecovery
|
||||
// Create backup
|
||||
serviceHost.SetRequestHandler(BackupRequest.Type, HandleBackupRequest);
|
||||
|
||||
// Create respore task
|
||||
// Create restore task
|
||||
serviceHost.SetRequestHandler(RestoreRequest.Type, HandleRestoreRequest);
|
||||
|
||||
// Create respore plan
|
||||
// Create restore plan
|
||||
serviceHost.SetRequestHandler(RestorePlanRequest.Type, HandleRestorePlanRequest);
|
||||
|
||||
// Create respore config
|
||||
// Create restore config
|
||||
serviceHost.SetRequestHandler(RestoreConfigInfoRequest.Type, HandleRestoreConfigInfoRequest);
|
||||
|
||||
// Register file path validation callbacks
|
||||
FileBrowserServiceInstance.RegisterValidatePathsCallback(FileValidationServiceConstants.Backup, DisasterRecoveryFileValidator.ValidatePaths);
|
||||
FileBrowserServiceInstance.RegisterValidatePathsCallback(FileValidationServiceConstants.Restore, DisasterRecoveryFileValidator.ValidatePaths);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
||||
Reference in New Issue
Block a user