2

I've been using Vagrant with Ansible to perform certain ETL tasks. This has provided some flexibility and transparency: jobs can be easily be moved around and the YAML playbook provides some level of documentation.

Here's a minimal example of the Vagrantfile:

# -*- mode: ruby -*-
# vi: set ft=ruby :

VAGRANTFILE_API_VERSION = "2"

Vagrant.configure(VAGRANTFILE_API_VERSION) do |config|

  config.vm.box = "hashicorp/precise64"

  config.vm.provision "ansible" do |ansible|
    ansible.playbook = "vagrantCronjobPlaybook.yml"
  end

end

... and the Ansible playbook:

# vagrantCronjobPlaybook.yml
- hosts: all
  user: vagrant
  sudo: True

    tasks:

    - name: leave the 'VM up' flag
      shell: "touch /vagrant/done"

    - name: shutdown the box
      shell: shutdown now

Ideally, I'd like to provision a box to perform some long-running task and, once it's complete, destroy the Vagrant box or at least power off. I tried adding a shutdown now to the playbook, but that didn't stop the VM. When I run this manually:

$ vagrant up
Bringing machine 'default' up with 'virtualbox' provider...
[... 'all is well' messages removed]
    default: /vagrant => /Users/awoolford/Documents/vagrantCronjob
==> default: Running provisioner: ansible...

PLAY [all] ******************************************************************** 

GATHERING FACTS *************************************************************** 
ok: [default]

TASK: [leave the 'VM up' flag] ************************************************ 
changed: [default]

TASK: [shutdown the box] ****************************************************** 
changed: [default]

PLAY RECAP ******************************************************************** 
default                    : ok=3    changed=2    unreachable=0    failed=0 

... I see that the task completes:

$ ls done
done

However, simply performing a 'shutdown now' in the Ansible playbook doesn't stop the VM from running:

$ vagrant status
Current machine states:

default                   running (virtualbox)

Quesion) Is it possible for a Vagrant VM to destroy itself or power itself off?

A colleague suggested that we create a RESTful endpoint on the host that, on completion of a long-running job, the guest makes a call that triggers a vagrant destroy in the folder of the Vagrant box. On AWS, we've done used Python's Flask and boto package to terminate boxes in a similar manner. This all seems a bit clunky and I'm wondering if there's a better solution.

  • Have you tried Ansible's local tasks? – ceejayoz Sep 10 '14 at 3:35
  • Thanks @ceejayoz. Are you suggesting that the entire workflow be performed on the host machine rather than in a guest VM? I wanted to use transient virtual machines for flexibility (ease of moving the activities to other hardware as utilization increases), reliability (to avoid the situation where a 'greedy' activity might consume all the memory or CPU), and to keep the server fairly clean. – Alex Woolford Sep 10 '14 at 21:45
2

I haven't used ansible, but if you can configure it to do your "work" as a provisioning step, then a simple vagrant up && vagrant destroy should take care of it.

Vagrant will create your VM, start it, provision it (doing your work tasks) then destroy it.

  • Thanks James. That's perfect. On my setup, the vagrant destroy needed an extra switch: vagrant destroy --force to avoid the following error Vagrant is attempting to interface with the UI in a way that requires a TTY. – Alex Woolford Sep 11 '14 at 18:14
  • Also, on my box the cron entry was missing the path to the ansible executable (/usr/local/bin/) and so had to be added to the PATH, e.g. 09 00 * * * export PATH=/usr/local/bin/:$PATH; cd /Users/biggus/vagrantCronjob; sh vagrant up && vagrant destroy --force. – Alex Woolford Sep 11 '14 at 18:24

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.