Resizing Fixed VirtualBox Disk

I like using fixed disks for VirtualBox VMs. It just gives me a warm fuzzy feelings when it comes to stability. However, that comes at a cost of not being able to resize it easily. If you try, you’ll get VBOX_E_NOT_SUPPORTED error.

vboxmanage modifyhd Test.vdi --resize 262144
 0%...
 Progress state: VBOX_E_NOT_SUPPORTED
 VBoxManage: error: Failed to resize medium
 VBoxManage: error: Resizing to new size 274877906944 is not yet supported
 VBoxManage: error: Details: code VBOX_E_NOT_SUPPORTED (0x80bb0009)
 VBoxManage: error: Context: "RTEXITCODE handleModifyMedium(HandlerArg*)" at line 816

But that doesn’t meant it’s impossible.

First we stop VM and clone its disk to a new image. This will automatically make it dynamic. And it will take a while.

sudo vboxmanage clonemedium "Test.vdi" "Test_new1.vdi"
 0%...10%...20%...30%...40%...50%...60%...70%...80%...90%...100%
 Clone medium created in format 'VDI'. UUID: 96e20ba5-65f6-4248-b42e-ab48683a4cf9

With dynamic disk, we can now resize disk image.

sudo vboxmanage modifymedium disk "Test_new1.vdi" --resize 262144
 0%...10%...20%...30%...40%...50%...60%...70%...80%...90%...100%

But resizing leaves us with dynamic disk which is not what I wanted. So we convert it back to fixed. Will take long time but we again have fixed disk once done.

sudo vboxmanage clonemedium "Test_new1.vdi" "Test_new2.vdi" --variant Fixed
 0%...10%...20%...30%...40%...50%...60%...70%...80%...90%...100%
 Clone medium created in format 'VDI'. UUID: 2bc060b6-0637-43f9-8a55-8ac6bc69ea0d

Since we want direct replacement, we need to copy old UID to the new image.

UUID=`sudo vboxmanage showmediuminfo "Test.vdi" | egrep '^UUID' | awk '{print $2}'`
sudo vboxmanage internalcommands sethduuid "Test_new2.vdi" $UUID
 UUID changed to: 4f046c99-d76a-478f-95cf-f52b07927bd0

And now we can remove intermediate step.

rm "Test_new1.vdi"

Then we copy file system properties of old image to the new one (probably not needed but it doesn’t hurt).

sudo chmod --reference="Test.vdi" "Test_new2.vdi"
sudo chown --reference="Test.vdi" "Test_new2.vdi"

And finally we replace the old image with the new one.

mv "Test_new2.vdi" "Test.vdi"

This whole process will take ages and it will require enough space to copy disk twice. Increasing disk from 128 to 256 GB required 128+128+256 - essentially 4x the disk space. But sometime roundabout way is the only way. :)

Automatic Mangling

Mikrotik routers give you a lot of control over traffic. If you stick with IPv4, it’s possible to nicely subdivide your network and use queues to traffic-shape any user’s bandwidth based on IP address. But things are not as easy when you allow IPv6. Suddenly your simple queues are essentially broken and tracking users becomes quite a lot more difficult.

For exactly that purpose, you have firewall mangle rules. In its simplest form, you just use MAC address as a condition to mark your connection and then you use that connection mark to mark each packet. In Mikrotik’s lingo, that would be something like this:

/ip firewall mangle add
    chain=forward
    src-mac-address=^^12:34:56:78:90:12^^
    connection-state=new
    action=mark-connection
    new-connection-mark=^^some-mark^^

/ip firewall mangle add
    chain=forward
    connection-mark=^^some-mark^^
    action=mark-packet
    new-packet-mark=^^some-mark^^
    passthrough=no

Illustration

Now you can use this packet mark in a simple queue as a condition instead of the subnet or IP. If you go further and create these mange rules in /ipv6 section as you did for /ip, you have yourself an easy way to track traffic even on per-MAC resolution.

The real challenge then becomes entering all these rules into the router. In order to fill this, it’s best to have a script as executing all these commands manually is really error prone. I like to keep this in a file looking something like this:

12:34:56:78:90:ab user1-mark
23:45:67:89:0a:bc user1-mark
34:56:78:90:ab:cd user2-mark

Using this I don’t necessarily track or limit traffic per device but per user. As long as all user’s MAC addresses result in the same mark, queue doesn’t really care.

I mark all automatic entries with !AUTO! in the comment field. Any time I want to update firewall rules, I make sure to delete the old ones first:

OLD_V4_ENTRIES=`ssh router.home "/ip firewall mangle print without-paging" | grep ";;; !AUTO!" | awk '{print $1}' | xargs | tr ' ' ','`
if [[ "$OLD_V4_ENTRIES" != "" ]]; then
    ssh router.home "/ip firewall mangle remove numbers=$OLD_V4_ENTRIES"
fi

OLD_V6_ENTRIES=`ssh router.home "/ipv6 firewall mangle print without-paging" | grep ";;; !AUTO!" | awk '{print $1}' | xargs | tr ' ' ','`
if [[ "$OLD_V6_ENTRIES" != "" ]]; then
    ssh router.home "/ipv6 firewall mangle remove numbers=$OLD_V6_ENTRIES"
fi

With old entries gone, we can add new entries using something like this:

cat ^^~/MAC.dat^^ | grep -v '^#' | while read ENTRY; do
    MAC=`echo "$ENTRY" | xargs | cut -sd' ' -f1`
    MARK=`echo "$ENTRY" | xargs | cut -sd' ' -f2`
    if [[ "$MAC" != "" ]] && [[ "$MARK" != "" ]]; then
        echo "$MAC $MARK"
        ssh -n router.home "/ip firewall mangle add chain=forward src-mac-address=$MAC connection-state=new action=mark-connection new-connection-mark=$MARK comment=\"!AUTO!\""
        ssh -n router.home "/ip firewall mangle add chain=forward connection-mark=$MARK action=mark-packet new-packet-mark=$MARK passthrough=no comment=\"!AUTO!\""
        ssh -n router.home "/ipv6 firewall mangle add chain=forward src-mac-address=$MAC connection-state=new action=mark-connection new-connection-mark=$MARK comment=\"!AUTO!\""
        ssh -n router.home "/ipv6 firewall mangle add chain=forward connection-mark=$MARK action=mark-packet new-packet-mark=$MARK passthrough=no comment=\"!AUTO!\""
    fi
done

Script above will go over the whole file, skipping all the comments, and assuming the first field in line is MAC address and the second is the mark you want to assign it. Then it will just add mangle pair to both IPv4 and the IPv6 firewall rules.

The last step is to force firewall to clear the existing connections so it can mark them with the new marks.

ssh -n router.home "/ip firewall connections remove [find]"
ssh -n router.home "/ipv6 firewall connections remove [find]"

Only thing now is to create simple queue based on each mark. And yes, that can be automated too. :)

Yield, Don't Stop

One of the first bad habits you pick up when riding a bicycle is not observing stop signs. Yes, you will (hopefully) check there is no traffic but I rarely see anybody come to the full stop if nobody is around. And I was regularly guilty of the same.

If you live in Washington state this is no longer infraction. As of October 1st, Safety Stop law turns all stop signs into yields if you’re on a bicycle.

While I am doubtful about it increasing safety, I am sure it won’t decrease it and it will make bike ride much smoother - even when cops are around. It’s about the time. :)

Stripping Diacritics in Qt

As someone dealing with languages different than English, I quite often need to deal with diacritics. You know, characters such as č, ć, đ, š, ž, and similar. Even in English texts I can sometime see them, e.g. voilà. And yes, quite often you can omit them and still have understandable text. But often you simply cannot because it changes meaning of the word.

One place where this often bites me is search. It’s really practical for search to be accent insensitive since that allows me to use English keyboard even though I am searching for content in another language. Search that would ignore diacritics would be awesome.

And over the time I implemented something like that in all my apps. As I am building a new QText, it came time to implement it in C++ with a Qt flavor. And, unlike C#, C++ was not really built with a lot of internationalization in mind.

Solution comes from non-other than now late Michael S. Kaplan. While his blog was deleted by Microsoft (great loss!), there are archives of his work still around - courtesy of people who loved his work. His solution was in C# (that’s how I actually rembered it - I already needed that once) and it was beautifully simple. Decompose unicode string, remove non-spacing mark characters, and finally combine what’s left back to a unicode string.

In Qt’s C++, that would be something like this:

QString stripDiacritics(QString text) {
    QString formD = text.normalized(QString::NormalizationForm_D);

    QString filtered;
    for (int i = 0; i < formD.length(); i++) {
        if (formD.at(i).category() != QChar::Mark_NonSpacing) {
            filtered.append(formD.at(i));
        }
    }

    return filtered.normalized(QString::NormalizationForm_C);
}

Poured Potatoes (Užljevak)

Illustration

Užljevak is one of my favorite childhood foods. Due to it’s simplicity and the low cost, this was on our table at least once or twice a week. It’s a peasant food using only pantry ingredients and it’s quite forgiving when it comes to preparation.

This recipe is one of the simplest užljevak recipes I know but it’s definitely not the only one. My mother alone used a few different recipes and you’ll find probably every Bosnian family has another few. They all will taste similar though so trying one will give you an idea what you’re working with.

Ingredients

Quantities given are just for the orientation purpose and can be fudged quite a lot while still getting an excellent result.

  • 600 g Russet potatoes (about 3 big ones)
  • 300 g Flour (about 14 spoons)
  • 1 Yellow onion
  • 3 dcl Water
  • 2 dcl Milk
  • 1 dcl Oil
  • 25 g Salt (1½ tablespoon)
  • 1.5 g Black pepper (⅔ teaspoon)

Instructions

Peel potatoes and cut them into small square pieces (0.5 cm side). Leave them in a cold water for about 10 minutes and then drain the water to remove (some) starch. While potatoes are soaking, finely dice onion. The finer, the better.

Mix all the ingredients (including oil) together and you should end with a runny mixture similar to what you would use for crepes (a slightly less dense than a pancake mix). You can fine tune it by adding flour or water but the end result will be good as long as you are in a ballpark. Leave it alone for 10 minutes.

Use that time to preheat the oven to 220 °C (425 °F) with a well-oiled wide pan inside. You can also go with parchment paper but in that case preheat only pan and place parchment only when you are ready to pour.

Once oven is at temperature get the pan out (place parchment paper if that’s your groove) and pour the mixture into the hot pan. It should be about 2-3 cm in height. Be very careful as pan will be really hot. Once poured, get it immediately into the oven.

Bake for 1 hour and then turn on a broiler for another 5 minutes. Once browned, it’s ready to go out.

Let it rest for 10 minutes, cut it into square pieces, and enjoy it with some yogurt on side.


PS: Some would say the only way to eat užljevak iz with homemade sour milk. Getting yogurt is not quite the same taste but it’s definitely easier.