Added test-backend command and web modules

This commit is contained in:
Kenneth Skovhede
2014-03-12 01:41:25 +01:00
parent 88e157b4f2
commit 81ebf21597
3 changed files with 221 additions and 55 deletions
@@ -0,0 +1,66 @@
// Copyright (C) 2014, Kenneth Skovhede
// http://www.hexad.dk, opensource@hexad.dk
//
// This library is free software; you can redistribute it and/or modify
// it under the terms of the GNU Lesser General Public License as
// published by the Free Software Foundation; either version 2.1 of the
// License, or (at your option) any later version.
//
// This library 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
// Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public
// License along with this library; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
using System;
using System.Collections.Generic;
using System.Text;
using Duplicati.Library.Interface;
namespace Duplicati.Library.DynamicLoader
{
public static class WebLoader
{
/// <summary>
/// Implementation overrides specific to encryption
/// </summary>
private class WebLoaderSub : DynamicLoader<IWebModule>
{
/// <summary>
/// Returns the filename extension, which is also the key
/// </summary>
/// <param name="item">The item to load the key for</param>
/// <returns>The file extension used by the module</returns>
protected override string GetInterfaceKey(IWebModule item)
{
return item.Key;
}
/// <summary>
/// Returns the subfolders searched for encryption modules
/// </summary>
protected override string[] Subfolders
{
get { return new string[] { "webmodules" }; }
}
}
#region Public static API
/// <summary>
/// Gets a list of loaded settings controls, the instances can be used to extract interface information, not used to interact with the module.
/// </summary>
public static IWebModule[] Modules { get { return new WebLoaderSub().Interfaces; } }
/// <summary>
/// Gets a list of keys supported
/// </summary>
public static string[] Keys { get { return new WebLoaderSub().Keys; } }
#endregion
}
}
+54
View File
@@ -0,0 +1,54 @@
// Copyright (C) 2014, Kenneth Skovhede
// http://www.hexad.dk, opensource@hexad.dk
//
// This library is free software; you can redistribute it and/or modify
// it under the terms of the GNU Lesser General Public License as
// published by the Free Software Foundation; either version 2.1 of the
// License, or (at your option) any later version.
//
// This library 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
// Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public
// License along with this library; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
using System;
using System.Collections.Generic;
namespace Duplicati.Library.Interface
{
public interface IWebModule
{
/// <summary>
/// The module key, used to activate or deactivate the module on the commandline
/// </summary>
string Key { get; }
/// <summary>
/// A localized string describing the module with a friendly name
/// </summary>
string DisplayName { get; }
/// <summary>
/// A localized description of the module
/// </summary>
string Description { get; }
/// <summary>
/// Gets a list of supported commandline arguments
/// </summary>
IList<ICommandLineArgument> SupportedCommands { get; }
/// <summary>
/// Execute the specified command with the given options.
/// </summary>
/// <param name="command">The command to execute</param>
/// <param name="options">The options to use</param>
IDictionary<string, string> Execute(string command, IDictionary<string, string> options);
}
}
+101 -55
View File
@@ -233,6 +233,7 @@ namespace Duplicati.Server
SUPPORTED_METHODS.Add("delete-backup", DeleteBackup);
SUPPORTED_METHODS.Add("validate-path", ValidatePath);
SUPPORTED_METHODS.Add("list-tags", ListTags);
SUPPORTED_METHODS.Add("test-backend", TestBackend);
}
public override bool Process (HttpServer.IHttpRequest request, HttpServer.IHttpResponse response, HttpServer.Sessions.IHttpSession session)
@@ -302,6 +303,28 @@ namespace Duplicati.Server
Serializer.SerializeJson(b, o);
}
private void TestBackend(HttpServer.IHttpRequest request, HttpServer.IHttpResponse response, HttpServer.Sessions.IHttpSession session, BodyWriter bw)
{
HttpServer.HttpInput input = request.Method.ToUpper() == "POST" ? request.Form : request.QueryString;
if (input["url"] == null || input["url"].Value == null)
{
ReportError(response, bw, "The path parameter was not set");
return;
}
try
{
using(var b = Duplicati.Library.DynamicLoader.BackendLoader.GetBackend(input["url"].Value, new Dictionary<string, string>()))
b.Test();
OutputObject(bw, new { Status = "OK" });
}
catch (Exception ex)
{
ReportError(response, bw, ex.Message);
}
}
private void ListSystemInfo(HttpServer.IHttpRequest request, HttpServer.IHttpResponse response, HttpServer.Sessions.IHttpSession session, BodyWriter bw)
{
OutputObject(bw, new
@@ -329,7 +352,8 @@ namespace Duplicati.Server
CompressionModules = Serializable.ServerSettings.CompressionModules,
EncryptionModules = Serializable.ServerSettings.EncryptionModules,
BackendModules = Serializable.ServerSettings.BackendModules,
GenericModules = Serializable.ServerSettings.GenericModules
GenericModules = Serializable.ServerSettings.GenericModules,
WebModules = Serializable.ServerSettings.WebModules
});
}
@@ -932,70 +956,92 @@ namespace Duplicati.Server
HttpServer.HttpInput input = request.Method.ToUpper() == "POST" ? request.Form : request.QueryString;
string command = input["command"].Value ?? "";
string module = input["module"].Value ?? "";
long id;
switch (command.ToLowerInvariant())
if (string.IsNullOrWhiteSpace(module))
{
case "pause":
if (input.Contains("duration") && !string.IsNullOrWhiteSpace(input["duration"].Value))
{
TimeSpan ts;
try { ts = Library.Utility.Timeparser.ParseTimeSpan(input["duration"].Value); }
catch (Exception ex)
switch (command.ToLowerInvariant())
{
case "pause":
if (input.Contains("duration") && !string.IsNullOrWhiteSpace(input["duration"].Value))
{
ReportError(response, bw, ex.Message);
return;
TimeSpan ts;
try
{
ts = Library.Utility.Timeparser.ParseTimeSpan(input["duration"].Value);
}
catch (Exception ex)
{
ReportError(response, bw, ex.Message);
return;
}
if (ts.TotalMilliseconds > 0)
Program.LiveControl.Pause(ts);
else
Program.LiveControl.Pause();
}
if (ts.TotalMilliseconds > 0)
Program.LiveControl.Pause(ts);
else
Program.LiveControl.Pause();
}
else
{
Program.LiveControl.Pause();
}
break;
case "resume":
Program.LiveControl.Resume();
break;
case "stop":
break;
case "abort":
break;
case "run":
case "run-backup":
{
Duplicati.Server.Serialization.Interface.IBackup backup = null;
if (long.TryParse(input["id"].Value, out id))
backup = Program.DataConnection.GetBackup(id);
if (backup == null)
{
ReportError(response, bw, string.Format("No backup found for id: {0}", input["id"].Value));
return;
Program.LiveControl.Pause();
}
Program.WorkThread.AddTask(new Tuple<long, DuplicatiOperation>(id, DuplicatiOperation.Backup));
}
break;
case "clear-warning":
Program.HasWarning = false;
break;
case "clear-error":
Program.HasError = false;
break;
break;
case "resume":
Program.LiveControl.Resume();
break;
case "stop":
break;
case "abort":
break;
case "run":
case "run-backup":
{
Duplicati.Server.Serialization.Interface.IBackup backup = null;
if (long.TryParse(input["id"].Value, out id))
backup = Program.DataConnection.GetBackup(id);
if (backup == null)
{
ReportError(response, bw, string.Format("No backup found for id: {0}", input["id"].Value));
return;
}
Program.WorkThread.AddTask(new Tuple<long, DuplicatiOperation>(id, DuplicatiOperation.Backup));
}
break;
case "clear-warning":
Program.HasWarning = false;
break;
case "clear-error":
Program.HasError = false;
break;
default:
ReportError(response, bw, string.Format("Unsupported command {0}", command));
return;
}
default:
ReportError(response, bw, string.Format("Unsupported command {0}", command));
break;
OutputObject(bw, new { Status = "OK" });
}
else
{
var m = Duplicati.Library.DynamicLoader.WebLoader.Modules.Where(x => x.Key.Equals(module, StringComparison.InvariantCultureIgnoreCase)).FirstOrDefault();
if (m == null)
{
ReportError(response, bw, string.Format("Unsupported module {0}", command));
return;
}
OutputObject(bw, new {
Status = "OK",
Result = m.Execute(command.ToLowerInvariant(), input.ToDictionary(x => x.Name, x => x.Value))
});
}
OutputObject(bw, new { Status = "OK" });
}
}
}