PowerCLI Mass Add Hard Disks to Virtual Machine

While doing some iSCSI LUN testing for a certain storage vendor, I was looking for a way to add multiple hard disks to a single VM across each iSCSI LUN whose name matched a certain pattern. In my case, all luns I was testing against had the full lun path in their name so the were similar to lun1.naa.600144f0dcb8480000005142553e0001 (thanks to Alan Renouf’s post “PowerCLI: Mass provision datastore’s” for guidance on  scripting datastore creation).

However, I do not have all luns mapped to every vSphere host. Easy enough to get around this in PowerCLI. The following script prompts for the Virtual Machine name, size and hard disk format. Then filters the datastores by that VM’s vSphere host and our common string in the datastore name.


$vmname = read-host "VM Name to add disks to"

$vm = get-vm $vmname

$size = read-host "Disk Size (GB)"

$format = read-host "Disk Format (thin, thick, EagerZeroedThick)"

$datastores = $vm | Get-VMHost | Get-Datastore | Where-Object {$_.name -like "lun*naa*"}

foreach ($item in $datastores){
$datastore = $item.name
write-host "Adding new $size VMDK to $vm on datastore $datastore"
New-HardDisk -vm $vm -CapacityGB $size -Datastore $datastore -StorageFormat $format
}

There are a lot of parameters for the New-HardDisk cmdlet that I don’t specify because the defaults were what I already wanted (e.g. Persistence, Controller, DiskType, etc.). Some, like StorageFormat which defaults to Thick Lazy Zeroed, I wanted to control.

In another case, I wanted to add multiple disks from one datastore to a vm.


### Get VM/Disk Count/Datastore information ###
$vmname = read-host "VM Name to add disks to"
$num_disks = read-host "number of disks to add"
$ds = read-host "Datastore to place the VMDK"
$format = read-host "Disk Format (thin, thick, EagerZeroedThick)"
$size = read-host "Disk Size (GB)"

$vm = get-vm $vmname
$datastore = get-datastore -name $ds
$x=0

### Add $num_disks to VM
while ($x -lt $num_disks){
write-host "Adding $size VMDK to $vm on datastore $datastore"
New-HardDisk -vm $vm -CapacityGB $size -Datastore $datastore -StorageFormat $format
$x++
}

You can read more about the New-HardDisk cmlet at:
http://www.vmware.com/support/developer/PowerCLI/PowerCLI51/html/New-HardDisk.html

Find Old Computers – Using PowerShell with LastLogonTimestamp

[updated with optimization from comment from JR]

Cleaning up Active Directory is a necessary evil. You need to stay under your CAL count and it can be difficult to figure out which computers (or users) have not logged in to the domain recently.

Windows Server 2003 introduced the lastLogonTimestamp attribute which replicates between all DCs in the domain. Now, this isn’t real-time data. In fact it can be up to 14 days behind the current date, depending on your domain settings. If you want that, you’re going to have to get yourself a good syslog server, but for general cleanup and auditing purposes it works great. You can read more about this attribute on Microsoft’s TechNet Blog.

I’ve written a couple very simple PowerShell scripts that will 1) search the entire domain for all computers with a lastLogonTimestamp before a certain date 2) return a computer’s lastLogonTimestamp value in a human readable local format. It’s not so easy to just go out and get the time stamp, because the format that AD stores it UTC (GMT) format, so it needs some converting to human readable, which my scripts do.

get_lastLogonTimestamp_from_host.ps1


# Gets host and lastLogonTimestamp in UTC of specified host

# get Name
$hostname = Read-host "Enter a hostname"

# grab the lastLogonTimestamp attribute
Get-ADComputer $hostname -Properties lastlogontimestamp |

# output hostname and timestamp in human readable format
Select-Object Name,@{Name="Stamp"; Expression={[DateTime]::FromFileTime($_.lastLogonTimestamp)}}

 

———————————————————–

 

get_stale_hosts_lastLogonTimestamp.ps1


# Gets time stamps for all computers in the domain that have NOT logged in since after specified date

$time = Read-host "Enter a date in format mm/dd/yyyy"
$time = get-date ($time)
$date = get-date ($time) -UFormat %d.%m.%y

# Get all AD computers with lastLogonTimestamp less than our time
Get-ADComputer -Filter {LastLogonTimeStamp -lt $time} -Properties LastLogonTimeStamp |

# Output hostname and lastLogonTimestamp into CSV
select-object Name,@{Name="Stamp"; Expression={[DateTime]::FromFileTime($_.lastLogonTimestamp)}} | export-csv .all_old_computers_timestamps_older_than-$time.csv -notypeinformation

These are two scripts that I use pretty often when I’m trying to determine if I should disable/delete computer accounts in AD. Hope it helps someone else.