Decoupling of userprincipalName and PrimaryEmailAddress OrganizationUsers updated with image buttons with the ability to go directly to offering settings When changing primaryemailaddress, sip address changes accordingly Mailboxes list view updated with Login (=userprincipalName) with the ability to go directly to user setting Lync list view updated with Login (=userprincipalName) with the ability to go directly to user setting
1422 lines
No EOL
55 KiB
C#
1422 lines
No EOL
55 KiB
C#
// 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
|
|
|
|
/// <summary>
|
|
/// Pool FQDN
|
|
/// </summary>
|
|
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 SetLyncUserGeneralSettings(string organizationId, string userUpn, LyncUser lyncUser)
|
|
{
|
|
return SetLyncUserGeneralSettingsInternal(organizationId, userUpn, lyncUser);
|
|
}
|
|
|
|
|
|
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)
|
|
{
|
|
sipDomain = sipDomain.ToLower();
|
|
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 == -1) | (maxConferenceSize > 250)) ? 250 : 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<PSObject> result = ExecuteShellCommand(runSpace, cmd, false);
|
|
if ((result != null) && (result.Count > 0))
|
|
{
|
|
Guid tenantId = (Guid)GetPSObjectProperty(result[0], "TenantId");
|
|
|
|
// create sip domain
|
|
string path = AddADPrefix(GetOrganizationPath(organizationId));
|
|
DirectoryEntry ou = ActiveDirectoryUtils.GetADObject(path);
|
|
string[] sipDs = (string[])ActiveDirectoryUtils.GetADObjectPropertyMultiValue(ou, "msRTCSIP-Domains");
|
|
|
|
foreach (string sipD in sipDs)
|
|
DeleteSipDomain(runSpace, sipD);
|
|
|
|
//clear the msRTCSIP-Domains, TenantID, ObjectID
|
|
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<PSObject> result = ExecuteShellCommand(runSpace, cmd, false);
|
|
if ((result != null) && (result.Count > 0))
|
|
{
|
|
tenantId = (Guid)GetPSObjectProperty(result[0], "TenantId");
|
|
|
|
string[] tmp = userUpn.Split('@');
|
|
if (tmp.Length < 2) return false;
|
|
|
|
// Get SipDomains and verify existence
|
|
bool bSipDomainExists = false;
|
|
cmd = new Command("Get-CsSipDomain");
|
|
Collection<PSObject> sipDomains = ExecuteShellCommand(runSpace, cmd, false);
|
|
|
|
foreach (PSObject domain in sipDomains)
|
|
{
|
|
string d = (string)GetPSObjectProperty(domain, "Name");
|
|
if (d.ToLower() == tmp[1].ToLower())
|
|
{
|
|
bSipDomainExists = true;
|
|
break;
|
|
}
|
|
}
|
|
|
|
string path = string.Empty;
|
|
|
|
if (!bSipDomainExists)
|
|
{
|
|
// Create Sip Domain
|
|
cmd = new Command("New-CsSipDomain");
|
|
cmd.Parameters.Add("Identity", tmp[1].ToLower());
|
|
ExecuteShellCommand(runSpace, cmd, false);
|
|
|
|
transaction.RegisterNewSipDomain(tmp[1].ToLower());
|
|
|
|
|
|
path = AddADPrefix(GetOrganizationPath(organizationId));
|
|
DirectoryEntry ou = ActiveDirectoryUtils.GetADObject(path);
|
|
string[] sipDs = (string[])ActiveDirectoryUtils.GetADObjectPropertyMultiValue(ou, "msRTCSIP-Domains");
|
|
List<string> listSipDs = new List<string>();
|
|
listSipDs.AddRange(sipDs);
|
|
listSipDs.Add(tmp[1]);
|
|
|
|
ActiveDirectoryUtils.SetADObjectPropertyValue(ou, "msRTCSIP-Domains", listSipDs.ToArray());
|
|
ou.CommitChanges();
|
|
|
|
//Create simpleurls
|
|
CreateSimpleUrl(runSpace, tmp[1].ToLower(), tenantId);
|
|
transaction.RegisterNewSimpleUrl(tmp[1].ToLower(), tenantId.ToString());
|
|
}
|
|
|
|
//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);
|
|
|
|
path = AddADPrefix(GetResultObjectDN(result));
|
|
DirectoryEntry user = ActiveDirectoryUtils.GetADObject(path);
|
|
ActiveDirectoryUtils.SetADObjectPropertyValue(user, "msRTCSIP-GroupingID", tenantId);
|
|
ActiveDirectoryUtils.SetADObjectPropertyValue(user, "msRTCSIP-TenantId", tenantId);
|
|
|
|
if (tmp.Length > 0)
|
|
{
|
|
string Url = SimpleUrlRoot + tmp[1];
|
|
ActiveDirectoryUtils.SetADObjectPropertyValue(user, "msRTCSIP-BaseSimpleUrl", Url.ToLower());
|
|
}
|
|
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<PSObject> result = ExecuteShellCommand(runSpace, cmd);
|
|
PSObject user = result[0];
|
|
|
|
lyncUser.DisplayName = (string)GetPSObjectProperty(user, "DisplayName");
|
|
lyncUser.SipAddress = (string)GetPSObjectProperty(user, "SipAddress");
|
|
lyncUser.LineUri = (string)GetPSObjectProperty(user, "LineURI");
|
|
|
|
lyncUser.SipAddress = lyncUser.SipAddress.ToLower().Replace("sip:", "");
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
HostedSolutionLog.LogError("GetLyncUserGeneralSettingsInternal", ex);
|
|
throw;
|
|
}
|
|
finally
|
|
{
|
|
CloseRunspace(runSpace);
|
|
}
|
|
HostedSolutionLog.LogEnd("GetLyncUserGeneralSettingsInternal");
|
|
return lyncUser;
|
|
}
|
|
|
|
private bool SetLyncUserGeneralSettingsInternal(string organizationId, string userUpn, LyncUser lyncUser)
|
|
{
|
|
HostedSolutionLog.LogStart("SetLyncUserGeneralSettingsInternal");
|
|
HostedSolutionLog.DebugInfo("organizationId: {0}", organizationId);
|
|
HostedSolutionLog.DebugInfo("userUpn: {0}", userUpn);
|
|
|
|
bool ret = true;
|
|
Runspace runSpace = null;
|
|
Guid tenantId = Guid.Empty;
|
|
LyncTransaction transaction = StartTransaction();
|
|
|
|
try
|
|
{
|
|
runSpace = OpenRunspace();
|
|
Command cmd = new Command("Get-CsTenant");
|
|
cmd.Parameters.Add("Identity", GetOrganizationPath(organizationId));
|
|
Collection<PSObject> result = ExecuteShellCommand(runSpace, cmd, false);
|
|
if ((result != null) && (result.Count > 0))
|
|
{
|
|
tenantId = (Guid)GetPSObjectProperty(result[0], "TenantId");
|
|
|
|
string[] tmp = userUpn.Split('@');
|
|
if (tmp.Length < 2) return false;
|
|
|
|
// Get SipDomains and verify existence
|
|
bool bSipDomainExists = false;
|
|
cmd = new Command("Get-CsSipDomain");
|
|
Collection<PSObject> sipDomains = ExecuteShellCommand(runSpace, cmd, false);
|
|
|
|
foreach (PSObject domain in sipDomains)
|
|
{
|
|
string d = (string)GetPSObjectProperty(domain, "Name");
|
|
if (d.ToLower() == tmp[1].ToLower())
|
|
{
|
|
bSipDomainExists = true;
|
|
break;
|
|
}
|
|
}
|
|
|
|
string path = string.Empty;
|
|
|
|
if (!bSipDomainExists)
|
|
{
|
|
// Create Sip Domain
|
|
cmd = new Command("New-CsSipDomain");
|
|
cmd.Parameters.Add("Identity", tmp[1].ToLower());
|
|
ExecuteShellCommand(runSpace, cmd, false);
|
|
|
|
transaction.RegisterNewSipDomain(tmp[1].ToLower());
|
|
|
|
|
|
path = AddADPrefix(GetOrganizationPath(organizationId));
|
|
DirectoryEntry ou = ActiveDirectoryUtils.GetADObject(path);
|
|
string[] sipDs = (string[])ActiveDirectoryUtils.GetADObjectPropertyMultiValue(ou, "msRTCSIP-Domains");
|
|
List<string> listSipDs = new List<string>();
|
|
listSipDs.AddRange(sipDs);
|
|
listSipDs.Add(tmp[1]);
|
|
|
|
ActiveDirectoryUtils.SetADObjectPropertyValue(ou, "msRTCSIP-Domains", listSipDs.ToArray());
|
|
ou.CommitChanges();
|
|
|
|
//Create simpleurls
|
|
CreateSimpleUrl(runSpace, tmp[1].ToLower(), tenantId);
|
|
transaction.RegisterNewSimpleUrl(tmp[1].ToLower(), tenantId.ToString());
|
|
|
|
path = AddADPrefix(GetResultObjectDN(result));
|
|
DirectoryEntry user = ActiveDirectoryUtils.GetADObject(path);
|
|
|
|
if (tmp.Length > 0)
|
|
{
|
|
string Url = SimpleUrlRoot + tmp[1];
|
|
ActiveDirectoryUtils.SetADObjectPropertyValue(user, "msRTCSIP-BaseSimpleUrl", Url.ToLower());
|
|
}
|
|
user.CommitChanges();
|
|
}
|
|
}
|
|
|
|
cmd = new Command("Set-CsUser");
|
|
cmd.Parameters.Add("Identity", userUpn);
|
|
if (!string.IsNullOrEmpty(lyncUser.SipAddress)) cmd.Parameters.Add("SipAddress", "SIP:"+lyncUser.SipAddress);
|
|
if (!string.IsNullOrEmpty(lyncUser.SipAddress)) cmd.Parameters.Add("LineUri", lyncUser.LineUri);
|
|
|
|
ExecuteShellCommand(runSpace, cmd, false);
|
|
|
|
//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("SetLyncUserGeneralSettingsInternal", ex);
|
|
RollbackTransaction(transaction);
|
|
}
|
|
finally
|
|
{
|
|
CloseRunspace(runSpace);
|
|
}
|
|
HostedSolutionLog.LogEnd("SetLyncUserGeneralSettingsInternal");
|
|
return ret;
|
|
}
|
|
|
|
|
|
|
|
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<PSObject> 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<PSObject> sipDomains = ExecuteShellCommand(runSpace, cmd, false);
|
|
|
|
IList<PSObject> SimpleUrls = new List<PSObject>();
|
|
|
|
|
|
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<PSObject> 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<PSObject> simpleUrl = ExecuteShellCommand(runSpace, cmd, false);
|
|
|
|
SimpleUrls.Add(simpleUrl[0]);
|
|
}
|
|
|
|
//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<PSObject> 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<PSObject> 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<LyncFederationDomain> domains = null;
|
|
Command cmd = new Command("Get-CsTenant");
|
|
cmd.Parameters.Add("Identity", GetOrganizationPath(organizationId));
|
|
Collection<PSObject> 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<LyncFederationDomain>();
|
|
|
|
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);
|
|
|
|
domainName = domainName.ToLower();
|
|
proxyFqdn = proxyFqdn.ToLower();
|
|
|
|
Runspace runSpace = null;
|
|
try
|
|
{
|
|
runSpace = OpenRunspace();
|
|
|
|
Guid tenantId = Guid.Empty;
|
|
Command cmd = new Command("Get-CsTenant");
|
|
cmd.Parameters.Add("Identity", GetOrganizationPath(organizationId));
|
|
Collection<PSObject> 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<PSObject> 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")
|
|
{
|
|
HostedSolutionLog.DebugInfo("Remove DomainName: {0}", domainName);
|
|
allowList = (AllowList)GetPSObjectProperty(result[0], "AllowedDomains");
|
|
DomainPattern domain = null;
|
|
foreach (DomainPattern d in allowList.AllowedDomain)
|
|
{
|
|
if (d.Domain.ToLower() == domainName.ToLower())
|
|
{
|
|
domain = d;
|
|
break;
|
|
}
|
|
}
|
|
if (domain != null)
|
|
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<PSObject> ExecuteShellCommand(Runspace runSpace, Command cmd)
|
|
{
|
|
return ExecuteShellCommand(runSpace, cmd, true);
|
|
}
|
|
|
|
internal Collection<PSObject> ExecuteShellCommand(Runspace runSpace, Command cmd, bool useDomainController)
|
|
{
|
|
object[] errors;
|
|
return ExecuteShellCommand(runSpace, cmd, useDomainController, out errors);
|
|
}
|
|
|
|
internal Collection<PSObject> ExecuteShellCommand(Runspace runSpace, Command cmd, out object[] errors)
|
|
{
|
|
return ExecuteShellCommand(runSpace, cmd, true, out errors);
|
|
}
|
|
|
|
internal Collection<PSObject> ExecuteShellCommand(Runspace runSpace, Command cmd, bool useDomainController, out object[] errors)
|
|
{
|
|
HostedSolutionLog.LogStart("ExecuteShellCommand");
|
|
List<object> errorList = new List<object>();
|
|
|
|
if (useDomainController)
|
|
{
|
|
CommandParameter dc = new CommandParameter("DomainController", PrimaryDomainController);
|
|
if (!cmd.Parameters.Contains(dc))
|
|
{
|
|
cmd.Parameters.Add(dc);
|
|
}
|
|
}
|
|
|
|
HostedSolutionLog.DebugCommand(cmd);
|
|
Collection<PSObject> results = null;
|
|
// Create a pipeline
|
|
Pipeline pipeLine = runSpace.CreatePipeline();
|
|
using (pipeLine)
|
|
{
|
|
// Add the command
|
|
pipeLine.Commands.Add(cmd);
|
|
// Execute the pipeline and save the objects returned.
|
|
results = pipeLine.Invoke();
|
|
|
|
// Log out any errors in the pipeline execution
|
|
// NOTE: These errors are NOT thrown as exceptions!
|
|
// Be sure to check this to ensure that no errors
|
|
// happened while executing the command.
|
|
if (pipeLine.Error != null && pipeLine.Error.Count > 0)
|
|
{
|
|
foreach (object item in pipeLine.Error.ReadToEnd())
|
|
{
|
|
errorList.Add(item);
|
|
string errorMessage = string.Format("Invoke error: {0}", item);
|
|
HostedSolutionLog.LogWarning(errorMessage);
|
|
}
|
|
}
|
|
}
|
|
pipeLine = null;
|
|
errors = errorList.ToArray();
|
|
HostedSolutionLog.LogEnd("ExecuteShellCommand");
|
|
return results;
|
|
}
|
|
|
|
internal object GetPSObjectProperty(PSObject obj, string name)
|
|
{
|
|
return obj.Members[name].Value;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Returns the identity of the object from the shell execution result
|
|
/// </summary>
|
|
/// <param name="result"></param>
|
|
/// <returns></returns>
|
|
internal string GetResultObjectIdentity(Collection<PSObject> result)
|
|
{
|
|
HostedSolutionLog.LogStart("GetResultObjectIdentity");
|
|
if (result == null)
|
|
throw new ArgumentNullException("result", "Execution result is not specified");
|
|
|
|
if (result.Count < 1)
|
|
throw new ArgumentException("Execution result is empty", "result");
|
|
|
|
if (result.Count > 1)
|
|
throw new ArgumentException("Execution result contains more than one object", "result");
|
|
|
|
PSMemberInfo info = result[0].Members["Identity"];
|
|
if (info == null)
|
|
throw new ArgumentException("Execution result does not contain Identity property", "result");
|
|
|
|
string ret = info.Value.ToString();
|
|
HostedSolutionLog.LogEnd("GetResultObjectIdentity");
|
|
return ret;
|
|
}
|
|
|
|
internal string GetResultObjectDN(Collection<PSObject> result)
|
|
{
|
|
HostedSolutionLog.LogStart("GetResultObjectDN");
|
|
if (result == null)
|
|
throw new ArgumentNullException("result", "Execution result is not specified");
|
|
|
|
if (result.Count < 1)
|
|
throw new ArgumentException("Execution result does not contain any object");
|
|
|
|
if (result.Count > 1)
|
|
throw new ArgumentException("Execution result contains more than one object");
|
|
|
|
PSMemberInfo info = result[0].Members["DistinguishedName"];
|
|
if (info == null)
|
|
throw new ArgumentException("Execution result does not contain DistinguishedName property", "result");
|
|
|
|
string ret = info.Value.ToString();
|
|
HostedSolutionLog.LogEnd("GetResultObjectDN");
|
|
return ret;
|
|
}
|
|
|
|
|
|
#endregion
|
|
|
|
#region Transactions
|
|
|
|
internal LyncTransaction StartTransaction()
|
|
{
|
|
return new LyncTransaction();
|
|
}
|
|
|
|
internal void RollbackTransaction(LyncTransaction transaction)
|
|
{
|
|
HostedSolutionLog.LogStart("RollbackTransaction");
|
|
Runspace runSpace = null;
|
|
try
|
|
{
|
|
runSpace = OpenRunspace();
|
|
|
|
|
|
for (int i = transaction.Actions.Count - 1; i > -1; i--)
|
|
{
|
|
//reverse order
|
|
try
|
|
{
|
|
RollbackAction(transaction.Actions[i], runSpace);
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
HostedSolutionLog.LogError("Rollback error", ex);
|
|
}
|
|
}
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
HostedSolutionLog.LogError("Rollback error", ex);
|
|
}
|
|
finally
|
|
{
|
|
|
|
CloseRunspace(runSpace);
|
|
}
|
|
HostedSolutionLog.LogEnd("RollbackTransaction");
|
|
}
|
|
|
|
private void RollbackAction(TransactionAction action, Runspace runspace)
|
|
{
|
|
HostedSolutionLog.LogInfo("Rollback action: {0}", action.ActionType);
|
|
switch (action.ActionType)
|
|
{
|
|
case TransactionAction.TransactionActionTypes.LyncNewSipDomain:
|
|
DeleteSipDomain(runspace, action.Id);
|
|
break;
|
|
//case TransactionAction.TransactionActionTypes.LyncNewSimpleUrl:
|
|
//DeleteSimpleUrl(runspace, action.Id);
|
|
//break;
|
|
case TransactionAction.TransactionActionTypes.LyncNewUser:
|
|
DeleteUser(runspace, action.Id);
|
|
break;
|
|
case TransactionAction.TransactionActionTypes.LyncNewConferencingPolicy:
|
|
DeleteConferencingPolicy(runspace, action.Id);
|
|
break;
|
|
case TransactionAction.TransactionActionTypes.LyncNewExternalAccessPolicy:
|
|
DeleteExternalAccessPolicy(runspace, action.Id);
|
|
break;
|
|
case TransactionAction.TransactionActionTypes.LyncNewMobilityPolicy:
|
|
DeleteMobilityPolicy(runspace, action.Id);
|
|
break;
|
|
}
|
|
}
|
|
|
|
#endregion
|
|
|
|
#region helpers
|
|
private string GetOrganizationPath(string organizationId)
|
|
{
|
|
StringBuilder sb = new StringBuilder();
|
|
// append provider
|
|
AppendOUPath(sb, organizationId);
|
|
AppendOUPath(sb, RootOU);
|
|
AppendDomainPath(sb, RootDomain);
|
|
|
|
return sb.ToString();
|
|
}
|
|
|
|
private static void AppendOUPath(StringBuilder sb, string ou)
|
|
{
|
|
if (string.IsNullOrEmpty(ou))
|
|
return;
|
|
|
|
string path = ou.Replace("/", "\\");
|
|
string[] parts = path.Split('\\');
|
|
for (int i = parts.Length - 1; i != -1; i--)
|
|
sb.Append("OU=").Append(parts[i]).Append(",");
|
|
}
|
|
|
|
private static void AppendDomainPath(StringBuilder sb, string domain)
|
|
{
|
|
if (string.IsNullOrEmpty(domain))
|
|
return;
|
|
|
|
string[] parts = domain.Split('.');
|
|
for (int i = 0; i < parts.Length; i++)
|
|
{
|
|
sb.Append("DC=").Append(parts[i]);
|
|
|
|
if (i < (parts.Length - 1))
|
|
sb.Append(",");
|
|
}
|
|
}
|
|
|
|
internal string AddADPrefix(string path)
|
|
{
|
|
string dn = path;
|
|
if (!dn.ToUpper().StartsWith("LDAP://"))
|
|
{
|
|
dn = string.Format("LDAP://{0}/{1}", PrimaryDomainController, dn);
|
|
}
|
|
return dn;
|
|
}
|
|
|
|
#endregion
|
|
|
|
public override bool IsInstalled()
|
|
{
|
|
string value = "";
|
|
bool bResult = false;
|
|
RegistryKey root = Registry.LocalMachine;
|
|
RegistryKey rk = root.OpenSubKey(LyncRegistryPath);
|
|
if (rk != null)
|
|
{
|
|
value = (string)rk.GetValue("ProductVersion", null);
|
|
if (value == "4.0.7577.0")
|
|
bResult = true;
|
|
|
|
rk.Close();
|
|
}
|
|
return bResult;
|
|
}
|
|
}
|
|
} |