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