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