start_vm.py (3253B)
1 #!/usr/bin/env python 2 3 import jinja2 4 from pathlib import Path 5 import sys 6 import tempfile 7 import time 8 from typing import List 9 10 from aetherscale.client import ServerCommunication 11 import aetherscale.config 12 from aetherscale.timing import timeout 13 14 15 def create_vm(init_script: Path, comm: ServerCommunication) -> str: 16 with open(init_script) as f: 17 script = f.read() 18 19 responses = comm.send_msg({ 20 'command': 'create-vm', 21 'options': { 22 'image': 'ubuntu-20.04.1-server-amd64', 23 'init-script': script, 24 # At the moment this is required for the installation of the 25 # packages, because there is no gateway defined inside VPNs 26 'public-ip': True, 27 'vpn': 'jitsi', 28 } 29 }, response_expected=True) 30 31 if len(responses) != 1: 32 raise RuntimeError( 33 'Did not receive exactly one response, something went wrong') 34 35 if responses[0]['execution-info']['status'] != 'success': 36 raise RuntimeError('Execution was not successful') 37 38 return responses[0]['response']['vm-id'] 39 40 41 def get_vm_ips(vm_id: str, comm: ServerCommunication) -> List[str]: 42 responses = comm.send_msg({ 43 'command': 'list-vms', 44 }, response_expected=True) 45 46 for r in responses: 47 try: 48 for vm in r['response']: 49 if vm['vm-id'] == vm_id: 50 return vm['ip-addresses'] 51 except KeyError: 52 pass 53 54 return [] 55 56 57 def main(): 58 env = jinja2.Environment(loader=jinja2.FileSystemLoader('./')) 59 template = env.get_template('jitsi-install.sh.jinja2') 60 61 with tempfile.NamedTemporaryFile('wt') as f: 62 template.stream(hostname='jitsi.example.com').dump(f.name) 63 64 with ServerCommunication() as comm: 65 try: 66 vm_id = create_vm(Path(f.name), comm) 67 except RuntimeError as e: 68 print(str(e), file=sys.stderr) 69 sys.exit(1) 70 71 try: 72 # TODO: Currently, the VM image has a flaw in setup of IP addresses 73 # it will wait for a DHCP to be available on all interfaces, but 74 # VPN interface does not have this. To make this work with all 75 # variants of vpn/public-ip we have to define fixed interface names 76 # with https://www.freedesktop.org/software/systemd/man/systemd.link.html 77 # and then can set the right IP lookup for each interface in 78 # /etc/systemd/network/ 79 # or we can omit the fixed interface names and directly match on the 80 # MAC address in .network files 81 # (both variants have to be copied to the image before booting it) 82 with timeout(300): 83 ip_address = None 84 85 while not ip_address: 86 with ServerCommunication() as comm: 87 ips = get_vm_ips(vm_id, comm) 88 vpn_prefix = aetherscale.config.VPN_48_PREFIX 89 vpn_ips = [ip for ip in ips if ip.startswith(vpn_prefix)] 90 91 if len(vpn_ips) > 0: 92 ip_address = vpn_ips[0] 93 94 time.sleep(5) 95 96 print(ip_address) 97 except TimeoutError: 98 print('Could not retrieve IP address', file=sys.stderr) 99 100 101 if __name__ == '__main__': 102 main()