#********************************************************************
#
# Copyright (C) 2005-2006 Hari Krishna Dara
#
# This file is part of p4admin.
#
# p4admin is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
#
# p4admin is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
#
#*******************************************************************
import re
import logging
import config
import notify
import utils
log = logging.getLogger(__name__)
rsyncDaemonStarted = False
def rsyncDaemonRunning(host):
moduleList = utils.execute('rsync rsync://'+host, verbosity=1)
if utils.shell_error == 0:
# We want the daemon with right configuration.
if not re.search(config.rsyncRootModuleName, moduleList) or \
not re.search(config.rsyncJnlModuleName, moduleList):
notify.sendError('Rsync daemon is running on host: '+host+
', but it is not configured properly')
# There is no use attempting to start another server on the same
# port, so return True.
#return False
log.debug('rsync daemon is running on %s with the module list:\n%s',
host, moduleList)
return True
else:
return False
def startupRsyncDaemon(host):
"""Ensure that an rsync daemon is running on this given host"""
global rsyncDaemonStarted
if rsyncDaemonStarted:
return 0
# First check if the rsync is running or not.
if not rsyncDaemonRunning(host):
log.debug('rsync daemon is not started, attempting to start')
if not config.packageInPerforce:
log.info('Copying the rsync configuration file')
if config.remoteShell == 'rsh':
rcpCmd = 'rcp'
elif config.remoteShell == 'ssh':
rcpCmd = 'scp'
else:
notify.sendError('Unknown remoteShell: '+config.remoteShell)
return 1
result = utils.execute(rcpCmd+' '+' '+ config.rsyncConfigFileName+
' '+config.p4HostRemote+':'+config.rsyncRemoteConfig)
if utils.shell_error != 0:
notify.sendError('Error in remote-copying: '+result)
# Attempt to start it up now.
rsyncCmd = 'rsync --daemon --config='+config.rsyncRemoteConfig
if config.rsyncPort:
rsyncCmd += ' --port='+config.rsyncPort
result = utils.execute(config.remoteShell+' '+host+' '+rsyncCmd)
if utils.shell_error != 0:
notify.sendError('Error starting up remote rsync daemon: ' +
result)
return 1
# Check once more if the daemon has started up.
if not rsyncDaemonRunning(host):
notify.sendError("Attempt to startup rsync daemon didn't seem to work")
return 1
rsyncDaemonStarted = True
return 0
def rsyncFile(remoteHost, module, remoteFile, localRoot, localFile,
additionalRsyncOpts, delete=True, ignoreMissingSrc=False):
"""remoteFile can be a directory or file and can contain wildcards."""
# Ensure rsync daemon is running.
rsyncOpts = config.rsyncOpts
if config.rsyncConfigFileName:
if startupRsyncDaemon(remoteHost) != 0:
return 1
remoteDir = 'rsync://'+remoteHost
if config.rsyncPort:
remoteDir += ':'+config.rsyncPort
remoteDir += '/'+module+'/'+remoteFile
else:
rsyncOpts += ' --rsh '+config.remoteShell
remoteDir = remoteHost+':/'+config.rsyncModulePathLookup[module]+'/'+\
remoteFile
localDir = localRoot+'/'+localFile
#if remoteDir[-1] == '/':
# localDir = localRoot+'/'+localFile
#else:
# localDir = localRoot
# rsync --rsh=ssh -av scallop:/cygdrive/e/Perforce/appsprod/depot/ /cygdrive/d/Perforce/appsprod/depot
# rsync -av rsync://scallop/perforceroot/depot/ /cygdrive/d/Perforce/appsprod/depot
result = utils.execute('rsync '+
rsyncOpts+' '+additionalRsyncOpts+
# Python doesn't have a ternary operator
(' --delete ', ' ')[not delete]+
remoteDir+' '+localDir)
if utils.shell_error != 0:
if not ignoreMissingSrc or not re.search(r'(ckp|jnl)\.\*.*: No such '
'file', result):
notify.sendError('rsync failed to synchronize: ' + result)
return 1
else:
log.debug('ignoring errors because ignoreMissingSrc?%s'
' and the output matches safe pattern', ignoreMissingSrc)
return 0