106
111
if self.group is not None:
107
112
self.group.Reset(dbus_interface='org.freedesktop.Avahi.EntryGroup')
109
def on_ItemNew(self, interface, protocol, name, _type, domain, flags):
110
if name == self.id: # Ignore what we publish ourselves
114
def on_ItemNew(self, interface, protocol, key, _type, domain, flags):
115
if key == self.id: # Ignore what we publish ourselves
112
if not name.startswith(self.base_id): # Ignore other libraries
117
if not key.startswith(self.base_id): # Ignore other libraries
114
119
(ip, port) = self.avahi.ResolveService(
115
interface, protocol, name, _type, domain, -1, 0,
120
interface, protocol, key, _type, domain, -1, 0,
116
121
dbus_interface='org.freedesktop.Avahi.Server'
118
123
url = 'http://{}:{}/'.format(ip, port)
119
log.info('Replicator: new peer %s at %s', name, url)
120
self.peers[name] = url
121
self.replicate(url, 'foo')
123
def on_ItemRemove(self, interface, protocol, name, _type, domain, flags):
124
log.info('Replicator: removing peer %s', name)
130
def replicate(self, url, dbname):
131
# Create local DB if needed
133
self.server.put(None, dbname)
134
except PreconditionFailed:
137
# Create remote DB if needed
138
env = {'url': url, 'oauth': self.tokens}
139
db = Database(dbname, env)
142
peer = get_peer(url, dbname, self.tokens)
143
local_to_remote = get_body(dbname, peer)
144
remote_to_local = get_body(peer, dbname)
145
for obj in (local_to_remote, remote_to_local):
146
self.server.post(obj, '_replicate')
124
log.info('Replicator: new peer %s at %s', key, url)
126
self.peers[key] = Peer(url, [])
127
self.replicate_all(key)
129
def on_ItemRemove(self, interface, protocol, key, _type, domain, flags):
130
log.info('Replicator: peer removed %s', key)
131
self.cancel_all(str(key))
133
def cancel_all(self, key):
134
p = self.peers.pop(key, None)
137
log.info('Canceling replications for %r', key)
139
self.replicate(p.url, name, cancel=True)
141
def replicate_all(self, key):
143
env = {'url': p.url, 'oauth': self.tokens}
145
for name in self.server.get('_all_dbs'):
146
if name.startswith('_'):
148
if not (name.startswith('dmedia-0') or name.startswith('novacut-0')):
150
# Create remote DB if needed
152
remote.put(None, name)
153
except PreconditionFailed:
158
self.replicate(p.url, name)
160
def replicate(self, url, name, cancel=False):
162
Start or cancel push replication of database *name* to peer at *url*.
164
Security note: we only do push replication because pull replication
165
would allow unauthorized peers to write to our databases via their
166
changes feed. For both push and pull, there is currently no privacy
167
whatsoever... everything is in cleartext and uses oauth 1.0a. But push
168
replication is the only way to at least prevent malicious data
172
log.info('Canceling push of %r to %r', name, url)
174
log.info('Starting push of %r to %r', name, url)
175
peer = get_peer(url, name, self.tokens)
176
push = get_body(name, peer, cancel)
177
self.server.post(push, '_replicate')