Merge lp:~corey.bryant/curtin/trunk into lp:~curtin-dev/curtin/trunk

Proposed by Corey Bryant
Status: Superseded
Proposed branch: lp:~corey.bryant/curtin/trunk
Merge into: lp:~curtin-dev/curtin/trunk
Diff against target: 84 lines (+60/-0)
1 file modified
curtin/commands/install.py (+60/-0)
To merge this branch: bzr merge lp:~corey.bryant/curtin/trunk
Reviewer Review Type Date Requested Status
curtin developers Pending
Review via email: mp+205447@code.launchpad.net

This proposal has been superseded by a proposal from 2014-02-14.

Description of the change

Add kexec support and a minor update to example launch command

Sample usage: curtin install --set "power_state/mode=kexec" ...

To post a comment you must log in.
Revision history for this message
Scott Moser (smoser) wrote :

Corey,
  Thanks for the merge request.

 * The 'opt_map' fix seems reasonable. Not the way I had thoght of implementing it, but that should be fine.
   The other option is to just not bother rebooting, but have curtin call 'kexec' itself.
   As I'm thinking... maybe that would be better. As if you reboot, kexec-tools will load the kernel by reading /boot/grub (or attempt to) in its root filesystem. However, we want to load the one that is in the *installed* OS's filesystem.

 * when you use subp, best to not run through 'sh' unless necessary. Ie:
   - util.subp(args=['sh', '-c', 'apt-get install kexec-tools -qy'])
   + util.subp(args=['apt-get', 'install', '-qy', 'kexec-tools'])

 * I generally prefer long format arguments to programs as they're more self documenting:
   + util.subp(args=['apt-get', 'install', '--quiet', '--assume-yes', 'kexec-tools'])

Thanks!

Revision history for this message
Corey Bryant (corey.bryant) wrote :

> Corey,
> Thanks for the merge request.
>

Thanks for reviewing!

> * The 'opt_map' fix seems reasonable. Not the way I had thoght of
> implementing it, but that should be fine.
> The other option is to just not bother rebooting, but have curtin call
> 'kexec' itself.

The reason I took the reboot approach is because I wanted to make sure proper
shutdown occurred before exec'ing the new kernel. From the looks of it you might
be able to get the same result by calling kexec directly without an option parameter.
But I don't think a simple 'kexec -e' does proper shutdown. I'll look into it.

> As I'm thinking... maybe that would be better. As if you reboot, kexec-
> tools will load the kernel by reading /boot/grub (or attempt to) in its root
> filesystem. However, we want to load the one that is in the *installed* OS's
> filesystem.

I think you're right. I'm currently running kexec-load in the root fs and it's
looking at the wrong /boot dir. Another approach is to run kexec-load while
chroot'ed into /tmp/.../target. Then it should look at the right /boot dir.

Which takes me to a somewhat related question that I haven't figured out. When
I use launch with a normal non-kexec reboot, and it reboots into the new OS, the
grub menu is not the one from /tmp/.../target/boot/grub/grub.cfg. However once
booted, the new root fs is the new system (/dev/vdc) and contains the updated
grub.cfg. Shouldn't the grub menu reflect what's in
/tmp/.../target/boot/grub/grub.cfg?

>
>
> * when you use subp, best to not run through 'sh' unless necessary. Ie:
> - util.subp(args=['sh', '-c', 'apt-get install kexec-tools -qy'])
> + util.subp(args=['apt-get', 'install', '-qy', 'kexec-tools'])

Ok

>
> * I generally prefer long format arguments to programs as they're more self
> documenting:
> + util.subp(args=['apt-get', 'install', '--quiet', '--assume-yes', 'kexec-
> tools'])

Yep, makes sense.

>
>
> Thanks!

lp:~corey.bryant/curtin/trunk updated
98. By Scott Moser

curthooks: always update grub linux default entry

Previously we only modified GRUB_CMDLINE_LINUX_DEFAULT in /etc/default/grub
if there were new kernel command line parameters found.

The images that were built from cloud images would have baked into them
'console=ttyS0'. The result was serial console output even if the user
didn't request it (or didn't have a serial console).

99. By Scott Moser

write_files: avoid writing a file if no path is given

if the user provides an entry in 'write_files' that did not have a 'path'
then this would warn, and then stack trace. better to just warn.

100. By Scott Moser

write_files: read 'permissions' or 'perms' to specify mode

cloud-init uses 'permissions' for the permission key in a write_files
input. this just makes it more forgiving.

101. By Scott Moser

decode_perms: fix error if permissions was not an int

isinstance(thing, None) is not valid, and that was throwing
an error, causing us down the return default path.

102. By Scott Moser

support source as a local tar file (not only a url)

103. By Scott Moser

partition: default to 'mbr' format

this will probably have to change with UEFI support, but for now, partition
default to 'mbr'

104. By Corey Bryant

curtin/commands/install.py: Add kexec support

This allows for a faster alternative to the existing reboot power_state mode.
Sample usage: curtin install --set "kexec/mode=on"

Unmerged revisions

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
=== modified file 'curtin/commands/install.py'
--- curtin/commands/install.py 2013-09-19 21:01:27 +0000
+++ curtin/commands/install.py 2014-02-14 15:32:12 +0000
@@ -19,6 +19,7 @@
19import json19import json
20import os20import os
21import re21import re
22import shlex
22import shutil23import shutil
23import tempfile24import tempfile
2425
@@ -158,6 +159,61 @@
158159
159 return (['sh', '-c', shcmd, 'curtin-poweroff', delay] + args)160 return (['sh', '-c', shcmd, 'curtin-poweroff', delay] + args)
160161
162def apply_kexec(kexec, target):
163 # load kexec kernel from target directory, similar to /etc/init.d/kexec-load
164 # kexec:
165 # mode: on
166 if kexec is None or kexec.get("mode") != "on":
167 return False
168
169 if not isinstance(kexec, dict):
170 raise TypeError("kexec is not a dict.")
171
172 util.subp(args=['apt-get', 'install', 'kexec-tools', '--assume-yes',
173 '--quiet'])
174
175 with open(target + "/boot/grub/grub.cfg", "r") as fp:
176 default = 0
177 menu_lines = []
178
179 # get the default grub boot entry number and menu entry line numbers
180 for line_num, line in enumerate(fp, 1):
181 if re.search(r"set default=\"[0-9]+\"", line):
182 default = int(re.sub(r"[^0-9]", '', line))
183 if re.match(r"menuentry", line):
184 menu_lines.append(line_num)
185
186 if not menu_lines:
187 LOG.error("grub config file does not have a menuentry\n")
188 return False
189
190 # get the begin and end line numbers for default menuentry section
191 begin = menu_lines[default]
192 if begin != menu_lines[-1]:
193 end = menu_lines[default + 1] - 1
194 else:
195 end = line_num
196
197 fp.seek(0)
198 lines=fp.readlines()
199 kernel = append = initrd = ""
200
201 for i in range(begin, end):
202 if 'vmlinuz' in lines[i]:
203 split_line = shlex.split(lines[i])
204 kernel = target + split_line[1]
205 append = "--append=" + ' '.join(split_line[2:])
206 if 'initrd' in lines[i]:
207 split_line = shlex.split(lines[i])
208 initrd = "--initrd=" + target + split_line[1]
209
210 if not kernel:
211 LOG.error("grub config file does not have a kernel\n")
212 return False
213
214 LOG.debug("kexec -l %s %s %s" % (kernel, append, initrd))
215 util.subp(args=['kexec', '-l', kernel, append, initrd])
216 return True
161217
162def cmd_install(args):218def cmd_install(args):
163 cfg = CONFIG_BUILTIN219 cfg = CONFIG_BUILTIN
@@ -191,6 +247,10 @@
191 stage = Stage(name, cfg.get(commands_name, {}), env)247 stage = Stage(name, cfg.get(commands_name, {}), env)
192 stage.run()248 stage.run()
193249
250 if apply_kexec(cfg.get('kexec'), workingd.target):
251 cfg['power_state'] = {'mode': 'reboot', 'delay': 'now',
252 'message': "'rebooting with kexec'"}
253
194 finally:254 finally:
195 for d in ('sys', 'dev', 'proc'):255 for d in ('sys', 'dev', 'proc'):
196 util.do_umount(os.path.join(workingd.target, d))256 util.do_umount(os.path.join(workingd.target, d))

Subscribers

People subscribed via source and target branches