This commit is contained in:
xenia 2021-06-15 04:37:57 -04:00
parent dfb2b9d956
commit 7aa8886b07
9 changed files with 197 additions and 4 deletions

10
leylines-ansible/.gitignore vendored Normal file
View File

@ -0,0 +1,10 @@
.venv
*.pyc
*.pyo
*.pyd
__pycache__
*.egg-info
.env
.vimrc
.ycm_extra_conf.py
*.db

View File

@ -0,0 +1,59 @@
#!/usr/bin/env python3
import argparse
import json
import os
import sys
from leylines import db, SERVER_NODE_ID
XDG_CACHE_HOME = os.path.expanduser(os.environ.get("XDG_CACHE_HOME", "~/.cache"))
CACHE_DIR = os.path.join(XDG_CACHE_HOME, "leylines")
if not os.path.isdir(CACHE_DIR):
os.mkdir(CACHE_DIR, 0o700)
def get_ansible_config():
server_node = db.get_server_node()
nodes = [node for node in db.get_nodes() if node.ssh_key is not None]
for node in nodes:
nid = node.id
ssh_key = node.ssh_key
ssh_key_path = os.path.join(CACHE_DIR, f"{nid}.key")
if not os.path.isfile(ssh_key_path):
with open(ssh_key_path, "w") as f:
f.write(ssh_key)
return {
"leylines": {
"hosts": [node.name for node in nodes],
"vars": {
"ansible_ssh_user": "haskal",
"ansible_python_interpreter": "auto"
}
},
"_meta": {
"hostvars": {
node.name: {
"ansible_host": str(node.ip),
"ansible_ssh_private_key_file": os.path.join(CACHE_DIR, f"{node.id}.key"),
"leylines_resources":
" ".join([f"{res}=1" for res in db.get_node_resources(node.id)]),
"leylines_ip": str(node.ip),
"leylines_server_addr": str(server_node.ip),
"leylines_is_server": "yes" if node.id == server_node.id else "no"
} for node in nodes
}
}
}
if __name__ == "__main__":
parser = argparse.ArgumentParser(description="leylines ansible inventory plugin")
parser.add_argument("--list", action="store_true", help="List inventory")
args = parser.parse_args()
if args.list:
json.dump(get_ansible_config(), sys.stdout)
else:
raise Exception("no action specified")

View File

@ -0,0 +1,94 @@
---
- hosts: all
vars:
python_version: 3.9.5
tasks:
- name: install prerequisite packages
become: yes
apt:
name: ["build-essential", "wget", "software-properties-common", "libnss3-dev", "zlib1g-dev",
"libgdbm-dev", "libncurses5-dev", "libssl-dev", "libffi-dev", "libreadline-dev",
"libsqlite3-dev", "libbz2-dev", "libopenblas-dev"]
state: present
update_cache: yes
- name: download build and install python {{ python_version }}
register: pyinstall
changed_when: "'NO_COMPILE_NEEDED' not in pyinstall.stdout"
args:
executable: "/bin/bash"
shell: |
set -eo pipefail
export PATH=$HOME/.local/bin:$PATH
export LD_LIBRARY_PATH=$HOME/.local/lib:$LD_LIBRARY_PATH
existing_ver="$(python3 -c 'import sys;print(f"{sys.version_info.major}.{sys.version_info.minor}.{sys.version_info.micro}")')"
if [ "$existing_ver" == "{{ python_version }}" ]; then
echo "NO_COMPILE_NEEDED"
exit
fi
if [ ! -d $HOME/python ]; then
mkdir $HOME/python
fi
cd $HOME/python
wget -O python.tgz https://www.python.org/ftp/python/{{ python_version }}/Python-{{ python_version }}.tgz
tar xf python.tgz
cd Python-{{ python_version }}
# https://bugs.python.org/issue41346
sed -i 's/-j0 //' Makefile.pre.in
# Speed up LTO
sed -i -e "s|-flto |-flto=4 |g" configure configure.ac
export CFLAGS="-O3 -fno-semantic-interposition"
export LDFLAGS="-fno-semantic-interposition"
./configure --prefix=$HOME/.local/ \
--enable-shared \
--with-computed-gotos \
--enable-optimizations \
--with-lto \
--enable-ipv6 \
--with-dbmliborder=gdbm:ndbm \
--enable-loadable-sqlite-extensions \
--with-tzpath=/usr/share/zoneinfo
make -j$(nproc) EXTRA_CFLAGS="$CFLAGS"
make EXTRA_CFLAGS="$CFLAGS" install
- name: Setup dask directory and venv
register: pysetup
changed_when: false # lol
args:
executable: "/bin/bash"
shell: |
set -eo pipefail
export PATH=$HOME/.local/bin:$PATH
export LD_LIBRARY_PATH=$HOME/.local/lib:$LD_LIBRARY_PATH
if [ ! -d $HOME/dask ]; then
mkdir $HOME/dask
fi
cd $HOME/dask
python3 -m venv dask-venv
. dask-venv/bin/activate
pip3 install --upgrade dask distributed
if [ "{{ leylines_is_server }}" == "no" ]; then
pip3 install --upgrade numpy scipy pandas scikit-image matplotlib
else
pip3 install --upgrade bokeh jupyter-server-proxy
fi
- name: Setup systemd user dir
file:
path: /home/{{ ansible_user }}/.config/systemd/user
mode: 0755
state: directory
- name: Install systemd task
template:
mode: 0644
src: templates/leylines-{% if leylines_is_server == "yes" %}scheduler{% else %}worker{% endif %}.service
dest: /home/{{ ansible_user }}/.config/systemd/user
- name: Enable and start systemd task
systemd:
scope: user
daemon_reload: true
name: leylines-{% if leylines_is_server == "yes" %}scheduler{% else %}worker{% endif %}
enabled: yes
state: restarted

View File

@ -0,0 +1,12 @@
[Unit]
Description=Dask scheduler for leylines
[Service]
Type=simple
Environment=PATH=%h/.local/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
Environment=LD_LIBRARY_PATH=%h/.local/lib:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
ExecStart=/bin/bash -c 'source dask-venv/bin/activate && exec dask-scheduler --host {{leylines_ip}} --port 31337 --protocol tcp --dashboard-address={{leylines_ip}}:31336 --dashboard --no-show --use-xheaders true'
WorkingDirectory=%h/dask
[Install]
WantedBy=default.target

View File

@ -0,0 +1,13 @@
[Unit]
Description=Dask worker for leylines
[Service]
Type=simple
Environment=PATH=%h/.local/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
Environment=LD_LIBRARY_PATH=%h/.local/lib:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
ExecStart=/bin/bash -c 'source dask-venv/bin/activate && exec dask-worker --dashboard-address {{leylines_ip}}:31336 --host {{leylines_ip}} --protocol tcp --nthreads 1 --nprocs auto --name {{inventory_hostname}} --local-directory $CACHE_DIRECTORY --resources "{{leylines_resources}}" {{leylines_server_addr}}:31337'
WorkingDirectory=%h/dask
CacheDirectory=leylines-worker
[Install]
WantedBy=default.target

View File

@ -12,7 +12,7 @@ from .database import Database, Node, SERVER_NODE_ID
IFNAME = 'leyline-wg'
DEFAULT_PORT = 31337
API_PORT = 31338
db = Database("leylines.db")
db = Database()
async def client_connected(reader: asyncio.StreamReader, writer: asyncio.StreamWriter) -> None:
@ -67,6 +67,7 @@ def generate_node_config(id: int) -> Optional[str]:
f"PublicKey={seckey_to_pubkey(server_node.seckey)}\n"
f"AllowedIPs={interface.network}\n"
f"Endpoint={server_node.public_ip}:{DEFAULT_PORT}\n"
f"PersistentKeepalive=25\n"
)
@ -76,7 +77,7 @@ def add_node_to_wg(wg: WireGuard, node: Node) -> None:
peer = {
"public_key": seckey_to_pubkey(node.seckey),
"persistent_keepalive": 60,
"persistent_keepalive": 25,
"allowed_ips": [f"{node.ip}/32"]
}
wg.set(IFNAME, peer=peer)

View File

@ -48,7 +48,8 @@ elif args.cmd == "status":
print("SERVER: <not defined. run leylines init>")
else:
print("SERVER:", server_node.name, server_node.ip, server_node.public_ip,
seckey_to_pubkey(server_node.seckey))
seckey_to_pubkey(server_node.seckey),
"<Have SSH Key>" if server_node.ssh_key is not None else "")
for node in nodes:
if node.id == SERVER_NODE_ID:
continue

View File

@ -2,11 +2,14 @@ import binascii
import ipaddress
import secrets
import sqlite3
import os
from typing import Iterable, List, NamedTuple, Optional, Set
import monocypher
DEFAULT_DB_PATH = "/var/lib/leylines/leylines.db"
XDG_CONFIG_HOME = os.path.expanduser(os.environ.get("XDG_CONFIG_HOME", "~/.config"))
DEFAULT_DB_PATH = os.environ.get("LEYLINES_DB",
os.path.join(XDG_CONFIG_HOME, "leylines", "leylines.db"))
DEFAULT_SUBNET = "172.16.10.1/24"
SERVER_NODE_ID = 1

View File