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
signature.asc
Description: Digital signature
------------------------------------------------------------------------------ Live Security Virtual Conference Exclusive live event will cover all the ways today's security and threat landscape has changed and how IT managers can respond. Discussions will include endpoint security, mobile security and the latest in malware threats. http://www.accelacomm.com/jaw/sfrnl04242012/114/50122263/
_______________________________________________ Lxc-devel mailing list Lxc-devel@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/lxc-devel