// 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.Collections.Specialized; using System.Collections.Generic; using System.Text; using System.Linq; using System.Linq.Expressions; using System.Xml; using System.Xml.Serialization; using System.Web; using WebsitePanel.Providers; using WebsitePanel.Providers.Database; using WebsitePanel.Providers.Common; using WebsitePanel.Providers.ResultObjects; namespace WebsitePanel.EnterpriseServer { public class DatabaseServerController : IImportController, IBackupController { private const int FILE_BUFFER_LENGTH = 5000000; // ~5MB public static DatabaseServer GetDatabaseServer(int serviceId) { DatabaseServer db = new DatabaseServer(); ServiceProviderProxy.Init(db, serviceId); return db; } #region Databases public static DataSet GetRawSqlDatabasesPaged(int packageId, string groupName, string filterColumn, string filterValue, string sortColumn, int startRow, int maximumRows) { return PackageController.GetRawPackageItemsPaged(packageId, groupName, typeof(SqlDatabase), true, filterColumn, filterValue, sortColumn, startRow, maximumRows); } public static List GetSqlDatabases(int packageId, string groupName, bool recursive) { List items = PackageController.GetPackageItemsByType( packageId, groupName, typeof(SqlDatabase), recursive); return items.ConvertAll( new Converter(ConvertItemToSqlDatabase)); } private static SqlDatabase ConvertItemToSqlDatabase(ServiceProviderItem item) { return (SqlDatabase)item; } public static SqlDatabase GetSqlDatabase(int itemId) { // load meta item SqlDatabase item = (SqlDatabase)PackageController.GetPackageItem(itemId); // load service item DatabaseServer sql = GetDatabaseServer(item.ServiceId); SqlDatabase database = sql.GetDatabase(item.Name); if (database == null) return item; // add common properties database.Id = item.Id; database.PackageId = item.PackageId; database.ServiceId = item.ServiceId; database.GroupName = item.GroupName; StringDictionary settings = ServerController.GetServiceSettings(item.ServiceId); if (settings["InternalAddress"] != null) database.InternalServerName = settings["InternalAddress"]; if (settings["ExternalAddress"] != null) database.ExternalServerName = settings["ExternalAddress"]; return database; } public static int AddSqlDatabase(SqlDatabase item, string groupName) { // check account int accountCheck = SecurityContext.CheckAccount(DemandAccount.NotDemo | DemandAccount.IsActive); if (accountCheck < 0) return accountCheck; // check package int packageCheck = SecurityContext.CheckPackage(item.PackageId, DemandPackage.IsActive); if (packageCheck < 0) return packageCheck; // check quota QuotaValueInfo quota = PackageController.GetPackageQuota(item.PackageId, groupName + ".Databases"); if (quota.QuotaExhausted) return BusinessErrorCodes.ERROR_MSSQL_DATABASES_RESOURCE_QUOTA_LIMIT; // check if mail resource is available int serviceId = PackageController.GetPackageServiceId(item.PackageId, groupName); if (serviceId == 0) return BusinessErrorCodes.ERROR_MSSQL_RESOURCE_UNAVAILABLE; // check package items if (PackageController.GetPackageItemByName(item.PackageId, groupName, item.Name, typeof(SqlDatabase)) != null) return BusinessErrorCodes.ERROR_MSSQL_DATABASES_PACKAGE_ITEM_EXISTS; // place log record TaskManager.StartTask("SQL_DATABASE", "ADD", item.Name); TaskManager.WriteParameter("Provider", groupName); int itemId = default(int); // try { // check service items DatabaseServer sql = GetDatabaseServer(serviceId); if (sql.DatabaseExists(item.Name)) return BusinessErrorCodes.ERROR_MSSQL_DATABASES_SERVICE_ITEM_EXISTS; // calculate database location StringDictionary settings = ServerController.GetServiceSettings(serviceId); UserInfo user = PackageController.GetPackageOwner(item.PackageId); if (settings["UseDefaultDatabaseLocation"] != null && !Utils.ParseBool(settings["UseDefaultDatabaseLocation"], false)) { item.Location = Utils.ReplaceStringVariable(settings["DatabaseLocation"], "user_name", user.Username); } // set database size item.DataSize = GetMaxDatabaseSize(item.PackageId, groupName); // set log size item.LogSize = GetMaxLogSize(item.PackageId, groupName); // add service item sql.CreateDatabase(item); // save item item.ServiceId = serviceId; itemId = PackageController.AddPackageItem(item); TaskManager.ItemId = itemId; } catch (Exception ex) { TaskManager.WriteError(ex); // if (ex.Message.Contains("INVALID_DATABASE_NAME")) return BusinessErrorCodes.ERROR_MYSQL_INVALID_DATABASE_NAME; // Return a generic error instead of default(int) itemId = BusinessErrorCodes.FAILED_EXECUTE_SERVICE_OPERATION; } finally { TaskManager.CompleteTask(); } return itemId; } public static int UpdateSqlDatabase(SqlDatabase item) { // check account int accountCheck = SecurityContext.CheckAccount(DemandAccount.NotDemo | DemandAccount.IsActive); if (accountCheck < 0) return accountCheck; // load original meta item SqlDatabase origItem = (SqlDatabase)PackageController.GetPackageItem(item.Id); if (origItem == null) return BusinessErrorCodes.ERROR_MSSQL_DATABASES_PACKAGE_ITEM_NOT_FOUND; // check package int packageCheck = SecurityContext.CheckPackage(origItem.PackageId, DemandPackage.IsActive); if (packageCheck < 0) return packageCheck; // place log record TaskManager.StartTask("SQL_DATABASE", "UPDATE", origItem.Name); TaskManager.ItemId = item.Id; TaskManager.WriteParameter("Provider", origItem.GroupName); try { // get service DatabaseServer sql = GetDatabaseServer(origItem.ServiceId); // update service item sql.UpdateDatabase(item); return 0; } catch (Exception ex) { TaskManager.WriteError(ex); // Return a generic error instead of re-throwing an exception return BusinessErrorCodes.FAILED_EXECUTE_SERVICE_OPERATION; } finally { TaskManager.CompleteTask(); } } public static int DeleteSqlDatabase(int itemId) { // check account int accountCheck = SecurityContext.CheckAccount(DemandAccount.NotDemo); if (accountCheck < 0) return accountCheck; // load original meta item SqlDatabase origItem = (SqlDatabase)PackageController.GetPackageItem(itemId); if (origItem == null) return BusinessErrorCodes.ERROR_MSSQL_DATABASES_PACKAGE_ITEM_NOT_FOUND; // place log record TaskManager.StartTask("SQL_DATABASE", "DELETE", origItem.Name); TaskManager.ItemId = itemId; TaskManager.WriteParameter("Provider", origItem.GroupName); try { // get service DatabaseServer sql = GetDatabaseServer(origItem.ServiceId); // delete service item sql.DeleteDatabase(origItem.Name); // delete meta item PackageController.DeletePackageItem(origItem.Id); return 0; } catch (Exception ex) { TaskManager.WriteError(ex); // Return a generic error instead of re-throwing an exception return BusinessErrorCodes.FAILED_EXECUTE_SERVICE_OPERATION; } finally { TaskManager.CompleteTask(); } } private static int GetMaxSize(int packageId, string groupName, string prefix) { // load package context int maxSize = 0; // unlimited string quotaName = groupName + prefix; PackageContext cntx = PackageController.GetPackageContext(packageId); if (cntx != null && cntx.Quotas.ContainsKey(quotaName)) { maxSize = cntx.Quotas[quotaName].QuotaAllocatedValue; if (maxSize == -1) maxSize = 0; } return maxSize; } private static int GetMaxDatabaseSize(int packageId, string groupName) { return GetMaxSize(packageId, groupName, ".MaxDatabaseSize"); } private static int GetMaxLogSize(int packageId, string groupName) { return GetMaxSize(packageId, groupName, ".MaxLogSize"); } public static string BackupSqlDatabase(int itemId, string backupName, bool zipBackup, bool download, string folderName) { // check account int accountCheck = SecurityContext.CheckAccount(DemandAccount.NotDemo); if (accountCheck < 0) return null; // load original meta item SqlDatabase item = (SqlDatabase)PackageController.GetPackageItem(itemId); if (item == null) return null; // place log record TaskManager.StartTask("SQL_DATABASE", "BACKUP", item.Name); TaskManager.ItemId = itemId; try { DatabaseServer sql = GetDatabaseServer(item.ServiceId); string backFile = sql.BackupDatabase(item.Name, backupName, zipBackup); if (!download) { // copy backup files to space folder string relFolderName = FilesController.CorrectRelativePath(folderName); if (!relFolderName.EndsWith("\\")) relFolderName = relFolderName + "\\"; // create backup folder if not exists if (!FilesController.DirectoryExists(item.PackageId, relFolderName)) FilesController.CreateFolder(item.PackageId, relFolderName); string packageFile = relFolderName + Path.GetFileName(backFile); // delete destination file if exists if (FilesController.FileExists(item.PackageId, packageFile)) FilesController.DeleteFiles(item.PackageId, new string[] { packageFile }); byte[] buffer = null; int offset = 0; do { // read remote content buffer = sql.GetTempFileBinaryChunk(backFile, offset, FILE_BUFFER_LENGTH); // write remote content FilesController.AppendFileBinaryChunk(item.PackageId, packageFile, buffer); offset += FILE_BUFFER_LENGTH; } while (buffer.Length == FILE_BUFFER_LENGTH); } return backFile; } catch (Exception ex) { throw TaskManager.WriteError(ex); } finally { TaskManager.CompleteTask(); } } public static byte[] GetSqlBackupBinaryChunk(int itemId, string path, int offset, int length) { // load original meta item SqlDatabase item = (SqlDatabase)PackageController.GetPackageItem(itemId); if (item == null) return null; DatabaseServer sql = GetDatabaseServer(item.ServiceId); return sql.GetTempFileBinaryChunk(path, offset, length); } public static string AppendSqlBackupBinaryChunk(int itemId, string fileName, string path, byte[] chunk) { // load original meta item SqlDatabase item = (SqlDatabase)PackageController.GetPackageItem(itemId); if (item == null) return null; DatabaseServer sql = GetDatabaseServer(item.ServiceId); return sql.AppendTempFileBinaryChunk(fileName, path, chunk); } public static int RestoreSqlDatabase(int itemId, string[] uploadedFiles, string[] packageFiles) { // check account int accountCheck = SecurityContext.CheckAccount(DemandAccount.NotDemo | DemandAccount.IsActive); if (accountCheck < 0) return accountCheck; // load original meta item SqlDatabase item = (SqlDatabase)PackageController.GetPackageItem(itemId); if (item == null) return BusinessErrorCodes.ERROR_MSSQL_DATABASES_PACKAGE_ITEM_NOT_FOUND; // check package int packageCheck = SecurityContext.CheckPackage(item.PackageId, DemandPackage.IsActive); if (packageCheck < 0) return packageCheck; // place log record TaskManager.StartTask("SQL_DATABASE", "RESTORE", item.Name); TaskManager.ItemId = itemId; try { DatabaseServer sql = GetDatabaseServer(item.ServiceId); List backupFiles = new List(); if (packageFiles != null && packageFiles.Length > 0) { // copy package files to the remote SQL Server foreach (string packageFile in packageFiles) { string path = null; byte[] buffer = null; int offset = 0; do { // read package file buffer = FilesController.GetFileBinaryChunk(item.PackageId, packageFile, offset, FILE_BUFFER_LENGTH); // write remote backup file string tempPath = sql.AppendTempFileBinaryChunk(Path.GetFileName(packageFile), path, buffer); if (path == null) { path = tempPath; backupFiles.Add(path); } offset += FILE_BUFFER_LENGTH; } while (buffer.Length == FILE_BUFFER_LENGTH); } } else if (uploadedFiles != null && uploadedFiles.Length > 0) { // upladed files backupFiles.AddRange(uploadedFiles); } // restore if (backupFiles.Count > 0) sql.RestoreDatabase(item.Name, backupFiles.ToArray()); return 0; } catch (Exception ex) { throw TaskManager.WriteError(ex); } finally { TaskManager.CompleteTask(); } } public static int TruncateSqlDatabase(int itemId) { // check account int accountCheck = SecurityContext.CheckAccount(DemandAccount.NotDemo); if (accountCheck < 0) return accountCheck; // load original meta item SqlDatabase origItem = (SqlDatabase)PackageController.GetPackageItem(itemId); if (origItem == null) return BusinessErrorCodes.ERROR_MSSQL_DATABASES_PACKAGE_ITEM_NOT_FOUND; // place log record TaskManager.StartTask("SQL_DATABASE", "TRUNCATE", origItem.Name); TaskManager.ItemId = itemId; try { // get service DatabaseServer sql = GetDatabaseServer(origItem.ServiceId); // truncate database sql.TruncateDatabase(origItem.Name); return 0; } catch (Exception ex) { throw TaskManager.WriteError(ex); } finally { TaskManager.CompleteTask(); } } private static string[] GetSqlDatabasesArray(int packageId, string groupName) { List databases = GetSqlDatabases(packageId, groupName, false); string[] arr = new string[databases.Count]; for (int i = 0; i < databases.Count; i++) arr[i] = databases[i].Name; return arr; } public static DatabaseBrowserConfiguration GetDatabaseBrowserConfiguration(int packageId, string groupName) { DatabaseBrowserConfiguration config = new DatabaseBrowserConfiguration(); int serviceId = PackageController.GetPackageServiceId(packageId, groupName); if (serviceId == 0) return config; StringDictionary settings = ServerController.GetServiceSettings(serviceId); config.Enabled = !String.IsNullOrEmpty(settings["BrowseURL"]); return config; } public static DatabaseBrowserConfiguration GetDatabaseBrowserLogonScript(int packageId, string groupName, string username) { int serviceId = PackageController.GetPackageServiceId(packageId, groupName); if (serviceId == 0) return null; StringDictionary settings = ServerController.GetServiceSettings(serviceId); string url = settings["BrowseURL"]; string method = settings["BrowseMethod"]; string prms = settings["BrowseParameters"]; DatabaseBrowserConfiguration config = new DatabaseBrowserConfiguration(); config.Enabled = !String.IsNullOrEmpty(url); config.Method = method; prms = Utils.ReplaceStringVariable(prms, "server", settings["InternalAddress"]); // load database user SqlUser user = (SqlUser)PackageController.GetPackageItemByName(packageId, groupName, username, typeof(SqlUser)); if (user != null) { prms = Utils.ReplaceStringVariable(prms, "user", username); prms = Utils.ReplaceStringVariable(prms, "password", CryptoUtils.Decrypt(user.Password)); string[] lines = Utils.ParseDelimitedString(prms, '\n', '\r'); StringBuilder sb = new StringBuilder(); if (String.Compare(method, "get", true) == 0) { // GET sb.Append(url).Append("?"); foreach (string line in lines) sb.Append(line).Append("&"); config.GetData = sb.ToString(); } else { // POST sb.Append(""); sb.Append("
"); foreach (string line in lines) { // var indexOfSplit = line.IndexOf('='); // if (indexOfSplit == -1) continue; // sb.Append(""); } sb.Append("
"); sb.Append(""); config.PostData = sb.ToString(); } } return config; } #endregion #region Users public static DataSet GetRawSqlUsersPaged(int packageId, string groupName, string filterColumn, string filterValue, string sortColumn, int startRow, int maximumRows) { return PackageController.GetRawPackageItemsPaged(packageId, groupName, typeof(SqlUser), true, filterColumn, filterValue, sortColumn, startRow, maximumRows); } public static List GetSqlUsers(int packageId, string groupName, bool recursive) { List items = PackageController.GetPackageItemsByType( packageId, groupName, typeof(SqlUser), recursive); return items.ConvertAll( new Converter(ConvertItemToSqlUser)); } private static SqlUser ConvertItemToSqlUser(ServiceProviderItem item) { return (SqlUser)item; } public static SqlUser GetSqlUser(int itemId) { // load meta item SqlUser item = (SqlUser)PackageController.GetPackageItem(itemId); // load service item DatabaseServer sql = GetDatabaseServer(item.ServiceId); SqlUser user = sql.GetUser(item.Name, GetSqlDatabasesArray(item.PackageId, item.GroupName)); // add common properties user.Id = item.Id; user.PackageId = item.PackageId; user.ServiceId = item.ServiceId; user.Password = CryptoUtils.Decrypt(item.Password); user.GroupName = item.GroupName; return user; } public static int AddSqlUser(SqlUser item, string groupName) { // check account int accountCheck = SecurityContext.CheckAccount(DemandAccount.NotDemo | DemandAccount.IsActive); if (accountCheck < 0) return accountCheck; // check package int packageCheck = SecurityContext.CheckPackage(item.PackageId, DemandPackage.IsActive); if (packageCheck < 0) return packageCheck; // check quota QuotaValueInfo quota = PackageController.GetPackageQuota(item.PackageId, groupName + ".Users"); if (quota.QuotaExhausted) return BusinessErrorCodes.ERROR_MSSQL_USERS_RESOURCE_QUOTA_LIMIT; // check if mail resource is available int serviceId = PackageController.GetPackageServiceId(item.PackageId, groupName); if (serviceId == 0) return BusinessErrorCodes.ERROR_MSSQL_RESOURCE_UNAVAILABLE; // check package items if (PackageController.GetPackageItemByName(item.PackageId, groupName, item.Name, typeof(SqlUser)) != null) return BusinessErrorCodes.ERROR_MSSQL_USERS_PACKAGE_ITEM_EXISTS; // place log record TaskManager.StartTask("SQL_USER", "ADD", item.Name); TaskManager.WriteParameter("Provider", groupName); int itemId = default(int); try { // check service items DatabaseServer sql = GetDatabaseServer(serviceId); if (sql.UserExists(item.Name)) return BusinessErrorCodes.ERROR_MSSQL_USERS_SERVICE_ITEM_EXISTS; // add service item sql.CreateUser(item, item.Password); // save item item.Password = CryptoUtils.Encrypt(item.Password); item.ServiceId = serviceId; itemId = PackageController.AddPackageItem(item); TaskManager.ItemId = itemId; } catch (Exception ex) { TaskManager.WriteError(ex); // if (ex.Message.Contains("INVALID_USERNAME")) return BusinessErrorCodes.ERROR_MYSQL_INVALID_USER_NAME; // Return a generic error instead of default(int) itemId = BusinessErrorCodes.FAILED_EXECUTE_SERVICE_OPERATION; } finally { TaskManager.CompleteTask(); } return itemId; } public static int UpdateSqlUser(SqlUser item) { // check account int accountCheck = SecurityContext.CheckAccount(DemandAccount.NotDemo | DemandAccount.IsActive); if (accountCheck < 0) return accountCheck; // load original meta item SqlUser origItem = (SqlUser)PackageController.GetPackageItem(item.Id); if (origItem == null) return BusinessErrorCodes.ERROR_MSSQL_USERS_PACKAGE_ITEM_NOT_FOUND; // check package int packageCheck = SecurityContext.CheckPackage(origItem.PackageId, DemandPackage.IsActive); if (packageCheck < 0) return packageCheck; // place log record TaskManager.StartTask("SQL_USER", "UPDATE", origItem.Name); TaskManager.ItemId = item.Id; try { // get service DatabaseServer sql = GetDatabaseServer(origItem.ServiceId); // update service item sql.UpdateUser(item, GetSqlDatabasesArray(origItem.PackageId, origItem.GroupName)); // update meta item if (item.Password == "") item.Password = CryptoUtils.Decrypt(origItem.Password); item.Password = CryptoUtils.Encrypt(item.Password); PackageController.UpdatePackageItem(item); return 0; } catch (Exception ex) { TaskManager.WriteError(ex); // Return a generic error instead of re-throwing an exception return BusinessErrorCodes.FAILED_EXECUTE_SERVICE_OPERATION; } finally { TaskManager.CompleteTask(); } } public static int DeleteSqlUser(int itemId) { // check account int accountCheck = SecurityContext.CheckAccount(DemandAccount.NotDemo); if (accountCheck < 0) return accountCheck; // load original meta item SqlUser origItem = (SqlUser)PackageController.GetPackageItem(itemId); if (origItem == null) return BusinessErrorCodes.ERROR_MSSQL_USERS_PACKAGE_ITEM_NOT_FOUND; // place log record TaskManager.StartTask("SQL_USER", "DELETE", origItem.Name); TaskManager.ItemId = itemId; try { // get service DatabaseServer sql = GetDatabaseServer(origItem.ServiceId); // delete service item sql.DeleteUser(origItem.Name, GetSqlDatabasesArray(origItem.PackageId, origItem.GroupName)); // delete meta item PackageController.DeletePackageItem(origItem.Id); return 0; } catch (Exception ex) { TaskManager.WriteError(ex); // Return a generic error instead of re-throwing an exception return BusinessErrorCodes.FAILED_EXECUTE_SERVICE_OPERATION; } finally { TaskManager.CompleteTask(); } } #endregion #region IImportController Members public List GetImportableItems(int packageId, int itemTypeId, Type itemType, ResourceGroupInfo group) { List items = new List(); // get service id int serviceId = PackageController.GetPackageServiceId(packageId, group.GroupName); if (serviceId == 0) return items; DatabaseServer db = GetDatabaseServer(serviceId); if (itemType == typeof(SqlDatabase)) items.AddRange(db.GetDatabases()); else if (itemType == typeof(SqlUser)) items.AddRange(db.GetUsers()); return items; } public void ImportItem(int packageId, int itemTypeId, Type itemType, ResourceGroupInfo group, string itemName) { // get service id int serviceId = PackageController.GetPackageServiceId(packageId, group.GroupName); if (serviceId == 0) return; if (itemType == typeof(SqlDatabase)) { // import database SqlDatabase db = new SqlDatabase(); db.ServiceId = serviceId; db.PackageId = packageId; db.Name = itemName; db.GroupName = group.GroupName; PackageController.AddPackageItem(db); } else if (itemType == typeof(SqlUser)) { // import user SqlUser user = new SqlUser(); user.ServiceId = serviceId; user.PackageId = packageId; user.Name = itemName; user.GroupName = group.GroupName; user.Password = ""; PackageController.AddPackageItem(user); } } #endregion #region IBackupController Members public int BackupItem(string tempFolder, XmlWriter writer, ServiceProviderItem item, ResourceGroupInfo group) { if (item is SqlDatabase) { // backup database DatabaseServer sql = GetDatabaseServer(item.ServiceId); string backupName = String.Format("DatabaseBackup_{0}.zip", item.Id); string remoteBackupFile = sql.BackupDatabase(item.Name, backupName, true); // download remote backup string localBackupPath = Path.Combine(tempFolder, backupName); byte[] buffer = null; FileStream stream = new FileStream(localBackupPath, FileMode.Create, FileAccess.Write); int offset = 0; long length = 0; do { // read remote content buffer = sql.GetTempFileBinaryChunk(remoteBackupFile, offset, FILE_BUFFER_LENGTH); // write remote content stream.Write(buffer, 0, buffer.Length); length += buffer.Length; offset += FILE_BUFFER_LENGTH; } while (buffer.Length == FILE_BUFFER_LENGTH); stream.Close(); // add file pointer BackupController.WriteFileElement(writer, "DatabaseBackup", backupName, length); // store meta item SqlDatabase database = sql.GetDatabase(item.Name); XmlSerializer serializer = new XmlSerializer(typeof(SqlDatabase)); serializer.Serialize(writer, database); } else if (item is SqlUser) { // backup user DatabaseServer sql = GetDatabaseServer(item.ServiceId); SqlUser userItem = item as SqlUser; // store user info SqlUser user = sql.GetUser(item.Name, GetSqlDatabasesArray(item.PackageId, item.GroupName)); user.Password = userItem.Password; XmlSerializer serializer = new XmlSerializer(typeof(SqlUser)); serializer.Serialize(writer, user); } return 0; } public int RestoreItem(string tempFolder, XmlNode itemNode, int itemId, Type itemType, string itemName, int packageId, int serviceId, ResourceGroupInfo group) { if (itemType == typeof(SqlDatabase)) { DatabaseServer sql = GetDatabaseServer(serviceId); // extract meta item XmlSerializer serializer = new XmlSerializer(typeof(SqlDatabase)); SqlDatabase db = (SqlDatabase)serializer.Deserialize( new XmlNodeReader(itemNode.SelectSingleNode("SqlDatabase"))); // create database if required if (!sql.DatabaseExists(itemName)) { sql.CreateDatabase(db); } // copy database backup to remote server XmlNode fileNode = itemNode.SelectSingleNode("File[@name='DatabaseBackup']"); string backupFileName = fileNode.Attributes["path"].Value; long backupFileLength = Int64.Parse(fileNode.Attributes["size"].Value); string localBackupFilePath = Path.Combine(tempFolder, backupFileName); if (new FileInfo(localBackupFilePath).Length != backupFileLength) return -3; FileStream stream = new FileStream(localBackupFilePath, FileMode.Open, FileAccess.Read); byte[] buffer = new byte[FILE_BUFFER_LENGTH]; int readBytes = 0; long length = 0; string remoteBackupPath = null; do { // read package file readBytes = stream.Read(buffer, 0, FILE_BUFFER_LENGTH); length += readBytes; if (readBytes < FILE_BUFFER_LENGTH) // resize buffer Array.Resize(ref buffer, readBytes); // write remote backup file string tempPath = sql.AppendTempFileBinaryChunk(backupFileName, remoteBackupPath, buffer); if (remoteBackupPath == null) remoteBackupPath = tempPath; } while (readBytes == FILE_BUFFER_LENGTH); stream.Close(); // restore database sql.RestoreDatabase(itemName, new string[] { remoteBackupPath }); // add meta-item if required if (PackageController.GetPackageItemByName(packageId, group.GroupName, itemName, typeof(SqlDatabase)) == null) { db.PackageId = packageId; db.ServiceId = serviceId; db.GroupName = group.GroupName; PackageController.AddPackageItem(db); } } else if (itemType == typeof(SqlUser)) { DatabaseServer sql = GetDatabaseServer(serviceId); // extract meta item XmlSerializer serializer = new XmlSerializer(typeof(SqlUser)); SqlUser user = (SqlUser)serializer.Deserialize( new XmlNodeReader(itemNode.SelectSingleNode("SqlUser"))); // create user if required if (!sql.UserExists(itemName)) { sql.CreateUser(user, CryptoUtils.Decrypt(user.Password)); } // add meta-item if required if (PackageController.GetPackageItemByName(packageId, group.GroupName, itemName, typeof(SqlUser)) == null) { user.PackageId = packageId; user.ServiceId = serviceId; user.GroupName = group.GroupName; PackageController.AddPackageItem(user); } } return 0; } #endregion } }