A quick anaconda trick

Here’s a quick anaconda solution that I am now using in some of my kickstart files…

I wanted to bootstrap a machine and do all the partitioning and logical volume creation, but not format or mount one of the logical volumes. The magic parameter I needed was:

--fstype=none

This seems to work perfectly for me. It’s not 100% intuitive to me, but it does work. I hope it’s not an accidental bug in the anaconda code! The full text of my partitioning is:

clearpart --all --drives=sda
part /boot --fstype=ext4 --size=1024
part pv.01 --grow --size=1024
volgroup VolGroup00 --pesize=4096 pv.01
logvol / --fstype=ext4 --name=root --vgname=VolGroup00 --size=65536
logvol swap --name=swap --vgname=VolGroup00 --size=16384
logvol /foo --name=foo --vgname=VolGroup00 --fstype=none --grow --size=1

Now all that anaconda is missing is support for RAID1 EFI /boot.

Happy hacking,

James

Automatic hiera lookups in puppet 3.x

Dear readers,

I’ve started the slow migration of code from puppet 2.6 all the way to 3.x+. There were a few things I wasn’t clear on, so hopefully this will help to discuss these and make your migration easier!

I used hiera in 2.6, and I actually like it a lot so far. I was concerned that automatic lookups would pull in values that I wasn’t expecting. This is not the case or a worry. Let’s dive in and let the code speak:

# create a class in a module or site.pp for testing...
class foo(
        $a = 'apple',
        $b = 'banana'
) {
        notify { 'foo':
                message => "a is: ${a}, b is: ${b}",
        }
}

and

# define it using :: as a prefix because we want to search in the
# top level, module namespace. optional if we only have one foo.
class { '::foo':
}

and

# /etc/puppet/hiera.yaml
:backends:
        - yaml

:hierarchy:
        - globals
        - whatever
        - youlike

:yaml:
        :datadir: /etc/puppet/hieradata/

and

# /etc/puppet/hieradata/whatever.yaml (because of - whatever above)
---
foo::a: 'somevalue' # this many colons is actually valid syntax
dude: 'sweet'

will produce:

[...]
Notice: a is somevalue, b is: banana
Notice: Finished catalog run in 3.14159265359 seconds

This is the automatic lookup. You probably have zero risk of collision with earlier data in your hiera yaml files, because these lookups use keys that match the classname::paramname pattern. If you had used :: (double colons) in your keys before, then you’re insane, and you should check for any collisions! The downside to this is that my whatever.yaml looks awkward with all those colons, but I got over that very quickly.

The full lookup order is first:

# directly specified values first (of course)
class { '::foo':
        a => 'this value is used first if set.',
}

and then:

# values matching an appropriate yaml key:
---
foo::a: 'this value is used next if found.'

and finally:

class foo(
        $a = 'this parameter default value is used last.'
        $b = 'b is still for banana...'
) {
        # do stuff...
}

all as detailed in: http://projects.puppetlabs.com/issues/11608. Finding this link and setting me down the path to knowledge was all thanks to eric0 in #puppet. Thanks Eric!

Make sure to reload your puppetmaster after you make any changes to /etc/puppet/hiera.yaml, and as always:

Happy hacking,

James

Picking up the pieces after a Fedora 18 install

I love GNOME and Fedora, but “upgrading” from Fedora 17 to 18 did not go well for me. I recommend you wait until either these are all fixed, or Fedora 19+ suits your needs. Here are a list of problems I had, and some workarounds. Hopefully proper patches to these bugs will get merged quickly, so that you don’t need to use these fixes.

Problem: Boot fails after upgrade from Fedora 17 to Fedora 18. I used the new “fedup” method.

Workaround: I did a fresh install. Make sure you have backups first, of course. I didn’t feel like spending a lot of time debugging why it broke.

Problem: The <Backspace> key no longer goes “up” in nautilus. I hope this wasn’t a “feature removal”.

Workaround: Add:

(gtk_accel_path "<Actions>/ShellActions/Up" "BackSpace")

to your: ~/.config/nautilus/accels and restart nautilus of course.

Problem: Split view (extra pane) functionality is missing in nautilus 3.6

Workaround: The GNOME developers plan to eventually replace this in a similar form. Until then, you can install the nemo file manager, which is a fork of nautilus 3.4 and is packaged in Fedora 18. (yum install nemo nemo-open-terminal)

Problem: GNOME Shell background is entirely black in overview mode.

Workaround: Using gnome-tweak-tool, under the “Desktop” section, set “Have file manager handle the desktop“, to “OFF“. Unfortunately, this disables viewing of files on your desktop. This wasn’t a problem in Fedora 17.

Problem: Restarting the X server with the familiar Control-Alt-Backspace, can’t be enabled in the keyboard shortcuts menu as it used to.

Workaround: This option is now hidden in the gnome-tweak-tool under typing: terminate.

I hope this scratches your itches!

Happy hacking,

James

How to send and receive files like a professional

Everyone needs to send and receive files sometimes. Traditionally people send files as email attachments. This still works great, and supports encryption, but many mail servers are slow and cap the upper file size limit.

ICQ was a great solution back in the 1990’s, but those days are now over. (I still remember my number.)

A lot of folks use dropbox, which requires a dropbox account, and for you to trust them with your files.

If you want a simple solution that doesn’t need internet access (if you’re on a LAN, for example) you can use droopy and woof. These are two shell scripts that I keep in my ~/bin/. Droopy lets you receive a file from a sender, and woof lets you send one their way. Unfortunately, they don’t support ssl. This could be a project for someone. (Hint)

I recently patched droopy to add inline image support. I’ve emailed my patch to the author, but until it gets merged, you can get my patched version here. (AGPLv.3+)

Hopefully these are helpful to you.

Happy hacking,

James

Renaming a GNOME keyring (for seahorse, the passwords and keyrings application)

The GNOME Keyring is a great tool to unify password management across the desktop. Sadly, Firefox is the one application that doesn’t support this natively. (Chrome actually does!)

Seahorse is a useful tool to browse and manage your keyrings. Each keyring is physically stored in: ~/.gnome2/keyrings/$something.keyring

Usually the “$something“, matches the name of the keyring, however the real name comes from within the file. I had an older ubuntu machine running GNOME, and I wanted to import my keyring. Here’s how I did it:

  1. Copy ~/.gnome2/keyrings/login.keyring (from the ubuntu machine) to ~/.gnome2/keyrings/ubuntu.keyring (on the new machine)
  2. Open up seahorse and change the keyring password of this “login” keyring to the empty string. This stores the passwords in a plain text format, which is briefly necessary.
  3. Edit the ubuntu.keyring file. There will be an obvious “display-name” section at the top of the file to edit. I changed it to:
    [keyring]
    display-name=ubuntu
  4. After restarting seahorse, I now changed the password back to something secure. If this process worked, you should already see the new keyring name in your keychain list.

Obviously this is a bit of a hack, and a proper rename function would be preferable, but until that exists, hopefully this will fill a niche if you’re stuck and you want to pull in an old keyring into your already populated $HOME.

Happy hacking,

James

SElinux causes pain when using puppet 2.x with hiera

So hiera wasn’t working when used through my puppetmaster. It worked perfectly when I was running my scripts manually with: puppet apply site.pp but the moment I switched over to regular puppetmasterd usage, everything went dead.

I realized a while back, that I could always expect some hiera failures from time to time. Whether this is hiera’s fault or not is irrelevant, the relevant part is that I quickly added:

$test = hiera('test', '')    # expects: 'Hiera is working!'
if "${test}" == '' {
    fail('The hiera function is not working as expected!')
}

to my site.pp and now I don’t risk breaking/changing a node because some data is missing. Naturally you’ll need to add a little message in your globals.yaml or similar. If you’re really cautious, you could change the above to an inequality and have your code “expect” a magic message.

To continue with the story, blkperl from #puppet recommended that I try running puppetmasterd manually to watch for any messages it might print. To my surprise, things started working! This just shows you how helpful it is to have a second set of eyes to help you on your way. So why did this work ?

To make a long story short, after following a few dead ends, it hit me, and so I looked in /var/log/audit/audit.log:

type=AVC msg=audit(1358404083.789:55416): avc:  denied  { getattr } for  pid=13830 comm="puppetmasterd" path="/etc/puppet/hiera.yaml" dev=dm-0 ino=18613624 scontext=unconfined_u:system_r:puppetmaster_t:s0 tcontext=unconfined_u:object_r:admin_home_t:s0 tclass=file

to find that selinux was once again causing me pain. When I had started puppetmasterd manually, I was root, which allowed me to bypass selinux rules. Sadly, I like selinux, but since I’m not nearly clever enough to want to learn how to fix this the right way, it just got disabled on another one of my machines.

Running:

restorecon -v /etc/puppet/hiera.yaml

fixed the bad selinux context I had on that file.

Hope this saves you some time and,

Happy hacking,

James

Dynamically including classes in puppet

As you might already know, I like pushing the boundaries of what puppet is able to do. Today, I realized that I needed to include a class by variable name. A simple way to do this is possible with:

$foo = 'world'
class { "hello::${foo}::params":
}

I then realized that you could also do this with the standard include keyword:

$foo = 'world'
include "hello::${foo}::params"

If you’re really insane enough to need to have your include depend on a variable, then this should suit your needs. The advantage of the second form is that if that statement appears more than once, you won’t cause a “duplicate definition” error.

Recently, I’ve been playing around with hiera. For completeness, I will mention one more form. It turns out that the hiera puppet functions offer a hiera_include function. As with all the hiera functions, the second argument lets you specify a default:

$foo = 'world'
hiera_include('...', "hello::${foo}::params")

which finishes off the trilogy. Hope this was useful, now start getting creative and

Happy hacking,

James

 

Clustering virtual machines with rgmanager and clusvcadm

This could be a post detailing how to host clustered virtual machines with rgmanager and clusvcadm, but that is a longer story and there is much work to do. For now, I will give you a short version including an informative “gotcha”.

With my cluster up and running, I added a virtual machine entry to my cluster.conf:

<vm name="test1" domain="somedomain" path="/shared/vm/" autostart="0" exclusive="0" recovery="restart" use_virsh="1" />

This goes inside the <rm> block. As a benchmark, please note that starting the machine with virsh worked perfectly:

[root@server1 ~]# virsh create /shared/vm/test1.xml --console
(...The operation worked perfectly!)

However, when I attempted to use the cluster aware tools, all I got was failure:

[root@server1 ~]# clusvcadm -e 'vm:test1' -m server1
Member server1 trying to enable vm:test1...Failure

Whenever I think I’ve done everything right, but something is still not working, I first check to see if I can blame someone else. Usually that someone is selinux. Make no mistake, selinux is a good thing, however it does still cause me pain.

The first clue is to remember that /var/log/ contains other files besides “messages“. Running a tail on /var/log/audit/audit.log while simultaneously running the above clusvcadm command revealed:

type=AVC msg=audit(1357202069.310:10904): avc:  denied  { read } for  pid=15675 comm="virsh" name="test1.xml" dev=drbd0 ino=198628 scontext=unconfined_u:system_r:xm_t:s0 tcontext=unconfined_u:object_r:default_t:s0 tclass=file
type=SYSCALL msg=audit(1357202069.310:10904): arch=c000003e syscall=2 success=no exit=-13 a0=24259e0 a1=0 a2=7ffff03af0d0 a3=7ffff03aee10 items=0 ppid=15609 pid=15675 auid=0 uid=0 gid=0 euid=0 suid=0 fsuid=0 egid=0 sgid=0 fsgid=0 tty=(none) ses=1 comm="virsh" exe="/usr/bin/virsh" subj=unconfined_u:system_r:xm_t:s0 key=(null)

I am not a magician, but if I was, I would probably understand what all of that means. For now, let’s pretend that we do. Closer inspection (or grep) will reveal:

  • test1.xml” (the definition for the virtual machine)

and:

  • “/usr/bin/virsh” (the command that I expect rgmanager’s /usr/share/cluster/vm.sh script to run)

A quick:

[root@server1 ~]# selinuxenabled && echo t || echo f
t

to confirm that selinux is auditing away, and a short:

[root@server1 ~]# /bin/echo 0 > /selinux/enforce

to temporarily test my theory, and:

[root@server1 ~]# clusvcadm -e 'vm:test1' -m server1
Member server1 trying to enable vm:test1...Success
vm:test1 is now running on server1

Presto change-o, the diagnosis is complete. This is a development system, and so for the time being, I will accept defeat and workaround this problem by turning selinux off, but this is most definitely the wrong solution. If you’re an selinux guru who knows the proper fix, please let me know! Until then,

Happy Hacking,

James

 

How I broke (and fixed) my rgmanager service

Rgmanager, clustat and clusvcadm are useful tools in cluster land. I recently built a custom resource which I added to one of my service chains. Upon inspecting clustat, I noticed:

[root@server1 ~]# clustat
Member Status: Quorate

Member Name                             ID   Status
------ ----                             ---- ------
server1                                 1 Online, Local, rgmanager
server2                                 2 Online, rgmanager

Service Name                   Owner (Last)                   State
------- ----                   ----- ------                   -----
service:service-main-server1   (server1)                      failed

Looking at /var/log/messages, I found:

server1 rgmanager: [script] script:shorewall-reload: start of shorewall-reload.sh failed (returned 2)
server1 rgmanager: start on script "shorewall-reload" returned 1 (generic error)

This was peculiar, because my script didn’t have an exit code of 2 anywhere. It was due to a syntax error (woops)! Moving on with the syntax error fixed, I had trouble getting the service going again. In the logs I found these:

server1 rgmanager: #68: Failed to start service:service-main-server1; return value: 1
server1 rgmanager: Stopping service service:service-main-server1
server1 rgmanager: #12: RG service:service-main-server1 failed to stop; intervention required
server1 rgmanager: Service service:service-main-server1 is failed
server1 rgmanager: #13: Service service:service-main-server1 failed to stop cleanly

Running commands like: clusvcadm -e service-main-server1 didn’t help. It turns out that you have to first convince rgmanager that you truly fixed the problem, by first disabling the service. Now you can safely enable it and things should work smoothly:

clusvcadm -d service-main-server1
clusvcadm -e service-main-server1

Hopefully you’ve now got your feet wet with this clustering intro! Remember that you can look in the logs for clues and run clustat -i 1 in a screen session to keep tabs on things.

Happy Hacking,

James

 

visible close buttons on every firefox tab (including the last one)

After hacking around with a few firefox internals the other day, I decided there was another little annoyance that I had… When I’m acting insane and using my mouse to open and close tabs, the per tab close button disappears when there is only one tab left! This is apparently a feature, and while I can respect it as a default, it certainly isn’t an option for me. Thankfully, there are a lot of common minded individuals on the net, and the (hack) solution already existed. Here’s to explaining it clearly:

  1. Create/edit a userChrome.css file in your profile directory. For me this path was:
    ~/.mozilla/firefox/xxxxxxxx.default/chrome/userChrome.css
  2. Insert the following and restart firefox:
    .tab-close-button {display: -moz-box !important; }
  3. Share and Enjoy!

Happy hacking,

James

PS: In case it’s not blatantly obvious, I didn’t invent any of this, but I am writing about it for your enjoyment, and for my own lousy memory.