Fast Potato Gnocci

Making potato gnocci can be fast if you cook your potatoes using a microwave. Microwaving the potatoes not only speeds the process up, but also results in drier potatoes and more robust dough. This is a “fast”, condensed version of the recipe found here.

Ingredients

  • About 2lbs of starchy potatoes, e.g. Russets
  • 1-1 1/2 dry cups flour
  • 1 tsp. salt
  • 1 egg

Steps

  1. Wash and peel the potatoes. Cut the potatoes up into 1/2-inch slices, but cut the larger pieces to match the size of the smaller ones. This helps cook them uniformly.
  2. Transfer potatoes into a microwave-safe bowl, and microwave until fork-tender. Cook on high in 2-minute intervals, stirring occasionally – it should take about 6-8 minutes.
  3. Press the potatoes through a ricer once cool enough to handle. A strainer or sieve will work equally well.
  4. In a large bowl, combine the potatoes with the egg and salt.
  5. Once the potatoes and eggs are well combined, mix in the flour. Start with 1 cup, and work your way up, lightly kneading until the dough stays together in a ball and holds its shape. Cover the dough with a damp paper towel to prevent drying.
  6. If cooking immediately, begin heating a large pot of water. You want it to be boiling vigorously when cooking your gnocci.
  7. Dust a cutting board or similar work surface and a baking sheet (to hold the finished gnocci) with flour. Have some extra flour to the side to replenish as you work.
  8. Take a good handful of dough, and roll it out into a 3/4 inch-thick noodle.
  9. Cut the noodle into 3/4 inch pillows. To shape, take a fork, and place the pillow on the tines. Press the pillow into the tines with your thumb, and pull away towards the points of the tines. The dough should curl up onto your fingers, and you should get a cylinder with the characteristic indentations. Place the gnocci onto the baking sheet.
  10. Once the water is boiling, drop the gnocci in. Lightly stir to prevent the dumplings from sticking to the bottom of the pot and to each other. The gnocci will begin to float as they cook through. Once one is floating, let it cook for another minute, then fish it out of the water and into a colander. You may want to toss them with oil (or with the sauce you were planning to eat them with) to prevent them from sticking together.

Notes

  • Note that the potatoes can get very (read: scalding) hot as they cook.
  • While mixing the dough, keep the kneading to a minimal, as too much will develop the gluten and toughen the dough (or conversely, knead it more, if you like it to be chewier).
  • The shaping is mostly cosmetic, but for an idea of how to roll the gnocci, take a look at this video.
  • Contrary to what some people think, microwaving the food is neither harmful, nor will it degrade the nutritional value of the food, any more than other forms of cooking.

Yeast pancakes – review, link, and (modified) recipe.

The other day I gave this yeast pancake recipe a try. The recipe followed duly makes a light but bready pancake that’s a bit on the savoury side.

Here are some notes from my first attempt at any recipe calling for fermentation. A recipe modified based on these observations are at the end of this post.

  • The recipe omits the fact that the milk should be warm. An incorrect temperature might prevent your batter from rising. It’s pretty easy to heat it up to the desired temperature of 120-130F/48-54C, by microwaving in 30 second intervals and measuring the temperature. It should take about 2-3 minutes.
  • Fast-rise dry yeast is different from regular dry yeast. Regular yeast needs to be activated first by adding to a warm liquid. The fast-rise yeast can simply be mixed in with the dry ingredients, and calls for a higher temperature for the added liquid than regular yeast.
  • The bubbles produced by the yeast tend to collect on the top. This results in batter being lighter and foamier at the top, and denser at the bottom. It would probably be good to redistribute the bubbles by gently folding the batter after it finishes rising.
  • If you are worried about the temperature like I was, heat the milk closer to 130F/54C, and add the eggs and butter into the milk before adding it to the dry ingredients.

Overall, this seems like a good beginner’s recipe for yeast pancakes, where the only things to watch out for are the temperature of the liquid being added, and the freshness of the yeast. As a side-note, doubling the sugar from two to four teaspoons mellows the savoriness quite a bit. It might also give the yeast more sugar to work with (more sugar and warm = more active yeast and bubbling, and fluffier batter).

And now, for a modified, half-sized recipe.

Ingredients

  • 2 cups flour
  • 1 tsp. salt
  • 2 tsp. sugar
  • 1 egg
  • 1 1/2 cups milk
  • 1/8 cup melted butter or oil
  • 1/4 oz fast-rise yeast – this is usually 1 packet of the yeast sold in packets
  • 1 tsp vanilla extract

Steps

  1. In a large bowl (with at least 8 cups volume), combine the dry ingredients. Make sure that they are mixed together well.
  2. Combine the eggs, vanilla, and oil.
  3. Heat the milk to the target temperature of 120-130F/48-54C. This can be done by microwaving the milk in a mug for about 1.5 to 2 minutes, checking in 30 second intervals.
  4. Add the egg mixture and warm milk to the dry ingredients. Mix well until smooth.
  5. Let the bowl sit in a warm place for 30 minutes, covered with a cloth or paper towel (something breathable – yeast needs oxygen).
  6. Once the batter has risen, gently fold together so that it is a uniform consistency.
  7. Make pancakes as you would with usual batter.

The recipe is fairly easy to modify – for example, you can add some almond butter or similar to the egg mixture at step 2 for almond pancakes, or cocoa to the dry ingredients at step 1.

Reading man pages without man.

zcat /usr/share/man/man1/ls.1.gz | groff -Tascii -man | less -R

This unzips and cats a compressed man page through groff to format it, and then to less so that you can scroll. The -R, which you may or may not need, prevents certain ANSI escape sequences from showing as “ESC [ …” garble (the same situation with git is described here).


References:

A roasted pumpkin soup.

This is a vegetarian pumpkin soup. Roasting brings out the sweet and savory flavors and a creaminess in the squash. I use Japanese squash for the soup, although I imagine that it works just as well with other starchy squashes and pumpkins (or maybe even chestnut).

The soy sauce might make some folks double-take, but all it does is add to the savoriness, and doesn’t actually make anything taste like soy sauce.

Ingredients

  • 1 kabocha (Japanese squash)
  • 1 carrot
  • 1 medium onion
  • 6 US cups vegetable stock
  • 1 Tbsp butter (optional)
  • 1 Tsp soy sauce
  • A few Tbsp vegetable oil
  • Minced parsley, and/or curry powder to taste

Step 1 of 2 (Roasting the squash)

  1. Pre-heat the oven to 375 F.
  2. Meanwhile, cut up the squash into slices or cubes, add them to a baking tray, and coat them in vegetable oil.
  3. When the oven is done preheating, bake the squash for about 30-45 minutes, until they are tender and the edges start browning a bit.
  4. Remove from the oven and set aside.

Step 2 of 2 (The soup)

  1. Chop the onions and carrots (think mirepoix without celery).
  2. In a pan, melt butter into the oil, and saute the onions and carrots until translucent.
  3. Add the roasted squash chunks to the pan and crush them up until a chunky paste consistency.
  4. Add the vegetable stock and soy sauce. Add salt to taste.
  5. Simmer for five or ten minutes, breaking any chunks of squash apart (if desired).

Garnish with parsley and/or curry powder. The soup can be blended at the end for a smoother consistency.

Notes on Linux namespaces and related things

Some notes about Linux namespaces and cgroups, based on the resources linked in the end of the page.

ip netns show and proc/

A quick search on ‘Linux namespaces’ usually turns up examples using ip netns, which might be confusing if it wasn’t used to create network namespaces, e.g. in the case of Docker (or Mininet). Namely, ip netns show will give you nothing, even when you clearly have things running in namespaces.

Referring to proc(5), information about a process’s namespaces and cgroups can be found under /proc/[pid]/ns and /proc/[pid]/cgroup, respectively. ip netns bind-mounts its ns directory (/proc/self/ns/net) to /run/netns, from where it gets the information that it would list. Hence, if netns wasn’t used, no bind mounted directory, and no listing.

ps(1)

In a related vein, given a process, it’s also possible to see some information about the namespaces and cgroups that it is associated with. Certain dialects of ps will let you display this information:

$ ps -eo pid,cgroup,netns,pidns
 6017 2:name=systemd:/user/1000.u 4026531956 4026531836
 6018 2:name=systemd:/user/1000.u 4026531956 4026531836
22772 11:hugetlb:/docker/505f3032          -          -
22843 11:hugetlb:/docker/a3685093          -          -

The options here would be:

  • cgroup – display control groups to which the process belongs.
  • ipcns – inode number describing the (IPC) namespace the process belongs to.
  • mntns – inode number describing the (mount) namespace the process belongs to.
  • netns – inode number describing the (network) namespace the process belongs to.
  • pidns – inode number describing the (PID) namespace the process belongs to.
  • userns – inode number describing the (User) namespace the process belongs to.
  • utsns – inode number describing the (UTS) namespace the process belongs to.

More information about each namespace type can be found in namespaces(7), although the particular man page isn’t guaranteed to be shipped. The particular ps and man page are shipped with 14.04, but Ubuntu’s online man pages seem to mysteriously omit it. Links to both provided below.

Looking through proc/

Even without ps, the same information can be gleaned from /proc/[pid]/. The inode numbers of a process’s namespace can be read from /proc/[pid]/task/[pid]/ns/:

$ readlink /proc/25414/task/25414/ns/*                  
ipc:[4026531839]
mnt:[4026531840]
net:[4026531956]
pid:[4026531836]
user:[4026531837]
uts:[4026531838]

And the cgroup(s), from /proc/[pid]/task/[pid]/cgroup:

$ cat /proc/25414/task/25414/cgroup
11:hugetlb:/
10:perf_event:/
9:blkio:/
8:freezer:/
7:devices:/
6:memory:/
5:cpuacct:/
4:cpu:/
3:cpuset:/
2:name=systemd:/user/1000.user/17.session

References:

A vegetarian chili.

Another open-ended one-pot recipe. Two cans of beans should work in place of the dried beans, but I haven’t tried. Step 1 might be best done the day before.

Ingredients

  • 1 1/4 cups of dried beans (any kind, or a mix, works), soaked overnight
  • 1 package extra firm tofu, drained and crumbled
  • 1 cup mushrooms (button, shiitake, maitake/hen of the woods, etc.), chopped
  • 1 large onion, chopped
  • 3-4 garlic cloves, minced
  • 1 large green pepper, chopped
  • 2-3 tomatoes, chopped
  • 1/2 can tomato paste
  • 1 Tbsp oil
  • A chili kit of choice, or the list below
  • lime, scallions, and cheese for garnish, to taste

If not using a chili kit:

  • 4 tsp chili powder
  • 1/2 tsp cumin
  • 1 tsp oregano
  • 1 tsp salt
  • 1 tsp or so thickener of choice (optional; some kind of starch or flour)

Steps

  1. simmer the beans in lightly salted water until tender, about 45-60 min. Reserve about 3 cups of the bean broth.
  2. fry minced garlic in oil
  3. saute onions and peppers with garlic once the latter begins to brown
  4. add tomato once onions and pepper become translucent and soft
  5. add tofu, mushrooms, and tomato paste once tomato is soft
  6. when everything is combined together, add spices, beans, and reserved broth.
  7. simmer for a few minutes, adjusting the thickness with water or thickener. If adding a thickener, it may have to be simmered for longer. At this point I sometimes add a cup of farro or quinoa, and say that it’s ready when that cooks.

Garnish and serve as you would regular chili.

Adding a new Switch class to Mininet.

This is a quick post about making Mininet support new network objects, like switches.

Depending on the amount of features that a software switch (or other program) supports, and the degree to which you want to access those features through Mininet, adding a custom node type to Mininet can be a relatively simple task. For something as simple as a classic learning switch, this may be a matter of of implementing just a handful of methods within a child class of Switch.

An example: the LinuxBridge class

A good example of such a custom node is the LinuxBridge, prepackaged with Mininet and found in nodelib.py. This node, which implements a non-OpenFlow learning switch using the classic Linux bridge(8) device, just implements five methods, ignoring its constructor:

  • connected( self ):
    Returns True if the switch is connected to a controller or False if not. For a non-SDN switch, a connected state is when it is fully started up and therefore, ready for interaction. For the LinuxBridge, this is when brctl(8) shows that it is in the “forwarding” state.

  • start( self, _controllers ):
    Initializes and configures the software switch underlying the Mininet Switch object. For our example, this method invokes a series of brctl commands to initialize the switch, add ports, and to apply the necessary configurations (e.g. enable STP) to get it to the connected state. An OpenFlow switch such as OVS would also be configured to connect with a set of controllers passed into this method.

  • stop( self, deleteIntfs=True ):
    Carries out the teardown and removal of the underlying software switch backing the Mininet object. This method is the complement to start.

  • dpctl( self, *args ):
    Invokes the configuration utility for the software switch, parameterized to point to the particular instance associated with the Mininet object. In our case, this is, again, brctl.

  • setup( cls ):
    Checks that all prerequisites are met in order to start up and configure the software switch. This may entail checking that certain kernel modules are loaded, packages like bridge-utils are installed, and certain features, such as the firewall, are configured to allow the switch to function.

A bit of detail to keep note of is that the Switch class does its own housekeeping in its __init__ and stop methods, so these should be called from your custom class as well:

class LinuxBridge( Switch ):

    def __init__( self, name, stp=False, prio=None, **kwargs ):
        # snipped out initialization things here
        Switch.__init__( self, name, **kwargs )

    # snip...

    def stop( self, deleteIntfs=True ):
        # snipped out cleanup things here
        super( LinuxBridge, self ).stop( deleteIntfs )

Specifically, __init__ would be tied to initializing any major lightweight virtualization functions and facilities for sending commands to the process(es) underlying the switch object, and stop, the teardown and cleanup of the interfaces on the switch.

This meant that, by implementing the above methods in a IfBridge class, I was able to quickly put together a learning switch using if_bridge(4) and ifconfig(8) for my experimental Mininet port – barring one easily circumvented but odd bit of behavior. As a convention, custom nodes usually end up in nodelib.py, so that is where I ended up adding my IfBridge node.

Integrating a custom element into `mn`

mn allows you to launch a Mininet topology from the shell, and is one of the first things that the Mininet quickstart has you run to sanity check an install. It’s also handy for launching a topology to test with, without having to write a Python script. Among the options that mn comes with is the class of various network elements (switches, links, etc) to use when building the topology:

$ mn --help
Usage: mn [options]
(type mn -h for details)

The mn utility creates Mininet network from the command line. It can create
parametrized topologies, invoke the Mininet CLI, and run tests.

Options:
  -h, --help            show this help message and exit
  --switch=SWITCH       default|ivs|lxbr|ovs|ovsbr|ovsk|user[,param=value...]
                        ovs=OVSSwitch default=OVSSwitch ovsk=OVSSwitch
                        lxbr=LinuxBridge user=UserSwitch ivs=IVSSwitch
                        ovsbr=OVSBridge
  --host=HOST           cfs|proc|rt[,param=value...]
                        rt=CPULimitedHost{'sched': 'rt'} proc=Host
                        cfs=CPULimitedHost{'sched': 'cfs'}
...

Adding your custom Switch to this list is a matter of a few changes in mn. mn keeps a mapping between the various Node and Link classes and their aliases (e.g. default for OVS, lxbr for LinuxBridge …). So in my case, I have my IfBridge custom switch, which I aliased to ‘ifbr’ in the SWITCHES map:

SWITCHES = { 'user': UserSwitch,
             'ovs': OVSSwitch,
             ...
             'ifbr': IfBridge }

At this point, your custom class should be displayed alongside the other choices in the help message:

  --switch=SWITCH       default|ifbr|ivs|lxbr|ovs|ovsbr|ovsk|user[,param=value
                        ...] ovs=OVSSwitch lxbr=LinuxBridge user=UserSwitch
                        ivs=IVSSwitch default=OVSSwitch ovsk=OVSSwitch
                        ovsbr=OVSBridge ifbr=IfBridge

The rest of the script more or less sanity-checks the combination of classes that had been chosen during invocation, before launching a Mininet object. The sanity checks done for each network element type depends on their features. For example, if --switch=default is specified, mn checks for an OpenFlow controller, since the OVS switch would need a controller to connect to. If a non-functional dummy controller (--controller=none) had been used in the invocation, it will fall back to using bridge-mode OVS (ovsbr) even if ‘default’ was chosen for the switch.

In the case of my custom ‘ifbr’ switch, since it is a good-old-fashioned learning switch, the only extra work I needed to do was to add it to the list of non-OpenFlow switch types that are available for use with the ‘none’ controller:

    def begin( self ):
        "Create and run mininet."
        # snip...
        if not self.options.controller:
            if not CONTROLLERS[ 'default' ]:
            # snip...
                elif self.options.switch not in ( 'ovsbr', 'lxbr', 'ifbr' ):
                    raise Exception( "Could not find a default controller "
                                     "for switch %s" %
                                     self.options.switch )

At this point, I can run mn with my custom switch as so:

sudo ./mn --switch=ifbr --controller=none --test=pingall