move the scheduler to a windows service

This commit is contained in:
vfedosevich 2013-04-30 10:47:34 +03:00
parent 97f09a5683
commit 5e414136b2
115 changed files with 587 additions and 166 deletions

View file

@ -0,0 +1,92 @@
// Copyright (c) 2012, Outercurve Foundation.
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without modification,
// are permitted provided that the following conditions are met:
//
// - Redistributions of source code must retain the above copyright notice, this
// list of conditions and the following disclaimer.
//
// - Redistributions in binary form must reproduce the above copyright notice,
// this list of conditions and the following disclaimer in the documentation
// and/or other materials provided with the distribution.
//
// - Neither the name of the Outercurve Foundation nor the names of its
// contributors may be used to endorse or promote products derived from this
// software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
// ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
// ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
using System;
using System.Threading;
using System.Collections.Generic;
using System.Text;
namespace WebsitePanel.EnterpriseServer
{
public class BackupAsyncWorker
{
public int threadUserId = -1;
public string taskId;
public int userId;
public int packageId;
public int serviceId;
public int serverId;
public string backupFileName;
public int storePackageId;
public string storePackageFolder;
public string storeServerFolder;
public string storePackageBackupPath;
public string storeServerBackupPath;
public bool deleteTempBackup;
#region Backup
public void BackupAsync()
{
// start asynchronously
Thread t = new Thread(new ThreadStart(Backup));
t.Start();
}
public void Backup()
{
// impersonate thread
if (threadUserId != -1)
SecurityContext.SetThreadPrincipal(threadUserId);
// perform backup
BackupController.BackupInternal(taskId, userId, packageId, serviceId, serverId, backupFileName, storePackageId,
storePackageFolder, storeServerFolder, deleteTempBackup);
}
#endregion
#region Restore
public void RestoreAsync()
{
// start asynchronously
Thread t = new Thread(new ThreadStart(Restore));
t.Start();
}
public void Restore()
{
// impersonate thread
if (threadUserId != -1)
SecurityContext.SetThreadPrincipal(threadUserId);
// perform restore
BackupController.RestoreInternal(taskId, userId, packageId, serviceId, serverId,
storePackageId, storePackageBackupPath, storeServerBackupPath);
}
#endregion
}
}

View file

@ -0,0 +1,924 @@
// Copyright (c) 2012, Outercurve Foundation.
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without modification,
// are permitted provided that the following conditions are met:
//
// - Redistributions of source code must retain the above copyright notice, this
// list of conditions and the following disclaimer.
//
// - Redistributions in binary form must reproduce the above copyright notice,
// this list of conditions and the following disclaimer in the documentation
// and/or other materials provided with the distribution.
//
// - Neither the name of the Outercurve Foundation nor the names of its
// contributors may be used to endorse or promote products derived from this
// software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
// ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
// ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
using System;
using System.IO;
using System.Data;
using System.Text;
using System.Collections.Generic;
using System.Xml;
using System.Security.Cryptography;
using System.Security.Cryptography.Xml;
using WebsitePanel.Providers;
using OS = WebsitePanel.Providers.OS;
using WebsitePanel.Ecommerce.EnterpriseServer;
namespace WebsitePanel.EnterpriseServer
{
public class BackupController
{
public const string BACKUP_CATALOG_FILE_NAME = "BackupCatalog.xml";
private const int FILE_BUFFER_LENGTH = 5000000; // ~5MB
private const string RSA_SETTINGS_KEY = "RSA_KEY";
public static int Backup(bool async, string taskId, int userId, int packageId, int serviceId, int serverId,
string backupFileName, int storePackageId, string storePackageFolder, string storeServerFolder,
bool deleteTempBackup)
{
// check demo account
int accountCheck = SecurityContext.CheckAccount(DemandAccount.NotDemo | DemandAccount.IsActive);
if (accountCheck < 0) return accountCheck;
// check admin account
accountCheck = SecurityContext.CheckAccount(DemandAccount.IsAdmin);
if ((serviceId > 0 || serverId > 0) && accountCheck < 0) return accountCheck;
if (accountCheck < 0)
deleteTempBackup = true;
// check if backup temp folder is available
string tempFolder = GetTempBackupFolder();
if (!FolderWriteAccessible(tempFolder))
return BusinessErrorCodes.ERROR_BACKUP_TEMP_FOLDER_UNAVAILABLE;
// check destination folder if required
if (!String.IsNullOrEmpty(storePackageFolder) &&
!RemoteServerFolderWriteAccessible(storePackageId, storePackageFolder))
return BusinessErrorCodes.ERROR_BACKUP_DEST_FOLDER_UNAVAILABLE;
// check server folder if required
if (!String.IsNullOrEmpty(storeServerFolder) &&
!FolderWriteAccessible(storeServerFolder))
return BusinessErrorCodes.ERROR_BACKUP_SERVER_FOLDER_UNAVAILABLE;
// check/reset delete flag
accountCheck = SecurityContext.CheckAccount(DemandAccount.IsAdmin);
if (accountCheck < 0 && !deleteTempBackup)
deleteTempBackup = true;
if (async)
{
BackupAsyncWorker worker = new BackupAsyncWorker();
worker.threadUserId = SecurityContext.User.UserId;
worker.taskId = taskId;
worker.userId = userId;
worker.packageId = packageId;
worker.serviceId = serviceId;
worker.serverId = serverId;
worker.backupFileName = backupFileName;
worker.storePackageId = storePackageId;
worker.storePackageFolder = storePackageFolder;
worker.storeServerFolder = storeServerFolder;
worker.deleteTempBackup = deleteTempBackup;
// run
worker.BackupAsync();
return 0;
}
else
{
return BackupInternal(taskId, userId, packageId, serviceId, serverId,
backupFileName, storePackageId, storePackageFolder, storeServerFolder,
deleteTempBackup);
}
}
public static int BackupInternal(string taskId, int userId, int packageId, int serviceId, int serverId,
string backupFileName, int storePackageId, string storePackageFolder, string storeServerFolder,
bool deleteTempBackup)
{
try
{
TaskManager.StartTask(taskId, "BACKUP", "BACKUP", backupFileName);
TaskManager.ItemId = SecurityContext.User.UserId;
// get the list of items to backup
TaskManager.Write("Calculate items to backup");
List<ServiceProviderItem> items = GetBackupItems(userId, packageId, serviceId, serverId);
if (items.Count == 0)
return 0;
// group items by item types
Dictionary<int, List<ServiceProviderItem>> groupedItems = new Dictionary<int, List<ServiceProviderItem>>();
// sort by groups
foreach (ServiceProviderItem item in items)
{
// add to group
if (!groupedItems.ContainsKey(item.TypeId))
groupedItems[item.TypeId] = new List<ServiceProviderItem>();
groupedItems[item.TypeId].Add(item);
}
// temp backup folder
string tempFolder = GetTempBackupFolder();
// create backup catalog file
StringWriter sw = new StringWriter();
XmlTextWriter writer = new XmlTextWriter(sw);
// write backup file header
writer.WriteProcessingInstruction("xml", "version=\"1.0\" encoding=\"utf-8\"");
writer.WriteStartElement("Backup");
writer.WriteStartElement("Info");
writer.WriteElementString("Name", backupFileName);
writer.WriteElementString("Created", DateTime.Now.ToString("r"));
writer.WriteElementString("User", GetLoggedUsername());
writer.WriteEndElement(); // Info
// determine the number of items to backup
int totalItems = 0;
foreach (int itemTypeId in groupedItems.Keys)
{
// load item type
ServiceProviderItemType itemType = PackageController.GetServiceItemType(itemTypeId);
if (!itemType.Backupable)
continue;
totalItems += groupedItems[itemTypeId].Count;
}
TaskManager.IndicatorMaximum = totalItems + 2;
TaskManager.IndicatorCurrent = 0;
// backup grouped items
writer.WriteStartElement("Items");
foreach (int itemTypeId in groupedItems.Keys)
{
// load item type
ServiceProviderItemType itemType = PackageController.GetServiceItemType(itemTypeId);
if (!itemType.Backupable)
continue;
// load group
ResourceGroupInfo group = ServerController.GetResourceGroup(itemType.GroupId);
// instantiate controller
IBackupController controller = null;
try
{
if (group.GroupController != null)
controller = Activator.CreateInstance(Type.GetType(group.GroupController)) as IBackupController;
if (controller != null)
{
// backup items
foreach (ServiceProviderItem item in groupedItems[itemTypeId])
{
TaskManager.Write(String.Format("Backup {0} of {1} - {2} '{3}'",
TaskManager.IndicatorCurrent + 1,
totalItems,
itemType.DisplayName,
item.Name));
try
{
int backupResult = BackupItem(tempFolder, writer, item, group, controller);
}
catch (Exception ex)
{
TaskManager.WriteError(ex, "Can't backup item");
}
// increment progress
TaskManager.IndicatorCurrent += 1;
}
}
}
catch (Exception ex)
{
TaskManager.WriteError(ex);
}
}
writer.WriteEndElement(); // Items
// close catalog writer
writer.WriteEndElement(); // Backup
writer.Close();
// convert to Xml document
XmlDocument doc = new XmlDocument();
doc.LoadXml(sw.ToString());
// sign XML document
//SignXmlDocument(doc);
// save signed doc to file
try
{
doc.Save(Path.Combine(tempFolder, BACKUP_CATALOG_FILE_NAME));
}
catch (Exception ex)
{
TaskManager.WriteError(ex, "Can't save backup catalog file: "
+ Path.Combine(tempFolder, BACKUP_CATALOG_FILE_NAME));
return 0;
}
TaskManager.Write("Packaging backup...");
// compress backup files
string[] zipFiles = Directory.GetFiles(tempFolder);
string[] zipFileNames = new string[zipFiles.Length];
for (int i = 0; i < zipFiles.Length; i++)
zipFileNames[i] = Path.GetFileName(zipFiles[i]);
string backupFileNamePath = Path.Combine(tempFolder, backupFileName);
try
{
FileUtils.ZipFiles(backupFileNamePath, tempFolder, zipFileNames);
// delete packed files
foreach (string zipFile in zipFiles)
File.Delete(zipFile);
}
catch (Exception ex)
{
TaskManager.WriteError(ex, "Can't zip backed up files");
return 0;
}
TaskManager.IndicatorCurrent += 1;
TaskManager.Write("Copying backup...");
// move/copy backup file
if (!String.IsNullOrEmpty(storeServerFolder))
{
// copy to local folder or UNC
try
{
string destFile = Path.Combine(storeServerFolder, backupFileName);
File.Copy(backupFileNamePath, destFile, true);
}
catch (Exception ex)
{
TaskManager.WriteError(ex, "Can't copy backup to destination location");
return 0;
}
}
else if (storePackageId > 0)
{
try
{
// copy to space folder
int osServiceId = PackageController.GetPackageServiceId(storePackageId, ResourceGroups.Os);
if (osServiceId > 0)
{
OS.OperatingSystem os = new OS.OperatingSystem();
ServiceProviderProxy.Init(os, osServiceId);
string remoteBackupPath = FilesController.GetFullPackagePath(storePackageId,
Path.Combine(storePackageFolder, backupFileName));
FileStream stream = new FileStream(backupFileNamePath, FileMode.Open, FileAccess.Read);
byte[] buffer = new byte[FILE_BUFFER_LENGTH];
int readBytes = 0;
do
{
// read package file
readBytes = stream.Read(buffer, 0, FILE_BUFFER_LENGTH);
if (readBytes < FILE_BUFFER_LENGTH)
// resize buffer
Array.Resize<byte>(ref buffer, readBytes);
// write remote backup file
os.AppendFileBinaryContent(remoteBackupPath, buffer);
}
while (readBytes == FILE_BUFFER_LENGTH);
stream.Close();
}
}
catch (Exception ex)
{
TaskManager.WriteError(ex, "Can't copy backup to destination hosting space");
return 0;
}
}
TaskManager.IndicatorCurrent += 1;
// delete backup file if required
if (deleteTempBackup)
{
try
{
// delete backup folder and all its contents
Directory.Delete(tempFolder, true);
}
catch (Exception ex)
{
TaskManager.WriteError(ex, "Can't delete temporary backup folder");
return 0;
}
}
TaskManager.IndicatorCurrent = TaskManager.IndicatorMaximum;
}
catch (Exception ex)
{
TaskManager.WriteError(ex);
}
finally
{
TaskManager.CompleteTask();
}
return 0;
}
public static List<ServiceProviderItem> GetBackupItems(int userId,
int packageId, int serviceId, int serverId)
{
List<ServiceProviderItem> items = new List<ServiceProviderItem>();
if (packageId > 0)
{
items.AddRange(PackageController.GetPackageItems(packageId));
}
else if (serviceId > 0)
{
items.AddRange(PackageController.GetServiceItems(serviceId));
}
else if (serverId > 0)
{
// get server services
List<ServiceInfo> services = ServerController.GetServicesByServerId(serverId);
foreach (ServiceInfo service in services)
items.AddRange(PackageController.GetServiceItems(service.ServiceId));
}
else if (userId > 0)
{
List<PackageInfo> packages = new List<PackageInfo>();
// get own spaces
packages.AddRange(PackageController.GetMyPackages(userId));
// get user spaces
packages.AddRange(PackageController.GetPackages(userId));
// build collection
foreach (PackageInfo package in packages)
items.AddRange(PackageController.GetPackageItems(package.PackageId));
}
return items;
}
public static KeyValueBunch GetBackupContentSummary(int userId, int packageId,
int serviceId, int serverId)
{
Dictionary<string, List<string>> summary = new Dictionary<string, List<string>>();
// Get backup items
List<ServiceProviderItem> items = GetBackupItems(userId, packageId, serviceId, serverId);
// Prepare filter for in-loop sort
ServiceProviderItemType[] itemTypes = PackageController.GetServiceItemTypes().ToArray();
// Group service items by type id
foreach (ServiceProviderItem si in items)
{
ServiceProviderItemType itemType = Array.Find<ServiceProviderItemType>(itemTypes,
x => x.ItemTypeId == si.TypeId && x.Backupable);
// Sort out item types without backup capabilities
if (itemType != null)
{
// Mimic a grouping sort
if (!summary.ContainsKey(itemType.DisplayName))
summary.Add(itemType.DisplayName, new List<string>());
//
summary[itemType.DisplayName].Add(si.Name);
}
}
//
KeyValueBunch result = new KeyValueBunch();
// Convert grouped data into serializable format
foreach (string groupName in summary.Keys)
result[groupName] = String.Join(",", summary[groupName].ToArray());
//
return result;
}
public static int Restore(bool async, string taskId, int userId, int packageId, int serviceId, int serverId,
int storePackageId, string storePackageBackupPath, string storeServerBackupPath)
{
// check demo account
int accountCheck = SecurityContext.CheckAccount(DemandAccount.NotDemo);
if (accountCheck < 0) return accountCheck;
// check admin account
accountCheck = SecurityContext.CheckAccount(DemandAccount.IsAdmin);
if ((serviceId > 0 || serverId > 0) && accountCheck < 0) return accountCheck;
// check if backup temp folder is available
string tempFolder = GetTempBackupFolder();
if (!FolderWriteAccessible(tempFolder))
return BusinessErrorCodes.ERROR_BACKUP_TEMP_FOLDER_UNAVAILABLE;
// check server source path if required
if (!String.IsNullOrEmpty(storeServerBackupPath))
{
try
{
if (!File.Exists(storeServerBackupPath))
return BusinessErrorCodes.ERROR_RESTORE_BACKUP_SOURCE_NOT_FOUND;
}
catch
{
return BusinessErrorCodes.ERROR_RESTORE_BACKUP_SOURCE_UNAVAILABLE;
}
}
if (async)
{
BackupAsyncWorker worker = new BackupAsyncWorker();
worker.threadUserId = SecurityContext.User.UserId;
worker.taskId = taskId;
worker.userId = userId;
worker.packageId = packageId;
worker.serviceId = serviceId;
worker.serverId = serverId;
worker.storePackageId = storePackageId;
worker.storePackageBackupPath = storePackageBackupPath;
worker.storeServerBackupPath = storeServerBackupPath;
// run
worker.RestoreAsync();
return 0;
}
else
{
return RestoreInternal(taskId, userId, packageId, serviceId, serverId,
storePackageId, storePackageBackupPath, storeServerBackupPath);
}
}
public static int RestoreInternal(string taskId, int userId, int packageId, int serviceId, int serverId,
int storePackageId, string storePackageBackupPath, string storeServerBackupPath)
{
try
{
// copy backup from remote or local server
string backupFileName = (storePackageId > 0)
? Path.GetFileName(storePackageBackupPath) : Path.GetFileName(storeServerBackupPath);
TaskManager.StartTask(taskId, "BACKUP", "RESTORE", backupFileName);
TaskManager.ItemId = SecurityContext.User.UserId;
// create temp folder
string tempFolder = GetTempBackupFolder();
string backupFileNamePath = Path.Combine(tempFolder, backupFileName);
if (storePackageId > 0)
{
try
{
int osServiceId = PackageController.GetPackageServiceId(storePackageId, ResourceGroups.Os);
if (osServiceId > 0)
{
OS.OperatingSystem os = new OS.OperatingSystem();
ServiceProviderProxy.Init(os, osServiceId);
string remoteBackupPath = FilesController.GetFullPackagePath(storePackageId,
storePackageBackupPath);
FileStream stream = new FileStream(backupFileNamePath, FileMode.Create, FileAccess.Write);
byte[] buffer = new byte[FILE_BUFFER_LENGTH];
int offset = 0;
do
{
// read remote content
buffer = os.GetFileBinaryChunk(remoteBackupPath, offset, FILE_BUFFER_LENGTH);
// write remote content
stream.Write(buffer, 0, buffer.Length);
offset += FILE_BUFFER_LENGTH;
}
while (buffer.Length == FILE_BUFFER_LENGTH);
stream.Close();
}
}
catch (Exception ex)
{
TaskManager.WriteError(ex, "Can't copy source backup set");
return 0;
}
}
else
{
backupFileNamePath = storeServerBackupPath;
}
try
{
// unpack archive
FileUtils.UnzipFiles(backupFileNamePath, tempFolder);
}
catch (Exception ex)
{
TaskManager.WriteError(ex, "Can't unzip backup set");
return 0;
}
// load backup catalog
XmlDocument doc = new XmlDocument();
try
{
doc.Load(Path.Combine(tempFolder, BACKUP_CATALOG_FILE_NAME));
}
catch (Exception ex)
{
TaskManager.WriteError(ex, "Can't find/open backup catalog file");
return 0;
}
// validate XML document
//if (!ValidateXmlDocument(doc))
//{
// TaskManager.WriteError("Corrupted or altered backup catalog file has been read");
// return 0;
//}
// get the list of items to restore
string condition = "";
if (userId > 0)
{
// get user spaces
List<PackageInfo> packages = new List<PackageInfo>();
packages.AddRange(PackageController.GetMyPackages(userId));
packages.AddRange(PackageController.GetPackages(userId));
List<string> parts = new List<string>();
foreach (PackageInfo package in packages)
parts.Add("@packageId = " + package.PackageId.ToString());
condition = "[" + String.Join(" or ", parts.ToArray()) + "]";
}
else if (packageId > 0)
{
condition = "[@packageId = " + packageId + "]";
}
else if (serviceId > 0)
{
condition = "[@serviceId = " + serviceId + "]";
}
else if (serverId > 0)
{
// get server services
List<ServiceInfo> services = ServerController.GetServicesByServerId(serverId);
List<string> parts = new List<string>();
foreach (ServiceInfo service in services)
parts.Add("@serviceId = " + service.ServiceId.ToString());
condition = "[" + String.Join(" or ", parts.ToArray()) + "]";
}
XmlNodeList itemNodes = doc.SelectNodes("Backup/Items/Item" + condition);
TaskManager.IndicatorMaximum = itemNodes.Count;
TaskManager.IndicatorCurrent = 0;
// group items by item types
Dictionary<int, List<XmlNode>> groupedItems = new Dictionary<int, List<XmlNode>>();
// sort by groups
foreach (XmlNode itemNode in itemNodes)
{
int itemTypeId = Utils.ParseInt(itemNode.Attributes["itemTypeId"].Value, 0);
// add to group
if (!groupedItems.ContainsKey(itemTypeId))
groupedItems[itemTypeId] = new List<XmlNode>();
groupedItems[itemTypeId].Add(itemNode);
}
// restore grouped items
foreach (int itemTypeId in groupedItems.Keys)
{
// load item type
ServiceProviderItemType itemTypeInfo = PackageController.GetServiceItemType(itemTypeId);
if (!itemTypeInfo.Backupable)
continue;
Type itemType = Type.GetType(itemTypeInfo.TypeName);
// load group
ResourceGroupInfo group = ServerController.GetResourceGroup(itemTypeInfo.GroupId);
// instantiate controller
IBackupController controller = null;
try
{
controller = Activator.CreateInstance(Type.GetType(group.GroupController)) as IBackupController;
if (controller != null)
{
// backup items
foreach (XmlNode itemNode in groupedItems[itemTypeId])
{
int itemId = Utils.ParseInt(itemNode.Attributes["itemId"].Value, 0);
string itemName = itemNode.Attributes["itemName"].Value;
int itemPackageId = Utils.ParseInt(itemNode.Attributes["packageId"].Value, 0);
int itemServiceId = Utils.ParseInt(itemNode.Attributes["serviceId"].Value, 0);
TaskManager.Write(String.Format("Restore {0} '{1}'",
itemTypeInfo.DisplayName, itemName));
try
{
int restoreResult = controller.RestoreItem(tempFolder, itemNode,
itemId, itemType, itemName, itemPackageId, itemServiceId, group);
}
catch (Exception ex)
{
TaskManager.WriteError(ex, "Can't restore item");
}
TaskManager.IndicatorCurrent++;
}
}
}
catch (Exception ex)
{
TaskManager.WriteError(ex);
}
}
// delete backup folder and all its contents
try
{
Directory.Delete(tempFolder, true);
}
catch (Exception ex)
{
TaskManager.WriteError(ex, "Can't delete temporary backup folder");
return 0;
}
}
catch (Exception ex)
{
TaskManager.WriteError(ex);
}
finally
{
TaskManager.CompleteTask();
}
return 0;
}
public static int BackupItem(string tempFolder, XmlWriter writer, ServiceProviderItem item)
{
// load item type
ServiceProviderItemType itemType = PackageController.GetServiceItemType(item.TypeId);
if (!itemType.Backupable)
return -1;
// load group
ResourceGroupInfo group = ServerController.GetResourceGroup(itemType.GroupId);
// create controller
IBackupController controller = null;
try
{
controller = Activator.CreateInstance(Type.GetType(group.GroupController)) as IBackupController;
if (controller != null)
{
return BackupItem(tempFolder, writer, item, group, controller);
}
}
catch (Exception ex)
{
TaskManager.WriteError(ex);
}
return -2;
}
private static int BackupItem(string tempFolder, XmlWriter writer,
ServiceProviderItem item, ResourceGroupInfo group, IBackupController controller)
{
writer.WriteStartElement("Item");
writer.WriteAttributeString("itemId", item.Id.ToString());
writer.WriteAttributeString("itemTypeId", item.TypeId.ToString());
writer.WriteAttributeString("itemName", item.Name);
writer.WriteAttributeString("packageId", item.PackageId.ToString());
writer.WriteAttributeString("serviceId", item.ServiceId.ToString());
try
{
return controller.BackupItem(tempFolder, writer, item, group);
}
catch (Exception ex)
{
TaskManager.WriteError(ex);
}
finally
{
writer.WriteEndElement(); // Item
}
return 0;
}
public static int RestoreItem()
{
return 0;
}
public static void WriteFileElement(XmlWriter writer, string fileName, string filePath, long size)
{
writer.WriteStartElement("File");
writer.WriteAttributeString("name", fileName);
writer.WriteAttributeString("path", filePath);
writer.WriteAttributeString("size", size.ToString());
writer.WriteEndElement();
}
#region Utility Methods
public static bool FolderWriteAccessible(string path)
{
try
{
string tempFile = Path.Combine(path, "check");
StreamWriter writer = File.CreateText(tempFile);
writer.Close();
File.Delete(tempFile);
return true;
}
catch
{
return false;
}
}
public static bool RemoteServerFolderWriteAccessible(int packageId, string path)
{
try
{
// copy to space folder
int osServiceId = PackageController.GetPackageServiceId(packageId, ResourceGroups.Os);
if (osServiceId > 0)
{
OS.OperatingSystem os = new OS.OperatingSystem();
ServiceProviderProxy.Init(os, osServiceId);
string remoteServerPathCheck = FilesController.GetFullPackagePath(packageId,
Path.Combine(path, "check.txt"));
//
os.CreateFile(remoteServerPathCheck);
os.AppendFileBinaryContent(remoteServerPathCheck, Encoding.UTF8.GetBytes(remoteServerPathCheck));
os.DeleteFile(remoteServerPathCheck);
}
//
return true;
}
catch
{
//
return false;
}
}
public static void SignXmlDocument(XmlDocument doc)
{
// Create a SignedXml object.
SignedXml signedXml = new SignedXml(doc);
// Add the key to the SignedXml document.
signedXml.SigningKey = GetUserRSAKey();
// Create a reference to be signed.
Reference reference = new Reference();
reference.Uri = "";
// Add an enveloped transformation to the reference.
XmlDsigEnvelopedSignatureTransform env = new XmlDsigEnvelopedSignatureTransform();
reference.AddTransform(env);
// Add the reference to the SignedXml object.
signedXml.AddReference(reference);
// Compute the signature.
signedXml.ComputeSignature();
// Get the XML representation of the signature and save
// it to an XmlElement object.
XmlElement xmlDigitalSignature = signedXml.GetXml();
// Append the element to the XML document.
doc.DocumentElement.AppendChild(doc.ImportNode(xmlDigitalSignature, true));
}
public static bool ValidateXmlDocument(XmlDocument doc)
{
// Create a new SignedXml object and pass it
// the XML document class.
SignedXml signedXml = new SignedXml(doc);
// Find the "Signature" node and create a new
// XmlNodeList object.
XmlNodeList nodeList = doc.GetElementsByTagName("Signature");
// Throw an exception if no signature was found.
if (nodeList.Count <= 0)
{
throw new CryptographicException("Verification failed: No Signature was found in the document.");
}
// This example only supports one signature for
// the entire XML document. Throw an exception
// if more than one signature was found.
if (nodeList.Count >= 2)
{
throw new CryptographicException("Verification failed: More that one signature was found for the document.");
}
// Load the first <signature> node.
signedXml.LoadXml((XmlElement)nodeList[0]);
// Check the signature and return the result.
return signedXml.CheckSignature(GetUserRSAKey());
}
public static RSA GetUserRSAKey()
{
int userId = SecurityContext.User.UserId;
if(SecurityContext.User.IsPeer)
userId = SecurityContext.User.OwnerId;
UserSettings settings = UserController.GetUserSettings(userId, RSA_SETTINGS_KEY);
string keyXml = settings[RSA_SETTINGS_KEY];
RSA rsa = RSA.Create();
if (String.IsNullOrEmpty(keyXml) || settings.UserId != userId)
{
// generate new key
keyXml = rsa.ToXmlString(true);
// store to settings
settings[RSA_SETTINGS_KEY] = keyXml;
settings.UserId = userId;
UserController.UpdateUserSettings(settings);
}
else
{
rsa.FromXmlString(keyXml);
}
return rsa;
}
private static string GetLoggedUsername()
{
string username = SecurityContext.User.Identity.Name;
UserInfo user = UserController.GetUser(SecurityContext.User.UserId);
if (user != null)
username = user.Username;
return username;
}
public static string GetTempBackupFolder()
{
string timeStamp = DateTime.Now.Ticks.ToString();
string tempFolder = Path.Combine(ConfigSettings.BackupsPath, GetLoggedUsername() + "_" + timeStamp);
// create folder
if (!Directory.Exists(tempFolder))
Directory.CreateDirectory(tempFolder);
return tempFolder;
}
#endregion
}
}

View file

@ -0,0 +1,50 @@
// Copyright (c) 2012, Outercurve Foundation.
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without modification,
// are permitted provided that the following conditions are met:
//
// - Redistributions of source code must retain the above copyright notice, this
// list of conditions and the following disclaimer.
//
// - Redistributions in binary form must reproduce the above copyright notice,
// this list of conditions and the following disclaimer in the documentation
// and/or other materials provided with the distribution.
//
// - Neither the name of the Outercurve Foundation nor the names of its
// contributors may be used to endorse or promote products derived from this
// software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
// ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
// ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
using System;
using System.Data;
using System.Configuration;
using System.Web;
using System.Web.Security;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Web.UI.WebControls.WebParts;
using System.Web.UI.HtmlControls;
using System.Xml;
using WebsitePanel.Providers;
namespace WebsitePanel.EnterpriseServer
{
public interface IBackupController
{
int BackupItem(string tempFolder, XmlWriter writer, ServiceProviderItem item, ResourceGroupInfo group);
int RestoreItem(string tempFolder, XmlNode itemNode, int itemId, Type itemType,
string itemName, int packageId, int serviceId, ResourceGroupInfo group);
}
}

View file

@ -0,0 +1,42 @@
// Copyright (c) 2012, Outercurve Foundation.
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without modification,
// are permitted provided that the following conditions are met:
//
// - Redistributions of source code must retain the above copyright notice, this
// list of conditions and the following disclaimer.
//
// - Redistributions in binary form must reproduce the above copyright notice,
// this list of conditions and the following disclaimer in the documentation
// and/or other materials provided with the distribution.
//
// - Neither the name of the Outercurve Foundation nor the names of its
// contributors may be used to endorse or promote products derived from this
// software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
// ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
// ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
using System;
using System.Collections.Generic;
namespace WebsitePanel.EnterpriseServer
{
public interface IImportController
{
List<string> GetImportableItems(int packageId, int itemTypeId,
Type itemType, ResourceGroupInfo group);
void ImportItem(int packageId, int itemTypeId,
Type itemType, ResourceGroupInfo group, string itemName);
}
}

View file

@ -0,0 +1,60 @@
// Copyright (c) 2012, Outercurve Foundation.
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without modification,
// are permitted provided that the following conditions are met:
//
// - Redistributions of source code must retain the above copyright notice, this
// list of conditions and the following disclaimer.
//
// - Redistributions in binary form must reproduce the above copyright notice,
// this list of conditions and the following disclaimer in the documentation
// and/or other materials provided with the distribution.
//
// - Neither the name of the Outercurve Foundation nor the names of its
// contributors may be used to endorse or promote products derived from this
// software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
// ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
// ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
using System;
using System.Collections.Generic;
using System.Text;
using System.Threading;
namespace WebsitePanel.EnterpriseServer
{
public class ImportAsyncWorker
{
public int threadUserId = -1;
public string taskId;
public int packageId;
public string[] items;
public void ImportAsync()
{
// start asynchronously
Thread t = new Thread(new ThreadStart(Import));
t.Start();
}
public void Import()
{
// impersonate thread
if (threadUserId != -1)
SecurityContext.SetThreadPrincipal(threadUserId);
// perform import
ImportController.ImportItemsInternal(taskId, packageId, items);
}
}
}

View file

@ -0,0 +1,311 @@
// Copyright (c) 2012, Outercurve Foundation.
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without modification,
// are permitted provided that the following conditions are met:
//
// - Redistributions of source code must retain the above copyright notice, this
// list of conditions and the following disclaimer.
//
// - Redistributions in binary form must reproduce the above copyright notice,
// this list of conditions and the following disclaimer in the documentation
// and/or other materials provided with the distribution.
//
// - Neither the name of the Outercurve Foundation nor the names of its
// contributors may be used to endorse or promote products derived from this
// software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
// ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
// ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
using System;
using System.Data;
using System.Collections.Generic;
using WebsitePanel.EnterpriseServer;
using WebsitePanel.Providers;
using WebsitePanel.Providers.Web;
namespace WebsitePanel.EnterpriseServer
{
public class ImportController
{
public static List<ServiceProviderItemType> GetImportableItemTypes(int packageId)
{
// load all service item types
List<ServiceProviderItemType> itemTypes = PackageController.GetServiceItemTypes();
// load package context
PackageContext cntx = PackageController.GetPackageContext(packageId);
// build importable items list
List<ServiceProviderItemType> importableTypes = new List<ServiceProviderItemType>();
foreach (ServiceProviderItemType itemType in itemTypes)
{
if (!itemType.Importable)
continue;
// load group
ResourceGroupInfo group = ServerController.GetResourceGroup(itemType.GroupId);
if (cntx.Groups.ContainsKey(group.GroupName))
importableTypes.Add(itemType);
}
return importableTypes;
}
public static List<string> GetImportableItems(int packageId, int itemTypeId)
{
List<string> items = new List<string>();
// check account
int accountCheck = SecurityContext.CheckAccount(DemandAccount.IsAdmin | DemandAccount.NotDemo);
if (accountCheck < 0) return items;
// load item type
if (itemTypeId > 0)
{
ServiceProviderItemType itemType = PackageController.GetServiceItemType(itemTypeId);
// load group
ResourceGroupInfo group = ServerController.GetResourceGroup(itemType.GroupId);
// get service id
int serviceId = PackageController.GetPackageServiceId(packageId, group.GroupName);
if (serviceId == 0)
return items;
DataTable dtServiceItems = PackageController.GetServiceItemsDataSet(serviceId).Tables[0];
DataTable dtPackageItems = PackageController.GetPackageItemsDataSet(packageId).Tables[0];
// instantiate controller
IImportController ctrl = null;
try
{
List<string> importableItems = null;
ctrl = Activator.CreateInstance(Type.GetType(group.GroupController)) as IImportController;
if (ctrl != null)
{
importableItems = ctrl.GetImportableItems(packageId, itemTypeId, Type.GetType(itemType.TypeName), group);
}
foreach (string importableItem in importableItems)
{
// filter items by service
bool serviceContains = false;
foreach (DataRow dr in dtServiceItems.Rows)
{
string serviceItemName = (string)dr["ItemName"];
int serviceItemTypeId = (int)dr["ItemTypeId"];
if (String.Compare(importableItem, serviceItemName, true) == 0
&& serviceItemTypeId == itemTypeId)
{
serviceContains = true;
break;
}
}
// filter items by package
bool packageContains = false;
foreach (DataRow dr in dtPackageItems.Rows)
{
string packageItemName = (string)dr["ItemName"];
int packageItemTypeId = (int)dr["ItemTypeId"];
if (String.Compare(importableItem, packageItemName, true) == 0
&& packageItemTypeId == itemTypeId)
{
packageContains = true;
break;
}
}
if (!serviceContains && !packageContains)
items.Add(importableItem);
}
}
catch { /* do nothing */ }
}
else
return GetImportableCustomItems(packageId, itemTypeId);
return items;
}
public static int ImportItems(bool async, string taskId, int packageId, string[] items)
{
// check account
int accountCheck = SecurityContext.CheckAccount(DemandAccount.NotDemo | DemandAccount.IsAdmin);
if (accountCheck < 0) return accountCheck;
if (async)
{
ImportAsyncWorker worker = new ImportAsyncWorker();
worker.threadUserId = SecurityContext.User.UserId;
worker.taskId = taskId;
worker.packageId = packageId;
worker.items = items;
// import
worker.ImportAsync();
return 0;
}
else
{
return ImportItemsInternal(taskId, packageId, items);
}
}
public static int ImportItemsInternal(string taskId, int packageId, string[] items)
{
PackageInfo package = PackageController.GetPackage(packageId);
TaskManager.StartTask(taskId, "IMPORT", "IMPORT", package.PackageName);
TaskManager.ItemId = packageId;
TaskManager.IndicatorMaximum = items.Length;
TaskManager.IndicatorCurrent = 0;
Dictionary<int, List<string>> groupedItems = new Dictionary<int, List<string>>();
List<string> customItems = new List<string>();
// sort by groups
foreach (string item in items)
{
string[] itemParts = item.Split('|');
if (!item.StartsWith("+"))
{
int itemTypeId = Utils.ParseInt(itemParts[0], 0);
string itemName = itemParts[1];
// add to group
if (!groupedItems.ContainsKey(itemTypeId))
groupedItems[itemTypeId] = new List<string>();
groupedItems[itemTypeId].Add(itemName);
}
else
{
switch (itemParts[0])
{
case ("+100"):
if (itemParts.Length > 2)
customItems.Add(item);
break;
}
}
}
// import each group
foreach (int itemTypeId in groupedItems.Keys)
{
// load item type
ServiceProviderItemType itemType = PackageController.GetServiceItemType(itemTypeId);
// load group
ResourceGroupInfo group = ServerController.GetResourceGroup(itemType.GroupId);
// instantiate controller
IImportController ctrl = null;
try
{
ctrl = Activator.CreateInstance(Type.GetType(group.GroupController)) as IImportController;
if (ctrl != null)
{
foreach (string itemName in groupedItems[itemTypeId])
{
TaskManager.Write(String.Format("Import {0} '{1}'",
itemType.DisplayName, itemName));
try
{
// perform import
ctrl.ImportItem(packageId, itemTypeId,
Type.GetType(itemType.TypeName), group, itemName);
}
catch (Exception ex)
{
TaskManager.WriteError(ex, "Can't import item");
}
TaskManager.IndicatorCurrent++;
}
}
}
catch { /* do nothing */ }
}
foreach (string s in customItems)
{
try
{
string[] sParts = s.Split('|');
switch (sParts[0])
{
case "+100":
TaskManager.Write(String.Format("Import {0}", sParts[4]));
int result = WebServerController.ImporHostHeader(int.Parse(sParts[2],0), int.Parse(sParts[3],0), int.Parse(sParts[5],0));
if (result < 0)
TaskManager.WriteError(String.Format("Failed to Import {0} ,error: {1}: ", sParts[4], result.ToString()));
break;
}
}
catch { /* do nothing */ }
TaskManager.IndicatorCurrent++;
}
TaskManager.IndicatorCurrent = items.Length;
TaskManager.CompleteTask();
return 0;
}
private static List<string> GetImportableCustomItems(int packageId, int itemTypeId)
{
List<string> items = new List<string>();
PackageInfo packageInfo = PackageController.GetPackage(packageId);
if (packageInfo == null) return items;
switch (itemTypeId)
{
case -100:
List<UserInfo> users = UserController.GetUsers(packageInfo.UserId, true);
foreach (UserInfo user in users)
{
List<PackageInfo> packages = PackageController.GetPackages(user.UserId);
foreach (PackageInfo package in packages)
{
List<WebSite> webSites = WebServerController.GetWebSites(package.PackageId, false);
foreach (WebSite webSite in webSites)
{
items.Add(user.Username+"|"+user.UserId.ToString()+"|"+package.PackageId.ToString()+"|"+webSite.SiteId+"|"+webSite.Id);
}
}
}
break;
}
return items;
}
}
}