Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(131)

Side by Side Diff: client/tests/kvm/scripts/unattended.py

Issue 3554003: Merge remote branch 'cros/upstream' into tempbranch3 (Closed) Base URL: http://git.chromium.org/git/autotest.git
Patch Set: Created 10 years, 2 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « client/tests/kvm/kvm_vm.py ('k') | client/tests/kvm/scripts/virtio_guest.py » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 #!/usr/bin/python 1 #!/usr/bin/python
2 """ 2 """
3 Simple script to setup unattended installs on KVM guests. 3 Simple script to setup unattended installs on KVM guests.
4 """ 4 """
5 # -*- coding: utf-8 -*- 5 # -*- coding: utf-8 -*-
6 import os, sys, shutil, tempfile, re 6 import os, sys, shutil, tempfile, re, ConfigParser, glob, inspect
7 import common 7 import common
8 8
9 9
10 SCRIPT_DIR = os.path.dirname(sys.modules[__name__].__file__)
11 KVM_TEST_DIR = os.path.abspath(os.path.join(SCRIPT_DIR, ".."))
12
13
10 class SetupError(Exception): 14 class SetupError(Exception):
11 """ 15 """
12 Simple wrapper for the builtin Exception class. 16 Simple wrapper for the builtin Exception class.
13 """ 17 """
14 pass 18 pass
15 19
16 20
21 def find_command(cmd):
22 """
23 Searches for a command on common paths, error if it can't find it.
24
25 @param cmd: Command to be found.
26 """
27 for dir in ["/usr/local/sbin", "/usr/local/bin",
28 "/usr/sbin", "/usr/bin", "/sbin", "/bin"]:
29 file = os.path.join(dir, cmd)
30 if os.path.exists(file):
31 return file
32 raise ValueError('Missing command: %s' % cmd)
33
34
35 def run(cmd, info=None):
36 """
37 Run a command and throw an exception if it fails.
38 Optionally, you can provide additional contextual info.
39
40 @param cmd: Command string.
41 @param reason: Optional string that explains the context of the failure.
42
43 @raise: SetupError if command fails.
44 """
45 print "Running '%s'" % cmd
46 cmd_name = cmd.split(' ')[0]
47 find_command(cmd_name)
48 if os.system(cmd):
49 e_msg = 'Command failed: %s' % cmd
50 if info is not None:
51 e_msg += '. %s' % info
52 raise SetupError(e_msg)
53
54
55 def cleanup(dir):
56 """
57 If dir is a mountpoint, do what is possible to unmount it. Afterwards,
58 try to remove it.
59
60 @param dir: Directory to be cleaned up.
61 """
62 print "Cleaning up directory %s" % dir
63 if os.path.ismount(dir):
64 os.system('fuser -k %s' % dir)
65 run('umount %s' % dir, info='Could not unmount %s' % dir)
66 if os.path.isdir(dir):
67 shutil.rmtree(dir)
68
69
70 def clean_old_image(image):
71 """
72 Clean a leftover image file from previous processes. If it contains a
73 mounted file system, do the proper cleanup procedures.
74
75 @param image: Path to image to be cleaned up.
76 """
77 if os.path.exists(image):
78 mtab = open('/etc/mtab', 'r')
79 mtab_contents = mtab.read()
80 mtab.close()
81 if image in mtab_contents:
82 os.system('fuser -k %s' % image)
83 os.system('umount %s' % image)
84 os.remove(image)
85
86
87 class Disk(object):
88 """
89 Abstract class for Disk objects, with the common methods implemented.
90 """
91 def __init__(self):
92 self.path = None
93
94
95 def setup_answer_file(self, filename, contents):
96 answer_file = open(os.path.join(self.mount, filename), 'w')
97 answer_file.write(contents)
98 answer_file.close()
99
100
101 def copy_to(self, src):
102 dst = os.path.join(self.mount, os.path.basename(src))
103 if os.path.isdir(src):
104 shutil.copytree(src, dst)
105 elif os.path.isfile(src):
106 shutil.copyfile(src, dst)
107
108
109 def close(self):
110 os.chmod(self.path, 0755)
111 cleanup(self.mount)
112 print "Disk %s successfuly set" % self.path
113
114
115 class FloppyDisk(Disk):
116 """
117 Represents a 1.44 MB floppy disk. We can copy files to it, and setup it in
118 convenient ways.
119 """
120 def __init__(self, path):
121 print "Creating floppy unattended image %s" % path
122 try:
123 qemu_img_binary = os.environ['KVM_TEST_qemu_img_binary']
124 except KeyError:
125 qemu_img_binary = os.path.join(KVM_TEST_DIR, qemu_img_binary)
126 if not os.path.exists(qemu_img_binary):
127 raise SetupError('The qemu-img binary that is supposed to be used '
128 '(%s) does not exist. Please verify your '
129 'configuration' % qemu_img_binary)
130
131 self.mount = tempfile.mkdtemp(prefix='floppy_', dir='/tmp')
132 self.virtio_mount = None
133 self.path = path
134 clean_old_image(path)
135 if not os.path.isdir(os.path.dirname(path)):
136 os.makedirs(os.path.dirname(path))
137
138 try:
139 c_cmd = '%s create -f raw %s 1440k' % (qemu_img_binary, path)
140 run(c_cmd, info='Could not create floppy image')
141 f_cmd = 'mkfs.msdos -s 1 %s' % path
142 run(f_cmd, info='Error formatting floppy image')
143 m_cmd = 'mount -o loop,rw %s %s' % (path, self.mount)
144 run(m_cmd, info='Could not mount floppy image')
145 except:
146 cleanup(self.mount)
147
148
149 def _copy_virtio_drivers(self, virtio_floppy):
150 """
151 Copy the virtio drivers on the virtio floppy to the install floppy.
152
153 1) Mount the floppy containing the viostor drivers
154 2) Copy its contents to the root of the install floppy
155 """
156 virtio_mount = tempfile.mkdtemp(prefix='virtio_floppy_', dir='/tmp')
157
158 pwd = os.getcwd()
159 try:
160 m_cmd = 'mount -o loop %s %s' % (virtio_floppy, virtio_mount)
161 run(m_cmd, info='Could not mount virtio floppy driver')
162 os.chdir(virtio_mount)
163 path_list = glob.glob('*')
164 for path in path_list:
165 self.copy_to(path)
166 finally:
167 os.chdir(pwd)
168 cleanup(virtio_mount)
169
170
171 def setup_virtio_win2003(self, virtio_floppy, virtio_oemsetup_id):
172 """
173 Setup the install floppy with the virtio storage drivers, win2003 style.
174
175 Win2003 and WinXP depend on the file txtsetup.oem file to install
176 the virtio drivers from the floppy, which is a .ini file.
177 Process:
178
179 1) Copy the virtio drivers on the virtio floppy to the install floppy
180 2) Parse the ini file with config parser
181 3) Modify the identifier of the default session that is going to be
182 executed on the config parser object
183 4) Re-write the config file to the disk
184 """
185 self._copy_virtio_drivers(virtio_floppy)
186 txtsetup_oem = os.path.join(self.mount, 'txtsetup.oem')
187 if not os.path.isfile(txtsetup_oem):
188 raise SetupError('File txtsetup.oem not found on the install '
189 'floppy. Please verify if your floppy virtio '
190 'driver image has this file')
191 parser = ConfigParser.ConfigParser()
192 parser.read(txtsetup_oem)
193 if not parser.has_section('Defaults'):
194 raise SetupError('File txtsetup.oem does not have the session '
195 '"Defaults". Please check txtsetup.oem')
196 default_driver = parser.get('Defaults', 'SCSI')
197 if default_driver != virtio_oemsetup_id:
198 parser.set('Defaults', 'SCSI', virtio_oemsetup_id)
199 fp = open(txtsetup_oem, 'w')
200 parser.write(fp)
201 fp.close()
202
203
204 def setup_virtio_win2008(self, virtio_floppy):
205 """
206 Setup the install floppy with the virtio storage drivers, win2008 style.
207
208 Win2008, Vista and 7 require people to point out the path to the drivers
209 on the unattended file, so we just need to copy the drivers to the
210 driver floppy disk.
211 Process:
212
213 1) Copy the virtio drivers on the virtio floppy to the install floppy
214 """
215 self._copy_virtio_drivers(virtio_floppy)
216
217
218 class CdromDisk(Disk):
219 """
220 Represents a CDROM disk that we can master according to our needs.
221 """
222 def __init__(self, path):
223 print "Creating ISO unattended image %s" % path
224 self.mount = tempfile.mkdtemp(prefix='cdrom_unattended_', dir='/tmp')
225 self.path = path
226 clean_old_image(path)
227 if not os.path.isdir(os.path.dirname(path)):
228 os.makedirs(os.path.dirname(path))
229
230
231 def close(self):
232 g_cmd = ('mkisofs -o %s -max-iso9660-filenames '
233 '-relaxed-filenames -D --input-charset iso8859-1 '
234 '%s' % (self.path, self.mount))
235 run(g_cmd, info='Could not generate iso with answer file')
236
237 os.chmod(self.path, 0755)
238 cleanup(self.mount)
239 print "Disk %s successfuly set" % self.path
240
241
17 class UnattendedInstall(object): 242 class UnattendedInstall(object):
18 """ 243 """
19 Creates a floppy disk image that will contain a config file for unattended 244 Creates a floppy disk image that will contain a config file for unattended
20 OS install. Optionally, sets up a PXE install server using qemu built in 245 OS install. Optionally, sets up a PXE install server using qemu built in
21 TFTP and DHCP servers to install a particular operating system. The 246 TFTP and DHCP servers to install a particular operating system. The
22 parameters to the script are retrieved from environment variables. 247 parameters to the script are retrieved from environment variables.
23 """ 248 """
24 def __init__(self): 249 def __init__(self):
25 """ 250 """
26 Gets params from environment variables and sets class attributes. 251 Gets params from environment variables and sets class attributes.
27 """ 252 """
28 script_dir = os.path.dirname(sys.modules[__name__].__file__) 253 images_dir = os.path.join(KVM_TEST_DIR, 'images')
29 kvm_test_dir = os.path.abspath(os.path.join(script_dir, "..")) 254 self.deps_dir = os.path.join(KVM_TEST_DIR, 'deps')
30 images_dir = os.path.join(kvm_test_dir, 'images') 255 self.unattended_dir = os.path.join(KVM_TEST_DIR, 'unattended')
31 self.deps_dir = os.path.join(kvm_test_dir, 'deps')
32 self.unattended_dir = os.path.join(kvm_test_dir, 'unattended')
33 256
34 tftp_root = os.environ.get('KVM_TEST_tftp', '') 257 attributes = ['kernel_args', 'finish_program', 'cdrom_cd1',
35 if tftp_root: 258 'unattended_file', 'medium', 'url', 'kernel', 'initrd',
36 self.tftp_root = os.path.join(kvm_test_dir, tftp_root) 259 'nfs_server', 'nfs_dir', 'pxe_dir', 'pxe_image',
37 if not os.path.isdir(self.tftp_root): 260 'pxe_initrd', 'install_virtio', 'tftp',
38 os.makedirs(self.tftp_root) 261 'floppy', 'cdrom_unattended']
39 else: 262 for a in attributes:
40 self.tftp_root = tftp_root 263 self._setattr(a)
41 264
42 self.kernel_args = os.environ.get('KVM_TEST_kernel_args', '') 265 if self.install_virtio == 'yes':
43 self.finish_program= os.environ.get('KVM_TEST_finish_program', '') 266 v_attributes = ['virtio_floppy', 'virtio_storage_path',
44 cdrom_iso = os.environ.get('KVM_TEST_cdrom_cd1') 267 'virtio_network_path', 'virtio_oemsetup_id',
45 self.unattended_file = os.environ.get('KVM_TEST_unattended_file') 268 'virtio_network_installer']
269 for va in v_attributes:
270 self._setattr(va)
46 271
47 self.qemu_img_bin = os.environ.get('KVM_TEST_qemu_img_binary') 272 # Silly attribution just to calm pylint down...
48 if not os.path.isabs(self.qemu_img_bin): 273 self.tftp = self.tftp
49 self.qemu_img_bin = os.path.join(kvm_test_dir, self.qemu_img_bin) 274 if self.tftp:
50 self.cdrom_iso = os.path.join(kvm_test_dir, cdrom_iso) 275 self.tftp = os.path.join(KVM_TEST_DIR, self.tftp)
51 self.floppy_mount = tempfile.mkdtemp(prefix='floppy_', dir='/tmp') 276 if not os.path.isdir(self.tftp):
52 self.cdrom_mount = tempfile.mkdtemp(prefix='cdrom_', dir='/tmp') 277 os.makedirs(self.tftp)
53 self.nfs_mount = tempfile.mkdtemp(prefix='nfs_', dir='/tmp')
54 floppy_name = os.environ['KVM_TEST_floppy']
55 self.floppy_img = os.path.join(kvm_test_dir, floppy_name)
56 floppy_dir = os.path.dirname(self.floppy_img)
57 if not os.path.isdir(floppy_dir):
58 os.makedirs(floppy_dir)
59 278
60 self.pxe_dir = os.environ.get('KVM_TEST_pxe_dir', '') 279 self.cdrom_cd1 = os.path.join(KVM_TEST_DIR, self.cdrom_cd1)
61 self.pxe_image = os.environ.get('KVM_TEST_pxe_image', '') 280 self.cdrom_cd1_mount = tempfile.mkdtemp(prefix='cdrom_cd1_', dir='/tmp')
62 self.pxe_initrd = os.environ.get('KVM_TEST_pxe_initrd', '') 281 if self.medium == 'nfs':
282 self.nfs_mount = tempfile.mkdtemp(prefix='nfs_', dir='/tmp')
63 283
64 self.medium = os.environ.get('KVM_TEST_medium', '') 284 self.floppy = os.path.join(KVM_TEST_DIR, self.floppy)
65 self.url = os.environ.get('KVM_TEST_url', '') 285 if not os.path.isdir(os.path.dirname(self.floppy)):
66 self.kernel = os.environ.get('KVM_TEST_kernel', '') 286 os.makedirs(os.path.dirname(self.floppy))
67 self.initrd = os.environ.get('KVM_TEST_initrd', '') 287
68 self.nfs_server = os.environ.get('KVM_TEST_nfs_server', '') 288 self.image_path = KVM_TEST_DIR
69 self.nfs_dir = os.environ.get('KVM_TEST_nfs_dir', '')
70 self.image_path = kvm_test_dir
71 self.kernel_path = os.path.join(self.image_path, self.kernel) 289 self.kernel_path = os.path.join(self.image_path, self.kernel)
72 self.initrd_path = os.path.join(self.image_path, self.initrd) 290 self.initrd_path = os.path.join(self.image_path, self.initrd)
73 291
74 292
75 def create_boot_floppy(self): 293 def _setattr(self, key):
76 """ 294 """
77 Prepares a boot floppy by creating a floppy image file, mounting it and 295 Populate class attributes with contents of environment variables.
78 copying an answer file (kickstarts for RH based distros, answer files 296
79 for windows) to it. After that the image is umounted. 297 Example: KVM_TEST_medium will populate self.medium.
298
299 @param key: Name of the class attribute we desire to have.
80 """ 300 """
81 print "Creating boot floppy" 301 env_name = 'KVM_TEST_%s' % key
302 value = os.environ.get(env_name, '')
303 setattr(self, key, value)
82 304
83 if os.path.exists(self.floppy_img):
84 os.remove(self.floppy_img)
85 305
86 c_cmd = '%s create -f raw %s 1440k' % (self.qemu_img_bin, 306 def render_answer_file(self):
87 self.floppy_img) 307 # Replace KVM_TEST_CDKEY (in the unattended file) with the cdkey
88 if os.system(c_cmd): 308 # provided for this test and replace the KVM_TEST_MEDIUM with
89 raise SetupError('Could not create floppy image.') 309 # the tree url or nfs address provided for this test.
310 unattended_contents = open(self.unattended_file).read()
311 dummy_cdkey_re = r'\bKVM_TEST_CDKEY\b'
312 real_cdkey = os.environ.get('KVM_TEST_cdkey')
313 if re.search(dummy_cdkey_re, unattended_contents):
314 if real_cdkey:
315 unattended_contents = re.sub(dummy_cdkey_re, real_cdkey,
316 unattended_contents)
317 else:
318 print ("WARNING: 'cdkey' required but not specified for "
319 "this unattended installation")
90 320
91 f_cmd = 'mkfs.msdos -s 1 %s' % self.floppy_img 321 dummy_medium_re = r'\bKVM_TEST_MEDIUM\b'
92 if os.system(f_cmd): 322 if self.medium == "cdrom":
93 raise SetupError('Error formatting floppy image.') 323 content = "cdrom"
324 elif self.medium == "url":
325 content = "url --url %s" % self.url
326 elif self.medium == "nfs":
327 content = "nfs --server=%s --dir=%s" % (self.nfs_server,
328 self.nfs_dir)
329 else:
330 raise SetupError("Unexpected installation medium %s" % self.url)
94 331
95 try: 332 unattended_contents = re.sub(dummy_medium_re, content,
96 m_cmd = 'mount -o loop %s %s' % (self.floppy_img, self.floppy_mount) 333 unattended_contents)
97 if os.system(m_cmd):
98 raise SetupError('Could not mount floppy image.')
99 334
100 if self.unattended_file.endswith('.sif'): 335 def replace_virtio_key(contents, dummy_re, env):
101 dest_fname = 'winnt.sif' 336 """
102 setup_file = 'winnt.bat' 337 Replace a virtio dummy string with contents.
103 setup_file_path = os.path.join(self.unattended_dir, setup_file) 338
104 setup_file_dest = os.path.join(self.floppy_mount, setup_file) 339 If install_virtio is not set, replace it with a dummy string.
105 shutil.copyfile(setup_file_path, setup_file_dest) 340
106 elif self.unattended_file.endswith('.ks'): 341 @param contents: Contents of the unattended file
107 # Red Hat kickstart install 342 @param dummy_re: Regular expression used to search on the.
108 dest_fname = 'ks.cfg' 343 unattended file contents.
109 elif self.unattended_file.endswith('.xml'): 344 @param env: Name of the environment variable.
110 if self.tftp_root is '': 345 """
111 # Windows unattended install 346 dummy_path = "C:"
112 dest_fname = "autounattend.xml" 347 driver = os.environ.get(env, '')
348
349 if re.search(dummy_re, contents):
350 if self.install_virtio == "yes":
351 if driver.endswith("msi"):
352 driver = 'msiexec /passive /package ' + driver
353 else:
354 try:
355 # Let's escape windows style paths properly
356 drive, path = driver.split(":")
357 driver = drive + ":" + re.escape(path)
358 except:
359 pass
360 contents = re.sub(dummy_re, driver, contents)
113 else: 361 else:
114 # SUSE autoyast install 362 contents = re.sub(dummy_re, dummy_path, contents)
115 dest_fname = "autoinst.xml" 363 return contents
116 364
117 dest = os.path.join(self.floppy_mount, dest_fname) 365 vdict = {r'\bKVM_TEST_STORAGE_DRIVER_PATH\b':
366 'KVM_TEST_virtio_storage_path',
367 r'\bKVM_TEST_NETWORK_DRIVER_PATH\b':
368 'KVM_TEST_virtio_network_path',
369 r'\bKVM_TEST_VIRTIO_NETWORK_INSTALLER\b':
370 'KVM_TEST_virtio_network_installer_path'}
118 371
119 # Replace KVM_TEST_CDKEY (in the unattended file) with the cdkey 372 for vkey in vdict:
120 # provided for this test and replace the KVM_TEST_MEDIUM with 373 unattended_contents = replace_virtio_key(unattended_contents,
121 # the tree url or nfs address provided for this test. 374 vkey, vdict[vkey])
122 unattended_contents = open(self.unattended_file).read() 375
123 dummy_cdkey_re = r'\bKVM_TEST_CDKEY\b' 376 print "Unattended install contents:"
124 real_cdkey = os.environ.get('KVM_TEST_cdkey') 377 print unattended_contents
125 if re.search(dummy_cdkey_re, unattended_contents): 378 return unattended_contents
126 if real_cdkey: 379
127 unattended_contents = re.sub(dummy_cdkey_re, real_cdkey, 380
128 unattended_contents) 381 def setup_boot_disk(self):
382 answer_contents = self.render_answer_file()
383
384 if self.unattended_file.endswith('.sif'):
385 dest_fname = 'winnt.sif'
386 setup_file = 'winnt.bat'
387 boot_disk = FloppyDisk(self.floppy)
388 boot_disk.setup_answer_file(dest_fname, answer_contents)
389 setup_file_path = os.path.join(self.unattended_dir, setup_file)
390 boot_disk.copy_to(setup_file_path)
391 if self.install_virtio == "yes":
392 boot_disk.setup_virtio_win2003(self.virtio_floppy,
393 self.virtio_oemsetup_id)
394 boot_disk.copy_to(self.finish_program)
395
396 elif self.unattended_file.endswith('.ks'):
397 # Red Hat kickstart install
398 dest_fname = 'ks.cfg'
399 if self.cdrom_unattended:
400 boot_disk = CdromDisk(self.cdrom_unattended)
401 elif self.floppy:
402 boot_disk = FloppyDisk(self.floppy)
403 else:
404 raise SetupError("Neither cdrom_unattended nor floppy set "
405 "on the config file, please verify")
406 boot_disk.setup_answer_file(dest_fname, answer_contents)
407
408 elif self.unattended_file.endswith('.xml'):
409 if self.tftp:
410 # SUSE autoyast install
411 dest_fname = "autoinst.xml"
412 if self.cdrom_unattended:
413 boot_disk = CdromDisk(self.cdrom_unattended)
414 elif self.floppy:
415 boot_disk = FloppyDisk(self.floppy)
129 else: 416 else:
130 print ("WARNING: 'cdkey' required but not specified for " 417 raise SetupError("Neither cdrom_unattended nor floppy set "
131 "this unattended installation") 418 "on the config file, please verify")
419 boot_disk.setup_answer_file(dest_fname, answer_contents)
132 420
133 dummy_re = r'\bKVM_TEST_MEDIUM\b'
134 if self.medium == "cdrom":
135 content = "cdrom"
136 elif self.medium == "url":
137 content = "url --url %s" % self.url
138 elif self.medium == "nfs":
139 content = "nfs --server=%s --dir=%s" % (self.nfs_server, self.nf s_dir)
140 else: 421 else:
141 raise SetupError("Unexpected installation medium %s" % self.url) 422 # Windows unattended install
423 dest_fname = "autounattend.xml"
424 boot_disk = FloppyDisk(self.floppy)
425 boot_disk.setup_answer_file(dest_fname, answer_contents)
426 if self.install_virtio == "yes":
427 boot_disk.setup_virtio_win2008(self.virtio_floppy)
428 boot_disk.copy_to(self.finish_program)
142 429
143 unattended_contents = re.sub(dummy_re, content, unattended_contents) 430 else:
431 raise SetupError('Unknown answer file %s' %
432 self.unattended_file)
144 433
145 print 434 boot_disk.close()
146 print "Unattended install %s contents:" % dest_fname
147 print unattended_contents
148 # Write the unattended file contents to 'dest'
149 open(dest, 'w').write(unattended_contents)
150
151 if self.finish_program:
152 dest_fname = os.path.basename(self.finish_program)
153 dest = os.path.join(self.floppy_mount, dest_fname)
154 shutil.copyfile(self.finish_program, dest)
155
156 finally:
157 u_cmd = 'umount %s' % self.floppy_mount
158 if os.system(u_cmd):
159 raise SetupError('Could not unmount floppy at %s.' %
160 self.floppy_mount)
161 self.cleanup(self.floppy_mount)
162
163 os.chmod(self.floppy_img, 0755)
164
165 print "Boot floppy created successfuly"
166 435
167 436
168 def setup_pxe_boot(self): 437 def setup_pxe_boot(self):
169 """ 438 """
170 Sets up a PXE boot environment using the built in qemu TFTP server. 439 Sets up a PXE boot environment using the built in qemu TFTP server.
171 Copies the PXE Linux bootloader pxelinux.0 from the host (needs the 440 Copies the PXE Linux bootloader pxelinux.0 from the host (needs the
172 pxelinux package or equivalent for your distro), and vmlinuz and 441 pxelinux package or equivalent for your distro), and vmlinuz and
173 initrd.img files from the CD to a directory that qemu will serve trough 442 initrd.img files from the CD to a directory that qemu will serve trough
174 TFTP to the VM. 443 TFTP to the VM.
175 """ 444 """
176 print "Setting up PXE boot using TFTP root %s" % self.tftp_root 445 print "Setting up PXE boot using TFTP root %s" % self.tftp
177 446
178 pxe_file = None 447 pxe_file = None
179 pxe_paths = ['/usr/lib/syslinux/pxelinux.0', 448 pxe_paths = ['/usr/lib/syslinux/pxelinux.0',
180 '/usr/share/syslinux/pxelinux.0'] 449 '/usr/share/syslinux/pxelinux.0']
181 for path in pxe_paths: 450 for path in pxe_paths:
182 if os.path.isfile(path): 451 if os.path.isfile(path):
183 pxe_file = path 452 pxe_file = path
184 break 453 break
185 454
186 if not pxe_file: 455 if not pxe_file:
187 raise SetupError('Cannot find PXE boot loader pxelinux.0. Make ' 456 raise SetupError('Cannot find PXE boot loader pxelinux.0. Make '
188 'sure pxelinux or equivalent package for your ' 457 'sure pxelinux or equivalent package for your '
189 'distro is installed.') 458 'distro is installed.')
190 459
191 pxe_dest = os.path.join(self.tftp_root, 'pxelinux.0') 460 pxe_dest = os.path.join(self.tftp, 'pxelinux.0')
192 shutil.copyfile(pxe_file, pxe_dest) 461 shutil.copyfile(pxe_file, pxe_dest)
193 462
194 try: 463 try:
195 m_cmd = 'mount -t iso9660 -v -o loop,ro %s %s' % (self.cdrom_iso, 464 m_cmd = ('mount -t iso9660 -v -o loop,ro %s %s' %
196 self.cdrom_mount) 465 (self.cdrom_cd1, self.cdrom_cd1_mount))
197 if os.system(m_cmd): 466 run(m_cmd, info='Could not mount CD image %s.' % self.cdrom_cd1)
198 raise SetupError('Could not mount CD image %s.' %
199 self.cdrom_iso)
200 467
201 pxe_dir = os.path.join(self.cdrom_mount, self.pxe_dir) 468 pxe_dir = os.path.join(self.cdrom_cd1_mount, self.pxe_dir)
202 pxe_image = os.path.join(pxe_dir, self.pxe_image) 469 pxe_image = os.path.join(pxe_dir, self.pxe_image)
203 pxe_initrd = os.path.join(pxe_dir, self.pxe_initrd) 470 pxe_initrd = os.path.join(pxe_dir, self.pxe_initrd)
204 471
205 if not os.path.isdir(pxe_dir): 472 if not os.path.isdir(pxe_dir):
206 raise SetupError('The ISO image does not have a %s dir. The ' 473 raise SetupError('The ISO image does not have a %s dir. The '
207 'script assumes that the cd has a %s dir ' 474 'script assumes that the cd has a %s dir '
208 'where to search for the vmlinuz image.' % 475 'where to search for the vmlinuz image.' %
209 (self.pxe_dir, self.pxe_dir)) 476 (self.pxe_dir, self.pxe_dir))
210 477
211 if not os.path.isfile(pxe_image) or not os.path.isfile(pxe_initrd): 478 if not os.path.isfile(pxe_image) or not os.path.isfile(pxe_initrd):
212 raise SetupError('The location %s is lacking either a vmlinuz ' 479 raise SetupError('The location %s is lacking either a vmlinuz '
213 'or a initrd.img file. Cannot find a PXE ' 480 'or a initrd.img file. Cannot find a PXE '
214 'image to proceed.' % self.pxe_dir) 481 'image to proceed.' % self.pxe_dir)
215 482
216 tftp_image = os.path.join(self.tftp_root, 'vmlinuz') 483 tftp_image = os.path.join(self.tftp, 'vmlinuz')
217 tftp_initrd = os.path.join(self.tftp_root, 'initrd.img') 484 tftp_initrd = os.path.join(self.tftp, 'initrd.img')
218 shutil.copyfile(pxe_image, tftp_image) 485 shutil.copyfile(pxe_image, tftp_image)
219 shutil.copyfile(pxe_initrd, tftp_initrd) 486 shutil.copyfile(pxe_initrd, tftp_initrd)
220 487
221 finally: 488 finally:
222 u_cmd = 'umount %s' % self.cdrom_mount 489 cleanup(self.cdrom_cd1_mount)
223 if os.system(u_cmd):
224 raise SetupError('Could not unmount CD at %s.' %
225 self.cdrom_mount)
226 self.cleanup(self.cdrom_mount)
227 490
228 pxe_config_dir = os.path.join(self.tftp_root, 'pxelinux.cfg') 491 pxe_config_dir = os.path.join(self.tftp, 'pxelinux.cfg')
229 if not os.path.isdir(pxe_config_dir): 492 if not os.path.isdir(pxe_config_dir):
230 os.makedirs(pxe_config_dir) 493 os.makedirs(pxe_config_dir)
231 pxe_config_path = os.path.join(pxe_config_dir, 'default') 494 pxe_config_path = os.path.join(pxe_config_dir, 'default')
232 495
233 pxe_config = open(pxe_config_path, 'w') 496 pxe_config = open(pxe_config_path, 'w')
234 pxe_config.write('DEFAULT pxeboot\n') 497 pxe_config.write('DEFAULT pxeboot\n')
235 pxe_config.write('TIMEOUT 20\n') 498 pxe_config.write('TIMEOUT 20\n')
236 pxe_config.write('PROMPT 0\n') 499 pxe_config.write('PROMPT 0\n')
237 pxe_config.write('LABEL pxeboot\n') 500 pxe_config.write('LABEL pxeboot\n')
238 pxe_config.write(' KERNEL vmlinuz\n') 501 pxe_config.write(' KERNEL vmlinuz\n')
239 pxe_config.write(' APPEND initrd=initrd.img %s\n' % 502 pxe_config.write(' APPEND initrd=initrd.img %s\n' %
240 self.kernel_args) 503 self.kernel_args)
241 pxe_config.close() 504 pxe_config.close()
242 505
243 print "PXE boot successfuly set" 506 print "PXE boot successfuly set"
244 507
245 508
246 def setup_url(self): 509 def setup_url(self):
247 """ 510 """
248 Download the vmlinuz and initrd.img from URL 511 Download the vmlinuz and initrd.img from URL.
249 """ 512 """
250 print "Downloading the vmlinuz and initrd.img" 513 print "Downloading the vmlinuz and initrd.img"
251 os.chdir(self.image_path) 514 os.chdir(self.image_path)
252 515
253 kernel_fetch_cmd = "wget -q %s/isolinux/%s" % (self.url, self.kernel) 516 kernel_fetch_cmd = "wget -q %s/isolinux/%s" % (self.url, self.kernel)
254 initrd_fetch_cmd = "wget -q %s/isolinux/%s" % (self.url, self.initrd) 517 initrd_fetch_cmd = "wget -q %s/isolinux/%s" % (self.url, self.initrd)
255 518
256 if os.path.exists(self.kernel): 519 if os.path.exists(self.kernel):
257 os.unlink(self.kernel) 520 os.unlink(self.kernel)
258 if os.path.exists(self.initrd): 521 if os.path.exists(self.initrd):
259 os.unlink(self.initrd) 522 os.unlink(self.initrd)
260 523
261 if os.system(kernel_fetch_cmd) != 0: 524 run(kernel_fetch_cmd, info="Could not fetch vmlinuz from %s" % self.url)
262 raise SetupError("Could not fetch vmlinuz from %s" % self.url) 525 run(initrd_fetch_cmd, info=("Could not fetch initrd.img from %s" %
263 if os.system(initrd_fetch_cmd) != 0: 526 self.url))
264 raise SetupError("Could not fetch initrd.img from %s" % self.url) 527 print "Download of vmlinuz and initrd.img finished"
265 528
266 print "Downloading finish"
267 529
268 def setup_nfs(self): 530 def setup_nfs(self):
269 """ 531 """
270 Copy the vmlinuz and initrd.img from nfs. 532 Copy the vmlinuz and initrd.img from nfs.
271 """ 533 """
272 print "Copying the vmlinuz and initrd.img from nfs" 534 print "Copying the vmlinuz and initrd.img from nfs"
273 535
274 m_cmd = "mount %s:%s %s -o ro" % (self.nfs_server, self.nfs_dir, self.nf s_mount) 536 m_cmd = ("mount %s:%s %s -o ro" %
275 if os.system(m_cmd): 537 (self.nfs_server, self.nfs_dir, self.nfs_mount))
276 raise SetupError('Could not mount nfs server.') 538 run(m_cmd, info='Could not mount nfs server')
277
278 kernel_fetch_cmd = "cp %s/isolinux/%s %s" % (self.nfs_mount,
279 self.kernel,
280 self.image_path)
281 initrd_fetch_cmd = "cp %s/isolinux/%s %s" % (self.nfs_mount,
282 self.initrd,
283 self.image_path)
284 539
285 try: 540 try:
286 if os.system(kernel_fetch_cmd): 541 kernel_fetch_cmd = ("cp %s/isolinux/%s %s" %
287 raise SetupError("Could not copy the vmlinuz from %s" % 542 (self.nfs_mount, self.kernel, self.image_path))
288 self.nfs_mount) 543 run(kernel_fetch_cmd, info=("Could not copy the vmlinuz from %s" %
289 if os.system(initrd_fetch_cmd): 544 self.nfs_mount))
290 raise SetupError("Could not copy the initrd.img from %s" % 545 initrd_fetch_cmd = ("cp %s/isolinux/%s %s" %
291 self.nfs_mount) 546 (self.nfs_mount, self.initrd, self.image_path))
547 run(initrd_fetch_cmd, info=("Could not copy the initrd.img from "
548 "%s" % self.nfs_mount))
292 finally: 549 finally:
293 u_cmd = "umount %s" % self.nfs_mount 550 cleanup(self.nfs_mount)
294 if os.system(u_cmd):
295 raise SetupError("Could not unmont nfs at %s" % self.nfs_mount)
296 self.cleanup(self.nfs_mount)
297
298 def cleanup(self, mount):
299 """
300 Clean up a previously used mountpoint.
301
302 @param mount: Mountpoint to be cleaned up.
303 """
304 if os.path.isdir(mount):
305 if os.path.ismount(mount):
306 print "Path %s is still mounted, please verify" % mount
307 else:
308 print "Removing mount point %s" % mount
309 os.rmdir(mount)
310 551
311 552
312 def setup(self): 553 def setup(self):
554 """
555 Configure the environment for unattended install.
556
557 Uses an appropriate strategy according to each install model.
558 """
313 print "Starting unattended install setup" 559 print "Starting unattended install setup"
560 print
314 561
315 print "Variables set:" 562 print "Variables set:"
316 print " medium: " + str(self.medium) 563 for member in inspect.getmembers(self):
317 print " qemu_img_bin: " + str(self.qemu_img_bin) 564 name, value = member
318 print " cdrom iso: " + str(self.cdrom_iso) 565 attribute = getattr(self, name)
319 print " unattended_file: " + str(self.unattended_file) 566 if not (name.startswith("__") or callable(attribute) or not value):
320 print " kernel_args: " + str(self.kernel_args) 567 print " %s: %s" % (name, value)
321 print " tftp_root: " + str(self.tftp_root) 568 print
322 print " floppy_mount: " + str(self.floppy_mount)
323 print " floppy_img: " + str(self.floppy_img)
324 print " finish_program: " + str(self.finish_program)
325 print " pxe_dir: " + str(self.pxe_dir)
326 print " pxe_image: " + str(self.pxe_image)
327 print " pxe_initrd: " + str(self.pxe_initrd)
328 print " url: " + str(self.url)
329 print " kernel: " + str(self.kernel)
330 print " initrd: " + str(self.initrd)
331 print " nfs_server: " + str(self.nfs_server)
332 print " nfs_dir: " + str(self.nfs_dir)
333 print " nfs_mount: " + str(self.nfs_mount)
334 569
335 if self.unattended_file and self.floppy_img is not None: 570 if self.unattended_file and (self.floppy or self.cdrom_unattended):
336 self.create_boot_floppy() 571 self.setup_boot_disk()
337 if self.medium == "cdrom": 572 if self.medium == "cdrom":
338 if self.tftp_root: 573 if self.tftp:
339 self.setup_pxe_boot() 574 self.setup_pxe_boot()
340 elif self.medium == "url": 575 elif self.medium == "url":
341 self.setup_url() 576 self.setup_url()
342 elif self.medium == "nfs": 577 elif self.medium == "nfs":
343 self.setup_nfs() 578 self.setup_nfs()
344 else: 579 else:
345 raise SetupError("Unexpected installation method %s" % 580 raise SetupError("Unexpected installation method %s" %
346 self.medium) 581 self.medium)
347 print "Unattended install setup finished successfuly" 582 print "Unattended install setup finished successfuly"
348 583
349 584
350 if __name__ == "__main__": 585 if __name__ == "__main__":
351 os_install = UnattendedInstall() 586 os_install = UnattendedInstall()
352 os_install.setup() 587 os_install.setup()
OLDNEW
« no previous file with comments | « client/tests/kvm/kvm_vm.py ('k') | client/tests/kvm/scripts/virtio_guest.py » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698