Archives for posts with tag: Powershell

One of the last projects I’ve been involved with at Seatrans, is to auto­mate the instal­la­tion and con­fig­u­ra­tion of vSphere ESXi 5 hosts for deploy­ment on ves­sels. I’ve talked a bit about this before, both on vSoup and in Set­ting Up Auto­mated ESXi Deploy­ments where I out­lined my PXE and Pow­er­CLI based instal­la­tion and con­fig­u­ra­tion scheme. Not much has changed since then, except updat­ing the PXE server to offer ESXi 5, instead of ESXi 4 and a lot of work has been put into the script­ing, includ­ing a front-end GUI for the Pow­er­CLI script itself. The end “prod­uct” is now in place for mass deploy­ments for inter­nal use.

The fol­low­ing video shows how the PXE based instal­la­tion works, as well as a run through the now GUI based con­fig­u­ra­tion tool aptly called Seatrans Hyper­vi­sor Instal­la­tion Tool.

The video jumps a bit between two VMs, one run­ning Win­dows Server 2008 R2, that runs the DHCP/PXE ser­vices and the Pow­er­CLI script, and one that gets ESXi installed and configured:

This goes to show that you can cre­ate your own, spe­cial­ized and portable deploy­ment solu­tion with­out requir­ing elab­o­rate net­work con­fig­u­ra­tions or recon­fig­ur­ing of exist­ing infrastructure.

Note: I will not be pro­vid­ing down­load­able ver­sions of the final script at this time. The rea­son for this is quite sim­ple, it’s very spe­cific and tai­lored for a non-generic envi­ron­ment. If I can man­age to find the time, I’ll post a generic ver­sion later but in order for any­one else to uti­lize the Pow­er­CLI scripts I’ve cre­ated, a lot of work is required.

Automat­ing ESXi installs was made much eas­ier after the release of vSphere 4.1 where the Scripted Install fea­ture was added, and by using VMware Auto Deploy from VMware Labs. VMware Auto Deploy requires that you have vCen­ter and Host Pro­files in your envi­ron­ment, and that again requires that you have Enter­prise Plus licenses in your environment.

It is, how­ever, pos­si­ble to deploy ESXi in an auto­mated fash­ion com­pletely with­out vCen­ter and Host Pro­files! By using a com­bi­na­tion of a PXE based instal­la­tion and Pow­er­CLI for automat­ing the setup of ESXi after the ini­tial deploy­ment. As this setup has been put together for a spe­cific work project, my Pow­er­CLI script also copies a VM tem­plate to the deployed ESXi host as well as the vMA for admin­is­tra­tive tasks. There is one caveat with regards to this setup though, and that is that the free ver­sion of ESXi only allows Pow­er­CLI in read-only mode. This means that you will either need to get licenses for the ESXi install, or use trial licenses. With the price drop from VMware on the Remote Office / Branch Office (ROBO) licenses, we’re look­ing at using that licens­ing model for our fleet of vessels.

Overview

The “com­plete pack­age” con­sists of the fol­low­ing components:

  • Deploy­ment VM
    This is a cus­tom VM, built to pro­vide DHCP and PXE ser­vices to do the actual ESXi installation
  • Pow­er­shell + Pow­er­CLI
    Scripts that con­fig­ure the ESXi host, post instal­la­tion, and copy your ini­tial VMs to the new host

Our cur­rent process looks like this:

  1. Con­nect phys­i­cal host to deploy­ment lap­top via ethernet
  2. Start deploy­ment VM on deploy­ment laptop
  3. When deploy­ment VM is fin­ished boot­ing, start phys­i­cal host
  4. Phys­i­cal host boots of net­work and PXE and installs ESXi
  5. When ESXi instal­la­tion fin­ishes, run Pow­er­CLI script against host
  6. Dis­con­nect deploy­ment lap­top and phys­i­cal host, and con­nect phys­i­cal host to ves­sel network
  7. Con­nect vSphere Client to ESXi install and start server VM

Deploy­ment VM

Since our deploy­ment sce­nario might be a bit out of the ordi­nary, we have the deploy­ment VM set up on VMware Work­sta­tion or VMware Player on a lap­top. The rea­son for this is that we need a mobile deploy­ment model as the loca­tions we are deploy­ing this on are not sta­tic. Not only are they mobile, they are actu­ally float­ing around on rather large oceans. That’s right, we’re deploy­ing ESXi hosts on our ves­sels world wide!

Basic VM Setup

The basic setup is a stan­dard Win­dows Server 2008 R2 with IIS installed. We will not be using any of the DHCP or other net­work­ing fea­tures included in Server 2008. In our envi­ron­ment it’s con­fig­ured with a sta­tic ip of 172.16.200.1

DHCP + PXE Setup

For DHCP and PXE ser­vices, we are using Tftpd32 a free and open source appli­ca­tion that pro­vides us with all the required ser­vices for deploy­ment eg. both DHCP and PXE.

Kick­start Script

Our very basic kick­start script — ks.cfg — looks like this

vmac­cep­teula
rootpw pass­word
autopart first­disk over­writevmfs
install url http://172.16.200.1/ESXi
net­work boot­proto=dhcp device=vmnic0
reboot

Basi­cally this sets the root pass­word, auto­mat­i­cally deletes all par­ti­tions and sets up a new vmfs, tells the installer that it will find the instal­la­tion files via http on the server and sets the net­work­ing con­fig­u­ra­tion to DHCP. This will of course need tweak­ing in your envi­ron­ment, but this should at least get you started with build­ing your own. More details on the ks.cfg boot­strap com­mands can be found in the ESX and vCen­ter Server Instal­la­tion Guide

Pow­er­CLI Con­fig­u­ra­tion Script

########################################################
#
# Cre­ated by Chris­t­ian Mohn
# for Seatrans AS
#
# No war­ranty sug­gested or implied
#
########################################################</code>

#con­nect to Vir­tu­al­Cen­ter or ESX host
#
func­tion Reg­is­ter-VMX {
param($enti­ty­Name = $null,$dsNames = $null,$tem­plate = $false,$ignore = $null,$check­NFS = $false,$whatif=$false)

func­tion Get-Usage{
Write-Host “Para­me­ters incor­rect” –Fore­ground­Color red
Write-Host “Register-VMX –enti­ty­Name –dsNames [,…]“
Write-Host “enti­ty­Name : a cluster-, dat­a­cen­ter or ESX host­name (not together with –dsNames)“
Write-Host “dsNames : one or more data­s­tore­name names (not together with –enti­ty­Name)“
Write-Host “ignore : names of fold­ers that shouldn’t be checked“
Write-Host “tem­plate : reg­is­ter guests ($false)or tem­plates ($true) — default : $false“
Write-Host “check­NFS : include NFS data­s­tores — default : $false“
Write-Host “whatif : when $true will only list and not exe­cute — default : $false“
}

if(($enti­ty­Name –ne $null –and $dsNames –ne $null) –or ($enti­ty­Name –eq $null –and $dsNames –eq $null)){
Get-Usage
break
}

if($dsNames –eq $null){
switch((Get-Inven­tory –Name $enti­ty­Name).Get­Type().Name.Replace(“Wrap­per”,””)){
“Clus­ter”{
$dsNames = Get-Clus­ter –Name $enti­ty­Name | Get-VMHost | Get-Data­s­tore | where {$_.Type –eq VMFS –or $check­NFS} | % {$_.Name}
}
“Dat­a­cen­ter”{
$dsNames = Get-Dat­a­cen­ter –Name $enti­ty­Name | Get-Data­s­tore | where {$_.Type –eq VMFS –or $check­NFS} | % {$_.Name}
}
“VMHost”{
$dsNames = Get-VMHost –Name $enti­ty­Name | Get-Data­s­tore | where {$_.Type –eq VMFS –or $check­NFS} | % {$_.Name}
}
Default{
Get-Usage
exit
}
}
}
else{
$dsNames = Get-Data­s­tore –Name $dsNames | where {$_.Type –eq VMFS –or $check­NFS} | Select –Unique | % {$_.Name}
}

$dsNames = $dsNames | Sort-Object
$pat­tern = “*.vmx“
if($tem­plate){
$pat­tern = “*.vmtx“
}

fore­ach($dsName in $dsNames){
Write-Host “Check­ing ” –NoNew­line; Write-Host –Fore­ground­Color red –Back­ground­Color yel­low $dsName
$ds = Get-Data­s­tore $dsName | Select –Unique | Get-View
$dsBrowser = Get-View $ds.Browser
$dc = Get-View $ds.Par­ent
while($dc.MoRef.Type –ne “Dat­a­cen­ter”){
$dc = Get-View $dc.Par­ent
}
$tgt­folder = Get-View $dc.VmFolder
$esx = Get-View $ds.Host[0].Key
$pool = Get-View (Get-View $esx.Par­ent).Resour­ce­Pool

$vms = @()
fore­ach($vmImpl in $ds.Vm){
$vm = Get-View $vmImpl
$vms += $vm.Config.Files.VmPathName
}
$data­s­torepath = “[“ + $ds.Name + ”]“

$search­spec = New-Object VMware.Vim.HostDatastoreBrowserSearchSpec
$search­spec.Match­Pat­tern = $pat­tern

$taskMoRef = $dsBrowser.SearchDatastoreSubFolders_Task($data­s­torePath, $search­Spec)

$task = Get-View $taskMoRef
while (“run­ning”,“queued” –con­tains $task.Info.State){
$task.Updat­e­View­Data(“Info.State”)
}
$task.Updat­e­View­Data(“Info.Result”)
fore­ach ($folder in $task.Info.Result){
if(!($ignore –and (&{$res = $false; $folder.FolderPath.Split(”]”)[1].Trim(” /”).Split(”/”) | %{$res = $res –or ($ignore –con­tains $_)}; $res}))){
$found = $FALSE
if($folder.file –ne $null){
fore­ach($vmx in $vms){
if(($folder.Fold­er­Path + $folder.File[0].Path) –eq $vmx){
$found = $TRUE
}
}
if (–not $found){
if($folder.Fold­er­Path[-1] –ne “/”){$folder.Fold­er­Path += “/”}
$vmx = $folder.Fold­er­Path + $folder.File[0].Path
if($tem­plate){
$params = @($vmx,$null,$true,$null,$esx.MoRef)
}
else{
$params = @($vmx,$null,$false,$pool.MoRef,$null)
}
if(!$whatif){
$taskMoRef = $tgt­folder.Get­Type().Get­Method(“RegisterVM_Task”).Invoke($tgt­folder, $params)
Write-Host ‘t $vmx “reg­is­tered“
}
else{
Write-Host ‘t $vmx “reg­is­tered” –NoNew­line; Write-Host –Fore­ground­Color blue –Back­ground­Color white ” ==> What If“
}
}
}
}
}
Write-Host “Done“
}
}

# Register-VMX –enti­ty­Name “MyDat­a­cen­ter“
# Register-VMX –dsNames “datastore1”,“datastore2“
# Register-VMX –dsNames “datastore1”,“datastore2” –template:$true
# Register-VMX –enti­ty­Name “MyDat­a­cen­ter” –ignore “Some­Folder“
# Register-VMX –dsNames “datastore3”,“datastore4” –ignore “Some­Folder” –checkNFS:$true
# Register-VMX –enti­ty­Name “MyDat­a­cen­ter” –whatif:$true

if ($args[0] –eq $null)
#
{$host­Name = Read-Host “Enter ESX Host Name or IP}
#
else
#
{$host­Name = $args[0]}
#
#
#con­nect to selected Vir­tu­al­cen­ter or host server
#
Con­nect-VIS­erver $host­Name

# Set Data­s­tore Name
$dsName = “datastore1“
$ds = Get-Data­s­tore –Name $dsName
New-PSDrive –Name $dsName –Root \ –PSProvider Vim­Data­s­tore -Data­s­tore $ds

# Copy and Reg­is­ter VM from local drive to ESXi Host
Copy-Data­s­tor­e­Item C:\VMs\MyTestVM\* datastore1:\MyTestVM\ –Force
Reg­is­ter-VMX -dsNames $dsName

# Import vMA ovf
Import-VApp -Source c:\VMs\vMA\vMA-4.1.0.0-268837.ovf -VMHost $host­Name -Data­s­tore $ds

# Lets con­fig­ure the host

########################################################
# Host Con­fig­u­ra­tion #
########################################################

#Dis­able IPv6
Get-VMHost­Net­workAdapter | where { $_.Port­Group­Name –eq “Ser­vice Con­sole 1″ } | Set-VMHost­Net­workAdapter -IPv6Enabled $false

# Con­fig­ure net­work­ing
# Not fin­ished

# Con­fig­ure NTP Server
Add-VMHost­NtpServer -VMHost $host­Name -NtpServer “0.vmware.pool.ntp.org“
Add-VMHost­NtpServer -VMHost $host­Name -NtpServer “1.vmware.pool.ntp.org“
Add-VMHost­NtpServer -VMHost $host­Name -NtpServer “2.vmware.pool.ntp.org“

# Set VM Start Pol­icy
$vmstart­pol­icy = Get-VMStart­Pol­icy -VM MyTestVM
Set-VMStart­Pol­icy -Start­Pol­icy $vmstart­pol­icy -Star­tAc­tion PowerOn

This Pow­er­CLI script is not 100% fin­ished yet, the net­work­ing part remains to be auto­mated to pro­vide cor­rect con­fig­u­ra­tion based on which ves­sel we are deploy­ing to, but in gen­eral it’s pretty much good to go.

Of course, there are loads of ways to extend and improve this process, but for now this suits our needs very well. I’m sure I’ll need to revise it once vSphere.next is out and ready for deployment.

Using a model like this, com­bined with some inter­est­ing usage pat­terns for vMA you can cre­ate an auto­mated ESXi deploy­ment sce­nario that let’s you deploy, patch and man­age your remote vSphere infra­struc­ture in a pretty stream­lined fashion.

Remote Desk­top Con­nec­tion Man­ager is a great tool from Microsoft which enables you to keep track of all your RDP ses­sions and tar­gets in a nice GUI. One of the things it’s lack­ing though, is some sort of Active Direc­tory con­nec­tion that allows you to import all your server objects directly, and not man­u­ally add/remove the serves as your infra­struc­ture changes over time.

In an attempt to bridge that gap, I’ve made a very small Pow­er­Shell script that queries your Active Direc­tory for server objects and dumps their names into a text file that you can import into RDC­Man. This is a very sim­ple solu­tion, but works great in my environment.

GetAllServers.ps1

1
2
3
4
5
6
7
8
9
10
11
12
13
Import-Module ActiveDirectory 
 
$servers = Get-ADComputer -LDAPFilter "(operatingsystem=*Windows Server*)" | select name,dnshostname
$Date = Get-Date
$filename = "Servers-{0}{1:d2}{2:d2}" -f $date.year,$date.month,$date.day
foreach ($server in $servers) { 
 
$servername = $server.name
 
#Customize this for your environment
$servername | Out-File -append -encoding ASCII <path>\$filename.txt
 
}

In short, replace the path in line 11, and you should be able to run the script. It will then cre­ate a file called servers-{current-date}.txt in the path you have spec­i­fied. This is a sim­ple text file with one server defined on each line.

This file can then be imported into RDC­Man by going to the Edit menu and select Import Servers. This brings up the Import Servers dia­log box where you can browse to the file that the Pow­er­Shell script cre­ated. Click on the Import But­ton and all your servers should now be listed in RDC­Man. The next time you need to update, delete the exist­ing servers, re-run the Pow­er­Shell script and import again.


While this isn’t a fully auto­mated solu­tion, and I really wish RDC­Man could do this for you by query­ing AD directly and find­ing new servers and remov­ing the ones that are no longer present and so on, it is a quick way to get your cur­rent servers into RDC­Man with­out man­u­ally cre­at­ing each and every entry.

Update:

After I ini­tially posted this, Jan Egil Ring, pointed me to his solu­tion which is a bit more elab­o­rate. Have a look at his solu­tion “Dynamic Remote Desk­top Con­nec­tion Man­ager con­nec­tion list”, which is how it really should be done…

Jan Egil Ring over at blog.powershell.no has cre­ated a great Pow­er­Shell script that lets you run the Microsoft Best Prac­tices Ana­lyzer on remote Win­dows Server 2008 R2 machines.

In short, Invoke-BPAModeling.ps1 queries your Active Direc­tory for any machines that run Win­dows Server 2008 R2, runs BPA on them (if Win­dows Pow­er­Shell Remot­ing is enabled) and emails you the report.

Great tool that should be in every Win­dows Server admins tool-belt, and prob­a­bly also set as a sched­uled job to make sure you stay up to date on your servers status.


A cou­ple of days ago, while I was at VMworld Europe I got the fol­low­ing tweet from Asb­jørn A. Mikkelsen (@neslekkim) (trans­lated from norwegian):

@h0bbel Do you know if I can script some­thing against vCen­ter to dupli­cate (or cre­ate from tem­plate) VMs, and also start/stop them?

My imme­di­ate response, was of course to sug­gest using Pow­er­CLI. Asb­jørn, who works as a full time devel­oper, jumped at Pow­er­CLI imme­di­ately and within a very short time frame came up with a Pow­er­CLI script for the task at hand.

You can down­load the script and play around with it, if you want. Inline doc­u­men­ta­tion is in Nor­we­gian, and if Asb­jørn had intended to redis­trib­ute the script I’m sure he would have opti­mized it more than the cur­rent revi­sion.
Con­tinue read­ing “Devel­oper meets Pow­er­CLI — awe­some­ness ensues” »