Lab Manager Config IP List and RDP Test
Jump to navigation
Jump to search
<#
=============================================================================================
Lab Manager VM NAT Getter
=============================================================================================
Simon Strutt - November 2010
=============================================================================================
Version 1
- Initial creation!
Version 1.1 - Dec 2010
- Added bucketName when displaying list of config's to better handle config's with same name in different workspaces
Version 1.2 - Jan 2011
- Added sorting by VM name
Version 1.3 - Feb 2011
- Configuration selection menu...
-- Now sorted by name
-- Displays configs in yellow if they're not shared
Version 2.0 - Apr 2011
- Changed from single run to modular, continuous operation
- Added RDP port test
=============================================================================================
#>
$UserFile = "User.fil"
$PassFile = "Pass.fil" # Encrypted file to store password in
$LabMgrSvr = "lab-manager" # Hostname of your lab Manager server
$smtpSvr = "smtp" # Hostname of your SMTP server
$EmailFrom = "me@domain.com" # Email address to send from
$EmailDomain = "domain.com" # Email domain (used to guess email to send to)
$ScriptName = ($MyInvocation.MyCommand.Name).Replace(".ps1", "")
$host.UI.RawUI.WindowTitle = $ScriptName
# =============================================================================================
# Basic helper functions
function PressAnyKeyToExit {
Write-Host "Press any key to exit..."
$x = $host.UI.RawUI.ReadKey("NoEcho,IncludeKeyDown")
$labManager.Dispose()
Exit
}
# =============================================================================================
# Lab Manager SOAP connection functions (adapted from POSH - http://poshcode.org/753)
function New-ObjectFromProxy {
param($proxy, $proxyAttributeName, $typeName)
# Locate the assembly for $proxy
$attribute = $proxy | gm | where { $_.Name -eq $proxyAttributeName }
$str = "`$assembly = [" + $attribute.TypeName + "].assembly"
invoke-expression $str
# Instantiate an AuthenticationHeaderValue object.
$type = $assembly.getTypes() | where { $_.Name -eq $typeName }
return $assembly.CreateInstance($type)
}
function Connect-LabManager {
param($server, $credential)
Write-Host "Connecting to $server..."
# Log in to Lab Manager's web service.
$server = "https://" + $server + "/"
$endpoint = $server + "LabManager/SOAP/LabManager.asmx"
try {
$proxy = new-webserviceproxy -uri $endpoint -cred $credential -ErrorAction:Stop
} catch {
Write-Host $_
if ($_.ErrorDetails.Message -match "401: Unauthorized") {
Remove-Item $UserFile
Remove-Item $PassFile
Write-Host "User/pass credential cache files have been deleted"
} else {
Write-Host $_.Exception.Message
Write-Host $_.Exception.GetType().FullName
}
PressAnyKeyToExit
}
# Before continuing we need to add an Authentication Header to $proxy.
$authHeader = New-ObjectFromProxy -proxy $proxy -proxyAttributeName "AuthenticationHeaderValue" -typeName "AuthenticationHeader"
$authHeader.username = $credential.GetNetworkCredential().UserName
$authHeader.password = $credential.GetNetworkCredential().Password
$proxy.AuthenticationHeaderValue = $authHeader
return $proxy
}
function Ignore-SslErrors {
# Create a compilation environment
$Provider=New-Object Microsoft.CSharp.CSharpCodeProvider
$Compiler=$Provider.CreateCompiler()
$Params=New-Object System.CodeDom.Compiler.CompilerParameters
$Params.GenerateExecutable=$False
$Params.GenerateInMemory=$True
$Params.IncludeDebugInformation=$False
$Params.ReferencedAssemblies.Add("System.DLL") > $null
$TASource=@'
namespace Local.ToolkitExtensions.Net.CertificatePolicy {
public class TrustAll : System.Net.ICertificatePolicy {
public TrustAll() {
}
public bool CheckValidationResult(System.Net.ServicePoint sp,
System.Security.Cryptography.X509Certificates.X509Certificate cert,
System.Net.WebRequest req, int problem) {
return true;
}
}
}
'@
$TAResults=$Provider.CompileAssemblyFromSource($Params,$TASource)
$TAAssembly=$TAResults.CompiledAssembly
## We now create an instance of the TrustAll and attach it to the ServicePointManager
$TrustAll=$TAAssembly.CreateInstance("Local.ToolkitExtensions.Net.CertificatePolicy.TrustAll")
[System.Net.ServicePointManager]::CertificatePolicy=$TrustAll
}
# ===============================================================================================
# TCP Port test function (adapted from POSH - http://poshcode.org/85)
function Test-Port {
Param([string]$srv,$port=3389,$timeout=3000)
# Does a TCP connection on port 3389 (RDP), port and timeout can be overriden
$ErrorActionPreference = "SilentlyContinue"
# Create TCP Client
$tcpclient = new-Object system.Net.Sockets.TcpClient
# Tell TCP Client to connect to machine on Port
$iar = $tcpclient.BeginConnect($srv,$port,$null,$null)
# Set the wait time
$wait = $iar.AsyncWaitHandle.WaitOne($timeout,$false)
# Check to see if the connection is done
if(!$wait)
{
# Close the connection and report timeout
$tcpclient.Close()
Write-Host "Connection Timeout" -BackgroundColor DarkRed
Return
}
else
{
# Close the connection and report the error if there is one
$error.Clear()
$tcpclient.EndConnect($iar) | out-Null
if (!$?) {
write-host $error[0] -BackgroundColor DarkRed
$failed = $true
}
$tcpclient.Close()
}
# Return $true if connection Establish else $False
if (!$failed) {
Write-Host "Connection successful" -BackgroundColor DarkGreen
}
}
# Bussiness functions ==========================================================================
function Select-Configuration {
# Get list of configurations, query user which to do, and return selected config ID
$ConfIDs = @()
$confID = -99
# Get list of config's and display deployed only
Write-Host ("Deployed configurations...`n")
$Configs = $labManager.ListConfigurations(1)
$Configs = $Configs | Sort name
foreach ($config in $Configs) {
if ($config.isDeployed) {
if ($FontColour -eq "Gray") {
$FontColour = "White"
} else {
$FontColour = "Gray"
}
if ($config.isPublic) {
Write-host -ForegroundColor $FontColour ("ID " + $config.id + " - " + $config.name + " [" + $config.bucketName + "]")
} else {
Write-Host -ForegroundColor Yellow ("ID " + $config.id + " - " + $config.name + " [" + $config.bucketName + "] - Not Shared !!")
}
$ConfIDs += $config.ID # List of config ID's (with which to validate user input)
}
}
# Get config ID from user
While (!($ConfIDs -contains $ConfID)) { # Don't leave loop until user selected config ID is valid!
$ConfID = Read-Host "`nSelect a configuration ID [0 to quit]"
if (!$ConfID -or ($ConfID -eq 0)) {
# Dump the Lab Manager connection
$labManager.Dispose()
exit
} elseif (!($ConfIDs -contains $ConfID)) {
Write-Host "Invalid, should be one of" ([string]::join(", ", $ConfIDs))
}
}
Return $labManager.GetConfiguration($ConfID)
}
function Get-ConfigVMs {
Param($objConfig)
$VMs = @()
# Get VM's for selected config
$labManager.ListMachines($objConfig.id) | foreach {
$vm = "" | Select VM_Name, VM_IntIP, VM_ExtIP, VM_State
$vm.VM_Name = $_.name
$vm.VM_IntIP = $_.internalIP
$vm.VM_ExtIP = $_.externalIP
$vm.VM_State = $_.status # 1=Off, 2=On, 3=Suspended, 4=Stuck, 128=Invalid
$VMs = $VMs + $vm
}
$VMs = $VMs | Sort VM_Name
#$VMs | Select VM_Name, VM_IntIP, VM_ExtIP | Format-Table
Return $VMs
}
function Send-ConfigIPs {
Param($objConfig, $objConfVMs)
# Include VM Power State
$tmp = Read-Host "Include VM power state (on/off) [N]"
if ($tmp -and ($tmp -match "y")) {
$IncPowerState = 1
} else {
$IncPowerState = 0
}
# Email results to user
$EmailTo = $env:username + "@" + $EmailDomain
$tmp = Read-Host "Email to [$EmailTo]"
if ($tmp) {$EmailTo = $tmp}
Write-Host "Emailing $EmailTo..." -nonewline
# Create HTML for email
[string]$msgHTML = "<!-- Genenerated by $ScriptName at " + (Get-Date).ToString() + " hrs -->`n"
$msgHTML += "<html xmlns='http://www.w3.org/TR/REC-html40'>`n`n<head>`n<meta http-equiv=Content-Type content='text/html; charset=uk'`n>"
$msgHTML += "<meta name=Generator content='Lab Manager NATs script'>`n<meta name=Author content='Simon Strutt'>`n</head>`n`n"
$msgHTML += "<body style='font-family: arial; font-size: 10;'><table style='font-family: arial; font-size: 11';><tr><td>`nConfiguration:<td><b>" + $objConfig.name + "</b><tr><td>`nWorkspace:<td>" + $objConfig.bucketName
$msgHTML += "<tr><td>`nDescription:<td>" + $objConfig.description + "<tr><td>Info correct at:<td>" + (Get-Date).ToString() + " hrs</table>`n"
$msgHTML += "<br><br>`n`n"
$msgHTML += "<table border=1 style='border-width: 1px; border-spacing: 0; border-color: black; background-color: #faf0e6; font-family: arial; font-size: 11; font-weight: bold'>`n"
$msgHTML += "<tr style='border-width: 2px; background-color: #fcf7f8;'><th>VM Name"
if ($IncPowerState) {
$msgHTML += "<th>Power"
}
$msgHTML += "<th>Internal IP<th>External IP`n"
foreach ($vm in $objConfVMs) {
$msgHTML += "<tr><td>" + $vm.VM_Name
if ($IncPowerState) {
Switch ($vm.VM_State) {
1 {$msgHTML += "<td style='font-weight: normal; text-align: center'>Off"}
2 {$msgHTML += "<td style='text-align: center'>On"}
3 {$msgHTML += "<td style='font-weight: normal; text-align: center'>Suspended"}
4 {$msgHTML += "<td style='font-weight: normal; text-align: center'>Stuck"}
128 {$msgHTML += "<td style='font-weight: normal; text-align: center'>Invalid"}
default {$msgHTML += "<td style='font-weight: normal; text-align: center'>Unknown"}
}
}
$msgHTML += "<td style='font-weight: normal'>" + $vm.VM_IntIP + "<td>" + $vm.VM_ExtIP
}
$msgHTML += "</table>`n`n<br><br>`n<table style='font-family: arial; font-size: 10; color: #888888'>`n<tr><td>Generated by script: <td>$ScriptName"
$msgHTML += "`n</table>`n`n</body></html>"
#Send via email
$smtp = New-Object Net.Mail.SmtpClient -arg $smtpSvr
$msg = New-Object Net.Mail.MailMessage
$msg.From = $EmailFrom
$msg.To.Add($EmailTo)
$msg.Subject = "Lab Manager configuration: " + $objConfig.name
$msg.IsBodyHTML = $true
$msg.Body = $msgHTML
try {
$smtp.Send($msg)
} catch {
Write-Host "`n" $_
Write-Host "`nCopy text above if you want to retain the info."
PressAnyKeyToExit
}
Write-Host "sent !`n"
}
function Test-Access {
Param($objConfVMs)
# Check RDP access to powered-on VM's
Write-Host -ForegroundColor white "`nTesting RDP (TCP port) access to powered on servers..."
foreach ($vm in $objConfVMs) {
if ($vm.VM_State -eq 2) {
Write-Host ($vm.VM_Name).PadRight(16) ($vm.VM_ExtIP).PadRight(15) -nonewline
Test-Port $vm.VM_ExtIP
}
}
}
# ===============================================================================================
# Faff around with credentials and connect to Lab Manager server
# Check for credential files, create if required
if (!(Test-Path $UserFile) -or !(Test-Path $PassFile)) {
Write-Host "Credential files not found"
$cred = Get-Credential -Credential ($env:userdomain + "\" + $env:username)
$cred.UserName | Set-Content $UserFile -Force
$cred.Password | ConvertFrom-SecureString | Set-Content $PassFile -Force
Write-Host "Credentials saved"
}
# Load password credential from encrypted file
$pass = Get-Content $PassFile | ConvertTo-SecureString
$user = Get-Content $UserFile
$cred = New-Object System.Management.Automation.PsCredential($user, $pass)
# Connect to Lab Mgr server
Ignore-SslErrors
$labManager = Connect-LabManager -server $LabMgrSvr -credential $cred
Write-Host "Sucessfully connected to Lab Manager web service!"
# ==============================================================================================
# Get list of configurations, query user which to do, then get list of VM's and IP's
$option = 1
$Config = Select-Configuration
$host.UI.RawUI.WindowTitle = $ScriptName + " - " + $Config.name
While (1) {
Write-Host -ForegroundColor white ("`n" + $Config.name + " (" + $Config.description + ")`n")
Write-Host "1 - Email IP addresses"
Write-Host "2 - Check RDP access"
Write-Host "3 - Change config"
Write-Host "0 - Exit"
$tmp = Read-Host "`nSelect an option [$option]"
if ($tmp) {$option = $tmp}
if ($option -notmatch "0|1|2|3") {
Write-Host "$option is invalid"
$option = 0
} elseif ($option -eq 0) {
# Dump the Lab Manager connection
$labManager.Dispose()
exit
} elseif ($option -eq 1) {
$ConfVMs = Get-ConfigVMs $Config
Send-ConfigIPs $Config $ConfVMs
} elseif ($option -eq 2) {
$ConfVMs = Get-ConfigVMs $Config
Test-Access $ConfVMs
} elseif ($option -eq 3) {
$Config = Select-Configuration
$host.UI.RawUI.WindowTitle = $ScriptName + " - " + $Config.name
} else {
Write-Host "Unexpected error...!"
}
}
PressAnyKeyToExit