def test_stage_downstream_except(mock_download): """ Test if staging exception is correctly raised if rsync exception happens. """ job = { "jobname": "jobone", "destdir": "/path/to/jobone12484", "localworkdir": "/path/to/local/dir" } mock_download.side_effect = exceptions.RsyncError("Rsync Error", "output") with pytest.raises(exceptions.StagingError): stage_downstream(job)
def test_stage_upstream_rsyncexcept(mock_ssh, mock_upload): """ Test if staging exception is correctly raised if rsync exception happens. """ jobs = { "jobone": { "destdir": "/path/to/jobone12484", "resource": "test-machine", "localworkdir": "/path/to/local/dir" } } mock_ssh.return_value = None mock_upload.side_effect = exceptions.RsyncError("Rsync Error", "output") with pytest.raises(exceptions.StagingError): stage_upstream(jobs)
def test_download_exceptiontest(mock_sendtorsync): """ Check that if the rsync method raises the rsync exception that it percolates up. """ job = { "port": "22", "user": "******", "host": "massive-machine", "destdir": "~/destination/directory/path", "localworkdir": "/destination/directory/path", "download-include": "", "download-exclude": "" } mock_sendtorsync.side_effect = exceptions.RsyncError("RsyncError", "Error") with pytest.raises(exceptions.RsyncError): download(job)
def sendtorsync(job, src, dst, includemask, excludemask): """Construct Rsync commands and hand them off to the shell. This method constructs a string that forms an rsync command, this string is then handed off to the sendtoshell() method for execution. Required arguments are: job (dictionary) - A single job dictionary, this is often simply passed in as a subset of the main jobs dictionary. src (string) - A string containing the source directory for transfer, if this is a download then this should include the host information. See the download and upload methods for how this should be done (or just make use of those two methods). dst (string) - A string containing the destination directory for transfer, if this is an upload then this should include the host information. See the download and upload methods for how this should be done (or just make use of those two methods). includemask (string) - This is a string that should contain a comma separated list of files for transfer. excludemask (string) - This is a string that should specify which files should be excluded from rsync transfer, this is useful for not transfering large unwanted files. """ # Initialise variables. include = [] exclude = [] port = job["port"] # Figure out if we are using masks to specify files. if excludemask is not "" and includemask is "": # Exclude masks are a comma separated list. for mask in excludemask.split(","): mask = mask.replace(" ", "") exclude.append("--exclude") exclude.append(mask) cmd = ["rsync", "-azP"] cmd.extend(exclude) cmd.extend(["-e", "ssh -p " + port, src, dst]) elif excludemask is not "" and includemask is not "": # Exclude masks are a comma separated list. for mask in excludemask.split(","): mask = mask.replace(" ", "") exclude.append("--exclude") exclude.append(mask) # Exclude masks are a comma separated list. for mask in includemask.split(","): mask = mask.replace(" ", "") include.append("--include") include.append(mask) cmd = ["rsync", "-azP"] cmd.extend(include) cmd.extend(exclude) cmd.extend(["-e", "ssh -p " + port, src, dst]) else: # Just normal rsync cmd = ["rsync", "-azP", "-e", "ssh -p " + port, src, dst] i = 0 # This loop is essentially so we can do 3 retries on commands that fail, # this is to catch when things go wrong over SSH like dropped connections, # issues with latency etc. while i is not 3: # Send to SSH. shellout = sendtoshell(cmd) errorstate = shellout[2] # If no error exit loop, if errorcode is not 0 raise exception unless # code is 255 if errorstate is 0: break else: i = i + 1 # If number of retries hits 3 then give up. if i is 3: raise exceptions.RsyncError( "rsync failed, make sure a normal terminal can connect to " "rsync to be sure there are no connection issues.", shellout) LOG.debug("Retry rsync after 10 second wait.") # Wait 10 seconds to see if problem goes away before trying again. time.sleep(10)