🖥️ VMware ✨ New Post

Automate VMware VM Provisioning with Jenkins Parameterised Build & PowerCLI

Stop clicking through wizards. One Jenkins build trigger provisions a complete vSphere VM — CPU, RAM, up to five disks, static IP, DNS, hostname — in under 10 minutes. This guide covers the script, the build parameters, and the Jenkins job setup.

📅 21 May 2026 ✍️ Ravindrakumar Narayanan ⏱️ 14 min read 🏷️ VMware · Jenkins · PowerCLI · DevOps

🚀 Overview

Manually provisioning a new virtual machine in VMware vSphere means navigating multiple UI wizards, typing network details, resizing disks by hand, then RDP-ing into the guest OS to rename the machine and extend partitions. On a good day that is 30–45 minutes per VM. On a bad day it is an incident waiting to happen.

This post walks through a fully function-based PowerShell / PowerCLI script that handles the entire lifecycle — connecting to a Production or DR vCenter, cloning from a template, resizing CPU and RAM, attaching up to five additional disks, configuring a static IP and DNS inside the guest OS via VMware Tools, renaming the hostname, extending the C: partition, and emailing the team a formatted HTML provisioning report — all driven by a Jenkins Parameterised Build with zero engineer scripting required.

💡 The script targets two vCenter environments — Production and DR — selectable as a Jenkins Choice Parameter at build time. No script editing is ever needed between runs.

🏗️ Architecture & Flow

The diagram below shows the full lifecycle from Jenkins trigger through to confirmation email.

Engineer ──▶ [ Jenkins: Build with Parameters ] [ Inject $Env: vars from Jenkins Parameters ] [ New_VM_Creation_Cluster.ps1 runs on Windows Agent ] ├──▶ Connect-ToVCenter (Production or DR) ├──▶ New-VMFromTemplate (clone + place on ESXi host) ├──▶ Set-VMResources (CPU / RAM / C: disk) ├──▶ Add-AdditionalDisks (up to 5, persistent) ├──▶ Start-VM Wait-ForVMwareTools ├──▶ Set-VMGuestNetwork (IP / DNS via netsh) ├──▶ Set-VMGuestHostname (rename + async restart) ├──▶ Expand-GuestDisks (diskpart + GPT + NTFS) └──▶ Get-VMProvisioningReport [ HTML Email: vmware-automation@automatewithravi.com → it-alerts@automatewithravi.com ]

✅ Prerequisites

1

Jenkins LTS with a Windows Build Agent

The script requires a Windows node running PowerShell 5.1+. Register a Windows agent in Jenkins → Manage Nodes, label it windows-powercli, and configure it to run as a Windows service so it starts automatically after reboots.

2

VMware PowerCLI Module

On the Windows agent node run: Install-Module VMware.PowerCLI -Scope AllUsers -Force then disable the CEIP prompt: Set-PowerCLIConfiguration -Scope AllUsers -ParticipateInCEIP $false

3

vSphere Template

A Windows Server 2019/2022 VM template with VMware Tools pre-installed. A 40 GB base C: drive is sufficient — the script resizes it at deployment time based on the Jenkins parameter.

4

Jenkins Plugins

Install from Manage Jenkins → Plugins: Credentials Binding (secrets injection).

5

Log Directory on the Agent

Create C:\vSphere_Automation\Logs\NewVM_Provisioning\ on the Windows agent and grant the Jenkins service account write permissions. Timestamped transcript files land here for every build run.

📜 Script Walkthrough — Functions

The script is refactored into eight purpose-built PowerShell functions, each owning a single phase of the provisioning lifecycle. Every function has a .SYNOPSIS comment block, is independently testable, and can be extended without touching unrelated code.

🔌
Connect-ToVCenter

Connects and validates the vCenter session. Exits code 1 on failure so Jenkins marks the build FAILED immediately.

🖥️
New-VMFromTemplate

Calls New-VM with all deployment parameters. ESXi host auto-selected by environment flag.

⚙️
Set-VMResources

Null-guarded adjustment of memory, vCPU count, and primary disk size. Blank = template default preserved.

💾
Add-AdditionalDisks

Loops a single array to attach up to 5 persistent disks (E: through I:) — replacing 5 separate if/else blocks.

Wait-ForVMwareTools

Polls toolsStatus every 5 seconds until toolsOK — called twice: after power-on and after hostname restart.

🌐
Set-VMGuestNetwork

Runs netsh commands via VMware Tools to configure static IP, subnet, gateway, and DNS — no RDP needed.

🏷️
Set-VMGuestHostname

Renames the Windows computer name and triggers an async restart via Invoke-VMScript.

📊
Get-VMProvisioningReport

Collects final VM state into a hashtable: hostname, power state, CPU, RAM, disks, timestamps — drives the HTML email.

🔐 Credential Security

⚠️ The guest administrator password is injected via $Env:GuestPassword using the Jenkins Credentials Binding plugin. It is stored as an encrypted Secret Text credential in Jenkins and never appears in build logs, script files, or notification emails. Do not pass it as a plain-text String Parameter.

📧 Email Addresses

All notification emails are sent from vmware-automation@automatewithravi.com to it-alerts@automatewithravi.com via the internal SMTP relay.

Full script on GitHub: github.com/automatewithravi/VMware — file: New VM creation in cluster.ps1

🔧 Jenkins Setup — Parameterised Build (CI)

This gives engineers a self-service form in Jenkins to provision a VM on demand — no PowerShell knowledge required. All inputs are captured at runtime; the script itself is never modified between deployments.

1

Create a New Freestyle Job

Go to Jenkins → New Item → Freestyle Project. Name it vSphere-New-VM-Provisioning. Tick "This project is parameterised" at the top of the General section.

2

Add Choice Parameters for Target Environment

Click Add Parameter → Choice Parameter. Name: Production, choices: no then yes (no as default is safer). Repeat for a second parameter named DR. Engineers choose which vCenter to target before every build run.

3

Add String Parameters for VM Details

Add String Parameter entries for: VMName, VMGuestname, VMTemplate, VMDatastoreName, VMFolder, VM_Networkname, IPAddress, SubnetMask, GatewayIP, DNSServerIP, VM_Memory, VM_CPU, VM_Cdrive. See the full reference table in Section 7.

4

Store Credentials in Jenkins

Go to Manage Jenkins → Credentials → Global → Add Credentials. Add two Secret Text entries with IDs vcenter-password and guest-admin-password. These values are encrypted at rest and masked in all build logs.

5

Bind Credentials in Build Environment

Under Build Environment, tick "Use secret text(s) or file(s)". Map vcenter-password → variable name Password and guest-admin-password → variable name GuestPassword. Jenkins injects these as environment variables before the build step runs.

6

Add a Windows PowerShell Build Step

Under Build → Add Build Step → Windows PowerShell, enter the two lines below. Jenkins automatically injects all parameters and bound secrets as $Env: variables.

⚙️ Jenkins Build Step — PowerShell
Set-ExecutionPolicy Bypass -Scope Process -Force
& "C:\vSphere_Automation\Scripts\New_VM_Creation_Cluster.ps1"
7

Restrict to the Windows PowerCLI Agent

Under General → Restrict where this project can be run, enter windows-powercli. This prevents the job from running on a Linux agent where PowerCLI is unavailable, which would fail silently.

8

Archive Transcript Logs as Build Artefacts

Under Post-build Actions → Archive the artefacts, enter C:/vSphere_Automation/Logs/NewVM_Provisioning/*.txt. Every build retains a full timestamped audit transcript downloadable from the Jenkins UI.

🎯 Once configured, engineers go to Build with Parameters, complete the form, and click Build. The console output streams in real time and an HTML summary email arrives on completion. No PowerShell knowledge required.

📋 Build Parameters Reference

Every parameter below appears in the Jenkins Build with Parameters form. Optional fields are null-checked by the script — leave blank and the template default is preserved.

Parameter Name Type Description Required?
ProductionChoiceDeploy to Production vCenter? (no / yes)REQUIRED
DRChoiceDeploy to DR vCenter? (no / yes)REQUIRED
UsernameStringvCenter service account — e.g. svc-vsphere@automatewithravi.comREQUIRED
PasswordSecretvCenter password injected via credentials bindingREQUIRED
VMNameStringvSphere display name for the new VMREQUIRED
VMGuestnameStringWindows computer name (hostname) inside the guest OSREQUIRED
VMTemplateStringExact name of the vSphere template to clone fromREQUIRED
VMDatastoreNameStringTarget datastore for VM filesREQUIRED
VMFolderStringvCenter inventory folder path for the new VMREQUIRED
VM_NetworknameStringvSphere port group or distributed switch nameREQUIRED
IPAddressStringStatic IPv4 address for the guest NICOptional
SubnetMaskStringSubnet mask — e.g. 255.255.255.0Optional
GatewayIPStringDefault gateway IP addressOptional
DNSServerIPStringPrimary DNS server IP addressOptional
VM_MemoryStringRAM in GB (e.g. 8). Blank = template defaultOptional
VM_CPUStringNumber of vCPUs. Blank = template defaultOptional
VM_CdriveStringC: drive size in GB. Blank = template defaultOptional
VM_HDD1ChoiceAdd extra disk 1 as E: drive? (no / yes)Optional
VM_HDD1_SizeStringSize in GB for extra disk 1 (E:)Optional
VM_HDD2 … VM_HDD5ChoiceSame pattern for disks 2–5 (F: through I:)Optional
GuestPasswordSecretGuest OS administrator password via credentials bindingREQUIRED

🌟 Benefits

Speed

Full VM provisioning — disks, network, OS config — in under 10 minutes vs 30–45 minutes manually.

🔒

No Credential Exposure

vCenter and guest passwords are encrypted in Jenkins Credentials. They never appear in logs, scripts, or emails.

📋

Self-Service for Engineers

Any authorised engineer provisions a VM from the Jenkins form. Zero PowerShell or vSphere UI knowledge required.

🔁

Consistent Every Time

Every VM is built from the same template with the same script version. No drift between Production and DR builds.

📊

Full Audit Trail

Jenkins records who triggered the build, when, and with which parameters. Transcript logs are archived per build.

📧

Automatic Reporting

HTML summary email on success, alert on failure — from vmware-automation@automatewithravi.com.

💡 Pro Tips & Best Practices

🔑 Use a Dedicated Service Account

Create a dedicated AD account (e.g. svc-vsphere@automatewithravi.com) with the minimum vCenter roles required: Virtual Machine → Provisioning and Resource → Assign VM to Resource Pool. Never use a personal or domain admin account for automated workflows.

📦 Keep the Template Thin

The template should contain only the base OS, VMware Tools, and your corporate hardening baseline. Deliver all application software post-provisioning via a downstream Jenkins job (Chocolatey, Ansible, or DSC) so the template stays small and clone times stay fast.

⏱️ Add a VMware Tools Timeout Guard

The do … until toolsOK polling loop spins indefinitely if VMware Tools fails to start. Add a loop counter (e.g. 60 iterations × 5 seconds = 5-minute ceiling) and throw a terminating error on timeout so Jenkins marks the build FAILED cleanly rather than hanging the agent.

🛡️ Prevent Dual-Environment Deployments

Add a validation check in your PowerShell script that errors if both Production = yes and DR = yes are selected simultaneously. Alternatively use an Active Choices parameter so selecting one automatically disables the other in the Jenkins UI.

📁 Transcript logs land in C:\vSphere_Automation\Logs\NewVM_Provisioning\ with a timestamp filename per run. Archive them in Jenkins under Post-build Actions to retain a permanent, downloadable record for every deployment — invaluable during incident investigations.

📦 GitHub Repository

The complete refactored script — New VM creation in cluster.ps1 — is published in the VMware automation repository. Clone it, update the vCenter hostnames and ESXi host names to match your environment, store your credentials in Jenkins, and you are ready to run your first parameterised build.

Star the repository to be notified when new VMware automation scripts are added — covering snapshot management, datastore reporting, host patching, and more.