revert cca3a2cd2096c0235dddb5982b1f05c8d4c7f916 as well
[bootmanager.git] / source / utils.py
1 #!/usr/bin/python
2
3 # Copyright (c) 2003 Intel Corporation
4 # All rights reserved.
5 #
6 # Copyright (c) 2004-2006 The Trustees of Princeton University
7 # All rights reserved.
8 # expected /proc/partitions format
9
10 import os, sys, shutil
11 import popen2
12 import socket
13 import fcntl
14 import string
15 import exceptions
16
17 from Exceptions import *
18
19
20 ### handling breakpoints in the startup process
21 import select, sys, string
22
23 ### global debug settings
24 # NOTE. when BREAKPOINT_MODE turns out enabled,
25 # you have to attend the boot phase, that would hang otherwise 
26
27 # enabling this will cause the node to ask for breakpoint-mode at startup
28 # production code should read False/False
29 PROMPT_MODE=False
30 # default for when prompt is turned off, or it's on but the timeout triggers
31 BREAKPOINT_MODE=False
32 VERBOSE_MODE=False
33 VERBOSE_MODE=True
34 # in seconds : if no input, proceed
35 PROMPT_TIMEOUT=5
36
37 def prompt_for_breakpoint_mode ():
38
39     global BREAKPOINT_MODE
40     if PROMPT_MODE:
41         default_answer=BREAKPOINT_MODE
42         answer=''
43         if BREAKPOINT_MODE:
44             display="[y]/n"
45         else:
46             display="y/[n]"
47         sys.stdout.write ("Want to run in breakpoint mode ? %s "%display)
48         sys.stdout.flush()
49         r,w,e = select.select ([sys.stdin],[],[],PROMPT_TIMEOUT)
50         if r:
51             answer = string.strip(sys.stdin.readline())
52         else:
53             sys.stdout.write("\nTimed-out (%d s)"%PROMPT_TIMEOUT)
54         if answer:
55             BREAKPOINT_MODE = ( answer == "y" or answer == "Y")
56         else:
57             BREAKPOINT_MODE = default_answer
58     label="Off"
59     if BREAKPOINT_MODE:
60         label="On"
61     sys.stdout.write("\nCurrent BREAKPOINT_MODE is %s\n"%label)
62
63 def breakpoint (message, cmd = None):
64
65     if BREAKPOINT_MODE:
66
67         if cmd is None:
68             cmd="/bin/sh"
69             message=message+" -- Entering bash - type ^D to proceed"
70
71         print message
72         os.system(cmd)
73
74
75 ########################################
76 def makedirs( path ):
77     """
78     from python docs for os.makedirs:
79     Throws an error exception if the leaf directory
80     already exists or cannot be created.
81
82     That is real useful. Instead, we'll create the directory, then use a
83     separate function to test for its existance.
84
85     Return 1 if the directory exists and/or has been created, a BootManagerException
86     otherwise. Does not test the writability of said directory.
87     """
88     try:
89         os.makedirs( path )
90     except OSError:
91         pass
92     try:
93         os.listdir( path )
94     except OSError:
95         raise BootManagerException, "Unable to create directory tree: %s" % path
96     
97     return 1
98
99
100
101 def removedir( path ):
102     """
103     remove a directory tree, return 1 if successful, a BootManagerException
104     if failure.
105     """
106     try:
107         os.listdir( path )
108     except OSError:
109         return 1
110
111     try:
112         shutil.rmtree( path )
113     except OSError, desc:
114         raise BootManagerException, "Unable to remove directory tree: %s" % path
115     
116     return 1
117
118
119
120 def sysexec( cmd, log= None ):
121     """
122     execute a system command, output the results to the logger
123     if log <> None
124
125     return 1 if command completed (return code of non-zero),
126     0 if failed. A BootManagerException is raised if the command
127     was unable to execute or was interrupted by the user with Ctrl+C
128     """
129     if VERBOSE_MODE:
130         print ("sysexec >>> %s" % cmd)
131     prog= popen2.Popen4( cmd, 0 )
132     if prog is None:
133         raise BootManagerException, \
134               "Unable to create instance of popen2.Popen4 " \
135               "for command: %s" % cmd
136
137     if log is not None:
138         try:
139             for line in prog.fromchild:
140                 log.write( line )
141         except KeyboardInterrupt:
142             raise BootManagerException, "Interrupted by user"
143
144     returncode= prog.wait()
145     # revert http://git.planet-lab.org/?p=bootmanager.git;a=commitdiff;h=cca3a2cd2096c0235dddb5982b1f05c8d4c7f916
146     # as 256 returned by Python
147     #
148     ## cat test.py 
149     #import popen2
150     #
151     #cmd = "false"
152     #prog = popen2.Popen4( cmd, 0 )
153     #returncode = prog.wait()
154     #print returncode
155     #
156     ## python test.py 
157     # 256
158     if returncode != 0:
159         raise BootManagerException, "Running %s failed (rc=%d)" % (cmd,returncode)
160
161     prog= None
162     return 1
163
164
165 def sysexec_chroot( path, cmd, log= None ):
166     """
167     same as sysexec, but inside a chroot
168     """
169     preload = ""
170     release = os.uname()[2]
171     # 2.6.12 kernels need this
172     if release[:5] == "2.6.1":
173         library = "%s/lib/libc-opendir-hack.so" % path
174         if not os.path.exists(library):
175             shutil.copy("./libc-opendir-hack.so", library)
176         preload = "/bin/env LD_PRELOAD=/lib/libc-opendir-hack.so"
177     sysexec("chroot %s %s %s" % (path, preload, cmd), log)
178
179
180 def sysexec_chroot_noerr( path, cmd, log= None ):
181     """
182     same as sysexec_chroot, but capture boot manager exceptions
183     """
184     try:
185         rc= 0
186         rc= syexec_chroot( cmd, log )
187     except BootManagerException, e:
188         pass
189
190     return rc
191
192
193 def sysexec_noerr( cmd, log= None ):
194     """
195     same as sysexec, but capture boot manager exceptions
196     """
197     try:
198         rc= 0
199         rc= sysexec( cmd, log )
200     except BootManagerException, e:
201         pass
202
203     return rc
204
205
206
207 def chdir( dir ):
208     """
209     change to a directory, return 1 if successful, a BootManagerException if failure
210     """
211     try:
212         os.chdir( dir )
213     except OSError:
214         raise BootManagerException, "Unable to change to directory: %s" % dir
215
216     return 1
217
218
219
220 def removefile( filepath ):
221     """
222     removes a file, return 1 if successful, 0 if failure
223     """
224     try:
225         os.remove( filepath )
226     except OSError:
227         raise BootManagerException, "Unable to remove file: %s" % filepath
228
229     return 1
230
231
232
233 # from: http://forums.devshed.com/archive/t-51149/
234 #              Ethernet-card-address-Through-Python-or-C
235
236 def hexy(n):
237     return "%02x" % (ord(n))
238
239 def get_mac_from_interface(ifname):
240     """
241     given a device name, like eth0, return its mac_address.
242     return None if the device doesn't exist.
243     """
244     
245     SIOCGIFHWADDR = 0x8927 # magic number
246
247     s=socket.socket(socket.AF_INET,socket.SOCK_STREAM)
248     ifname = string.strip(ifname)
249     ifr = ifname + '\0'*(32-len(ifname))
250
251     try:
252         r= fcntl.ioctl(s.fileno(),SIOCGIFHWADDR,ifr)
253         addr = map(hexy,r[18:24])
254         ret = (':'.join(map(str, addr)))
255     except IOError, e:
256         ret = None
257         
258     return ret
259