""" rorolite.runtime ~~~~~~~~~~~~~~~~ This module implements support for multiple rorolite runtimes. """ from fabric.api import sudo, put, cd from pkg_resources import resource_listdir, resource_exists, resource_filename, resource_stream import yaml import pathlib DEFAULT_RUNTIME = "python3" class Runtime(object): """Runtime represents a software setup. Some examples of runtimes are python3, python3-keras, raspberrypi-python3-keras etc. The runtime object contains all the metadata required to install all the required software on a computer. It provides an `install` method, which is supposed to be called from a fabric task. It'll perform some actions on the remote machine to complete the setup. """ def __init__(self, name, version, data): self.root = resource_filename(__name__, "runtimes/" + name) self.name = name self.version = version self.data = data self.init() def __repr__(self): return "<Runtime:{}>".format(self.name) def init(self): self.apt_packages = self.data.get("apt_packages", []) self.pip_packages = self.data.get("pip_packages", []) self.python_binary = self.data.get("python_binary", "python") self.before_scripts = self.data.get("before_scripts", []) self.after_scripts = self.data.get("after_scripts", []) def install(self): """Installs the runtime on a remote machine. This method must be called only from a fabric task. """ target = "/tmp/rorolite-runtime/" + self.name sudo("mkdir -p " + target) put(self.root, "/tmp/rorolite-runtime", use_sudo=True) if self.before_scripts: with cd(target): for s in self.before_scripts: print("executing", s) sudo(s) if self.apt_packages: sudo("apt-get -q update") sudo("apt-get -q -y install " + " ".join(self.apt_packages)) if self.pip_packages: sudo("{} -m pip -q install {}".format( self.python_binary, " ".join(self.pip_packages))) if self.after_scripts: with cd(target): for s in self.after_scripts: print("executing", s) sudo(s) self.setup_system_path() def setup_system_path(self): path = pathlib.Path(__file__).parent / "files" / "etc" / "profile.d" / "rorolite.sh" put(str(path), "/etc/profile.d/Z99-rorolite.sh", use_sudo=True) @classmethod def all(cls): def is_runtime(name): return resource_exists("runtimes/{}/runtime.yml".format(name)) names = resource_listdir(__name__, "runtimes") names = [is_runtime(name) for name in names] return [cls.load(name) for name in names] @classmethod def load(cls, name): """Loads the runtime of the specified name. """ f = resource_stream(__name__, "runtimes/{}/runtime.yml".format(name)) data = yaml.safe_load(f) return Runtime(data['name'], data['version'], data)