diff --git a/library/vagrant b/library/vagrant
deleted file mode 100644
index 3b97efc169..0000000000
--- a/library/vagrant
+++ /dev/null
@@ -1,574 +0,0 @@
-#!/usr/bin/python
-# This file is part of Ansible
-#
-# Ansible is free software: you can redistribute it and/or modify
-# it under the terms of the GNU General Public License as published by
-# the Free Software Foundation, either version 3 of the License, or
-# (at your option) any later version.
-#
-# Ansible is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with Ansible. If not, see .
-
-DOCUMENTATION = '''
----
-module: vagrant
-short_description: create a local instance via vagrant
-description:
- - creates VM instances via vagrant and optionally waits for it to be 'running'.
-version_added: "1.1"
-options:
- state:
- description:
- - Should the VMs be "present" or "absent."
- cmd:
- description:
- - vagrant subcommand to execute.
- required: false
- default: null
- aliases: ['command']
- choices: [ "up", "status", "config", "ssh", "halt", "destroy", "clear" ]
- box_name:
- description:
- - vagrant boxed image to start
- required: false
- default: null
- aliases: ['image']
- box_path:
- description:
- - path to vagrant boxed image to start
- required: false
- default: null
- aliases: []
- vm_name:
- description:
- - name to give an associated VM
- required: false
- default: null
- aliases: []
- count:
- description:
- - number of instances to launch
- required: False
- default: 1
- aliases: []
- forward_ports:
- description:
- - comma separated list of ports to forward to the host. If the port is under 1024, the host port will be the guest port +10000
- required: False
- aliases: []
- memory:
- description:
- - memory in MB
- required: False
-
-examples:
- - code: 'local_action: vagrant cmd=up box_name=lucid32 vm_name=webserver'
- description:
-requirements: [ "vagrant", "python-vagrant" ]
-author: Rob Parrott
-'''
-
-VAGRANT_FILE = "./Vagrantfile"
-VAGRANT_DICT_FILE = "./Vagrantfile.json"
-VAGRANT_LOCKFILE = "./.vagrant-lock"
-
-VAGRANT_FILE_HEAD = "Vagrant::Config.run do |config|\n"
-VAGRANT_FILE_BOX_NAME = " config.vm.box = \"%s\"\n"
-VAGRANT_FILE_VM_STANZA_HEAD = """
- config.vm.define :%s do |%s_config|
- %s_config.vm.network :hostonly, "%s"
- %s_config.vm.box = "%s"
-"""
-VAGRANT_FILE_HOSTNAME_LINE = " %s_config.vm.host_name = \"%s\"\n"
-VAGRANT_FILE_PORT_FORWARD_LINE = " %s_config.vm.forward_port %s, %s\n"
-VAGRANT_FILE_MEMORY_LINE = " %s_config.vm.customize [\"modifyvm\", :id, \"--memory\", %s]\n"
-VAGRANT_FILE_VM_STANZA_TAIL=" end\n"
-
-VAGRANT_FILE_TAIL = "\nend\n"
-
-# If this is already a network on your machine, this may fail ... change it here.
-VAGRANT_INT_IP = "192.168.179.%s"
-
-DEFAULT_VM_NAME = "ansible"
-DEFAULT_VM_RAM = 1024
-
-import sys
-import subprocess
-#import time
-import os.path
-import json
-
-try:
- import lockfile
-except ImportError:
- print "Python module lockfile is not installed. Falling back to using flock(), which will fail on Windows."
-
-try:
- import vagrant
-except ImportError:
- print "failed=True msg='python-vagrant required for this module'"
- sys.exit(1)
-
-class VagrantWrapper(object):
-
- def __init__(self):
- '''
- Wrapper around the python-vagrant module for use with ansible.
- Note that Vagrant itself is non-thread safe, as is the python-vagrant lib, so we need to lock on basically all operations ...
- '''
- # Get a lock
- self.lock = None
-
- try:
- self.lock = lockfile.FileLock(VAGRANT_LOCKFILE)
- self.lock.acquire()
- except:
- # fall back to using flock instead ...
- try:
- import fcntl
- self.lock = open(VAGRANT_LOCKFILE, 'w')
- fcntl.flock(self.lock, fcntl.LOCK_EX)
- except:
- print "failed=True msg='Could not get a lock for using vagrant. Install python module \"lockfile\" to use vagrant on non-POSIX filesytems.'"
- sys.exit(1)
-
- # Initialize vagrant and state files
- self.vg = vagrant.Vagrant()
-
- # operation will create a default data structure if none present
- self._deserialize()
- self._serialize()
-
- def __del__(self):
- '''Clean up file locks'''
- try:
- self.lock.release()
- except:
- os.close(self.lock)
- os.unlink(self.lock)
-
- def prepare_box(self, box_name, box_path):
- '''Given a specified name and URL, import a Vagrant "box" for use.'''
- changed = False
- if box_name == None:
- raise Exception("You must specify a box_name with a box_path for vagrant.")
- boxes = self.vg.box_list()
- if not box_name in boxes:
- self.vg.box_add(box_name, box_path)
- changed = True
-
- return changed
-
- def up(self, box_name, vm_name=None, count=1, box_path=None, ports=[]):
- '''Fire up a given VM and name it, using vagrant's multi-VM mode.'''
-
- changed = False
- if vm_name == None:
- vm_name = DEFAULT_VM_NAME
-
- if box_name == None:
- raise Exception("You must specify a box name for Vagrant.")
- if box_path != None:
- changed = self.prepare_box(box_name, box_path)
-
- for icount in range(int(count)):
-
- self._deserialize()
-
- this_instance_dict = self._get_instance(vm_name,icount)
- if not 'box_name' in this_instance_dict:
- this_instance_dict['box_name'] = box_name
-
- this_instance_dict['forward_ports'] = ports
-
- # Save our changes and run
- inst_array = self._instances()[vm_name]
- inst_array[icount] = this_instance_dict
-
- self._serialize()
-
- # See if we need to fire it up ...
- vgn = this_instance_dict['vagrant_name']
- status = self.vg.status(vgn)
- if status != 'running':
- self.vg.up(False, this_instance_dict['vagrant_name'])
- changed =True
-
- ansible_instance_array = self._build_instance_array_for_ansible(vm_name)
- return (changed, ansible_instance_array)
-
- def status(self, vm_name = None, index = -1):
- '''Return the run status of the VM instance. If no instance N is given, returns first instance.'''
- vm_names = []
- if vm_name != None:
- vm_names = [vm_name]
- else:
- vm_names = self._instances().keys()
-
- statuses = {}
- for vmn in vm_names:
- stat_array = []
- instance_array = self.vg_data['instances'][vmn]
- if index >= 0:
- instance_array = [ self._get_instance(vmn,index) ]
- for inst in instance_array:
- vgn = inst['vagrant_name']
- stat_array.append(self.vg.status(vgn))
- statuses[vmn] = stat_array
-
- return (False, statuses)
-
- def config(self, vm_name, index = -1):
- '''Return info on SSH for the running instance.'''
- vm_names = []
- if vm_name != None:
- vm_names = [vm_name]
- else:
- vm_names = self._instances().keys()
-
- configs = {}
- for vmn in vm_names:
- conf_array = []
- instance_array = self.vg_data['instances'][vmn]
- if index >= 0:
- instance_array = [ self._get_instance(vmn,index) ]
- for inst in instance_array:
- cnf = self.vg.conf(None, inst['vagrant_name'])
- conf_array.append(cnf)
- configs[vmn] = conf_array
-
- return (False, configs)
-
- def halt(self, vm_name = None, index = -1):
- '''Shuts down a vm_name or all VMs.'''
-
- changed = False
- vm_names = []
- if vm_name != None:
- vm_names = [vm_name]
- else:
- vm_names = self._instances().keys()
-
- statuses = {}
- for vmn in vm_names:
- stat_array = []
- instance_array = self.vg_data['instances'][vmn]
- if index >= 0:
- instance_array = [ self.vg_data['instances'][vmn][index] ]
- for inst in instance_array:
- vgn = inst['vagrant_name']
- if self.vg.status(vgn) == 'running':
- self.vg.halt(vgn)
- changed = True
- stat_array.append(self.vg.status(vgn))
- statuses[vmn] = stat_array
-
- return (changed, statuses)
-
- def destroy(self, vm_name=None, index = -1):
- '''Halt and remove data for a VM, or all VMs.'''
-
- self._deserialize()
-
- (changed, stats) = self.halt(vm_name, index)
-
- self.vg.destroy(vm_name)
- if vm_name != None:
- self._instances().pop(vm_name)
- else:
- self.vg_data['instances'] = {}
-
- self._serialize()
-
- changed = True
-
- return changed
-
- def clear(self, vm_name=None):
- '''Halt and remove data for a VM, or all VMs. Also clear all state data.'''
-
- changed = self.vg.destroy(vm_name)
-
- if os.path.isfile(VAGRANT_FILE):
- os.remove(VAGRANT_FILE)
- if os.path.isfile(VAGRANT_DICT_FILE):
- os.remove(VAGRANT_DICT_FILE)
-
- return changed
-#
-# Helper Methods
-#
-
- def _instances(self):
- return self.vg_data['instances']
-
- def _get_instance(self, vm_name, index):
-
- instances = self._instances()
-
- inst_array = []
- if vm_name in instances:
- inst_array = instances[vm_name]
-
- if len(inst_array) > index:
- return inst_array[index]
-
- #
- # otherwise create one afresh
- #
- this_instance_N = self.vg_data['num_inst']+1
- name_for_vagrant = "%s%d" % (vm_name.replace("-","_"),index)
-
- instance_dict = dict(
- n = index,
- N = this_instance_N,
- name = vm_name,
- vagrant_name = name_for_vagrant,
- internal_ip = VAGRANT_INT_IP % (255-this_instance_N),
- forward_ports = [],
- ram = DEFAULT_VM_RAM,
- )
-
- # Save this ...
- self.vg_data['num_inst'] = this_instance_N
- inst_array.append(instance_dict)
-
- self._instances()[vm_name] = inst_array
-
- return instance_dict
-
- #
- # Serialize/Deserialize current state to a JSON representation, and
- # a file format for Vagrant.
- #
- # This is where we need to deal with file locking, since multiple threads/procs
- # may be trying to operate on the same files
- #
-
- def _serialize(self):
- '''Save state to a JSON file, and write the Vagrantfile based on this.'''
- self._save_state()
- self._write_vagrantfile()
-
- def _deserialize(self):
- '''Load in data from the JSON state file.'''
- self._load_state()
-
-
- #
- # Manage a JSON representation of vagrantfile for statefulness across invocations.
- #
- def _load_state(self):
- self.vg_data = dict(num_inst=0, instances = {})
- if os.path.isfile(VAGRANT_DICT_FILE):
- json_file=open(VAGRANT_DICT_FILE)
- self.vg_data = json.load(json_file)
- json_file.close()
-
-# def _state_as_string(self):
-# from StringIO import StringIO
-# io = StringIO()
-# json.dump(self.vg_data, io)
-# return io.getvalue()
-
- def _save_state(self):
- json_file=open(VAGRANT_DICT_FILE, 'w')
- json.dump(self.vg_data,json_file, sort_keys=True, indent=4, separators=(',', ': '))
- json_file.close()
-
- #
- # Translate the state dictionary into the Vagrantfile
- #
- def _write_vagrantfile(self):
-
- vfile = open(VAGRANT_FILE, 'w')
- vfile.write(VAGRANT_FILE_HEAD)
-
- instances = self._instances()
- for vm_name in instances.keys():
- inst_array = instances[vm_name]
- for index in range(len(inst_array)):
- instance_dict = inst_array[index]
- name = instance_dict['vagrant_name']
- ip = instance_dict['internal_ip']
- box_name = instance_dict['box_name']
- vfile.write(VAGRANT_FILE_VM_STANZA_HEAD % (name, name, name, ip, name, box_name))
- if 'ram' in instance_dict:
- vfile.write(VAGRANT_FILE_MEMORY_LINE % (name, instance_dict['ram']))
- vfile.write(VAGRANT_FILE_HOSTNAME_LINE % (name, name.replace('_','-')))
- if 'forward_ports' in instance_dict:
- for port in instance_dict['forward_ports']:
- port = int(port)
- host_port = port
- if port < 1024:
- host_port = port + 10000
- vfile.write(VAGRANT_FILE_PORT_FORWARD_LINE % (name, port, host_port))
- vfile.write(VAGRANT_FILE_VM_STANZA_TAIL)
-
- vfile.write(VAGRANT_FILE_TAIL)
- vfile.close()
-
- #
- # To be returned to ansible with info about instances
- #
- def _build_instance_array_for_ansible(self, vmname=None):
-
- vm_names = []
- instances = self._instances()
- if vmname != None:
- vm_names = [vmname]
- else:
- vm_names = instances.keys()
-
- ans_instances = []
- for vm_name in vm_names:
- for inst in instances[vm_name]:
- vagrant_name = inst['vagrant_name']
- cnf = self.vg.conf(None,vagrant_name)
- vg_data = instances[vm_name]
- if cnf != None:
- instance_dict = dict(
- name = vm_name,
- vagrant_name = vagrant_name,
- id = cnf['Host'],
- public_ip = cnf['HostName'],
- internal_ip = inst['internal_ip'],
- public_dns_name = cnf['HostName'],
- port = cnf['Port'],
- username = cnf['User'],
- key = cnf['IdentityFile'],
- status = self.vg.status(vagrant_name)
- )
- ans_instances.append(instance_dict)
-
- return ans_instances
-
-#--------
-# MAIN
-#--------
-def main():
-
- module = AnsibleModule(
- argument_spec = dict(
- state=dict(),
- cmd=dict(required=False, aliases = ['command']),
- box_name=dict(required=False, aliases = ['image']),
- box_path=dict(),
- vm_name=dict(),
- forward_ports=dict(),
- count = dict(default='1'),
- )
- )
-
- state = module.params.get('state')
- cmd = module.params.get('cmd')
- box_name = module.params.get('box_name')
- box_path = module.params.get('box_path')
- vm_name = module.params.get('vm_name')
- forward_ports = module.params.get('forward_ports')
-
- if forward_ports != None:
- forward_ports=forward_ports.split(',')
- if forward_ports == None:
- forward_ports=[]
-
- count = module.params.get('count')
-
- # Initialize vagrant
- vgw = VagrantWrapper()
-
- #
- # Check if we are being invoked under an idempotency idiom of "state=present" or "state=absent"
- #
- try:
- if state != None:
-
- if state != 'present' and state != 'absent':
- module.fail_json(msg = "State must be \"present\" or \"absent\" in vagrant module.")
-
- if state == 'present':
-
- changd, insts = vgw.up(box_name, vm_name, count, box_path, forward_ports)
- module.exit_json(changed = changd, instances = insts)
-
- if state == 'absent':
- changd = vgw.halt(vm_name)
- module.exit_json(changed = changd, status = vgw.status(vm_name))
-
-
- #
- # Main command tree for old style invocation
- #
-
- else:
-
- if cmd == 'up':
-
- if count == None:
- count = 1
- (changd, insts) = vgw.up(box_name, vm_name, count, box_path, forward_ports)
- module.exit_json(changed = changd, instances = insts)
-
- elif cmd == 'status':
-
-# if vm_name == None:
-# module.fail_json(msg = "Error: you must specify a vm_name when calling status." )
-
- (changd, result) = vgw.status(vm_name)
- module.exit_json(changed = changd, status = result)
-
- elif cmd == "config" or cmd == "conf":
-
- if vm_name == None:
- module.fail_json(msg = "Error: a vm_name is required when calling config.")
- (changd, cnf) = vgw.config(vm_name)
- module.exit_json(changed = changd, config = cnf)
-
- elif cmd == 'ssh':
- # this doesn't really seem to belong here, should just manage the VM with ansible -- MPD
-
- if vm_name == None:
- module.fail_json(msg = "Error: a vm_name is required when calling ssh.")
-
- (changd, cnf) = vgw.config(vm_name)
- sshcmd = "ssh -i %s -p %s %s@%s" % (cnf["IdentityFile"], cnf["Port"], cnf["User"], cnf["HostName"])
- sshmsg = "Execute the command \"vagrant ssh %s\"" % (vm_name)
- module.exit_json(changed = changd, msg = sshmsg, SshCommand = sshcmd)
-
- elif cmd == 'halt':
-
- (changd, stats) = vgw.halt(vm_name)
- module.exit_json(changed = changd, status = stats)
-
- elif cmd == 'destroy':
-
- changd = vgw.destroy(vm_name)
- module.exit_json(changed = changd, status = vgw.status(vm_name))
-
- elif cmd == 'clear':
-
- changd = vgw.clear()
- module.exit_json(changed = changd)
-
- else:
-
- module.fail_json(msg = "Unknown vagrant subcommand: \"%s\"." % (cmd))
-
- except subprocess.CalledProcessError as errer:
- module.fail_json(msg = "Vagrant command failed: %s." % (errer))
- except Exception as errer:
- module.fail_json(msg = errer.__str__())
- module.exit_json(status = "success")
-
-
-
-
-# this is magic, see lib/ansible/module_common.py
-#<>
-
-main()