Skip to content

Instantly share code, notes, and snippets.

@jphalip
Last active October 18, 2021 21:54
Show Gist options
  • Save jphalip/6025225 to your computer and use it in GitHub Desktop.
Save jphalip/6025225 to your computer and use it in GitHub Desktop.
A Python script I wrote to quickly shut down Vagrant/VirtualBox VMs. See also the associated blog post: https://www.julienphalip.com/blog/fast-shutdown-of-development-vagrantvirtualbox/
#!/usr/bin/env python
import argparse
import re
import os
import subprocess
try:
import json
except ImportError:
import simplejson as json
def get_running_vms():
"""
Returns the list of ids for the VMs currently running in VirtualBox.
"""
output = subprocess.Popen(['VBoxManage', 'list', 'runningvms'], stdout=subprocess.PIPE).communicate()[0]
vms = []
if output is not None:
lines = output.split('\n')
for line in lines:
pattern = re.compile(r'.*{(.*)}')
match = pattern.match(line)
if match:
vms.append(match.group(1))
return vms
def poweroff_vm(vm_id):
"""
Issues a 'poweroff' command to VirtualBox for the given VM.
"""
print "Powering off VM: %s..." % vm_id
subprocess.call(['VBoxManage', 'controlvm', vm_id, 'poweroff'])
def find_machines_dir():
"""
Walks up from the current path untils it finds a '.vagrant/machines/' directory.
"""
path = os.getcwd()
while path != '/':
machines_dir = os.path.join(path, '.vagrant/machines/')
if os.path.isdir(machines_dir):
return machines_dir
# Try one level up
path = os.path.abspath(os.path.join(path, os.pardir))
def find_vm_ids(machines_dir):
"""
Returns all the VM id files found under the given .vagrant/machines/ directory.
"""
matches = []
for root, dirnames, filenames in os.walk(machines_dir):
for filename in filenames:
if filename == 'id':
matches.append(os.path.join(root, filename))
return matches
# Parse the command's arguments
parser = argparse.ArgumentParser()
parser.add_argument('--all', action='store_true')
args = parser.parse_args()
running_vms = get_running_vms()
if args.all:
if len(running_vms):
print "%s VM(s) currently running..." % len(running_vms)
for vm in running_vms:
poweroff_vm(vm)
else:
print "No VMs are currently running."
else:
machines_dir = find_machines_dir()
if machines_dir:
for vm_id in find_vm_ids(machines_dir):
vm_id = open(vm_id).read()
if vm_id in running_vms:
poweroff_vm(vm_id)
else:
print "VM %s is already powered off." % vm_id
else:
print "Cannot find any '.vagrant/machines/' directory..."
@ageis
Copy link

ageis commented Oct 2, 2019

@jphalip thx for sharing. I remixed your script a bit, using the 'pick' module to allow selection of the VM to stop.

#!/usr/bin/env python2
import argparse
import re
import os
import subprocess
import json
import sys
from pick import pick


def get_running_vms():
    output = subprocess.Popen(["VBoxManage", "list", "runningvms"],
                              stdout=subprocess.PIPE).communicate()[0]
    vms = []
    if output is not None:
        lines = output.split("\n")
        for line in lines:
            pattern = re.compile(r'^"(.*)"\s+{(.*)}$')
            match = pattern.match(line)
            if match:
                vms.append({"name": match.group(1), "id": match.group(2)})
    return vms


def poweroff_vm(vm):
    print "Powering off VM: %s..." % vm
    subprocess.call(["VBoxManage", "controlvm", vm, "poweroff"])


def main():

    parser = argparse.ArgumentParser()
    parser.add_argument("--all", action="store_true")
    args = parser.parse_args()

    running_vms = get_running_vms()
    if len(running_vms) == 0:
        print "No VMs are currently running."
        sys.exit(0)

    if args.all:
        print "%s VM(s) currently running..." % len(running_vms)
        for vm in running_vms:
            poweroff_vm(vm["id"])
    else:
        prompt = "Choose which VM you'd like to stop. (press SPACE to mark, ENTER to continue):"
        selected, index = pick(running_vms, prompt)
        poweroff_vm(selected["id"])


if __name__ == '__main__':
    main()

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment