Mercurial > hg > silvermirror
view silvermirror/unify.py @ 1:9b139702a8f9
use a real backend architecture with an inteface and vastly simplify unify.py
author | k0s <k0scist@gmail.com> |
---|---|
date | Sat, 26 Sep 2009 23:36:42 -0400 |
parents | abb358e2434c |
children | 743c920bc041 |
line wrap: on
line source
#!/usr/bin/env python import getpass import os import pexpect import socket import subprocess import sys from martini.config import ConfigMunger from optparse import OptionParser from pkg_resources import iter_entry_points from pprint import pprint from utils import home from utils import ip_addresses def make_config(filename): # XXX needed? raise NotImplementedError('Need to specify a config file, like\n~/silvermirror/silvermirror.ini') def read_config(filename): config = ConfigMunger(filename).dict() ### main configuration main = config.pop('::SilverMirror::', {}) if not main.get('basedir'): main['basedir'] = home() main['ignore'] = main.get('ignore', '').split() # patterns to ignore - not used main['hosts'] = main.get('hosts', '').split() main['password'] = main.get('password', 'true') # XXX not used main['timeout'] = float(main.get('timeout', '10.')) ### resources for resource in config: # directory of resource directory = config[resource].get('directory', resource) if not os.path.isabs(directory): # XXX note: absolute directories will not work for now # XXX so....don't do this! directory = os.path.join(main['basedir'], directory) config[resource]['directory'] = directory.rstrip(os.path.sep) # per-resource files to ignore # XXX regexps for now (see `man unison`) # - this is bad as whitespace patterns cannot be ignored ignore = main['ignore'][:] if config[resource].has_key('ignore'): ignore += config[resource]['ignore'].split() config[resource]['ignore'] = ignore ### config = { 'main': main, 'resources': config } return config def unify(conf, _resources, test=False): # passwords pw = {} # XXX needed for now assert conf['main']['basedir'] == home() ### determine hosts to sync with hosts = conf['hosts'] addresses = ip_addresses().values() hosts = hosts.difference(addresses) # don't sync with self _hosts = [] for host in hosts: s = socket.socket() s.settimeout(conf['main']['timeout']) if test: print 'Resolving %s' % host try: s.connect((host, 22)) s.close() except (socket.gaierror, socket.timeout, socket.error): continue _hosts.append(host) hosts = _hosts if test: print 'Hosts:' for host in hosts: print host assert hosts if conf['main']['password']: for host in hosts: pw[host] = getpass.getpass('Enter password for %s: ' % host) # TODO: ensure that the hosts are resolvable # XXX: hosts should actually be manageable on a per-resource basis ### determine resources to sync cwd = os.path.realpath(os.getcwd()) resources = conf['resources'] if 'all' not in _resources: if _resources: resources = dict([(key, value) for key, value in resources.items() if key in _resources]) else: for key, value in resources.items(): directory = os.path.realpath(value['directory']) + os.sep if (cwd + os.sep).startswith(directory): resources = { key: value } break if test: print 'Resources:' pprint(resources) ### choose reflector backend reflectors = dict([(i.name, i.load()) for i in iter_entry_points('silvermirror.reflectors')]) reflector = reflectors['unison']() # only one right now ### sync with hosts os.chdir(conf['main']['basedir']) for resource in resources: for host in hosts: reflector.sync(host, resource, resources[resource]['ignore'], pw, test) os.chdir(cwd) def main(args=sys.argv[1:]): ### command line options parser = OptionParser() parser.add_option('-c', '--config') parser.add_option('-H', '--host', dest='hosts', action='append', default=None) parser.add_option('--no-password', dest='password', action='store_false', default=True) parser.add_option('--test', dest='test', action='store_true', default=False) (options, args) = parser.parse_args() ### configuration user_conf = os.path.join(home(), '.silvermirror') if options.config: assert os.path.exists(options.config) conf = read_config(options.config) else: for i in user_conf, '/etc/silvermirror': if os.path.exists(i): conf = read_config(i) break else: conf = make_config(user_conf) # XXX needed for now assert conf['main']['basedir'] == home() # fix up configuration from command line options conf['hosts'] = set(options.hosts or conf['main']['hosts']) conf['main']['password'] = options.password and conf['main']['password'] unify(conf, args, options.test) if __name__ == '__main__': unify()