On Tue, Aug 26, 2008 at 10:05 PM, Daniel P. Berrange
<berrange@redhat.com> wrote:
THis patch is intended to be committed to libvirt, so the config file rules
are distributed alongside libvirt. I'm CC'ing augeas-devel for feedback on
the lens itself.
Very nice idea. This might have to be thought about for the future since so far we're only adding lenses to the Augeas repository.
===================================================================
RCS file: qemud/libvirtd.aug
diff -N qemud/libvirtd.aug
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ qemud/libvirtd.aug 26 Aug 2008 20:03:48 -0000
@@ -0,0 +1,64 @@
+(* /etc/libvirt/libvirtd.conf *)
+
+module Libvirtd =
+ autoload xfm
+
+ let eol = del /[ \t]*\n/ "\n"
This is also Util.eol
+ let value_sep = del /[ \t]*=[ \t]*/ " = "
+ let prespace = del /[ \t]*/ ""
+
And this is Util.indent
+ let array_sep = del /,[ \t\n]*/ ", "
+ let array_start = del /\[[ \t\n]*/ "[ "
+ let array_end = del /\]/ " ]"
+
+ let str_val = del /\"/ "\"" . store /[^\"]*/ . del /\"/ "\""
+ let bool_val = store /0|1/
+ let str_array_element = [ str_val ] . del /[ \t\n]*/ ""
+ let str_array_val = array_start . ( str_array_element . ( array_sep . str_array_element ) * ) ? . array_end
+
+ let str_entry (kw:string) = [ prespace . key kw . value_sep . str_val . eol ]
+ let bool_entry (kw:string) = [ prespace . key kw . value_sep . bool_val . eol ]
+ let str_array_entry (kw:string) = [ prespace . key kw . value_sep . str_array_val . eol ]
+
+ let network_entry = bool_entry "listen_tls"
+ | bool_entry "listen_tcp"
+ | str_entry "tls_port"
+ | str_entry "tcp_port"
+ | str_entry "listen_addr"
+ | bool_entry "mdns_adv"
+ | str_entry "mdns_name"
+
While I can see why it is useful to gather these entries logically, it's not very optimised for the parser. Eventually, all this will be compiled into a huge regexp, so it's more efficient to regroup entries by type and feed the functions with regexps instead of strings, like
let str_entry (kw:regexp) = [ prespace . key kw . value_sep . str_val . eol ]
let bool_entry (kw:regexp) = [ prespace . key kw . value_sep . bool_val . eol ]
let str_array_entry (kw:regexp) = [ prespace . key kw . value_sep . str_array_val . eol ]
let str_keys = "tls_port"
| "tcp_port"
| "listen_addr"
| "mdns_name"
| etc.
let bool_keys = "listen_tls"
| "listen_tcp"
| "mdns_adv"
| etc.
let str_entries = str_entry str_keys
let bool_entries = bool_entry bool_keys
You get the point, each function is only evaluated once, with a single regexp (every string ets turned into a regexp, and so will str_keys and bool_keys). The less you will call the *_entry functions, the faster your lens will be.
+ let sock_acl_entry = str_entry "unix_sock_group"
+ | str_entry "unix_sock_ro_perms"
+ | str_entry "unix_sock_rw_perms"
+
+ let authentication_entry = str_entry "auth_unix_ro"
+ | str_entry "auth_unix_rw"
+ | str_entry "auth_tcp"
+ | str_entry "auth_tls"
+
+ let certificate_entry = str_entry "key_file"
+ | str_entry "cert_file"
+ | str_entry "ca_file"
+ | str_entry "crl_file"
+
+ let authorization_entry = bool_entry "tls_no_verify_certificate"
+ | str_array_entry "tls_allowed_dn_list"
+ | str_array_entry "sasl_allowed_username_list"
+
+ let entry = network_entry
+ | sock_acl_entry
+ | authentication_entry
+ | certificate_entry
+ | authorization_entry
+
So here you would have something like
let entry = str_entries
| bool_entries
| etc.
gather entries by parser type.
+ let comment = [ label "comment" . del /#[ \t]*/ "# " . store /([^ \t\n][^\n]*)?/ . del /\n/ "\n" ]
Some time ago, we thought that it would be good to map comments in "#comment" nodes to avoid confusion with possible "comment" nodes, especially when the lens allows a wide range of labels. Util.comment would fit your need here, and the new version of it would provide a "#comment" node.
+ let empty = [ label "empty" . del /[ \t]*\n/ "" ]
Util.empty provides a definition of empty lines, too. Do you really need to map them with a label? I thought about doing that some time ago, but mapping them in "#empty" for the same reason that we map comments in "#comment". The useful application to this is to allow users to control empty lines in conffile from the augeas API.
+
+ let lns = ( entry | comment | empty ) +
Is an empty file not valid?
+
+ let filter = incl "/etc/libvirt/libvirtd.conf"
+ . Util.stdexcl
+
+ let xfm = transform lns filter
+
Index: qemud/test_libvirtd.aug
===================================================================
RCS file: qemud/test_libvirtd.aug
diff -N qemud/test_libvirtd.aug
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ qemud/test_libvirtd.aug 26 Aug 2008 20:03:48 -0000
@@ -0,0 +1,484 @@
+module Test_libvirtd =
+ let conf1 = "# Master libvirt daemon configuration file
+#
+# For further information consult http://libvirt.org/format.html
+
+
+#################################################################
+#
+# Network connectivity controls
+#
+
+# Flag listening for secure TLS connections on the public TCP/IP port.
+# NB, must pass the --listen flag to the libvirtd process for this to
+# have any effect.
+#
+# It is necessary to setup a CA and issue server certificates before
+# using this capability.
+#
+# This is enabled by default, uncomment this to disable it
+listen_tls = 0
+"
+
+ let conf = "# Master libvirt daemon configuration file
+#
+# For further information consult http://libvirt.org/format.html
+
+
+#################################################################
+#
+# Network connectivity controls
+#
+
+# Flag listening for secure TLS connections on the public TCP/IP port.
+# NB, must pass the --listen flag to the libvirtd process for this to
+# have any effect.
+#
+# It is necessary to setup a CA and issue server certificates before
+# using this capability.
+#
+# This is enabled by default, uncomment this to disable it
+listen_tls = 0
+
+# Listen for unencrypted TCP connections on the public TCP/IP port.
+# NB, must pass the --listen flag to the libvirtd process for this to
+# have any effect.
+#
+# Using the TCP socket requires SASL authentication by default. Only
+# SASL mechanisms which support data encryption are allowed. This is
+# DIGEST_MD5 and GSSAPI (Kerberos5)
+#
+# This is disabled by default, uncomment this to enable it.
+listen_tcp = 1
+
+
+
+# Override the port for accepting secure TLS connections
+# This can be a port number, or service name
+#
+tls_port = \"16514\"
+
+# Override the port for accepting insecure TCP connections
+# This can be a port number, or service name
+#
+tcp_port = \"16509\"
+
+
+# Override the default configuration which binds to all network
+# interfaces. This can be a numeric IPv4/6 address, or hostname
+#
+listen_addr = \"192.168.0.1\"
+
+
+# Flag toggling mDNS advertizement of the libvirt service.
+#
+# Alternatively can disable for all services on a host by
+# stopping the Avahi daemon
+#
+# This is enabled by default, uncomment this to disable it
+mdns_adv = 0
+
+# Override the default mDNS advertizement name. This must be
+# unique on the immediate broadcast network.
+#
+# The default is \"Virtualization Host HOSTNAME\", where HOSTNAME
+# is subsituted for the short hostname of the machine (without domain)
+#
+mdns_name = \"Virtualization Host Joe Demo\"
+
+
+#################################################################
+#
+# UNIX socket access controls
+#
+
+# Set the UNIX domain socket group ownership. This can be used to
+# allow a 'trusted' set of users access to management capabilities
+# without becoming root.
+#
+# This is restricted to 'root' by default.
+unix_sock_group = \"libvirt\"
+
+# Set the UNIX socket permissions for the R/O socket. This is used
+# for monitoring VM status only
+#
+# Default allows any user. If setting group ownership may want to
+# restrict this to:
+unix_sock_ro_perms = \"0777\"
+
+# Set the UNIX socket permissions for the R/W socket. This is used
+# for full management of VMs
+#
+# Default allows only root. If PolicyKit is enabled on the socket,
+# the default will change to allow everyone (eg, 0777)
+#
+# If not using PolicyKit and setting group ownership for access
+# control then you may want to relax this to:
+unix_sock_rw_perms = \"0770\"
+
+
+
+#################################################################
+#
+# Authentication.
+#
+# - none: do not perform auth checks. If you can connect to the
+# socket you are allowed. This is suitable if there are
+# restrictions on connecting to the socket (eg, UNIX
+# socket permissions), or if there is a lower layer in
+# the network providing auth (eg, TLS/x509 certificates)
+#
+# - sasl: use SASL infrastructure. The actual auth scheme is then
+# controlled from /etc/sasl2/libvirt.conf. For the TCP
+# socket only GSSAPI & DIGEST-MD5 mechanisms will be used.
+# For non-TCP or TLS sockets, any scheme is allowed.
+#
+# - polkit: use PolicyKit to authenticate. This is only suitable
+# for use on the UNIX sockets. The default policy will
+# require a user to supply their own password to gain
+# full read/write access (aka sudo like), while anyone
+# is allowed read/only access.
+#
+# Set an authentication scheme for UNIX read-only sockets
+# By default socket permissions allow anyone to connect
+#
+# To restrict monitoring of domains you may wish to enable
+# an authentication mechanism here
+auth_unix_ro = \"none\"
+
+# Set an authentication scheme for UNIX read-write sockets
+# By default socket permissions only allow root. If PolicyKit
+# support was compiled into libvirt, the default will be to
+# use 'polkit' auth.
+#
+# If the unix_sock_rw_perms are changed you may wish to enable
+# an authentication mechanism here
+auth_unix_rw = \"none\"
+
+# Change the authentication scheme for TCP sockets.
+#
+# If you don't enable SASL, then all TCP traffic is cleartext.
+# Don't do this outside of a dev/test scenario. For real world
+# use, always enable SASL and use the GSSAPI or DIGEST-MD5
+# mechanism in /etc/sasl2/libvirt.conf
+auth_tcp = \"sasl\"
+
+# Change the authentication scheme for TLS sockets.
+#
+# TLS sockets already have encryption provided by the TLS
+# layer, and limited authentication is done by certificates
+#
+# It is possible to make use of any SASL authentication
+# mechanism as well, by using 'sasl' for this option
+auth_tls = \"none\"
+
+
+
+#################################################################
+#
+# TLS x509 certificate configuration
+#
+
+
+# Override the default server key file path
+#
+key_file = \"/etc/pki/libvirt/private/serverkey.pem\"
+
+# Override the default server certificate file path
+#
+cert_file = \"/etc/pki/libvirt/servercert.pem\"
+
+# Override the default CA certificate path
+#
+ca_file = \"/etc/pki/CA/cacert.pem\"
+
+# Specify a certificate revocation list.
+#
+# Defaults to not using a CRL, uncomment to enable it
+crl_file = \"/etc/pki/CA/crl.pem\"
+
+
+
+#################################################################
+#
+# Authorization controls
+#
+
+
+# Flag to disable verification of client certificates
+#
+# Client certificate verification is the primary authentication mechanism.
+# Any client which does not present a certificate signed by the CA
+# will be rejected.
+#
+# Default is to always verify. Uncommenting this will disable
+# verification - make sure an IP whitelist is set
+tls_no_verify_certificate = 1
+
+
+# A whitelist of allowed x509 Distinguished Names
+# This list may contain wildcards such as
+#
+# \"C=GB,ST=London,L=London,O=Red Hat,CN=*\"
+#
+# See the POSIX fnmatch function for the format of the wildcards.
+#
+# NB If this is an empty list, no client can connect, so comment out
+# entirely rather than using empty list to disable these checks
+#
+# By default, no DN's are checked
+ tls_allowed_dn_list = [\"DN1\", \"DN2\"]
+
+
+# A whitelist of allowed SASL usernames. The format for usernames
+# depends on the SASL authentication mechanism. Kerberos usernames
+# look like username@REALM
+#
+# This list may contain wildcards such as
+#
+# \"*@EXAMPLE.COM\"
+#
+# See the POSIX fnmatch function for the format of the wildcards.
+#
+# NB If this is an empty list, no client can connect, so comment out
+# entirely rather than using empty list to disable these checks
+#
+# By default, no Username's are checked
+sasl_allowed_username_list = [
+ \"joe@EXAMPLE.COM\",
+ \"fred@EXAMPLE.COM\"
+]
+"
+
+ test Libvirtd.lns get conf =
+ { "comment" = "Master libvirt daemon configuration file" }
+ { "comment" = "" }
+ { "comment" = "For further information consult http://libvirt.org/format.html" }
+ { "empty" }
+ { "empty" }
+ { "comment" = "################################################################" }
+ { "comment" = "" }
+ { "comment" = "Network connectivity controls" }
+ { "comment" = "" }
+ { "empty" }
+ { "comment" = "Flag listening for secure TLS connections on the public TCP/IP port." }
+ { "comment" = "NB, must pass the --listen flag to the libvirtd process for this to" }
+ { "comment" = "have any effect." }
+ { "comment" = "" }
+ { "comment" = "It is necessary to setup a CA and issue server certificates before" }
+ { "comment" = "using this capability." }
+ { "comment" = "" }
+ { "comment" = "This is enabled by default, uncomment this to disable it" }
+ { "listen_tls" = "0" }
+ { "empty" }
+ { "comment" = "Listen for unencrypted TCP connections on the public TCP/IP port." }
+ { "comment" = "NB, must pass the --listen flag to the libvirtd process for this to" }
+ { "comment" = "have any effect." }
+ { "comment" = "" }
+ { "comment" = "Using the TCP socket requires SASL authentication by default. Only" }
+ { "comment" = "SASL mechanisms which support data encryption are allowed. This is" }
+ { "comment" = "DIGEST_MD5 and GSSAPI (Kerberos5)" }
+ { "comment" = "" }
+ { "comment" = "This is disabled by default, uncomment this to enable it." }
+ { "listen_tcp" = "1" }
+ { "empty" }
+ { "empty" }
+ { "empty" }
+ { "comment" = "Override the port for accepting secure TLS connections" }
+ { "comment" = "This can be a port number, or service name" }
+ { "comment" = "" }
+ { "tls_port" = "16514" }
+ { "empty" }
+ { "comment" = "Override the port for accepting insecure TCP connections" }
+ { "comment" = "This can be a port number, or service name" }
+ { "comment" = "" }
+ { "tcp_port" = "16509" }
+ { "empty" }
+ { "empty" }
+ { "comment" = "Override the default configuration which binds to all network" }
+ { "comment" = "interfaces. This can be a numeric IPv4/6 address, or hostname" }
+ { "comment" = "" }
+ { "listen_addr" = "192.168.0.1" }
+ { "empty" }
+ { "empty" }
+ { "comment" = "Flag toggling mDNS advertizement of the libvirt service." }
+ { "comment" = "" }
+ { "comment" = "Alternatively can disable for all services on a host by" }
+ { "comment" = "stopping the Avahi daemon" }
+ { "comment" = "" }
+ { "comment" = "This is enabled by default, uncomment this to disable it" }
+ { "mdns_adv" = "0" }
+ { "empty" }
+ { "comment" = "Override the default mDNS advertizement name. This must be" }
+ { "comment" = "unique on the immediate broadcast network." }
+ { "comment" = "" }
+ { "comment" = "The default is \"Virtualization Host HOSTNAME\", where HOSTNAME" }
+ { "comment" = "is subsituted for the short hostname of the machine (without domain)" }
+ { "comment" = "" }
+ { "mdns_name" = "Virtualization Host Joe Demo" }
+ { "empty" }
+ { "empty" }
+ { "comment" = "################################################################" }
+ { "comment" = "" }
+ { "comment" = "UNIX socket access controls" }
+ { "comment" = "" }
+ { "empty" }
+ { "comment" = "Set the UNIX domain socket group ownership. This can be used to" }
+ { "comment" = "allow a 'trusted' set of users access to management capabilities" }
+ { "comment" = "without becoming root." }
+ { "comment" = "" }
+ { "comment" = "This is restricted to 'root' by default." }
+ { "unix_sock_group" = "libvirt" }
+ { "empty" }
+ { "comment" = "Set the UNIX socket permissions for the R/O socket. This is used" }
+ { "comment" = "for monitoring VM status only" }
+ { "comment" = "" }
+ { "comment" = "Default allows any user. If setting group ownership may want to" }
+ { "comment" = "restrict this to:" }
+ { "unix_sock_ro_perms" = "0777" }
+ { "empty" }
+ { "comment" = "Set the UNIX socket permissions for the R/W socket. This is used" }
+ { "comment" = "for full management of VMs" }
+ { "comment" = "" }
+ { "comment" = "Default allows only root. If PolicyKit is enabled on the socket," }
+ { "comment" = "the default will change to allow everyone (eg, 0777)" }
+ { "comment" = "" }
+ { "comment" = "If not using PolicyKit and setting group ownership for access" }
+ { "comment" = "control then you may want to relax this to:" }
+ { "unix_sock_rw_perms" = "0770" }
+ { "empty" }
+ { "empty" }
+ { "empty" }
+ { "comment" = "################################################################" }
+ { "comment" = "" }
+ { "comment" = "Authentication." }
+ { "comment" = "" }
+ { "comment" = "- none: do not perform auth checks. If you can connect to the" }
+ { "comment" = "socket you are allowed. This is suitable if there are" }
+ { "comment" = "restrictions on connecting to the socket (eg, UNIX" }
+ { "comment" = "socket permissions), or if there is a lower layer in" }
+ { "comment" = "the network providing auth (eg, TLS/x509 certificates)" }
+ { "comment" = "" }
+ { "comment" = "- sasl: use SASL infrastructure. The actual auth scheme is then" }
+ { "comment" = "controlled from /etc/sasl2/libvirt.conf. For the TCP" }
+ { "comment" = "socket only GSSAPI & DIGEST-MD5 mechanisms will be used." }
+ { "comment" = "For non-TCP or TLS sockets, any scheme is allowed." }
+ { "comment" = "" }
+ { "comment" = "- polkit: use PolicyKit to authenticate. This is only suitable" }
+ { "comment" = "for use on the UNIX sockets. The default policy will" }
+ { "comment" = "require a user to supply their own password to gain" }
+ { "comment" = "full read/write access (aka sudo like), while anyone" }
+ { "comment" = "is allowed read/only access." }
+ { "comment" = "" }
+ { "comment" = "Set an authentication scheme for UNIX read-only sockets" }
+ { "comment" = "By default socket permissions allow anyone to connect" }
+ { "comment" = "" }
+ { "comment" = "To restrict monitoring of domains you may wish to enable" }
+ { "comment" = "an authentication mechanism here" }
+ { "auth_unix_ro" = "none" }
+ { "empty" }
+ { "comment" = "Set an authentication scheme for UNIX read-write sockets" }
+ { "comment" = "By default socket permissions only allow root. If PolicyKit" }
+ { "comment" = "support was compiled into libvirt, the default will be to" }
+ { "comment" = "use 'polkit' auth." }
+ { "comment" = "" }
+ { "comment" = "If the unix_sock_rw_perms are changed you may wish to enable" }
+ { "comment" = "an authentication mechanism here" }
+ { "auth_unix_rw" = "none" }
+ { "empty" }
+ { "comment" = "Change the authentication scheme for TCP sockets." }
+ { "comment" = "" }
+ { "comment" = "If you don't enable SASL, then all TCP traffic is cleartext." }
+ { "comment" = "Don't do this outside of a dev/test scenario. For real world" }
+ { "comment" = "use, always enable SASL and use the GSSAPI or DIGEST-MD5" }
+ { "comment" = "mechanism in /etc/sasl2/libvirt.conf" }
+ { "auth_tcp" = "sasl" }
+ { "empty" }
+ { "comment" = "Change the authentication scheme for TLS sockets." }
+ { "comment" = "" }
+ { "comment" = "TLS sockets already have encryption provided by the TLS" }
+ { "comment" = "layer, and limited authentication is done by certificates" }
+ { "comment" = "" }
+ { "comment" = "It is possible to make use of any SASL authentication" }
+ { "comment" = "mechanism as well, by using 'sasl' for this option" }
+ { "auth_tls" = "none" }
+ { "empty" }
+ { "empty" }
+ { "empty" }
+ { "comment" = "################################################################" }
+ { "comment" = "" }
+ { "comment" = "TLS x509 certificate configuration" }
+ { "comment" = "" }
+ { "empty" }
+ { "empty" }
+ { "comment" = "Override the default server key file path" }
+ { "comment" = "" }
+ { "key_file" = "/etc/pki/libvirt/private/serverkey.pem" }
+ { "empty" }
+ { "comment" = "Override the default server certificate file path" }
+ { "comment" = "" }
+ { "cert_file" = "/etc/pki/libvirt/servercert.pem" }
+ { "empty" }
+ { "comment" = "Override the default CA certificate path" }
+ { "comment" = "" }
+ { "ca_file" = "/etc/pki/CA/cacert.pem" }
+ { "empty" }
+ { "comment" = "Specify a certificate revocation list." }
+ { "comment" = "" }
+ { "comment" = "Defaults to not using a CRL, uncomment to enable it" }
+ { "crl_file" = "/etc/pki/CA/crl.pem" }
+ { "empty" }
+ { "empty" }
+ { "empty" }
+ { "comment" = "################################################################" }
+ { "comment" = "" }
+ { "comment" = "Authorization controls" }
+ { "comment" = "" }
+ { "empty" }
+ { "empty" }
+ { "comment" = "Flag to disable verification of client certificates" }
+ { "comment" = "" }
+ { "comment" = "Client certificate verification is the primary authentication mechanism." }
+ { "comment" = "Any client which does not present a certificate signed by the CA" }
+ { "comment" = "will be rejected." }
+ { "comment" = "" }
+ { "comment" = "Default is to always verify. Uncommenting this will disable" }
+ { "comment" = "verification - make sure an IP whitelist is set" }
+ { "tls_no_verify_certificate" = "1" }
+ { "empty" }
+ { "empty" }
+ { "comment" = "A whitelist of allowed x509 Distinguished Names" }
+ { "comment" = "This list may contain wildcards such as" }
+ { "comment" = "" }
+ { "comment" = "\"C=GB,ST=London,L=London,O=Red Hat,CN=*\"" }
+ { "comment" = "" }
+ { "comment" = "See the POSIX fnmatch function for the format of the wildcards." }
+ { "comment" = "" }
+ { "comment" = "NB If this is an empty list, no client can connect, so comment out" }
+ { "comment" = "entirely rather than using empty list to disable these checks" }
+ { "comment" = "" }
+ { "comment" = "By default, no DN's are checked" }
+ { "tls_allowed_dn_list"
+ { = "DN1"}
+ { = "DN2"}
+ }
+ { "empty" }
+ { "empty" }
+ { "comment" = "A whitelist of allowed SASL usernames. The format for usernames" }
+ { "comment" = "depends on the SASL authentication mechanism. Kerberos usernames" }
+ { "comment" = "look like username@REALM" }
+ { "comment" = "" }
+ { "comment" = "This list may contain wildcards such as" }
+ { "comment" = "" }
+ { "comment" = "\"*@EXAMPLE.COM\"" }
+ { "comment" = "" }
+ { "comment" = "See the POSIX fnmatch function for the format of the wildcards." }
+ { "comment" = "" }
+ { "comment" = "NB If this is an empty list, no client can connect, so comment out" }
+ { "comment" = "entirely rather than using empty list to disable these checks" }
+ { "comment" = "" }
+ { "comment" = "By default, no Username's are checked" }
+ { "sasl_allowed_username_list"
+ { = "joe@EXAMPLE.COM" }
+ { = "fred@EXAMPLE.COM" }
+ }
Index: libvirt.spec.in
===================================================================
RCS file: /data/cvs/libvirt/libvirt.spec.in,v
retrieving revision 1.91
diff -u -p -r1.91 libvirt.spec.in
--- libvirt.spec.in 21 Aug 2008 09:28:54 -0000 1.91
+++ libvirt.spec.in 26 Aug 2008 20:04:24 -0000
@@ -252,6 +252,8 @@ fi
%dir %{_localstatedir}/lib/libvirt/
%dir %attr(0700, root, root) %{_localstatedir}/lib/libvirt/images/
%dir %attr(0700, root, root) %{_localstatedir}/lib/libvirt/boot/
+%{_datadir}/augeas/lenses/libvirtd.aug
+%{_datadir}/augeas/lenses/tests/test_libvirtd.aug
%if %{with_polkit}
%{_datadir}/PolicyKit/policy/org.libvirt.unix.policy
%endif
--
|: Red Hat, Engineering, London -o- http://people.redhat.com/berrange/ :|
|: http://libvirt.org -o- http://virt-manager.org -o- http://ovirt.org :|
|: http://autobuild.org -o- http://search.cpan.org/~danberr/ :|
|: GnuPG: 7D3B9505 -o- F3C9 553F A1DA 4AC2 5648 23C1 B3DF F742 7D3B 9505 :|
_______________________________________________
augeas-devel mailing list
augeas-devel@redhat.com
https://www.redhat.com/mailman/listinfo/augeas-devel