Ale Mania - Gose

This weeks visit to the local bottle shop brought a german Gose into my fridge. The label reads, among the usual suspects, coriander, sea salt and lactic acid. It doesn't however list wheat as an ingredient.

The bottle overcarbonated. Great head. Smells like coriander. Very funky taste, slight clove aroma. Tart but mild sourness overall. Characteristically hopped at 14 IBU.

Compared to some belgians (oude geuze specifically) the aroma components could be more varied. Ale Manias Gose is bright and floral, I like more complex sour beers. Let's hope we get more sour beers from german brewers.

Rating: 4 points out of five.

Modernist Rillette

I had a guest on sunday and we usually sit there talking all day. Even if you're sitting all day you need an occasional snack to gorge on. My eyes were set on the Rillette from Modernist Cuisine.

So on saturday I went to the butcher. I explained to him that I wanted beef shank. After I assured him that I wanted to cook the meet for at least an hour, he handed me two very nice slices ox shank. MC calls for molten tallow to be added to a fluid gel. The first problem was to find tallow, the second problem was apparent after I added the substitute - lard in this case - to the "liquid gel".

The gel wasn't liquid at all, it was mostly grainy. Sadly this resulted in a grainy texture of the liquid gel/lard mixture. I chilled the meat overnight, which meant that the meat wasn't quite tender enough to give nice rillette. The taste however is impeccable. And I would note that you really need to add a lot of pepper, since the lard seems to absorb it easily.

Recovering from a botched LV resize

Two months ago a coworker of mine and me were taking an exam together. Everything seems to be going along smoothly, when 45 minutes into the exam the coworker starts to talk to the instructor, gesticulating wildly. I can overhear the instructor giving him two options: either figure it out or reset the machine to the beginning state. Now the exam was hands on. That is you have to setup service, test and

debug on your machine. Out of the 150 minutes available he opted to reset at 45 minutes into the exam. He was visibly distraught.

It turned out, that he botched the resize of a filesystem. He had dutifully unmounted the volume in question and resized the logical volume. The oversight was that he didn't shrink the filesystem. When he rebooted the system there was a kernel panic. This was the situation he was confronted with. He was half into the exam and the system wouldn't boot up anymore.

The coworker choose to reset the machine and start over with the exam. Can you do better? The filesystem was on an ephemeral mount-point uncritical to the functioning of the system. You can still boot into single-user mode and start emergency procedures.

Let's get us into the situation:

  [root@localhost ~]# lvs
  LV      VG       Attr   LSize  Origin Snap%  Move Log Copy%  Convert
  lv_root VolGroup -wi-ao 32.00g                                      
  lv_swap VolGroup -wi-ao  3.88g                                      
  testlv  testvg   -wi-a-  4.00g

Add the following line to /etc/fstab:

  /dev/mapper/testvg-testlv /test                      ext4     defaults 1 1

Create the mountpoint and test the mount:

  [root@localhost ~]# mkdir /test
  [root@localhost ~]# mount /test
  [root@localhost ~]# ls /test/
  lost+found  test.1.0  test.txt
  [root@localhost ~]# cat /test/test.txt 
  test

Now to the resize. Note that the -r option to lvresize resizes the underlying filesystem before touching the logical volume. This ensures a proper resize, but:

  [root@localhost ~]# umount /test
  [root@localhost ~]# lvresize /dev/mapper/testvg-testlv -L 2G
    WARNING: Reducing active logical volume to 2.00 GiB
    THIS MAY DESTROY YOUR DATA (filesystem etc.)
  Do you really want to reduce testlv? [y/n]: y
    Reducing logical volume testlv to 2.00 GiB
    Logical volume testlv successfully resized
  [root@localhost ~]# shutdown -rf now

Now the system reboots to the following screen:

It's hosed. Enter the root password. The slash partition is not affected by this operation since it's on a different volume group. Now remount slash writable:

  (Repair filesystem) 0 # mount -o remount,rw /

Find the necessary backup of the metadata. This is located in /etc/lvm/archive on my system.

Contrary to this /etc/lvm/backup contains the current configuration. Use your editor to

inspect it, to ascertain you have the correct file. Then pass the file and the volume group name to the vgcfgrestore command:

  (Repair filesystem) 10 # vgcfgrestore -f /etc/lvm/archive/testvg_00012_1773263284.vg testvg

At this point you can reboot the system by hitting control-D. It should startup right away and you should be able to verify that the filesystems integrity has been unharmed:

  [root@localhost ~]# cat /test/test.txt 
  test
  [root@localhost ~]# umount /test
  [root@localhost ~]# fsck /dev/mapper/testvg-testlv 
  fsck from util-linux-ng 2.17.2
  e2fsck 1.41.12 (17-May-2010)
  /dev/mapper/testvg-testlv: clean, 13/262144 files, 543313/1048576 blocks

There you go. In case you botch the resize, there's no need to panic. Restore the volume group to

a known good state instead of doing a full backup or in our case a reset of the machine. There's

much time to be saved in doing it this way.

Better yet hit man 8 lvresize and lookup the -r option and heed the warnings of your tools.

Above all: keep calm.

Weißer Nougat

Thomas Kellers zugänglichstes Buch soll das Neueste sein: Bouchon Bakery. Ich habe gerade mein Exemplar bekommen und musste am selben Abend noch etwas ausprobieren. Nur was? Mein Auge ist auf den weißen Nougat gefallen.

Im Zucker kochen besitze ich eine gewisse Routine, aber Vorsicht ist geboten, wenn man mit 145°C heißen Zutaten arbeitet.

Weißer Nougat Wat? Auch bekannt als türkischer Honig. Benutzen Sie wie Keller vorschlägt Lavendelhonig, dann ist es eine Spezialität der Nord-Provence. Das Rezept hier ist vereinfacht, denn ich konnte so kurzfristig an jenem Abend weder Kakaobutter noch Glukose auftreiben.

Zutaten

  • 360g Honig

  • 700g Zucker

  • 160ml Wasser

  • 2 Eiweiß

  • 1 TL Zucker

  • 250g Mandeln

  • 200g Pistazien in der Schale

  • 20g Kokosfett

  • Küchenmaschine

  • 2 Zuckerthermometer

Das Vorgehen ist ganz einfach. Ca. ein Drittel Honig, zwei Drittel Zucker und das ganze Fett wird in Eiweiss gerührt. Dazu gesellen sich 250g Mandeln und 100g (geschälte) Pistazien. Vom Ablauf her werden die Eiweiß schaumig (

aber nicht steif!) geschlagen, und Honig und Zucker sollen nacheinander ihre Temperatur erreichen, damit sie direkt in die Eiweißmasse eingearbeitet werden können. Dann wird die Masse nur noch kühl geschlagen und die Nüsse und ein bisschen Fett untergehoben.

  1. Mandeln und Pistazien schälen, leicht anrösten und in Schalen bereitlegen.
  2. Den Zucker mit dem Wasser zusammen im ersten Topf ansetzen.
  3. Den Honig im zweiten Topf ansetzen
  4. Das Eiweiß bei hoher Geschwindigkeit schaumig (aber nicht steif) schlagen, 1 TL Zucker unterheben
  5. Hat der Honig 125°C erreicht, wird der Mixer auf langsam gestellt und der Honig unter das Eiweiß gezogen
  6. Kurz darauf wenn der Zucker auf 145°C gestiegen ist, wird dieser Langsam unter die Masse gezogen
  7. Währenddessen lösen Sie ein 20g Stück Kokosfett (Keller empfiehlt Kakaobutter) auf kleiner Flamme flüssig werden und ziehen dies wieder unter die Masse
  8. Lassen Sie die Masse bei eingeschaltetem Mixer 10 Minuten (Keller empfiehlt 16) kalt werden.
  9. Nun geben Sie die Nüsse dazu und warten noch eine Minute

Die ganze Masse wird zwischen zwei Blätter beschichtetes Backpapier gegeben und darf dann über Nacht bei Zimmertemperatur durchkühlen. Allerdings kann das bei diesem heißen Osterwetter immer noch eine ziemlich klebrige

Sache sein. Guten Appetit.

Das Ganze ist sehr lecker geworden. Nur wie gesagt etwas klebrig.

Moving an LVM mirror log

Suppose you created an LVM mirror but your mirror log is on the wrong SAN device. SAN migration won't help you since these LUNs exist on different SAN machines altogehter. But how do you move the mirror log?

Let's create an LVM mirror:

  Last login: Sat Nov 23 17:36:23 2013
  [root@leonis ~]# ls /dev/sd*
  /dev/sda  /dev/sdb
  [root@leonis ~]# pvcreate /dev/sda
    Writing physical volume data to disk "/dev/sda"
    Physical volume "/dev/sda" successfully created
  [root@leonis ~]# pvcreate /dev/sdb
    Writing physical volume data to disk "/dev/sdb"
    Physical volume "/dev/sdb" successfully created
  [root@leonis ~]# vgcreate vgmir /dev/sda /dev/sdb
    Volume group "vgmir" successfully created
  [root@leonis ~]# lvcreate -l 45%FREE vgmir -n lvmir
    Logical volume "lvmir" created
  [root@leonis ~]# lvconvert -m 1 /dev/vgmir/lvmir 
    vgmir/lvmir: Converted: 0.2%
    vgmir/lvmir: Converted: 2.2%
  ...
    vgmir/lvmir: Converted: 99.5%
    vgmir/lvmir: Converted: 100.0%

Now lvs -a -o +devices will show you the detailed mirror configuration:

  LV               VG       Attr     LSize Pool Origin Data%  Move Log        Copy%  Convert Devices
  lvmir            vgmir    mwi-a-m- 3.59g                         lvmir_mlog 100.00         lvmir_mimage_0(0),lvmir_mimage_1(0)
  [lvmir_mimage_0] vgmir    iwi-aom- 3.59g                                                   /dev/sda(0)
  [lvmir_mimage_1] vgmir    iwi-aom- 3.59g                                                   /dev/sdb(0)
  [lvmir_mlog]     vgmir    lwi-aom- 4.00m                                                   /dev/sdb(920)

In my case /dev/sdb and /dev/sdc were on different SAN machines and one machine was loaded quite heavily. Meaning we got a 160 IOPS maximum out of the entire mirror. Now all credit goes to our SAN admins for getting the utilization of the older SAN machine to the point where the LUN could easily deliver 4000 IOPS.

However there's one thing to consider: the mirror log. The mirror log generally incurs extra IOPS, so you want to create it on the faster/less loaded SAN machine. Two approaches immediately come to mind: a) convert the mirror from on disk log to in-memory then recreating it on the faster SAN machine; b) dropping the slower mirror leg entirely and recreating the mirror with the faster SAN as the mirror device.

Let's drop the mirror:

  [root@leonis ~]# lvconvert -m 0 vgmir/lvmir /dev/sdb
    Logical volume lvmir converted.

And recreate the mirror with the mirror log on ``/dev/sda``::

  [root@leonis ~]# lvs -a -o +devices,seg_pe_ranges
    LV      VG       Attr     LSize Pool Origin Data%  Move Log Copy%  Convert Devices        PE Ranges         
    lvmir   vgmir    -wi-a--- 3.59g                                            /dev/sda(0)    /dev/sda:0-919    
  [root@leonis ~]# lvconvert -m 1 vgmir/lvmir /dev/sdb:0-919 /dev/sda
    vgmir/lvmir: Converted: 0.2%
    vgmir/lvmir: Converted: 2.7%
    vgmir/lvmir: Converted: 99.8%
    vgmir/lvmir: Converted: 100.0%
  [root@leonis ~]# lvs -a -o +devices
    LV               VG       Attr     LSize Pool Origin Data%  Move Log        Copy%  Convert Devices                            
    lv_root          VolGroup -wi-ao-- 3.45g                                                   /dev/vda2(0)                       
    lv_swap          VolGroup -wi-ao-- 3.88g                                                   /dev/vda2(882)                     
    lvmir            vgmir    mwi-a-m- 3.59g                         lvmir_mlog 100.00         lvmir_mimage_0(0),lvmir_mimage_1(0)
    [lvmir_mimage_0] vgmir    iwi-aom- 3.59g                                                   /dev/sda(0)                        
    [lvmir_mimage_1] vgmir    iwi-aom- 3.59g                                                   /dev/sdb(0)                        
    [lvmir_mlog]     vgmir    lwi-aom- 4.00m                                                   /dev/sda(920)

The trick here is, since we don't have an option to specify the mirror leg explicitely we specify a PE range on /dev/sdb and the full /dev/sda and LVM figures out where to place the segments.

Let's convert that to a core mirror:

  [root@leonis ~]# lvconvert --mirrorlog core vgmir/lvmir
    Logical volume lvmir converted.
  [root@leonis ~]# lvs -a -o +devices
    LV               VG       Attr     LSize Pool Origin Data%  Move Log Copy%  Convert Devices                            
    lv_root          VolGroup -wi-ao-- 3.45g                                            /dev/vda2(0)                       
    lv_swap          VolGroup -wi-ao-- 3.88g                                            /dev/vda2(882)                     
    lvmir            vgmir    mwi-a-m- 3.59g                             100.00         lvmir_mimage_0(0),lvmir_mimage_1(0)
    [lvmir_mimage_0] vgmir    iwi-aom- 3.59g                                            /dev/sda(0)                        
    [lvmir_mimage_1] vgmir    iwi-aom- 3.59g                                            /dev/sdb(0)

Then convert it back to a on-disk mirror::

  [root@leonis ~]# lvconvert --mirrorlog disk vgmir/lvmir /dev/sdb
    Logical volume lvmir converted.
  [root@leonis ~]# lvs -a -o +devices
    LV               VG       Attr     LSize Pool Origin Data%  Move Log        Copy%  Convert Devices                            
    lv_root          VolGroup -wi-ao-- 3.45g                                                   /dev/vda2(0)                       
    lv_swap          VolGroup -wi-ao-- 3.88g                                                   /dev/vda2(882)                     
    lvmir            vgmir    mwi-a-m- 3.59g                         lvmir_mlog 100.00         lvmir_mimage_0(0),lvmir_mimage_1(0)
    [lvmir_mimage_0] vgmir    iwi-aom- 3.59g                                                   /dev/sda(0)                        
    [lvmir_mimage_1] vgmir    iwi-aom- 3.59g                                                   /dev/sdb(0)                        
    [lvmir_mlog]     vgmir    lwi-aom- 4.00m                                                   /dev/sdb(920)

Converting the mirror-log to a core-log is clearly much faster and the only drawback seems to be that in case of a reboot the whole mirror will be resynced which is just as good as resyncing the mirror in the first place.

tcpnice & tcpkill

Have you ever thought about killing a particular TCP connection or just

shaping that traffic down to acceptable levels?

dsniff is a little collection of tools that were build for security

analysis. They include two tools that I'm interested in: tcpnice and tcpkill.

tcpkill is the easier tool to comprehend. It takes the following form:

  tcpkill -9 port 22

The -9 part is a severity specifier, the port 22 part is a tcpdump

filter argument. Internally tcpkill uses libpcap to open a raw socket,

listening to anything that passes the filter (i.e. port 22). For

every TCP packet received, it constructs a corresponding RST packet

and injects it over a raw socket into the host. Increasing the

severity means doing this process multiple times. It's a simple way to

kill just the right connections.

tcpnice is a little different. It takes the following form:

  tcpnice [-I] -n X port 80

Again the port 80 is a tcpdump filter argument. The X is a nice

value from 1 to 20, where larger values indicate a slower connection.

Again this works by opening a pcap session and then injecting packets

over a raw socket. But this time we inject a TCP segment with a new TCP window size

The -I option additionally injects a ICMP source quench packet into the raw socket to further quench the resource hunger of your connections.

This works for well behaved programs, but if your target uses raw

sockets to implement some kind of attack this is not going to work.

Scharfe Kartoffelsuppe

1,5 kg Kartoffeln. 4 kleine Pfaumen-Tomaten. 2 gut angetrocknete Pepperoni. 2 Zehen Knoblauch. 2 Tassen Bruehe (irgendeine). 300g Gelderlaender Speck. Speck gut anbraten, mit Bruehe und Kartoffeln ansetzen und dann den Topf mit Wasser auffuellen, bis die Kartoffeln abgedeckt sind. Wenn die Kartoffeln gar sind, einen Teil der Kartoffeln herausnehmen und durch die Muehle schieben/stampfen. Kartoffelbrei wieder zur Suppe geben.

APOD to Desktop Wallpaper

Recently I had a meeting with one of our customers. I was setting up my laptop, plugging it into the beamer. Immediately the customer raised a brow. The beamer was showing a gorgeous HD image of the deepwater horizon oil rig blowing up. The following smalltalk was interesting.

I decided to show some nicer images the next time I'd meet them and this evening I got around to writing a little Perl snippet to download the Astronomy Picture of the Day from apod.nasa.gov <http://apod.nasa.gov>_ and set it as the Windows wallpaper. It uses LWP::get to fetch the main page. It fiddles with the text and downloads the linked image to $dlbase, finally using Win32::API to call SystemParametersInfo to set the background.

Be warned: during testing not every valid .jpeg actually would display as a desktop wallpaper. Another thing is that you really want to specify an absolute path, when calling SystemParametersInfo, or it wont display correctly after logging out and back in again, hence the $dlbasew variable.

    #!/usr/bin/perl  
    use strict;  
    use warnings;

    use Win32;  
    use Win32::API;  
    use LWP::Simple;  
    require Carp;

    # for both constants see winuser.h

    use constant SPI_SETDESKWALLPAPER  => 20;  
    use constant SPIF_UPDATEANDSENDINI => 3; # SPIF_UPDATEINIFILE || SPIF_SENDWININICHANGE

    my $apodbase = 'http://apod.nasa.gov/';  
    my $dlbase = 'c:/Users/mmeyer/Downloads';  
    my $dlbasew = 'c:\\Users\\mmeyer\\Downloads\\';

    chdir $dlbase or die "Couldnt chdir to $dlbase: $!";

    my $content = get($apodbase) or die "Couldn't download image: $!";

    Carp::croak 'Content doesn\'t match' unless $content =~ m/<IMG SRC="(.*)"/g;

    my $urlend = $1;

    Carp::croak 'No url found' unless $urlend =~ m|([^/]+)$|;  
    my $targ = $1;

    my $status = getstore($apodbase . $urlend, $targ);  
    Carp::croak "Couldn't store image: $status" unless is_success($status);

    my $spf = Win32::API->new('user32','SystemParametersInfo', 'IIPI', 'I')  
      or Carp::croak "Could not import function.\n";

    $spf->Call(SPI_SETDESKWALLPAPER, 0, $dlbasew . $targ, SPIF_UPDATEANDSENDINI)  
      or Carp::croak "Could not set wallpaper:\n" . Win32::GetLastError();

    exit;

See my github scratch repo.

Simple Mojolicious RSS feed

At work we're thriving to conform to the ITIL guidelines. This entails a detailed change management for our infrastructure. Change dates, authors and possible impact are tracked in our Technical Change Management System.

This is all nice and shiny, but how do you get this information to the individual administrator? To put it politely, the interface itself doesn't invite casual browsing. However that's a technical problem. And this time the solution was to write a simple Perl script using Mojolicious. Mojolicous documentation is sparse at the moment, but the cheat sheet contains a note about simply calling

$self->render(format => 'rss');

during the render. I did just that, supplied a proper rss template and it just worked out of the box. The following code just dumps some test data into port 80.

  use Mojolicious::Lite;

  use strict;
  use warnings;

  my $data = [
  { author => 'Mark', title => 'Post to blog', description => 'Yadda.',  
    date => 'Wed, 02 Oct 2002 13:00:00 GMT'},  
  { author => 'Mork', title => 'Scratch an itch', description => 'Yadda',  
    date => 'Wed, 02 Oct 2002 15:00:00 +0200'},  
  ];

  get '/changefeed' => sub {  
    my $self = shift;

    $self->stash('items', $data);

    $self->render(format => 'rss');  
    $self->render('changefeed');  
  };

  app->start;

  __DATA__

  @@ changefeed.rss.ep  
  <?xml version="1.0" encoding="utf-8"?>  
  <rss version="2.0">

  <channel>  
    <title>The Internation House of Mojo</title>  
    <link>http://houseofmojo.com</link>  
    <description>Current changes in our IT</description>  
    <copyright>The Witch</copyright>

  % foreach my $item (@$items) {  
    <item>  
      <title><%= $item->{title} %></title>  
      <description><%= $item->{description} %></description>  
      <author><%= $item->{author} %></author>  
      <pubDate><%= $item->{date} %></pubDate>  
    </item>  
  % }

  </channel>  
  </rss>

Testing is simple, save it to changefeed.pl and hit

  perl changefeed.pl daemon

The above fragment is half code, half template. Even for someone who is dead set against using a framework for web development this is a good ratio. Of course Mojolicous tagline is to grow your application organically by introducing advanced concepts as you go.

If you want to generate the data from the database, the gotcha is to generate an RFC822 date. You can do this either by using DateTime::Format or you can format the date right in the database. I prefer the latter. In MS SQL Server this looks like the following.

  left(datename( dw, your_date_column ), 3 ) + ', ' +  
  convert( varchar(20), your_date_column, 113 ) + ' GMT' as date

Stachelbeer-Quarkkuchen

Rezeptewiki hat einen guten Quarkkuchen. Alles halbieren. Die Margarine durch Butter ersetzen. Den Boden weglassen und stattdessen Semmelbroesel in die Form. Zubereiten wie angegeben und mit Stachelbeeren auffuellen. Ergibt zwei 30cm Tarte Formen.