1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18 """C{copyfrom [-Crpx] -c CLUSTER FILES LOCAL_DIR}
19
20 Copies C{FILES} from each node of the specified C{CLUSTER} to
21 C{LOCAL_DIR}. If C{CLUSTER} is omitted, then the default cluster is
22 used. C{FILES} identifies files on nodes of the cluster. It must be
23 an absolute path, (i.e. must begin with C{'/'}) and may specify
24 multiple files, e.g. C{/foo/bar*/*.[0-9]}. C{LOCAL_DIR} is a
25 directory on the node from which the command is being issued.
26
27 C{copyfrom} will normally populate a directory under C{LOCAL_DIR} for
28 each node in the cluster, creating the subdirectories if necessary.
29 The name of the subdirectory will be the same as the node's name,
30 specified in C{.oshrc}. But if C{-x} is specified, then subdirectories
31 will not be populated; files will be placed directly in
32 C{LOCAL_DIR}. The C{-x} option is supported only for single-node
33 clusters.
34
35 C{copyfrom} is implemented using C{scp}, and the following C{scp} flags are supported:
36 - C{-C}: enable compression.
37 - C{-r}: recursive copy
38 - C{-p}: preserve modification times, access times, and modes.
39 """
40
41 import os
42 import pickle
43 import threading
44
45 import osh.args
46 import osh.core
47 import osh.spawn
48
49 Spawn = osh.spawn.Spawn
50 Option = osh.args.Option
51
52
55
56
57 -def copyfrom(cluster, files, local_dir,
58 compress = False, recursive = False, preserve = False, no_subdirs = False):
59 """Copies C{files} from each node of the specified C{cluster} to C{local_dir}.
60 If C{no_subdirs} is False, then a subdirectory under C{local_dir} is created for
61 each node of the cluster and the files from a node are copied to that node's subdirectory.
62 If C{no_subdirs} is true, then C{cluster} must be a single-node cluster, no subdirectory
63 is created, and files are copied directly into C{local_dir}. Compression is used
64 for copying if C{compress} is True. Directories are copied recursively if C{recursive} is
65 True. File attributes are preserved if C{preserve} is True.
66 """
67 args = [Option('-c', cluster)]
68 scp_options = ''
69 if compress:
70 scp_options += 'C'
71 if recursive:
72 scp_options += 'r'
73 if preserve:
74 scp_options += 'p'
75 if len(scp_options) > 0:
76 scp_options = '-' + scp_options
77 args.append(Option(scp_options))
78 if no_subdirs:
79 args.append(Option('-x'))
80 return _CopyFrom().process_args(*args)
81
82
83
85 if options[0] != '-':
86 options = '-' + options
87 return osh.args.Option(options)
88
90
91
92
93 _local_dir = None
94 _file = None
95 _scp_options = None
96 _use_subdirs = None
97
98
99
100
103
104
105
108
110 osh.core.RemoteOp.setup(self)
111 args = self.args()
112 self._use_subdirs = not args.flag('-x')
113 if not self._use_subdirs and len(self.hosts()) > 1:
114 self.usage()
115 if args.has_next():
116 self._file = args.next_string()
117 if args.has_next():
118 self._local_dir = args.next_string()
119 if not self._file or not self._local_dir or args.has_next():
120 self.usage()
121 if not self._file.startswith('/'):
122 self.usage()
123
124
125
127 target_dir = self._local_dir
128 if self._use_subdirs:
129 target_dir += '/' + host.name
130 try:
131 os.makedirs(target_dir)
132 except OSError:
133 pass
134 _copydown(self.user(),
135 host.address,
136 self._file,
137 target_dir,
138 self.scp_options())
139
140 -def _copydown(user, host, file, local_dir, options = ''):
141 scp_command = 'scp %s %s@%s:%s %s' % (options, user, host, file, local_dir)
142 Spawn(scp_command, None, None, None).run()
143