svn:keywords
[bootmanager.git] / source / steps / CheckHardwareRequirements.py
1 #!/usr/bin/python
2 #
3 # $Id$
4 # $URL$
5 #
6 # Copyright (c) 2003 Intel Corporation
7 # All rights reserved.
8 #
9 # Copyright (c) 2004-2006 The Trustees of Princeton University
10 # All rights reserved.
11 # expected /proc/partitions format
12
13 import os
14 import popen2
15 import string
16
17 import systeminfo
18 from Exceptions import *
19 import utils
20 import notify_messages
21 import BootAPI
22
23
24 def Run( vars, log ):
25     """
26     Make sure the hardware we are running on is sufficient for
27     the PlanetLab OS to be installed on. In the process, identify
28     the list of block devices that may be used for a node installation,
29     and identify the cdrom device that we booted off of.
30
31     Return 1 if requiremenst met, 0 if requirements not met. Raise
32     BootManagerException if any problems occur that prevent the requirements
33     from being checked.
34
35     Expect the following variables from the store:
36
37     MINIMUM_MEMORY          minimum amount of memory in kb required
38                             for install
39     NODE_ID                 the node_id from the database for this node
40     MINIMUM_DISK_SIZE       any disks smaller than this size, in GB, are not used
41     TOTAL_MINIMUM_DISK_SIZE total disk size in GB, if all usable disks
42                             meet this number, there isn't enough disk space for
43                             this node to be usable after install
44     SKIP_HARDWARE_REQUIREMENT_CHECK
45                             If set, don't check if minimum requirements are met
46     Sets the following variables:
47     INSTALL_BLOCK_DEVICES    list of block devices to install onto
48     """
49
50     log.write( "\n\nStep: Checking if hardware requirements met.\n" )        
51         
52     try:
53         MINIMUM_MEMORY= int(vars["MINIMUM_MEMORY"])
54         if MINIMUM_MEMORY == "":
55             raise ValueError, "MINIMUM_MEMORY"
56
57         NODE_ID= vars["NODE_ID"]
58         if NODE_ID == "":
59             raise ValueError("NODE_ID")
60
61         MINIMUM_DISK_SIZE= int(vars["MINIMUM_DISK_SIZE"])
62
63         TOTAL_MINIMUM_DISK_SIZE= \
64                    int(vars["TOTAL_MINIMUM_DISK_SIZE"])
65
66         SKIP_HARDWARE_REQUIREMENT_CHECK= \
67                    int(vars["SKIP_HARDWARE_REQUIREMENT_CHECK"])
68         
69     except KeyError, var:
70         raise BootManagerException, \
71               "Missing variable in install store: %s" % var
72     except ValueError, var:
73         raise BootManagerException, \
74               "Variable in install store blank, shouldn't be: %s" % var
75
76     # lets see if we have enough memory to run
77     log.write( "Checking for available memory.\n" )
78
79     total_mem= systeminfo.get_total_phsyical_mem(vars, log)
80     if total_mem is None:
81         raise BootManagerException, "Unable to read total physical memory"
82         
83     if total_mem < MINIMUM_MEMORY:
84         if not SKIP_HARDWARE_REQUIREMENT_CHECK:
85             log.write( "Insufficient memory to run node: %s kb\n" % total_mem )
86             log.write( "Required memory: %s kb\n" % MINIMUM_MEMORY )
87
88             include_pis= 0
89             include_techs= 1
90             include_support= 0
91             
92             sent= 0
93             try:
94                 sent= BootAPI.call_api_function( vars, "BootNotifyOwners",
95                                          (notify_messages.MSG_INSUFFICIENT_MEMORY,
96                                           include_pis,
97                                           include_techs,
98                                           include_support) )
99             except BootManagerException, e:
100                 log.write( "Call to BootNotifyOwners failed: %s.\n" % e )
101                 
102             if sent == 0:
103                 log.write( "Unable to notify site contacts of problem.\n" )
104             else:
105                 log.write( "Notified contacts of problem.\n" )
106                 
107             return 0
108         else:
109             log.write( "Memory requirements not met, but running anyway: %s kb\n"
110                        % total_mem )
111     else:
112         log.write( "Looks like we have enough memory: %s kb\n" % total_mem )
113
114
115
116     # get a list of block devices to attempt to install on
117     # (may include cdrom devices)
118     install_devices= systeminfo.get_block_device_list(vars, log)
119
120     # save the list of block devices in the log
121     log.write( "Detected block devices:\n" )
122     log.write( repr(install_devices) + "\n" )
123
124     if not install_devices or len(install_devices) == 0:
125         log.write( "No block devices detected.\n" )
126         
127         include_pis= 0
128         include_techs= 1
129         include_support= 0
130         
131         sent= 0
132         try:
133             sent= BootAPI.call_api_function( vars, "BootNotifyOwners",
134                                        (notify_messages.MSG_INSUFFICIENT_DISK,
135                                         include_pis,
136                                         include_techs,
137                                         include_support) )
138         except BootManagerException, e:
139             log.write( "Call to BootNotifyOwners failed: %s.\n" % e )
140             
141         if sent == 0:
142             log.write( "Unable to notify site contacts of problem.\n" )
143
144         return 0
145
146     # now, lets remove any block devices we know won't work (readonly,cdroms),
147     # or could be other writable removable disks (usb keychains, zip disks, etc)
148     # i'm not aware of anything that helps with the latter test, so,
149     # what we'll probably do is simply not use any block device below
150     # some size threshold (set in installstore)
151
152     # also, keep track of the total size for all devices that appear usable
153     total_size= 0
154
155     for device in install_devices.keys():
156
157         (major,minor,blocks,gb_size,readonly)= install_devices[device]
158         
159         # if the device string starts with
160         # planetlab or dm- (device mapper), ignore it (could be old lvm setup)
161         if device[:14] == "/dev/planetlab" or device[:8] == "/dev/dm-":
162             del install_devices[device]
163             continue
164
165         if gb_size < MINIMUM_DISK_SIZE:
166             log.write( "Device is too small to use: %s \n(appears" \
167                            " to be %4.2f GB)\n" % (device,gb_size) )
168             try:
169                 del install_devices[device]
170             except KeyError, e:
171                 pass
172             continue
173
174         if readonly:
175             log.write( "Device is readonly, not using: %s\n" % device )
176             try:
177                 del install_devices[device]
178             except KeyError, e:
179                 pass
180             continue
181             
182         # add this sector count to the total count of usable
183         # sectors we've found.
184         total_size= total_size + gb_size
185
186
187     if len(install_devices) == 0:
188         log.write( "No suitable block devices found for install.\n" )
189
190         include_pis= 0
191         include_techs= 1
192         include_support= 0
193         
194         sent= 0
195         try:
196             sent= BootAPI.call_api_function( vars, "BootNotifyOwners",
197                                        (notify_messages.MSG_INSUFFICIENT_DISK,
198                                         include_pis,
199                                         include_techs,
200                                         include_support) )
201         except BootManagerException, e:
202             log.write( "Call to BootNotifyOwners failed: %s.\n" % e )
203             
204         if sent == 0:
205             log.write( "Unable to notify site contacts of problem.\n" )
206
207         return 0
208
209
210     # show the devices we found that are usable
211     log.write( "Usable block devices:\n" )
212     log.write( repr(install_devices.keys()) + "\n" )
213
214     # save the list of devices for the following steps
215     vars["INSTALL_BLOCK_DEVICES"]= install_devices.keys()
216
217
218     # ensure the total disk size is large enough. if
219     # not, we need to email the tech contacts the problem, and
220     # put the node into debug mode.
221     if total_size < TOTAL_MINIMUM_DISK_SIZE:
222         if not SKIP_HARDWARE_REQUIREMENT_CHECK:
223             log.write( "The total usable disk size of all disks is " \
224                        "insufficient to be usable as a PlanetLab node.\n" )
225             include_pis= 0
226             include_techs= 1
227             include_support= 0
228             
229             sent= 0
230             try:
231                 sent= BootAPI.call_api_function( vars, "BootNotifyOwners",
232                                             (notify_messages.MSG_INSUFFICIENT_DISK,
233                                              include_pis,
234                                              include_techs,
235                                              include_support) )
236             except BootManagerException, e:
237                 log.write( "Call to BootNotifyOwners failed: %s.\n" % e )
238             
239             if sent == 0:
240                 log.write( "Unable to notify site contacts of problem.\n" )
241
242             return 0
243         
244         else:
245             log.write( "The total usable disk size of all disks is " \
246                        "insufficient, but running anyway.\n" )
247             
248     log.write( "Total size for all usable block devices: %4.2f GB\n" % total_size )
249
250     return 1