// 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.Collections;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Text;
using System.Reflection;
using System.Globalization;
using System.DirectoryServices;
using Microsoft.Win32;
using WebsitePanel.Providers;
using WebsitePanel.Providers.HostedSolution;
using WebsitePanel.Providers.Utils;
using WebsitePanel.Server.Utils;
using System.Management;
using System.Management.Automation;
using System.Management.Automation.Runspaces;
using Microsoft.Rtc.Management.Hosted;
using Microsoft.Rtc.Management.WritableConfig.Settings.Edge;
using Microsoft.Rtc.Management.WritableConfig.Settings.SimpleUrl;
namespace WebsitePanel.Providers.HostedSolution
{
public class Lync2010 : HostingServiceProviderBase, ILyncServer
{
#region Static constructor
static Lync2010()
{
LyncRegistryPath = "SOFTWARE\\Microsoft\\Real-Time Communications";
}
internal static string LyncRegistryPath
{
get;
set;
}
#endregion
#region Properties
///
/// Pool FQDN
///
private string PoolFQDN
{
get { return ProviderSettings[LyncConstants.PoolFQDN]; }
}
private string SimpleUrlRoot
{
get { return ProviderSettings[LyncConstants.SimpleUrlRoot]; }
}
internal string PrimaryDomainController
{
get { return ProviderSettings["PrimaryDomainController"]; }
}
private string RootOU
{
get { return ProviderSettings["RootOU"]; }
}
private string RootDomain
{
get { return ServerSettings.ADRootDomain; }
}
#endregion
#region ILyncServer implementation
public string CreateOrganization(string organizationId, string sipDomain, bool enableConferencing, bool enableConferencingVideo, int maxConferenceSize, bool enabledFederation, bool enabledEnterpriseVoice)
{
return CreateOrganizationInternal(organizationId, sipDomain, enableConferencing, enableConferencingVideo, maxConferenceSize, enabledFederation, enabledEnterpriseVoice);
}
public bool DeleteOrganization(string organizationId, string sipDomain)
{
return DeleteOrganizationInternal(organizationId, sipDomain);
}
public bool CreateUser(string organizationId, string userUpn, LyncUserPlan plan)
{
return CreateUserInternal(organizationId, userUpn, plan);
}
public LyncUser GetLyncUserGeneralSettings(string organizationId, string userUpn)
{
return GetLyncUserGeneralSettingsInternal(organizationId, userUpn);
}
public bool SetLyncUserPlan(string organizationId, string userUpn, LyncUserPlan plan)
{
return SetLyncUserPlanInternal(organizationId, userUpn, plan, null);
}
public bool DeleteUser(string userUpn)
{
return DeleteUserInternal(userUpn);
}
public LyncFederationDomain[] GetFederationDomains(string organizationId)
{
return GetFederationDomainsInternal(organizationId);
}
public bool AddFederationDomain(string organizationId, string domainName, string proxyFqdn)
{
return AddFederationDomainInternal(organizationId, domainName, proxyFqdn);
}
public bool RemoveFederationDomain(string organizationId, string domainName)
{
return RemoveFederationDomainInternal(organizationId, domainName);
}
public void ReloadConfiguration()
{
ReloadConfigurationInternal();
}
#endregion
#region organization
private string CreateOrganizationInternal(string organizationId, string sipDomain, bool enableConferencing, bool enableConferencingVideo, int maxConferenceSize, bool enabledFederation, bool enabledEnterpriseVoice)
{
HostedSolutionLog.LogStart("CreateOrganizationInternal");
HostedSolutionLog.DebugInfo("organizationId: {0}", organizationId);
HostedSolutionLog.DebugInfo("sipDomain: {0}", sipDomain);
string TenantId = string.Empty;
LyncTransaction transaction = StartTransaction();
Runspace runSpace = null;
try
{
runSpace = OpenRunspace();
// create sip domain
Command cmd = new Command("New-CsSipDomain");
cmd.Parameters.Add("Identity", sipDomain);
ExecuteShellCommand(runSpace, cmd, false);
transaction.RegisterNewSipDomain(sipDomain);
//set the msRTCSIP-Domains, TenantID, ObjectID
Guid id = Guid.NewGuid();
string path = AddADPrefix(GetOrganizationPath(organizationId));
DirectoryEntry ou = ActiveDirectoryUtils.GetADObject(path);
ActiveDirectoryUtils.SetADObjectPropertyValue(ou, "msRTCSIP-Domains", sipDomain);
ActiveDirectoryUtils.SetADObjectPropertyValue(ou, "msRTCSIP-TenantId", id);
ActiveDirectoryUtils.SetADObjectPropertyValue(ou, "msRTCSIP-ObjectId", id);
ou.CommitChanges();
//Create simpleurls
CreateSimpleUrl(runSpace, sipDomain, id);
transaction.RegisterNewSimpleUrl(sipDomain, id.ToString());
//create conferencing policy
cmd = new Command("New-CsConferencingPolicy");
cmd.Parameters.Add("Identity", organizationId);
cmd.Parameters.Add("MaxMeetingSize", maxConferenceSize);
cmd.Parameters.Add("AllowIPVideo", enableConferencingVideo);
ExecuteShellCommand(runSpace, cmd, false);
transaction.RegisterNewConferencingPolicy(organizationId);
//create external access policy
cmd = new Command("New-CsExternalAccessPolicy");
cmd.Parameters.Add("Identity", organizationId);
cmd.Parameters.Add("EnableFederationAccess", true);
cmd.Parameters.Add("EnableOutsideAccess", true);
cmd.Parameters.Add("EnablePublicCloudAccess", false);
cmd.Parameters.Add("EnablePublicCloudAudioVideoAccess", false);
ExecuteShellCommand(runSpace, cmd, false);
transaction.RegisterNewCsExternalAccessPolicy(organizationId);
//Enable for federation
AllowList allowList = new AllowList();
DomainPattern domain = new DomainPattern(sipDomain);
allowList.AllowedDomain.Add(domain);
cmd = new Command("Set-CsTenantFederationConfiguration");
cmd.Parameters.Add("Tenant", id);
cmd.Parameters.Add("AllowFederatedUsers", true);
cmd.Parameters.Add("AllowedDomains", allowList);
ExecuteShellCommand(runSpace, cmd, false);
//create mobility policy
cmd = new Command("New-CsMobilityPolicy");
cmd.Parameters.Add("Identity", organizationId + " EnableOutSideVoice");
cmd.Parameters.Add("EnableMobility", true);
cmd.Parameters.Add("EnableOutsideVoice", true);
ExecuteShellCommand(runSpace, cmd, false);
transaction.RegisterNewCsMobilityPolicy(organizationId + " EnableOutSideVoice");
cmd = new Command("New-CsMobilityPolicy");
cmd.Parameters.Add("Identity", organizationId + " DisableOutSideVoice");
cmd.Parameters.Add("EnableMobility", true);
cmd.Parameters.Add("EnableOutsideVoice", false);
ExecuteShellCommand(runSpace, cmd, false);
transaction.RegisterNewCsMobilityPolicy(organizationId + " DisableOutSideVoice");
cmd = new Command("Invoke-CsManagementStoreReplication");
ExecuteShellCommand(runSpace, cmd, false);
TenantId = id.ToString();
}
catch (Exception ex)
{
HostedSolutionLog.LogError("CreateOrganizationInternal", ex);
RollbackTransaction(transaction);
throw;
}
finally
{
CloseRunspace(runSpace);
}
HostedSolutionLog.LogEnd("CreateOrganizationInternal");
return TenantId;
}
private bool DeleteOrganizationInternal(string organizationId, string sipDomain)
{
HostedSolutionLog.LogStart("DeleteOrganizationInternal");
HostedSolutionLog.DebugInfo("organizationId: {0}", organizationId);
HostedSolutionLog.DebugInfo("sipDomain: {0}", sipDomain);
bool ret = true;
Runspace runSpace = null;
try
{
runSpace = OpenRunspace();
Command cmd = new Command("Get-CsTenant");
cmd.Parameters.Add("Identity", GetOrganizationPath(organizationId));
Collection result = ExecuteShellCommand(runSpace, cmd, false);
if ((result != null) && (result.Count > 0))
{
Guid tenantId = (Guid)GetPSObjectProperty(result[0], "TenantId");
// create sip domain
DeleteSipDomain(runSpace, sipDomain);
//clear the msRTCSIP-Domains, TenantID, ObjectID
string path = AddADPrefix(GetOrganizationPath(organizationId));
DirectoryEntry ou = ActiveDirectoryUtils.GetADObject(path);
ActiveDirectoryUtils.ClearADObjectPropertyValue(ou, "msRTCSIP-Domains");
ActiveDirectoryUtils.ClearADObjectPropertyValue(ou, "msRTCSIP-TenantId");
ActiveDirectoryUtils.ClearADObjectPropertyValue(ou, "msRTCSIP-ObjectId");
ou.CommitChanges();
try
{
DeleteConferencingPolicy(runSpace, organizationId);
}
catch (Exception)
{
}
try
{
DeleteExternalAccessPolicy(runSpace, organizationId);
}
catch (Exception)
{
}
try
{
DeleteMobilityPolicy(runSpace, organizationId + " EnableOutSideVoice");
}
catch (Exception)
{
}
try
{
DeleteMobilityPolicy(runSpace, organizationId + " DisableOutSideVoice");
}
catch (Exception)
{
}
try
{
DeleteSimpleUrl(runSpace, sipDomain, tenantId);
}
catch (Exception)
{
}
}
cmd = new Command("Invoke-CsManagementStoreReplication");
ExecuteShellCommand(runSpace, cmd, false);
}
catch (Exception ex)
{
ret = false;
HostedSolutionLog.LogError("DeleteOrganizationInternal", ex);
throw;
}
finally
{
CloseRunspace(runSpace);
}
HostedSolutionLog.LogEnd("DeleteOrganizationInternal");
return ret;
}
#endregion
#region Users
private bool CreateUserInternal(string organizationId, string userUpn, LyncUserPlan plan)
{
HostedSolutionLog.LogStart("CreateUserInternal");
HostedSolutionLog.DebugInfo("organizationId: {0}", organizationId);
HostedSolutionLog.DebugInfo("userUpn: {0}", userUpn);
bool ret = true;
Guid tenantId = Guid.Empty;
LyncTransaction transaction = StartTransaction();
Runspace runSpace = null;
try
{
runSpace = OpenRunspace();
Command cmd = new Command("Get-CsTenant");
cmd.Parameters.Add("Identity", GetOrganizationPath(organizationId));
Collection result = ExecuteShellCommand(runSpace, cmd, false);
if ((result != null) && (result.Count > 0))
{
tenantId = (Guid)GetPSObjectProperty(result[0], "TenantId");
//enable for lync
cmd = new Command("Enable-CsUser");
cmd.Parameters.Add("Identity", userUpn);
cmd.Parameters.Add("RegistrarPool", PoolFQDN);
cmd.Parameters.Add("SipAddressType", "UserPrincipalName");
ExecuteShellCommand(runSpace, cmd);
transaction.RegisterNewCsUser(userUpn);
//set groupingID and tenantID
cmd = new Command("Get-CsAdUser");
cmd.Parameters.Add("Identity", userUpn);
result = ExecuteShellCommand(runSpace, cmd);
string path = AddADPrefix(GetResultObjectDN(result));
DirectoryEntry user = ActiveDirectoryUtils.GetADObject(path);
ActiveDirectoryUtils.SetADObjectPropertyValue(user, "msRTCSIP-GroupingID", tenantId);
ActiveDirectoryUtils.SetADObjectPropertyValue(user, "msRTCSIP-TenantId", tenantId);
string[] tmp = userUpn.Split('@');
if (tmp.Length > 0)
{
string Url = SimpleUrlRoot + tmp[1];
ActiveDirectoryUtils.SetADObjectPropertyValue(user, "msRTCSIP-BaseSimpleUrl", Url);
}
user.CommitChanges();
//set-plan
SetLyncUserPlanInternal(organizationId, userUpn, plan, runSpace);
//initiate addressbook generation
cmd = new Command("Update-CsAddressBook");
ExecuteShellCommand(runSpace, cmd, false);
//initiate user database replication
cmd = new Command("Update-CsUserDatabase");
ExecuteShellCommand(runSpace, cmd, false);
}
else
{
ret = false;
HostedSolutionLog.LogError("Failed to retrieve tenantID", null);
}
}
catch (Exception ex)
{
ret = false;
HostedSolutionLog.LogError("CreateUserInternal", ex);
RollbackTransaction(transaction);
throw;
}
finally
{
CloseRunspace(runSpace);
}
HostedSolutionLog.LogEnd("CreateUserInternal");
return ret;
}
private LyncUser GetLyncUserGeneralSettingsInternal(string organizationId, string userUpn)
{
HostedSolutionLog.LogStart("GetLyncUserGeneralSettingsInternal");
HostedSolutionLog.DebugInfo("organizationId: {0}", organizationId);
HostedSolutionLog.DebugInfo("userUpn: {0}", userUpn);
LyncUser lyncUser = new LyncUser();
Runspace runSpace = null;
try
{
runSpace = OpenRunspace();
Command cmd = new Command("Get-CsUser");
cmd.Parameters.Add("Identity", userUpn);
Collection result = ExecuteShellCommand(runSpace, cmd);
PSObject user = result[0];
lyncUser.DisplayName = (string)GetPSObjectProperty(user, "DisplayName");
lyncUser.PrimaryUri = (string)GetPSObjectProperty(user, "SipAddress");
lyncUser.LineUri = (string)GetPSObjectProperty(user, "LineURI");
}
catch (Exception ex)
{
HostedSolutionLog.LogError("GetLyncUserGeneralSettingsInternal", ex);
throw;
}
finally
{
CloseRunspace(runSpace);
}
HostedSolutionLog.LogEnd("GetLyncUserGeneralSettingsInternal");
return lyncUser;
}
private bool SetLyncUserPlanInternal(string organizationId, string userUpn, LyncUserPlan plan, Runspace runSpace)
{
HostedSolutionLog.LogStart("SetLyncUserPlanInternal");
HostedSolutionLog.DebugInfo("organizationId: {0}", organizationId);
HostedSolutionLog.DebugInfo("userUpn: {0}", userUpn);
bool ret = true;
bool bCloseRunSpace = false;
try
{
if (runSpace == null)
{
runSpace = OpenRunspace();
bCloseRunSpace = true;
}
//CsExternalAccessPolicy
Command cmd = new Command("Grant-CsExternalAccessPolicy");
cmd.Parameters.Add("Identity", userUpn);
cmd.Parameters.Add("PolicyName", plan.Federation ? organizationId : null);
ExecuteShellCommand(runSpace, cmd);
//CsConferencingPolicy
cmd = new Command("Grant-CsConferencingPolicy");
cmd.Parameters.Add("Identity", userUpn);
cmd.Parameters.Add("PolicyName", plan.Federation ? organizationId : null);
ExecuteShellCommand(runSpace, cmd);
//CsMobilityPolicy
cmd = new Command("Grant-CsMobilityPolicy");
cmd.Parameters.Add("Identity", userUpn);
if (plan.Mobility)
cmd.Parameters.Add("PolicyName", plan.MobilityEnableOutsideVoice ? organizationId + " EnableOutSideVoice" : organizationId + " DisableOutSideVoice");
else
cmd.Parameters.Add("PolicyName", null);
ExecuteShellCommand(runSpace, cmd);
//initiate user database replication
cmd = new Command("Update-CsUserDatabase");
ExecuteShellCommand(runSpace, cmd, false);
}
catch (Exception ex)
{
ret = false;
HostedSolutionLog.LogError("SetLyncUserPlanInternal", ex);
throw;
}
finally
{
if (bCloseRunSpace) CloseRunspace(runSpace);
}
HostedSolutionLog.LogEnd("SetLyncUserPlanInternal");
return ret;
}
private bool DeleteUserInternal(string userUpn)
{
HostedSolutionLog.LogStart("DeleteUserInternal");
HostedSolutionLog.DebugInfo("userUpn: {0}", userUpn);
bool ret = true;
Runspace runSpace = null;
try
{
runSpace = OpenRunspace();
//Delete User
DeleteUser(runSpace, userUpn);
//Clear groupingID and tenantID
Command cmd = new Command("Get-CsAdUser");
cmd.Parameters.Add("Identity", userUpn);
Collection result = ExecuteShellCommand(runSpace, cmd);
string path = AddADPrefix(GetResultObjectDN(result));
DirectoryEntry user = ActiveDirectoryUtils.GetADObject(path);
ActiveDirectoryUtils.ClearADObjectPropertyValue(user, "msRTCSIP-GroupingID");
ActiveDirectoryUtils.ClearADObjectPropertyValue(user, "msRTCSIP-TenantId");
ActiveDirectoryUtils.ClearADObjectPropertyValue(user, "msRTCSIP-BaseSimpleUrl");
user.CommitChanges();
//initiate addressbook generation
cmd = new Command("Update-CsAddressBook");
ExecuteShellCommand(runSpace, cmd, false);
//initiate user database replication
cmd = new Command("Update-CsUserDatabase");
ExecuteShellCommand(runSpace, cmd, false);
}
catch (Exception ex)
{
ret = false;
HostedSolutionLog.LogError("DeleteUserInternal", ex);
throw;
}
finally
{
CloseRunspace(runSpace);
}
HostedSolutionLog.LogEnd("DeleteUserInternal");
return ret;
}
internal void DeleteUser(Runspace runSpace, string userUpn)
{
HostedSolutionLog.LogStart("DeleteUser");
HostedSolutionLog.DebugInfo("userUpn : {0}", userUpn);
Command cmd = new Command("Disable-CsUser");
cmd.Parameters.Add("Identity", userUpn);
cmd.Parameters.Add("Confirm", false);
ExecuteShellCommand(runSpace, cmd, false);
HostedSolutionLog.LogEnd("DeleteUser");
}
#endregion
#region SipDomains
internal void DeleteSipDomain(Runspace runSpace, string id)
{
HostedSolutionLog.LogStart("DeleteSipDomain");
HostedSolutionLog.DebugInfo("SipDomain : {0}", id);
Command cmd = new Command("Remove-CsSipDomain");
cmd.Parameters.Add("Identity", id);
cmd.Parameters.Add("Confirm", false);
cmd.Parameters.Add("Force", true);
ExecuteShellCommand(runSpace, cmd, false);
HostedSolutionLog.LogEnd("DeleteSipDomain");
}
private void CreateSimpleUrl(Runspace runSpace, string sipDomain, Guid id)
{
//Create the simpleUrlEntry
Command cmd = new Command("Get-CsSipDomain");
Collection sipDomains = ExecuteShellCommand(runSpace, cmd, false);
IList SimpleUrls = new List();
foreach (PSObject domain in sipDomains)
{
string d = (string)GetPSObjectProperty(domain, "Name");
string Url = SimpleUrlRoot + d;
//Create the simpleUrlEntry
cmd = new Command("New-CsSimpleUrlEntry");
cmd.Parameters.Add("Url", Url);
Collection simpleUrlEntry = ExecuteShellCommand(runSpace, cmd, false);
//Create the simpleUrl
cmd = new Command("New-CsSimpleUrl");
cmd.Parameters.Add("Component", "meet");
cmd.Parameters.Add("Domain", d);
cmd.Parameters.Add("SimpleUrl", simpleUrlEntry[0]);
cmd.Parameters.Add("ActiveUrl", Url);
Collection simpleUrl = ExecuteShellCommand(runSpace, cmd, false);
SimpleUrls.Add(simpleUrl[0]);
}
Hashtable properties = new Hashtable();
properties.Add("Add", SimpleUrls);
//PSListModifier
cmd = new Command("Set-CsSimpleUrlConfiguration");
cmd.Parameters.Add("Identity", "Global");
cmd.Parameters.Add("Tenant", id);
cmd.Parameters.Add("SimpleUrl", SimpleUrls);
ExecuteShellCommand(runSpace, cmd, false);
}
internal void DeleteSimpleUrl(Runspace runSpace, string sipDomain, Guid id)
{
/*
//build the url
string Url = SimpleUrlRoot + sipDomain;
//Create the simpleUrlEntry
Command cmd = new Command("New-CsSimpleUrlEntry");
cmd.Parameters.Add("Url", Url);
Collection simpleUrlEntry = ExecuteShellCommand(runSpace, cmd, false);
//Create the simpleUrl
cmd = new Command("New-CsSimpleUrl");
cmd.Parameters.Add("Component", "meet");
cmd.Parameters.Add("Domain", sipDomain);
cmd.Parameters.Add("SimpleUrl", simpleUrlEntry[0]);
cmd.Parameters.Add("ActiveUrl", Url);
Collection simpleUrl = ExecuteShellCommand(runSpace, cmd, false);
//PSListModifier
Hashtable properties = new Hashtable();
properties.Add("Remove", simpleUrl[0]);
cmd = new Command("Set-CsSimpleUrlConfiguration");
cmd.Parameters.Add("Identity", "Global");
cmd.Parameters.Add("Tenant", id);
cmd.Parameters.Add("SimpleUrl", properties);
ExecuteShellCommand(runSpace, cmd, false);
*/
}
#endregion
#region Policies
internal void DeleteConferencingPolicy(Runspace runSpace, string policyName)
{
HostedSolutionLog.LogStart("DeleteConferencingPolicy");
HostedSolutionLog.DebugInfo("policyName : {0}", policyName);
Command cmd = new Command("Remove-CsConferencingPolicy");
cmd.Parameters.Add("Identity", policyName);
cmd.Parameters.Add("Confirm", false);
cmd.Parameters.Add("Force", true);
ExecuteShellCommand(runSpace, cmd, false);
HostedSolutionLog.LogEnd("DeleteConferencingPolicy");
}
internal void DeleteExternalAccessPolicy(Runspace runSpace, string policyName)
{
HostedSolutionLog.LogStart("DeleteExternalAccessPolicy");
HostedSolutionLog.DebugInfo("policyName : {0}", policyName);
Command cmd = new Command("Remove-CsExternalAccessPolicy");
cmd.Parameters.Add("Identity", policyName);
cmd.Parameters.Add("Confirm", false);
cmd.Parameters.Add("Force", true);
ExecuteShellCommand(runSpace, cmd, false);
HostedSolutionLog.LogEnd("DeleteExternalAccessPolicy");
}
internal void DeleteMobilityPolicy(Runspace runSpace, string policyName)
{
HostedSolutionLog.LogStart("DeleteMobilityPolicy");
HostedSolutionLog.DebugInfo("policyName : {0}", policyName);
Command cmd = new Command("Remove-CsMobilityPolicy");
cmd.Parameters.Add("Identity", policyName);
cmd.Parameters.Add("Confirm", false);
cmd.Parameters.Add("Force", true);
ExecuteShellCommand(runSpace, cmd, false);
HostedSolutionLog.LogEnd("DeleteMobilityPolicy");
}
#endregion
#region Sytsem Related Methods
private void ReloadConfigurationInternal()
{
HostedSolutionLog.LogStart("ReloadConfigurationInternal");
Runspace runSpace = null;
try
{
runSpace = OpenRunspace();
Command cmd = new Command("Enable-CsComputer");
ExecuteShellCommand(runSpace, cmd, false);
}
catch (Exception ex)
{
HostedSolutionLog.LogError("ReloadConfigurationInternal", ex);
throw;
}
finally
{
CloseRunspace(runSpace);
}
HostedSolutionLog.LogEnd("ReloadConfigurationInternal");
}
#endregion
#region Federation Domains
private LyncFederationDomain[] GetFederationDomainsInternal(string organizationId)
{
HostedSolutionLog.LogStart("GetFederationDomainsInternal");
HostedSolutionLog.DebugInfo("organizationId: {0}", organizationId);
LyncFederationDomain[] domains = null;
Runspace runSpace = null;
try
{
runSpace = OpenRunspace();
Guid tenantId = Guid.Empty;
domains = GetFederationDomainsInternal(runSpace, organizationId, ref tenantId);
}
catch (Exception ex)
{
HostedSolutionLog.LogError("GetFederationDomainsInternal", ex);
throw;
}
finally
{
CloseRunspace(runSpace);
}
HostedSolutionLog.LogEnd("GetFederationDomainsInternal");
return domains;
}
private LyncFederationDomain[] GetFederationDomainsInternal(Runspace runSpace, string organizationId, ref Guid tenantId)
{
//Get TenantID
List domains = null;
Command cmd = new Command("Get-CsTenant");
cmd.Parameters.Add("Identity", GetOrganizationPath(organizationId));
Collection result = ExecuteShellCommand(runSpace, cmd, false);
if ((result != null) && (result.Count > 0))
{
tenantId = (Guid)GetPSObjectProperty(result[0], "TenantId");
//Get-CSTenantFederationConfiguration (AllowedDomains)
cmd = new Command("Get-CsTenantFederationConfiguration");
cmd.Parameters.Add("Tenant", tenantId);
result = ExecuteShellCommand(runSpace, cmd, false);
if ((result != null) && (result.Count > 0))
{
domains = new List();
if (GetPSObjectProperty(result[0], "AllowedDomains").GetType().ToString() == "Microsoft.Rtc.Management.WritableConfig.Settings.Edge.AllowList")
{
AllowList allowList = (AllowList)GetPSObjectProperty(result[0], "AllowedDomains");
foreach (DomainPattern d in allowList.AllowedDomain)
{
LyncFederationDomain domain = new LyncFederationDomain();
domain.DomainName = d.Domain.ToString();
domains.Add(domain);
}
}
}
}
if (domains != null)
return domains.ToArray();
else
return null;
}
private bool AddFederationDomainInternal(string organizationId, string domainName, string proxyFqdn)
{
HostedSolutionLog.LogStart("AddFederationDomainInternal");
HostedSolutionLog.DebugInfo("organizationId: {0}", organizationId);
HostedSolutionLog.DebugInfo("domainName: {0}", domainName);
Runspace runSpace = null;
try
{
runSpace = OpenRunspace();
Guid tenantId = Guid.Empty;
Command cmd = new Command("Get-CsTenant");
cmd.Parameters.Add("Identity", GetOrganizationPath(organizationId));
Collection result = ExecuteShellCommand(runSpace, cmd, false);
if ((result != null) && (result.Count > 0))
{
tenantId = (Guid)GetPSObjectProperty(result[0], "TenantId");
//Get-CSTenantFederationConfiguration (AllowedDomains)
cmd = new Command("Get-CsTenantFederationConfiguration");
cmd.Parameters.Add("Tenant", tenantId);
result = ExecuteShellCommand(runSpace, cmd, false);
if ((result != null) && (result.Count > 0))
{
AllowList allowList = null;
if (GetPSObjectProperty(result[0], "AllowedDomains").GetType().ToString() == "Microsoft.Rtc.Management.WritableConfig.Settings.Edge.AllowList")
{
allowList = (AllowList)GetPSObjectProperty(result[0], "AllowedDomains");
DomainPattern domain = new DomainPattern(domainName);
allowList.AllowedDomain.Add(domain);
}
else
{
allowList = new AllowList();
DomainPattern domain = new DomainPattern(domainName);
allowList.AllowedDomain.Add(domain);
}
cmd = new Command("Set-CsTenantFederationConfiguration");
cmd.Parameters.Add("Tenant", tenantId);
cmd.Parameters.Add("AllowedDomains", allowList);
ExecuteShellCommand(runSpace, cmd, false);
}
}
}
catch (Exception ex)
{
HostedSolutionLog.LogError("AddFederationDomainInternal", ex);
throw;
}
finally
{
CloseRunspace(runSpace);
}
HostedSolutionLog.LogEnd("AddFederationDomainInternal");
return true;
}
private bool RemoveFederationDomainInternal(string organizationId, string domainName)
{
HostedSolutionLog.LogStart("RemoveFederationDomainInternal");
HostedSolutionLog.DebugInfo("organizationId: {0}", organizationId);
HostedSolutionLog.DebugInfo("domainName: {0}", domainName);
Runspace runSpace = null;
try
{
runSpace = OpenRunspace();
Guid tenantId = Guid.Empty;
Command cmd = new Command("Get-CsTenant");
cmd.Parameters.Add("Identity", GetOrganizationPath(organizationId));
Collection result = ExecuteShellCommand(runSpace, cmd, false);
if ((result != null) && (result.Count > 0))
{
tenantId = (Guid)GetPSObjectProperty(result[0], "TenantId");
//Get-CSTenantFederationConfiguration (AllowedDomains)
cmd = new Command("Get-CsTenantFederationConfiguration");
cmd.Parameters.Add("Tenant", tenantId);
result = ExecuteShellCommand(runSpace, cmd, false);
if ((result != null) && (result.Count > 0))
{
AllowList allowList = null;
if (GetPSObjectProperty(result[0], "AllowedDomains").GetType().ToString() == "Microsoft.Rtc.Management.WritableConfig.Settings.Edge.AllowList")
{
allowList = (AllowList)GetPSObjectProperty(result[0], "AllowedDomains");
DomainPattern domain = new DomainPattern(domainName);
allowList.AllowedDomain.Remove(domain);
}
cmd = new Command("Set-CsTenantFederationConfiguration");
cmd.Parameters.Add("Tenant", tenantId);
cmd.Parameters.Add("AllowedDomains", allowList);
ExecuteShellCommand(runSpace, cmd, false);
}
}
}
catch (Exception ex)
{
HostedSolutionLog.LogError("RemoveFederationDomainInternal", ex);
throw;
}
finally
{
CloseRunspace(runSpace);
}
HostedSolutionLog.LogEnd("RemoveFederationDomainInternal");
return true;
}
#endregion
#region PowerShell integration
private static InitialSessionState session = null;
internal virtual Runspace OpenRunspace()
{
HostedSolutionLog.LogStart("OpenRunspace");
if (session == null)
{
session = InitialSessionState.CreateDefault();
session.ImportPSModule(new string[] { "ActiveDirectory", "Lync", "LyncOnline" });
}
Runspace runSpace = RunspaceFactory.CreateRunspace(session);
//
runSpace.Open();
//
runSpace.SessionStateProxy.SetVariable("ConfirmPreference", "none");
HostedSolutionLog.LogEnd("OpenRunspace");
return runSpace;
}
internal void CloseRunspace(Runspace runspace)
{
try
{
if (runspace != null && runspace.RunspaceStateInfo.State == RunspaceState.Opened)
{
runspace.Close();
}
}
catch (Exception ex)
{
HostedSolutionLog.LogError("Runspace error", ex);
}
}
internal Collection ExecuteShellCommand(Runspace runSpace, Command cmd)
{
return ExecuteShellCommand(runSpace, cmd, true);
}
internal Collection ExecuteShellCommand(Runspace runSpace, Command cmd, bool useDomainController)
{
object[] errors;
return ExecuteShellCommand(runSpace, cmd, useDomainController, out errors);
}
internal Collection ExecuteShellCommand(Runspace runSpace, Command cmd, out object[] errors)
{
return ExecuteShellCommand(runSpace, cmd, true, out errors);
}
internal Collection ExecuteShellCommand(Runspace runSpace, Command cmd, bool useDomainController, out object[] errors)
{
HostedSolutionLog.LogStart("ExecuteShellCommand");
List