Hi,
Actually I´m looking for a monster script to extend a Windows Drive by passing only the Information " VMname, Driverletter, extendbyGB
The Script should collect all Information like the correct vmdk, check Datastoresfreespace , Extend the vmdk, Extend the correct Drive inside the VM..
this is one part of the script..
Remote WMI is not enalbed and I cant not do a get-wmiObject -servername remotely.
My Idea was to do an Invoke-command to get the wmi information from inside the vm.
Invoke runs, but the output is wrong DeviceID is not recognized, do I need to pass the $Drive to the remotecommand? If yes, how?
$SystemFQFDN = "vmtest01"
$Username = "Administrator"
$Password = "blabla"
$Drive = 'd:'
$VMName = ($SystemFQFDN.Split('.'))[0]
$SecureStringPwd = $Password | ConvertTo-SecureString -AsPlainText -Force
$creds = New-Object System.Management.Automation.PSCredential -ArgumentList $UserName, $SecureStringPwd
Write-Host " invokeWMI $vmname" -ForegroundColor Green
$invokescript = " (((Get-WmiObject -ClassName 'Win32_LogicalDisk') | WHERE {$_.DeviceID -eq $Drive}).GetRelated('Win32_DiskPartition')).GetRelated('Win32_DiskDrive') | Select * "
$Windrive = Invoke-VMScript -vm $vmname -ScriptType Powershell -ScriptText $invokescript -GuestUser $UserName -GuestPassword $pw.password
$Windrive
The ScriptOutput property of the returned object contains the output from the script that ran inside the guest OS.
The data in there is one string.
One method to interpret the output on the receiving end is to use a well-known format.
In the following, I use the CSV format.
The result will be one or more objects, each with the desired properties.
$SecureStringPwd = $Password | ConvertTo-SecureString -AsPlainText -Force
$creds = New-Object System.Management.Automation.PSCredential -ArgumentList $UserName, $SecureStringPwd
$MyScript = @"
((Get-WmiObject -ClassName 'Win32_LogicalDisk' |
WHERE {`$_.DeviceID -eq "$Drive"}).GetRelated('Win32_DiskPartition')).GetRelated('Win32_DiskDrive') |
Select-Object -Property SCSIBus,SCSITargetId,SerialNumber |
ConvertTo-Csv
"@
Invoke-VMScript -vm $vmname -ScriptType Powershell -ScriptText $myScript -GuestCredential $creds |
Select -ExpandProperty ScriptOutput |
ConvertFrom-Csv -UseCulture
Blog: lucd.info Twitter: @LucD22 Co-author PowerCLI Reference
I hate to disappoint you but there is no fool-proof method to link a VMDK to a guest OS partition.
On the script, you placed it in double quotes, that means that all variables will be substituted, including $_.DeviceID and $Drive.
If I understand your intention correctly, that is probably not what you want for $_.DeviceId.
One option is to escape the $-sign with a back-tick.
A short demo snippet
$var2 = 2
$t1 = "$var1 and $var2"
$t1
$t2 = "`$var1 and $var2"
$t2
Blog: lucd.info Twitter: @LucD22 Co-author PowerCLI Reference
Hi Luc,
sorry I dont unterstand for sure.
but in Gerneral, how can i pass some $var´s in a scripttext over Invoke? Sometimes I see scripttext, or scriptblock
I testet someting like this, but its not working.:-(
thanks for your patience
Example
$SystemFQFDN = "vmtest01.test.local"
$UserName = 'administrator' # Subscribe your Variable for User with access to VCenter and VM
$pw = "mypass"
$Drive = 'd:'
$argsArray = @()
$argsArray += $Drive
$VMName = ($SystemFQFDN.Split('.'))[0]
$SecureStringPwd = $Pw | ConvertTo-SecureString -AsPlainText -Force
$creds = New-Object System.Management.Automation.PSCredential -ArgumentList $UserName, $SecureStringPwd
$Windrive = Invoke-VMscript -vm $vmname -ScriptType Powershell -GuestUser $UserName -GuestPassword $pw.password -ScriptText {
Param(
[string]$Drive
)
(((Get-WmiObject -ClassName 'Win32_LogicalDisk') | WHERE {$_.DeviceID -eq $Drive}).GetRelated('Win32_DiskPartition')).GetRelated('Win32_DiskDrive') | Select *
$resultArray = @()
return $resultArray
}
$Windrive
I use a code-block with single quotes.
And I escape (backtick) the dollar signs I don't want to have substituted.
Have a look at my Here string and variable substitution dive
Blog: lucd.info Twitter: @LucD22 Co-author PowerCLI Reference
ok now i found out how to invoke this. The Problem now is, that the output is a text arry and I dont know how to pic a special line like SCSIBUS,SCSITargetID,DiskSNfromWMI
I used the "ScriptOutput funktion, I guess this is the only way to get the output nativ.
Write-Host " invokeWMI $vmname" -ForegroundColor Green
$MyScript = @"
(((Get-WmiObject -ClassName 'Win32_LogicalDisk') | WHERE {`$_.DeviceID -eq "$Drive"}).GetRelated('Win32_DiskPartition')).GetRelated('Win32_DiskDrive') | Select *
"@
$Windrivetemp = Invoke-VMScript -vm $vmname -ScriptType Powershell -ScriptText $myScript -GuestUser $UserName -GuestPassword $pw.password
$Windrive = $windrivetemp.ScriptOutput
$Windrive
#$outputarray = ($Windrivetemp -split('\n'))
###this is not working
$SCSIBus = $Windrive.SCSIBus
$SCSITargetId =$Windrive.SCSITargetId
$DiskSNfromWMI = $Windrive.SerialNumber
The ScriptOutput property of the returned object contains the output from the script that ran inside the guest OS.
The data in there is one string.
One method to interpret the output on the receiving end is to use a well-known format.
In the following, I use the CSV format.
The result will be one or more objects, each with the desired properties.
$SecureStringPwd = $Password | ConvertTo-SecureString -AsPlainText -Force
$creds = New-Object System.Management.Automation.PSCredential -ArgumentList $UserName, $SecureStringPwd
$MyScript = @"
((Get-WmiObject -ClassName 'Win32_LogicalDisk' |
WHERE {`$_.DeviceID -eq "$Drive"}).GetRelated('Win32_DiskPartition')).GetRelated('Win32_DiskDrive') |
Select-Object -Property SCSIBus,SCSITargetId,SerialNumber |
ConvertTo-Csv
"@
Invoke-VMScript -vm $vmname -ScriptType Powershell -ScriptText $myScript -GuestCredential $creds |
Select -ExpandProperty ScriptOutput |
ConvertFrom-Csv -UseCulture
Blog: lucd.info Twitter: @LucD22 Co-author PowerCLI Reference
ok, here is the final script
Extend VMDK and Windows Drive inside the VM with Parameter of VMname and Driveletter
In my case it was working, just the check Datastore Freespace thing is not done yet
what do you think?
Param(
$DeineVM = (Read-Host "Select VMname"),
$Drive = (Read-Host "Select Drive Letter")+":"
)
$SystemFQFDN = $DeineVM #Subscribe the Published Data of the affected VM
$UserName = 'administrator' # Subscribe your Variable for User with access to VCenter and VM
#getting the Laps pw
$pw = get-adcomputer $SystemFQFDN -Properties * | select @{Label="Name";Expression={$_.name}}, @{Label="OS";Expression={$_.operatingsystem}}, @{Label="Distinguished name";Expression={$_.'distinguishedname'}}, @{Label="Password";Expression={$_.'ms-Mcs-AdmPwd'}} | select Password
$Password = $pw # Subscribe your encrypted Variable for the Password
#VName equals Netbios name here
$VMName = ($SystemFQFDN.Split('.'))[0]
#Make Credentials
$SecureStringPwd = $Password | ConvertTo-SecureString -AsPlainText -Force
$creds = New-Object System.Management.Automation.PSCredential -ArgumentList $UserName, $SecureStringPwd
Write-Host " invokeWMI $vmname" -ForegroundColor Green
#$invokescript = " ipconfig /all"
$MyScript = @"
((Get-WmiObject -ClassName 'Win32_LogicalDisk' |
WHERE {`$_.DeviceID -eq "$Drive"}).GetRelated('Win32_DiskPartition')).GetRelated('Win32_DiskDrive') |
Select-Object -Property SCSIBus,SCSITargetId,SerialNumber |
ConvertTo-Csv
"@
$Windrive = Invoke-VMScript -vm $vmname -ScriptType Powershell -ScriptText $myScript -GuestUser $UserName -GuestPassword $pw.password |
Select -ExpandProperty ScriptOutput |
ConvertFrom-Csv -UseCulture
$Windrive
#$outputarray = ($Windrive -split('\n'))
$SCSIBus = $Windrive.SCSIBus
$SCSITargetId =$Windrive.SCSITargetId
$DiskSNfromWMI = $Windrive.SerialNumber
# Match the VMWare Disk with the windows Disk
$vm = Get-VM -Name $VMName
foreach($ctrl in Get-ScsiController -VM $vm)
{
foreach($disk in (Get-HardDisk -VM $vm | where{$_.ExtensionData.ControllerKey -eq $ctrl.Key}))
{
IF (($disk.ExtensionData.UnitNumber -eq $SCSITargetId )-and (($disk.ExtensionData.Backing.Uuid).Replace('-','') -eq $DiskSNfromWMI) )
{
# The below Variables are for the tab Published Data of "Run .Net Script" Activiy
$VMDiskName = $disk.Name
$VMDiskFilename = $disk.Filename
$DiskUID = $disk.Uid
$DiskCapacityGB = $disk.CapacityGB
$DiskFreeSpaceGB = ((Get-VMGuest -VM $vm).Disks | where {$_.Path -eq "$Drive\"}).FreeSpaceGB
$DiskFreeSpaceGB = "{0:N3}" -f ([math]::Round($DiskFreeSpaceGB,3))
}
}
}
$LUN = Get-HardDisk -vm $vm | Where {$_.Uid -eq $DiskUID} | Get-Datastore
$LUNName = $LUN.Name
$FreespaceGB = "{0:N3}" -f ([math]::Round($LUN.FreeSpaceGB,3))
$CapacityGB = "{0:N3}" -f ([math]::Round($LUN.CapacityGB,3))
##################
#Driveletter will be extended with 10GB
$extend10GB = "10"
$newsize = $DiskCapacityGB + $extend10GB
# Extend VMDK
Get-HardDisk -vm $vm | Where {$_.Name -eq "$VMDiskName"} | Set-HardDisk -CapacityGB $newsize -ResizeGuestPartition -Confirm:$false
#rescan
Invoke-VMScript -vm $VM -ScriptText "echo select vol $drive > c:\diskpart.txt && echo rescan >> c:\diskpart.txt && diskpart.exe /s c:\diskpart.txt" -ScriptType BAT -GuestUser $UserName -GuestPassword $pw.password
#Extend Disc inside
Invoke-VMScript -vm $VM -ScriptText "echo select vol $drive > c:\diskpart.txt && echo extend >> c:\diskpart.txt && diskpart.exe /s c:\diskpart.txt" -ScriptType BAT -GuestUser $UserName -GuestPassword $pw.password
Well, if it is working in your environment, so much the better.
Just be aware that the logic how you link the VMDK to the drive/partition might have issues when you start adding/removing harddisks to the VM and also when you start reconfiguring partitions inside the Guest OS.
What is missing with regards to the FreeSpaceGB?
Blog: lucd.info Twitter: @LucD22 Co-author PowerCLI Reference