Detangled steps. No step makes calls into another step.
[bootmanager.git] / source / steps / InitializeBootManager.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
9 import os
10 import xmlrpclib
11 import socket
12 import string
13
14 from Exceptions import *
15 import utils
16
17
18 # locations of boot os version files
19 BOOT_VERSION_2X_FILE='/usr/bootme/ID'
20 BOOT_VERSION_3X_FILE='/pl_version'
21
22 # minimium version of the boot os we need to run, as a (major,minor) tuple
23 MINIMUM_BOOT_VERSION= (2,0)
24
25 # minimum version of python required to run the boot manager
26 MINIMUM_PYTHON_VERSION= (2,2,0)
27
28
29 def Run( vars, log ):
30     """
31     Setup the boot manager so it can run, do any extra necessary
32     hardware setup (to fix old cd problems)
33
34     Sets the following variables:
35     PARTITIONS        A dictionary of generic partition types and their
36                       associated devices.
37     BOOT_CD_VERSION   A two number tuple of the boot cd version
38     """
39
40     log.write( "\n\nStep: Initializing the BootManager.\n" )
41
42     # define the basic partition paths
43     PARTITIONS= {}
44     PARTITIONS["root"]= "/dev/planetlab/root"
45     PARTITIONS["swap"]= "/dev/planetlab/swap"
46     PARTITIONS["vservers"]= "/dev/planetlab/vservers"
47     # Linux 2.6 mounts LVM with device mapper
48     PARTITIONS["mapper-root"]= "/dev/mapper/planetlab-root"
49     PARTITIONS["mapper-swap"]= "/dev/mapper/planetlab-swap"
50     PARTITIONS["mapper-vservers"]= "/dev/mapper/planetlab-vservers"
51     vars["PARTITIONS"]= PARTITIONS
52
53     log.write( "Opening connection to API server\n" )
54     try:
55         api_inst= xmlrpclib.Server( vars['BOOT_API_SERVER'], verbose=0 )
56     except KeyError, e:
57         raise BootManagerException, \
58               "configuration file does not specify API server URL"
59
60     vars['API_SERVER_INST']= api_inst
61
62     if not __check_boot_version( vars, log ):
63         raise BootManagerException, \
64               "Boot CD version insufficient to run the Boot Manager"
65     else:
66         log.write( "Running on boot cd version: %s\n" %
67                    str(vars['BOOT_CD_VERSION']) )
68
69     BOOT_CD_VERSION= vars['BOOT_CD_VERSION']
70     
71     # old cds need extra modules loaded for compaq smart array
72     if BOOT_CD_VERSION[0] == 2:
73
74         has_smartarray= utils.sysexec_noerr(
75             'lspci | egrep "0e11:b178|0e11:4070|0e11:4080|0e11:4082|0e11:4083"')
76         
77         if has_smartarray:
78             log.write( "Loading support for Compaq smart array\n" )
79             utils.sysexec_noerr( "modprobe cciss", log )
80             _create_cciss_dev_entries()
81             
82
83         has_fusion= utils.sysexec_noerr('lspci | egrep "1000:0030"')
84         
85         if has_fusion:
86             log.write( "Loading support for Fusion MPT SCSI controllers\n" )
87             utils.sysexec_noerr( "modprobe mptscsih", log )
88
89     # for anything that needs to know we are running under the boot cd and
90     # not the runtime os
91     os.environ['PL_BOOTCD']= "1"
92         
93     return 1
94
95
96
97 def __check_boot_version( vars, log ):
98     """
99     identify which version of the boot os we are running on, and whether
100     or not we can run at all on the given version. later, this will be
101     used to identify extra packages to download to enable the boot manager
102     to run on any supported version.
103
104     2.x cds have the version file in /usr/bootme/ID, which looked like:
105     'PlanetLab BootCD v2.0.3'
106
107     3.x cds have the version file in /pl_version, which lookes like:
108     'PlanetLab BootCD 3.0-beta0.3'
109
110     All current known version strings that we support:
111     PlanetLab BootCD 3.0
112     PlanetLab BootCD 3.0-beta0.1
113     PlanetLab BootCD 3.0-beta0.3
114     PlanetLab BootCD v2.0
115     PlanetLab BootCD v2.0.1
116     PlanetLab BootCD v2.0.2
117     PlanetLab BootCD v2.0.3
118
119     Returns 1 if the boot os version is identified and will work
120     to run the boot manager. Two class variables are set:
121     BOOT_OS_MAJOR_VERSION
122     BOOT_OS_MINOR_VERSION
123     version strings with three parts parts to the version ignore the
124     middle number (so 2.0.3 is major 2, minor 3)
125
126     Returns 0 if the boot os is insufficient to run the boot manager
127     """
128
129     try:
130         # check for a 3.x version first
131         version_file= file(BOOT_VERSION_3X_FILE,'r')
132         full_version= string.strip(version_file.read())
133         version_file.close()
134
135         version_parts= string.split(full_version)
136         version= version_parts[-1]
137
138         version_numbers= string.split(version,".")
139         if len(version_numbers) == 2:
140             BOOT_OS_MAJOR_VERSION= int(version_numbers[0])
141             BOOT_OS_MINOR_VERSION= int(version_numbers[1])
142         else:
143             # for 3.x cds, if there are more than two parts
144             # separated by a ., its one of the beta cds.
145             # hardcode as a 3.0 cd
146             BOOT_OS_MAJOR_VERSION= 3
147             BOOT_OS_MINOR_VERSION= 0
148
149         vars['BOOT_CD_VERSION']= (BOOT_OS_MAJOR_VERSION,BOOT_OS_MINOR_VERSION)
150         
151         if (BOOT_OS_MAJOR_VERSION,BOOT_OS_MINOR_VERSION) >= \
152                MINIMUM_BOOT_VERSION:
153             return 1
154
155     except IOError, e:
156         pass
157     except IndexError, e:
158         pass
159     except TypeError, e:
160         pass
161
162
163     try:
164         # check for a 2.x version first
165         version_file= file(BOOT_VERSION_2X_FILE,'r')
166         full_version= string.strip(version_file.read())
167         version_file.close()
168
169         version_parts= string.split(full_version)
170         version= version_parts[-1]
171         if version[0] == 'v':
172             version= version[1:]
173
174         version_numbers= string.split(version,".")
175         if len(version_numbers) == 2:
176             BOOT_OS_MAJOR_VERSION= int(version_numbers[0])
177             BOOT_OS_MINOR_VERSION= int(version_numbers[1])
178         else:
179             BOOT_OS_MAJOR_VERSION= int(version_numbers[0])
180             BOOT_OS_MINOR_VERSION= int(version_numbers[2])
181
182         vars['BOOT_CD_VERSION']= (BOOT_OS_MAJOR_VERSION,BOOT_OS_MINOR_VERSION)
183
184         if (BOOT_OS_MAJOR_VERSION,BOOT_OS_MINOR_VERSION) >= \
185            MINIMUM_BOOT_VERSION:
186             return 1
187
188     except IOError, e:
189         pass
190     except IndexError, e:
191         pass
192     except TypeError, e:
193         pass
194
195
196     return 0
197
198
199
200 def _create_cciss_dev_entries():
201     def mkccissnod(dev,node):
202         dev = dev + " b 104 %d" % (node)
203         cmd = "mknod /dev/cciss/%s" %dev
204         utils.sysexec_noerr(cmd)
205         node = node + 1
206         return node
207
208     node = 0
209     for i in range(0,16):
210         dev = "c0d%d" % i
211         node = mkccissnod(dev,node)
212         for j in range(1,16):
213             subdev = dev + "p%d" % j
214             node = mkccissnod(subdev,node)