* improve availability - reliability : start a fallback sshd very early in the bm...
[bootmanager.git] / source / steps / CheckForNewDisks.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 import string
10
11 import InstallPartitionDisks
12 from Exceptions import *
13 import systeminfo
14 import utils
15 import os
16
17
18 def Run( vars, log ):
19     """
20     Find any new large block devices we can add to the vservers volume group
21     
22     Expect the following variables to be set:
23     SYSIMG_PATH          the path where the system image will be mounted
24     MINIMUM_DISK_SIZE       any disks smaller than this size, in GB, are not used
25     
26     Set the following variables upon successfully running:
27     ROOT_MOUNTED             the node root file system is mounted
28     """
29
30     log.write( "\n\nStep: Checking for unused disks to add to LVM.\n" )
31
32     # make sure we have the variables we need
33     try:
34         SYSIMG_PATH= vars["SYSIMG_PATH"]
35         if SYSIMG_PATH == "":
36             raise ValueError, "SYSIMG_PATH"
37
38         MINIMUM_DISK_SIZE= int(vars["MINIMUM_DISK_SIZE"])
39
40         PARTITIONS= vars["PARTITIONS"]
41         if PARTITIONS == None:
42             raise ValueError, "PARTITIONS"
43         
44     except KeyError, var:
45         raise BootManagerException, "Missing variable in vars: %s\n" % var
46     except ValueError, var:
47         raise BootManagerException, "Variable in vars, shouldn't be: %s\n" % var
48
49     all_devices= systeminfo.get_block_device_list(vars, log)
50     
51     # will contain the new devices to add to the volume group
52     new_devices= []
53
54     # total amount of new space in gb
55     extended_gb_size= 0
56     
57     for device in all_devices.keys():
58
59         (major,minor,blocks,gb_size,readonly)= all_devices[device]
60
61         if device[:14] == "/dev/planetlab":
62             log.write( "Skipping device %s in volume group.\n" % device )
63             continue
64
65         if readonly:
66             log.write( "Skipping read only device %s\n" % device )
67             continue
68
69         if gb_size < MINIMUM_DISK_SIZE:
70             log.write( "Skipping too small device %s (%4.2f)\n" %
71                        (device,gb_size) )
72             continue
73
74         log.write( "Checking device %s to see if it is part " \
75                    "of the volume group.\n" % device )
76
77         # this is the lvm partition, if it exists on that device
78         lvm_partition= InstallPartitionDisks.get_partition_path_from_device( device, vars, log )
79         cmd = "pvdisplay %s | grep -q 'planetlab'" % lvm_partition
80         already_added= utils.sysexec_noerr(cmd, log)
81
82         if already_added:
83             log.write( "It appears %s is part of the volume group, continuing.\n" %
84                        device )
85             continue
86
87         # just to be extra paranoid, ignore the device if it already has
88         # an lvm partition on it (new disks won't have this, and that is
89         # what this code is for, so it should be ok).
90         cmd = "sfdisk -l %s | grep -q 'Linux LVM'" % device 
91         has_lvm= utils.sysexec_noerr(cmd, log)
92         if has_lvm:
93             log.write( "It appears %s has lvm already setup on it.\n" % device)
94             paranoid = False
95             if paranoid:
96                 log.write("To paranoid to add %s to vservers lvm.\n" % device)
97                 continue
98         
99         log.write( "Attempting to add %s to the volume group\n" % device )
100
101         if not InstallPartitionDisks.single_partition_device( device, vars, log ):
102             log.write( "Unable to partition %s, not using it.\n" % device )
103             continue
104
105         log.write( "Successfully initialized %s\n" % device )
106
107         part_path= InstallPartitionDisks.get_partition_path_from_device( device,
108                                                                          vars, log )
109         if not InstallPartitionDisks.create_lvm_physical_volume( part_path,
110                                                                  vars, log ):
111             log.write( "Unable to create lvm physical volume %s, not using it.\n" %
112                        part_path )
113             continue
114
115         log.write( "Adding %s to list of devices to add to " \
116                    "planetlab volume group.\n" % device )
117
118         extended_gb_size= extended_gb_size + gb_size
119         new_devices.append( part_path )
120         
121
122     if len(new_devices) > 0:
123
124         log.write( "Extending planetlab volume group.\n" )
125         
126         log.write( "Unmounting disks.\n" )
127         try:
128             # backwards compat, though, we should never hit this case post PL 3.2
129             os.stat("%s/rcfs/taskclass"%SYSIMG_PATH)
130             utils.sysexec_noerr( "chroot %s umount /rcfs" % SYSIMG_PATH, log )
131         except OSError, e:
132             pass
133
134         # umount in order to extend disk size
135         utils.sysexec_noerr( "umount %s/proc" % SYSIMG_PATH, log )
136         utils.sysexec_noerr( "umount %s/vservers" % SYSIMG_PATH, log )
137         utils.sysexec_noerr( "umount %s" % SYSIMG_PATH, log )
138         utils.sysexec( "vgchange -an", log )
139         
140         vars['ROOT_MOUNTED']= 0
141
142         while True:
143             cmd = "vgextend planetlab %s" % string.join(new_devices," ")
144             if not utils.sysexec_noerr( cmd, log ):
145                 log.write( "Failed to add physical volumes %s to " \
146                            "volume group, continuing.\n" % string.join(new_devices," "))
147                 res = 1
148                 break
149             
150             # now, get the number of unused extents, and extend the vserver
151             # logical volume by that much.
152             remaining_extents= \
153                InstallPartitionDisks.get_remaining_extents_on_vg( vars, log )
154
155             log.write( "Extending vservers logical volume.\n" )
156             utils.sysexec( "vgchange -ay", log )
157             cmd = "lvextend -l +%s %s" % (remaining_extents, PARTITIONS["vservers"])
158             if not utils.sysexec_noerr(cmd, log):
159                 log.write( "Failed to extend vservers logical volume, continuing\n" )
160                 res = 1
161                 break
162
163             log.write( "making the ext3 filesystem match new logical volume size.\n" )
164
165             vars['ROOT_MOUNTED']= 1
166             cmd = "mount %s %s" % (PARTITIONS["root"],SYSIMG_PATH)
167             utils.sysexec_noerr( cmd, log )
168             cmd = "mount %s %s/vservers" % \
169                 (PARTITIONS["vservers"],SYSIMG_PATH)
170             utils.sysexec_noerr( cmd, log )
171             cmd = "ext2online %s/vservers" % SYSIMG_PATH
172             resize = utils.sysexec_noerr(cmd,log)
173             utils.sysexec_noerr( "umount %s/vservers" % SYSIMG_PATH, log )
174             utils.sysexec_noerr( "umount %s" % SYSIMG_PATH, log )
175             vars['ROOT_MOUNTED']= 0
176
177             utils.sysexec( "vgchange -an", log )
178
179             if not resize:
180                 log.write( "Failed to resize vservers partition, continuing.\n" )
181                 res = 1
182                 break
183             else:
184                 log.write( "Extended vservers partition by %4.2f GB\n" %
185                            extended_gb_size )
186                 res = 1
187                 break
188
189     else:
190         log.write( "No new disk devices to add to volume group.\n" )
191         res = 1
192
193     return res