Published on 28 July 2015 by

As part of the Puppet Enterprise 2015.2.0 release, we have built a new supported module to help manage virtual machines running on VMware’s vSphere platform.

The vSphere module allows you to describe your VMs in code, and then run Puppet to create and manage your infrastructure. More than just launching new VMs, the module can modify properties like CPU and memory, and ensure machines are in a stopped or running state. This quick code sample should give you an idea if you’re already familiar with Puppet.

vsphere_vm { '/dc/vm/samplemachine':
  ensure => running,
  source => '/dc/vm/templates/debian',
  memory => 1024,
  cpus   => 1,

Why Is This Useful?

One of the problems Puppet solves is configuration drift. Over time, the configuration of a host under manual management tends to wander, specifically as the gap grows between how you think it’s configured, how your colleagues think it’s configured and how it’s actually configured. The wider that gap, the more often you'll get unexpected issues and failed deployments. The same thing can happen with your VM infrastructure. When you're running virtualized infrastructure, you need to answer questions like:

  • Do you have 15 application servers or 20?
  • Do the database machines have 4GB or memory or 2GB?
  • Are all new machines really being launched from the approved RHEL template?

One approach to gaining this consistency is rigid change control processes for creating or changing machines, and maybe even a dedicated team responsible for doing so. But that has the side effect of slowing down critical changes, and puts a wall up between the development team who need to run their applications and the operations team running the infrastructure.

A better approach is infrastructure as code. The desired state of your vCenter cluster can be described in Puppet, giving you a simple model of your VMs in code. The model can be versioned using your favourite version control system, and changes can be proposed using pull requests or other code management workflows. Those modifications can be reviewed and tests written to enforce various constraints, all before the changes hit production. And finally, Puppet can ensure that the model in code matches the reality, by creating missing machines or modifying back to their desired state any machines that have drifted.

The real advantage comes when you describe entire application stacks in Puppet, and create your own simple abstraction for end users. Especially with the new language features available in Puppet Enterprise 2015.2 you could easily create something like this:

my_vsphere_based_application { 'primary':
  ensure              => running,
  load_balancers      => 3,
  web_servers         => 5,
  application_servers => 10,
  db_servers          => 5,
  total_memory        => 35328,

The Puppet language is pretty powerful, and anything really is possible. With the new node graph visualization in 2015.2, you can even visualize the application stack components you’ve modeled in Puppet code.

Works with Existing Infrastructure

You probably already have machines running in vCenter. The good news is the module doesn’t require you to describe all of that in Puppet to get started. In fact, the command line tools that form part of the module work with your existing machines, whether you describe them in Puppet code or not. For instance, we can run puppet resource vsphere_vm and get back information about our machines like so:

vsphere_vm { '/dc/vm/samplemachine':
  ensure                      => 'present',
  cpu_reservation             => '0',
  cpus                        => '1',
  guest_ip                    => '',
  hostname                    => 'debian',
  guest_os                    => 'Debian GNU/Linux 6 (64-bit)',
  instance_uuid               => '501870f2-f891-879f-2bb7-f87023789959',
  memory                      => '1024',
  memory_reservation          => '0',
  number_ethernet_cards       => '1',
  power_state                 => 'poweredOn',
  resource_pool               => 'general1',
  snapshot_disabled           => 'false',
  snapshot_locked             => 'false',
  snapshot_power_off_behavior => 'powerOff',
  template                    => 'false',
  tools_installer_mounted     => 'false',
  uuid                        => '4218419b-3b98-18ca-e77f-93b567dda463',

Not all of this information is manageable by the module; you can check the type reference for the full details. Do let us know in the comments what other properties and types you want to see support for in the future.

Next Steps

The module we’re releasing as part of 2015.2 is only the first small step. We’re actively looking for feedback from users about what works well and what could be improved, and about what other aspects of virtual machines, or vSphere as a whole, you would like to see managed by Puppet.

Learn More

Share via:
Posted in:

Providing access to things like affinity rules would be necessary for full functionality. I would imagine them this would be affinity based on some sort of grouping logic.

Sreejith Gireesan

when we try using PE Trial version, VMware integration fails.:
puppet module install puppetlabs-vsphere gives error: "You must have a valid Puppet Enterprise license on this node in order to download puppetlabs-vsphere" Are we missing something?

Hi Sreejith

Unfortunately you'll need a full version of PE rather than the trial license to try out the module. If you talk to your PE account manager or reach out to [email protected] you may be able to arrange something for a proof-of-concept.

Hi. Ive been testing with this module and it seems quite limited in functionality. For example, the ability to specify the datastore at creation time is a 'must have', plus being able to add and configure virtual hardware other than CPU and Memory. Also it would be useful if the guest OS could be shutdown gracefully.
Additionally Ive noticed that if configuring hardware at creation time, an immediate reboot takes place which prevents the 'create_command' from running to completion.

Hi Ernie

For the moment the module has a relatively small featureset, we're definitely hoping to add to that based on feedback like this - so thanks alot, it's much appreciated.

We have the ability to specifiy the datastore on the roadmap, I'm hopefull that should be in the next release of the module. In terms of other virtual hardware what properties did you specifically have in mind?

Thanks Gareth. I think Disk, NIC, Memory and CPU are the main requirements, but for each of those, it would be necessary to be able to assign basic properties, as follows.
Disk: size, datastore, thick/thin provisioning, controller
NIC: adapter type, network
Memory: size
CPU: quantity, cores per socket
Also we occasionally add additional SCSI controllers. And as per above, the ability to specify host and datastore at deployment time would be useful, as currently new VM's reside on the same location as the template.
Ive found that by using numerous templates, we can address the variety in hardware, but its not ideal. And whether assigning virtual hardware to new or existing VM's the process should always be: Graceful shutown -> Edit settings -> Restart VM.
Thanks again.

For basic use, this is great. It's not a great thing that VMWare only has the bloated 'customization specification' that is required if one wants to clone a vm from template and then assign it a specific IP Address, but that's not Puppetlabs' fault :) Anyway, even when going thought that VMWare pain, my POC provisioning mostly works, but my create_command never gets executed because the module can't seem to find the VM once it's provisioned, and it's definitely provisioned. I can see it in the VCenter console, I can see it with puppet resource vsphere_vm, and it's name matches the namevar I gave it, etc. I'm so close to being able to show a pretty slick demo to our customers, but w/o the ability to spin up the VM before classifying it and letting puppet do the rest, I'm dead in the water.

"change from absent to present failed: Could not set 'present' on ensure: FileNotFound: File <unspecified filename> was not found at"

Where this declaration: "vsphere_vm { '/CF PaaS DC/vm/Puppet/nginxnode':"

Matches what the module successfully provisioned:

[[email protected] ~]# puppet resource vsphere_vm '/CF PaaS DC/vm/Puppet/nginxnode'
vsphere_vm { '/CF PaaS DC/vm/Puppet/nginxnode':

And I just realized that it's very likely due to the spaces in the namevar , which I cannot do anything about. We use spaces in our VMWare folders; dumb idea or not.

Hi Steve. It looks like some of the details might be getting lost in the comment. If you could open an issue over on with the manifest you're trying to run, how you're running it and the output we can try and take a look.

I think the problem may be with the command attribute of the create_command hash. I've run into this same problem whereby I tried to touch a file to test this functionality. The value I input for the command attribute was:

command => '/bin/touch /tmp/test'

As such, the command that attempts to execute is "/bin/touch /tmp/test" which isn't a command, hence the "FileNotFound: File <unspecified filename>" error. Instead, /tmp/test is treated as an argument, therefore, the following worked for me:
create_command => {
command => '/bin/touch',
arguments => '/tmp/test',
working_directory => '/',
user => 'root',
password => 'password',

What I'd really like to get working is to install the puppet agent. This executes, but the install doesn't actually run. Any ideas?
create_command => {
command => '/usr/bin/curl',
arguments => "-k https://puppetmaster:8140/packages/current/install.bash | /bin/bash",
working_directory => '/',
user => 'root',
password => 'password',

Output from debug puppet run:
Info: Applying configuration version '1448123753'
Debug: Prefetching rbvmomi resources for vsphere_vm
Debug: Time spent querying for list of VMs: 0.202729599
Debug: Time spent querying for VMware vCenter Server Appliance: 0.035548355
Debug: Time spent querying for mco: 0.008928846
Debug: Time spent querying for hikvision: 0.008412461
Debug: Time spent querying for git: 0.00806874
Debug: Time spent querying for haproxy: 0.008271636
Debug: Time spent querying for redhat6.5: 0.00434785
Debug: Time spent querying for rhelrepo: 0.009028405
Debug: Time spent querying for puppet: 0.008502418
Info: Checking if machine /REESE/vm/kris exists
Info: Creating machine /REESE/vm/kris
Debug: GuestOperationsUnavailable: The guest operations agent could not be contacted.; retry attempt 1; 0.028043224 seconds have passed
Debug: GuestOperationsUnavailable: The guest operations agent could not be contacted.; retry attempt 2; 5.061476772 seconds have passed
Info: Ran /usr/bin/curl, started with PID 1935
Notice: /Stage[main]/Main/Vsphere_vm[/REESE/vm/kris]/ensure: changed absent to running
Debug: /Stage[main]/Main/Vsphere_vm[/REESE/vm/kris]: The container Class[Main] will propagate my refresh event
Debug: Class[Main]: The container Stage[main] will propagate my refresh event
Debug: Finishing transaction 42942720
Debug: Storing state
Debug: Stored state in 0.08 seconds
Notice: Applied catalog in 93.40 seconds

Hi Kris

We are having the same issue. Could you find a solution yet?


Hi Arkadi

I was able to get it to work using a pipe as follows:
create_command => {
command => '/usr/bin/curl',
arguments => '-k https://puppetmaster:8140/packages/current/install.bash | /bin/bash >/tmp/agent.install.log 2>&1',
working_directory => '/',
user => 'root',
password => 'password',

In some of my tests, I saw curl timeout while trying to connect to the puppetmaster. I speculate that the customization_spec wasn't fully applied yet, thus no network connectivity was available since the IP had not yet been assigned before vsphere_vm executed the command. This boils down to a timing issue between availability of an active network connection and the timing of the retry attempts of the vsphere_vm guest operations agent. A work around may be to use nc to check available connectivity to a port on the source of the curl command, or perhaps Gareth can throw in an attribute to wait for an available network connection in addition to guest additions availability before executing 'command'.

Hi Kris

I don't think it's a timing issue in my case. Please see the post at Gareth


Gareth Rushgrove

Hi Kris, Arkadi

I think you're speculation is likely correct, it certainly sounds likely depending on how you have networking setup within vSphere.

One approach to solve that would be to adjust some of the timeouts for curl, something like so. The options you're looking for are connect-timeout and max-time. Obviously increase or decrease the values to match you're environment.

create_command => {
  command => '/usr/bin/curl',
  arguments => '-k https://puppetmaster:8140/packages/current/install.bash --connect-timeout 120 --max-time 600 | /bin/bash >/tmp/agent.install.log 2>&1',
  working_directory => '/',
  user => 'root',
  password => 'password',

Do let us know if this reduces the failure rate, and thanks for posting the example.

Hi Gareth

Even when putting a simple script into the template which executes a touch it doesn't work. So a network problem can be excluded I think in this case. The result is an empty /opt directory.

Any ideas left :-)?

[email protected]:~# cat /usr/local/bin/

/usr/bin/touch /opt/fff;

/bin/echo "dasdsad dsa das das dsadsa";

exit 0;
[email protected]:~# ls -la /usr/local/bin/
total 12
drwxrwsr-x 2 root staff 4096 Nov 24 10:43 .
drwxrwsr-x 10 root staff 4096 Feb 28 2014 ..
-rwxr-xr-x 1 root staff 88 Nov 24 10:43
class vcenter::install {
vsphere_vm { '/Office/vm/Discovered virtual machine/test_vcenter':
ensure => running,
source => '/Office/vm/debian790amd64-16G',
memory => 1024,
cpus => 1,
create_command => {
command => '/usr/local/bin/',
arguments => '2>&1>/opt/provision.log',
working_directory => '/',
user => 'root',
password => '***',

This is the exact problem we're having with vsphere_vm on 2015.2. The agent output says the create_command ran with PID [XXX] but there's no indication on the new VM that I did. I even did the same test you did and try to touch a file and got the same result.

Did you ever figure out what was going on?

Nope not yet... You?

Even strace does not provide more information.

read(15, "\204wy\211'X'Z-\331\343\271\352 \375^\207\264\216Dy\333T\346\354\227\242\313\340A\v\304"..., 620) = 620
write(1, "\33[0;32mInfo: Ran /usr/local/bin/"..., 71Info: Ran /usr/local/bin/, started with PID 2661) = 71
write(1, "\n", 1
) = 1
sendto(7, "<30>Dec 11 10:42:59 puppet-agent"..., 95, MSG_NOSIGNAL, NULL, 0) = 95
write(1, "\33[mNotice: /Stage[main]/Basesysc"..., 144Notice: /Stage[main]/Basesysconf/Vsphere_vm[/Office/vm/Discovered virtual machine/test_vcenter]/ensure: changed absent to running) = 144
write(1, "\n", 1
) = 1
sendto(7, "<29>Dec 11 10:42:59 puppet-agent"..., 171, MSG_NOSIGNAL, NULL, 0) = 171
write(1, "\33[0;36mDebug: Looking up /Discov"..., 75Debug: Looking up /Discovered virtual machine/test_vcenter again) = 75

Thanks for all the comments everyone. We're working on providing some better guidance and working examples for the create_command parameter. I'll update here when we publish that.

Thanks Gareth

I had some time off soon after getting into the thick of it with trying to bootstrap the puppet agent via the create_command parameter and hadn't taken the opportunity to touch base with this dialog. With that said, I want to preface the below with the fact that I'm not having any issues with the create_command when testing it with "touch" as it creates a file for me in that regard.

As far as trying to bootstrap the puppet agent via create_command, here's what I found. When using the customization_spec, vmware disables the network interface until the spec is applied and the vm reboots. Since create_command is just waiting for vmware tools to become available, often times, what happens is the command is "sent in" during the middle of the application of the customization spec (when the network interface is still disabled) so the curl command hangs, and of course is killed when the customization spec reboots the vm.

I understand puppetlabs is looking into other ways of bootstrapping the puppet agent using the vsphere module, perhaps via another attribute that waits for the customization spec to complete before installing the agent?


The content of this field is kept private and will not be shown publicly.

Restricted HTML

  • Allowed HTML tags: <a href hreflang> <em> <strong> <cite> <blockquote cite> <code> <ul type> <ol start type> <li> <dl> <dt> <dd> <h2 id> <h3 id> <h4 id> <h5 id> <h6 id>
  • Lines and paragraphs break automatically.
  • Web page addresses and email addresses turn into links automatically.