Skip to content
Snippets Groups Projects

Replacement MR for defunct MR13

Merged Noe Nieto requested to merge noe.nieto/ldh_developer:master into master
2 files
+ 37
1
Compare changes
  • Side-by-side
  • Inline
Files
2
+ 291
0
#!/usr/bin/python3
import sys
import os
import os, stat
import argparse
import tempfile
import subprocess
@@ -10,26 +10,6 @@ from pathlib import Path
import ipaddress
vagrant_template = """
Vagrant.configure("2") do |config|
config.vm.hostname = "{hostname}"
config.vm.define :{hostname} do |{hostname}|
{hostname}.vm.box = "debian/stretch64"
{hostname}.vm.hostname = "{hostname}"
{hostname}.vm.provider :libvirt do |libvirt|
libvirt.driver = "kvm"
libvirt.memory = "{ram}"
libvirt.username = "root"
libvirt.graphics_type = "spice"
libvirt.cpus = {cpus}
end
{hostname}.vm.provision "ansible" do |ansible|
ansible.playbook = "shim.yml"
end
end
end
"""
ansible_shim = """
---
- hosts: all
@@ -37,23 +17,45 @@ ansible_shim = """
tasks:
- name: Shim file for ansible
file:
path: /etc/shipyard_shim.txt
path: /etc/ansible_shim.txt
state: touch
"""
XDG_VM_CONFIG_HOME = Path(os.environ['HOME'],'.config','ldh_developer','shipyard')
XDG_BOX_CONFIG_HOME = Path(os.environ['HOME'],'.config','ldh_developer','box')
XDG_PB_CONFIG_HOME = Path(os.environ['HOME'],'.config','ldh_developer','playbooks')
VG_REQ_PLUGINS = {'libvirt': 'vagrant-libvirt', 'digital_ocean': 'vagrant-digitalocean'}
HERE = Path(__file__).parent
DO_SSH_KEY_PATH = Path('~/.ssh/shipwright/').expanduser()
def ensure_plugins():
cp = subprocess.run(
['vagrant', 'plugin', 'list'],
stdout=subprocess.PIPE, stderr=subprocess.PIPE,
universal_newlines=True
)
if cp.returncode != 0:
print("Ooops, there's be something wrong with vagrant!!?")
print(cp.stdout)
print(cp.stderr)
sys.exit(1)
if set(VG_REQ_PLUGINS.values()) != set([l.split()[0] for l in cp.stdout.splitlines()]):
print('There are some missing vagrant plugins.')
print('Install them with: apt install ' + ' '.join(VG_REQ_PLUGINS))
print('Or run the bootstrap script')
sys.exit(1)
def only_if_box_exist(func):
def wrapper(*args, **kwargs):
hostname = args[0]
vagrant_wd = XDG_VM_CONFIG_HOME.joinpath(hostname)
vagrant_wd = XDG_BOX_CONFIG_HOME.joinpath(hostname)
if vagrant_wd.exists():
func(*args, **kwargs)
else:
print("Shipyard error: no vm managed by me has the hostname '{}'".format(hostname))
print("Error: no box managed by Shipwright has the hostname '{}'".format(hostname))
exit(1)
return wrapper
@@ -68,20 +70,20 @@ def is_ipaddress(ip_addr):
def print_status():
"""
Prints the status of all the virtual machines managed by shipyard
Prints the status of all the boxes managed by Shipwright
"""
shpyrd_paths = [str(d) for d in XDG_VM_CONFIG_HOME.iterdir() if d.is_dir()]
box_paths = [str(d) for d in XDG_BOX_CONFIG_HOME.iterdir() if d.is_dir()]
vgt_db = Path(
os.environ.get('VAGRANT_HOME', str(Path.home().joinpath('.vagrant.d'))),
'data', 'machine-index', 'index'
)
count = 0
if vgt_db.exists():
print('hostname \t State\t IP Address')
print('hostname \t State\t IP Address \t Provider')
db = json.loads(vgt_db.open().read())
for k, v in db['machines'].items():
vagrant_wd = v['vagrantfile_path']
if vagrant_wd in shpyrd_paths:
if vagrant_wd in box_paths:
# get the ip address
cp = subprocess.run(
['vagrant','ssh-config'], cwd=vagrant_wd,
@@ -97,39 +99,55 @@ def print_status():
break
print(f"{v['name']} \t {v['state']}\t {ip_addr}")
count+=1
print('Total {} machine(s)'.format(count))
print('Total {} box(es)'.format(count))
def create_box(hostname, ram, cpus):
def box_create(hostname, ram, cpus, provider, token):
"""
This creates a box using the template
"""
vagrant_wd = XDG_VM_CONFIG_HOME.joinpath(hostname)
vagrant_wd = XDG_BOX_CONFIG_HOME.joinpath(hostname)
if vagrant_wd.exists():
print("Shipyard error: There's already a vm with that hostname")
print("Shipyard error: There's already a box with that hostname")
exit(0)
vagrant_wd.mkdir(parents=True)
# Generate Vagrantfile
with vagrant_wd.joinpath('Vagrantfile').open(mode='w') as vfile:
vfile.write(vagrant_template.format(
hostname=hostname,
ram=ram,
cpus=cpus,
))
# The Ansible shim
vagrant_wd.mkdir(parents=True)
os.chmod(vagrant_wd, stat.S_IRWXU)
vagrant_wd.joinpath('shim.yml').open(mode='w').write(ansible_shim)
if provider == 'digital_ocean':
if not DO_SSH_KEY_PATH.joinpath('id_rsa').exists():
print("Creating ssh key required by Vagrant's Digital Ocean plugin ...")
DO_SSH_KEY_PATH.mkdir(parents=True, exist_ok=True)
os.chmod(DO_SSH_KEY_PATH, stat.S_IRWXU)
subprocess.run(['ssh-keygen', '-f', 'id_rsa', '-t', 'rsa', '-C', 'Created automatically by Shipwright', '-N', ''], cwd=DO_SSH_KEY_PATH)
vagrant_template = open(HERE.joinpath('digital_ocean.tpl'), 'r').read()
with vagrant_wd.joinpath('Vagrantfile').open(mode='w') as vfile:
vfile.write(vagrant_template.format(
hostname=hostname,
do_token=token,
username=os.environ['USER']
))
else:
vagrant_template = open(HERE.joinpath('libvirt.tpl'), 'r').read()
with vagrant_wd.joinpath('Vagrantfile').open(mode='w') as vfile:
vfile.write(vagrant_template.format(
hostname=hostname,
ram=ram,
cpus=cpus
))
# Execute vagrant with the generated vagrantfile
subprocess.run(['vagrant','up'], cwd=vagrant_wd)
@only_if_box_exist
def destroy_vm(hostname):
def box_destroy(hostname):
"""
Destroy a box, or all
"""
vagrant_wd = XDG_VM_CONFIG_HOME.joinpath(hostname)
vagrant_wd = XDG_BOX_CONFIG_HOME.joinpath(hostname)
subprocess.run(['vagrant','destroy'], cwd=vagrant_wd)
shutil.rmtree(vagrant_wd)
@@ -137,12 +155,13 @@ def destroy_vm(hostname):
@only_if_box_exist
def run_playbook(hostname, playbook, retry_file=None):
"""
run an Ansible playbook against this vm
run an Ansible playbook against this box
"""
vagrant_wd = XDG_VM_CONFIG_HOME.joinpath(hostname)
vagrant_wd = XDG_BOX_CONFIG_HOME.joinpath(hostname)
inventory_file = vagrant_wd.joinpath('.vagrant', 'provisioners', 'ansible', 'inventory', 'vagrant_ansible_inventory')
_args = [
'ansible-playbook', '-u', 'vagrant', '-i', f'{inventory_file}',
'-e', f'shipwright_box_config_home={vagrant_wd}',
f'{XDG_PB_CONFIG_HOME.joinpath(playbook).resolve()}'
]
@@ -153,20 +172,20 @@ def run_playbook(hostname, playbook, retry_file=None):
@only_if_box_exist
def start_vm(hostname):
def box_start(hostname):
"""
Starts the vm with the provided hostname
Starts the box with the provided hostname
"""
vagrant_wd = XDG_VM_CONFIG_HOME.joinpath(hostname)
vagrant_wd = XDG_BOX_CONFIG_HOME.joinpath(hostname)
subprocess.run(['vagrant','up'], cwd=vagrant_wd)
@only_if_box_exist
def halt_vm(hostname):
def box_halt(hostname):
"""
Stops the vm with the provided hostname
Stops the box with the provided hostname
"""
vagrant_wd = XDG_VM_CONFIG_HOME.joinpath(hostname)
vagrant_wd = XDG_BOX_CONFIG_HOME.joinpath(hostname)
subprocess.run(['vagrant','halt'], cwd=vagrant_wd)
@@ -175,68 +194,76 @@ def invoke_shell(hostname):
"""
Open a SSH session to the hostname
"""
vagrant_wd = XDG_VM_CONFIG_HOME.joinpath(hostname)
vagrant_wd = XDG_BOX_CONFIG_HOME.joinpath(hostname)
subprocess.run(['vagrant','ssh'], cwd=vagrant_wd)
@only_if_box_exist
def which(hostname):
"""
Print the directory of a vm by it's hostname
Print the directory of a box by it's hostname
"""
vagrant_wd = XDG_VM_CONFIG_HOME.joinpath(hostname)
vagrant_wd = XDG_BOX_CONFIG_HOME.joinpath(hostname)
print(vagrant_wd)
@only_if_box_exist
def gio_open_vm(hostname):
def box_gio_open(hostname):
"""
Open the vm directory in nautilis or any other file manager
Open the box directory in nautilis or any other file manager
"""
vagrant_wd = XDG_VM_CONFIG_HOME.joinpath(hostname)
vagrant_wd = XDG_BOX_CONFIG_HOME.joinpath(hostname)
subprocess.run(['gio','open', vagrant_wd])
COMMANDS = {
'status': "Prints the status of all the VM's managed by shipyard",
'create': 'Creates a new VM using vagrant and libvirt (KVM)',
'up': 'Start VM',
'halt': 'Stop/shutdown a VM',
'restart': 'Restarts the VM',
'destroy': 'Destroy the VM and do cleanup',
'ssh': 'Connect to the vm using SSH',
'playbook': 'Run a playbook against a machine',
'status': "Prints the status of all the boxes' managed by box",
'create': 'Creates a new box using either libvirt(default) or Digital Ocean',
'up': 'Start box',
'halt': 'Stop/shutdown a box',
'restart': 'Restarts the box',
'destroy': 'Destroy the box and do cleanup',
'ssh': 'Connect to the box using SSH',
'playbook': 'Run a playbook against a box',
'which': 'Print the path to the Vagrantfile',
'open': 'Show the working directory of the VM using the file manager.'
'open': 'Show the working directory of the box using the file manager.'
}
if __name__ == '__main__':
cmd_parser = argparse.ArgumentParser(
prog='shipyard',
description='This utility helps you mange virtual machines with Vagrant without dealing with configuration details',
prog='box',
description="This utility helps you mange virtual boxes'ith Vagrant without dealing with configuration details",
)
cmd_parser.add_argument('command', choices=COMMANDS,)
cmd_args = cmd_parser.parse_args(sys.argv[1:2])
# Ensure XDG_VM_CONFIG_HOME exists
XDG_VM_CONFIG_HOME.mkdir(parents=True, exist_ok=True)
# Ensure XDG_BOX_CONFIG_HOME exists
XDG_BOX_CONFIG_HOME.mkdir(parents=True, exist_ok=True)
ensure_plugins()
if cmd_args.command == 'status':
print_status()
sys.exit()
sub_parser = argparse.ArgumentParser(prog='shipyard',)
sub_parser = argparse.ArgumentParser(prog='box',)
if cmd_args.command == 'create':
sub_parser.usage = 'shipyard create <hostname> [--ram RAM] [--cpus CPUS]'
sub_parser.usage = 'box create <hostname> [--ram RAM] [--cpus CPUS] [--provider libvirt|digital_ocean] [--token]'
sub_parser.add_argument('hostname', help='This is the hostname for the new the box')
sub_parser.add_argument('--ram', help='Hoy much RAM for this box (default is 512)', default=512)
sub_parser.add_argument('--ram', help='Hoy much RAM for this box (default is 512MB for libvirt and 1GB for digital ocean.)', default=512)
sub_parser.add_argument('--cpus', help='Hoy many CPUs for this box (default is 1)', default=1)
sub_parser.add_argument('--provider', help='Tells Shipwright which vagrant provider to use. Default is libvirt', default='libvirt')
sub_parser.add_argument('--token', help="This is your personal access token for Digital Ocean's API")
sub_args = sub_parser.parse_args(sys.argv[2:])
create_box(sub_args.hostname, sub_args.ram, sub_args.cpus)
if sub_args.provider == 'digital_ocean' and sub_args.token is None:
print('Error: When using the digital_ocean provider you must provide the access token\n')
print('Example: shipwright box create foobar --provider digital_ocean --token 0d74f0a...')
sys.exit(1)
box_create(sub_args.hostname, sub_args.ram, sub_args.cpus, sub_args.provider, sub_args.token)
sys.exit()
sub_parser.add_argument('hostname', help='This is the hostname of the box')
if cmd_args.command == 'playbook':
sub_parser.usage = 'shipyard playbook hostname path/to/playbook.yml'
sub_parser.usage = 'box playbook hostname path/to/playbook.yml'
sub_parser.add_argument('playbook', help='The path to the playbook file')
sub_parser.add_argument('--retry', help='The path to the playbook retry file.', required=False)
sub_args = sub_parser.parse_args(sys.argv[2:])
@@ -245,20 +272,20 @@ if __name__ == '__main__':
sub_args = sub_parser.parse_args(sys.argv[2:])
if cmd_args.command == 'up':
start_vm(sub_args.hostname)
if cmd_args.command == 'halt':
halt_vm(sub_args.hostname)
if cmd_args.command == 'restart':
halt_vm(sub_args.hostname)
start_vm(sub_args.hostname)
box_start(sub_args.hostname)
elif cmd_args.command == 'halt':
box_halt(sub_args.hostname)
elif cmd_args.command == 'restart':
box_halt(sub_args.hostname)
box_start(sub_args.hostname)
elif cmd_args.command == 'destroy':
destroy_vm(sub_args.hostname)
box_destroy(sub_args.hostname)
elif cmd_args.command == 'ssh':
invoke_shell(sub_args.hostname)
elif cmd_args.command == 'which':
which(sub_args.hostname)
elif cmd_args.command == 'open':
gio_open_vm(sub_args.hostname)
box_gio_open(sub_args.hostname)
else:
cmd_parser.print_help()
exit(100)
Loading