/// <summary> /// Start a copy pushing data to a particular destination. /// </summary> /// <param name="destination"></param> /// <param name="uris"></param> public async Task CopyToAsync(IPlace destination, Uri[] uris, Action <string> statusUpdate = null, Func <bool> failNow = null, int timeoutMinutes = 60) { // Make sure we have something we can deal with. var scpTarget = destination as ISCPTarget; if (scpTarget == null) { throw new ArgumentException($"Place {destination.Name} is not an SCP target."); } // Do things one dataset at a time. foreach (var fsGroup in uris.GroupBy(u => u.DataSetName())) { // Get the remote user, path, and password. var remoteUser = scpTarget.SCPUser; var remoteMachine = scpTarget.SCPMachineName; var passwd = GetPasswordForHost(remoteMachine, remoteUser); // Get the catalog over await destination.CopyDataSetInfoAsync(fsGroup.Key, await DataSetManager.ListOfFilenamesInDatasetAsync(fsGroup.Key, statusUpdate, failNow, probabalLocation: this), statusUpdate, failNow); // The file path where we will store it all var destLocation = await scpTarget.GetPathToCopyFilesAsync(fsGroup.Key); // Next, queue up the copies, one at a time. Move to a part file and then do a rename. foreach (var f in fsGroup) { if (failNow.PCall(false)) { break; } var localFilePath = await GetSCPFilePathAsync(f); var fname = f.DataSetFileName(); var pname = $"{fname}.part"; statusUpdate.PCall($"Copying file {fname}: {Name} -> {destination.Name}"); await _connection.ApplyAsync(async c => { await c.Value.ExecuteLinuxCommandAsync($"scp {localFilePath} {remoteUser}@{remoteMachine}:{destLocation}/{pname}", seeAndRespond: new Dictionary <string, string>() { { "password:"******"ssh {remoteUser}@{remoteMachine} mv {destLocation}/{pname} {destLocation}/{fname}", seeAndRespond: new Dictionary <string, string>() { { "password:", passwd } }, secondsTimeout: 5 * 60, refreshTimeout: true, failNow: failNow); }); } } }
/// <summary> /// Copy via SCP to the remote machine! /// </summary> /// <param name="destination"></param> /// <param name="uris"></param> private async Task CopyToSCPTargetAsync(IPlace destination, Uri[] uris, Action <string> statusUpdate = null, Func <bool> failNow = null) { foreach (var dsGroup in uris.GroupBy(u => u.DataSetName())) { // Move the catalog over. var files = await DataSetManager.ListOfFilenamesInDatasetAsync(dsGroup.Key, statusUpdate, failNow, probabalLocation : this); await destination.CopyDataSetInfoAsync(dsGroup.Key, files); // Now, do the files via SCP. var localFiles = await GetLocalFileLocationsAsync(uris); await((destination as ISCPTarget).CopyFromLocalToRemoteAsync(dsGroup.Key, localFiles.Select(u => new FileInfo(u.LocalPath)), statusUpdate, failNow)); } }