From 7c85eb643f66ff9fba8d1979151fd45a4d8219c7 Mon Sep 17 00:00:00 2001 From: VoosW Date: Mon, 29 Oct 2012 19:35:27 +0100 Subject: [PATCH 1/6] change "Getdatabase" code for Exchange 2010SP2 so that it accepts a database group name of DAG\MailboxDatabase to turn off the load-balancing and instead use a fixed database. The default behaviour of load-balancing mailboxes between all Provsioning-Enabled mailbox databases of the DAG-Group is still present and functioning. --- .../Exchange2010SP2.cs | 94 ++++++++++++++----- 1 file changed, 71 insertions(+), 23 deletions(-) diff --git a/WebsitePanel/Sources/WebsitePanel.Providers.HostedSolution/Exchange2010SP2.cs b/WebsitePanel/Sources/WebsitePanel.Providers.HostedSolution/Exchange2010SP2.cs index 65d4dabf..230ac187 100644 --- a/WebsitePanel/Sources/WebsitePanel.Providers.HostedSolution/Exchange2010SP2.cs +++ b/WebsitePanel/Sources/WebsitePanel.Providers.HostedSolution/Exchange2010SP2.cs @@ -607,15 +607,42 @@ namespace WebsitePanel.Providers.HostedSolution ExchangeLog.LogStart("GetDatabase"); ExchangeLog.LogInfo("DAG: " + dagName); - //Get Dag Servers + // this part of code handles mailboxnames like in the old 2007 provider + // check if DAG is in reality DAG\mailboxdatabase + string dagNameDAG = string.Empty; + string dagNameMBX = string.Empty; + bool isFixedDatabase = false; + if (dagName.Contains("\\")) + { + // split the two parts and extract DAG-Name and mailboxdatabase-name + string[] parts = dagName.Split(new char[] { '\\' }, 2, StringSplitOptions.None); + dagNameDAG = parts[0]; + dagNameMBX = parts[1]; + // check that we realy have a database name + if (!String.IsNullOrEmpty(dagNameMBX)) + { + isFixedDatabase = true; + } + } + else + { + // there is no mailboxdatabase-name use the loadbalancing-code + dagNameDAG = dagName; + isFixedDatabase = false; + } + + //Get Dag Servers - with the name of the database availability group Collection dags = null; Command cmd = new Command("Get-DatabaseAvailabilityGroup"); - cmd.Parameters.Add("Identity", dagName); + cmd.Parameters.Add("Identity", dagNameDAG); dags = ExecuteShellCommand(runSpace, cmd); if (htBbalancer == null) htBbalancer = new Hashtable(); + // use fully qualified dagName for loadbalancer. Thus if there are two services and one of them + // contains only the DAG, the "fixed" database could also be used in loadbalancing. If you do not want this, + // set either IsExcludedFromProvisioning or IsSuspendedFromProvisioning - it is not evaluated for fixed databases if (htBbalancer[dagName] == null) htBbalancer.Add(dagName, 0); @@ -628,35 +655,56 @@ namespace WebsitePanel.Providers.HostedSolution { System.Collections.Generic.List lstDatabase = new System.Collections.Generic.List(); - foreach (object objServer in servers) + if (!isFixedDatabase) // "old" loadbalancing code + { + foreach (object objServer in servers) + { + Collection databases = null; + cmd = new Command("Get-MailboxDatabase"); + cmd.Parameters.Add("Server", ObjToString(objServer)); + databases = ExecuteShellCommand(runSpace, cmd); + + foreach (PSObject objDatabase in databases) + { + if (((bool)GetPSObjectProperty(objDatabase, "IsExcludedFromProvisioning") == false) && + ((bool)GetPSObjectProperty(objDatabase, "IsSuspendedFromProvisioning") == false)) + { + string db = ObjToString(GetPSObjectProperty(objDatabase, "Identity")); + + bool bAdd = true; + foreach (string s in lstDatabase) + { + if (s.ToLower() == db.ToLower()) + { + bAdd = false; + break; + } + } + + if (bAdd) + { + lstDatabase.Add(db); + ExchangeLog.LogInfo("AddDatabase: " + db); + } + } + } + } + } + else // new fixed database code { Collection databases = null; cmd = new Command("Get-MailboxDatabase"); - cmd.Parameters.Add("Server", ObjToString(objServer)); + cmd.Parameters.Add("Identity", dagNameMBX); databases = ExecuteShellCommand(runSpace, cmd); + // do not check "IsExcludedFromProvisioning" or "IsSuspended", just check if it is a member of the DAG foreach (PSObject objDatabase in databases) { - if (((bool)GetPSObjectProperty(objDatabase, "IsExcludedFromProvisioning") == false) && - ((bool)GetPSObjectProperty(objDatabase, "IsSuspendedFromProvisioning") == false)) + string dagSetting = ObjToString(GetPSObjectProperty(objDatabase, "MasterServerOrAvailabilityGroup")); + if (dagNameDAG.Equals(dagSetting, StringComparison.OrdinalIgnoreCase)) { - string db = ObjToString(GetPSObjectProperty(objDatabase, "Identity")); - - bool bAdd = true; - foreach (string s in lstDatabase) - { - if (s.ToLower() == db.ToLower()) - { - bAdd = false; - break; - } - } - - if (bAdd) - { - lstDatabase.Add(db); - ExchangeLog.LogInfo("AddDatabase: " + db); - } + lstDatabase.Add(dagNameMBX); + ExchangeLog.LogInfo("AddFixedDatabase: " + dagNameMBX); } } } From 9188c649794440e0671630d5c705227bf8f2ed2b Mon Sep 17 00:00:00 2001 From: Virtuworks Date: Fri, 2 Nov 2012 08:19:33 -0400 Subject: [PATCH 2/6] Added tag build-2.0.0.150 for changeset f57a16601d33 From bc8c122d8128f3ef036ce2765e1f69b5e3eeeba0 Mon Sep 17 00:00:00 2001 From: VoosW Date: Fri, 2 Nov 2012 20:18:32 +0100 Subject: [PATCH 3/6] Adapted Enterprise Importer for 2.0: samAccountName is now needed for more (all) kinds of accounts, make sure that it is imported correctly --- .../ApplicationForm.cs | 1 + .../WebsitePanel.Import.Enterprise/Global.cs | 7 +++++ .../OrganizationImporter.cs | 27 +++++++++++++------ 3 files changed, 27 insertions(+), 8 deletions(-) diff --git a/WebsitePanel/Sources/Tools/WebsitePanel.Import.Enterprise/ApplicationForm.cs b/WebsitePanel/Sources/Tools/WebsitePanel.Import.Enterprise/ApplicationForm.cs index 1e1984c2..fb403a0a 100644 --- a/WebsitePanel/Sources/Tools/WebsitePanel.Import.Enterprise/ApplicationForm.cs +++ b/WebsitePanel/Sources/Tools/WebsitePanel.Import.Enterprise/ApplicationForm.cs @@ -100,6 +100,7 @@ namespace WebsitePanel.Import.Enterprise Global.TempDomain = serviceSettings["TempDomain"]; ServerInfo serverInfo = ServerController.GetServerById(serviceInfo.ServerId); Global.ADRootDomain = serverInfo.ADRootDomain; + Global.NetBiosDomain = ActiveDirectoryUtils.GetNETBIOSDomainName(Global.ADRootDomain); } private void OnBrowseOU(object sender, EventArgs e) diff --git a/WebsitePanel/Sources/Tools/WebsitePanel.Import.Enterprise/Global.cs b/WebsitePanel/Sources/Tools/WebsitePanel.Import.Enterprise/Global.cs index 0b279f17..1e5a928d 100644 --- a/WebsitePanel/Sources/Tools/WebsitePanel.Import.Enterprise/Global.cs +++ b/WebsitePanel/Sources/Tools/WebsitePanel.Import.Enterprise/Global.cs @@ -58,6 +58,13 @@ namespace WebsitePanel.Import.Enterprise set { aDRootDomain = value; } } + private static string netBiosDomain; + public static string NetBiosDomain + { + get { return netBiosDomain; } + set { netBiosDomain = value; } + } + public static PackageInfo Space; public static string TempDomain; diff --git a/WebsitePanel/Sources/Tools/WebsitePanel.Import.Enterprise/OrganizationImporter.cs b/WebsitePanel/Sources/Tools/WebsitePanel.Import.Enterprise/OrganizationImporter.cs index 7b3ff1bb..21b1c5f5 100644 --- a/WebsitePanel/Sources/Tools/WebsitePanel.Import.Enterprise/OrganizationImporter.cs +++ b/WebsitePanel/Sources/Tools/WebsitePanel.Import.Enterprise/OrganizationImporter.cs @@ -757,15 +757,19 @@ namespace WebsitePanel.Import.Enterprise if (EmailAddressExists(email)) return BusinessErrorCodes.ERROR_EXCHANGE_EMAIL_EXISTS; - - if (AccountExists(accountName)) throw new Exception(string.Format("Account {0} already exists", accountName)); string displayName = (string)entry.Properties["displayName"].Value; + string samName = (string)entry.Properties["sAMAccountName"].Value; + // this should really NEVER happen - an AD account without sAMAccountName?! + if (string.IsNullOrEmpty(samName)) + throw new Exception("SAMAccountName is not specified"); + // add Netbios-Domainname before samAccountName - format in the database + samName = Global.NetBiosDomain + "\\" + samName; - int userId = AddOrganizationUser(itemId, accountName, displayName, email, string.Empty); + int userId = AddOrganizationUser(itemId, accountName, displayName, email, samName, string.Empty); AddAccountEmailAddress(userId, email); //account type @@ -796,7 +800,7 @@ namespace WebsitePanel.Import.Enterprise return userId; } - UpdateExchangeAccount(userId, accountName, accountType, displayName, email, false, string.Empty, string.Empty, string.Empty); + UpdateExchangeAccount(userId, accountName, accountType, displayName, email, false, string.Empty, samName, string.Empty); string defaultEmail = (string)entry.Properties["extensionAttribute3"].Value; @@ -847,7 +851,7 @@ namespace WebsitePanel.Import.Enterprise if (email != null && email.ToLower().StartsWith("smtp:")) email = email.Substring(5); - + // no sAMAccountName for contacts - so String.Empty is OK int accountId = AddAccount(itemId, ExchangeAccountType.Contact, accountName, displayName, email, false, 0, string.Empty, null); Log.WriteEnd("Contact imported"); @@ -886,7 +890,14 @@ namespace WebsitePanel.Import.Enterprise if (EmailAddressExists(email)) return BusinessErrorCodes.ERROR_EXCHANGE_EMAIL_EXISTS; - int accountId = AddAccount(itemId, ExchangeAccountType.DistributionList, accountName, displayName, email, false, 0, string.Empty, null); + string samName = (string)entry.Properties["sAMAccountName"].Value; + // this should really NEVER happen - an AD group without sAMAccountName?! + if (string.IsNullOrEmpty(samName)) + throw new Exception("SAMAccountName is not specified"); + // add Netbios-Domainname before samAccountName - format in the database + samName = Global.NetBiosDomain + "\\" + samName; + + int accountId = AddAccount(itemId, ExchangeAccountType.DistributionList, accountName, displayName, email, false, 0, samName, null); AddAccountEmailAddress(accountId, email); string defaultEmail = (string)entry.Properties["extensionAttribute3"].Value; @@ -938,10 +949,10 @@ namespace WebsitePanel.Import.Enterprise mailboxManagerActions.ToString(), samAccountName, CryptoUtils.Encrypt(accountPassword),0, string.Empty); } - private static int AddOrganizationUser(int itemId, string accountName, string displayName, string email, string accountPassword) + private static int AddOrganizationUser(int itemId, string accountName, string displayName, string email, string samAccountName, string accountPassword) { return DataProvider.AddExchangeAccount(itemId, (int)ExchangeAccountType.User, accountName, displayName, email, false, string.Empty, - string.Empty, CryptoUtils.Encrypt(accountPassword),0 , string.Empty); + samAccountName, CryptoUtils.Encrypt(accountPassword), 0 , string.Empty); } From d367078cc6f6f2a60c0e41aa46330be3c8e26c9b Mon Sep 17 00:00:00 2001 From: VoosW Date: Tue, 6 Nov 2012 18:39:48 +0100 Subject: [PATCH 4/6] change GetItemIdByOrganizationId to reflect change of column length in underlying table --- WebsitePanel/Database/update_db.sql | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/WebsitePanel/Database/update_db.sql b/WebsitePanel/Database/update_db.sql index 2b2e2222..8d25b4dc 100644 --- a/WebsitePanel/Database/update_db.sql +++ b/WebsitePanel/Database/update_db.sql @@ -6439,3 +6439,19 @@ GO +ALTER PROCEDURE [dbo].[GetItemIdByOrganizationId] + @OrganizationId nvarchar(128) +AS +BEGIN + SET NOCOUNT ON; + + SELECT + ItemID + FROM + dbo.ExchangeOrganizations + WHERE + OrganizationId = @OrganizationId +END +GO + + From 71a68cccdca0fada45aad0f58dacd0db853fc958 Mon Sep 17 00:00:00 2001 From: VoosW Date: Tue, 6 Nov 2012 18:59:11 +0100 Subject: [PATCH 5/6] also adapt intall_db.sql to reflect changed column length --- WebsitePanel/Database/install_db.sql | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/WebsitePanel/Database/install_db.sql b/WebsitePanel/Database/install_db.sql index 8eb8ed16..25b32209 100644 --- a/WebsitePanel/Database/install_db.sql +++ b/WebsitePanel/Database/install_db.sql @@ -6220,7 +6220,7 @@ GO CREATE PROCEDURE [dbo].[GetItemIdByOrganizationId] - @OrganizationId nvarchar(10) + @OrganizationId nvarchar(128) AS BEGIN SET NOCOUNT ON; From 6c60977de5e37897236a1ce6c9fa160149fea80d Mon Sep 17 00:00:00 2001 From: Virtuworks Date: Tue, 6 Nov 2012 14:14:46 -0500 Subject: [PATCH 6/6] Added tag build-2.0.0.151 for changeset 52a719006602