Arrfab's blog - anacondahttps://arrfab.net/2015-05-06T00:00:00+02:00Some tips and tricks, mostly around CentOSHacking initrd.img for fun and profit2015-05-06T00:00:00+02:002015-05-06T00:00:00+02:00Fabian Arrotintag:arrfab.net,2015-05-06:/posts/2015/May/06/hacking-initrdimg-for-fun-and-profit/<p>During my presentation at <a href="http://loadays.org">Loadays 2015</a> , I was mentioning some tips and tricks around <a href="http://fedoraproject.org/wiki/Anaconda">Anaconda</a> and <a href="https://access.redhat.com/documentation/en-US/Red_Hat_Enterprise_Linux/7/html/Installation_Guide/chap-kickstart-installations.html">kickstart</a>, and so how to deploy CentOS , fully automated.
I asked the audience about where to store the kickstart, that would be used then by anaconda to install CentOS (same works for RHEL/Fedora), and I got several answers, like "on the http server", or "on the ftp server", which is where most people will put their kickstart files.
Some would generate those files files "dynamically" (through $cfgmgmt - I use <a href="http://www.ansible.com">Ansible</a> with Jinja2 template for this - ) as a bonus point.</p>
<p>But it's not mandatory to host your kickstart file on a publicly available http/ftp/nfs server, and surely not when having to reinstall nodes not in the same DC. Within the CentOS.org infra, I sometimes have to reinstall remote nodes ("donated" to the Project) that are running CentOS 5 or 6 to 7. That's how injecting your ks file directly into the initrd.img really helps. (yes, so network server needed).
Just as an intro, here is how you can remotely trigger a CentOS install, without any medium/iso/pxe environment : basically you just need to download the pxeboot images (so vmlinuz …</p><p>During my presentation at <a href="http://loadays.org">Loadays 2015</a> , I was mentioning some tips and tricks around <a href="http://fedoraproject.org/wiki/Anaconda">Anaconda</a> and <a href="https://access.redhat.com/documentation/en-US/Red_Hat_Enterprise_Linux/7/html/Installation_Guide/chap-kickstart-installations.html">kickstart</a>, and so how to deploy CentOS , fully automated.
I asked the audience about where to store the kickstart, that would be used then by anaconda to install CentOS (same works for RHEL/Fedora), and I got several answers, like "on the http server", or "on the ftp server", which is where most people will put their kickstart files.
Some would generate those files files "dynamically" (through $cfgmgmt - I use <a href="http://www.ansible.com">Ansible</a> with Jinja2 template for this - ) as a bonus point.</p>
<p>But it's not mandatory to host your kickstart file on a publicly available http/ftp/nfs server, and surely not when having to reinstall nodes not in the same DC. Within the CentOS.org infra, I sometimes have to reinstall remote nodes ("donated" to the Project) that are running CentOS 5 or 6 to 7. That's how injecting your ks file directly into the initrd.img really helps. (yes, so network server needed).
Just as an intro, here is how you can remotely trigger a CentOS install, without any medium/iso/pxe environment : basically you just need to download the pxeboot images (so vmlinuz and initrd.img), provide some default settings for Anaconda (for the network config, and how to grab stage2 image, and so where is the install tree)
On the machine to be reinstalled : </p>
<div class="highlight"><pre><span></span><span class="n">cd</span> <span class="o">/</span><span class="n">boot</span><span class="o">/</span>
<span class="n">wget</span> <span class="n">http</span><span class="p">:</span><span class="o">//</span><span class="n">mirror</span><span class="p">.</span><span class="n">centos</span><span class="p">.</span><span class="n">org</span><span class="o">/</span><span class="n">centos</span><span class="o">/</span><span class="mi">7</span><span class="o">/</span><span class="n">os</span><span class="o">/</span><span class="n">x86_64</span><span class="o">/</span><span class="n">images</span><span class="o">/</span><span class="n">pxeboot</span><span class="o">/</span><span class="err">{</span><span class="n">vmlinuz</span><span class="p">,</span><span class="n">initrd</span><span class="p">.</span><span class="n">img</span><span class="err">}</span>
</pre></div>
<p>Now you can generate and copy your kickstart file for that node and send it to the remote node (with scp, etc ..)
Next step on that remote node is to "inject" the kickstart directly in the initrd.img :</p>
<div class="highlight"><pre><span></span><span class="o">#</span><span class="n">assuming</span> <span class="n">we</span> <span class="n">have</span> <span class="n">copied</span> <span class="n">the</span> <span class="n">ks</span> <span class="n">file</span> <span class="k">as</span> <span class="n">ks</span><span class="p">.</span><span class="n">cfg</span> <span class="k">in</span> <span class="o">/</span><span class="n">boot</span> <span class="n">already</span>
<span class="n">echo</span> <span class="n">ks</span><span class="p">.</span><span class="n">cfg</span> <span class="o">|</span> <span class="n">cpio</span> <span class="o">-</span><span class="k">c</span> <span class="o">-</span><span class="n">o</span> <span class="o">>></span> <span class="n">initrd</span><span class="p">.</span><span class="n">img</span>
</pre></div>
<p>So now we have a kernel/initrd.img, containing the kickstart file. You can modify grub(2) to add a new menu entry, make it the default one for next reboot and enjoy. But I usually prefer not doing that, if you need someone to reset that node remotely if something wrong happens, so instead of modifying grub(2), I just use kexec to reboot directly with the new kernel (without having to power cycle the node) :</p>
<div class="highlight"><pre><span></span># <span class="nv">can</span> <span class="nv">be</span> <span class="nv">changed</span> <span class="nv">to</span> <span class="nv">something</span> <span class="k">else</span>, <span class="k">if</span> <span class="k">for</span> <span class="nv">example</span> <span class="nv">node</span> <span class="nv">is</span> <span class="nv">running</span> <span class="nv">another</span> <span class="nv">distro</span> <span class="nv">not</span> <span class="nv">using</span> <span class="nv">yum</span> <span class="nv">as</span> <span class="nv">package</span> <span class="nv">manager</span>
<span class="nv">yum</span> <span class="nv">install</span> <span class="o">-</span><span class="nv">y</span> <span class="nv">wget</span> <span class="nv">kexec</span><span class="o">-</span><span class="nv">tools</span>
<span class="nv">kexec</span> <span class="o">-</span><span class="nv">l</span> <span class="nv">vmlinuz</span> <span class="o">--</span><span class="nv">append</span><span class="o">=</span><span class="s1">'</span><span class="s">net.ifnames=0 biosdevname=0 ksdevice=eth0 inst.ks=file:/ks.cfg inst.lang=en_GB inst.keymap=be-latin1 ip=your.ip netmask=your.netmask gateway=your.gw dns=your.dns</span><span class="s1">'</span> <span class="o">--</span><span class="nv">initrd</span><span class="o">=</span><span class="nv">initrd</span>.<span class="nv">img</span> <span class="o">&&</span> <span class="nv">kexec</span> <span class="o">-</span><span class="nv">e</span>
</pre></div>
<p>As you can see in the append line, I just tell anaconda/kernel to <em>not</em> use the new nic naming (default now in CentOS 7, and sometimes hard to guess in advance), assuming that eth0 is the one to use (verify carefully that !), and the traditional ks= line in fact now just points to /ks.cfg ( initrd.img being / ). The rest is self-explained.</p>
<p>The other cool stuff, is that you can use the same "inject" technique but for Virtual Machines installed through virt-install : it supports injecting directly files in the initrd.img, so easier than for bare metal nodes : you just have to use two parameters for virt-install : </p>
<ul>
<li>--initrd-inject=/path/to/your/ks.cfg</li>
<li>--extra-args "console=ttyS0 ks=file:/ks.cfg”</li>
</ul>
<p>Hope this helps </p>Modifying Anaconda behaviour without rebuilding the whole install media2011-06-11T14:54:00+02:002011-06-11T14:54:00+02:00Fabian Arrotintag:arrfab.net,2011-06-11:/posts/2011/Jun/11/modifying-anaconda-behaviour-without-rebuilding-the-whole-install-media/<p>One thing that I had to have a look at (during CentOS 6 QA), is the way
<a href="http://fedoraproject.org/wiki/Anaconda">anaconda</a> (the Red
Hat/Fedora/CentOS installer) pre-defines some 'tasks' . People used to
those kind of install know what I'm talking about : the "Mininal",
"Desktop", "Basic Server" and other choices you have during setup. From
that first selection, you can decide (or not) to customize the software
selection which then leads you to a screen containing categories /
groups / packages defined in the comps.xml file present under /repodata
on the tree/install media.</p>
<p>If you don't 'see' which screen i'm talking about, a small screenshot of
the upcoming CentOS 6 will explain better than words :</p>
<p><img alt="Anaconda in CentOS" src="/images/anaconda-centos.png" title="anaconda-centos"></p>
<p>Those pre-defined tasks aren't defined in the comps.xml file but rather
at build time within anaconda. Fine but how can you 'modify' anaconda
behaviour and test it without having to patch anaconda SRPM, rebuild it
and launch a new build to generate the tree and install medias ? Easy ,
thanks to a simple file on the tree !</p>
<p>People wanting to modify anaconda behaviour at install time without
having to regenerate the whole tree can just create a small file
(updates.img) , put it in the /images directory in …</p><p>One thing that I had to have a look at (during CentOS 6 QA), is the way
<a href="http://fedoraproject.org/wiki/Anaconda">anaconda</a> (the Red
Hat/Fedora/CentOS installer) pre-defines some 'tasks' . People used to
those kind of install know what I'm talking about : the "Mininal",
"Desktop", "Basic Server" and other choices you have during setup. From
that first selection, you can decide (or not) to customize the software
selection which then leads you to a screen containing categories /
groups / packages defined in the comps.xml file present under /repodata
on the tree/install media.</p>
<p>If you don't 'see' which screen i'm talking about, a small screenshot of
the upcoming CentOS 6 will explain better than words :</p>
<p><img alt="Anaconda in CentOS" src="/images/anaconda-centos.png" title="anaconda-centos"></p>
<p>Those pre-defined tasks aren't defined in the comps.xml file but rather
at build time within anaconda. Fine but how can you 'modify' anaconda
behaviour and test it without having to patch anaconda SRPM, rebuild it
and launch a new build to generate the tree and install medias ? Easy ,
thanks to a simple file on the tree !</p>
<p>People wanting to modify anaconda behaviour at install time without
having to regenerate the whole tree can just create a small file
(updates.img) , put it in the /images directory in the tree. Anaconda
(when installing over the network, http/ftp/nfs) always try to see if an
updates.img file exists, and if so, use it. Fine, so I could easily try
to "patch" it without having to modify the whole tree.</p>
<p>Creating that updates.img (it's just a ext2 filesystem on top) is really
easy :</p>
<div class="highlight"><pre><span></span><span class="nv">dd</span> <span class="k">if</span><span class="o">=/</span><span class="nv">dev</span><span class="o">/</span><span class="nv">zero</span> <span class="nv">of</span><span class="o">=/</span><span class="nv">tmp</span><span class="o">/</span><span class="nv">updates</span>.<span class="nv">img</span> <span class="nv">bs</span><span class="o">=</span><span class="mi">1</span><span class="nv">k</span> <span class="nv">count</span><span class="o">=</span><span class="mi">1440</span>
<span class="nv">losetup</span> \`<span class="nv">losetup</span> <span class="o">-</span><span class="nv">f</span>\` <span class="o">/</span><span class="nv">tmp</span><span class="o">/</span><span class="nv">updates</span>.<span class="nv">img</span>
<span class="nv">losetup</span> <span class="o">-</span><span class="nv">a</span><span class="o">|</span><span class="nv">grep</span> <span class="nv">updates</span>.<span class="nv">img</span>
<span class="nv">mkfs</span>.<span class="nv">ext2</span> <span class="o">/</span><span class="nv">dev</span><span class="o">/</span><span class="nv">loop3</span> \# <span class="nv">was</span> <span class="nv">loop3</span> <span class="nv">in</span> <span class="nv">my</span> <span class="nv">case</span>
<span class="nv">mkdir</span> <span class="o">/</span><span class="nv">mnt</span><span class="o">/</span><span class="k">loop</span> <span class="c1">; mount -o loop /tmp/updates.img /mnt/loop/ ; ll</span>
<span class="o">/</span><span class="nv">mnt</span><span class="o">/</span><span class="k">loop</span>
<span class="nv">drwx</span><span class="o">------</span>. <span class="mi">2</span> <span class="nv">root</span> <span class="nv">root</span> <span class="mi">12288</span> <span class="nv">Jun</span> <span class="mi">11</span> <span class="mi">15</span>:<span class="mi">43</span> <span class="nv">lost</span><span class="o">+</span><span class="nv">found</span>
</pre></div>
<p>From now, it's just a matter of putting the new files that you want to
test and that will "overwrite" at run-time the defaults anaconda ones.</p>
<p>(in our current example, it was the installclasses/rhel.py that needed
to be modified, so I just had to create a installclasses dir and drop my
version of rhel.py in there on the loop device)</p>
<p>When you're done, umount the updates.img, copy it to
/path/to/your/install/tree/images , restart a http install (verify that
permissions and selinux contexts are of course correct !) and enjoy !</p>
<p>Easier and faster. Thanks to the Anaconda team which decided to permit
modifying the anaconda behaviour at run-time with a simple file :-)</p>