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

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

Issue 3541002: Revert "Merge remote branch 'cros/upstream' into tempbranch2" (Closed) Base URL: ssh://git@gitrw.chromium.org:9222/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, ConfigParser, glob, inspect 6 import os, sys, shutil, tempfile, re
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
14 class SetupError(Exception): 10 class SetupError(Exception):
15 """ 11 """
16 Simple wrapper for the builtin Exception class. 12 Simple wrapper for the builtin Exception class.
17 """ 13 """
18 pass 14 pass
19 15
20 16
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
242 class UnattendedInstall(object): 17 class UnattendedInstall(object):
243 """ 18 """
244 Creates a floppy disk image that will contain a config file for unattended 19 Creates a floppy disk image that will contain a config file for unattended
245 OS install. Optionally, sets up a PXE install server using qemu built in 20 OS install. Optionally, sets up a PXE install server using qemu built in
246 TFTP and DHCP servers to install a particular operating system. The 21 TFTP and DHCP servers to install a particular operating system. The
247 parameters to the script are retrieved from environment variables. 22 parameters to the script are retrieved from environment variables.
248 """ 23 """
249 def __init__(self): 24 def __init__(self):
250 """ 25 """
251 Gets params from environment variables and sets class attributes. 26 Gets params from environment variables and sets class attributes.
252 """ 27 """
253 images_dir = os.path.join(KVM_TEST_DIR, 'images') 28 script_dir = os.path.dirname(sys.modules[__name__].__file__)
254 self.deps_dir = os.path.join(KVM_TEST_DIR, 'deps') 29 kvm_test_dir = os.path.abspath(os.path.join(script_dir, ".."))
255 self.unattended_dir = os.path.join(KVM_TEST_DIR, 'unattended') 30 images_dir = os.path.join(kvm_test_dir, 'images')
31 self.deps_dir = os.path.join(kvm_test_dir, 'deps')
32 self.unattended_dir = os.path.join(kvm_test_dir, 'unattended')
256 33
257 attributes = ['kernel_args', 'finish_program', 'cdrom_cd1', 34 tftp_root = os.environ.get('KVM_TEST_tftp', '')
258 'unattended_file', 'medium', 'url', 'kernel', 'initrd', 35 if tftp_root:
259 'nfs_server', 'nfs_dir', 'pxe_dir', 'pxe_image', 36 self.tftp_root = os.path.join(kvm_test_dir, tftp_root)
260 'pxe_initrd', 'install_virtio', 'tftp', 37 if not os.path.isdir(self.tftp_root):
261 'floppy', 'cdrom_unattended'] 38 os.makedirs(self.tftp_root)
262 for a in attributes: 39 else:
263 self._setattr(a) 40 self.tftp_root = tftp_root
264 41
265 if self.install_virtio == 'yes': 42 self.kernel_args = os.environ.get('KVM_TEST_kernel_args', '')
266 v_attributes = ['virtio_floppy', 'virtio_storage_path', 43 self.finish_program= os.environ.get('KVM_TEST_finish_program', '')
267 'virtio_network_path', 'virtio_oemsetup_id', 44 cdrom_iso = os.environ.get('KVM_TEST_cdrom_cd1')
268 'virtio_network_installer'] 45 self.unattended_file = os.environ.get('KVM_TEST_unattended_file')
269 for va in v_attributes:
270 self._setattr(va)
271 46
272 # Silly attribution just to calm pylint down... 47 self.qemu_img_bin = os.environ.get('KVM_TEST_qemu_img_binary')
273 self.tftp = self.tftp 48 if not os.path.isabs(self.qemu_img_bin):
274 if self.tftp: 49 self.qemu_img_bin = os.path.join(kvm_test_dir, self.qemu_img_bin)
275 self.tftp = os.path.join(KVM_TEST_DIR, self.tftp) 50 self.cdrom_iso = os.path.join(kvm_test_dir, cdrom_iso)
276 if not os.path.isdir(self.tftp): 51 self.floppy_mount = tempfile.mkdtemp(prefix='floppy_', dir='/tmp')
277 os.makedirs(self.tftp) 52 self.cdrom_mount = tempfile.mkdtemp(prefix='cdrom_', dir='/tmp')
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)
278 59
279 self.cdrom_cd1 = os.path.join(KVM_TEST_DIR, self.cdrom_cd1) 60 self.pxe_dir = os.environ.get('KVM_TEST_pxe_dir', '')
280 self.cdrom_cd1_mount = tempfile.mkdtemp(prefix='cdrom_cd1_', dir='/tmp') 61 self.pxe_image = os.environ.get('KVM_TEST_pxe_image', '')
281 if self.medium == 'nfs': 62 self.pxe_initrd = os.environ.get('KVM_TEST_pxe_initrd', '')
282 self.nfs_mount = tempfile.mkdtemp(prefix='nfs_', dir='/tmp')
283 63
284 self.floppy = os.path.join(KVM_TEST_DIR, self.floppy) 64 self.medium = os.environ.get('KVM_TEST_medium', '')
285 if not os.path.isdir(os.path.dirname(self.floppy)): 65 self.url = os.environ.get('KVM_TEST_url', '')
286 os.makedirs(os.path.dirname(self.floppy)) 66 self.kernel = os.environ.get('KVM_TEST_kernel', '')
287 67 self.initrd = os.environ.get('KVM_TEST_initrd', '')
288 self.image_path = KVM_TEST_DIR 68 self.nfs_server = os.environ.get('KVM_TEST_nfs_server', '')
69 self.nfs_dir = os.environ.get('KVM_TEST_nfs_dir', '')
70 self.image_path = kvm_test_dir
289 self.kernel_path = os.path.join(self.image_path, self.kernel) 71 self.kernel_path = os.path.join(self.image_path, self.kernel)
290 self.initrd_path = os.path.join(self.image_path, self.initrd) 72 self.initrd_path = os.path.join(self.image_path, self.initrd)
291 73
292 74
293 def _setattr(self, key): 75 def create_boot_floppy(self):
294 """ 76 """
295 Populate class attributes with contents of environment variables. 77 Prepares a boot floppy by creating a floppy image file, mounting it and
78 copying an answer file (kickstarts for RH based distros, answer files
79 for windows) to it. After that the image is umounted.
80 """
81 print "Creating boot floppy"
296 82
297 Example: KVM_TEST_medium will populate self.medium. 83 if os.path.exists(self.floppy_img):
84 os.remove(self.floppy_img)
298 85
299 @param key: Name of the class attribute we desire to have. 86 c_cmd = '%s create -f raw %s 1440k' % (self.qemu_img_bin,
300 """ 87 self.floppy_img)
301 env_name = 'KVM_TEST_%s' % key 88 if os.system(c_cmd):
302 value = os.environ.get(env_name, '') 89 raise SetupError('Could not create floppy image.')
303 setattr(self, key, value)
304 90
91 f_cmd = 'mkfs.msdos -s 1 %s' % self.floppy_img
92 if os.system(f_cmd):
93 raise SetupError('Error formatting floppy image.')
305 94
306 def render_answer_file(self): 95 try:
307 # Replace KVM_TEST_CDKEY (in the unattended file) with the cdkey 96 m_cmd = 'mount -o loop %s %s' % (self.floppy_img, self.floppy_mount)
308 # provided for this test and replace the KVM_TEST_MEDIUM with 97 if os.system(m_cmd):
309 # the tree url or nfs address provided for this test. 98 raise SetupError('Could not mount floppy image.')
310 unattended_contents = open(self.unattended_file).read() 99
311 dummy_cdkey_re = r'\bKVM_TEST_CDKEY\b' 100 if self.unattended_file.endswith('.sif'):
312 real_cdkey = os.environ.get('KVM_TEST_cdkey') 101 dest_fname = 'winnt.sif'
313 if re.search(dummy_cdkey_re, unattended_contents): 102 setup_file = 'winnt.bat'
314 if real_cdkey: 103 setup_file_path = os.path.join(self.unattended_dir, setup_file)
315 unattended_contents = re.sub(dummy_cdkey_re, real_cdkey, 104 setup_file_dest = os.path.join(self.floppy_mount, setup_file)
316 unattended_contents) 105 shutil.copyfile(setup_file_path, setup_file_dest)
106 elif self.unattended_file.endswith('.ks'):
107 # Red Hat kickstart install
108 dest_fname = 'ks.cfg'
109 elif self.unattended_file.endswith('.xml'):
110 if self.tftp_root is '':
111 # Windows unattended install
112 dest_fname = "autounattend.xml"
113 else:
114 # SUSE autoyast install
115 dest_fname = "autoinst.xml"
116
117 dest = os.path.join(self.floppy_mount, dest_fname)
118
119 # Replace KVM_TEST_CDKEY (in the unattended file) with the cdkey
120 # provided for this test and replace the KVM_TEST_MEDIUM with
121 # the tree url or nfs address provided for this test.
122 unattended_contents = open(self.unattended_file).read()
123 dummy_cdkey_re = r'\bKVM_TEST_CDKEY\b'
124 real_cdkey = os.environ.get('KVM_TEST_cdkey')
125 if re.search(dummy_cdkey_re, unattended_contents):
126 if real_cdkey:
127 unattended_contents = re.sub(dummy_cdkey_re, real_cdkey,
128 unattended_contents)
129 else:
130 print ("WARNING: 'cdkey' required but not specified for "
131 "this unattended installation")
132
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)
317 else: 140 else:
318 print ("WARNING: 'cdkey' required but not specified for " 141 raise SetupError("Unexpected installation medium %s" % self.url)
319 "this unattended installation")
320 142
321 dummy_medium_re = r'\bKVM_TEST_MEDIUM\b' 143 unattended_contents = re.sub(dummy_re, content, unattended_contents)
322 if self.medium == "cdrom":
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)
331 144
332 unattended_contents = re.sub(dummy_medium_re, content, 145 print
333 unattended_contents) 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)
334 150
335 def replace_virtio_key(contents, dummy_re, env): 151 if self.finish_program:
336 """ 152 dest_fname = os.path.basename(self.finish_program)
337 Replace a virtio dummy string with contents. 153 dest = os.path.join(self.floppy_mount, dest_fname)
154 shutil.copyfile(self.finish_program, dest)
338 155
339 If install_virtio is not set, replace it with a dummy string. 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)
340 162
341 @param contents: Contents of the unattended file 163 os.chmod(self.floppy_img, 0755)
342 @param dummy_re: Regular expression used to search on the.
343 unattended file contents.
344 @param env: Name of the environment variable.
345 """
346 dummy_path = "C:"
347 driver = os.environ.get(env, '')
348 164
349 if re.search(dummy_re, contents): 165 print "Boot floppy created successfuly"
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)
361 else:
362 contents = re.sub(dummy_re, dummy_path, contents)
363 return contents
364
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'}
371
372 for vkey in vdict:
373 unattended_contents = replace_virtio_key(unattended_contents,
374 vkey, vdict[vkey])
375
376 print "Unattended install contents:"
377 print unattended_contents
378 return unattended_contents
379
380
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)
416 else:
417 raise SetupError("Neither cdrom_unattended nor floppy set "
418 "on the config file, please verify")
419 boot_disk.setup_answer_file(dest_fname, answer_contents)
420
421 else:
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)
429
430 else:
431 raise SetupError('Unknown answer file %s' %
432 self.unattended_file)
433
434 boot_disk.close()
435 166
436 167
437 def setup_pxe_boot(self): 168 def setup_pxe_boot(self):
438 """ 169 """
439 Sets up a PXE boot environment using the built in qemu TFTP server. 170 Sets up a PXE boot environment using the built in qemu TFTP server.
440 Copies the PXE Linux bootloader pxelinux.0 from the host (needs the 171 Copies the PXE Linux bootloader pxelinux.0 from the host (needs the
441 pxelinux package or equivalent for your distro), and vmlinuz and 172 pxelinux package or equivalent for your distro), and vmlinuz and
442 initrd.img files from the CD to a directory that qemu will serve trough 173 initrd.img files from the CD to a directory that qemu will serve trough
443 TFTP to the VM. 174 TFTP to the VM.
444 """ 175 """
445 print "Setting up PXE boot using TFTP root %s" % self.tftp 176 print "Setting up PXE boot using TFTP root %s" % self.tftp_root
446 177
447 pxe_file = None 178 pxe_file = None
448 pxe_paths = ['/usr/lib/syslinux/pxelinux.0', 179 pxe_paths = ['/usr/lib/syslinux/pxelinux.0',
449 '/usr/share/syslinux/pxelinux.0'] 180 '/usr/share/syslinux/pxelinux.0']
450 for path in pxe_paths: 181 for path in pxe_paths:
451 if os.path.isfile(path): 182 if os.path.isfile(path):
452 pxe_file = path 183 pxe_file = path
453 break 184 break
454 185
455 if not pxe_file: 186 if not pxe_file:
456 raise SetupError('Cannot find PXE boot loader pxelinux.0. Make ' 187 raise SetupError('Cannot find PXE boot loader pxelinux.0. Make '
457 'sure pxelinux or equivalent package for your ' 188 'sure pxelinux or equivalent package for your '
458 'distro is installed.') 189 'distro is installed.')
459 190
460 pxe_dest = os.path.join(self.tftp, 'pxelinux.0') 191 pxe_dest = os.path.join(self.tftp_root, 'pxelinux.0')
461 shutil.copyfile(pxe_file, pxe_dest) 192 shutil.copyfile(pxe_file, pxe_dest)
462 193
463 try: 194 try:
464 m_cmd = ('mount -t iso9660 -v -o loop,ro %s %s' % 195 m_cmd = 'mount -t iso9660 -v -o loop,ro %s %s' % (self.cdrom_iso,
465 (self.cdrom_cd1, self.cdrom_cd1_mount)) 196 self.cdrom_mount)
466 run(m_cmd, info='Could not mount CD image %s.' % self.cdrom_cd1) 197 if os.system(m_cmd):
198 raise SetupError('Could not mount CD image %s.' %
199 self.cdrom_iso)
467 200
468 pxe_dir = os.path.join(self.cdrom_cd1_mount, self.pxe_dir) 201 pxe_dir = os.path.join(self.cdrom_mount, self.pxe_dir)
469 pxe_image = os.path.join(pxe_dir, self.pxe_image) 202 pxe_image = os.path.join(pxe_dir, self.pxe_image)
470 pxe_initrd = os.path.join(pxe_dir, self.pxe_initrd) 203 pxe_initrd = os.path.join(pxe_dir, self.pxe_initrd)
471 204
472 if not os.path.isdir(pxe_dir): 205 if not os.path.isdir(pxe_dir):
473 raise SetupError('The ISO image does not have a %s dir. The ' 206 raise SetupError('The ISO image does not have a %s dir. The '
474 'script assumes that the cd has a %s dir ' 207 'script assumes that the cd has a %s dir '
475 'where to search for the vmlinuz image.' % 208 'where to search for the vmlinuz image.' %
476 (self.pxe_dir, self.pxe_dir)) 209 (self.pxe_dir, self.pxe_dir))
477 210
478 if not os.path.isfile(pxe_image) or not os.path.isfile(pxe_initrd): 211 if not os.path.isfile(pxe_image) or not os.path.isfile(pxe_initrd):
479 raise SetupError('The location %s is lacking either a vmlinuz ' 212 raise SetupError('The location %s is lacking either a vmlinuz '
480 'or a initrd.img file. Cannot find a PXE ' 213 'or a initrd.img file. Cannot find a PXE '
481 'image to proceed.' % self.pxe_dir) 214 'image to proceed.' % self.pxe_dir)
482 215
483 tftp_image = os.path.join(self.tftp, 'vmlinuz') 216 tftp_image = os.path.join(self.tftp_root, 'vmlinuz')
484 tftp_initrd = os.path.join(self.tftp, 'initrd.img') 217 tftp_initrd = os.path.join(self.tftp_root, 'initrd.img')
485 shutil.copyfile(pxe_image, tftp_image) 218 shutil.copyfile(pxe_image, tftp_image)
486 shutil.copyfile(pxe_initrd, tftp_initrd) 219 shutil.copyfile(pxe_initrd, tftp_initrd)
487 220
488 finally: 221 finally:
489 cleanup(self.cdrom_cd1_mount) 222 u_cmd = 'umount %s' % self.cdrom_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)
490 227
491 pxe_config_dir = os.path.join(self.tftp, 'pxelinux.cfg') 228 pxe_config_dir = os.path.join(self.tftp_root, 'pxelinux.cfg')
492 if not os.path.isdir(pxe_config_dir): 229 if not os.path.isdir(pxe_config_dir):
493 os.makedirs(pxe_config_dir) 230 os.makedirs(pxe_config_dir)
494 pxe_config_path = os.path.join(pxe_config_dir, 'default') 231 pxe_config_path = os.path.join(pxe_config_dir, 'default')
495 232
496 pxe_config = open(pxe_config_path, 'w') 233 pxe_config = open(pxe_config_path, 'w')
497 pxe_config.write('DEFAULT pxeboot\n') 234 pxe_config.write('DEFAULT pxeboot\n')
498 pxe_config.write('TIMEOUT 20\n') 235 pxe_config.write('TIMEOUT 20\n')
499 pxe_config.write('PROMPT 0\n') 236 pxe_config.write('PROMPT 0\n')
500 pxe_config.write('LABEL pxeboot\n') 237 pxe_config.write('LABEL pxeboot\n')
501 pxe_config.write(' KERNEL vmlinuz\n') 238 pxe_config.write(' KERNEL vmlinuz\n')
502 pxe_config.write(' APPEND initrd=initrd.img %s\n' % 239 pxe_config.write(' APPEND initrd=initrd.img %s\n' %
503 self.kernel_args) 240 self.kernel_args)
504 pxe_config.close() 241 pxe_config.close()
505 242
506 print "PXE boot successfuly set" 243 print "PXE boot successfuly set"
507 244
508 245
509 def setup_url(self): 246 def setup_url(self):
510 """ 247 """
511 Download the vmlinuz and initrd.img from URL. 248 Download the vmlinuz and initrd.img from URL
512 """ 249 """
513 print "Downloading the vmlinuz and initrd.img" 250 print "Downloading the vmlinuz and initrd.img"
514 os.chdir(self.image_path) 251 os.chdir(self.image_path)
515 252
516 kernel_fetch_cmd = "wget -q %s/isolinux/%s" % (self.url, self.kernel) 253 kernel_fetch_cmd = "wget -q %s/isolinux/%s" % (self.url, self.kernel)
517 initrd_fetch_cmd = "wget -q %s/isolinux/%s" % (self.url, self.initrd) 254 initrd_fetch_cmd = "wget -q %s/isolinux/%s" % (self.url, self.initrd)
518 255
519 if os.path.exists(self.kernel): 256 if os.path.exists(self.kernel):
520 os.unlink(self.kernel) 257 os.unlink(self.kernel)
521 if os.path.exists(self.initrd): 258 if os.path.exists(self.initrd):
522 os.unlink(self.initrd) 259 os.unlink(self.initrd)
523 260
524 run(kernel_fetch_cmd, info="Could not fetch vmlinuz from %s" % self.url) 261 if os.system(kernel_fetch_cmd) != 0:
525 run(initrd_fetch_cmd, info=("Could not fetch initrd.img from %s" % 262 raise SetupError("Could not fetch vmlinuz from %s" % self.url)
526 self.url)) 263 if os.system(initrd_fetch_cmd) != 0:
527 print "Download of vmlinuz and initrd.img finished" 264 raise SetupError("Could not fetch initrd.img from %s" % self.url)
528 265
266 print "Downloading finish"
529 267
530 def setup_nfs(self): 268 def setup_nfs(self):
531 """ 269 """
532 Copy the vmlinuz and initrd.img from nfs. 270 Copy the vmlinuz and initrd.img from nfs.
533 """ 271 """
534 print "Copying the vmlinuz and initrd.img from nfs" 272 print "Copying the vmlinuz and initrd.img from nfs"
535 273
536 m_cmd = ("mount %s:%s %s -o ro" % 274 m_cmd = "mount %s:%s %s -o ro" % (self.nfs_server, self.nfs_dir, self.nf s_mount)
537 (self.nfs_server, self.nfs_dir, self.nfs_mount)) 275 if os.system(m_cmd):
538 run(m_cmd, info='Could not mount nfs server') 276 raise SetupError('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)
539 284
540 try: 285 try:
541 kernel_fetch_cmd = ("cp %s/isolinux/%s %s" % 286 if os.system(kernel_fetch_cmd):
542 (self.nfs_mount, self.kernel, self.image_path)) 287 raise SetupError("Could not copy the vmlinuz from %s" %
543 run(kernel_fetch_cmd, info=("Could not copy the vmlinuz from %s" % 288 self.nfs_mount)
544 self.nfs_mount)) 289 if os.system(initrd_fetch_cmd):
545 initrd_fetch_cmd = ("cp %s/isolinux/%s %s" % 290 raise SetupError("Could not copy the initrd.img from %s" %
546 (self.nfs_mount, self.initrd, self.image_path)) 291 self.nfs_mount)
547 run(initrd_fetch_cmd, info=("Could not copy the initrd.img from "
548 "%s" % self.nfs_mount))
549 finally: 292 finally:
550 cleanup(self.nfs_mount) 293 u_cmd = "umount %s" % 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)
551 310
552 311
553 def setup(self): 312 def setup(self):
554 """
555 Configure the environment for unattended install.
556
557 Uses an appropriate strategy according to each install model.
558 """
559 print "Starting unattended install setup" 313 print "Starting unattended install setup"
560 print
561 314
562 print "Variables set:" 315 print "Variables set:"
563 for member in inspect.getmembers(self): 316 print " medium: " + str(self.medium)
564 name, value = member 317 print " qemu_img_bin: " + str(self.qemu_img_bin)
565 attribute = getattr(self, name) 318 print " cdrom iso: " + str(self.cdrom_iso)
566 if not (name.startswith("__") or callable(attribute) or not value): 319 print " unattended_file: " + str(self.unattended_file)
567 print " %s: %s" % (name, value) 320 print " kernel_args: " + str(self.kernel_args)
568 print 321 print " tftp_root: " + str(self.tftp_root)
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)
569 334
570 if self.unattended_file and (self.floppy or self.cdrom_unattended): 335 if self.unattended_file and self.floppy_img is not None:
571 self.setup_boot_disk() 336 self.create_boot_floppy()
572 if self.medium == "cdrom": 337 if self.medium == "cdrom":
573 if self.tftp: 338 if self.tftp_root:
574 self.setup_pxe_boot() 339 self.setup_pxe_boot()
575 elif self.medium == "url": 340 elif self.medium == "url":
576 self.setup_url() 341 self.setup_url()
577 elif self.medium == "nfs": 342 elif self.medium == "nfs":
578 self.setup_nfs() 343 self.setup_nfs()
579 else: 344 else:
580 raise SetupError("Unexpected installation method %s" % 345 raise SetupError("Unexpected installation method %s" %
581 self.medium) 346 self.medium)
582 print "Unattended install setup finished successfuly" 347 print "Unattended install setup finished successfuly"
583 348
584 349
585 if __name__ == "__main__": 350 if __name__ == "__main__":
586 os_install = UnattendedInstall() 351 os_install = UnattendedInstall()
587 os_install.setup() 352 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