However, in a global IT infrastructure, there's always someone rebuilding a server with a new name. Imagine this: there's a very enthusiastic engineer who is testing a new multicast OS build method by installing OS on 200+ virtual machines (VM). And to make this test more comprehensive, he/she rebuilds these VMs with new names 4-5 times - but keeps the IP addresses because changing the MAC <-> IP assignment would be too much hassle... yeah, you got it right, cleaning up DNS is not that much hassle at all?! :)
So at the end of the test we end up with ~800 incorrect DNS records (which we initially don't know about).
I've got scripts to check out different aspects of list of servers remotely and if I hit a name which points to an IP of one of those VMs and it already has a new name, then all remote queries will fail (while ping will be successful). Why? Because Windows has a so called Strict Name checking, it does not allow incoming connections if the connection has a different target name. (unless you disable this behaviour).
Solution:
To make sure my checks are transparent, I need to see if a server's name is different to what it was on my list. Here is an example code which can do that. For the sake of the simple example, I want to query the last boot time of each host on a list:
# get the IP of the server from DNS
$ip = [System.Net.Dns]::GetHostAddresses($srv)[0].IPAddressToString
# creating an object to store results
$obj = "" | Select Computername,Real_computername,LastBootTime
$obj.Computername = $srv
# reading the name of the computer (contacted via its IP) from WMI
$obj.Real_computername = (gwmi -class Win32_ComputerSystem -ComputerName $ip).name
# reading boot time of the remote host
$obj.LastBootTime = (gwmi -class Win32_OperatingSystem -ComputerName $ip).lastbootuptime
To explain the essential line:
$ip = [System.Net.Dns]::GetHostAddresses($srv)
This line returns an array, but this time I only care about the first IP, so the [0] element of the array, because I have only 1 IP for each sever.
The rest of the script is straightforward and commented.
Example output:
Computername Real_computername LastBootTime ------------ ----------------- ------------ R2D2 NEWR2D2 20130129000920.125000+060
Entire example code:
## Usage: PS C:\> gc hostlist.txt | getBootTime.ps1
function PingServer ([string]$srv){
$ping = new-object System.Net.Networkinformation.Ping
Trap {Continue} $pingresult = $ping.send($srv, 3000, [byte[]][char[]]"z"*16)
if($pingresult.Status -ieq "Success"){$true} else {$false}
}
$hostlist = @($Input)
foreach($srv in $hostlist){
# get the IP of the server from DNS
$ip = [System.Net.Dns]::GetHostAddresses($srv)[0].IPAddressToString
if(PingServer $ip){
# creating an object to store results
$obj = "" | Select Computername,Real_computername,LastBootTime
$obj.Computername = $srv
# reading the name of the computer (contacted via its IP) from WMI
$obj.Real_computername = (gwmi -class Win32_ComputerSystem -ComputerName $ip).name
# reading boot time of the remote host
$obj.LastBootTime = (gwmi -class Win32_OperatingSystem -ComputerName $ip).lastbootuptime
$objcoll += $obj
}
}
May the Force...
t
No comments:
Post a Comment