'Call to 169.254.169.254/latest/meta-data/instance-id fails in AWS deployment script
I'm using some scripts based on http://blog.brianbeach.com/2014/07/setting-hostname-in-syspreped-ami.html to set the Host Name of a new windows instance created from an AMI to be the Name tag of the instance. Instead of HKLM:\System\Setup pointing to windeploy.exe, it runs a script which runs this:
$InstanceName = 'WebServerNew'
Try
{
Start-Transcript -Path D:\WebServerUtility\SysPrep\Windeploy.log -Append
Write-Host "Discovering instance identity from meta-data web service"
$InstanceId = (Invoke-RestMethod 'http://169.254.169.254/latest/meta-data/instance-id').ToString()
$AvailabilityZone = (Invoke-RestMethod 'http://169.254.169.254/latest/meta-data/placement/availability-zone').ToString()
$Region = $AvailabilityZone.Substring(0,$AvailabilityZone.Length-1)
Write-Host "Getting Tags for the instance"
$Tags = Get-EC2Tag -Filters @{Name='resource-id';Value=$InstanceId} -Region $Region
$InstanceName = ($Tags | Where-Object {$_.Key -eq 'Name'}).Value
Write-Host "`tFound Instance Name: $InstanceName"
}
Catch
{
Write-Host $_
$InstanceName = 'WebServerError'
}
try
{
If($InstanceName -ne $null) {
Write-Host "Setting the machine name to $InstanceName"
$AnswerFilePath = "C:\Windows\Panther\unattend.xml"
$AnswerFile = [xml](Get-Content -Path $AnswerFilePath)
$ns = New-Object System.Xml.XmlNamespaceManager($AnswerFile.NameTable)
$ns.AddNamespace("ns", $AnswerFile.DocumentElement.NamespaceURI)
$ComputerName = $AnswerFile.SelectSingleNode('/ns:unattend/ns:settings[@pass="specialize"]/ns:component[@name="Microsoft-Windows-Shell-Setup"]/ns:ComputerName', $ns)
$ComputerName.InnerText = $InstanceName
$AnswerFile.Save($AnswerFilePath)
}
}
Catch
{
Write-Host $_
}
Finally
{
Stop-Transcript
}
and THEN it calls WinDeploy.exe to finish the specialization.
The problem is that the line
Write-Host "Discovering instance identity from meta-data web service"
$InstanceId = (Invoke-RestMethod 'http://169.254.169.254/latest/meta-data/instance-id').ToString()
fails with "Unable to connect to the remote server".
Any idea why it would be unable to connect to that?
Solution 1:[1]
looks weird.. . URL looks correct.. Lets try to debug this. Let's isolate the problem and see if its script issue or something else.
- try telnet 169.254.169.254 80
if it says connected or not
- Also try http://169.254.169.254/latest/meta-data/instance-id on browser and see the output..
Also, try to run the script after system has initialized... Probably the time during which script is running; this local IP is not initialized.
Every time system starts ; EC2 Adds a custom route to the primary network adapter to enable the following IP addresses when multiple NICs are attached: 169.254.169.254. And this script of yours is getting executed before NICs are attached. Hence the problem.
Solution 2:[2]
Your script works perfectly fine for me.
The issue is that something on your instance is blocking access to that IP Address, such as a firewall.
Check your system configuration to see whether Windows Firewall is blocking access, or any other security software is installed that is blocking it.
Trying Invoke-RestMethod 'http://google.com'
would be a good test, too.
Solution 3:[3]
DHCP is started but Interface is not allocated IP intermittently and below is the workaround to get this done
Function Get-IP{
$global:initializedIP=netsh interface ip show address $interfaceName | where { $_ -match "IP Address"} | %{ $_ -replace "^.*IP Address:\W*", ""}
Write-host "`tInitialized IP: $initializedIP"
}
Function InitializeNetwork{
$global:interfaceName = netsh interface ipv4 show interfaces | where { $_ -match "Ethernet"}| %{ $_ -replace "^.*Connected\W*",""}
write-host "`tInterface name: $interfaceName"
$status = Invoke-Command -Command { netsh interface ipv4 set interface $interfaceName mtu=1460 }
Write-host "`tInitializing $interfaceName : $status"
Write-Host "`tStarting Service: DHCP"
Start-Service -Name 'Dhcp'
$r_status = Invoke-Command -Command { route /p add 169.254.169.254 mask 255.255.255.255 0.0.0.0 if 6 metric 1}
Write-Host "`tAdding metadata route $r_status"
}
Try {
Start-Transcript -Path C:\Temp\Windeploy.log -Append
Write-Host "[Meta-Data] Discovering instance identity from meta-data web service"
Set-Variable -Name "interfaceName" -value "Ethernet 2" -scope global
Set-Variable -Name "initializedIP" -value "169.254.169.254" -scope global
Write-Host "[Network] Initializing default network"
InitializeNetwork
Get-IP
While (-not ($initializedIP -like "10.*.*.*"))
{
Write-Host "`tGetting IP for $interfaceName"
Invoke-Command -Command {ipconfig /renew $interfaceName}
Get-IP
}
$Global:InstanceInfo = Invoke-WebRequest 'http://169.254.169.254/latest/dynamic/instance-identity/document/' -UseBasicParsing | ConvertFrom-Json
$AccountId = $InstanceInfo.accountId
$AWSRegion = $InstanceInfo.region
$InstanceId = $InstanceInfo.instanceId
Write-Host "[Instance-Tags] Getting Tags for the instance"
$Tags = Get-EC2Tag -Filters @{Name='resource-id';Value=$InstanceId} -Region $AWSRegion
Write-Host "`t$Tags"
#Generate windows hostname with lowercase letters/numbers only if meta-data not available
Write-Host "[ComputerName] Auto generate the default computer name."
$instanceName = "WIN-" + -join ((48..57) + (97..122) | Get-Random -Count 11 | % {[char]$_})
Write-Host "`tAuto Instance Name: $InstanceName"
If ($null -eq $Tags.Where( { $_.Key -eq "hostname" }).Value){
$instanceName="{0}{1}" -F $Tags.Where( {($_.Key).ToLower() -eq "appcode" }).Value, $InstanceId.Remove(0,($InstanceId.Length - 9))
}else{
$InstanceName = ($Tags | Where-Object {$_.Key -eq 'hostname'}).Value
}
Write-Host "`tFound Instance Name: $InstanceName"
If($InstanceName) {
Write-Host "[Unattend] Setting the machine name to $InstanceName"
$AnswerFilePath = "C:\Windows\Panther\Unattend.xml"
$AnswerFile = [xml](Get-Content -Path $AnswerFilePath)
$ns = New-Object System.Xml.XmlNamespaceManager($answerFile.NameTable)
$ns.AddNamespace("ns", $AnswerFile.DocumentElement.NamespaceURI)
$ComputerName = $AnswerFile.SelectSingleNode('/ns:unattend/ns:settings[@pass="specialize"]/ns:component[@name="Microsoft-Windows-Shell-Setup"]/ns:ComputerName', $ns)
$ComputerName.InnerText = $InstanceName
$AnswerFile.Save($AnswerFilePath)
Write-host "[Unattend] ComputerName is added."
}else{
Write-host "[Unattend] Unable to Set Instance Name"
}
Write-host "[BootMGR] Setting 0 Timeout to Boot Manager"
Invoke-Command -Command { bcdedit.exe /set "{bootmgr}" timeout 0 }
}
Catch {
Write-Host $_
}
Finally
{
Write-host "[Start-up] Starting OOBE Setup"
Start-Process C:\windows\system32\oobe\windeploy.exe -Wait
Stop-Transcript
}
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
Solution | Source |
---|---|
Solution 1 | |
Solution 2 | John Rotenstein |
Solution 3 | Rahul Trivedi |