Convert file transfer to the new callbacks.
[gsh.git] / gsh / file_transfer.py
blobd17163523115e84a8130e9f5961b2a71c887ff0e
1 # This program is free software; you can redistribute it and/or modify
2 # it under the terms of the GNU General Public License as published by
3 # the Free Software Foundation; either version 2 of the License, or
4 # (at your option) any later version.
6 # This program is distributed in the hope that it will be useful,
7 # but WITHOUT ANY WARRANTY; without even the implied warranty of
8 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
9 # GNU Library General Public License for more details.
11 # You should have received a copy of the GNU General Public License
12 # along with this program; if not, write to the Free Software
13 # Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
15 # See the COPYING file for license information.
17 # Copyright (c) 2007, 2008 Guillaume Chazarain <guichaz@gmail.com>
19 import base64
20 import random
22 from gsh import callbacks
23 from gsh import pity
24 from gsh.console import console_output
26 def base64version(module):
27 path = module.__file__
28 if path.endswith('.pyc'):
29 # Read from the .py source file
30 path = path[:-1]
31 python_lines = []
32 for line in file(path):
33 hash_pos = line.find(chr(35))
34 if hash_pos < 0:
35 line = line[:hash_pos]
36 line = line.rstrip()
37 if line:
38 python_lines.append(line)
39 python_source = '\n'.join(python_lines)
40 encoded = base64.encodestring(python_source).rstrip('\n').replace('\n', ',')
41 return encoded
43 CMD_PREFIX = 'python -c "`echo "' + base64version(pity) + '"|' + \
44 'tr , \\\\\\n|' + \
45 'openssl base64 -d`" '
47 CMD_SEND = CMD_PREFIX + 'send "%s" "%s" "%s"\n'
48 CMD_FORWARD = CMD_PREFIX + 'forward "%s" "%s"\n'
49 CMD_RECEIVE = CMD_PREFIX + 'receive "%s" "%s"\n'
51 def file_transfer_cb(dispatcher, host_port):
52 previous_shell = get_previous_shell(dispatcher)
53 previous_shell.dispatch_write(host_port + '\n')
55 def get_infos():
56 """Returns (first, last)"""
57 from gsh import dispatchers
58 first = None
59 last = None
60 for i in dispatchers.all_instances():
61 if i.enabled:
62 if not first:
63 first = i
64 last = i
65 return first, last
67 def get_previous_shell(shell):
68 from gsh import dispatchers
69 shells = [i for i in dispatchers.all_instances() if i.enabled]
70 current_pos = shells.index(shell)
71 while True:
72 current_pos = (current_pos - 1) % len(shells)
73 prev_shell = shells[current_pos]
74 if prev_shell.enabled:
75 return prev_shell
77 def replicate(shell, path):
78 from gsh import dispatchers
79 from gsh import remote_dispatcher
80 nr_peers = len([i for i in dispatchers.all_instances() if i.enabled])
81 if nr_peers <= 1:
82 console_output('No other remote shell to replicate files to\n')
83 return
84 receiver = get_previous_shell(shell)
85 for i in dispatchers.all_instances():
86 if not i.enabled:
87 continue
88 cb = lambda host_port, i=i: file_transfer_cb(i, host_port)
89 transfer1, transfer2 = callbacks.add('file transfer', cb, False)
90 if i == shell:
91 i.dispatch_command(CMD_SEND % (path, transfer1, transfer2))
92 elif i != receiver:
93 i.dispatch_command(CMD_FORWARD % (transfer1, transfer2))
94 else:
95 i.dispatch_command(CMD_RECEIVE % (transfer1, transfer2))
96 i.change_state(remote_dispatcher.STATE_RUNNING)