All pastes #1491042 Raw Edit

Something

public text v1 · immutable
#1491042 ·published 2009-07-10 19:45 UTC
rendered paste body
#!/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()