#!/usr/bin/env python
# -*- coding: utf-8 -*-
#
# Copyright (C) 2014 Glencoe Software, Inc. All Rights Reserved.
# Use is subject to license terms supplied in LICENSE.txt
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License along
# with this program; if not, write to the Free Software Foundation, Inc.,
# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
"""
Parser for the omero.properties file to generate RST
mark up.
"""
DB_HEADER = Header("Database", reference="db")
FS_HEADER = Header("Binary repository", reference="fs")
GRID_HEADER = Header("Grid", reference="grid")
ICE_HEADER = Header("Ice", reference="ice")
LDAP_HEADER = Header("LDAP", reference="ldap")
JVM_HEADER = Header("JVM", reference="jvm")
LOGGING_HEADER = Header("Logging", reference="log")
MISC_HEADER = Header("Misc", reference="misc")
PERFORMANCE_HEADER = Header("Performance", reference="performance")
SCRIPTS_HEADER = Header("Scripts", reference="scripts")
SECURITY_HEADER = Header("Security", reference="security")
TABLES_HEADER = Header("Tables", reference="tables")
HEADER_MAPPING = {
"omero.data": FS_HEADER,
"omero.db": DB_HEADER,
"omero.cluster": GRID_HEADER,
"omero.grid": GRID_HEADER,
"omero.checksum": FS_HEADER,
"omero.fs": FS_HEADER,
"omero.managed": FS_HEADER,
"omero.ldap": LDAP_HEADER,
"omero.jvmcfg": JVM_HEADER,
"omero.logging": LOGGING_HEADER,
"omero.sessions": PERFORMANCE_HEADER,
"omero.threads": PERFORMANCE_HEADER,
"omero.throttling": PERFORMANCE_HEADER,
"omero.launcher": SCRIPTS_HEADER,
"omero.process": SCRIPTS_HEADER,
"omero.scripts": SCRIPTS_HEADER,
"omero.security": SECURITY_HEADER,
"omero.tables": TABLES_HEADER,
"omero.resetpassword": SECURITY_HEADER,
"omero.upgrades": MISC_HEADER,
"Ice": ICE_HEADER,
}
TOP = \
""".. This file is auto-generated from omero.properties. DO NOT EDIT IT
Configuration properties glossary
=================================
.. contents::
:depth: 1
:local:
.. _introduction_configuration:
Introduction
------------
The primary form of configuration is via the use of key/value properties,
stored in :file:`etc/grid/config.xml` and read on server startup. Backing up
and copying these properties is as easy as copying this file to a new server
version.
The :source:`etc/omero.properties` file of your distribution defines all the
default configuration properties used by the server. Changes made to the file
are *not* recognized by the server. Instead, configuration options can be set
using the :program:`omero config set` command:
::
$ omero config set <parameter> <value>
When supplying a value with spaces or multiple elements, use **single
quotes**. The quotes will not be saved as part of the value (see below).
To remove a configuration option (to return to default values where
mentioned), simply omit the value:
::
$ omero config set <parameter>
These options will be stored in a file: ``etc/grid/config.xml`` which
you can read for reference. **DO NOT** edit this file directly.
You can also review all your settings by using:
::
$ omero config get
which should return values without quotation marks.
A final useful option of :program:`omero config edit` is:
::
$ omero config edit
which will allow for editing the configuration in a system-default text
editor.
.. note::
Please use the **escape sequence** ``\\"`` for nesting double quotes (e.g.
``"[\\"foo\\", \\"bar\\"]"``) or wrap with ``'`` (e.g. ``'["foo",
"bar"]'``).
Examples of doing this are on the
:doc:`server installation page <unix/server-installation>`, as well as the
:doc:`LDAP installation <server-ldap>` page.
.. _core_configuration:
Mandatory properties
--------------------
The following properties need to be correctly set for all installations of the
OMERO.server. Depending on your set-up, default values may be sufficient.
- :property:`omero.data.dir`
- :property:`omero.db.host`
- :property:`omero.db.name`
- :property:`omero.db.pass`
"""
HEADER = \
""".. _%(reference)s_configuration:
%(header)s
%(hline)s
%(properties)s"""
EXCLUDE_LIST = ("##", "versions", "omero.upgrades", "omero.version")
STOP = "### END"
import os
import argparse
import fileinput
import logging
import warnings
from collections import defaultdict
[docs]
def fail(msg="", debug=0):
if debug:
import pdb
pdb.set_trace()
else:
raise Exception(msg)
[docs]
def dbg(msg):
logging.debug(msg)
[docs]
def underline(size):
"""Create underline for reStructuredText headings"""
return '^' * size
[docs]
class Property(object):
def __init__(self, key=None, val=None, txt=""):
"""Initialize new configuration property"""
self.key = key
self.val = val
self.txt = txt
[docs]
def append(self, line):
"""Append line to property description"""
dbg("append:" + line)
self.txt += line
self.txt += "\n"
[docs]
def detect(self, line):
dbg("detect:" + line)
idx = line.index("=")
self.key = line[0:idx]
self.val = line[idx + 1:]
[docs]
def cont(self, line):
dbg("cont: " + line)
if self.key is None:
fail("key is none on line: " + line)
self.val += line
def __str__(self):
return ("Property(key='%s', val='%s', txt='%s')"
% (self.key, self.val, self.txt))
IN_PROGRESS = "in_progress_action"
ESCAPED = "escaped_action"
[docs]
class PropertyParser(object):
def __init__(self):
"""Initialize a property set"""
self.properties = []
self.curr_p = None
self.curr_a = None
[docs]
def parse_file(self, argv=None):
"""Parse the properties from the input configuration file"""
try:
self.parse_lines(fileinput.input(argv))
finally:
fileinput.close()
return self.properties
[docs]
def parse_lines(self, lines):
"""Parse the properties from the given configuration file lines"""
for line in lines:
if isinstance(line, bytes):
line = line.decode("utf-8")
if line.endswith("\n"):
line = line[:-1]
if line.startswith(STOP):
self.cleanup()
break
if self.is_excluded(line):
self.cleanup()
continue
elif not line.strip():
self.cleanup()
continue
elif line.startswith("#"):
self.append(line)
elif "=" in line and self.curr_a != ESCAPED:
self.detect(line)
elif line.endswith("\\"):
self.cont(line[:-1])
else:
self.cont(line)
self.cleanup() # Handle no newline at end of file
return self.properties
[docs]
def black_list(self, line):
warnings.warn(
"This method is deprecated. Use is_excluded instead",
DeprecationWarning)
return self.is_excluded(line)
[docs]
def is_excluded(self, line):
for x in EXCLUDE_LIST:
if line.startswith(x):
return True
[docs]
def cleanup(self):
if self.curr_p is not None:
if self.curr_p.key is not None: # Handle ending '####'
self.properties.append(self.curr_p)
self.curr_p = None
self.curr_a = None
[docs]
def init(self):
if self.curr_p is None:
self.curr_p = Property()
[docs]
def ignore(self):
self.cleanup()
[docs]
def append(self, line):
self.init()
# Assume line starts with "# " and strip
self.curr_p.append(line[2:])
[docs]
def detect(self, line):
if line.endswith("\\"):
line = line[:-1]
self.curr_a = ESCAPED
else:
self.cleanup()
self.curr_a = IN_PROGRESS
self.init()
self.curr_p.detect(line)
if self.curr_a != ESCAPED:
self.cleanup()
[docs]
def cont(self, line):
self.curr_p.cont(line)
def __iter__(self):
return iter(self.properties)
[docs]
def data(self):
data = defaultdict(list)
for x in self:
if x.key is None:
raise Exception("Bad key: %s" % x)
parts = x.key.split(".")
if parts[0] == "Ice":
continue
if parts[0] != "omero":
raise Exception("Bad key: %s" % x)
parts = parts[1:]
data[parts[0]].append(".".join(parts[1:]))
return data
[docs]
def parse_module(self, module='omeroweb.settings'):
"""Parse the properties from the setting module"""
os.environ['DJANGO_SETTINGS_MODULE'] = module
from django.conf import settings
for key, values in sorted(
iter(list(settings.CUSTOM_SETTINGS_MAPPINGS.items())),
key=lambda k: k):
p = Property()
global_name, default_value, mapping, description, config = \
tuple(values)
p.val = str(default_value)
p.key = key
p.txt = (description or "") + "\n"
self.properties.append(p)
[docs]
def print_defaults(self):
"""Print all keys and their default values"""
values = ["%s=%s" % (p.key, p.val) for p in self]
for x in sorted(values):
print(x)
[docs]
def print_keys(self):
"""Print all keys"""
data = self.data()
for k, v in sorted(data.items()):
print("%s (%s)" % (k, len(v)))
for i in v:
print("\t", i)
[docs]
def print_rst(self):
"""Print configuration in reStructuredText format"""
print(TOP)
headers = self.headers()
for header in sorted(headers, key=lambda x: x.name):
properties = ""
# Filter properties marked as DEVELOPMENT
props = [p for p in headers[header] if
not p.txt.startswith('DEVELOPMENT')]
for p in props:
properties += ".. property:: %s\n" % (p.key)
properties += "\n"
properties += "%s\n" % p.key
properties += "%s\n" % underline(len(p.key))
for line in p.txt.split("\n"):
if line:
if isinstance(line, bytes):
line = line.decode("utf-8")
properties += "%s\n" % (line)
else:
properties += "\n"
v = p.val
if not p.val:
v = "[empty]"
v = v.replace('"', '\\\\"')
if ',' in v and ', ' not in v:
properties += "Default: `%s`\n\n" % (
",\n".join(v.split(',')))
else:
properties += "Default: `%s`\n\n" % v
hline = "-" * len(header.name)
m = {"header": header.name,
"hline": hline,
"properties": properties,
"reference": header.get_reference()}
print(HEADER % m)
if __name__ == "__main__":
ap = argparse.ArgumentParser()
g = ap.add_mutually_exclusive_group()
g.add_argument("--rst", action="store_true")
g.add_argument("--dbg", action="store_true")
g.add_argument("--keys", action="store_true")
g.add_argument("--headers", action="store_true")
ap.add_argument("files", nargs="+")
ns = ap.parse_args()
if ns.dbg:
logging.basicConfig(level=10)
else:
logging.basicConfig(level=20)
pp = PropertyParser()
pp.parse_file(ns.files)
pp.parse_module('omeroweb.settings')
if ns.dbg:
print("Found:", len(list(pp)))
elif ns.keys:
pp.print_keys()
elif ns.headers:
pp.print_headers()
elif ns.rst:
pp.print_rst()
else:
raise Exception(ns)