Moving AD computers based on Ipaddress

Dave May 1 Reputation point
2022-08-24T17:05:29.363+00:00

Greetings,

I'm working for a medium to large enterprise that has never taken time to organize their computer objects based on site OU. Currently all of our machines are grouped under one OU. However each site has an independent DCHP scope, so the addresses are 192.168.1.x, 192.168.2.x, ect. So what I would like to do is use powershell to filter by subnet basically and move the objects to the corresponding OU. I am not new to powershell, but am by no means an expert. I was reviewing a post from a Eric Wright, but it's from 2011.

https://devblogs.microsoft.com/scripting/use-powershell-to-move-computers-based-on-ip-addresses-part-1/

There is a link to the full script, but it has long since broken.

In any case, this is the script I'm currently working with.

$ADComps= Get-ADComputer -Filter * -SearchBase "OU=Computers,DC=test,dc=com" -Properties ipv4address | Select-Object -Property Name, ipv4address |sort -Property name | Out-GridView -PassThru –title “Select Computers to Move”| Select -ExpandProperty Name

$ADOUs= Get-ADOrganizationalUnit -Filter * | Select-Object -Property DistinguishedName | Out-GridView -PassThru –title “Select Target OU”| Select-Object -ExpandProperty DistinguishedName

Foreach($ou in $ADOUs){

Foreach($comp in $ADComps){

get-adcomputer $comp |Move-ADObject -TargetPath "$ou" -Verbose }

}

And this works for what it's doing. But I'm trying to filter it down so that I can only aggregate the machines within the specific subnets so that I can move them with a bit more automation rather than selecting from the list and doing it that way. Any help is appreciated! Thanks everyone in advance!

Dave M-

Windows Server PowerShell
Windows Server PowerShell
Windows Server: A family of Microsoft server operating systems that support enterprise-level management, data storage, applications, and communications.PowerShell: A family of Microsoft task automation and configuration management frameworks consisting of a command-line shell and associated scripting language.
5,323 questions
0 comments No comments
{count} votes

3 answers

Sort by: Most helpful
  1. Andreas Baumgarten 94,196 Reputation points MVP
    2022-08-24T18:41:40.353+00:00

    Hi @Dave May ,

    I got the idea of sorting the computers by IP address in different OUs.
    How are the OUs structured and named (Name of OU -> IP-Subnet)?
    What subnet mask is used for the subnets? All are /24 or are the subnet masks different per subnet?
    And about how many IP-Subnets/OUs and computers are we talking? Just rough numbers to get an idea.

    ----------

    (If the reply was helpful please don't forget to upvote and/or accept as answer, thank you)

    Regards
    Andreas Baumgarten

    0 comments No comments

  2. Rich Matheisen 44,416 Reputation points
    2022-08-24T19:11:03.463+00:00

    Can you map the IPnetworks to the different OUs? If you can, then this might be one way to go about it in a hands-off way:

    $IpOuMap = @{}  
    $NeedsFixing = $false  
    Import-Csv c:\junk\IP-to-OU-Map.csv|  
        ForEach-Object{  
            If ($IpOuMap.ContainsKey($_.IP){  
                Write-Host "IP $($_.IP) : $($_.OU)) already mapped to $($IpOuMap.($_.IP))"  
                $NeedsFixing = $true  
            }  
            else {  
                $IpOuMap[$_.IP] = $_.OU  
            }  
        }  
    if ($NeedsFixing){ return } # don't go any farther until mapping is error-free  
      
    Get-ADComputer |  
        ForEach-Object{  
            $ipv4 = $_.IpV4Address  
            $x=$ipv4 -split "\."  
            $y = $x[0,1,2] -join "."  
            $ou = $IpOuMap.$y            # get OU name based on IP network  
            #  
            # move the computer (i.e. the AD Object) to it's new location here  
            #  
            # then do any other work to support the move  
            #  
        }  
    

    The CSV would look like this:

    IP,OU  
    192.168.1,"ou=US,dc=domain,dc=tld"  
    192.168.2,"ou=CA,dc=domain,dc=tld"  
    192.168.2,"ou=MX,dc=domain,dc=tld"  
    

    NONE of that code has been tested!

    0 comments No comments

  3. Andreas Baumgarten 94,196 Reputation points MVP
    2022-08-24T20:16:15.4+00:00

    Here is another approach (using a DataTable):

    # Define the DataTable (only once)  
    $table = ""  
    $table = New-Object system.Data.DataTable 'IP2OU'  
    $newcol = New-Object system.Data.DataColumn ouName, ([string]); $table.columns.add($newcol)  
    $newcol = New-Object system.Data.DataColumn Prefix, ([string]); $table.columns.add($newcol)  
         
    # Add DataTable rows  
    $row = $table.NewRow()  
    $row.ouName = ("OUSubnet4")  
    $row.Prefix = ("192.168.4.0")  
    $table.Rows.Add($row)  
      
    $row = $table.NewRow()  
    $row.ouName = ("OUSubnet3")  
    $row.Prefix = ("192.168.3.0")  
    $table.Rows.Add($row)  
      
    $row = $table.NewRow()  
    $row.ouName = ("OUSubnet2")  
    $row.Prefix = ("192.168.2.0")  
    $table.Rows.Add($row)  
      
    $row = $table.NewRow()  
    $row.ouName = ("OUSubnet1")  
    $row.Prefix = ("192.168.1.0")  
    $table.Rows.Add($row)  
      
    ### here we go with different IPs  
    $ips = "192.168.4.111", "192.168.3.27", "192.168.2.245", "192.168.1.10", "192.168.4.131", "192.168.3.127", "192.168.2.49", "192.168.1.68"  
    foreach ($ip in $ips) {  
        [ipaddress]$hostIP = $ip  
        [string]$prefix = ($hostIP.GetAddressBytes()[0..2] -join ".") + ".0"  
        $ou = ($table.Select("Prefix = '$prefix'")).ouName  
        Write-Output "OU for $ip is $ou"  
    }  
    

    ----------

    (If the reply was helpful please don't forget to upvote and/or accept as answer, thank you)

    Regards
    Andreas Baumgarten

    0 comments No comments