diff 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 diff
--- a/silvermirror/unify.py	Mon Sep 07 15:39:06 2009 -0400
+++ b/silvermirror/unify.py	Sat Sep 26 23:36:42 2009 -0400
@@ -9,6 +9,7 @@
 
 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
@@ -52,11 +53,73 @@
     config = { 'main': main, 'resources': config }
     return config
 
-def unify(args=sys.argv[1:]):
+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')
@@ -67,7 +130,8 @@
     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:
@@ -84,72 +148,11 @@
     # 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
-    _hosts = []
-    for host in hosts:
-        s = socket.socket()
-        s.settimeout(conf['main']['timeout'])
-        if options.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 options.test:
-        print 'Hosts:'
-        for host in hosts:
-            print host
-    assert hosts
-
-    if options.password and 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
+    # 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']
 
-    ### determine resources to sync
-    cwd = os.path.realpath(os.getcwd())
-    resources = conf['resources']
-    _resources = args
-    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 options.test:
-        print 'Resources:'
-        pprint(resources)
-
-    ### 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)]
-
-            # XXX - to refactor?
-            for i in resources[resource]['ignore']:
-                command.extend(('-ignore', "'Name %s'" % i))
-
-            command = ' '.join(command) 
-            print command # XXX debug 
-            if not options.test:
-                child = pexpect.spawn(command, timeout=36000, maxread=1)
-                child.expect('password: ')
-                child.sendline(pw[host])
-                print child.read()
-                #                subprocess.call(command)
-    os.chdir(cwd)
+    unify(conf, args, options.test)
 
 if __name__ == '__main__':
     unify()