Note
Access to this page requires authorization. You can try signing in or changing directories.
Access to this page requires authorization. You can try changing directories.
In an earlier post “Active Directory Powershell to manage sites – Part 1 (New-XADSite)” Jairo explained in detail about how to create a Site in Active Directory using AD Powershell. In today’s post I am going to discuss about how to create Subnets using AD Powershell.
Before going into details of creating a subnet object, first let us understand what is a Site and Subnet.
The following definition is from: https://technet.microsoft.com/en-us/library/cc782048(WS.10).aspx
|
A subnet object (objectClass=subnet) in AD DS stores the prefix information in its name and the site information in attribute siteObject. It should be created under “CN=Subnets,CN=Sites,<Configuration-NC>”. For documentation on “how to determine the prefix of a subnet” bing for the phrase “Entering Address Prefixes”.
I have written a function below called New-XADSubnet that creates a new subnet. It accepts the subnet-prefix, site name, description and ___location of the subnet as input. The function also does some validation to provide a reliable experience, for example: it validates whether the specified subnet prefix length is correct or not. If a prefix length is not specified then this function will auto-generate the prefix length based on the number of trailing zero bits found in the prefix-ip-address.
NOTE: The script below uses Test-XADObject function published in a previous post.
1: #
2: # Advanced Function to create a new subnet.
3: #
4: function New-XADSubnet() {
5: [CmdletBinding(ConfirmImpact="Low")]
6: Param (
7: [Parameter(Mandatory=$true,
8: Position=0,
9: ValueFromPipeline=$true,
10: HelpMessage="Prefix of the subnet to be created. This should be a combination of IP Address followed by / and Prefix length. IPv4 example: 157.54.208.0/20 IPv6 example: 3FFE:FFFF:0:C000::/64 . NOTE: If the prefix length is not specified then this cmdlet will auto-generate the prefix length based on the number of trailing zero bits. For example: If supplied Prefix is 157.54.208.0 then the subnet created is 157.54.208.0/20. Another example: If supplied Prefix is 3FFE:FFFF:0:C000:: then the subnet created is 3FFE:FFFF:0:C000::/34"
11: )]
12: [String] $Prefix,
13: [Parameter(Mandatory=$false,
14: Position=1,
15: ValueFromPipeline=$false,
16: HelpMessage="Site to which the subnet will be applied. Accepts Site name, Guid, DN or ADObject representing the site"
17: )]
18: [Object] $Site,
19: [Parameter(Mandatory=$false,
20: ValueFromPipeline=$false,
21: HelpMessage="Description"
22: )]
23: [String] $Description,
24: [Parameter(Mandatory=$false,
25: ValueFromPipeline=$false,
26: HelpMessage="Location"
27: )]
28: [String] $Location
29: )
30: PROCESS {
31:
32: if ([String]::IsNullOrEmpty($Prefix)) {
33: throw New-Object System.Management.Automation.PSArgumentException("Prefix name cannot be an empty string, please try again.")
34: }
35:
36: $newSubnetName = $Prefix
37:
38: if ($Prefix.Contains("/")) {
39: $subnetIPAddressStr,$prefixLengthStr = $newSubnetName.Split("/")
40: $subnetIPAddress = [System.Net.IPAddress]::Parse($subnetIPAddressStr)
41: $specifiedPrefixLength = [int]::Parse($prefixLengthStr)
42:
43: $ipAddressPrefixLength = GetIPAddressPrefixLength $subnetIPAddress
44: if ($ipAddressPrefixLength -gt $specifiedPrefixLength) {
45: throw New-Object System.Management.Automation.PSArgumentException("The subnet prefix length you specified is incorrect. Please check the prefix and try again.")
46: }
47:
48: } else {
49: $subnetIPAddress = [System.Net.IPAddress]::Parse($newSubnetName)
50: $prefixLength = GetIPAddressPrefixLength $subnetIPAddress
51: $newSubnetName = $newSubnetName + "/" + $prefixLength
52: }
53:
54: # Get the configuration partition DN, the sites container and build the new site DN
55: $configNCDN = (Get-ADRootDSE).ConfigurationNamingContext
56: $subnetContainerDN = ("CN=Subnets,CN=Sites," + $configNCDN)
57: $newSubnetDN = ("CN=" + $newSubnetName +"," + $subnetContainerDN)
58: $siteDN = $null
59: if ($Site -ne $null) {
60: $siteDN = (Get-XADSite $Site).DistinguishedName
61: }
62:
63: # Verify if the subnet already exists
64: $subnetExists = Test-XADObject -Identity $newSubnetDN
65: if ($subnetExists) {
66: throw New-Object System.Management.Automation.PSArgumentException("Subnet already exists. Please check the name and try again.")
67: }
68:
69: [Hashtable] $ht = new-object -type hashtable
70: if ($siteDN -ne $null) {
71: $ht.Add("siteObject", $siteDN)
72: }
73: if (-not [String]::IsNullOrEmpty($Description)) {
74: $ht.Add("description", $Description)
75: }
76: if (-not [String]::IsNullOrEmpty($Location)) {
77: $ht.Add("___location", $Location)
78: }
79:
80:
81: # Create subnet object
82: if ($ht.Count -eq 0) {
83: New-ADObject -Name $newSubnetName -Path $subnetContainerDN -Type subnet
84: } else {
85: New-ADObject -Name $newSubnetName -Path $subnetContainerDN -Type subnet -OtherAttributes $ht
86: }
87:
88: # Fetch the subnet object
89: Get-ADObject $newSubnetDN -properties "siteObject", "description", "___location"
90:
91: }
92: }
93:
94:
95:
96: #
97: # Internal utility function
98: # This function returns the number of trailing zeroes in the input byte
99: #
100: function GetNumberOfTrailingZeroes {
101: Param ([byte] $x)
102: $numOfTrailingZeroes = 0;
103: if ( $x -eq 0) {
104: return 8
105: }
106: if ( $x % 2 -eq 0) {
107: $numOfTrailingZeroes ++;
108: $numOfTrailingZeroes += GetNumberOfTrailingZeroes($x/2);
109: }
110: return $numOfTrailingZeroes
111: }
112:
113:
114:
115:
116: #
117: # Internal utility function
118: # This function returns the number of non-zero bits in an ip-address
119: #
120: function GetIPAddressPrefixLength {
121: Param ([System.Net.IPAddress] $ipAddress)
122: $byteArray = $ipAddress.GetAddressBytes()
123: $numOfTrailingZeroes = 0;
124: for ($i = $byteArray.Length - 1; $i -ge 0; $i--) {
125: $numOfZeroesInByte = GetNumberOfTrailingZeroes($byteArray[$i]);
126: if ($numOfZeroesInByte -eq 0) {
127: break;
128: }
129: $numOfTrailingZeroes += $numOfZeroesInByte;
130: }
131: (($byteArray.Length * 8) - $numOfTrailingZeroes)
132: }
Sample usage in my test environment:
PS AD:\>
PS AD:\> New-XADSubnet "10.10.0.0/16" -Location "Redmond,WA" -Description "Redmond Subnet"Description : Redmond Subnet
DistinguishedName : CN=10.10.0.0/16,CN=Subnets,CN=Sites,CN=Configuration,DC=dsw
amipat-w7-vm1,DC=nttest,DC=microsoft,DC=com
___location : Redmond,WA
Name : 10.10.0.0/16
ObjectClass : subnet
ObjectGUID : e4c924ff-ee39-47e3-8b92-71a8600188af
Cheers,
Swami
--
Swaminathan Pattabiraman
Developer – Active Directory Powershell Team
Comments
- Anonymous
October 29, 2010
The comment has been removed - Anonymous
July 26, 2011
It seems the code references a function Get-XADSite which isn't defined in provided code. Can you please provide missing code? - Anonymous
February 29, 2012
The comment has been removed - Anonymous
March 27, 2012
I had to manually create the Get-XADSite function using code examples from the Part 3 of this series:blogs.msdn.com/.../active-directory-powershell-to-manage-sites-and-subnets-part-3-getting-site-and-subnets.aspxHere is the function that I put together:Get a specified Active Directory Site. function Get-XADSite() {
}I've tested this with the New-XADSite function and it works; just created 45 subnets and associated them with appropriate sites.Param ([String] $siteName)$configNCDN = (Get-ADRootDSE).ConfigurationNamingContext$siteContainerDN = ("CN=Sites," + $configNCDN)$siteDN = "CN=" + $siteName + "," + $siteContainerDNreturn Get-ADObject -Identity $siteDN
- Anonymous
May 14, 2012
thancks PS AD:> PS AD:> New-XADSubnet "10.10.0.0/16" -Location "Redmond,WA" -Description "Redmond Subnet" Description : Redmond Subnet DistinguishedName : CN=10.10.0.0/16,CN=Subnets,CN=Sites,CN=Configuration,DC=dsw amipat-w7-vm1,DC=nttest,DC=microsoft,DC=com ___location : Redmond,WA Name : 10.10.0.0/16 ObjectClass : subnet ObjectGUID : e4c924ff-ee39-47e3-8b92-71a8600188af # # Advanced Function to create a new subnet. # function New-XADSubnet() { [CmdletBinding(ConfirmImpact="Low")] Param ( [Parameter(Mandatory=$true, Position=0, ValueFromPipeline=$true, HelpMessage="Prefix of the subnet to be created. This should be a combination of IP Address followed by / and Prefix length. IPv4 example: 157.54.208.0/20 IPv6 example: 3FFE:FFFF:0:C000::/64 . NOTE: If the prefix length is not specified then this cmdlet will auto-generate the prefix length based on the number of trailing zero bits. For example: If supplied Prefix is 157.54.208.0 then the subnet created is 157.54.208.0/20. Another example: If supplied Prefix is 3FFE:FFFF:0:C000:: then the subnet created is 3FFE:FFFF:0:C000::/34" )] [String] $Prefix, [Parameter(Mandatory=$false, Position=1, ValueFromPipeline=$false, HelpMessage="Site to which the subnet will be applied. Accepts Site name, Guid, DN or ADObject representing the site" )] [Object] $Site, [Parameter(Mandatory=$false, ValueFromPipeline=$false, HelpMessage="Description" )] [String] $Description, [Parameter(Mandatory=$false, ValueFromPipeline=$false, HelpMessage="Location" )] [String] $Location ) 30: PROCESS { if ([String]::IsNullOrEmpty($Prefix)) { throw New-Object System.Management.Automation.PSArgumentException("Prefix name cannot be an empty string, please try again.") } $newSubnetName = $Prefix if ($Prefix.Contains("/")) { $subnetIPAddressStr,$prefixLengthStr = $newSubnetName.Split("/") $subnetIPAddress = [System.Net.IPAddress]::Parse($subnetIPAddressStr) $specifiedPrefixLength = [int]::Parse($prefixLengthStr) $ipAddressPrefixLength = GetIPAddressPrefixLength $subnetIPAddress if ($ipAddressPrefixLength -gt $specifiedPrefixLength) { throw New-Object System.Management.Automation.PSArgumentException("The subnet prefix length you specified is incorrect. Please check the prefix and try again.") } } else { $subnetIPAddress = [System.Net.IPAddress]::Parse($newSubnetName) $prefixLength = GetIPAddressPrefixLength $subnetIPAddress $newSubnetName = $newSubnetName + "/" + $prefixLength } # Get the configuration partition DN, the sites container and build the new site DN $configNCDN = (Get-ADRootDSE).ConfigurationNamingContext $subnetContainerDN = ("CN=Subnets,CN=Sites," + $configNCDN) $newSubnetDN = ("CN=" + $newSubnetName +"," + $subnetContainerDN) $siteDN = $null if ($Site -ne $null) { $siteDN = (Get-XADSite $Site).DistinguishedName } # Verify if the subnet already exists $subnetExists = Test-XADObject -Identity $newSubnetDN if ($subnetExists) { throw New-Object System.Management.Automation.PSArgumentException("Subnet already exists. Please check the name and try again.") } [Hashtable] $ht = new-object -type hashtable if ($siteDN -ne $null) { $ht.Add("siteObject", $siteDN) } if (-not [String]::IsNullOrEmpty($Description)) { $ht.Add("description", $Description) } if (-not [String]::IsNullOrEmpty($Location)) { $ht.Add("___location", $Location) } # Create subnet object if ($ht.Count -eq 0) { New-ADObject -Name $newSubnetName -Path $subnetContainerDN -Type subnet } else { New-ADObject -Name $newSubnetName -Path $subnetContainerDN -Type subnet -OtherAttributes $ht } # Fetch the subnet object Get-ADObject $newSubnetDN -properties "siteObject", "description", "___location" } } # # Internal utility function # This function returns the number of trailing zeroes in the input byte # 100: function GetNumberOfTrailingZeroes { Param ([byte] $x) $numOfTrailingZeroes = 0; if ( $x -eq 0) { return 8 } if ( $x % 2 -eq 0) { $numOfTrailingZeroes ++; $numOfTrailingZeroes += GetNumberOfTrailingZeroes($x/2); } 110: return $numOfTrailingZeroes } # # Internal utility function # This function returns the number of non-zero bits in an ip-address # function GetIPAddressPrefixLength { Param ([System.Net.IPAddress] $ipAddress) $byteArray = $ipAddress.GetAddressBytes() $numOfTrailingZeroes = 0; 124: for ($i = $byteArray.Length - 1; $i -ge 0; $i--) { $numOfZeroesInByte = GetNumberOfTrailingZeroes($byteArray[$i]); if ($numOfZeroesInByte -eq 0) { break; } $numOfTrailingZeroes += $numOfZeroesInByte; } (($byteArray.Length * 8) - $numOfTrailingZeroes) }