#!/usr/bin/env python import os import socket import subprocess import sys from martini.config import ConfigMunger from optparse import OptionParser 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 main['hosts'] = main.get('hosts', '').split() # resources for resource in config: 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) config = { 'main': main, 'resources': config } return config 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) (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() ### determine hosts to sync with hosts = set(options.hosts or conf['main']['hosts']) addresses = ip_addresses().values() hosts = hosts.difference(addresses) # don't sync with self # TODO: ensure that the hosts are resolvable # XXX: this should actually be manageable on a per-resource basis ### determine resources to sync cwd = os.path.realpath(os.getcwd()) resources = conf['resources'] _resources = args 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 ### sync with hosts os.chdir(conf['main']['basedir']) for resource in resources: for host in hosts: command = ['unison', '-auto', '-batch', resource, 'ssh://%s/%s' % (host, resource)] print ' '.join(command) # subprocess.call(command) os.chdir(cwd) if __name__ == '__main__': main()