diff --git a/WebsitePanel.Installer/Sources/WebsitePanel.Installer.sln b/WebsitePanel.Installer/Sources/WebsitePanel.Installer.sln index 6ded8966..2a9fa4c2 100644 --- a/WebsitePanel.Installer/Sources/WebsitePanel.Installer.sln +++ b/WebsitePanel.Installer/Sources/WebsitePanel.Installer.sln @@ -25,6 +25,9 @@ EndProject Project("{930C7802-8A8C-48F9-8165-68863BCCD9DD}") = "Setup.WIX", "Setup.WIX\Setup.WIX.wixproj", "{F963A4AF-CC72-4512-B636-829345C35318}" EndProject Project("{930C7802-8A8C-48F9-8165-68863BCCD9DD}") = "Setup.SchedulerService", "Setup.SchedulerService\Setup.SchedulerService.wixproj", "{EAD7C528-EA3D-40E8-9688-9F1D8DC8D758}" + ProjectSection(ProjectDependencies) = postProject + {24A4C231-73A9-4F03-ABAD-9A8FE5324495} = {24A4C231-73A9-4F03-ABAD-9A8FE5324495} + EndProjectSection EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "WebsitePanel.SchedulerServiceInstaller", "WebsitePanel.SchedulerServiceInstaller\WebsitePanel.SchedulerServiceInstaller.csproj", "{24A4C231-73A9-4F03-ABAD-9A8FE5324495}" EndProject diff --git a/WebsitePanel.Installer/Sources/WebsitePanel.SchedulerServiceInstaller/CustomAction.cs b/WebsitePanel.Installer/Sources/WebsitePanel.SchedulerServiceInstaller/CustomAction.cs index f5655efd..eff618a7 100644 --- a/WebsitePanel.Installer/Sources/WebsitePanel.SchedulerServiceInstaller/CustomAction.cs +++ b/WebsitePanel.Installer/Sources/WebsitePanel.SchedulerServiceInstaller/CustomAction.cs @@ -35,6 +35,7 @@ using System.Linq; using System.ServiceProcess; using System.Text.RegularExpressions; using Microsoft.Deployment.WindowsInstaller; +using WebsitePanel.Setup; namespace WebsitePanel.SchedulerServiceInstaller { @@ -72,11 +73,19 @@ namespace WebsitePanel.SchedulerServiceInstaller { try { - if (!ServiceController.GetServices().Any(s => s.DisplayName.Equals("WebsitePanel Scheduler", StringComparison.CurrentCultureIgnoreCase))) + var schedulerService = + ServiceController.GetServices().FirstOrDefault( + s => s.DisplayName.Equals("WebsitePanel Scheduler", StringComparison.CurrentCultureIgnoreCase)); + + if (schedulerService != null) { - ManagedInstallerClass.InstallHelper(new[] {"/i", Path.Combine(installFolder, "WebsitePanel.SchedulerService.exe")}); + StopService(schedulerService.ServiceName); + + SecurityUtils.DeleteService(schedulerService.ServiceName); } + ManagedInstallerClass.InstallHelper(new[] { "/i", Path.Combine(installFolder, "WebsitePanel.SchedulerService.exe") }); + StartService("WebsitePanel Scheduler"); } catch (Exception) @@ -122,6 +131,17 @@ namespace WebsitePanel.SchedulerServiceInstaller } } + private static void StopService(string serviceName) + { + var sc = new ServiceController(serviceName); + + if (sc.Status == ServiceControllerStatus.Running) + { + sc.Stop(); + sc.WaitForStatus(ServiceControllerStatus.Stopped); + } + } + private static void StartService(string serviceName) { var sc = new ServiceController(serviceName); diff --git a/WebsitePanel.Installer/Sources/WebsitePanel.SchedulerServiceInstaller/WebsitePanel.SchedulerServiceInstaller.csproj b/WebsitePanel.Installer/Sources/WebsitePanel.SchedulerServiceInstaller/WebsitePanel.SchedulerServiceInstaller.csproj index 22f11548..10824162 100644 --- a/WebsitePanel.Installer/Sources/WebsitePanel.SchedulerServiceInstaller/WebsitePanel.SchedulerServiceInstaller.csproj +++ b/WebsitePanel.Installer/Sources/WebsitePanel.SchedulerServiceInstaller/WebsitePanel.SchedulerServiceInstaller.csproj @@ -37,6 +37,7 @@ + @@ -47,6 +48,12 @@ + + + {3951C0EC-BD98-450E-B228-CDBE5BD4AD49} + WebsitePanel.Setup + + \ No newline at end of file diff --git a/WebsitePanel.Installer/Sources/WebsitePanel.Setup/Common/SecurityUtils.cs b/WebsitePanel.Installer/Sources/WebsitePanel.Setup/Common/SecurityUtils.cs index e69f9bbb..668e7875 100644 --- a/WebsitePanel.Installer/Sources/WebsitePanel.Setup/Common/SecurityUtils.cs +++ b/WebsitePanel.Installer/Sources/WebsitePanel.Setup/Common/SecurityUtils.cs @@ -27,6 +27,7 @@ // SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. using System; +using System.IO; using System.Text; using System.DirectoryServices; using System.DirectoryServices.ActiveDirectory; @@ -1099,7 +1100,18 @@ namespace WebsitePanel.Setup } #endregion - } + + #region Windows Services + + public static void DeleteService(string serviceName) + { + var wmiService = wmi.GetObject(String.Format("Win32_Service.Name='{0}'", serviceName)); + + wmiService.Delete(); + } + + #endregion + } #region Enums [Flags] diff --git a/WebsitePanel/Database/update_db.sql b/WebsitePanel/Database/update_db.sql index 0d98ef0e..af169668 100644 --- a/WebsitePanel/Database/update_db.sql +++ b/WebsitePanel/Database/update_db.sql @@ -2604,6 +2604,15 @@ BEGIN END GO +-- DNS.2013 + +IF NOT EXISTS ( SELECT * FROM [dbo].[Providers] WHERE [ProviderID] = 410 ) +BEGIN + INSERT [dbo].[Providers] ([ProviderID], [GroupID], [ProviderName], [DisplayName], [ProviderType], [EditorControl], [DisableAutoDiscovery]) VALUES + (410, 7, N'MSDNS.2012', N'Microsoft DNS Server 2012+', N'WebsitePanel.Providers.DNS.MsDNS2012, WebsitePanel.Providers.DNS.MsDNS2012', N'MSDNS', NULL) +END +GO + -- CRM Provider fix UPDATE Providers SET EditorControl = 'CRM2011' Where ProviderID = 1201; @@ -2731,7 +2740,7 @@ WHERE END GO - +IF NOT EXISTS (SELECT * FROM [dbo].[Providers] WHERE [DisplayName] = 'MySQL Server 5.6') -- CRM Quota diff --git a/WebsitePanel/Lib/Microsoft.Management.Infrastructure.dll b/WebsitePanel/Lib/Microsoft.Management.Infrastructure.dll new file mode 100644 index 00000000..9c72405b Binary files /dev/null and b/WebsitePanel/Lib/Microsoft.Management.Infrastructure.dll differ diff --git a/WebsitePanel/Lib/References/MySQL/MySql.Data.dll b/WebsitePanel/Lib/References/MySQL/MySql.Data.dll index 088ef1c0..c029eae7 100644 Binary files a/WebsitePanel/Lib/References/MySQL/MySql.Data.dll and b/WebsitePanel/Lib/References/MySQL/MySql.Data.dll differ diff --git a/WebsitePanel/Sources/WebsitePanel.EnterpriseServer.Code/EnterpriseStorage/EnterpriseStorageController.cs b/WebsitePanel/Sources/WebsitePanel.EnterpriseServer.Code/EnterpriseStorage/EnterpriseStorageController.cs index dec560e2..c4b90813 100644 --- a/WebsitePanel/Sources/WebsitePanel.EnterpriseServer.Code/EnterpriseStorage/EnterpriseStorageController.cs +++ b/WebsitePanel/Sources/WebsitePanel.EnterpriseServer.Code/EnterpriseStorage/EnterpriseStorageController.cs @@ -66,12 +66,12 @@ namespace WebsitePanel.EnterpriseServer public static ResultObject DeleteEnterpriseStorage(int packageId, int itemId) { - return DeleteEnterpriseStorageInternal(packageId,itemId); + return DeleteEnterpriseStorageInternal(packageId, itemId); } public static SystemFile[] GetFolders(int itemId) { - return GetFoldersInternal(itemId); + return GetFoldersInternal(itemId); } public static SystemFile GetFolder(int itemId, string folderName) @@ -102,7 +102,7 @@ namespace WebsitePanel.EnterpriseServer public static ResultObject DeleteFolder(int itemId, string folderName) { return DeleteFolderInternal(itemId, folderName); - } + } public static List SearchESAccounts(int itemId, string filterColumn, string filterValue, string sortColumn) { @@ -121,7 +121,7 @@ namespace WebsitePanel.EnterpriseServer public static ESPermission[] GetFolderPermission(int itemId, string folder) { - return ConvertToESPermission(itemId,GetFolderWebDavRulesInternal(itemId, folder)); + return ConvertToESPermission(itemId, GetFolderWebDavRulesInternal(itemId, folder)); } public static bool CheckFileServicesInstallation(int serviceId) @@ -144,7 +144,7 @@ namespace WebsitePanel.EnterpriseServer public static bool GetDirectoryBrowseEnabled(int itemId, string siteId) { - return GetDirectoryBrowseEnabledInternal(itemId, siteId); + return GetDirectoryBrowseEnabledInternal(itemId, siteId); } public static void SetDirectoryBrowseEnabled(int itemId, string siteId, bool enabled) @@ -164,10 +164,10 @@ namespace WebsitePanel.EnterpriseServer public static int DeleteWebDavDirectory(int packageId, string site, string vdirName) { return DeleteWebDavDirectoryInternal(packageId, site, vdirName); - } + } #endregion - + #endregion protected static bool CheckUsersDomainExistsInternal(int itemId) @@ -227,7 +227,7 @@ namespace WebsitePanel.EnterpriseServer string usersDomain = esSesstings["UsersDomain"]; WebServer web = GetWebServer(packageId); - + if (!web.VirtualDirectoryExists(usersDomain, org.OrganizationId)) { checkResult = false; @@ -261,16 +261,16 @@ namespace WebsitePanel.EnterpriseServer EnterpriseStorageController.AddWebDavDirectory(packageId, usersDomain, org.OrganizationId, homePath); - int osId = PackageController.GetPackageServiceId(packageId, ResourceGroups.Os); - bool enableHardQuota = (esSesstings["enablehardquota"] != null) - ? bool.Parse(esSesstings["enablehardquota"]) - : false; + //int osId = PackageController.GetPackageServiceId(packageId, ResourceGroups.Os); + //bool enableHardQuota = (esSesstings["enablehardquota"] != null) + // ? bool.Parse(esSesstings["enablehardquota"]) + // : false; - if (enableHardQuota && osId != 0 && OperatingSystemController.CheckFileServicesInstallation(osId)) - { - FilesController.SetFolderQuota(packageId, Path.Combine(usersHome, org.OrganizationId), - locationDrive, Quotas.ENTERPRISESTORAGE_DISKSTORAGESPACE); - } + //if (enableHardQuota && osId != 0 && OperatingSystemController.CheckFileServicesInstallation(osId)) + //{ + // FilesController.SetFolderQuota(packageId, Path.Combine(usersHome, org.OrganizationId), + // locationDrive, Quotas.ENTERPRISESTORAGE_DISKSTORAGESPACE); + //} } } catch (Exception ex) @@ -347,7 +347,7 @@ namespace WebsitePanel.EnterpriseServer Organization org = OrganizationController.GetOrganization(itemId); if (org == null) { - return null; + return new SystemFile[0]; } EnterpriseStorage es = GetEnterpriseStorage(GetEnterpriseStorageServiceID(org.PackageId)); @@ -418,6 +418,8 @@ namespace WebsitePanel.EnterpriseServer EnterpriseStorage es = GetEnterpriseStorage(GetEnterpriseStorageServiceID(org.PackageId)); es.CreateFolder(org.OrganizationId, folderName); + + UpdateESHardQuota(org.PackageId); } catch (Exception ex) { @@ -473,7 +475,7 @@ namespace WebsitePanel.EnterpriseServer return result; } - + protected static List SearchESAccountsInternal(int itemId, string filterColumn, string filterValue, string sortColumn) { // load organization @@ -547,7 +549,7 @@ namespace WebsitePanel.EnterpriseServer return result; } - + #region WebDav protected static int AddWebDavDirectoryInternal(int packageId, string site, string vdirName, string contentpath) @@ -579,11 +581,6 @@ namespace WebsitePanel.EnterpriseServer dir.HttpErrors = null; dir.MimeMaps = null; - int serviceId = PackageController.GetPackageServiceId(packageId, ResourceGroups.Web); - - if (serviceId == -1) - return serviceId; - // create directory WebServer web = GetWebServer(packageId); @@ -755,7 +752,7 @@ namespace WebsitePanel.EnterpriseServer var account = ObjectUtils.FillObjectFromDataReader(DataProvider.GetExchangeAccountByAccountName(itemId, permission.Account)); - if (account.AccountType == ExchangeAccountType.SecurityGroup + if (account.AccountType == ExchangeAccountType.SecurityGroup || account.AccountType == ExchangeAccountType.DefaultSecurityGroup) { rule.Roles.Add(permission.Account); @@ -838,6 +835,33 @@ namespace WebsitePanel.EnterpriseServer } + private static void UpdateESHardQuota(int packageId) + { + int esServiceId = PackageController.GetPackageServiceId(packageId, ResourceGroups.EnterpriseStorage); + + if (esServiceId != 0) + { + + StringDictionary esSesstings = ServerController.GetServiceSettings(esServiceId); + + string usersHome = esSesstings["UsersHome"]; + string usersDomain = esSesstings["UsersDomain"]; + string locationDrive = esSesstings["LocationDrive"]; + + string homePath = string.Format("{0}:\\{1}", locationDrive, usersHome); + + int osId = PackageController.GetPackageServiceId(packageId, ResourceGroups.Os); + bool enableHardQuota = (esSesstings["enablehardquota"] != null) + ? bool.Parse(esSesstings["enablehardquota"]) + : false; + + if (enableHardQuota && osId != 0 && OperatingSystemController.CheckFileServicesInstallation(osId)) + { + FilesController.SetFolderQuota(packageId, usersHome, locationDrive, Quotas.ENTERPRISESTORAGE_DISKSTORAGESPACE); + } + } + } + /// /// Get webserver (IIS) installed on server connected with packageId /// @@ -847,15 +871,15 @@ namespace WebsitePanel.EnterpriseServer { try { - var group = ServerController.GetResourceGroupByName(ResourceGroups.Web); + var webGroup = ServerController.GetResourceGroupByName(ResourceGroups.Web); + var webProviders = ServerController.GetProvidersByGroupID(webGroup.GroupId); + var esServiceInfo = ServerController.GetServiceInfo(GetEnterpriseStorageServiceID(packageId)); - var webProviders = ServerController.GetProvidersByGroupID(group.GroupId); - - var package = PackageController.GetPackage(packageId); + var serverId = esServiceInfo.ServerId; foreach (var webProvider in webProviders) { - BoolResult result = ServerController.IsInstalled(package.ServerId, webProvider.ProviderId); + BoolResult result = ServerController.IsInstalled(serverId, webProvider.ProviderId); if (result.IsSuccess && result.Value) { @@ -867,7 +891,12 @@ namespace WebsitePanel.EnterpriseServer cnfg.ProviderSettings.ProviderName = webProvider.DisplayName; cnfg.ProviderSettings.ProviderType = webProvider.ProviderType; - ServiceProviderProxy.ServerInit(web, cnfg, package.ServerId); + //// set service settings + //StringDictionary serviceSettings = ServerController.GetServiceSettings(serviceId); + //foreach (string key in serviceSettings.Keys) + // cnfg.ProviderSettings.Settings[key] = serviceSettings[key]; + + ServiceProviderProxy.ServerInit(web, cnfg, serverId); return web; } diff --git a/WebsitePanel/Sources/WebsitePanel.EnterpriseServer.Code/ExchangeServer/ExchangeServerController.cs b/WebsitePanel/Sources/WebsitePanel.EnterpriseServer.Code/ExchangeServer/ExchangeServerController.cs index e533a752..2070d35c 100644 --- a/WebsitePanel/Sources/WebsitePanel.EnterpriseServer.Code/ExchangeServer/ExchangeServerController.cs +++ b/WebsitePanel/Sources/WebsitePanel.EnterpriseServer.Code/ExchangeServer/ExchangeServerController.cs @@ -1235,7 +1235,7 @@ namespace WebsitePanel.EnterpriseServer DataProvider.DeleteExchangeAccount(itemId, accountId); } - +/* private static string BuildAccountName(string orgId, string name) { string accountName = name = name.Replace(" ", ""); @@ -1271,7 +1271,7 @@ namespace WebsitePanel.EnterpriseServer } } - +*/ #endregion @@ -3041,7 +3041,7 @@ namespace WebsitePanel.EnterpriseServer if (idx > -1) name = email.Substring(0, idx); - string accountName = BuildAccountName(org.OrganizationId, name); + string accountName = OrganizationController.BuildAccountNameEx(org, name); // add contact int exchangeServiceId = GetExchangeServiceID(org.PackageId); @@ -3375,7 +3375,7 @@ namespace WebsitePanel.EnterpriseServer int packageCheck = SecurityContext.CheckPackage(org.PackageId, DemandPackage.IsActive); if (packageCheck < 0) return packageCheck; - string accountName = OrganizationController.BuildAccountNameWithOrgId(org.OrganizationId, name, org.ServiceId); + string accountName = OrganizationController.BuildAccountNameEx(org, name); // add account // add contact @@ -4179,7 +4179,7 @@ namespace WebsitePanel.EnterpriseServer if (String.IsNullOrEmpty(name)) name = Utils.CleanIdentifier(folderName); - string accountName = BuildAccountName(org.OrganizationId, name); + string accountName = OrganizationController.BuildAccountNameEx(org, name); // add mailbox int exchangeServiceId = GetExchangeServiceID(org.PackageId); @@ -4324,7 +4324,7 @@ namespace WebsitePanel.EnterpriseServer if (EmailAddressExists(email)) return BusinessErrorCodes.ERROR_EXCHANGE_EMAIL_EXISTS; - string accountName = BuildAccountName(org.OrganizationId, name); + string accountName = OrganizationController.BuildAccountNameEx(org, name); int exchangeServiceId = GetExchangeServiceID(org.PackageId); ExchangeServer exchange = GetExchangeServer(exchangeServiceId, org.ServiceId); diff --git a/WebsitePanel/Sources/WebsitePanel.EnterpriseServer.Code/HostedSolution/OrganizationController.cs b/WebsitePanel/Sources/WebsitePanel.EnterpriseServer.Code/HostedSolution/OrganizationController.cs index 5ed2188e..4239f90a 100644 --- a/WebsitePanel/Sources/WebsitePanel.EnterpriseServer.Code/HostedSolution/OrganizationController.cs +++ b/WebsitePanel/Sources/WebsitePanel.EnterpriseServer.Code/HostedSolution/OrganizationController.cs @@ -397,7 +397,7 @@ namespace WebsitePanel.EnterpriseServer { foreach (AdditionalGroup additionalGroup in GetAdditionalGroups(settings.UserId)) { - string additionalGroupName = BuildAccountNameWithOrgId(org.OrganizationId, additionalGroup.GroupName.Replace(" ", ""), org.ServiceId); + string additionalGroupName = BuildAccountNameEx(org, additionalGroup.GroupName.Replace(" ", "")); if (orgProxy.CreateSecurityGroup(org.OrganizationId, additionalGroupName) == 0) { @@ -1383,7 +1383,7 @@ namespace WebsitePanel.EnterpriseServer return BusinessErrorCodes.ERROR_EXCHANGE_EMAIL_EXISTS; // load organization - Organization org = GetOrganization(itemId); + WebsitePanel.Providers.HostedSolution.Organization org = GetOrganization(itemId); if (org == null) { @@ -1408,7 +1408,7 @@ namespace WebsitePanel.EnterpriseServer Organizations orgProxy = GetOrganizationProxy(org.ServiceId); string upn = string.Format("{0}@{1}", name, domain); - string sAMAccountName = AppendOrgId(serviceSettings) ? BuildAccountNameWithOrgId(org.OrganizationId, name, org.ServiceId) : BuildAccountName(org.OrganizationId, name, org.ServiceId); + string sAMAccountName = BuildAccountNameEx(org, name); TaskManager.Write("accountName :" + sAMAccountName); TaskManager.Write("upn :" + upn); @@ -1446,6 +1446,15 @@ namespace WebsitePanel.EnterpriseServer return userId; } + + public static string BuildAccountNameEx(Organization org, string name) + { + StringDictionary serviceSettings = ServerController.GetServiceSettings(org.ServiceId); + + return AppendOrgId(serviceSettings) ? BuildAccountNameWithOrgId(org.OrganizationId, name, org.ServiceId) : BuildAccountName(org.OrganizationId, name, org.ServiceId); + } + + /// Checks should or not user name include organization id. /// The service settings. /// True - if organization id should be appended. @@ -2370,8 +2379,8 @@ namespace WebsitePanel.EnterpriseServer Organizations orgProxy = GetOrganizationProxy(org.ServiceId); - string groupName = BuildAccountNameWithOrgId(org.OrganizationId, displayName.Replace(" ", ""), org.ServiceId); - + string groupName = BuildAccountNameEx(org, displayName.Replace(" ", "")); + TaskManager.Write("accountName :" + groupName); if (orgProxy.CreateSecurityGroup(org.OrganizationId, groupName) == 0) diff --git a/WebsitePanel/Sources/WebsitePanel.EnterpriseServer.Code/Packages/PackageController.cs b/WebsitePanel/Sources/WebsitePanel.EnterpriseServer.Code/Packages/PackageController.cs index 1b89f3dc..cda59b87 100644 --- a/WebsitePanel/Sources/WebsitePanel.EnterpriseServer.Code/Packages/PackageController.cs +++ b/WebsitePanel/Sources/WebsitePanel.EnterpriseServer.Code/Packages/PackageController.cs @@ -489,7 +489,7 @@ namespace WebsitePanel.EnterpriseServer ServerController.AddServiceDNSRecords(packageId, ResourceGroups.VPSForPC, domain, ""); } } - + if (createInstantAlias) ServerController.CreateDomainInstantAlias("", domainId); @@ -994,7 +994,7 @@ namespace WebsitePanel.EnterpriseServer { DataProvider.UpdatePackageBandwidthUpdate(packageId, updateDate); } - + // This gets the system quota and updates the home folder with the value public static void UpdatePackageHardQuota(int packageId) { @@ -1019,6 +1019,33 @@ namespace WebsitePanel.EnterpriseServer } + //public static void UpdateESHardQuota(int packageId) + //{ + // int esServiceId = PackageController.GetPackageServiceId(packageId, ResourceGroups.EnterpriseStorage); + + // if (esServiceId != 0) + // { + + // StringDictionary esSesstings = ServerController.GetServiceSettings(esServiceId); + + // string usersHome = esSesstings["UsersHome"]; + // string usersDomain = esSesstings["UsersDomain"]; + // string locationDrive = esSesstings["LocationDrive"]; + + // string homePath = string.Format("{0}:\\{1}", locationDrive, usersHome); + + // int osId = PackageController.GetPackageServiceId(packageId, ResourceGroups.Os); + // bool enableHardQuota = (esSesstings["enablehardquota"] != null) + // ? bool.Parse(esSesstings["enablehardquota"]) + // : false; + + // if (enableHardQuota && osId != 0 && OperatingSystemController.CheckFileServicesInstallation(osId)) + // { + // FilesController.SetFolderQuota(packageId, usersHome, locationDrive, Quotas.ENTERPRISESTORAGE_DISKSTORAGESPACE); + // } + // } + //} + #endregion #region Package Add-ons @@ -1061,7 +1088,7 @@ namespace WebsitePanel.EnterpriseServer if (result.Result < 0) result.Result = SecurityContext.CheckAccount(DemandAccount.NotDemo | DemandAccount.IsActive | DemandAccount.IsResellerCSR); - + if (result.Result < 0) return result; int addonId = 0; @@ -1108,7 +1135,6 @@ namespace WebsitePanel.EnterpriseServer // Update the Hard quota on home folder in case it was enabled and in case there was a change in disk space UpdatePackageHardQuota(addon.PackageId); - return result; } @@ -1119,12 +1145,13 @@ namespace WebsitePanel.EnterpriseServer | DemandAccount.IsReseller); if (accountCheck < 0) return accountCheck; - - // Update the Hard quota on home folder in case it was enabled and in case there was a change in disk space - UpdatePackageHardQuota(GetPackageAddon(packageAddonId).PackageId); + var packageId = GetPackageAddon(packageAddonId).PackageId; DataProvider.DeletePackageAddon(SecurityContext.User.UserId, packageAddonId); + // Update the Hard quota on home folder in case it was enabled and in case there was a change in disk space + UpdatePackageHardQuota(packageId); + return 0; } @@ -2075,7 +2102,7 @@ namespace WebsitePanel.EnterpriseServer } items["Addons"] = addOns; - + // package contexts Hashtable cntxs = new Hashtable(); foreach (PackageInfo package in packages) diff --git a/WebsitePanel/Sources/WebsitePanel.Providers.DNS.MsDNS2012/DnsCommands.cs b/WebsitePanel/Sources/WebsitePanel.Providers.DNS.MsDNS2012/DnsCommands.cs new file mode 100644 index 00000000..52e0e367 --- /dev/null +++ b/WebsitePanel/Sources/WebsitePanel.Providers.DNS.MsDNS2012/DnsCommands.cs @@ -0,0 +1,315 @@ +// Copyright (c) 2012 - 2013, 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.Linq; +using System.Management.Automation; +using System.Management.Automation.Runspaces; +using System.Net; +using WebsitePanel.Server.Utils; + +namespace WebsitePanel.Providers.DNS +{ + /// This class wraps MS DNS server PowerShell commands used by the WebsitePanel. + internal static class DnsCommands + { + /// Add parameter to PS command + /// command + /// Parameter name + /// Parameter value + /// Same command + private static Command addParam( this Command cmd, string name, object value ) + { + cmd.Parameters.Add( name, value ); + return cmd; + } + + /// Add parameter without value to the PS command + /// command + /// Parameter name + /// Same command + private static Command addParam( this Command cmd, string name ) + { + // http://stackoverflow.com/a/10304080/126995 + cmd.Parameters.Add( name, true ); + return cmd; + } + + /// Create "Where-Object -Property ... -eq -Value ..." command + /// + /// + /// + private static Command where( string property, object value ) + { + return new Command( "Where-Object" ) + .addParam( "Property", property ) + .addParam( "eq" ) + .addParam( "Value", value ); + } + + /// Test-DnsServer -IPAddress 127.0.0.1 + /// PowerShell host to use + /// true if localhost is an MS DNS server + public static bool Test_DnsServer( this PowerShellHelper ps ) + { + if( null == ps ) + throw new ArgumentNullException( "ps" ); + + var cmd = new Command( "Test-DnsServer" ) + .addParam( "IPAddress", IPAddress.Loopback ); + + PSObject res = ps.RunPipeline( cmd ).FirstOrDefault(); + + if( null == res || null == res.Properties ) + return false; + PSPropertyInfo p = res.Properties[ "Result" ]; + if( null == p || null == p.Value ) + return false; + return p.Value.ToString() == "Success"; + } + + #region Zones + + /// Get-DnsServerZone | Select-Object -Property ZoneName + /// Only primary DNS zones are returned + /// Array of zone names + public static string[] Get_DnsServerZone_Names( this PowerShellHelper ps ) + { + var allZones = ps.RunPipeline( new Command( "Get-DnsServerZone" ), + where( "IsAutoCreated", false ) ); + + string[] res = allZones + .Select( pso => new + { + name = (string)pso.Properties[ "ZoneName" ].Value, + type = (string)pso.Properties[ "ZoneType" ].Value + } ) + .Where( obj => obj.type == "Primary" ) + .Select( obj => obj.name ) + .ToArray(); + + Log.WriteInfo( "Get_DnsServerZone_Names: {{{0}}}", String.Join( ", ", res ) ); + return res; + } + + /// Returns true if the specified zone exists. + /// The PS pipeline being run: Get-DnsServerZone | Where-Object -Property ZoneName -eq -Value "name" + /// + /// + /// + public static bool ZoneExists( this PowerShellHelper ps, string name ) + { + Log.WriteStart( "ZoneExists {0}", name ); + bool res = ps.RunPipeline( new Command( "Get-DnsServerZone" ), + where( "ZoneName", name ) ) + .Any(); + Log.WriteEnd( "ZoneExists: {0}", res ); + return res; + } + + /* public enum eReplicationScope: byte + { + Custom, Domain, Forest, Legacy + } */ + + /// + /// + /// + /// Specifies a partition on which to store an Active Directory-integrated zone. + /// + public static void Add_DnsServerPrimaryZone( this PowerShellHelper ps, string zoneName, string[] secondaryServers ) + { + Log.WriteStart( "Add_DnsServerPrimaryZone {0} {{{1}}}", zoneName, String.Join( ", ", secondaryServers ) ); + + // Add-DnsServerPrimaryZone -Name zzz.com -ZoneFile zzz.com.dns + var cmd = new Command( "Add-DnsServerPrimaryZone" ); + cmd.addParam( "Name", zoneName ); + cmd.addParam( "ZoneFile", zoneName + ".dns" ); + ps.RunPipeline( cmd ); + + // Set-DnsServerPrimaryZone -Name zzz.com -SecureSecondaries ... -Notify ... Servers .. + cmd = new Command( "Set-DnsServerPrimaryZone" ); + cmd.addParam( "Name", zoneName ); + + if( secondaryServers == null || secondaryServers.Length == 0 ) + { + // transfers are not allowed + // inParams2[ "SecureSecondaries" ] = 3; + // inParams2[ "Notify" ] = 0; + cmd.addParam( "SecureSecondaries", "NoTransfer" ); + cmd.addParam( "Notify", "NoNotify" ); + } + else if( secondaryServers.Length == 1 && secondaryServers[ 0 ] == "*" ) + { + // allowed transfer from all servers + // inParams2[ "SecureSecondaries" ] = 0; + // inParams2[ "Notify" ] = 1; + cmd.addParam( "SecureSecondaries", "TransferAnyServer" ); + cmd.addParam( "Notify", "Notify" ); + } + else + { + // allowed transfer from specified servers + // inParams2[ "SecureSecondaries" ] = 2; + // inParams2[ "SecondaryServers" ] = secondaryServers; + // inParams2[ "NotifyServers" ] = secondaryServers; + // inParams2[ "Notify" ] = 2; + cmd.addParam( "SecureSecondaries", "TransferToSecureServers" ); + cmd.addParam( "Notify", "NotifyServers" ); + cmd.addParam( "SecondaryServers", secondaryServers ); + cmd.addParam( "NotifyServers", secondaryServers ); + } + ps.RunPipeline( cmd ); + Log.WriteEnd( "Add_DnsServerPrimaryZone" ); + } + + /// Call Add-DnsServerSecondaryZone cmdlet + /// + /// a name of a zone + /// an array of IP addresses of the master servers of the zone. You can use both IPv4 and IPv6. + public static void Add_DnsServerSecondaryZone( this PowerShellHelper ps, string zoneName, string[] masterServers ) + { + // Add-DnsServerSecondaryZone -Name zzz.com -ZoneFile zzz.com.dns -MasterServers ... + var cmd = new Command( "Add-DnsServerSecondaryZone" ); + cmd.addParam( "Name", zoneName ); + cmd.addParam( "ZoneFile", zoneName + ".dns" ); + cmd.addParam( "MasterServers", masterServers ); + ps.RunPipeline( cmd ); + } + + public static void Remove_DnsServerZone( this PowerShellHelper ps, string zoneName ) + { + var cmd = new Command( "Remove-DnsServerZone" ); + cmd.addParam( "Name", zoneName ); + cmd.addParam( "Force" ); + ps.RunPipeline( cmd ); + } + #endregion + + /// Get all records, except the SOA + /// + /// Name of the zone + /// Array of records + public static DnsRecord[] GetZoneRecords( this PowerShellHelper ps, string zoneName ) + { + // Get-DnsServerResourceRecord -ZoneName xxxx.com + var allRecords = ps.RunPipeline( new Command( "Get-DnsServerResourceRecord" ).addParam( "ZoneName", zoneName ) ); + + return allRecords.Select( o => o.asDnsRecord( zoneName ) ) + .Where( r => null != r ) + .Where( r => r.RecordType != DnsRecordType.SOA ) + // .Where( r => !( r.RecordName == "@" && DnsRecordType.NS == r.RecordType ) ) + .ToArray(); + } + + #region Records add / remove + + public static void Add_DnsServerResourceRecordA( this PowerShellHelper ps, string zoneName, string Name, string address ) + { + var cmd = new Command( "Add-DnsServerResourceRecordA" ); + cmd.addParam( "ZoneName", zoneName ); + cmd.addParam( "Name", Name ); + cmd.addParam( "IPv4Address", address ); + ps.RunPipeline( cmd ); + } + + public static void Add_DnsServerResourceRecordAAAA( this PowerShellHelper ps, string zoneName, string Name, string address ) + { + var cmd = new Command( "Add-DnsServerResourceRecordAAAA" ); + cmd.addParam( "ZoneName", zoneName ); + cmd.addParam( "Name", Name ); + cmd.addParam( "IPv6Address", address ); + ps.RunPipeline( cmd ); + } + + public static void Add_DnsServerResourceRecordCName( this PowerShellHelper ps, string zoneName, string Name, string alias ) + { + var cmd = new Command( "Add-DnsServerResourceRecordCName" ); + cmd.addParam( "ZoneName", zoneName ); + cmd.addParam( "Name", Name ); + cmd.addParam( "HostNameAlias", alias ); + ps.RunPipeline( cmd ); + } + + public static void Add_DnsServerResourceRecordMX( this PowerShellHelper ps, string zoneName, string Name, string mx, UInt16 pref ) + { + var cmd = new Command( "Add-DnsServerResourceRecordMX" ); + cmd.addParam( "ZoneName", zoneName ); + cmd.addParam( "Name", Name ); + cmd.addParam( "MailExchange", mx ); + cmd.addParam( "Preference", pref ); + ps.RunPipeline( cmd ); + } + + public static void Add_DnsServerResourceRecordNS( this PowerShellHelper ps, string zoneName, string Name, string NameServer ) + { + var cmd = new Command( "Add-DnsServerResourceRecord" ); + cmd.addParam( "ZoneName", zoneName ); + cmd.addParam( "Name", Name ); + cmd.addParam( "NS" ); + cmd.addParam( "NameServer", NameServer ); + ps.RunPipeline( cmd ); + } + + public static void Add_DnsServerResourceRecordTXT( this PowerShellHelper ps, string zoneName, string Name, string txt ) + { + var cmd = new Command( "Add-DnsServerResourceRecord" ); + cmd.addParam( "ZoneName", zoneName ); + cmd.addParam( "Name", Name ); + cmd.addParam( "Txt" ); + cmd.addParam( "DescriptiveText", txt ); + ps.RunPipeline( cmd ); + } + + public static void Add_DnsServerResourceRecordSRV( this PowerShellHelper ps, string zoneName, string Name, string DomainName, UInt16 Port, UInt16 Priority, UInt16 Weight ) + { + var cmd = new Command( "Add-DnsServerResourceRecord" ); + cmd.addParam( "ZoneName", zoneName ); + cmd.addParam( "Name", Name ); + cmd.addParam( "Srv" ); + cmd.addParam( "DomainName", DomainName ); + cmd.addParam( "Port", Port ); + cmd.addParam( "Priority", Priority ); + cmd.addParam( "Weight", Weight ); + ps.RunPipeline( cmd ); + } + + public static void Remove_DnsServerResourceRecord( this PowerShellHelper ps, string zoneName, string Name, string type ) + { + // Remove-DnsServerResourceRecord -ZoneName xxxx.com -Name "@" -RRType Soa -Force + var cmd = new Command( "Remove-DnsServerResourceRecord" ); + cmd.addParam( "ZoneName", zoneName ); + cmd.addParam( "Name", Name ); + cmd.addParam( "RRType", type ); + cmd.addParam( "Force" ); + ps.RunPipeline( cmd ); + } + + #endregion + } +} \ No newline at end of file diff --git a/WebsitePanel/Sources/WebsitePanel.Providers.DNS.MsDNS2012/MsDNS.cs b/WebsitePanel/Sources/WebsitePanel.Providers.DNS.MsDNS2012/MsDNS.cs new file mode 100644 index 00000000..13b69fdb --- /dev/null +++ b/WebsitePanel/Sources/WebsitePanel.Providers.DNS.MsDNS2012/MsDNS.cs @@ -0,0 +1,422 @@ +// Copyright (c) 2012 - 2013, 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.Management; +using System.Collections.Generic; +using System.Text; +using Microsoft.Win32; + +using WebsitePanel.Server.Utils; +using WebsitePanel.Providers.Utils; + +namespace WebsitePanel.Providers.DNS +{ + public class MsDNS: HostingServiceProviderBase, IDnsServer + { + + protected int ExpireLimit + { + get { return ProviderSettings.GetInt( "ExpireLimit" ); } + } + + protected int MinimumTTL + { + get { return ProviderSettings.GetInt( "MinimumTTL" ); } + } + + protected int RefreshInterval + { + get { return ProviderSettings.GetInt( "RefreshInterval" ); } + } + + protected int RetryDelay + { + get { return ProviderSettings.GetInt( "RetryDelay" ); } + } + + protected bool AdMode + { + get { return ProviderSettings.GetBool( "AdMode" ); } + } + + private PowerShellHelper ps = null; + private WmiHelper wmi = null; //< We still need WMI because PowerShell doesn't support SOA updates. + private bool bulkRecords; + + public MsDNS() + { + // Create PowerShell helper + ps = new PowerShellHelper(); + if( !this.IsInstalled() ) + return; + + // Create WMI helper + wmi = new WmiHelper( "root\\MicrosoftDNS" ); + } + + #region Zones + + public virtual string[] GetZones() + { + return ps.Get_DnsServerZone_Names(); + } + + public virtual bool ZoneExists( string zoneName ) + { + return ps.ZoneExists( zoneName ); + } + + public virtual DnsRecord[] GetZoneRecords( string zoneName ) + { + return ps.GetZoneRecords( zoneName ); + } + + public virtual void AddPrimaryZone( string zoneName, string[] secondaryServers ) + { + ps.Add_DnsServerPrimaryZone( zoneName, secondaryServers ); + + // delete orphan NS records + DeleteOrphanNsRecords( zoneName ); + } + + public virtual void AddSecondaryZone( string zoneName, string[] masterServers ) + { + ps.Add_DnsServerSecondaryZone( zoneName, masterServers ); + + // delete orphan NS records + DeleteOrphanNsRecords( zoneName ); + } + + public virtual void DeleteZone( string zoneName ) + { + try + { + ps.Remove_DnsServerZone( zoneName ); + } + catch( Exception ex ) + { + Log.WriteError( ex ); + } + } + + public virtual void AddZoneRecord( string zoneName, DnsRecord record ) + { + try + { + string name = record.RecordName; + if( String.IsNullOrEmpty( name ) ) + name = "."; + + if( record.RecordType == DnsRecordType.A ) + ps.Add_DnsServerResourceRecordA( zoneName, name, record.RecordData ); + else if( record.RecordType == DnsRecordType.AAAA ) + ps.Add_DnsServerResourceRecordAAAA( zoneName, name, record.RecordData ); + else if( record.RecordType == DnsRecordType.CNAME ) + ps.Add_DnsServerResourceRecordCName( zoneName, name, record.RecordData ); + else if( record.RecordType == DnsRecordType.MX ) + ps.Add_DnsServerResourceRecordMX( zoneName, name, record.RecordData, (ushort)record.MxPriority ); + else if( record.RecordType == DnsRecordType.NS ) + ps.Add_DnsServerResourceRecordNS( zoneName, name, record.RecordData ); + else if( record.RecordType == DnsRecordType.TXT ) + ps.Add_DnsServerResourceRecordTXT( zoneName, name, record.RecordData ); + else if( record.RecordType == DnsRecordType.SRV ) + ps.Add_DnsServerResourceRecordSRV( zoneName, name, record.RecordData, (ushort)record.SrvPort, (ushort)record.SrvPriority, (ushort)record.SrvWeight ); + else + throw new Exception( "Unknown record type" ); + } + catch( Exception ex ) + { + // log exception + Log.WriteError( ex ); + } + } + + public virtual void AddZoneRecords( string zoneName, DnsRecord[] records ) + { + bulkRecords = true; + try + { + foreach( DnsRecord record in records ) + AddZoneRecord( zoneName, record ); + } + finally + { + bulkRecords = false; + } + + UpdateSoaRecord( zoneName ); + } + + public virtual void DeleteZoneRecord( string zoneName, DnsRecord record ) + { + try + { + string rrType; + if( !RecordTypes.rrTypeFromRecord.TryGetValue( record.RecordType, out rrType ) ) + throw new Exception( "Unknown record type" ); + ps.Remove_DnsServerResourceRecord( zoneName, record.RecordName, rrType ); + } + catch( Exception ex ) + { + // log exception + Log.WriteError( ex ); + } + } + + public virtual void DeleteZoneRecords( string zoneName, DnsRecord[] records ) + { + foreach( DnsRecord record in records ) + DeleteZoneRecord( zoneName, record ); + } + + public void AddZoneRecord( string zoneName, string recordText ) + { + try + { + Log.WriteStart( string.Format( "Adding MS DNS Server zone '{0}' record '{1}'", zoneName, recordText ) ); + AddDnsRecord( zoneName, recordText ); + Log.WriteEnd( "Added MS DNS Server zone record" ); + } + catch( Exception ex ) + { + Log.WriteError( ex ); + throw; + } + } + #endregion + + #region SOA Record + public virtual void UpdateSoaRecord( string zoneName, string host, string primaryNsServer, string primaryPerson ) + { + host = CorrectHostName( zoneName, host ); + + // delete record if exists + DeleteSoaRecord( zoneName ); + + // format record data + string recordText = GetSoaRecordText( host, primaryNsServer, primaryPerson ); + + // add record + AddDnsRecord( zoneName, recordText ); + + // update SOA record + UpdateSoaRecord( zoneName ); + } + + private void DeleteSoaRecord( string zoneName ) + { + // TODO: find a PowerShell replacement + + string query = String.Format( "SELECT * FROM MicrosoftDNS_SOAType " + + "WHERE OwnerName = '{0}'", + zoneName ); + using( ManagementObjectCollection objRRs = wmi.ExecuteQuery( query ) ) + { + foreach( ManagementObject objRR in objRRs ) using( objRR ) + objRR.Delete(); + } + + // This doesn't work: no errors in PS, but the record stays in the DNS + /* try + { + ps.Remove_DnsServerResourceRecord( zoneName, "@", "Soa" ); + } + catch( System.Exception ex ) + { + Log.WriteWarning( "{0}", ex.Message ); + } */ + } + + private string GetSoaRecordText( string host, string primaryNsServer, string primaryPerson ) + { + return String.Format( "{0} IN SOA {1} {2} 1 900 600 86400 3600", host, primaryNsServer, primaryPerson ); + } + + private static string RemoveTrailingDot( string str ) + { + return ( str.EndsWith( "." ) ) ? str.Substring( 0, str.Length - 1 ) : str; + } + + private void UpdateSoaRecord( string zoneName ) + { + if( bulkRecords ) + return; + + // TODO: find a PowerShell replacement + + // get existing SOA record in order to read serial number + try + { + + ManagementObject objSoa = wmi.GetWmiObject( "MicrosoftDNS_SOAType", "ContainerName = '{0}'", RemoveTrailingDot( zoneName ) ); + + if( objSoa != null ) + { + if( objSoa.Properties[ "OwnerName" ].Value.Equals( zoneName ) ) + { + string primaryServer = (string)objSoa.Properties[ "PrimaryServer" ].Value; + string responsibleParty = (string)objSoa.Properties[ "ResponsibleParty" ].Value; + UInt32 serialNumber = (UInt32)objSoa.Properties[ "SerialNumber" ].Value; + + // update record's serial number + string sn = serialNumber.ToString(); + string todayDate = DateTime.Now.ToString( "yyyyMMdd" ); + if( sn.Length < 10 || !sn.StartsWith( todayDate ) ) + { + // build a new serial number + sn = todayDate + "01"; + serialNumber = UInt32.Parse( sn ); + } + else + { + // just increment serial number + serialNumber += 1; + } + + // update SOA record + using( ManagementBaseObject methodParams = objSoa.GetMethodParameters( "Modify" ) ) + { + methodParams[ "ResponsibleParty" ] = responsibleParty; + methodParams[ "PrimaryServer" ] = primaryServer; + methodParams[ "SerialNumber" ] = serialNumber; + + methodParams[ "ExpireLimit" ] = ExpireLimit; + methodParams[ "MinimumTTL" ] = MinimumTTL; + methodParams[ "TTL" ] = MinimumTTL; + methodParams[ "RefreshInterval" ] = RefreshInterval; + methodParams[ "RetryDelay" ] = RetryDelay; + + ManagementBaseObject outParams = objSoa.InvokeMethod( "Modify", methodParams, null ); + } + // + objSoa.Dispose(); + } + + } + } + catch( Exception ex ) + { + Log.WriteError( ex ); + } + } + + #endregion + + private void DeleteOrphanNsRecords( string zoneName ) + { + // TODO: find a PowerShell replacement + string machineName = System.Net.Dns.GetHostEntry( "LocalHost" ).HostName.ToLower(); + string computerName = Environment.MachineName.ToLower(); + + using( ManagementObjectCollection objRRs = wmi.ExecuteQuery( String.Format( "SELECT * FROM MicrosoftDNS_NSType WHERE DomainName = '{0}'", zoneName ) ) ) + { + foreach( ManagementObject objRR in objRRs ) + { + using( objRR ) + { + string ns = ( (string)objRR.Properties[ "NSHost" ].Value ).ToLower(); + if( ns.StartsWith( machineName ) || ns.StartsWith( computerName ) ) + objRR.Delete(); + + } + } + } + } + + #region private helper methods + + private string GetDnsServerName() + { + // TODO: find a PowerShell replacement + using( ManagementObject objServer = wmi.GetObject( "MicrosoftDNS_Server.Name=\".\"" ) ) + { + return (string)objServer.Properties[ "Name" ].Value; + } + } + + private string AddDnsRecord( string zoneName, string recordText ) + { + // get the name of the server + string serverName = GetDnsServerName(); + + // TODO: find a PowerShell replacement + // add record + using( ManagementClass clsRR = wmi.GetClass( "MicrosoftDNS_ResourceRecord" ) ) + { + object[] prms = new object[] { serverName, zoneName, recordText, null }; + clsRR.InvokeMethod( "CreateInstanceFromTextRepresentation", prms ); + return (string)prms[ 3 ]; + } + } + + private string CorrectHostName( string zoneName, string host ) + { + // if host is empty or null + if( host == null || host == "" ) + return zoneName; + + // if there are not dot at all + else if( host.IndexOf( "." ) == -1 ) + return host + "." + zoneName; + + // if only one dot at the end + else if( host[ host.Length - 1 ] == '.' && host.IndexOf( "." ) == ( host.Length - 1 ) ) + return host + zoneName; + + // other cases + else + return host; + } + #endregion + + public override void DeleteServiceItems( ServiceProviderItem[] items ) + { + foreach( ServiceProviderItem item in items ) + { + if( item is DnsZone ) + { + try + { + // delete DNS zone + DeleteZone( item.Name ); + } + catch( Exception ex ) + { + Log.WriteError( String.Format( "Error deleting '{0}' MS DNS zone", item.Name ), ex ); + } + } + } + } + + public override bool IsInstalled() + { + return ps.Test_DnsServer(); + } + } +} \ No newline at end of file diff --git a/WebsitePanel/Sources/WebsitePanel.Providers.DNS.MsDNS2012/PowerShellHelper.cs b/WebsitePanel/Sources/WebsitePanel.Providers.DNS.MsDNS2012/PowerShellHelper.cs new file mode 100644 index 00000000..72f5563e --- /dev/null +++ b/WebsitePanel/Sources/WebsitePanel.Providers.DNS.MsDNS2012/PowerShellHelper.cs @@ -0,0 +1,112 @@ +// Copyright (c) 2012 - 2013, 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.Collections.ObjectModel; +using System.Management.Automation; +using System.Management.Automation.Runspaces; +using WebsitePanel.Server.Utils; + +namespace WebsitePanel.Providers.DNS +{ + /// This class is a generic helper hosting the PowerShell runtime. + /// It's probably a good idea to move to some utility module. + public class PowerShellHelper: IDisposable + { + private static InitialSessionState s_session = null; + + static PowerShellHelper() + { + s_session = InitialSessionState.CreateDefault(); + // s_session.ImportPSModule( new string[] { "FileServerResourceManager" } ); + } + + public PowerShellHelper() + { + Log.WriteStart( "PowerShellHelper::ctor" ); + + Runspace rs = RunspaceFactory.CreateRunspace( s_session ); + rs.Open(); + // rs.SessionStateProxy.SetVariable( "ConfirmPreference", "none" ); + + this.runSpace = rs; + Log.WriteEnd( "PowerShellHelper::ctor" ); + } + + public void Dispose() + { + try + { + if( this.runSpace == null ) + return; + if( this.runSpace.RunspaceStateInfo.State == RunspaceState.Opened ) + this.runSpace.Close(); + this.runSpace = null; + } + catch( Exception ex ) + { + Log.WriteError( "Runspace error", ex ); + } + } + + public Runspace runSpace { get; private set; } + + public Collection RunPipeline( params Command[] pipelineCommands ) + { + Log.WriteStart( "ExecuteShellCommand" ); + List errorList = new List(); + + Collection results = null; + using( Pipeline pipeLine = runSpace.CreatePipeline() ) + { + // Add the command + foreach( var cmd in pipelineCommands ) + pipeLine.Commands.Add( cmd ); + + // Execute the pipeline and save the objects returned. + results = pipeLine.Invoke(); + + // Only non-terminating errors are delivered here. + // Terminating errors raise exceptions instead. + if( null != pipeLine.Error && pipeLine.Error.Count > 0 ) + { + foreach( object item in pipeLine.Error.ReadToEnd() ) + { + errorList.Add( item ); + string errorMessage = string.Format( "Invoke error: {0}", item ); + Log.WriteWarning( errorMessage ); + } + } + } + // errors = errorList.ToArray(); + Log.WriteEnd( "ExecuteShellCommand" ); + return results; + } + } +} \ No newline at end of file diff --git a/WebsitePanel/Sources/WebsitePanel.Providers.DNS.MsDNS2012/Properties/AssemblyInfo.cs b/WebsitePanel/Sources/WebsitePanel.Providers.DNS.MsDNS2012/Properties/AssemblyInfo.cs new file mode 100644 index 00000000..b37fc853 --- /dev/null +++ b/WebsitePanel/Sources/WebsitePanel.Providers.DNS.MsDNS2012/Properties/AssemblyInfo.cs @@ -0,0 +1,36 @@ +using System.Reflection; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; + +// General Information about an assembly is controlled through the following +// set of attributes. Change these attribute values to modify the information +// associated with an assembly. +[assembly: AssemblyTitle("WebsitePanel.Providers.DNS.MsDNS2012")] +[assembly: AssemblyDescription("")] +[assembly: AssemblyConfiguration("")] +[assembly: AssemblyCompany("")] +[assembly: AssemblyProduct("WebsitePanel.Providers.DNS.MsDNS2012")] +[assembly: AssemblyCopyright("Copyright © 2013")] +[assembly: AssemblyTrademark("")] +[assembly: AssemblyCulture("")] + +// Setting ComVisible to false makes the types in this assembly not visible +// to COM components. If you need to access a type in this assembly from +// COM, set the ComVisible attribute to true on that type. +[assembly: ComVisible(false)] + +// The following GUID is for the ID of the typelib if this project is exposed to COM +[assembly: Guid("f2a902f2-5654-4e67-8c5e-4d2fdf6de873")] + +// Version information for an assembly consists of the following four values: +// +// Major Version +// Minor Version +// Build Number +// Revision +// +// You can specify all the values or you can default the Build and Revision Numbers +// by using the '*' as shown below: +// [assembly: AssemblyVersion("1.0.*")] +[assembly: AssemblyVersion("1.0.0.0")] +[assembly: AssemblyFileVersion("1.0.0.0")] diff --git a/WebsitePanel/Sources/WebsitePanel.Providers.DNS.MsDNS2012/RecordConverter.cs b/WebsitePanel/Sources/WebsitePanel.Providers.DNS.MsDNS2012/RecordConverter.cs new file mode 100644 index 00000000..31743ea0 --- /dev/null +++ b/WebsitePanel/Sources/WebsitePanel.Providers.DNS.MsDNS2012/RecordConverter.cs @@ -0,0 +1,175 @@ +// Copyright (c) 2012 - 2013, 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.Linq; +using System.Management.Automation; +using Microsoft.Management.Infrastructure; +using Microsoft.Management.Infrastructure.Generic; +using WebsitePanel.Server.Utils; + +namespace WebsitePanel.Providers.DNS +{ + /// Copy fields from CimInstance#DnsServerResourceRecord into DnsRecord + /// It's also possible to access native CIM object, and use Mgmtclassgen.exe for that. + internal static class RecordConverter + { + private static string RemoveTrailingDot( string str ) + { + if( !str.EndsWith( "." ) ) + return str; + return str.Substring( 0, str.Length - 1 ); + } + + private static string CorrectHost( string zoneName, string host ) + { + if( host.ToLower() == zoneName.ToLower() ) + return ""; + if( host.ToLower().EndsWith( "." + zoneName.ToLower() ) ) + return host.Substring( 0, ( host.Length - zoneName.Length - 1 ) ); + return host; + } + + public static DnsRecord asDnsRecord( this PSObject obj, string zoneName ) + { + // Here's what comes from Server 2012 in the TypeNames: + // "Microsoft.Management.Infrastructure.CimInstance#root/Microsoft/Windows/DNS/DnsServerResourceRecord" + // "Microsoft.Management.Infrastructure.CimInstance#ROOT/Microsoft/Windows/DNS/DnsDomain" + // "Microsoft.Management.Infrastructure.CimInstance#DnsServerResourceRecord" + // "Microsoft.Management.Infrastructure.CimInstance#DnsDomain" + // "Microsoft.Management.Infrastructure.CimInstance" + // "System.Object" string + + if( !obj.TypeNames.Contains( "Microsoft.Management.Infrastructure.CimInstance#DnsServerResourceRecord" ) ) + { + Log.WriteWarning( "asDnsRecord: wrong object type {0}", obj.TypeNames.FirstOrDefault() ); + return null; + } + + string strRT = (string)obj.Properties[ "RecordType" ].Value; + DnsRecordType tp; + if( !RecordTypes.recordFromString.TryGetValue( strRT, out tp ) ) + return null; + + /*// Debug code below: + obj.dumpProperties(); + CimInstance rd = (CimInstance)obj.Properties[ "RecordData" ].Value; + rd.dumpProperties(); //*/ + + CimKeyedCollection data = ( (CimInstance)obj.Properties[ "RecordData" ].Value ).CimInstanceProperties; + string host = CorrectHost( zoneName, (string)obj.Properties[ "HostName" ].Value ); + + switch( tp ) + { + // The compiler should create a Dictionary<> from dis switch + case DnsRecordType.A: + { + return new DnsRecord() + { + RecordType = tp, + RecordName = host, + RecordData = data[ "IPv4Address" ].Value as string, + }; + } + case DnsRecordType.AAAA: + { + return new DnsRecord() + { + RecordType = tp, + RecordName = host, + RecordData = data[ "IPv6Address" ].Value as string, + }; + } + case DnsRecordType.CNAME: + { + return new DnsRecord() + { + RecordType = tp, + RecordName = host, + RecordData = RemoveTrailingDot( data[ "HostNameAlias" ].Value as string ), + }; + } + case DnsRecordType.MX: + { + return new DnsRecord() + { + RecordType = tp, + RecordName = host, + RecordData = RemoveTrailingDot( data[ "MailExchange" ].Value as string ), + MxPriority = (UInt16)data[ "Preference" ].Value, + }; + } + case DnsRecordType.NS: + { + return new DnsRecord() + { + RecordType = tp, + RecordName = host, + RecordData = RemoveTrailingDot( data[ "NameServer" ].Value as string ), + }; + } + case DnsRecordType.TXT: + { + return new DnsRecord() + { + RecordType = tp, + RecordName = host, + RecordData = data[ "DescriptiveText" ].Value as string, + }; + } + case DnsRecordType.SOA: + { + string PrimaryServer = data[ "PrimaryServer" ].Value as string; + string ResponsiblePerson = data[ "ResponsiblePerson" ].Value as string; + UInt32? sn = (UInt32?)data[ "SerialNumber" ].Value; + return new DnsSOARecord() + { + RecordType = tp, + RecordName = host, + PrimaryNsServer = PrimaryServer, + PrimaryPerson = ResponsiblePerson, + SerialNumber = ( sn.HasValue ) ? sn.Value.ToString() : null, + }; + } + case DnsRecordType.SRV: + { + return new DnsRecord() + { + RecordType = tp, + RecordName = host, + RecordData = RemoveTrailingDot( data[ "DomainName" ].Value as string ), + SrvPriority = (UInt16)data[ "Priority" ].Value, + SrvWeight = (UInt16)data[ "Weight" ].Value, + SrvPort = (UInt16)data[ "Port" ].Value, + }; + } + } + return null; + } + } +} \ No newline at end of file diff --git a/WebsitePanel/Sources/WebsitePanel.Providers.DNS.MsDNS2012/RecordTypes.cs b/WebsitePanel/Sources/WebsitePanel.Providers.DNS.MsDNS2012/RecordTypes.cs new file mode 100644 index 00000000..38efb4db --- /dev/null +++ b/WebsitePanel/Sources/WebsitePanel.Providers.DNS.MsDNS2012/RecordTypes.cs @@ -0,0 +1,68 @@ +// Copyright (c) 2012 - 2013, 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.Globalization; +using System.Linq; + +namespace WebsitePanel.Providers.DNS +{ + /// This static class holds 2 lookup tables, from/to DnsRecordType enum + internal static class RecordTypes + { + static readonly Dictionary s_lookup; + static readonly Dictionary s_lookupInv; + + static RecordTypes() + { + s_lookup = new Dictionary() + { + { "A", DnsRecordType.A }, + { "AAAA", DnsRecordType.AAAA }, + { "NS", DnsRecordType.NS }, + { "MX", DnsRecordType.MX }, + { "CNAME", DnsRecordType.CNAME }, + { "SOA", DnsRecordType.SOA }, + { "TXT", DnsRecordType.TXT }, + { "SRV", DnsRecordType.SRV }, + }; + + TextInfo ti = new CultureInfo( "en-US", false ).TextInfo; + + s_lookupInv = s_lookup + .ToDictionary( kvp => kvp.Value, kvp => ti.ToTitleCase( kvp.Key ) ); + } + + /// The dictionary that maps string record types to DnsRecordType enum + public static Dictionary recordFromString { get { return s_lookup; } } + + /// the dictionary that maps DnsRecordType enum to strings, suitable for PowerShell + public static Dictionary rrTypeFromRecord { get { return s_lookupInv; } } + } +} \ No newline at end of file diff --git a/WebsitePanel/Sources/WebsitePanel.Providers.DNS.MsDNS2012/WebsitePanel.Providers.DNS.MsDNS2012.csproj b/WebsitePanel/Sources/WebsitePanel.Providers.DNS.MsDNS2012/WebsitePanel.Providers.DNS.MsDNS2012.csproj new file mode 100644 index 00000000..3e204b0a --- /dev/null +++ b/WebsitePanel/Sources/WebsitePanel.Providers.DNS.MsDNS2012/WebsitePanel.Providers.DNS.MsDNS2012.csproj @@ -0,0 +1,75 @@ + + + + + Debug + AnyCPU + {FA0FB0BA-5A39-4F4E-8EC2-B806B58B74D4} + Library + Properties + WebsitePanel.Providers.DNS.MsDNS2012 + WebsitePanel.Providers.DNS.MsDNS2012 + v4.0 + 512 + + + + true + full + false + ..\WebsitePanel.Server\bin\Dns2012\ + DEBUG;TRACE + prompt + 4 + + + pdbonly + true + ..\WebsitePanel.Server\bin\Dns2012\ + TRACE + prompt + 4 + + + + False + ..\..\Lib\Microsoft.Management.Infrastructure.dll + True + + + + + + False + ..\..\Lib\System.Management.Automation.dll + True + + + + + + + + + + + + + + {684c932a-6c75-46ac-a327-f3689d89eb42} + WebsitePanel.Providers.Base + + + {e91e52f3-9555-4d00-b577-2b1dbdd87ca7} + WebsitePanel.Server.Utils + + + + + \ No newline at end of file diff --git a/WebsitePanel/Sources/WebsitePanel.Providers.Database.MySQL/MySqlServer56.cs b/WebsitePanel/Sources/WebsitePanel.Providers.Database.MySQL/MySqlServer56.cs new file mode 100644 index 00000000..cbb5b13c --- /dev/null +++ b/WebsitePanel/Sources/WebsitePanel.Providers.Database.MySQL/MySqlServer56.cs @@ -0,0 +1,83 @@ +// 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.Text.RegularExpressions; +using System.Data; +using Microsoft.Win32; +//using MySql.Data.MySqlClient; +using System.IO; + +using WebsitePanel.Server.Utils; +using WebsitePanel.Providers.Utils; +using WebsitePanel.Providers; +using System.Reflection; + +namespace WebsitePanel.Providers.Database +{ + public class MySqlServer56 : MySqlServer + { + + public MySqlServer56() + { + + } + + public override bool IsInstalled() + { + string versionNumber = null; + + RegistryKey HKLM = Registry.LocalMachine; + + RegistryKey key = HKLM.OpenSubKey(@"SOFTWARE\MySQL AB\MySQL Server 5.6"); + + if (key != null) + { + versionNumber = (string)key.GetValue("Version"); + } + else + { + key = HKLM.OpenSubKey(@"SOFTWARE\Wow6432Node\MySQL AB\MySQL Server 5.6"); + if (key != null) + { + versionNumber = (string)key.GetValue("Version"); + } + else + { + return false; + } + } + + string[] split = versionNumber.Split(new char[] { '.' }); + + return split[0].Equals("5") & split[1].Equals("6"); + } + } +} diff --git a/WebsitePanel/Sources/WebsitePanel.Providers.Database.MySQL/WebsitePanel.Providers.Database.MySQL.csproj b/WebsitePanel/Sources/WebsitePanel.Providers.Database.MySQL/WebsitePanel.Providers.Database.MySQL.csproj index 4a691541..3750d9e5 100644 --- a/WebsitePanel/Sources/WebsitePanel.Providers.Database.MySQL/WebsitePanel.Providers.Database.MySQL.csproj +++ b/WebsitePanel/Sources/WebsitePanel.Providers.Database.MySQL/WebsitePanel.Providers.Database.MySQL.csproj @@ -71,6 +71,7 @@ + diff --git a/WebsitePanel/Sources/WebsitePanel.Providers.HostedSolution.Exchange2013/Exchange2013.cs b/WebsitePanel/Sources/WebsitePanel.Providers.HostedSolution.Exchange2013/Exchange2013.cs index 1c77bf52..5f34766f 100644 --- a/WebsitePanel/Sources/WebsitePanel.Providers.HostedSolution.Exchange2013/Exchange2013.cs +++ b/WebsitePanel/Sources/WebsitePanel.Providers.HostedSolution.Exchange2013/Exchange2013.cs @@ -4330,7 +4330,7 @@ namespace WebsitePanel.Providers.HostedSolution string orgCanonicalName = ConvertADPathToCanonicalName(organizationDistinguishedName); //create organization public folder mailbox if required - CheckOrganizationPublicFolderMailbox(runSpace, orgCanonicalName, organizationId); + CheckOrganizationPublicFolderMailbox(runSpace, orgCanonicalName, organizationId, domain); //create organization root folder if required CheckOrganizationRootFolder(runSpace, organizationId, securityGroup, orgCanonicalName, organizationId); @@ -4360,7 +4360,7 @@ namespace WebsitePanel.Providers.HostedSolution ExchangeLog.LogEnd("CreatePublicFolderInternal"); } - private void CheckOrganizationPublicFolderMailbox(Runspace runSpace, string orgCanonicalName, string organizationId) + private void CheckOrganizationPublicFolderMailbox(Runspace runSpace, string orgCanonicalName, string organizationId, string domain) { ExchangeLog.LogStart("CheckOrganizationPublicFolderMailbox"); @@ -4370,7 +4370,7 @@ namespace WebsitePanel.Providers.HostedSolution ExchangeTransaction transaction = StartTransaction(); try { - string rootId = AddPublicFolderMailbox(runSpace, orgCanonicalName, GetPublicFolderMailboxName(organizationId)); + string rootId = AddPublicFolderMailbox(runSpace, orgCanonicalName, GetPublicFolderMailboxName(organizationId), domain); transaction.RegisterNewPublicFolderMailbox(orgCanonicalName + "/" + GetPublicFolderMailboxName(organizationId)); } catch @@ -4421,12 +4421,13 @@ namespace WebsitePanel.Providers.HostedSolution return id; } - private string AddPublicFolderMailbox(Runspace runSpace, string organizationDistinguishedName, string name) + private string AddPublicFolderMailbox(Runspace runSpace, string organizationDistinguishedName, string name, string domain) { ExchangeLog.LogStart("CreatePublicFolderMailbox"); Command cmd = new Command("New-Mailbox"); cmd.Parameters.Add("Name", name); cmd.Parameters.Add("PublicFolder"); + cmd.Parameters.Add("PrimarySmtpAddress", name.Replace(" ", "")+"@"+domain); cmd.Parameters.Add("OrganizationalUnit", organizationDistinguishedName); string database = GetDatabase(runSpace, PrimaryDomainController, MailboxDatabase); ExchangeLog.DebugInfo("database: " + database); diff --git a/WebsitePanel/Sources/WebsitePanel.Providers.OS.Windows2012/Windows2012.cs b/WebsitePanel/Sources/WebsitePanel.Providers.OS.Windows2012/Windows2012.cs index 3542555e..238cbc0c 100644 --- a/WebsitePanel/Sources/WebsitePanel.Providers.OS.Windows2012/Windows2012.cs +++ b/WebsitePanel/Sources/WebsitePanel.Providers.OS.Windows2012/Windows2012.cs @@ -49,6 +49,7 @@ using System.Management.Automation.Runspaces; using WebsitePanel.Providers.Common; using WebsitePanel.Providers; using WebsitePanel.Providers.HostedSolution; +using System.Runtime.InteropServices; namespace WebsitePanel.Providers.OS @@ -80,28 +81,34 @@ namespace WebsitePanel.Providers.OS Log.WriteInfo("ShareNameDrive : {0}", shareNameDrive); Log.WriteInfo("QuotaLimit : {0}", quotaLimit); + string path = Path.Combine(shareNameDrive + @":\", folderPath); + var quota = CalculateQuota(quotaLimit); + Runspace runSpace = null; try { runSpace = OpenRunspace(); - string[] splits = folderPath.Split('\\'); - if (splits.Length > 0) + + if (path.IndexOfAny(Path.GetInvalidPathChars()) == -1) { - string sharePath = String.Empty; + if (!FileUtils.DirectoryExists(path)) + FileUtils.CreateDirectory(path); - if (splits.Length > 4) + switch (mode) { - // Form the share physicalPath - sharePath = shareNameDrive + @":\" + splits[3]; - - if (splits.Length == 5 && !quotaLimit.Equals(String.Empty)) - { - Command cmd = new Command("Set-FsrmQuota"); - cmd.Parameters.Add("Path", sharePath + @"\" + splits[4]); - cmd.Parameters.Add("Size", quotaLimit); - cmd.Parameters.Add("Confirm", true); - ExecuteShellCommand(runSpace, cmd, false); - } + //deleting old quota and creating new one + case 0: + { + RemoveOldQuotaOnFolder(runSpace, path); + ChangeQuotaOnFolder(runSpace, "New-FsrmQuota", path, quota); + break; + } + //modifying folder quota + case 1: + { + ChangeQuotaOnFolder(runSpace, "Set-FsrmQuota", path, quota); + break; + } } } } @@ -112,13 +119,60 @@ namespace WebsitePanel.Providers.OS } finally { - CloseRunspace(runSpace); } Log.WriteEnd("SetQuotaLimitOnFolder"); } + public UInt64 CalculateQuota(string quota) + { + UInt64 OneKb = 1024; + UInt64 OneMb = OneKb * 1024; + UInt64 OneGb = OneMb * 1024; + + UInt64 result = 0; + + // Quota Unit + if (quota.ToLower().Contains("gb")) + { + result = UInt64.Parse(quota.ToLower().Replace("gb", "")) * OneGb; + } + else if (quota.ToLower().Contains("mb")) + { + result = UInt64.Parse(quota.ToLower().Replace("mb", "")) * OneMb; + } + else + { + result = UInt64.Parse(quota.ToLower().Replace("kb", "")) * OneKb; + } + + return result; + } + + public void RemoveOldQuotaOnFolder(Runspace runSpace, string path) + { + try + { + runSpace = OpenRunspace(); + if (!string.IsNullOrEmpty(path)) + { + Command cmd = new Command("Remove-FsrmQuota"); + cmd.Parameters.Add("Path", path); + ExecuteShellCommand(runSpace, cmd, false); + } + } + catch { /* do nothing */ } + } + + public void ChangeQuotaOnFolder(Runspace runSpace, string command, string path, UInt64 quota) + { + Command cmd = new Command(command); + cmd.Parameters.Add("Path", path); + cmd.Parameters.Add("Size", quota); + ExecuteShellCommand(runSpace, cmd, false); + } + #region PowerShell integration private static InitialSessionState session = null; diff --git a/WebsitePanel/Sources/WebsitePanel.Server.sln b/WebsitePanel/Sources/WebsitePanel.Server.sln index aaca761a..97e2925c 100644 --- a/WebsitePanel/Sources/WebsitePanel.Server.sln +++ b/WebsitePanel/Sources/WebsitePanel.Server.sln @@ -142,6 +142,12 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "WebsitePanel.Providers.Host EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "WebsitePanel.Providers.Web.WebDav", "WebsitePanel.Providers.Web.WebDav\WebsitePanel.Providers.Web.WebDav.csproj", "{CE2DF3D7-D6FF-48FA-B2EA-7B836FCBF698}" EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "WebsitePanel.Providers.DNS.MsDNS2012", "WebsitePanel.Providers.DNS.MsDNS2012\WebsitePanel.Providers.DNS.MsDNS2012.csproj", "{FA0FB0BA-5A39-4F4E-8EC2-B806B58B74D4}" + ProjectSection(ProjectDependencies) = postProject + {684C932A-6C75-46AC-A327-F3689D89EB42} = {684C932A-6C75-46AC-A327-F3689D89EB42} + {E91E52F3-9555-4D00-B577-2B1DBDD87CA7} = {E91E52F3-9555-4D00-B577-2B1DBDD87CA7} + EndProjectSection +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -732,6 +738,16 @@ Global {CE2DF3D7-D6FF-48FA-B2EA-7B836FCBF698}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU {CE2DF3D7-D6FF-48FA-B2EA-7B836FCBF698}.Release|Mixed Platforms.Build.0 = Release|Any CPU {CE2DF3D7-D6FF-48FA-B2EA-7B836FCBF698}.Release|x86.ActiveCfg = Release|Any CPU + {FA0FB0BA-5A39-4F4E-8EC2-B806B58B74D4}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {FA0FB0BA-5A39-4F4E-8EC2-B806B58B74D4}.Debug|Any CPU.Build.0 = Debug|Any CPU + {FA0FB0BA-5A39-4F4E-8EC2-B806B58B74D4}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU + {FA0FB0BA-5A39-4F4E-8EC2-B806B58B74D4}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU + {FA0FB0BA-5A39-4F4E-8EC2-B806B58B74D4}.Debug|x86.ActiveCfg = Debug|Any CPU + {FA0FB0BA-5A39-4F4E-8EC2-B806B58B74D4}.Release|Any CPU.ActiveCfg = Release|Any CPU + {FA0FB0BA-5A39-4F4E-8EC2-B806B58B74D4}.Release|Any CPU.Build.0 = Release|Any CPU + {FA0FB0BA-5A39-4F4E-8EC2-B806B58B74D4}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU + {FA0FB0BA-5A39-4F4E-8EC2-B806B58B74D4}.Release|Mixed Platforms.Build.0 = Release|Any CPU + {FA0FB0BA-5A39-4F4E-8EC2-B806B58B74D4}.Release|x86.ActiveCfg = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE diff --git a/WebsitePanel/Sources/WebsitePanel.Server/Web.config b/WebsitePanel/Sources/WebsitePanel.Server/Web.config index 1b5facc3..d3cfc0ac 100644 --- a/WebsitePanel/Sources/WebsitePanel.Server/Web.config +++ b/WebsitePanel/Sources/WebsitePanel.Server/Web.config @@ -168,7 +168,7 @@ - + \ No newline at end of file diff --git a/WebsitePanel/Sources/WebsitePanel.WebPortal/App_Themes/Default/Icons.skin b/WebsitePanel/Sources/WebsitePanel.WebPortal/App_Themes/Default/Icons.skin index 4d334ddb..2e2c3967 100644 --- a/WebsitePanel/Sources/WebsitePanel.WebPortal/App_Themes/Default/Icons.skin +++ b/WebsitePanel/Sources/WebsitePanel.WebPortal/App_Themes/Default/Icons.skin @@ -94,4 +94,4 @@ Default skin template. The following skins are provided as examples only. <%-- Enterprise Storage Icons --%> - \ No newline at end of file + \ No newline at end of file diff --git a/WebsitePanel/Sources/WebsitePanel.WebPortal/App_Themes/Default/Images/Exchange/spaces16.png b/WebsitePanel/Sources/WebsitePanel.WebPortal/App_Themes/Default/Images/Exchange/spaces16.png new file mode 100644 index 00000000..9885c54b Binary files /dev/null and b/WebsitePanel/Sources/WebsitePanel.WebPortal/App_Themes/Default/Images/Exchange/spaces16.png differ diff --git a/WebsitePanel/Sources/WebsitePanel.WebPortal/App_Themes/Default/Images/Exchange/spaces48.png b/WebsitePanel/Sources/WebsitePanel.WebPortal/App_Themes/Default/Images/Exchange/spaces48.png new file mode 100644 index 00000000..4e200101 Binary files /dev/null and b/WebsitePanel/Sources/WebsitePanel.WebPortal/App_Themes/Default/Images/Exchange/spaces48.png differ