Automation

 View Only
  • 1.  Expanding a disk inside guest as part of VM build

    Posted May 09, 2019 06:52 PM

    I have been reading a lot of articles online, and reading through the many times I have seen this question has been asked here on the forums, but haven't seen a concrete answer. I currently have a build script I supply to customers for building new servers, both Windows and Linux flavors. The customer populates a web form or thick client with all necessary info, and the script adds the machine to A.D., selects a free IP address from their tool of choice, builds the VM, and adds it to the requisite GPOs. The only piece I have not been able to work out is the correlation of in-guest drives with VM disks. Currently the web form has slots for number of disks and size, but the admin building the machine is still required to go in manually and initialize the disk and assign a drive letter.

    I have seen a number of suggestions around using invoke-vmscript, but most of them break down to using diskpart. For example, if I have a drive letter assigned already, I can do something like this, to use the max size:

    $VolumeLetter = "e"

        Invoke-VMScript -vm $VM `

                        -ScriptText "echo rescan > c:\diskpart.txt && echo select vol $VolumeLetter >> c:\diskpart.txt && echo extend >> c:\diskpart.txt && diskpart.exe /s c:\diskpart.txt" `

                        -ScriptType BAT

    But this doesn't help me on raw disks. If I have to log in to set the drive letter, the work is already done. I have also come across a number of posts about using WMI through invoke-vmscript but folks seem to run into the same frustrations as I am; pulling back raw disk info is easy enough, but assigning the drive letter does not work.

    So I am just curious if anyone has this successfully, and reliably, running in their environment.



  • 2.  RE: Expanding a disk inside guest as part of VM build
    Best Answer

    Posted May 09, 2019 07:26 PM

    There have been a number of attempts, but in my experience, none of these is 100% fool-proof.
    Since I understand that you are dealing with a freshly installed system, some of these methods might work for you.
    But then you seem to mention that you handle Win and Lin guest OS installations, which none of the current scripts I know can handle.

    In short, I don't think there is currently a one-size-fits-all solution for your issue.



  • 3.  RE: Expanding a disk inside guest as part of VM build

    Posted May 09, 2019 07:31 PM

    Thanks for the reply, I was afraid of such. At present I am only worried about drives on the Windows side (the script has branching logic based on OS), but to further complicate things I have found a number of customers lately that block PSRemoting, so as soon as the server reboots and picks up GPO that avenue is closed to me as well.



  • 4.  RE: Expanding a disk inside guest as part of VM build

    Posted May 09, 2019 07:33 PM

    Running a script inside the guest OS through Invoke-VMScript is not a form of PS Remoting.

    I don't think a PS Remoting GPO can block that.
    Unless of course, they block the use of PS altogether.



  • 5.  RE: Expanding a disk inside guest as part of VM build

    Posted May 09, 2019 08:58 PM

    No, you are correct, I run other scripts through Invoke-VMScript with no issues. I just meant that upon hitting a snag getting this process to work with Invoke-VMScript I thought to simply do it all remotely with PS Remoting, but too often that is blocked. Each time I build a server I am making a non-persistent copy of the customization spec and then modifying; I am looking at how I might use the Run Once to potentially do what I want. It won't happen until someone logs in, but in testing I can initialize, apply a drive letter, and convert upwards of 10 drives to dynamic in less than a minute.



  • 6.  RE: Expanding a disk inside guest as part of VM build

    Posted May 10, 2019 05:54 PM

    Just to circle back, for anyone who may search for similar in the future, this is as far as I have come thus far:

    The build script reads in the csv, producing an array of machines to be built, like so:

    NameCPURAMIPNetMaskGatewayDNS1DNS2PortGroupFolderDescriptionCompute_ClusterDataStore_ClusterTemplateLocationDomainSQLDrive1SizeDrive2LetterDrive2SizeDrive2NameDrive3LetterDrive3SizeDrive3NameDrive4LetterDrive4SizeDrive4NameDrive5LetterDrive5SizeDrive5NameOSTypeOSArchOwnerEnvironmentRequest
    JLoTest0124172.24.16.25255.255.248.0172.24.16.6172.24.16.2172.24.16.3dvportGroup_VLAN22Testing

    Testing

    CXO_ProductionCMO_I_Non-Prod2016_DEOKINTRANo100F30LogsG150AppsI90BackupJ120RolloverWindows2016HostingSandbox123456

    The foreach loop takes each VM object and runs it through the various build processes. At the end, on the newly built server, if I pull in that same VM object from the csv, I can use this function to prepare the disks:

    Function _initializeDisks {

       [CmdLetBinding()]

       Param (

          [Parameter(Mandatory, Position=1)]

             $oServer

        )

        $aFinal = @()

        $aRawDisks = gwmi win32_diskdrive |

                         where {$_.Partitions -eq 0} |

                            Select @{n="Number";e={$_.index}}, @{n="Size"; e={[math]::Round(((($_.Size / 1024) /1024) / 1024))}} |

                               Sort Number

        foreach($a in 2..5) {

            $sLetter = "Drive$($a)Letter"

            $sSize = "Drive$($a)Size"

            $sName = "Drive$($a)Name"

            if(!([string]::IsNullOrEmpty($oServer.$sSize))) {

                foreach ($disk in $aRawDisks) {

                    if ($oServer.$sSize -eq $disk.Size) {

                        $aFinal += New-Object PSObject -Property @{DriveLetter=$($oServer.$sLetter);Number=$($disk.Number);Size=$($disk.Size);Description=$($oServer.$sName)}

                    }      

                }

            }

        }

        foreach($newDrive in $aFinal) {

           Initialize-Disk -Number $newDrive.Number -PartitionStyle GPT

           $sDrive = New-Partition -DiskNumber $newDrive.Number -AssignDriveLetter -UseMaximumSize

           Format-Volume -DriveLetter $sDrive.DriveLetter -FileSystem NTFS

           Set-Volume -DriveLetter $sDrive.DriveLetter -NewFileSystemLabel $newDrive.Description

           Set-Partition -DriveLetter $sDrive.DriveLetter -NewDriveLetter $newDrive.DriveLetter

           Start-Sleep 1

           $sCommand = "select disk $($newDrive.Number)`r`nconvert dynamic"

           $sCommand | diskpart

        }

    }

    This works great, but again has to be after someone logs into the new server and manually runs it. I have yet to be able to use Invoke-VMScript to do this process; cannot seem to pass the VM object through. Hope to overcome that hurdle at some point and make this fully automated.



  • 7.  RE: Expanding a disk inside guest as part of VM build

    Posted May 10, 2019 06:07 PM

    I'm still not sure that I understand what the problem is you have with Invoke-VMScript when assigning the harddisks and then creating a drive inside the guest OS.
    When you add a harddisk (with New-HardDisk), you could then run inside the guest OS (through Invoke-VMScript) a script to discover this new disk, format it and assign a drive letter.
    Repeat for the number of harddisks required.



  • 8.  RE: Expanding a disk inside guest as part of VM build

    Posted May 10, 2019 09:06 PM

    The issue I am having is passing that $VM object in through the Invoke-VMScript. Something like this, for example:

    $script = '&"C:\Users\Me\Desktop\InitializeDisks.ps1"'

    Get-VM -Name "JLoTest" |

        Invoke-VMScript -ScriptText $script -GuestCredential $creds

    Throws errors because of one of more missing mandatory parameters (oServer). However if I try to pass the $VM object to the script like so:

    $script = '&"C:\Users\Me\Desktop\InitializeDisks.ps1 -oServer "' + $VM

    Get-VM -Name "JLoTest" |

        Invoke-VMScript -ScriptText $script -GuestCredential $creds

    It throws an error, like it cannot parse through the object.

    ScriptOutput : JLoTest : The term 'JLoTest' is not recognized as the name of a cmdlet, function, script file,

                   or operable program. Check the spelling of the name, or if a path was included, verify that the path is correct and

                   try again.

                   At line:1 char:69

                  + ... sktop\InitializeDisks.ps1 -oServer "@{Name=JLoTest; NumCPU ...

                   +                                                ~~~~~~~~~~~~~~~~~~

    I have confirmed I can run scripts requiring no parameters, or simple strings, through Invoke-VMScript. Just not sure the correct syntax to pass the $VM object in,



  • 9.  RE: Expanding a disk inside guest as part of VM build

    Posted May 10, 2019 09:13 PM

    You need to use variable substitution for that.

    See my Here strings and the ExpandString method dive.

    Your code could be something like this

    $script = @'

    &"C:\Users\Me\Desktop\InitializeDisks.ps1 -oServer $vmName"

    '@


    $vmName = 'JLoTest'

    $scriptSub = $ExecutionContext.InvokeCommand.ExpandString($script)


    Invoke-VMScript -VM $vmName -ScriptText $scriptSub -GuestCredential $creds