From the Canyon Edge -- :-Dustin
Showing posts with label dotdee. Show all posts
Showing posts with label dotdee. Show all posts

Monday, December 12, 2011

I've Joined the Gazzang Team!


A few weeks ago, I joined a fun, new start-up company here in Austin called Gazzang.  I was a little surprised that this was published in the form of a rather flattering press release :-)  Let's just say that my Mom was very proud!

I know that some of you in the Ubuntu community are wondering how that career change will affect my responsibilities and contributions to Ubuntu.  I'm delighted to say that I'll most certainly continue to contribute to Ubuntu and many of my upstream projects.  Gazzang is quite supportive of my work in both Ubuntu and open source.

Most directly, you should see me being far more active in my regular maintenance, development, bug triage, and support of eCryptfs.  Gazzang's core business is in building information privacy and data security solutions for the Cloud.  eCryptfs is at the heart of their current products, and in my new role as Gazzang's Chief Architect, we're working on some interesting innovations in and around eCryptfs.  A healthy, high-quality, feature-filled, high-performance eCryptfs is essential to Gazzang's objectives, and I'm looking forward to working on one of my real passions in eCryptfs!

More specifically, looking at the projects I maintain, I expect to continue to be very active in:
  • eCryptfs (essential to my new job)
  • byobu (mostly around tmux, and because hacking on byobu is fun and awesome :-)
  • manpages.ubuntu.com and manpg.es (because that's how I read manpages)
  • musica (because that's how I've streamed music since 1998)
  • pictor (because that's how I've managed and shared pictures since 1998)
You'll probably see opportunistic development (nothing active, but when an opportunity or bugs spring up), including the usual bzr/launchpad dance, developing, testing, upstream releasing, packaging, and uploading to Ubuntu, of:
And finally, as prescribed by the Ubuntu Code of Conduct, I'm gracefully stepping away from a few other projects I've founded or maintained in the past.  I'll help out if and when I can, but for now I've transferred all of the necessary rights, responsibilities and ownership of:


Finally, I must say that the last 4 years have been the most amazing 4 years of my entire 12 year professional career.  It's been quite rewarding to witness the fledgling Ubuntu Server of February 2008 (when I joined Canonical), and the tiny team of 5 grow and evolve to the 20+ amazing people now working directly on the Ubuntu Server.  And that list doesn't even remotely cover the dozens (if not hundreds!) of others around Canonical and the Ubuntu Community who contribute and depend on the amazing Server and Cloud distribution that is Ubuntu.

I'm really looking forward to my new opportunities around Gazzang and eCryptfs, but you'll still most certainly see me around Ubuntu too :-)  As crooned by The Beatles...
You say "Yes", I say "No". \\ You say "Stop" and I say "Go, go, go". \\ Oh no. \\ You say "Goodbye" and I say "Hello, hello, hello". \\ I don't know why you say "Goodbye", I say "Hello, hello, hello". \\ I don't know why you say goodbye, I say hello!
 Cheers,
:-Dustinhttp://www.gazzang.com

Wednesday, June 1, 2011

dotdee How-To



A couple of months ago, I blogged a proposal for a tool I called dotdee.

Based on the feedback I received here, in IRC, on the Debian dpkg mailing list, and at the Ubuntu Developer Summit in Budapest, I have vastly improved the implementation and cut a 1.x release series, which is now available in the Ubuntu Oneiric archive, and in ppa:dotdee/ppa for all supported Ubuntu releases!

Juan Negron has already begun using dotdee in the Ubuntu Orchestra packaging (more about Orchestra very soon!), so I thought I should probably put together a small how-to, such that you could start using dotdee too.

The full manpage is here.  This how-to is more of a set of sample instructions for you to try.

INTRODUCTION

You can read the initial proposal here.  Basically, dotdee is a utility that allows you to take any flat file in your filesystem, replace it with a symlink pointing to a file that is generated from a ".d" style directory.  Using inotify, the generated file is automatically and dynamically updated any time any file in the ".d" directory is added, deleted, or modified.

The files in the ".d" are processed in alphanumeric order (per POSIX shell ordering) and can take any combination of 3 different forms:
  1. Flat text files -- which are simply concatenated
  2. Executable programs/scripts/binaries -- the current state of the generated file is passed as STDIN, and the STDOUT of the executable replaces the current state of the generated file
  3. Patch/diff files -- which are applied by patch against the current state of the generated file
SETUP

To begin, you need to "setup" a file for management by dotdee. Here, we use dotdee --setup, we pass it the file to manage, /etc/hosts, and we optionally tell dotdee that the "#" symbol is the comment character in this file's format.
$ ll /etc/hosts
-rw-r--r-- 1 root root 219 2011-05-02 17:31 /etc/hosts

$ sudo dotdee --setup /etc/hosts "#"
update-alternatives: using /etc/dotdee//etc/hosts to provide /etc/hosts (etc:hosts) in auto mode.

Let's see what happened...

Note that /etc/hosts is now a symbolic link...

$ ll /etc/hosts
lrwxrwxrwx 1 root root 27 2011-06-01 11:52 /etc/hosts -> /etc/alternatives/etc:hosts

$ ll /etc/alternatives/etc:hosts
lrwxrwxrwx 1 root root 22 2011-06-01 11:52 /etc/alternatives/etc:hosts -> /etc/dotdee//etc/hosts

That eventually points to /etc/dotdee//etc/hosts. Note that this file is read-only! This is to try and prevent inadvertent writes to this dynamically generated file.

$ ll /etc/dotdee//etc/hosts
-r--r--r-- 1 root root 353 2011-06-01 11:52 /etc/dotdee//etc/hosts

Moreover, since we told dotdee that the comment character is "#", dotdee added a comment to the top of the file for us.

$ cat /etc/hosts
# DO NOT EDIT THIS FILE DIRECTLY!
# Rather, add, remove, or modify file(s) in [/etc/dotdee//etc/hosts.d]
# per the dotdee(8) manpage.
127.0.0.1       localhost
127.0.1.1       x201

# The following lines are desirable for IPv6 capable hosts
::1     ip6-localhost ip6-loopback
fe00::0 ip6-localnet
ff00::0 ip6-mcastprefix
ff02::1 ip6-allnodes
ff02::2 ip6-allrouters

Next, let's look at what's going on in the ".d" directory. Let's see where this directory actually is...

$ sudo dotdee --dir /etc/hosts
/etc/dotdee//etc/hosts.d

$ ll /etc/dotdee/etc/hosts.d/
total 16
drwxr-xr-x 2 root root 4096 2011-06-01 11:52 ./
drwxr-xr-x 3 root root 4096 2011-06-01 11:52 ../
-rw-r--r-- 1 root root  219 2011-05-02 17:31 50-original
-rw------- 1 root root    2 2011-06-01 11:52 .comment

50-original simply contains the original contents of the managed file. And .comment contains the comment string (#).

But now, we can start adding information in this directory and dynamically update our /etc/hosts!

FLAT FILES

Let's append the Google DNS IP address to our hosts, and see it immediately take effect. For this, we can create simple flat file at /etc/dotdee/etc/hosts.d/70-googledns.

$ echo "8.8.8.8 googledns" | sudo tee /etc/dotdee/etc/hosts.d/70-googledns
8.8.8.8 googledns

$ cat /etc/hosts
# DO NOT EDIT THIS FILE DIRECTLY!
# Rather, add, remove, or modify file(s) in [/etc/dotdee//etc/hosts.d]
# per the dotdee(8) manpage.
127.0.0.1       localhost
127.0.1.1       x201

# The following lines are desirable for IPv6 capable hosts
::1     ip6-localhost ip6-loopback
fe00::0 ip6-localnet
ff00::0 ip6-mcastprefix
ff02::1 ip6-allnodes
ff02::2 ip6-allrouters
8.8.8.8 googledns

See our new entry at the end?

EXECUTABLES
sed is a great way to programmatically modify files or standard output. Let's use a sed script to remove blank lines from our generated /etc/hosts.

$ printf '#!/bin/sh\n sed -e "/^$/d"\n' | sudo tee /etc/dotdee/etc/hosts.d/90-noblanklines
#!/bin/sh
 sed -e "/^$/d"

$ sudo chmod +x /etc/dotdee/etc/hosts.d/90-noblanklines

$ cat /etc/hosts
# DO NOT EDIT THIS FILE DIRECTLY!
# Rather, add, remove, or modify file(s) in [/etc/dotdee//etc/hosts.d]
# per the dotdee(8) manpage.
127.0.0.1       localhost
127.0.1.1       x201
# The following lines are desirable for IPv6 capable hosts
::1     ip6-localhost ip6-loopback
fe00::0 ip6-localnet
ff00::0 ip6-mcastprefix
ff02::1 ip6-allnodes
ff02::2 ip6-allrouters
8.8.8.8 googledns

No blank lines!

PATCH FILES

Finally, dotdee supports quilt-like patch files. Here's a simple patch, to our current /etc/hosts file, which can insert some data into the middle of the file:

--- /etc/hosts 2011-06-01 12:39:45.277010248 -0500
+++ /tmp/hosts 2011-06-01 12:33:58.737010336 -0500
@@ -3,6 +3,7 @@
 # per the dotdee(8) manpage.
 127.0.0.1 localhost
 127.0.1.1 x201
+1.2.3.4  foobar
 # The following lines are desirable for IPv6 capable hosts
 ::1     ip6-localhost ip6-loopback
 fe00::0 ip6-localnet

Let's put this content in /etc/dotdee/etc/hosts.d/91-foobar.patch. Note that this file must not be executable, and must end in either a ".patch" or ".diff" extension.

$ sudo vi /etc/dotdee/etc/hosts.d/91-foobar.patch
# Paste the above patch, write, and quit

$ cat /etc/hosts
# DO NOT EDIT THIS FILE DIRECTLY!
# Rather, add, remove, or modify file(s) in [/etc/dotdee//etc/hosts.d]
# per the dotdee(8) manpage.
127.0.0.1       localhost
127.0.1.1       x201
1.2.3.4         foobar
# The following lines are desirable for IPv6 capable hosts
::1     ip6-localhost ip6-loopback
fe00::0 ip6-localnet
ff00::0 ip6-mcastprefix
ff02::1 ip6-allnodes
ff02::2 ip6-allrouters
8.8.8.8 googledns

UNDO

While testing and debugging all of this, I found it quite useful to have an "undo" function at my disposal. So after running this demo, I can safely:

$ sudo dotdee --undo /etc/hosts
update-alternatives: using /etc/dotdee//etc/hosts.d/50-original to provide /etc/hosts (etc:hosts) in auto mode.
INFO: [/etc/hosts] has been restored
INFO: You may want to manually remove [/etc/dotdee//etc/hosts /etc/dotdee//etc/hosts.d]

$ sudo rm -rf /etc/dotdee//etc/hosts /etc/dotdee//etc/hosts.d

PACKAGING

Once you're comfortable with the above, you should be well set to use dotdee as an administrator, or as a packager. As I said above, Juan is using dotdee in the Ubuntu Orchestra packaging now, to generate and manage a file, /etc/puppet/manifests/site.pp.

He uses debhelper to install a header and footer for the file.

/etc/dotdee
/etc/dotdee/etc
/etc/dotdee/etc/puppet
/etc/dotdee/etc/puppet/manifests
/etc/dotdee/etc/puppet/manifests/site.pp.d
/etc/dotdee/etc/puppet/manifests/site.pp.d/10-header
/etc/dotdee/etc/puppet/manifests/site.pp.d/90-footer
/etc/dotdee/etc/puppet/manifests/node.pp.d
/etc/dotdee/etc/puppet/manifests/node.pp.d/10-header
/etc/dotdee/etc/puppet/manifests/node.pp.d/90-footer

His 10-header looks like this:
# Globals
Exec { path => "/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin:/root/bin" }

# Imports

And then his 90-footer looks like this:
# fixup permissions on sudo
class sudo {
    file { "/etc/sudoers":
        owner => root,
        group => root,
        mode => 440,
    }
}

import "node"

In his postinst, he sets up the file for dotdee management, if necessary:
dotdee --dir ${PUPPET_NODE_FILE} >/dev/null 2>&1 || \
dotdee --setup ${PUPPET_NODE_FILE} "#"

And now, he can insert as many puppet snippets in between the header and footer of site.pp, as necessary, from other packages!

Pretty slick, huh!?!

COMMENTS?

I'm quite interested in hearing your questions and comments!

A number of people have asked about Augeas, and how the two projects might be similar. They are similar in that they're both tools usable by system administrators to more programmatically interface with configuration files. I think they differ quite a bit after that. dotdee is extremely small, fast, and simple. It's not specific to configuration files, and could actually work against any file on the filesystem.  It's completely agnostic to the format of the file, whereas Augeas is a library/API that must understand the particular configuration file type.  I'm hoping that dotdee will be usable by Debian/Ubuntu packagers to improve some configuration file handling, in the long run!

Enjoy,
:-Dustin

Friday, April 29, 2011

dotdee: A modern proposal for improving Debian Conffile Management

SOME BACKGROUND

Debian's management of conffiles is a truly inspired approach to a very difficult topic in any Linux/UNIX distribution.

Conffiles are files in /etc that the Debian package management system (dpkg) won't automatically overwrite when you upgrade a package.  Local modifications by the system administrator are preserved.  This a critical policy expectation by Debian and Ubuntu system administrators, which ensures the proper in-place upgrade of packages on a running system.  Moreover, handling conffiles correctly, as a package maintainer according to Debian policy, requires considerable expertise.  Debian Developer RaphaĆ«l Hertzog has one of the best, most concise explanations of how dpkg handles conffiles in this blog post.

THE ISSUE


Having read in detail several times now the Debian policies on conffile management, I see some room for improvement, with respect to modern Debian and Ubuntu deployments.  I believe there are two key points that the current policy sufficient handle...
  1. Particularly in modern, massive Debian/Ubuntu deployments (think Cloud, Grid, and Cluster computing), it's no longer humans that are managing individual systems, but rather systems (puppet, chef, cfengine, et al.) managing systems.  (Insert your Skynet jokes here...)  As such, it's difficult (if not impossible) for a Debian package or a distribution to make configuration changes to another package's conffiles without violating Debian policy -- even when the change might objectively be the "right" or the "best" thing to do, in terms of end user experience and package operation (especially when the given system is only ever managed by a configuration management system).
  2. In other cases, one local package has a run-time dependency on a second package on the local system, but requires the package it depends on to be configured in a particular way.  Again, if that configuration lives in a conffile owned by the second package, the first package cannot automatically make that configuration change without violating said policy.
As an exception, rather than the rule, there are a couple of very mature packages that provide smart frameworks enabling system administrators, packagers, and distributions to configure them all within policy.

A good example would be apache2's /etc/apache2 directory, which allows for said admins, packagers, and distributions to drop their own configuration modifications as files (or symbolic links) into sourced directories such as /etc/apache2/conf.d, /etc/apache2/mods-available, and /etc/apache2/sites-available.

A PROPOSAL

The concept of a ".d" directory in /etc is very well understood in most Linux/UNIX circles, actually.  Check your own /etc directory with the command: find /etc -type d -name "*.d" and you should see quite a number of ".d" style configuration directories.

Here, I'm proposing a tool that I think would greatly benefit Debian and Debian-derived distributions such as Ubuntu.  For the purposes of this discussion, let's call the tool "dotdee".  Its stated goal is to turn any given flat file on your system to a dynamically concatenated flat file generated from a unique ".d" directory dedicated to that file.  With such a dedicated and well-formed directory, system administrators, Debian packagers, and distributions could conveniently place additional configuration snippets in particular conffile's dedicated ".d" directory.

I have written a first prototype of the tool dotdee, which you can examine here.  It's a very simple, straightforward shell script, inspired a bit by Debian's incredibly useful update-alternatives tool.

The script runs in 3 different modes:
  1. sudo dotdee --setup /etc/path/to/some.conf
  2. sudo dotdee --update /etc/path/to/some.conf
  3. sudo dotdee --undo /etc/path/to/some.conf

SETUP MODE

First the setup mode takes a flat file as a target.  Assuming the file is not already managed by dotdee, a new directory structure is created under /etc/dotdee.  In the example above, that would be /etc/dotdee/etc/path/to/some.conf.d.  So "/etc/dotdee" is prepended, and ".d" is appended to the path which is to be managed.  It's trivial to get back to the name of the managed file by stripping /etc/dotdee from the head, and .d from the tail of the string.

Next, the actual managed flat file is moved from /etc/path/to/some.conf to /etc/dotdee/etc/path/to/some.conf.d/50-dpkg-original.  Again, this a well-formed path, with "/etc/dotee" prepended, a ".d" appended, and the file itself is renamed to "50-dpkg-original".  This is intended to clearly denote that this is the original, base file, as installed by dpkg itself.  The number "50" is precisely halfway between "00" and "99", leaving plenty of room for other file snippets to be placed in ordered positions before and/or after the original file.

After this, we run the update function, which will concatenate in alphanumeric order all of the files in /etc/dotdee/etc/path/to/some.conf.d/* and write the output into /etc/dotdee/etc/path/to/some.conf.

Finally, the update-alternatives system is used to place a symlink at the original location, /etc/path/to/some.conf, pointing to /etc/dotdee/etc/path/to/some.conf.  Additionally, a second, lower-priority alternative is also set, pointing to dpkg's original at /etc/dotdee/path/to/some.conf.d/50-dpkg-original.

UPDATE MODE

As mentioned above, the update function performs the concatenation immediately, building the targeted path from its dotdee managed collection of snippets.  This should be run anytime a file is added, removed, or modified in the dotdee directory for a given managed file.  As a convenience, this could easily and automatically be performed by an inotify watch of the /etc/dotdee directory.  That, itself, would be a dotdee configuration option.

UNDO MODE

The undo function is something I added for my own development and debugging while working on the tool, however I quickly realized that it might be an important tool for other system administrators and packagers (think, postrm maintenance scripts!).

DPKG INTEGRATION

This would require some (minor?) integration with dpkg itself.  On package upgrade/installation, dpkg would need to need to detect when the target path of a file it wants to create/update is in fact a symbolic link referencing an /etc/dotdee path.  It would need to drill down into that path and place the file it wants to write on top of the 50-dpkg-original file instead.  I have not yet contacted the dpkg maintainers yet, so I don't know if this is a reasonable proposal or not.

IN PRACTICE

So what would this look like in practice?

Once integrated with dpkg, I'd like dotdee to be a utility that human system administrators could run to manually turn a generic conffile into a ".d" style configuration directory, such that they could append their own changes to some numbered file in the dotdee directory, avoid the interactive dpkg-conffile-changed prompts.

More importantly, I would like one package's postinst maintainer script to be able take another package that it depends upon and turn its conffile into a dotdee managed file, such that it could append or prepend configuration information necessary for proper operation.

COMMENTS?

I plan to lead a session on this topic at the Ubuntu Developer Summit in May 2011 in Budapest, and I have also proposed this on the debian-dpkg@ list as well.

But in the mean time, what do you think?  Have you encountered this problem before?  How have you solved it?  What parts of this proposal do you think are reasonable?  Are any parts completely unreasonable to you?  Can you think of any extensions or changes you'd make?  Would you use something like this?

Cheers,
:-Dustin

Printfriendly