[lxc-devel] Creating an lxc-config binary

Matthijs Kooijman matthijs at stdin.nl
Mon Apr 30 20:41:35 UTC 2012


Hi folks,

while writing scripts, I occasionally miss an lxc-config command, that
can parse (and possibly also write) the lxc config files for me in a
robust way. Sure, it's an easy format to just grep and sed over (or at
least it looks like that at first glance), but that's not very
future-proof or robust.

So, I looked into implementing such a command, with some help from
Daniel Baumann on IRC, but ran into some (conceptual) problems along the
way. So, instead of randomly picking a solution that didn't quite seem
good, I'll detail my thoughts on the subject and hope others have useful
ideas.

Similar to git-config?
======================
First, Daniel proposed to make the command work similar to git-config
(e.g., borrow command line options and syntax from there, as far as
applicable). This seems like a good idea to me, to at least be
consistent with something (for lack of any defined standard AFAIK).

Script or binary?
=================
Then, there is the question if this command should be implemented in a
script or an actual C binary.

Using a script is good because:
 - A script is probably quicker to write
Using a binary is good because:
 - Having only a single codebase doing the file parsing prevents
   (subtle) differences between lxc-config and the other commands.
 - Having a single codebase is easie to maintain.

I'd say, using a binary is the better approach here.

Raw values or processed values?
===============================
Looking at how configuration file parsing works in C (confile.c), I see
another choice/challenge. It's obvious to just let confile.c do the
entire parsing and then look up the requested values in the resulting
lxc_conf struct. This guarantees that the values returned by lxc-config
are exactly those as will be used by the other lxc commands, which seems
like a plus (you can even take --define options into account if you
want). However, there's also a number of downsides:
 - This is tricky to implement: Since I can't use the config key
   supplied by the user, which is just a string, to look up the right
   value in the struct. Even using a lookup table, like the one used for
   parsing in confile.c is tricky, since the current table is decoupled
   from the struct because each config key has a specific callback to
   check and store the value.
 - If any post-processing happens by the callbacks in confile.c, the
   output from lxc-config be different from the actual strings inside
   the config file. This is good for callers that just want to know the
   value that is being used, but does not make sense for callers that
   are focused on the config file (since this can break the symmetry
   between reading and writing config values).

   Note that I think no post-processing actually happens in the current
   codebase (instead of type conversion, which actually has to be
   reversed to make everything a string again for lxc-config output).

Since these are significant problems, it seems better to adopt a "raw
output" approach where the values are taken from the config file and
outputted as-is. This means that the code re-use from confile.c is
limited to just the basic file parsing (key/value splitting), and not
any post-processing and any (implicit) single-value or list-value
handling. This limits the upsides of using a binary over a script a bit,
but they're still enough to use a binary IMHO.

(An alternative would be to have a --raw and a --processed mode or
something to get the best of both worlds, but since that would make the
code considerably more complex, with even more possibilities of
inconsistencies, I don't think that's a good idea).

Single- and multivalue entries
==============================
I was going to write some stuff about the handling of singlevalue
entries (e.g., lxc.utsname) versus multivalue entries (e.g.,
lxc.cap.drop). However, it seems more sensible to just let the caller
make this distinction, just like git-config does (e.g., by calling --get
versus --get-all etc.).

Networking values
=================
The networking values are a bit special in lxc.conf: They are
effectively divided into sections, separated by lxc.network.type values.
This means that to query these values, we need to somehow specify or
return to which network they belong.

The most obvious way of specifying the network is by passing an index. I
considered generalizing this by making the index work on any multivalue
configuration entry, but this doesn't work for the lxc.network.ipv4
configuration (which can occur multiple times within a single network,
so specifying the nth occurence in the file does not say anything about
the network the occurence belongs to).

So, we need some way to specify the index of the network interface to
query/update. I can imagine the following options:
 1. In the middle of the key specified, e.g.:
    lxc-config --get lxc.network[1].ipv4. This seems like an intuitive
    way to specify the network to use, but this isn't very easy to parse
    and might not be the most flexible for the future.
 2. At the end of the key specified, e.g.,:
    lxc-config --get lxc.network.ipv4[1]. This is easier to parse, but
    doesn't seem to be so intuitive to me (I would expect this
    particular example to return the second ipv4 address, while it would
    return the ipv4 address of the second interface).
 3. Using a separate commandline argument, e.g.:
    lxc-config --network-index 1 --get lxc.network.ipv4. This is
    probably the best way, though it is a bit more verbose than the
    other options.

In any case, it seems obvious to just consider all network interfaces
when no index was specified in a query and require specifying an index
when manipulating the config.

I considered allowing the user to specify a key=value pair to select the
network interface (e.g., to select the interface with link=eth0), but I
guess that would be more (too) complicated to implement and up to users
of the command to implement.


So, any other thoughts or opinions on the subject?

Gr.

Matthijs
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 197 bytes
Desc: Digital signature
URL: <http://lists.linuxcontainers.org/pipermail/lxc-devel/attachments/20120430/3399b203/attachment.pgp>


More information about the lxc-devel mailing list