=== modified file 'doc/QUICKSTART'
@@ -80,8 +80,9 @@
Configuring the dispatcher
++++++++++++++++++++++++++
-The dispatcher looks for config values in ~/.config/lava-dispatcher/,
-then /etc/xdg/lava-dispatcher, then its own source tree.
+The dispatcher looks for config values in ~/.config/lava-dispatcher/, then
+/etc/lava-dispatcher (inside the current virtual environment if any, or
+/etc/lava-dispatcher itself otherwise), then its own source tree.
To get started, you ned to make a directory for storing artefacts
before they are downloaded to the device being tested
=== modified file 'lava/dispatcher/commands.py'
@@ -1,3 +1,4 @@
+import argparse
import json
import logging
import os
@@ -7,26 +8,24 @@
from lava.tool.command import Command
from lava.tool.errors import CommandError
+import lava_dispatcher.config
from lava_dispatcher.config import get_config, get_device_config, get_devices
from lava_dispatcher.job import LavaTestJob, validate_job_data
+class SetUserConfigDirAction(argparse.Action):
+ def __call__(self, parser, namespace, value, option_string=None):
+ lava_dispatcher.config.custom_config_path = value
+
+
class DispatcherCommand(Command):
@classmethod
def register_arguments(cls, parser):
super(DispatcherCommand, cls).register_arguments(parser)
- # When we're working inside a virtual environment use venv-relative
- # configuration directory. This works well with lava-deployment-tool
- # and the directory layout it currently provides but will need to be
- # changed for codeline support.
- if "VIRTUAL_ENV" in os.environ:
- default_config_dir = os.path.join(
- os.environ["VIRTUAL_ENV"], "etc", "lava-dispatcher")
- else:
- default_config_dir = None
parser.add_argument(
"--config-dir",
- default=default_config_dir,
+ default=None,
+ action=SetUserConfigDirAction,
help="Configuration directory override (currently %(default)s")
@@ -35,7 +34,7 @@
Lists all the configured devices in this LAVA instance.
"""
def invoke(self):
- for d in get_devices(self.args.config_dir):
+ for d in get_devices():
print d.hostname
@@ -88,7 +87,7 @@
FORMAT = '<LAVA_DISPATCHER>%(asctime)s %(levelname)s: %(message)s'
DATEFMT = '%Y-%m-%d %I:%M:%S %p'
logging.basicConfig(format=FORMAT, datefmt=DATEFMT)
- config = get_config(self.args.config_dir)
+ config = get_config()
logging.root.setLevel(config.logging_level)
# Set process id if job-id was passed to dispatcher
@@ -139,7 +138,7 @@
@property
def device_config(self):
try:
- return get_device_config(self.args.device, self.args.config_dir)
+ return get_device_config(self.args.device)
except Exception:
raise CommandError("no such device: %s" % self.args.device)
=== modified file 'lava_dispatcher/config.py'
@@ -152,31 +152,58 @@
class DispatcherConfig(object):
- def __init__(self, cp, config_dir):
+ def __init__(self, cp):
self.cp = cp
- self.config_dir = config_dir
for option in DispatcherSchema().options():
locals()[option.name] = OptionDescriptor(option.name)
-default_config_path = os.path.join(
- os.path.dirname(__file__), 'default-config')
-
-
-def load_config_paths(name, config_dir):
- if config_dir is None:
- paths = [
- os.path.join(path, name) for path in [
- os.path.expanduser("~/.config"),
- "/etc/xdg",
- default_config_path]]
- else:
- paths = [config_dir, os.path.join(default_config_path, name)]
- for path in paths:
- if os.path.isdir(path):
- yield path
-
+user_config_path = os.path.expanduser("~/.config/lava-dispatcher")
+
+if "VIRTUAL_ENV" in os.environ:
+ system_config_path = os.path.join(os.environ["VIRTUAL_ENV"],
+ "etc/lava-dispatcher")
+else:
+ system_config_path = "/etc/lava-dispatcher"
+
+deprecated_system_config_path = "/etc/xdg/lava-dispatcher"
+
+default_config_path = os.path.join(os.path.dirname(__file__),
+ 'default-config/lava-dispatcher')
+
+custom_config_path = None
+
+def search_path():
+ if custom_config_path:
+ return [
+ custom_config_path,
+ default_config_path,
+ ]
+ else:
+ return [
+ user_config_path,
+ system_config_path,
+ default_config_path,
+ ]
+
+def write_path():
+ """
+ Returns the configuration directories where configuration files should be
+ written to.
+
+ Returns an array with a list of directories. Client tools should then write
+ any configuration files to the first directory in that list that is
+ writable by the user.
+ """
+ if custom_config_path:
+ return [custom_config_path]
+ else:
+ # Since usually you need to run the dispatcher as root, but lava-tool
+ # as a regular user, we give preference to writing to the system
+ # configuration to avoid the user writing config file to ~user, and the
+ # dispatcher looking for them at ~root.
+ return [system_config_path, user_config_path]
def _read_into(path, cp):
s = StringIO.StringIO()
@@ -186,7 +213,7 @@
cp.readfp(s)
-def _get_config(name, config_dir, cp):
+def _get_config(name, cp):
"""Read a config file named name + '.conf'.
This checks and loads files from the source tree, site wide location and
@@ -194,7 +221,7 @@
settings which override source settings.
"""
config_files = []
- for directory in load_config_paths('lava-dispatcher', config_dir):
+ for directory in search_path():
path = os.path.join(directory, '%s.conf' % name)
if os.path.exists(path):
config_files.append(path)
@@ -207,13 +234,13 @@
return cp
-def get_config(config_dir):
+def get_config():
cp = parser.SchemaConfigParser(DispatcherSchema())
- _get_config("lava-dispatcher", config_dir, cp)
+ _get_config("lava-dispatcher", cp)
valid, report = cp.is_valid(report=True)
if not valid:
logging.warning("dispatcher config is not valid:\n %s", '\n '.join(report))
- return DispatcherConfig(cp, config_dir)
+ return DispatcherConfig(cp)
def _hack_boot_options(scp):
@@ -243,19 +270,19 @@
return scrubbed
-def get_device_config(name, config_dir):
+def get_device_config(name):
# We read the device config once to get the device type, then we start
# again and read device-defaults, device-types/$device-type and
# devices/$device in that order.
initial_config = ConfigParser()
- _get_config("devices/%s" % name, config_dir, initial_config)
+ _get_config("devices/%s" % name, initial_config)
real_device_config = parser.SchemaConfigParser(DeviceSchema())
- _get_config("device-defaults", config_dir, real_device_config)
+ _get_config("device-defaults", real_device_config)
_get_config(
"device-types/%s" % initial_config.get('__main__', 'device_type'),
- config_dir, real_device_config)
- _get_config("devices/%s" % name, config_dir, real_device_config)
+ real_device_config)
+ _get_config("devices/%s" % name, real_device_config)
real_device_config.set("__main__", "hostname", name)
_hack_boot_options(real_device_config)
valid, report = real_device_config.is_valid(report=True)
@@ -269,10 +296,19 @@
return DeviceConfig(real_device_config)
-def get_devices(config_dir):
+def get_devices():
devices = []
- devices_dir = os.path.join(config_dir, 'devices')
- for d in os.listdir(devices_dir):
- d = os.path.splitext(d)[0]
- devices.append(get_device_config(d, config_dir))
+ for config_dir in search_path():
+ devices_dir = os.path.join(config_dir, 'devices')
+ if os.path.isdir(devices_dir):
+ for d in os.listdir(devices_dir):
+ d = os.path.splitext(d)[0]
+ devices.append(get_device_config(d))
return devices
+
+def get_config_file(config_file):
+ for config_dir in search_path():
+ config_file_path = os.path.join(config_dir, config_file)
+ if os.path.exists(config_file_path):
+ return config_file_path
+ return None
=== modified file 'lava_dispatcher/context.py'
@@ -94,8 +94,7 @@
self.job_data = job_data
self.output = Outputter(output_dir)
self.logfile_read = self.output.logfile_read
- self.device_config = get_device_config(
- target, dispatcher_config.config_dir)
+ self.device_config = get_device_config(target)
self._client = TargetBasedClient(self, self.device_config)
self.test_data = LavaTestData()
self.oob_file = oob_file
=== modified file 'lava_dispatcher/downloader.py'
@@ -33,6 +33,7 @@
import zlib
from tempfile import mkdtemp
+from lava_dispatcher.config import get_config_file
from lava_dispatcher.utils import rmtree
@@ -122,8 +123,8 @@
'''allows the downloader to override a URL so that something like:
http://blah/ becomes file://localhost/blah
'''
- mappings = '%s/urlmappings.txt' % context.config.config_dir
- if os.path.exists(mappings):
+ mappings = get_config_file('urlmappings.txt')
+ if mappings:
newurl = url
with open(mappings, 'r') as f:
for line in f.readlines():