aetherscale

[unmaintained] code for a cloud provider tutorial
Log | Files | Refs | README | LICENSE

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()