#!/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()