diff --git a/.gitignore b/.gitignore index 0d20b64..cae31ec 100644 --- a/.gitignore +++ b/.gitignore @@ -1 +1,2 @@ *.pyc +config.yaml diff --git a/application.py b/application.py new file mode 100644 index 0000000..4d84bdc --- /dev/null +++ b/application.py @@ -0,0 +1,62 @@ +import core # Nexus core +import argparse, sys +import logging + +def run(args): + parser = argparse.ArgumentParser(description="Nexus daemon") + parser.add_argument("-c", "--config", dest="config_file", metavar="PATH", help="specifies the configuration file to use", default="config.yaml") + parser.add_argument("-d", "--debug", dest="debug_mode", action="store_true", help="enables debugging mode", default=False) + arguments = parser.parse_args(args) + + if arguments.debug_mode == True: + logging.basicConfig(level=logging.DEBUG, format="%(asctime)s - %(levelname)s - %(message)s") + else: + logging.basicConfig(level=logging.INFO, format="%(asctime)s - %(levelname)s - %(message)s") + + logging.info("Application started") + + try: + config = core.config.ConfigurationReader(arguments.config_file) + except IOError, e: + sys.stderr.write("Failed to read configuration file (%s).\nCreate a configuration file that Nexus can access, or specify a different location using the -c switch.\n" % e.strerror) + exit(1) + + logging.info("Read configuration file at %s" % arguments.config_file) + + # Connect to node database + database = core.db.Database(config.database) + database.setup() + node_table = database.get_memory_table("nodes") + + logging.info("Connected to database at %s" % config.database) + + # Read bootstrap/override node data + for uuid, node in config.nodes.iteritems(): + existing_rows = [dbnode for rowid, dbnode in node_table.data.iteritems() if dbnode['uuid'] == uuid] + + if node['override'] == True: + row = existing_rows[0] + row['uuid'] = uuid + row['host'] = node['host'] + row['port'] = node['port'] + row['pubkey'] = node['pubkey'] + row['presupplied'] = 1 + row['attributes'] = 0 + row.commit() + logging.info("Updated data in database for node using configuration file (%s:%s, %s)" % (node['host'], node['port'], uuid)) + else: + if len(existing_rows) == 0: + row = core.db.Row() + row['uuid'] = uuid + row['host'] = node['host'] + row['port'] = node['port'] + row['pubkey'] = node['pubkey'] + row['presupplied'] = 1 + row['attributes'] = 0 + database['nodes'].append(row) + logging.info("Learned about new node from configuration file, inserted into database (%s:%s, %s)" % (node['host'], node['port'], uuid)) + else: + pass # Already exists and no override flag set, ignore + +if __name__ == "__main__": + run(sys.argv[1:]) diff --git a/core/__init__.py b/core/__init__.py index 8b13789..5447cb1 100644 --- a/core/__init__.py +++ b/core/__init__.py @@ -1 +1 @@ - +import config, db, util diff --git a/core/config.py b/core/config.py index 776ab35..c94dd25 100644 --- a/core/config.py +++ b/core/config.py @@ -1,6 +1,4 @@ -import yaml, glob, os -import logging -logging.basicConfig(level=logging.DEBUG, format="%(asctime)s - %(levelname)s - %(message)s") +import yaml, glob, os, logging from util import dict_combine_recursive @@ -52,6 +50,13 @@ class ConfigurationReader(object): logging.debug("Own privkey is %s" % self.privkey) except KeyError, e: raise ConfigurationError("You must specify a private key for this node.") + + try: + self.database = configdata['self']['database'] + except KeyError, e: + self.database = "node.db" + + logging.debug("Database location is %s" % self.database) def config_nodes(self, configdata): try: @@ -60,16 +65,18 @@ class ConfigurationReader(object): self.nodes = {} # Optional for uuid, node in self.nodes.iteritems(): - if "ip" not in node: - raise ConfigurationError("IP is missing for node %s." % uuid) + if "host" not in node: + raise ConfigurationError("Hostname is missing for node %s." % uuid) if "port" not in node: raise ConfigurationError("Port is missing for node %s." % uuid) if "pubkey" not in node: raise ConfigurationError("Public key is missing for node %s." % uuid) if "permissions" not in node: node['permissions'] = [] # Optional + if "override" not in node: + node['override'] = False - logging.debug("Node %s : IP %s, port %s, pubkey %s, permissions %s" % (uuid, node["ip"], node["port"], node["pubkey"], "|".join(node["permissions"]))) + logging.debug("Node %s : Hostname %s, port %s, pubkey %s, permissions %s" % (uuid, node["host"], node["port"], node["pubkey"], "|".join(node["permissions"]))) def config_package_settings(self, configdata): try: diff --git a/core/db.py b/core/db.py index 53272e5..1947eac 100644 --- a/core/db.py +++ b/core/db.py @@ -194,7 +194,7 @@ class MemoryTable(Table): self._retrieve_data() def _retrieve_data(self): - result = database.query("SELECT * FROM %s" % self.table) # Not SQLi-safe! + result = self.db.query("SELECT * FROM %s" % self.table) # Not SQLi-safe! self._set_column_names([x[0] for x in result.description]) for row in result: diff --git a/nexus-cli.py b/nexus-cli.py new file mode 100755 index 0000000..4e59ac2 --- /dev/null +++ b/nexus-cli.py @@ -0,0 +1,26 @@ +#!/usr/bin/env python2 + +import sys + +def usage(): + print "Specify a valid action.\nPossible actions: start, stop, add-node, reload-config, reload-packages" + +if len(sys.argv) < 2: + usage() + exit(1) + +if sys.argv[1] == "start": + import application + application.run(sys.argv[2:]) +elif sys.argv[1] == "stop": + pass +else: + usage() + exit(1) + + +""" +parser = argparse.ArgumentParser(description="Nexus control application") + +config = core.config.ConfigReader("") +"""