-
Notifications
You must be signed in to change notification settings - Fork 15
/
sync.py
executable file
·125 lines (108 loc) · 4.02 KB
/
sync.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
#!/usr/bin/env python
# Sync utility, forked from original by gdb@openai
import argparse
import fcntl
import logging
import os
import re
import select
import subprocess
import sys
import util as u
# In modules, use `logger = logging.getLogger(__name__)`
parser = argparse.ArgumentParser(description='sync')
parser.add_argument('-v', '--verbose', action='count', dest='verbosity',
default=0, help='Set verbosity.')
parser.add_argument('-n', '--name', type=str, default='', help="name of instance to sync with")
args = parser.parse_args()
logger = logging.getLogger()
logger.addHandler(logging.StreamHandler(sys.stderr))
if args.verbosity == 0:
logger.setLevel(logging.INFO)
elif args.verbosity >= 1:
logger.setLevel(logging.DEBUG)
class Error(Exception):
pass
class Resyncd(object):
def __init__(self, remote, sync):
self.remote = remote
self.sync = sync
self.counter = 0
def run(self):
self.resync()
sources = [sync.source for sync in self.sync]
fswatch = subprocess.Popen(['fswatch'] + sources, stdout=subprocess.PIPE)
fl = fcntl.fcntl(fswatch.stdout.fileno(), fcntl.F_GETFL)
fcntl.fcntl(fswatch.stdout.fileno(), fcntl.F_SETFL, fl | os.O_NONBLOCK)
while True:
r, _, _ = select.select([fswatch.stdout], [], [])
fswatch_output = r[0].read()
output = fswatch_output.decode('ascii')
files = output.strip().split("\n")
# Ignore emacs swap files
files = [f for f in files if not '#' in os.path.basename(f)]
if files:
print("changed: "+str(files))
files = set(files) # remove duplicates from fswatch_output
if not files:
continue
print("---")
print(files)
print("---")
self.resync()
def resync(self):
procs = []
for sync in self.sync:
instance = u.get_instances(args.name, verbose=False)[0]
print("Syncing with ", u.get_name(instance))
command = sync.command(instance)
popen = subprocess.Popen(command)
procs.append({
'popen': popen,
'command': command,
})
# Wait
for proc in procs:
print(proc["command"])
proc['popen'].communicate()
for proc in procs:
if proc['popen'].returncode != 0:
raise Error('Bad returncode from %s: %d', proc['command'], proc['popen'].returncode)
logger.info('Resync %d complete', self.counter)
self.counter += 1
class Sync(object):
# todo: exclude .#sync.py
excludes = ['*.model', '*.cache', '.picklecache', '.git', '*.pyc', '*.gz']
def __init__(self, source, dest, modify_window=True, copy_links=False, excludes=[]):
self.source = os.path.expanduser(source)
self.dest = dest
self.modify_window = modify_window
self.copy_links = copy_links
self.excludes = self.excludes + excludes
def command(self, instance, pem_location=''):
excludes = []
for exclude in self.excludes:
excludes += ['--exclude', exclude]
# todo, rename no_strict_checking to ssh_command
keypair_fn = u.get_keypair_fn()
username = u.get_username(instance)
ip = instance.public_ip_address
ssh_command = "ssh -i %s -o StrictHostKeyChecking=no"%(keypair_fn,)
no_strict_checking = ['-arvce', ssh_command]
command = ['rsync'] + no_strict_checking + excludes
if self.modify_window:
command += ['--update', '--modify-window=600']
if self.copy_links:
command += ['-L']
command += ['-rv', self.source, username+"@"+ip + ':' + self.dest]
print("Running ")
print(command)
return command
def main():
sync = [Sync(source='.', dest='.', copy_links=False),]
# obtain ssh
resyncd = Resyncd('asdf', sync)
resyncd.run()
return 0
if __name__ == '__main__':
sys.exit(main())