test_ok1/py/execnet/gwmanage.py

121 lines
4.2 KiB
Python

"""
instantiating, managing and rsyncing to hosts
"""
import py
import sys, os
from py.__.execnet.channel import RemoteError
NO_ENDMARKER_WANTED = object()
class GatewayManager:
RemoteError = RemoteError
def __init__(self, specs):
self.specs = [py.execnet.XSpec(spec) for spec in specs]
self.gateways = []
def trace(self, msg):
self.notify("trace", "gatewaymanage", msg)
def notify(self, eventname, *args, **kwargs):
py._com.pyplugins.notify(eventname, *args, **kwargs)
def makegateways(self):
assert not self.gateways
for spec in self.specs:
gw = py.execnet.makegateway(spec)
self.gateways.append(gw)
gw.id = "[%s]" % len(self.gateways)
self.notify("gwmanage_newgateway", gw)
def getgateways(self, remote=True, inplacelocal=True):
if not self.gateways and self.specs:
self.makegateways()
l = []
for gw in self.gateways:
if gw.spec._samefilesystem():
if inplacelocal:
l.append(gw)
else:
if remote:
l.append(gw)
return py.execnet.MultiGateway(gateways=l)
def multi_exec(self, source, inplacelocal=True):
""" remote execute code on all gateways.
@param inplacelocal=False: don't send code to inplacelocal hosts.
"""
multigw = self.getgateways(inplacelocal=inplacelocal)
return multigw.remote_exec(source)
def multi_chdir(self, basename, inplacelocal=True):
""" perform a remote chdir to the given path, may be relative.
@param inplacelocal=False: don't send code to inplacelocal hosts.
"""
self.multi_exec("import os ; os.chdir(%r)" % basename,
inplacelocal=inplacelocal).waitclose()
def rsync(self, source, notify=None, verbose=False, ignores=None):
""" perform rsync to all remote hosts.
"""
rsync = HostRSync(source, verbose=verbose, ignores=ignores)
seen = {}
for gateway in self.gateways:
spec = gateway.spec
if not spec._samefilesystem():
if spec in seen:
continue
def finished():
if notify:
notify("rsyncrootready", spec, source)
rsync.add_target_host(gateway, finished=finished)
seen[spec] = gateway
if seen:
self.notify("gwmanage_rsyncstart", source=source, gateways=seen.values())
rsync.send()
self.notify("gwmanage_rsyncfinish", source=source, gateways=seen.values())
else:
self.trace("rsync: nothing to do.")
def exit(self):
while self.gateways:
gw = self.gateways.pop()
self.trace("exiting gateway %s" % gw)
gw.exit()
class HostRSync(py.execnet.RSync):
""" RSyncer that filters out common files
"""
def __init__(self, sourcedir, *args, **kwargs):
self._synced = {}
ignores= None
if 'ignores' in kwargs:
ignores = kwargs.pop('ignores')
self._ignores = ignores or []
super(HostRSync, self).__init__(sourcedir=sourcedir, **kwargs)
def filter(self, path):
path = py.path.local(path)
if not path.ext in ('.pyc', '.pyo'):
if not path.basename.endswith('~'):
if path.check(dotfile=0):
for x in self._ignores:
if path == x:
break
else:
return True
def add_target_host(self, gateway, finished=None):
remotepath = os.path.basename(self._sourcedir)
super(HostRSync, self).add_target(gateway, remotepath,
finishedcallback=finished,
delete=True,)
def _report_send_file(self, gateway, modified_rel_path):
if self._verbose:
path = os.path.basename(self._sourcedir) + "/" + modified_rel_path
remotepath = gateway.spec.chdir
print '%s:%s <= %s' % (gateway.remoteaddress, remotepath, path)