You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
139 lines
4.6 KiB
139 lines
4.6 KiB
#!/usr/bin/env python3
|
|
|
|
# depends on:
|
|
# python 3.4 (included in Raspbian Jessie)
|
|
# APScheduler
|
|
|
|
|
|
import sys
|
|
import argparse
|
|
import os
|
|
import toml
|
|
|
|
|
|
import shepherd.config
|
|
import shepherd.module
|
|
|
|
from apscheduler.schedulers.blocking import BlockingScheduler
|
|
from datetime import datetime
|
|
|
|
from types import SimpleNamespace
|
|
|
|
|
|
# Future implementations of checking config differences should be done on
|
|
# the hash of the nested conf dict, so comments shouldn't affect this.
|
|
|
|
# save old config to somewhere in the shepherd root dir - probably need to
|
|
# implement a TOML writer in the config module.
|
|
|
|
# later on, there's going to be an issue with a new config being applied
|
|
# remotely, then the system restarting, and an old edit in /boot being
|
|
# applied over the top...
|
|
# Fix this by saving the working config to /boot when new config applied
|
|
# remotely.
|
|
|
|
def load_config(config_path):
|
|
confman = shepherd.config.ConfigManager()
|
|
confman.load(os.path.expanduser(config_path))
|
|
core_conf = confman.get_config("shepherd", core_confdef())
|
|
|
|
# Check for an edit_conf file, and try to load it
|
|
try:
|
|
edit_confman = shepherd.config.ConfigManager()
|
|
edit_confman.load(os.path.expanduser(core_conf["conf_edit_path"]))
|
|
core_edit_conf = edit_confman.get_config("shepherd", core_confdef())
|
|
|
|
mod_classes = shepherd.module.find_modules(core_edit_conf["modules"])
|
|
mod_configs = edit_confman.get_module_configs(mod_classes)
|
|
|
|
except FileNotFoundError:
|
|
conf_edit_message = None
|
|
except shepherd.config.InvalidConfigError as e:
|
|
conf_edit_message = "Invalid config.\n " + str(e.args)
|
|
except toml.TomlDecodeError as e:
|
|
conf_edit_message = "TOML syntax error.\n" + str(e)
|
|
except Exception:
|
|
conf_edit_message = "Error processing new config"
|
|
else:
|
|
conf_edit_message = ("Successfully applied this config at:" +
|
|
str(datetime.now()))
|
|
confman = edit_confman
|
|
core_conf = core_edit_conf
|
|
|
|
if conf_edit_message is not None:
|
|
shepherd.config.update_toml_message(
|
|
os.path.expanduser(core_conf["conf_edit_path"]), conf_edit_message)
|
|
|
|
# if editconf failed, load current config
|
|
if confman is not edit_confman:
|
|
mod_classes = shepherd.module.find_modules(core_conf["modules"])
|
|
mod_configs = confman.get_module_configs(mod_classes)
|
|
|
|
# If no editconf file was found, write out the current config as a template
|
|
if conf_edit_message is None:
|
|
confman.dump_to_file(os.path.expanduser(core_conf["conf_edit_path"]),
|
|
"Config generated at:" + str(datetime.now()))
|
|
|
|
return (core_conf, mod_classes, mod_configs)
|
|
|
|
|
|
def core_confdef():
|
|
confdef = shepherd.config.ConfDefinition()
|
|
confdef.add_def("id", shepherd.config.StringDef())
|
|
confdef.add_def("modules", shepherd.config.StringArrayDef())
|
|
confdef.add_def("root_dir", shepherd.config.StringDef())
|
|
confdef.add_def("conf_edit_path", shepherd.config.StringDef())
|
|
return confdef
|
|
|
|
|
|
class ShepherdInterface(shepherd.module.Interface):
|
|
def __init__(self, scheduler, config):
|
|
super().__init__(None)
|
|
self.id = config["id"]
|
|
self.root_dir = config["root_dir"]
|
|
self.scheduler = scheduler
|
|
|
|
|
|
def main():
|
|
argparser = argparse.ArgumentParser(description="Keep track of a mob "
|
|
"of roaming Pis")
|
|
argparser.add_argument("configfile", nargs='?', metavar="configfile",
|
|
help="Path to configfile", default="shepherd.toml")
|
|
|
|
args = argparser.parse_args()
|
|
|
|
confman = shepherd.config.ConfigManager()
|
|
confman.load(os.path.expanduser(args.configfile))
|
|
core_conf = confman.get_config("shepherd", core_confdef())
|
|
breakpoint()
|
|
|
|
(core_conf, mod_classes, mod_configs) = load_config(args.configfile)
|
|
|
|
scheduler = BlockingScheduler()
|
|
core_interface = ShepherdInterface(scheduler, core_conf)
|
|
|
|
# get validated config values for modules, then instantiate them
|
|
modules = {}
|
|
mod_interfaces = {}
|
|
for name, mod_class in mod_classes.items():
|
|
modules[name] = mod_class(mod_configs[name], core_interface)
|
|
mod_interfaces[name] = modules[name].interface
|
|
|
|
# run post init after all modules are loaded to allow them to hook in to
|
|
# each other
|
|
mod_interfaces = SimpleNamespace(**mod_interfaces)
|
|
for module in modules.values():
|
|
module.init_other_interfaces(mod_interfaces)
|
|
|
|
print(str(datetime.now()))
|
|
print('Press Ctrl+{0} to exit'.format('Break' if os.name == 'nt' else 'C'))
|
|
|
|
try:
|
|
scheduler.start()
|
|
except (KeyboardInterrupt, SystemExit):
|
|
pass
|
|
|
|
|
|
if __name__ == "__main__":
|
|
main()
|