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.
138 lines
4.9 KiB
138 lines
4.9 KiB
#!/usr/bin/env python3
|
|
|
|
# depends on:
|
|
# python 3.4 (included in Raspbian Jessie)
|
|
# APScheduler
|
|
|
|
|
|
import argparse
|
|
import os
|
|
from datetime import datetime
|
|
import toml
|
|
|
|
import shepherd.scheduler
|
|
import shepherd.config
|
|
import shepherd.plugin
|
|
import shepherd.control
|
|
|
|
|
|
# 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 define_core_config(confdef):
|
|
confdef.add_def("id", shepherd.config.StringDef())
|
|
confdef.add_def("plugins", shepherd.config.StringArrayDef())
|
|
confdef.add_def("plugin_dir", shepherd.config.StringDef())
|
|
confdef.add_def("root_dir", shepherd.config.StringDef())
|
|
confdef.add_def("conf_edit_path", shepherd.config.StringDef())
|
|
|
|
def load_config(config_path,load_editconf):
|
|
# Load config from default location
|
|
confman = shepherd.config.ConfigManager()
|
|
confman.load(os.path.expanduser(config_path))
|
|
# Create core confdef and populate it
|
|
core_confdef = shepherd.config.ConfDefinition()
|
|
define_core_config(core_confdef)
|
|
# attempt to retrive core config and validate it
|
|
core_conf = confman.get_config("shepherd", core_confdef)
|
|
edit_confman = None
|
|
conf_edit_message = None
|
|
|
|
if load_editconf:
|
|
# Check for an edit_conf file, and try to load it and plugin configs
|
|
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)
|
|
|
|
plugin_classes = shepherd.plugin.find_plugins(
|
|
core_edit_conf["plugins"])
|
|
plugin_configs = edit_confman.get_plugin_configs(plugin_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 for plugins
|
|
if confman is not edit_confman:
|
|
plugin_classes = shepherd.plugin.find_plugins(core_conf["plugins"])
|
|
plugin_configs = confman.get_plugin_configs(plugin_classes)
|
|
|
|
# If no editconf file was found, write out the current config as a template
|
|
if (conf_edit_message is None) and load_editconf:
|
|
confman.dump_to_file(os.path.expanduser(core_conf["conf_edit_path"]),
|
|
"Config generated at:" + str(datetime.now()))
|
|
|
|
return (core_conf, plugin_classes, plugin_configs)
|
|
|
|
|
|
|
|
|
|
|
|
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")
|
|
argparser.add_argument('-e', '--noedit',help="Disable the editable config temporarily", action="store_true", default=False)
|
|
argparser.add_argument("-t", "--test", help="Test and interface function of the from 'plugin:function'",
|
|
default=None)
|
|
|
|
args = argparser.parse_args()
|
|
|
|
confman = shepherd.config.ConfigManager()
|
|
confman.load(os.path.expanduser(args.configfile))
|
|
|
|
(core_conf, plugin_classes, plugin_configs) = load_config(args.configfile, not args.noedit)
|
|
|
|
if args.test is None:
|
|
shepherd.control.init_control(core_conf)
|
|
|
|
shepherd.scheduler.init_scheduler(core_conf)
|
|
|
|
shepherd.plugin.init_plugins(plugin_classes, plugin_configs, core_conf)
|
|
|
|
shepherd.scheduler.restore_jobs()
|
|
|
|
print(str(datetime.now()))
|
|
|
|
if args.test is not None:
|
|
(test_plugin, test_func) = args.test.split(':')
|
|
func = getattr(shepherd.plugin.plugin_functions[test_plugin], test_func)
|
|
print(func())
|
|
return
|
|
|
|
print('Press Ctrl+{0} to exit'.format('Break' if os.name == 'nt' else 'C'))
|
|
|
|
try:
|
|
shepherd.scheduler.start()
|
|
except (KeyboardInterrupt, SystemExit):
|
|
pass
|
|
|
|
|
|
if __name__ == "__main__":
|
|
main()
|