Technical Article

PowerShell to Pre-Create domain objects for SQL Server Cluster

,

As a DBA, you probably nod dissaprovingly when a vendor or a developer claims they need [sysadmin] priviledges on your SQL Instance in order for their code or product to work.  I have also seen this look on the face of many domain admins (DA) when they are approached by the DBA who claims they need full create, edit, delete, property change rights on the main Computers OU in the corporate Active Directory, because SQL Clustering requires it.  If this is you, brace yourself for a disapproving nod from your DA.

My preferred alternative, one shared by my DA is to create a separate OU in the Active Directlry for all SQL Cluster related objects [ex: SQLCLuster], and let the DA pre-create the computer  objects.  Your only job is to establish all the names you intend to create during the installation of your SQL Cluster.

My personal naming convention for creating Computer Objects to support a SQL Cluster are:

  • SQLPRODc01
  • SQLPRODc01-fs1
  • SQLPRODc01-sql08
  • SQLPRODc01-DTC1
  • SQLPRODc01-sql08r2
  • SQLPRODc01-DTC2
  • SQLPRODc01-sql12
  • SQLPRODc01-DTC3

This script will allow the Domain Admin to create the OU if it does not already exist, and then create the computer object (one per run)  and place it into that OU.  

It is imperative that the new computer object is created as DISABLED (this is taken care of in this script), because when you eventually create the clustered resource in windows, it will look for the unused computer object with a specified name to revive and claim to complete its setup.

It is also crucial that the Domain Admin manually affect the permissions of the created objects.  Once the main cluster computer account (SQLPRODc01$) is created, it needs to be added to the subsequent computer Security tab with FULL CONTROL on all subsequent objects related to that cluster.  I could not elegently script a solution to automate this; any help or enhancements are welcomed.

<#
WHO:   Fahim Ahmad DBA Manager 
WHEN:  2013-04-15
WHY:   Pre-Create AD Organizational Units and Computer objects for clustering
WHERE: (DBAFahim a t g m a i l . c o m)
       https://plus.google.com/102254351697166166538
#>


    # BEGIN USER INPUT //////////////////////////////////////////////
$OU     = "Cluster"
    $DistinguishedName = "DC=DBA,DC=TEST,DC=com"

    $DNSHost         = "DBA.TEST.com" 

$NewComputerName = "SQLPRODc01" 
$NewComputerDesc = "Failover cluster virtual network name account." 
    # END USER INPUT ////////////////////////////////////////////////

Set-ExecutionPolicy Unrestricted
    cls
    
    $PathOU          = "OU=$OU,$DistinguishedName"
    $PathComputer    = "CN=$NewComputerName,$PathOU"
    $ADConnection    = [adsi]"LDAP://$DistinguishedName"

TRY
{
    # VERIFY the OU exists, if not, then create
    # Inspiration: http://www.anuragg.com/2013/03/create-ou-in-active-directory-using.html
    if (!([adsi]::Exists("LDAP://$PathOU")))
    {
        $CreateOU = $ADConnection.Create("OrganizationalUnit","OU= $OU")
        $CreateOU.SetInfo()
        Write-Host "OU does not yet exist, creating OU:: "$PathOU
        Write-Host "CREATED :: $PathOU " -foregroundcolor Green

        Write-Host "NOTE: MANUAL STEP REQUIRED
    After this OU is created, you must add the cluster administration account [ex: Domain\SQLClusterAdmin] to the security of the new OU with FULL CONTROL permissions." -foregroundcolor Black -BackgroundColor Cyan
    }
    else
    {
        Write-Host "WARNING :: $PathOU OU already existed" -foregroundcolor Cyan
    }

    # VERIFY the COMPUTER exists, if not, then create
    if (!([adsi]::Exists("LDAP://$PathComputer")))
    {
    $CreateComputer = $ADConnection.Create("computer", "CN=" + $NewComputerName.ToUpper() + ",OU="+$OU) 
    $CreateComputer.Put("sAMAccountName",$NewComputerName + "$") # A dollar sign must be appended to the end of every computer sAMAccountName. 
    $CreateComputer.Put("DNSHostName",$NewComputerName+"."+$DNSHost) 
    $CreateComputer.Put("Description",$NewComputerDesc) 
    $CreateComputer.Put("userAccountControl", 4098)  # to create a disabled computer account you would add the decimal values of the UAC's WORKSTATION_TRUST_ACCOUNT=4096 and ACCOUNTDISABLE=2 which equals 4098
    $CreateComputer.SetInfo() 

        Write-Host "CREATED :: $PathComputer " -foregroundcolor Green

        Write-Host "NOTE: MANUAL STEP REQUIRED
    After this computer object is created, you must add the cluster computer account [$OrigClustName$] to the security of the new computer with FULL CONTROL permissions. " -foregroundcolor Black -BackgroundColor Cyan
    }
    else
    {
        Write-Host "WARNING :: $PathComputer Computer already existed" -foregroundcolor Cyan
    }
}    

Catch [System.UnauthorizedAccessException]
{
   $userName = [Environment]::UserDomainName+"\"+[Environment]::UserName
   Write-Host $_.Exception.ToString() -Backgroundcolor RED
   Write-Host "Most Likely Reason: $userName does not have create object rights on the Domain.  You most likely need to log in as Domain Admin." -Backgroundcolor RED
}
Catch [System.DirectoryServices.DirectoryServicesCOMException]
{
   $userName = [Environment]::UserDomainName+"\"+[Environment]::UserName
   Write-Host $_.Exception.ToString() -Backgroundcolor RED
   Write-Host "Most Likely Reason: $userName does not have create object rights on the Domain.  You most likely need to log in as Domain Admin." -Backgroundcolor RED
}
Catch [System.Exception]
{
   Write-Host $_.Exception.ToString() -Backgroundcolor RED
}



Finally
{
# VERIFY the specific computer now exists in the desired OU
$computers = ([adsisearcher]"ObjectCategory=computer")
$computers.Filter="name=$NewComputerName*"
$computer=$computers.FindAll()
$FoundDistinguishedNames = $computer.properties.distinguishedname

    if ($FoundDistinguishedNames)
    {
        foreach($DistinguishedName in $FoundDistinguishedNames)
        {
            if ($PathComputer -eq $DistinguishedName)
            {
                Write-Host "FOUND  :: "$DistinguishedName -foregroundcolor green
            }
            else
            {
                Write-Host "SIMILAR:: "$DistinguishedName -foregroundcolor White
            }
        }
    }
    else
    {
        Write-Host "FAILURE :: $PathComputer not found"-Backgroundcolor RED
    }

}

Rate

5 (1)

You rated this post out of 5. Change rating

Share

Share

Rate

5 (1)

You rated this post out of 5. Change rating