From 81da9d7c1385678f88ec4a403fb6a8b895475f18 Mon Sep 17 00:00:00 2001 From: gryf Date: Sat, 5 Jun 2021 17:54:14 +0200 Subject: [PATCH] Added ssh command --- README.rst | 42 +++++++++++++++++++++++++++++++++++------- box.py | 30 +++++++++++++++++++++++++++--- 2 files changed, 62 insertions(+), 10 deletions(-) diff --git a/README.rst b/README.rst index 58ce832..edf9fbb 100644 --- a/README.rst +++ b/README.rst @@ -40,7 +40,7 @@ your operating system, or by using virtualenv for Python requirements, i.e.: $ . .venv/bin/activate (.venv) $ pip install requirements.txt -than you can issue: +then you can issue: .. code:: shell-session @@ -53,8 +53,33 @@ or simply link it somewhere in the path: $ ln -s /path/to/box.py ~/bin/boxpy $ chmod +x ~/bin/boxpy -and now you can issue some command. There are four command for simple managing -VMs, maybe some other will be available in the future. Who knows. +and now you can issue some command. For example, to spin up a VM with Ubuntu +18.04 with one CPU, 2GB of memory and 10GB of disk: + +.. code:: shell-session + + $ boxpy create --version 18.04 myvm + +note, that Ubuntu is default distribution you don't need to specify +``--distro`` nor ``--version`` it will pick up latest LTS version. Now, let's +recreate it with 20.04: + +.. code:: shell-session + + $ boxpy rebuild --version 20.04 myvm + +or recreate it with Fedora and add additional CPU: + +.. code:: shell-session + + $ boxpy rebuild --distro fedora --version 34 --cpu 2 myvm + +now, let's connect to the VM using either ssh command, which is printed out at +as last ``boxpy`` output line, or simply by using ssh boxpy command: + +.. code:: shell-session + + $ boxpy ssh myvm For your convenience there is a bash completion for each command, so you can use it ad-hoc, or place on your ``.bashrc`` or whatever: @@ -63,14 +88,17 @@ use it ad-hoc, or place on your ``.bashrc`` or whatever: $ source <(boxpy completion bash) -currently there are four commands available: +Currently, following commands are available: - ``list`` - for quickly listing all/running VMs - ``destroy`` - that is probably obvious one -- ``create`` and ``rebuild`` +- ``create`` - create new VM +- ``rebuild`` - recreate specified VM +- ``ssh`` - connect to the VM using ssh +- ``completion`` - as described above -The latter two accepts several options besides required vm name. You can -examine it by using ``--help``. +All of the commands have a range of options, and can be examined it by using +``--help``. What is more interesting though, is the fact, that you can pass your own `cloud-init`_ yaml file, so that VM can be provisioned in easy way. diff --git a/box.py b/box.py index dc5100c..e936bce 100755 --- a/box.py +++ b/box.py @@ -119,7 +119,7 @@ _boxpy() { fi fi - opts="create destroy rebuild list completion" + opts="create destroy rebuild list completion ssh" if [[ ${cur} == "-q" || ${cur} == "-v" || ${COMP_CWORD} -eq 1 ]] ; then COMPREPLY=( $(compgen -W "${opts}" -- ${cur}) ) return 0 @@ -172,6 +172,11 @@ _boxpy() { _get_excluded_items "${items[@]}" COMPREPLY=( $(compgen -W "$result" -- ${cur}) ) ;; + ssh) + if [[ ${prev} == ${cmd} ]]; then + _vms_comp vms + fi + ;; esac } @@ -255,7 +260,7 @@ class Config: setattr(self, attr, vm_info[attr]) # next, grab the cloud config file - if 'config' in args: + if 'config' in args and args.config: self.user_data = os.path.abspath(args.config) else: self.user_data = vm_info.get('user_data') @@ -855,7 +860,7 @@ def vmcreate(args, conf=None): vbox.poweron() print('You can access your VM by issuing:') print(f'ssh -p {conf.port} -i {conf.ssh_key_path[:-4]} ' - f'{DISTROS[args.distro]["username"]}@localhost') + f'{DISTROS[conf.distro]["username"]}@localhost') return 0 @@ -894,6 +899,21 @@ def shell_completion(args): return 0 +def connect(args): + vbox = VBoxManage(args.name) + conf = Config(args, vbox) + try: + subprocess.call(['ssh', '-o', 'StrictHostKeyChecking=no', + '-o', 'UserKnownHostsFile=/dev/null', + '-i', conf.ssh_key_path[:-4], + f'ssh://{DISTROS[conf.distro]["username"]}' + f'@localhost:{conf.port}']) + except subprocess.CalledProcessError: + return None + + return 0 + + def main(): parser = argparse.ArgumentParser(description="Automate deployment and " "maintenance of Ubuntu VMs using " @@ -963,6 +983,10 @@ def main(): help="pick shell to generate completions for") completion.set_defaults(func=shell_completion) + ssh = subparsers.add_parser('ssh', help='Connect to the machine via SSH') + ssh.add_argument('name', help='name or UUID of the VM') + ssh.set_defaults(func=connect) + args = parser.parse_args() if hasattr(args, 'func'):