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