summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--xlators/features/marker/utils/syncdaemon/configinterface.py121
-rw-r--r--xlators/features/marker/utils/syncdaemon/gsyncd.py47
2 files changed, 130 insertions, 38 deletions
diff --git a/xlators/features/marker/utils/syncdaemon/configinterface.py b/xlators/features/marker/utils/syncdaemon/configinterface.py
index 25a2a526818..f0efc1df861 100644
--- a/xlators/features/marker/utils/syncdaemon/configinterface.py
+++ b/xlators/features/marker/utils/syncdaemon/configinterface.py
@@ -3,29 +3,106 @@ try:
except ImportError:
# py 3
import configparser as ConfigParser
+import re
+try:
+ # py 3
+ from urllib import parse as urllib
+except ImportError:
+ import urllib
+SECT_ORD = '__section_order__'
-DEF_SECT = 'global'
+re_type = type(re.compile(''))
class GConffile(object):
def __init__(self, path, peers):
- if peers:
- self.section = 'peers ' + ' '.join(peers)
- else:
- self.section = DEF_SECT
+ self.peers = peers
self.path = path
self.config = ConfigParser.RawConfigParser()
self.config.read(path)
+ def section(self, rx=False):
+ peers = self.peers
+ if not peers:
+ peers = ['.', '.']
+ rx = True
+ if rx:
+ st = 'peersrx'
+ else:
+ st = 'peers'
+ return ' '.join([st] + [urllib.quote_plus(u) for u in peers])
+
+ @staticmethod
+ def parse_section(section):
+ sl = section.split()
+ st = sl.pop(0)
+ sl = [urllib.unquote_plus(u) for u in sl]
+ if st == 'peersrx':
+ sl = [re.compile(u) for u in sl]
+ return sl
+
+ def ord_sections(self):
+ """Return an ordered list of sections.
+
+ Ordering happens based on the auxiliary
+ SECT_ORD section storing indices for each
+ section added through the config API.
+
+ To not to go corrupt in case of manually
+ written config files, we take care to append
+ also those sections which are not registered
+ in SECT_ORD.
+
+ Needed for python 2.{4,5} where ConfigParser
+ cannot yet order sections/options internally.
+ """
+ so = {}
+ if self.config.has_section(SECT_ORD):
+ so = self.config._sections[SECT_ORD]
+ so2 = {}
+ for k, v in so.items():
+ if k != '__name__':
+ so2[k] = int(v)
+ tv = 0
+ if so2:
+ tv = max(so2.values()) + 1
+ ss = self.config.sections()
+ try:
+ ss.remove(SECT_ORD)
+ except ValueError:
+ pass
+ for s in ss:
+ if s in so.keys():
+ continue
+ so2[s] = tv
+ tv += 1
+ def scmp(x, y):
+ return cmp(*(so2[s] for s in (x, y)))
+ ss.sort(scmp)
+ return ss
+
def update_to(self, dct):
- for sect in set([DEF_SECT, self.section]):
- if self.config.has_section(sect):
- for k, v in self.config._sections[sect].items():
- if k == '__name__':
- continue
- k = k.replace('-', '_')
- dct[k] = v
+ if not self.peers:
+ raise RuntimeError('no peers given, cannot select matching options')
+ def update_from_sect(sect):
+ for k, v in self.config._sections[sect].items():
+ if k == '__name__':
+ continue
+ k = k.replace('-', '_')
+ dct[k] = v
+ for sect in self.ord_sections():
+ sp = self.parse_section(sect)
+ if isinstance(sp[0], re_type) and len(sp) == len(self.peers):
+ match = True
+ for i in range(len(sp)):
+ if not sp[i].search(self.peers[i]):
+ match = False
+ break
+ if match:
+ update_from_sect(sect)
+ if self.config.has_section(self.section()):
+ update_from_sect(self.section())
def get(self, opt=None):
d = {}
@@ -46,14 +123,20 @@ class GConffile(object):
if f:
f.close()
- def set(self, opt, val):
- if not self.config.has_section(self.section):
- self.config.add_section(self.section)
- self.config.set(self.section, opt, val)
+ def set(self, opt, val, rx=False):
+ sect = self.section(rx)
+ if not self.config.has_section(sect):
+ self.config.add_section(sect)
+ # regarding SECT_ORD, cf. ord_sections
+ if not self.config.has_section(SECT_ORD):
+ self.config.add_section(SECT_ORD)
+ self.config.set(SECT_ORD, sect, len(self.config._sections[SECT_ORD]))
+ self.config.set(sect, opt, val)
self.write()
- def delete(self, opt):
- if not self.config.has_section(self.section):
+ def delete(self, opt, rx=False):
+ sect = self.section(rx)
+ if not self.config.has_section(sect):
return
- if self.config.remove_option(self.section, opt):
+ if self.config.remove_option(sect, opt):
self.write()
diff --git a/xlators/features/marker/utils/syncdaemon/gsyncd.py b/xlators/features/marker/utils/syncdaemon/gsyncd.py
index b8b92056b54..d8166baea53 100644
--- a/xlators/features/marker/utils/syncdaemon/gsyncd.py
+++ b/xlators/features/marker/utils/syncdaemon/gsyncd.py
@@ -199,9 +199,14 @@ def main_i():
a[-1].values.__dict__.update(log_level='DEBUG')))
op.add_option('--config-get', metavar='OPT', type=str, dest='config', action='callback', callback=store_local)
op.add_option('--config-get-all', dest='config', action='callback', callback=store_local_curry(True))
- op.add_option('--config-set', metavar='OPT VAL', type=str, nargs=2, dest='config', action='callback', callback=store_local)
+ op.add_option('--config-set', metavar='OPT VAL', type=str, nargs=2, dest='config', action='callback',
+ callback=lambda o, oo, vx, p: store_local(o, oo, (vx[0], vx[1], False), p))
+ op.add_option('--config-set-rx', metavar='OPT VAL', type=str, nargs=2, dest='config', action='callback',
+ callback=lambda o, oo, vx, p: store_local(o, oo, (vx[0], vx[1], True), p))
op.add_option('--config-del', metavar='OPT', type=str, dest='config', action='callback', callback=lambda o, oo, vx, p:
- store_local(o, oo, (vx, False), p))
+ store_local(o, oo, (vx, False, False), p))
+ op.add_option('--config-del-rx', metavar='OPT', type=str, dest='config', action='callback', callback=lambda o, oo, vx, p:
+ store_local(o, oo, (vx, False, True), p))
# precedence for sources of values: 1) commandline, 2) cfg file, 3) defaults
# -- for this to work out we need to tell apart defaults from explicitly set
@@ -209,25 +214,30 @@ def main_i():
# values container.
defaults = op.get_default_values()
opts, args = op.parse_args(values=optparse.Values())
- if not (len(args) == 2 or (len(args) == 1 and rconf.get('listen')) or (len(args) <= 2 and rconf.get('config'))):
+ confdata = rconf.get('config')
+ if not (len(args) == 2 or (len(args) == 1 and rconf.get('listen')) or (len(args) <= 2 and confdata)):
sys.stderr.write("error: incorrect number of arguments\n\n")
sys.stderr.write(op.get_usage() + "\n")
sys.exit(1)
- local = remote = None
- if args:
- local = resource.parse_url(args[0])
- if len(args) > 1:
- remote = resource.parse_url(args[1])
- if not local.can_connect_to(remote):
- raise RuntimeError("%s cannot work with %s" % (local.path, remote and remote.path))
- pa = ([], [])
- canon = [False, True]
- for x in (local, remote):
- if x:
- for i in range(2):
- pa[i].append(x.get_url(canonical=canon[i]))
- peers, canon_peers = pa
+ if confdata and isinstance(confdata, tuple) and confdata[2]:
+ # peers are regexen, don't try to parse them
+ canon_peers = args
+ else:
+ local = remote = None
+ if args:
+ local = resource.parse_url(args[0])
+ if len(args) > 1:
+ remote = resource.parse_url(args[1])
+ if not local.can_connect_to(remote):
+ raise RuntimeError("%s cannot work with %s" % (local.path, remote and remote.path))
+ pa = ([], [])
+ canon = [False, True]
+ for x in (local, remote):
+ if x:
+ for i in range(2):
+ pa[i].append(x.get_url(canonical=canon[i]))
+ peers, canon_peers = pa
if not 'config_file' in rconf:
rconf['config_file'] = os.path.join(os.path.dirname(sys.argv[0]), "conf/gsyncd.conf")
confp = os.path.dirname(sys.argv[0]) + "conf/"
@@ -241,13 +251,12 @@ def main_i():
raise
gcnf = GConffile(rconf['config_file'], canon_peers)
- confdata = rconf.get('config')
if confdata:
if isinstance(confdata, tuple):
if confdata[1]:
gcnf.set(*confdata)
else:
- gcnf.delete(confdata[0])
+ gcnf.delete(confdata[0], confdata[1])
else:
if confdata == True:
confdata = None