Monday, April 21, 2014

Lync 2013, SQL, and low RAM situations

I recently was working with a customer with a Lync 2013 Enterprise Edition single node front end who was finding that Lync and SQL services were frequently failing and generally performing very poorly. This was a new deployment and only homed about five users at the time.

After reviewing the Front End's CPU and RAM, we saw that it had 16GB of RAM at its disposal, and there was plenty of available memory, but we would see memory errors in the event log, and even while trying to pull up the properties of the SQL server itself:



 

After stopping and starting SQL, we were able to pull up the properties and found that the SQL memory was set very low.

LYNCLOCAL:


RTCLOCAL:


Comparing these settings to known working configurations, these values were about 10-12x too small. So we upped the memory here, and the server began behaving… for some time at least. The SQL memory settings are dynamically changed by Lync, so the following day, they would revert to the above settings and performance would take a hit.

In our findings, these settings are defined as a percentage of installed memory at time of Lync deployment. In this particular case, the Lync Front End deployment was performed at a time when the virtual machine was provisioned with VERY low system memory. So the SQL setting was set in Lync, and when memory was later upgraded to prepare for deployment, the change was unknown to Lync.

The Fix

The fix here was simply to re-run the Lync Deployment Wizard Step One for the local SQL instances with the system memory at its production value. Running this reset the setting and the servers have run without a performance issue since!

In testing this more since, here is what we found the defaults to be (roughly):

Database

Min Memory

Max Memory

RTCLOCAL

12% of installed

15% of installed

LYNCLOCAL

6% of installed

8% of installed


 

Monday, January 14, 2013

Creating a Conferencing Directory after you delete it

In OCS 2007 R2, the decommission steps are widely documented by both Microsoft Technet and many other bloggers.  And with Lync 2010 and Lync 2013 now being generally available, I find myself cleaning up a few OCS 2007 R2 implementations.  I got fairly comfortable with the steps, and I goofed on the order of things.  I removed the assigned conferencing directories to an OCS pool before I deactivated the Conferencing Attendant.

I found this related post on Lee Desmond's blog, which matched the error I was receiving in my attempted deactivation:

"A call to a subtask failed.: The call to subtask AppServer.GetAppState failed. Pool is not ready."

The error associated was  0xc3FC200D

I searched a while and finally found that I made the mistake of removing the conferencing directory prior to deactivating the Conferencing Attendant.  Simple, enough - I'd just need to create a new conferencing directory.  Only there is not a way to do so in the OCS GUI.  So I had to take to ADSIEdit.msc for this one.

Much of this is thanks to this blog entry, which solves a different issue, but contained most of the knowledge I needed!

Open ADSIEDIT.
Navigate to the following:
CN=Configuration.
CN=Configuration,DC=,DC=com
CN=Services.
CN=RTC Service.
CN=Conference Directories.

Right Click on "CN=Conference Directories".
New -> Object
On the New Windows that opens which says "Select a Class:" choose msRTCSIP-ConferenceDirectory
In the Value Field type 2.
Note:- Value Field corresponds to the Common-Name of the Conference Object that we are creating.

Click on Next.
Click on Finish.

Now under the "CN=Conference Directories" we will see the new Directory Created with name "CN=2".

Now expand the following.
CN=Configuration.
CN=Configuration,DC=,DC=com
CN=Services.
CN=RTC Service.
CN=Pools
CN=
CN=Microsoft
CN=LC Services

Right Click on "CN=LC Services" and go to properties.
Check for the Attribute called distinguishedName.
Copy the value of distinguishedName.

Now expand the following.
CN=Configuration.
CN=Configuration,DC=,DC=com
CN=Services.
CN=RTC Service.
CN=Conference Directories.
Cn=2

Right Click on the "CN=2" and go to the Properties.
Check for the Attribute msRTCSIP-ConferenceDirectory.
Paste the distinguishedName Value here.

Also check for the Attribute msRTCSIP-ConferenceDirectoryId
Enter the Value 2 there.
Now, close and reopen (refresh didn't seem to pull the update) your OCS server console, and you should see your Conferencing Directory ID of "2" show up again.  Now you can deactivate the Conferencing Attendant successfully!

Tuesday, December 11, 2012

Lync Profiles tool for Lync 2010 and 2013

OK, So I typically only post things here when I learn them or document them myself...   but today I am posting something just for the sheer amount of time it will save me, and possibly you.  I reached out to co-worker and well known Lync blogger Jeff Schertz asking if he has ever heard of a way to have profiles in Lync like you can in Outlook.  I spend about 20-30 minutes per day retyping SIP URI's, server names, etc to sign into multiple Lync environments.  To my amazement, he replied  minutes later with this gem.

Lync Profiles for Lync 2010
Lync Profiles for Lync 2013

This really simple tool allows you to have preconfigured Lync profiles and allows for a single click to sign out of one environment/user and into another.  Most excellent!  Thanks Jeff!


Thursday, September 06, 2012

Move Mailboxes and Notify Users

I wrote this script for an Exchange 2003 to Exchange 2010 migration. The administrator wanted a way to communicate with users when their mailbox move was complete, as well as give him a way to monitor the progress of mailbox moves without sitting in front of the computer all night.

This script was tested in an Exchange 2010 SP2 environment where anonymous relay from specific hosts was allowed. 

Purpose

The script accomplishes the following:
-        Create move requests for users specified in the $MailboxestoMove variable at the top
-        Moves each mailbox and monitors status every 30 seconds
-        Will output “Moving Users…” to the screen  every 30 seconds while moves are in process
-        As a move completes with a “complete” status, an email is sent to the user – subject and body defined by variables at the top ($MessageSubject and $MessageBody). Then, the completed move request is cleared
-        As a move request completes with a “CompletedWithWarning” status, an email is sent to the user – the subject and body are defined by variables at the top ($MessageSubject and $MessageBody). Next, an email is sent to the administrator – the subject and body are defined by variables at the top($MessageSubjectWarning and $MessageBodyWarning) – which includes the move history report so you can investigate the warning. Then, the completed move request is cleared
-        If a move request completes with a “Failed” status, then an email is sent to the administrator – the subject and body are defined by variables at the top ($MessageSubjectFailure and $MessageBodyFailure) – which includes the move history report so you can investigate the warning. Then, the failed move request is cleared.   NOTE: an email is NOT sent to the user
-      When all move requests have completed and cleared, an email is sent to the administrator – the subject and body are defined by variables at the top($MessagesSubjectComplete and $MessageBodyComplete). Once this email has been sent, the script ends.

Usability

To use the script, editing the values of the following variables is required:
-        $MailboxestoMove
-        $TargetDB
-        $SMTPServer
-        $SMTPFrom
Optionally, edit the message subject and body variables.

To run the script:
-        Open an elevated Exchange PowerShell window
-        Save the text file as a .PS1 file type rather than TXT
-        Navigate to the place the script is saved
-        Type .\MoveUsersandNotifyv2.7-Final.PS1
-        Script will begin running.

Feature Requests for a Future Version

There are a few things that I think could be improved in order to make this a really great tool.
  • Turn the script into a CMDlet. Doing that would involve wrapping the script in a function, parameterizing the 12 input variables, saving the script as a PSM1, and putting it in the /modules subfolder of your Exchange installation. If anyone does this before I get around to it, please post the updated script.
  • The script does not handle move requests that are suspended or automatically suspended. It completely ignores them. Additional code would need to be written to add script blocks to handle these two move request status types
  • The script assumes that there are no existing move requests when it begins running. If you run the script while there are existing requests, the script will get stuck in an infinite loop because it doesn't know of the existing request.

The Script

#Copyright 2012
#Author: Robin Lehr
#Last Modified Date 09/06/12
#Names of the users you would like to move, enclosed in double quotes and 

#separated by commas. Type these in the format of the user's email address

$MailboxestoMove="test@contoso.com", "test2@contoso.com"

#Type the name of the database you would like to move the users to
$TargetDB = "TestDB2"

#Set variables for sending email
$SMTPServer="smtp.contoso.com"
$SMTPFrom="administrator@contoso.com"
$MessageSubject="Your Mailbox Move is Complete!"
$MessageSubjectFailure="FAILURE: There are one or more failed move requests"
$MessageSubjectWarning="WARNING: There are one or more move requests that completed with warnings"
$MessageSubjectComplete="All Move Requests Have Been Processed" 
$MessageBody="$User - Thank you for your patience, your mailbox move request is complete"
$MessageBodyFailure="The Move request for $User has failed. The Move Request Report says: $StatusReport"
$MessageBodyWarning="The Move request for $User has completed with warnings. The Move Request Report says: $StatusReport"
$MessageBodyComplete="All Move Requests with status other than suspended are complete." 
#End of Variables

$UserstoMove=New-Object System.Collections.ArrayList
ForEach($Mailbox in $MailboxestoMove)
{
    $UserstoMove.Add($Mailbox)
}

#Create Array to remove users from loop processing
$removeUsers=New-Object System.Collections.ArrayList
ForEach ($User in $UserstoMove)
 {
     New-MoveRequest -Identity $User -TargetDatabase $TargetDB -WarningAction "SilentlyContinue"
 }
$Moves=Get-MoveRequest | Where {$_.Status -ne "AutoSuspended" -and $_.Status -ne "Suspended"}
$requests=($Moves|group-object status).count
Do 
 {
 Start-Sleep -seconds 30
 ForEach ($User in $UserstoMove) 
   {
    #Define Variable that will determine the move request status
    $MoveStatus=Get-MoveRequest -Identity $User
    if($MoveStatus.Status -eq "Completed") 
   {
          $SMTPTo=$User
          $SMTP=New-Object Net.Mail.SmtpClient($SMTPServer)
          $smtp.Send($SmtpFrom,$SmtpTo,$messageSubject,$MessageBody)
          Remove-MoveRequest $user -Confirm:$false
          $RemoveUsers.Add($User)
   }
        ElseIf($MoveStatus.Status -eq "Failed") 
   {
       #This Command will send a report for failed move requests
        $StatusReport=Get-MailboxStatistics -Identity $User -IncludeMoveReport

#In this case the email should go to the administrator, which is assumed to 
#be the same as the SMTP From Address. That is why the $SMTPFrom variable is 
#repeated twice in the send command.

        $SMTP=New-Object Net.Mail.SmtpClient($SMTPServer)
        $smtp.Send($SmtpFrom,$SmtpFrom,$messageSubjectFailure,$MessageBodyFailure)

#This script block will send the move request history report and then remove 
#the request. If you do not wish this behavior to happen, comment out the below line. 

#IMPORTANT: if the "Remove-Moverequest" line below is commented out, you 
# MUST also add the following to the Where-Object conditions of the 
# $Moves=Get-MoveRequest line above:
# -and $_.Status -ne "Failed"
            Remove-MoveRequest $User -Confirm:$false
            $RemoveUsers.Add($User)
        }

#In this case the email should go to the administrator, which is assumed to 
#be the same as the SMTP From Address. That is why the $SMTPFrom variable is 
#repeated twice in the send command.

        ElseIf($MoveStatus.Status -eq "CompletedWithWarning") 
        {
#This Command will send a report for failed move requests 
            $StatusReport=Get-MailboxStatistics -Identity $User -IncludeMoveReport
            $SMTP=New-Object Net.Mail.SmtpClient($SMTPServer)
            $smtp.Send($SmtpFrom,$SmtpFrom,$messageSubjectWarning,$MessageBodyWarning)
            $smtp.Send($SmtpFrom,$SmtpTo,$messageSubject,$MessageBody)
            Remove-MoveRequest $User -Confirm:$false
            $RemoveUsers.Add($User)
        } Else {
        Write-Host "Moving Users..."
        }
    } 


#Remove Users who are complete
    ForEach ($value in $UserstoRemove)
    {
        $UserstoMove.Remove($value)
    }

#Find the number of move requests
    $Moves=Get-MoveRequest | Where {$_.Status -ne "AutoSuspended" -and $_.Status -ne "Suspended"}
    $requests=($Moves|group-object status).count
    } 
    Until($requests -eq 0 -or $requests -eq $null) 
#Send Email to Administrator that moves are complete
$SMTP=New-Object Net.Mail.SmtpClient($SMTPServer)
$smtp.Send($SmtpFrom,$SmtpFrom,$messageSubjectComplete,$MessageBodyComplete)
 

Labels:

Wednesday, August 29, 2012

Lync 2013 - Using ClsController.exe instead of ocslogger.exe


Required Reading: 

One of the things that I felt that Jens did not cover was additional detail on sub components of the scenarios that Microsoft gives us with the new clscontroller.exe.  Below are a list of the scenarios, the text name  of the scenario, and the logging subcomponents included in the scenario.

All of this detail is attainable using the method Jens described in the bottom of his post, I just cleaned it up and made a table, so all the credit is to his work.  :)

One of the things that I have not really seen discussed or posted about much is that when using clscontroller, one of the intended benefits is that you do not have to stop/start logging.    AlwaysOn is….  Always on.  So you can just utilize the last command in Jen's blog:

.\ClsController.exe -search -pools redmond.contoso.com -components SipStack -loglevel verbose > c:\temp\redmond_sipstack_logs.txt

You can further narrow your search using -phone, -uri, or -ip like this:
.\ClsController.exe -search -pools redmond.contoso.com -components SipStack -loglevel verbose -uri john@contoso.com > c:\temp\redmond_sipstack_logs_filtered.txt

I have not been able to successfully utilize  the filters however, and started a forum post here regarding it.


Scenario
Description
Logging Subcomponents
AlwaysOn
This scenario will the one that is always running when no other scenario is active.  This is the one the registry will be configured with to enable on machine startup
AsMcu
AVMCU
AVMP
CAAServer
Collaboration
DataMCU
DataMcuRuntime
ExumRouting
IMMCU
InboundRouting
InterClusterRouting
McuInfra
MediationServer
OutboundRouting
Routing_Data_Sync_Agent
S4
ServerTransportAdaptor
Sipstack
LDM
AppShareOoty
RdpApiTrace
UserServices
UDCAgent
PNCHService
TenantAdminUI
HostedMigration
Powershell
UCWA
GCCommon
GCEndpoint
GCServer
GCCompliance
GCWebService
XmppTGW
XmppCommonLibrary
XmppListener
XmppRouting
XmppTGWProxy
Lyss
StoreWeb
TranslationApplication
RgsClientsLib
RgsCommonLibrary
RgsDatastores
RgsDiagnostics
RgsHostingFramework
RgsMatchMakingService
RgsPowershell
CpsDiagnostics
CpsHostingFramework
CpsOrbit
JoinLauncher
WebInfrastructure
Infrastructure
InternalCommon
MediaConnectivity
Media Connectivity
MediaStack_AUDIO_AGC
MediaStack_AUDIO_DRC
MediaStack_AUDIO_ECHODT
MediaStack_AUDIO_FAXDT
MediaStack_AUDIO_HEALER
MediaStack_AUDIO_NOISEDT
MediaStack_AUDIO_VAD
MediaStack_AUDIO_VSP
MediaStack_AudioCodecs
MediaStack_AudioEngine
MediaStack_COMAPI
MediaStack_COMMON
MediaStack_Crossbar
MediaStack_Crypto
MediaStack_DebugUI
MediaStack_DebugUI_AEC
MediaStack_DEVICE
MediaStack_MassConvertedTraces1
MediaStack_MediaManager
MediaStack_PerFrame
MediaStack_PerPacket
MediaStack_QualityController
MediaStack_RTCP
MediaStack_RTP
MediaStack_StreamingEngine
MediaStack_TLS
MediaStack_Transport
MediaStack_VIDEO
MediaStack_VOICEENHANCE
ApplicationSharing
Application Sharing
AsMcu
AppShareOoty
ServerTransportAdaptor
RDPApiTrace
MCUInfra
Collaboration
S4
AudioVideoConferencingIssue
Audio Video Conferencing Issue
AvMcu
AvMP
MCUInfra
Collaboration
S4
HybridVoice
Hybrid Voice
MediationServer
S4
Sipstack
OutboundRouting
TranslationApplication
IncomingAndOutgoingCall
Incoming And Outgoing Call
MediationServer
S4
Sipstack
TranslationApplication
OutboundRouting
InboundRouting
UserServices
VoiceMail
Voice Mail
Sipstack
Sipstack*
ExumRouting
InboundRouting
IMAndPresence
IM And Presence
Sipstack
UserServices
AddressBook
Address Book
ABCommon
ABServer
ABServerIISModule
Dlx
DeviceUpdate
Device Update
DeviceUpdate
DeviceUpdateHttpHandler
LYSSAndUCS
LYSS And UCS
UserServices
Lyss
McuInfra
CLS
Centralized Logging Service
CLSAgent
CLSCommon
CLSController
CLSControllerLib
SP
Support Portal
SupportPortal
SPHelper
SPModule
SPSearchTool
SPCLSTool
CLSCommon
CLSControllerLib
WAC
WAC
DataMCURunTime
DataMCU
LDM
Infrastructure
WebInfrastructure
InternalCommon
UserReplicator
User Replicator
UserServices
HostedMigration
Hosted Migration
HostedMigration
Powershell
WebInfrastructure
MonitoringAndArchiving
Monitoring And Archiving
UDCAgent
LILRLegacy
LILR Legacy
LogRetention
LegalIntercept
LILRLYSS
LILR LYSS
LogRetention
UDCAgent
MeetingJoin
Meeting Join
Collaboration
S4
UserServices
McuInfra
JoinLauncher
WebInfrastructure
Infrastructure
InternalCommon
UCWA
RGS
Response Group Service
RgsClientsLib
RgsCommonLibrary
RgsDatastores
RgsDeploymentApi
RgsDeploymentLibrary
RgsDiagnostics
RgsHostingFramework
RgsMatchMakingService
RgsPowershell
Collaboration
S4
Sipstack
CPS
Call Park Service
CpsDiagnostics
CpsHostingFramework
CpsOrbit
Collaboration
S4
Sipstack
XMPP
XMPP Gateway
XmppTGW
XmppCommonLibrary
XmppListener
XmppRouting
XmppTGWProxy
Collaboration
S4
Sipstack
CAA
Conference Auto Attendant
CAAServer
Collaboration
S4
Sipstack
UserServices

*Not sure why, but it was listed twice.



Labels:

Tuesday, June 26, 2012

WinRM QuickConfig failing with 0x8033809D

There are a few posts out there on this that point to a few different things on this error while running winrm qc.

 PS C:\Users\administrator> winrm quickconfig
WinRM already is set up to receive requests on this machine.
WSManFault
    Message = WinRM cannot process the request. The following error occured while using Negotiate authentication: An unknown security error occurred.
 Possible causes are:
  -The user name or password specified are invalid.
  -Kerberos is used when no authentication method and no user name are specified.
  -Kerberos accepts domain user names, but not local user names.
  -The Service Principal Name (SPN) for the remote computer name and port does not exist.
  -The client and remote computers are in different domains and there is no trust between the two domains.
 After checking for the above issues, try the following:
  -Check the Event Viewer for events related to authentication.
  -Change the authentication method; add the destination computer to the WinRM TrustedHosts configuration setting or use HTTPS transport.
 Note that computers in the TrustedHosts list might not be authenticated.
   -For more information about WinRM configuration, run the following command: winrm help config.

Error number:  -2144108387 0x8033809D
An unknown security error occurred.

Keep in mind what you are doing, opening WinRM via HTTP/HTTPS.  Check what your server is configured for (80 or 443, or both) and review the SPN's, and add what is needed.

To review (read only)
setspn.exe -L MACHINENAME

Review the results for HTTP/HTTPS entries (or any duplicates as well)

 Add missing names:
setspn -A HTTP/machinename
setspn -A HTTP/machinename.fqdn.com
setspn -A HTTPS/machinename
setspn -A HTTPS/machinename.fqdn.com

They reattempt your quickconfig.