Linux RootFS extension in VMware with PowerCLI

Just a quick post around VMware ESXi and programatically extending the disk and volume size of the root filesystem on Linux.

I wanted to find a way of doing this using the existing PowerCLI cmdlets, but full support for Linux doing this seemed limited to RHEL installations, so I started to dig around as to what the limitations may be.

The Set-Harddisk -CapacityGB part of the powershell script appeared to work fine. – This is where the Disk within a given datastore has its capacity expanded, but this does nothing to the Guest filesystem in terms of making that space available.

If it were to work properly you would use the ResizeGuestPartition parameter, however as the VMware support page informs you:

“On Linux, only the last partition can be expanded.

Resizing guest partitions is supported only for Windows OS and for ext3 partitions on RHEL 5. It is achieved by scripts, provided with the vSphere PowerCLI installation. You can modify these scripts or add new ones to support operating systems different than Windows and RHEL 5, and more specific disk resizing scenarios. “

I started trying to think what might need changing, and for this test case kept the layout of the Guest Vdisk flat, so no LVM on the rootfs,etc.

I also decided that I would move swap away from the disk completely to another Vdisk to make the test easier. (although in reality this could probably be re-added to the end of the extended guest disk after all other operations are complete.)

So I created a new VM with 2 Vdisks, one for swap and the other for the root filesystem, and then did an installation of Ubuntu and installed VMTools. I then created a VMware template, so I could repeat the tests as needed.

I then added 2 shell scripts to the VM which I would be to interact with using the Invoke-Script cmdlet in PowerCLI.

Here are the 2 shell scripts to include into the Template VM.

/root/Disk_Extend.sh

#!/bin/sh
scsihost=`grep -R mpt /sys/class/scsi_host/host*/proc_name|awk -F "/" '{ print $5}'|grep -o '[0-9]\+'`
echo $scsihost
echo 1 > /sys/class/scsi_device/$scsihost\:0\:0\:0/device/rescan
sleep 5
/sbin/fdisk /dev/sda < d
1
n
p
1

w
EOF

/root/Disk_resize.sh

#!/bin/sh
echo "Root partition extended..Now running resize2fs"
DISK_RESIZE=$1
/sbin/resize2fs /dev/sda1 $DISK_RESIZE
echo "resizing /dev/sda1 to $DISK_RESIZE"

Disk_Extend.sh is actually deleting the old partition table and then adding a new one (without exiting fdisk) this brings in the newly available space that has been added to the disk using the CapacityGB parameter in the Set-Harddisk cmdlet. Disk_Extend.sh contains 2 carriage returns shown as whitespace – this isn’t a mistake :-)

Disk_resize.sh takes an argument ($1) which is the size in GB that you want to extend the root filesystem to. $1 is taken as a user entered value at execution time of the powerCLI script. This means that you can grow the base disk to a larger size than you may want to give solely to the root filesystem, whereas ResizeGuestPartition I think takes all available space.

Putting it all together.

Ok, so the assumptions I made were:

You are on at least ESXi 5.1.

• The rootFS will never have LVM on it and is on /dev/sda, and swap is on another Vdisk (you could change this pretty easily).

• VMTools is baked into the guest.

• The structure of the base disk containing the RootFS is completely flat. i.e: /usr /var ,etc are all hanging off of slash-root and are not contained in a Logical partition on separate /dev/sdX devices.

• The user would make sure that the required shell scripts (Disk_Extend.sh and Disk_resize.sh) are also baked into any VM/Template.

The second script will wait until it sees a response from VMTools before executing the shell script within the guest.

Here is the PowerCLI script (Grow_Flat_Linux_FS.sh):

<#
.SYNOPSIS
Resize a VMs flat root filesystem.
.DESCRIPTION
Resizes the vDisk and then extends the root filesystem within the guest.
.PARAMETER vmname
The name of the VM to be extended.
.PARAMETER CapacityGB
The size that you want the VDisk in the datastore to be in Gigabytes.
.PARAMETER disk_size
The size that you want the root disk filesystem to be extended to.

.EXAMPLE
.\& Grow_Flat_Linux_FS.sh
#>
[CmdletBinding()]
Param(
[Parameter(Mandatory=$false)]
[string]$vmname = $( Read-Host "Enter VM NAME to be extended" ),
[Parameter(Mandatory=$false)]
[string]$CapacityGB = $( Read-Host "Enter Proposed VDisk size " ),
[Parameter(Mandatory=$false)]
[string]$disk_size = $( Read-Host "Enter Root FS Max extended size G" )
)

Add-PSSnapin VMware.VimAutomation.core
$cred = Get-Credential

$vcenter = ""

# VM user - must be root user
$GuestCred = “
$GuestPass = ""

# VM Deployment Details
function PowerOn-VM {
    param ([string] $vmname)

    if ($vmname -eq "" ) {
          Write-Host "No VM defined."
     }

    if ((Get-VM $vmname).powerstate -eq "PoweredOn" ) {
        Write-Host "$vmname is already powered on."
          return "ok"
     } else {
        Start-VM -VM (Get-VM $vmname) -Confirm:$false
        Write-Host "Starting $vmname now."
        do {
            $status = (Get-vm $vmname | Get-View).Guest.ToolsRunningStatus
               sleep 10
        } until ($status -eq "guestToolsRunning")
         
        return "ok"
    }
}

Connect-VIServer -Server $vcenter -Credential $cred

Get-VM $vmname | Get-Harddisk | where {$_.Name -eq "Hard disk 1" }| Set-Harddisk -CapacityGB $CapacityGB -Confirm:$false -GuestUser $GuestCred -GuestPassword $GuestPass
$poweron = PowerOn-VM $vmname
if ($poweron -eq "ok") {
     Write-Host "$vmname started."
}

$command = "/root/Disk_Extend.sh"
Invoke-VMScript -VM $vmname -ScriptText $command -GuestUser $GuestCred -GuestPassword $GuestPass -ScriptType Bash
Restart-VMGuest -VM $vmname

Write-Host "Waiting for VM Tools to Start"
do {
$toolsStatus = (Get-VM $vmname | Get-View).Guest.ToolsRunningStatus
Write-Host $toolsStatus
sleep 3
} until ( $toolsStatus -eq “guestToolsRunning” )

$command2 = "/root/Disk_resize.sh $disk_size"
Invoke-VMScript -VM $vmname -ScriptText $command2 -GuestUser $GuestCred -GuestPassword $GuestPass -ScriptType Bash -ToolsWaitSecs 240

The script connects to Vcentre and asks for the VMName of the Guest whose disk you want to extend, the size of the VDisk and the required size of the RootFS. Then it extends the VDisk on the datastore. Once this is done it executes Disk_Extend.sh on the guest which deletes the partition table and applies a new one.

It does a reboot, and tells the PowerCLI script to wait until it sees a response from VMTools again on the guest. Then it does an online expansion of the root filesystem using resize2fs within the guest.

The script finishes and you have your larger root filesystem!

Hope this helps someone. Leave a comment if it was of use.

I tested this on Debian 6+7 and Ubuntu guests on ESXi 5.5. I tested the PowerCLI script both locally on a Windows box running PowerCLI and also in a web browser using PowerShell Web Access (PSWA).

This is just my approach on solving the expansion of the rootFS disk in Linux. It has worked for me but can’t stress enough make sure you have a backup, and that you test this for yourself on a non-mission critical VM first.

Matt Palmer 5th May 2016

Linux Guru & Technology Enthusiast…