TImesync Script Version 1

This was written for prior to 4.1.

#################################################################################################
# Title:	vmTools TimeSyc Script
# Filename:	vmtoolstimesync.ps1
# Created by:	Douglas Smith
# Date:		4/6/2010
# Version:    	0.1
# Description:	This script will list all VMs that do not have timesync enabled, You have the 
#		option of viewing on the screen or emailing the report, doing all servers or a 
#		specific one, and the ability to enable timesync on the client.
#################################################################################################
#### Pass through paramaeters
param(
[String]$vcserver
)
#### Detail Settings
#### Other Variables $EmailTo = "doug@local.com"
$EmailReportFrom = "vSphere-PowerShell@local.com"
$EmailServer = "mail.local.com"
#### Functions
function GUIprompt {
[hashtable]$answers = @{}
[void] [System.Reflection.Assembly]::LoadWithPartialName("System.Drawing")
[void] [System.Reflection.Assembly]::LoadWithPartialName("System.Windows.Forms")
# defining $cancel, otherwise the program just exits.
$cancel = $False
# creates a form for input via a window
$objForm = New-Object System.Windows.Forms.Form
$objForm.Text = "vSphere Information Prompt"
$objForm.Size = New-Object System.Drawing.Size(290,365) # overall size
$objForm.StartPosition = "CenterScreen"
# Textbox for server name
$objTextBox = New-Object System.Windows.Forms.TextBox
$objTextBox.Location = New-Object System.Drawing.Size(10,20)
$objTextBox.Size = New-Object System.Drawing.Size(260,20)
$objForm.Controls.Add($objTextBox)
# Textbox for username
$objTextBoxUserName = New-Object System.Windows.Forms.TextBox
$objTextBoxUserName.Location = New-Object System.Drawing.Size(10,60)
$objTextBoxUserName.Size = New-Object System.Drawing.Size(260,20)
$objForm.Controls.Add($objTextBoxUserName)
# Textbox for password
$objTextBoxUserPassword = New-Object System.Windows.Forms.TextBox
$objTextBoxUserPassword.Location = New-Object System.Drawing.Size(10,100)
$objTextBoxUserPassword.Size = New-Object System.Drawing.Size(260,20)
$objTextBoxUserPassword.PasswordChar = 'ï'
$objForm.Controls.Add($objTextBoxUserPassword)
# Checkbox for Report or Fix
$objCheckBox1 = New-Object System.Windows.Forms.CheckBox
$objCheckBox1.Location = New-Object System.Drawing.Size(10,140)
$objCheckBox1.Size = New-Object System.Drawing.Size(110,20)
$objCheckBox1.Text = "Enable Timesync"
$objForm.Controls.Add($objCheckBox1)
# Textbox for email
$objTextBoxEmail = New-Object System.Windows.Forms.TextBox
$objTextBoxEmail.Location = New-Object System.Drawing.Size(10,260)
$objTextBoxEmail.Size = New-Object System.Drawing.Size(260,20)
$objTextBoxEmail.Visible = $False
$objForm.Controls.Add($objTextBoxEmail)
# Checkbox for email report
$objCheckBox3 = New-Object System.Windows.Forms.CheckBox
$objCheckBox3.Location = New-Object System.Drawing.Size(10,220)
$objCheckBox3.Size = New-Object System.Drawing.Size(110,20)
$objCheckBox3.Text = "Email Report"
$objCheckBox3.Add_checkedChanged({if ($objCheckBox3.checked) {$objTextBoxEmail.Visible = $True; $objLabelEmail.Visible = $True} Else {$objTextBoxEmail.Visible = $False; $objLabelEmail.Visible = $False}})
$objForm.Controls.Add($objCheckBox3)
# Textbox for virtual servername
$objTextBoxvm = New-Object System.Windows.Forms.TextBox
$objTextBoxvm.Location = New-Object System.Drawing.Size(10,180)
$objTextBoxvm.Size = New-Object System.Drawing.Size(260,20)
$objTextBoxvm.Visible = $False
$objForm.Controls.Add($objTextBoxvm)
# Textbox for Single Server or All
$objCheckBox2 = New-Object System.Windows.Forms.CheckBox
$objCheckBox2.Location = New-Object System.Drawing.Size(130,140)
$objCheckBox2.Text = "Single Server"
$objCheckBox2.Add_checkedChanged({if ($objCheckBox2.checked) {$objTextBoxvm.Visible = $True; $objLabelvm.Visible = $True} Else {$objTextBoxvm.Visible = $False; $objLabelvm.Visible = $False}})
$objForm.Controls.Add($objCheckBox2)
# add keystroke options. Pressing "Enter" is the same as clicking "OK, "Esc" is the same as "Cancel"
$objForm.KeyPreview = $True
$objForm.Add_KeyDown({if ($_.KeyCode -eq "Enter")
{$Server=$objTextBox.Text;$objForm.Close()}})
$objForm.Add_KeyDown({if ($_.KeyCode -eq "Escape")
{$cancel = $True;$objForm.Close()}})
# Draw 'OK' button and sets button action.
$OKButton = New-Object System.Windows.Forms.Button
$OKButton.Location = New-Object System.Drawing.Size(60,300)
$OKButton.Size = New-Object System.Drawing.Size(75,23)
$OKButton.Text = "OK"
$OKButton.Add_Click({
$answers.server=$objTextBox.Text
$answers.user=$objTextBoxUserName.Text
$answers.password=$objTextBoxUserPassword.Text
$answers.Enablets=$objCheckBox1.checked
$answers.EnableSingle=$objCheckBox2.checked
$answers.SingleServer=$objTextBoxvm.Text
$answers.EmailReport=$objCheckBox3.checked
$answers.EmailAddress=$objTextBoxEmail.Text
$objForm.Close()})
$objForm.Controls.Add($OKButton)
# Draw 'Cancel' button and sets button action.
$CancelButton = New-Object System.Windows.Forms.Button
$CancelButton.Location = New-Object System.Drawing.Size(135,300)
$CancelButton.Size = New-Object System.Drawing.Size(75,23)
$CancelButton.Text = "Cancel"
$CancelButton.Add_Click({$cancel = $True;$objForm.Close()})
$objForm.Controls.Add($CancelButton)
# Adding labels for text boxes.
# Label for server name prompt
$objLabel = New-Object System.Windows.Forms.Label
$objLabel.Location = New-Object System.Drawing.Size(10,5)
$objLabel.Size = New-Object System.Drawing.Size(240,40)
$objLabel.Text = "Enter Server name of vSphere:"
$objForm.Controls.Add($objLabel)
# Label for username prompt
$objLabelUserName = New-Object System.Windows.Forms.Label
$objLabelUserName.Location = New-Object System.Drawing.Size(10,45)
$objLabelUserName.Size = New-Object System.Drawing.Size(240,40)
$objLabelUserName.Text = "Enter the vSphere Username:"
$objForm.Controls.Add($objLabelUserName)
# Label for password prompt
$objLabelPassword = New-Object System.Windows.Forms.Label
$objLabelPassword.Location = New-Object System.Drawing.Size(10,85)
$objLabelPassword.Size = New-Object System.Drawing.Size(240,40)
$objLabelPassword.Text = "Enter the vSphere Password:"
$objForm.Controls.Add($objLabelPassword)
# Label for email prompt
$objLabelEmail = New-Object System.Windows.Forms.Label
$objLabelEmail.Location = New-Object System.Drawing.Size(10,245)
$objLabelEmail.Size = New-Object System.Drawing.Size(240,40)
$objLabelEmail.Text = "Enter your Email Address:"
$objLabelEmail.Visible = $False
$objForm.Controls.Add($objLabelEmail)
# Label for Virtual Machine
$objLabelvm = New-Object System.Windows.Forms.Label
$objLabelvm.Location = New-Object System.Drawing.Size(10,165)
$objLabelvm.Size = New-Object System.Drawing.Size(240,40)
$objLabelvm.Text = "Enter the virtual server name:"
$objLabelvm.Visible = $False
$objForm.Controls.Add($objLabelvm)
# Puts the form on top of all other windows.
$objForm.Topmost = $True
# Activates/draws the form.
$objForm.Add_Shown({$objForm.Activate()})
[void] $objForm.ShowDialog()
return $answers
}
Function Enable-VMTimeSync {
Begin {
$spec = new-object VMware.Vim.VirtualMachineConfigSpec
$spec.tools = New-Object VMware.Vim.ToolsConfigInfo
$spec.tools.syncTimeWithHost = $true
}
Process {
$_.ReconfigVM_Task($spec)
}
}
#### Begin Script
#### Validate Input Variables
If ($vcserver -eq "") {
[hashtable]$info = @{}
$info = GUIprompt
$vcserver = $info.server
}
If ($info.server -eq "") {
$wscript = new-object -comobject wscript.shell
$msgbox = $wscript.popup("You MUST enter the name or IP of your vSphere server",0,"Access Denied",1)
exit
}
If ($info.EnableTS) {
If (!$info.user.ToLower().EndsWith("ad")) {
$wscript = new-object -comobject wscript.shell
$msgbox = $wscript.popup("You need admin privledges to complete this function",0,"Access Denied",1)
exit
}
}
If ($info.EmailReport) {
If (!$info.EmailAddress.ToLower().Contains("@local.com")) {
$wscript = new-object -comobject wscript.shell
$msgbox = $wscript.popup("You MUST enter a valid SMTP address",0,"Access Denied",1)
exit
}
}
#### Check if Snapin loaded, if not load
if ((Get-PSSnapin -Name VMware.VimAutomation.Core -ErrorAction SilentlyContinue) -eq $null )
{Add-PSsnapin VMware.VimAutomation.Core -ErrorAction SilentlyContinue}
#### Connect to vCenter
If ($info.user -eq "") {
$VIServer = connect-VIServer $vcserver
}
Else {
$VIServer = connect-VIServer $vcserver -user $info.user -Password $info.password
}
#### Get A list of Objects that meet the criteria
$VMs = get-vm | where-object {$_.powerstate -eq "PoweredOn"}
If ($info.EnableSingle) {$VMs = $VMs | where-object {$_.Name -eq $info.SingleServer}}
$VMs = $VMs | get-view | where-object {$_.config.tools.SyncTimeWithHost -eq $False}
$VMs = $VMs | sort-object Name
If ($info.EnableTS) {
$VMs = $VMs | where-object {$_.name -notlike "*vpopnet*"}
$VMs | Enable-VMTimeSync
}
If ($info.EmailReport) {
$SendEmail = $mailer = new-object Net.Mail.SMTPclient($EmailServer)
$message = new-object Net.Mail.MailMessage
$message.From = $EmailReportFrom
$message.To.add($info.EmailAddress)
$message.Subject = 'Virtual Machine TimeSync Report for ' + (Get-Date)
$message.body = $VMs | Select Name | ConvertTo-Html
$message.IsBodyHTML = $true
$mailer.send($message)
} Else {$VMs | Select Name}
#Disconnect from vCenter Server
$VIServer | Disconnect-VIServer -Confirm:$false

 

Importing DPM Settings

In the last article I showed you the code to export the settings.  In this one I show you the code to import them into the server.  I am assuming that the hostname, login and password are remaining.  You are just moving the servers from one virtual center server to another.

if ((Get-PSSnapin -Name VMware.VimAutomation.Core -ErrorAction SilentlyContinue) -eq $null )
{Add-PSsnapin VMware.VimAutomation.Core -ErrorAction SilentlyContinue}
Set-PowerCLIConfiguration -DefaultVIServerMode Multiple -Confirm:$false
$sourceVI = Read-Host "Please enter the name of the source Server";
$creds = get-credential
$datacenter = Read-Host "Please give the name of the datacenter you would like to run against"
connect-viserver -server $sourceVI -credential $creds
import-csv "R:\Reports\Datacenter-exports\dpm-settings-$datacenter.csv" | %{
$hostview = get-vmhost $_.Name | % {Get-View $_.Id}
$IpmiInfo = New-Object Vmware.Vim.HostIpmiInfo
$IpmiInfo.BmcIpAddress = $_.BmcIpAddress
$IpmiInfo.BmcMacAddress = $_.BmcMacAddress
$IpmiInfo.Login = $_.Login
$IpmiInfo.Password = $_.password
$hostview.UpdateIpmi($IpmiInfo)}
Disconnect-VIServer -Server $SourceVI -Force -confirm:$false

 

Exporting DPM Settings

I recently was tasked to move several datacenters to balance the overall load on our virtual center servers.  One of the things I had to do was to export the existing host settings for Distributed Power Management (DPM).  I wrote the following script to export the settings to a CSV file.

if ((Get-PSSnapin -Name VMware.VimAutomation.Core -ErrorAction SilentlyContinue) -eq $null )
{Add-PSsnapin VMware.VimAutomation.Core -ErrorAction SilentlyContinue}
#Change to multi-mode vcenter management
Set-PowerCLIConfiguration -DefaultVIServerMode Multiple -Confirm:$false
#Get vCenter Server Names
$sourceVI = Read-Host "Please enter the name of the source Server";
$creds = get-credential
$datacenter = Read-Host "Please give the name of the datacenter you would like to run against"
#Connect to Source vCenter
connect-viserver -server $sourceVI -credential $creds
Function Get-IpmiInfo {
Begin {
# This hides the errors which appear if the VM Tools are not running
$ErrorActionPreference = "SilentlyContinue"
$Name = @{
Name    = "Name"
Expr     = { $_.name }
}
$BmcIpAddress = @{
Name    = "BmcIpAddress"
Expr     = { $_.config.ipmi.BmcIpAddress }
}
$BmcMacAddress = @{
Name    = "BmcMacAddress"
Expr     = { $_.config.ipmi.BmcMacAddress }
}
$Login = @{
Name    = "Login"
Expr     = { $_.config.ipmi.Login }
}
$Password = @{
Name    = "Password"
Expr     = { $_.config.ipmi.Password }
}
}
Process {
if ( $_.GetType().Name -ne 'VirtualMachineImpl' ) {
Throw "This script expects a VirtualMachineImpl object as input."
}
$_ | Select-Object $name, $BmcIpAddress, $BmcMacAddress, $Login, $Password
}
}
$report = @()
Get-datacenter $datacenter | get-vmhost | get-view | Get-IpmiInfo | export-csv "c:\temp\dpm-settings-$datacenter.csv" -notypeinformation
Disconnect-VIServer -Server $SourceVI -Force -confirm:$false

 

VM Compare AD Group Script

If you apply GPO’s to servers for ease of administration and security, you may want an easy way if all your servers are in the appropriate group(in this case “Virtual Servers”) and compare this list to a list of all running Windows machines. ┬áThe following script will do this:

########################################################################
# Title:	VM Groupmembership Script
# Filename:	vmgroup.ps1
# Created by:	Douglas Smith
# Date:		7/14/2010
# Version:	0.1
# Description:		*This script requires the Quest AD cmdlets be installed.*
########################################################################
#### Pass through paramaeters ###################################################
param (
[string]$vcserver,
)
#### Variables ##############################################################
$Date = Get-Date
#### Functions ##############################################################
#### Begin Script ############################################################
#### Validate Input Variables ####################################################
If ($vcserver -eq "") {
$wscript = new-object -comobject wscript.shell
$msgbox = $wscript.popup("You MUST enter the name or IP of your vSphere server",0,"Access Denied",1)
exit
}
#### Check if Snapin loaded, if not load #############################################
if ((Get-PSSnapin -Name VMware.VimAutomation.Core -ErrorAction SilentlyContinue) -eq $null )
{Add-PSsnapin VMware.VimAutomation.Core -ErrorAction SilentlyContinue}
if ((Get-PSSnapin -Name Quest.ActiveRoles.ADManagement -ErrorAction SilentlyContinue) -eq $null )
{Add-PSsnapin Quest.ActiveRoles.ADManagement -ErrorAction SilentlyContinue}
#### Connect to vSphere
$VIServer = connect-VIServer $vcserver
$adlist = get-qadgroupmember "Virtual Servers" -type computer | Select-Object name |
Sort-Object name | ForEach-Object{$_.name.tolower()}
$vms = Get-Vm | Where-Object {$_.powerstate -eq "PoweredOn"} |
Where-Object {$_.name.length -gt 10} |
Where-Object {$_.guest.osfullname -like quot;*indows*"} | Select-Object name |
Sort-Object name | ForEach-Object{$_.Name.ToLower()}
$vmcount = $vms.count
$AddMachine = Compare-Object $vms $adlist -syncwindow $vmcount |
Where-Object {$_.sideindicator -eq "< ="} | Sort-Object InputObject
$RemoveMachine = Compare-Object $vms $adlist -syncwindow $vmcount |
Where-Object {$_.sideindicator -eq "=>"} | Sort-Object InputObject
#### Create Spreadsheet
$excel = New-Object -comobject Excel.Application
#$excel.visible = $True #### Use for troubleshooting purposes
$excel.DisplayAlerts = $False
$excelfile = $excel.Workbooks.Add()
$WorkSheet = $excelfile.worksheets.item(1)
$Worksheet.Name = "Add to Group"
$Worksheet.Cells.Item(1, 1) = "Machines that need to be added to the Group"
$WorkBook = $Worksheet.UsedRange
$WorkBook.Interior.ColorIndex = 8
$WorkBook.Font.ColorIndex = 11
$WorkBook.Font.Bold = $True
$Row = 2
$Addmachine | ForEach-Object {
$Worksheet.Cells.Item($Row, 1) = $_.InputObject
$Row ++
}
[void]$WorkBook.EntireColumn.AutoFit()
$WorkSheet = $excelfile.worksheets.item(2)
$Worksheet.Name = "Remove from Group"
$Worksheet.Cells.Item(1, 1) = "Machines that need to be removed from the Group"
$WorkBook = $Worksheet.UsedRange
$WorkBook.Interior.ColorIndex = 8
$WorkBook.Font.ColorIndex = 11
$WorkBook.Font.Bold = $True
$Row = 2
$RemoveMachine | ForEach-Object {
$Worksheet.Cells.Item($Row, 1) = $_.InputObject
$Row ++
}
#### Adjust Columns
[void]$WorkBook.EntireColumn.AutoFit()
#### Save File
$excelfile.SaveAs("c:\temp\VirtualServerGroup-" + $date.month + "-" + $date.day + "-" + $date.year + ".xls", 1)
#### Quit Excel
$excel.Quit()
#Disconnect from vCenter Server
$VIServer | Disconnect-VIServer -Confirm:$false