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