1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23 import sys
24
25 import help
26
27
30
31 self.__relax_help__ = \
32 """Class for controlling threading of calculations."""
33
34
35 self.__relax_help__ = self.__relax_help__ + "\n" + help.relax_class_help
36
37
38 self.__relax__ = relax
39
40
41 - def read(self, file="hosts", dir="~/.relax"):
42 """Function for reading a file containing entries for each computer to run calculations on.
43
44 Keyword Arguments
45 ~~~~~~~~~~~~~~~~~
46
47 file: The name of the file containing the host entries.
48
49 dir: The directory where the hosts file is located.
50
51
52 Description
53 ~~~~~~~~~~~
54
55 Certain functions within relax are coded to handle threading. This is achieved by running
56 multiple instances of relax on different processes or computers for each thread. The
57 default behaviour is that the parent instance of relax will execute all the code, however if
58 a hosts file is read or a hosts entry manually entered, then the threaded code will run on
59 the specified hosts. This function is for reading a hosts file which should contain an
60 an entry for each computer on which to run calculations.
61
62 For remote computers, a SSH connection will be attempted. Public key authentication must be
63 enabled to run calculations on remote machines so that thread can be created without asking
64 for a password. Details on how to do this are given below.
65
66
67 The format of the hosts file is as follows. Default values are specified by placing the
68 character '-' in the corresponding column. Columns can be separated by any whitespace
69 character, and all columns must contain an entry. Any lines beginning with a hash will be
70 ignored.
71
72 Column 1: The host name or IP address of the computer on which to run a thread.
73
74 Column 2: The login name of the user on the remote machine. The default is to use the same
75 name as the current user.
76
77 Column 3: The full program path. The default is to run 'relax'. This only works if relax
78 can be found in the environmental variable $PATH, as alias are not recognised.
79
80 Column 4: The working directory where thread specific files are stored. The default is
81 '~/.relax' where the tilde '~' symbol represents the user's home directory on the remote
82 machine.
83
84 Column 5: The priority value for running the program. The default is 15. The remote
85 instances of relax will be niced to this value.
86
87 Column 6: The number of CPU or CPU cores on the machine. The default is 1. A thread is
88 started for each CPU.
89
90 An example is:
91
92 -------------------------------------------------------------------------------------------
93 # Host User name Program path Working directory Priority CPUs
94 localhost - - - 0 2
95 192.168.0.10 dauvergne /usr/local/bin/relax - - -
96 192.168.0.11 edward - - - -
97 -------------------------------------------------------------------------------------------
98
99 In this case, two threads will be run on the parent computer which would be either a dual
100 CPU system or a dual core 'Hyper threaded' Pentium processor. These threads will have the
101 highest level user priority of 0. The other two machines will have single threads running
102 with a low priority of 15.
103
104 Once threading is enabled, to allow calculations to run on the parent machine a 'localhost'
105 entry should be included.
106
107
108 If the keyword argument 'dir' is set to None, the hosts file will be assumed to be in the
109 current working directory.
110
111
112 SSH Public Key Authentication
113 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
114
115 To enable SSH Public Key Authentication for the use of ssh, sftp, and scp without having to
116 type a password, use the following steps. This is essential for running a thread on a
117 remote machine.
118
119 If the files 'id_rsa' and 'id_rsa.pub' do not exist in the directory '~/.ssh', type:
120
121 $ ssh-keygen -t rsa
122
123 Press enter three times when asked for input. This will generate the two identification
124 files. Then, to copy the public key into the 'authorized_keys' file on the remote machine,
125 type:
126
127 $ ssh zucchini "echo $(cat ~/.ssh/id_rsa.pub) >> ~/.ssh/authorized_keys"
128
129 Make sure you replace 'zucchini' with the name or IP address of the remote machine. To use
130 DSA rather than RSA authentication, replace 'rsa' with 'dsa' in the above commands.
131 Normally the sshd keyword StrictModes, which is found in the file '/etc/ssh/sshd_config', is
132 set to 'yes' or, if unspecified, defaults to 'yes'. In this case, public key authentication
133 may fail as the permissions of the remote file '~/.ssh/authorized_keys' may be too
134 permissive. The file should only be read/write for the user, ie 600. To remotely change
135 the permissions, type:
136
137 $ ssh zucchini "chmod 600 ~/.ssh/authorized_keys"
138
139 One last keyword may need to be changed in the file '/etc/ssh/sshd_config'. If the keyword
140 PubkeyAuthentication is set to 'no', change this to 'yes'. The default is yes, so if the
141 keyword is missing or is commented out, nothing needs to be done.
142
143 Public key authentication should now work. To test, type:
144
145 $ ssh zucchini
146
147 This should securely login into the remote machine without asking for a password. If a
148 password prompt appears, check all the permissions on the directory '~/.ssh' and all files
149 within or set the sshd_config keyword StrictModes to 'no'.
150
151 $ ssh zucchini "chmod 700 ~/.ssh/"
152 $ ssh zucchini "chmod 600 ~/.ssh/*"
153 $ ssh zucchini "chmod 644 ~/.ssh/*.pub"
154
155 Finally, if all else fails, make sure the three lines
156
157 -----
158 RSAAuthentication yes
159 PubkeyAuthentication yes
160 AuthorizedKeysFile .ssh/authorized_keys
161 -----
162
163 of the file 'sshd_config' found within the directory '/etc/ssh/' are uncommented and not set
164 to 'no' or the 'AuthorizedKeysFile' set to another file name.
165 """
166
167
168 if self.__relax__.interpreter.intro:
169 text = sys.ps3 + "thread.read("
170 text = text + "file=" + `file`
171 text = text + ", dir=" + `dir` + ")"
172 print text
173
174
175 if type(file) != str:
176 raise RelaxStrError, ('file', file)
177
178
179 if dir != None and type(dir) != str:
180 raise RelaxNoneStrError, ('directory name', dir)
181
182
183 self.__relax__.threading.read(file=file, dir=dir)
184