Puppet Module: kolab

The Kolab module for Puppet allows the continued management of a Kolab Groupware environment, by defining nodes as having a certain role within the Kolab Groupware environment.

To configure the exact way an included kolab module class behaves, the kolab module uses multiple parameterized classes.

Module Classes (or Roles)

kolab::imap

A class defining virtual resources to be realized by individual sub-classes, and resources shared between all IMAP servers.

Includes the following Munin plugins:

kolab::imap::full

A full, standalone Cyrus IMAP server. Inherits kolab::imap.

kolab::imap::backend

A Cyrus IMAP backend server, such that this server holds IMAP mailbox payload (technically, a backend can function as a frontend in a unified Cyrus IMAP Murder topology).

Inherits kolab::imap.

kolab::imap::frontend

A Cyrus IMAP frontend in a discrete Cyrus IMAP Murder topology.

Inherits kolab::imap.

kolab::imap::mupdate

A Cyrus IMAP Master Update (mupdate) server in a discrete Cyrus IMAP Murder topology.

Inherits kolab::imap.

kolab::ldap

kolab::mx

A generic mail exchanger.

kolab::mx::amavisd

Adds anti-spam and anti-virus to a mail exchanger.

kolab::mx::external

An Internet-facing mail exchanger.

kolab::mx::external::inbound

An Internet-facing mail exchanger for inbound traffic.

kolab::mx::external::outbound

An Internet-facing mail exchanger for outbound traffic.

kolab::mx::internal

An internal mail exchanger.

kolab::webserver

An webserver with all standard functionality included.

kolab::webserver::activesync

A webserver dedicated to providing ActiveSync for mobile device synchronization.

Merely includes kolab::webserver::syncroton.

kolab::webserver::chwala

A webserver dedicated to providing the Chwala file-cloud.

Inherits kolab::webserver::common.

kolab::webserver::common

Commonly shared resources between kolab::webserver sub-classes.

kolab::webserver::freebusy

A webserver dedicated to providing Free/Busy scheduling information.

Inherits kolab::webserver::common.

kolab::webserver::hkccp

A webserver dedicated to the Hosted Kolab Customer Control Panel.

Inherits kolab::webserver::common.

kolab::webserver::irony

A webserver dediciated to providing CalDAV, CardDAV and WebDAV functionality.

Inherits kolab::webserver::common.

kolab::webserver::roundcubemail

A webserver dedicated to the Roundcube webmail interface.

Inherits kolab::webserver::common.

kolab::webserver::syncroton

A webserver dedicated to providing ActiveSync for mobile device synchronization.

Inherits kolab::webserver::common.

kolab::webserver::webadmin

A webserver dedicated to providing the Kolab Web Administration Panel user interface and API.

Inherits kolab::webserver::common.

kolab::webserver::webmail

A wrapper class to install both kolab::webserver::roundcubemail and kolab::webserver::chwala.

kolab::yum

A class to maintain the YUM repository configuration for staged environments.

kolab::webserver::common

This class is shared between other kolab::webserver sub-classes, and provides the basis for a webserver configuration.

It includes Class[“webserver”] from Puppet Module: webserver, and configures commonly used virtual resources so that each individual component can realize them, preventing collisions between duplicate definitions.

Environment Stages and Package Version Locks

Configuration Parameters

kolab::params

The kolab::params class is a class commonly shared between all nodes participating in servicing Kolab Groupware.

imap_admin_login (cyrus-admin)

The administrative login for Cyrus IMAP.

Todo

A separate set of credentials should be supplied for wallace, freebusy, replication and proxy for the purposes of maintaining a more well-informed audit trail.

imap_admin_password (undef)

The password for the imap_admin_login.

imap_enable_notify (undef)

Enable the notifyd(8) service.

imap_enable_pop (undef)

Enable the pop3d(8) services.

imap_enable_ptloader (undef)

Enable the ptloader services.

imap_hostname ($fqdn)

The hostname to use to connect to IMAP.

While this setting applies to many services including the Kolab daemon, Wallace and Roundcube webmail, should the IMAP server for each of these services need to be different, we recommend you use a split DNS horizon.

imap_port (993)

The port to use when connecting to IMAP.

imap_scheme (imaps)

The scheme to use. Using imaps translates to configuring a prefix of ssl:// where appropriate, otherwise means tls://.

imap_storage_partitions ([ "default" ])

Define one or more storage partitions.

Note

The inclusion of the “default” partition is mandatory.

Example usage:

class { "kolab::params":
    imap_storage_partitions => [ "default", "archive" ]
}

imap_storage_meta_base_path (undef)

Undefined by default, allows the separation of IMAP spool metadata and message payload.

If defined, imap_storage_meta_base_path must be set to an absolute path that exists with 0750 permissions for the cyrus user and mail group.

The kolab module (or actually, Puppet) cannot ensure the directory exists, unless there is a guarantee that the parent directory exists – only / is guaranteed.

Example usage:

class { "kolab::params":
    imap_storage_meta_base_path => "/srv/imap/meta"
}

imap_storage_spool_base_path (/var/spool/imap)

Sets the root of the IMAP spool partitions.

Under the directory specified here, directories are created for each partition defined (with a mandated minimum list including default).

Example usage:

class { "kolab::params":
    imap_storage_spool_base_path => "/srv/imap/spool"
}

results in:

File["/srv/imap/spool/default/"]

imap_configdir (/var/lib/imap/)

The imapd.conf(5) configdir setting.

This directory normally contains databases among which mailboxes.db and annotations.db.

Because of backup processes, it may be desirable to have the default spool partition and configdir located under the same directory hierarchy off of the same logical volume mount.

Example usage:

class { "kolab::params":
    imap_configdir => "/srv/imap/config",
    imap_storage_spool_base_path => "/srv/imap/spool"
}

imap_duplicate_db_path (undef)

The deliver.db database file used to determine whether new message arrivals are duplicates (to be suppressed) contains a few days worth of delivery information.

However, it is not critical for operations and may simply be discarded in case of a system reboot.

If performance of message delivery is more important than the suppression of duplicates (which are a rather rare occurrence), then this file may be located under a directory hierarchy mounted off of tmpfs.

imap_ptscache_db_path (undef)

The ptscache.db database file caches information related to LDAP queries performed to find target result attributes for the process of canonification, and additional authorization information such as a user’s group memberships or roles.

This database can be discarded when a node reboots, and might therefore also live in a directory hierarchy mounted off of tmpfs.

imap_sievedir (undef)

Unless specifically required, keep this to a default value of ${configdir}/sieve.

imap_socket_path (/var/lib/imap/socket)

The path to where socket files are stored.

imap_statuscache_db_path (undef)

The statuscache.db database file is undocumented.

imap_temp_path (undef)

The absolute path to a location Cyrus IMAP can use to store temporary files.

imap_tlscache_db_path (undef)

The tls_sessions.db is a database file that maintains previously negotiated TLS sessions, allowing those sessions to be resumed at a later time.

This database can be discarded when a node reboots, and might therefore also live in a directory hierarchy mounted off of tmpfs.

kolab_version_name (kolab_14)

The version name of the Kolab Groupware product stream to use.

Possible values include:

  • kolab_14 (the default)

  • kolab_13

  • kolab_3_3

kolab_primary_domain ($domain)

The primary domain for the Kolab Groupware deployment.

Corresponds to the primary_domain setting in the [kolab] section of kolab.conf(5).

kolab_default_locale (en_US)

The default locale for the environment.

Corresponds to the setting default_locale in the [kolab] section of kolab.conf(5).

kolab_policy_uid (%(surname)s.lower())

The UID policy for Kolab.

Corresponds to the setting policy_uid in the [kolab] section of kolab.conf(5).

memcache_hosts (undef)

An array of hosts that serve memcached to be used for memcache- capable software applications unless specific memcached host addresses are defined for that service.

webclient_memcache_hosts ($kolab::params::memcache_hosts)

An array of hosts that serve memcached to be used solely for the webmail client software.

webadmin_memcache_hosts ($kolab::params::memcache_hosts)

An array of hosts that serve memcached to be used solely for the webadmin client software.

ldap_scheme (ldap)

The scheme name to use to connect to LDAP, where URIs are used.

Can be either of ldap or ldaps.

ldap_hostname ($fqdn)

The host address to use to connect to the LDAP service.

ldap_port (389)

The port to use to connect to the LDAP service.

ldap_domain_base_dn (cn=kolab,cn=config)

The base dn for domain objects.

roundcubemail_db_dsnw (mysqli://roundcube:password@localhost/roundcube)

roundcubemail_db_dsnr (undef)

ldap_bind_dn (cn=Directory Manager)

The login for the administrative credentials to use when binding to LDAP.

Note

Note that you are encouraged to provide the Kolab Groupware environment with credentials lesser privileged than “cn=Directory Manager”, but that certain functionality we have to make available in a standard deployment requires the use of these superuser credentials.

ldap_bind_pw (undef)

The password for the administrative credentials used to bind to LDAP.

ldap_root_dn (undef)

The root DN.

ldap_service_bind_dn (undef)

The bind DN for services, normally uid=kolab-service,ou=Special Users,${ldap_root_dn}

ldap_service_bind_pw (undef)

The bind password for services.

kolab_cache_sql_uri (mysql://kolab:Welcome2KolabSystems@localhost/kolab)

The URI to a SQL location to use for caching.

kolab_webadmin_sql_uri (mysql://kolab:Welcome2KolabSystems@localhost/kolab)

The URI to a SQL location to use for the web administration panel configuration.

roundcubemail_des_key (rcmail-!24ByteDESkey*Str)

The DES key used by the Roundcube webmail program to encrypt session-related information.

smtp_scheme (undef)

The scheme to use when connecting to SMTP.

smtp_hostname ($fqdn)

The host address to use when connecting to SMTP.

smtp_port (587)

The port to use when connecting to SMTP.

kolab::params::imap

imap_storage_partitions ($kolab::params::imap_storage_partitions)

Override the IMAP storage partitions set using kolab::params.

imap_storage_meta_base_path ($kolab::params::imap_storage_meta_base_path)

Override the IMAP metadata base path set using kolab::params.

imap_storage_spool_base_path ($kolab::params::imap_storage_spool_base_path)

Override the IMAP mail spool base path set using kolab::params.

imap_configdir ($kolab::params::imap_configdir)

Override the configdirectory setting in imapd.conf(5) set using kolab::params.

Note

So far this has not yet worked in practice.

imap_duplicate_db_path ($kolab::params::imap_duplicate_db_path)

Override the path to deliver.db set using kolab::params.

imap_ptscache_db_path ($kolab::params::imap_ptscache_db_path)

Override the path to ptscache.db set using kolab::params.

imap_sievedir ($kolab::params::imap_sievedir)

Override the Sieve directory set using kolab::params.

imap_socket_path ($kolab::params::imap_socket_path)

Override the directory used to store socket files set using kolab::params.

imap_statuscache_db_path ($kolab::params::imap_statuscache_db_path)

imap_temp_path ($kolab::params::imap_temp_path)

imap_tlscache_db_path ($kolab::params::imap_tlscache_db_path)

Todo

  1. Add a setting imap_proc_path.

  2. Add a setting webadmin_api_memcache_hosts

  3. Add a setting hkccp_memcache_hosts

Using the Kolab Module

We strongly encourage you wrap the individual kolab module classes with some of your own, in order to share certain configuration information between multiple nodes, but not share all information with all of them, and in order to allow divergence (in terms of development).

In the simplest form, going with all defaults, the class structure you might want to use looks as follows:

digraph {
        rankdir = LR;
        splines = true;
        overlab = prism;

        edge [color=gray50, fontname=Calibri, fontsize=11];
        node [shape=record, fontname=Calibri, fontsize=11, style=filled];

        "imapb01.example.org" [color="#EEFFEE"];
        "imapf01.example.org" [color="#EEFFEE"];

        subgraph cluster_example_org_kolab {
                label = "Class['example_org_kolab']";
                style = filled;

                "example_org_kolab::common" [color="#EEFFEE"];
                "example_org_kolab::imap" [color="#EEFFEE"];
                "example_org_kolab::imap::backend" [color="#EEFFEE"];
                "example_org_kolab::imap::frontend" [color="#EEFFEE"];

                "example_org_kolab::imap::backend" -> "example_org_kolab::imap" [label="inherits"];
                "example_org_kolab::imap::frontend" -> "example_org_kolab::imap" [label="inherits"];
                "example_org_kolab::imap" -> "example_org_kolab::common" [label="inherits"];
            }

        subgraph cluster_module_kolab {
                label = "Kolab Module";

                "kolab::imap::backend" [color="#EEEEFF"];
                "kolab::imap::frontend" [color="#EEEEFF"];
                "kolab::params" [color="#EEEEFF"];

                "Package['cyrus-imapd']" [color="#EEEEFF"];

            }

        "example_org_kolab::common" -> "kolab::params" [label="configures"];

        "imapb01.example.org" -> "example_org_kolab::imap::backend" [label="includes"];
        "example_org_kolab::imap::backend" -> "kolab::imap::backend" [label="includes"];

        "imapf01.example.org" -> "example_org_kolab::imap::frontend" [label="includes"];
        "example_org_kolab::imap::frontend" -> "kolab::imap::frontend" [label="includes"];

        "kolab::imap::backend" -> "Package['cyrus-imapd']" [label="installs"];
        "kolab::imap::frontend" -> "Package['cyrus-imapd']" [label="installs"];

        "kolab::params" -> "Package['cyrus-imapd']" [label="sets version for"];
    }

You might wonder why the green parts (yours) need to be so large, so lets look under the hood and apply some differentiation between IMAP frontends and backends.

Suppose that, for example, both types of IMAP servers require a different configdir setting in imapd.conf(5).

The kolab::params class is already configured by the parameterized inclusion of example_org_kolab::common, the class you use to share settings between all nodes related to Kolab Groupware services.

The frontend-, backend- and mupdate-specific classes would need to break the inheritance of the common class, and each instantiate kolab::params themselves, individually. Because your other functional components would still use the common class, this duplicates instantiating kolab::params times 4, for 3 environments each.

Therefore each example_org_kolab::imap sub-class is to instantiate a parameterized sub-class of kolab::params, called kolab::params::imap. This sub-class inherits kolab::params, so that you still have to configure those settings only once, but allow you to configure some additional, IMAP-server specific settings.

The same picture as before now looks a little bit more complex:

digraph {
        rankdir = LR;
        splines = true;
        overlab = prism;

        edge [color=gray50, fontname=Calibri, fontsize=11];
        node [shape=record, fontname=Calibri, fontsize=11, style=filled];

        "imapb01.example.org" [color="#EEFFEE"];
        "imapf01.example.org" [color="#EEFFEE"];

        subgraph cluster_example_org_kolab {
                label = "Class['example_org_kolab']";
                style = filled;

                "example_org_kolab::common" [color="#EEFFEE"];

                "example_org_kolab::imap" [color="#EEFFEE"];
                "example_org_kolab::imap::backend" [color="#EEFFEE"];
                "example_org_kolab::imap::frontend" [color="#EEFFEE"];
            }

        subgraph cluster_module_kolab {
                label = "Kolab Module";

                "kolab::imap::backend" [color="#EEEEFF"];
                "kolab::imap::frontend" [color="#EEEEFF"];
                "kolab::params" [color="#EEEEFF"];
                "kolab::params::imap" [color="#EEEEFF"];

                "File['/etc/imapd.conf']" [color="#EEEEFF"];
            }

        "example_org_kolab::common" -> "kolab::params" [label="configures"];

        "imapb01.example.org" -> "example_org_kolab::imap::backend" [label="includes"];
        "example_org_kolab::imap::backend" -> "example_org_kolab::imap" [label="inherits"];
        "example_org_kolab::imap" -> "example_org_kolab::common" [label="inherits"];
        "example_org_kolab::imap::backend" -> "kolab::params::imap" [label="configures"];
        "example_org_kolab::imap::backend" -> "kolab::imap::backend" [label="includes"];

        "imapf01.example.org" -> "example_org_kolab::imap::frontend" [label="includes"];
        "example_org_kolab::imap::frontend" -> "example_org_kolab::imap" [label="inherits"];
        "example_org_kolab::imap::frontend" -> "kolab::params::imap" [label="configures"];
        "example_org_kolab::imap::frontend" -> "kolab::imap::frontend" [label="includes"];

        "kolab::imap::backend" -> "File['/etc/imapd.conf']" [label="installs"];
        "kolab::imap::frontend" -> "File['/etc/imapd.conf']" [label="installs"];

        "kolab::params::imap" -> "kolab::params" [label="inherits"];
        "kolab::params::imap" -> "File['/etc/imapd.conf']" [label="sets configdir"];
        "kolab::params" -> "File['/etc/imapd.conf']" [label="configures"];
    }

Add to this picture the following considerations:

  • A deployment does not necessarily consist of homogeneous operating systems and operating system versions.

    Some systems may run CentOS 6, others RHEL 6, and perhaps yet some others RHEL 7.

    Even if this is not the day-to-day, each deployment will transition, sooner or later, therefore creating a hybrid environment (or worse).

  • A deployment is not necessarily comprised of systems all running the exact same Kolab Enterprise version. Some systems may happily continue to run a functional component based on Kolab Enterprise 13, while perhaps the web- or IMAP servers have moved on to run Kolab Enterprise 14.

    Again even if this is not the day-to-day, each deployment will transition, sooner or later.

  • The reproducibility of a system you have in production today, whether for the purposes of recovery or capacity increase, depends on your ability to not only produce a system, but have that system be maintained using the exact same package versions as the other systems in production.

While Puppet is intended to describe the desired state of individual nodes, and the desired state of so many nodes across and even within deployments may differ so much, the picture of the internals of the kolab module look yet again a little different from the previous diagram:

digraph {
        splines = true;
        overlab = prism;

        edge [color=gray50, fontname=Calibri, fontsize=11];
        node [shape=record, fontname=Calibri, fontsize=11, style=filled];

        "imapf01.example.org" [color="#EEFFEE"];
        "imapb01.example.org" [color="#EEFFEE"];
        "imapm01.example.org" [color="#EEFFEE"];

        subgraph cluster_example_org_kolab {
                label = "Class['example_org_kolab']";
                style = filled;

                "example_org_kolab::common" [color="#EEFFEE"];

                "example_org_kolab::imap" [color="#EEFFEE"];
                "example_org_kolab::imap::backend" [color="#EEFFEE"];
                "example_org_kolab::imap::frontend" [color="#EEFFEE"];
                "example_org_kolab::imap::mupdate" [color="#EEFFEE"];
            }

        subgraph cluster_module_kolab {
                label = "Kolab Module";

                "kolab::common" [color="#EEEEFF"];
                "kolab::imap" [color="#EEEEFF"];
                "kolab::imap::backend" [color="#EEEEFF"];
                "kolab::imap::frontend" [color="#EEEEFF"];
                "kolab::imap::mupdate" [color="#EEEEFF"];
                "kolab::params" [color="#EEEEFF"];
                "kolab::params::imap" [color="#EEEEFF"];
                "kolab::pkg" [color="#EEEEFF"];
                "kolab::pkg::${os}" [color="#EEEEFF"];
                "kolab::pkg::${os}::${osname}" [color="#EEEEFF"];
                "kolab::pkg::${os}::${osname}::${environment}" [color="#EEEEFF"];
                "kolab::pkg::${os}::${osname}::${environment}::${kolab_version}" [color="#EEEEFF"];
                "kolab::yum" [color="#EEEEFF"];

                "File['/etc/imapd.conf']" [color="#EEEEFF"];
                "Package['cyrus-imapd']" [color="#EEEEFF"];

                "File['/etc/imapd.conf']" -> "Package['cyrus-imapd']" [label="requires"];

            }

        "example_org_kolab::common" -> "kolab::params" [label="configures"];

        "imapb01.example.org" -> "example_org_kolab::imap::backend" [label="includes"];
        "example_org_kolab::imap::backend" -> "example_org_kolab::imap" [label="inherits"];
        "example_org_kolab::imap" -> "example_org_kolab::common" [label="inherits"];
        "example_org_kolab::imap::backend" -> "kolab::params::imap" [label="configures"];
        "example_org_kolab::imap::backend" -> "kolab::imap::backend" [label="includes"];

        "imapf01.example.org" -> "example_org_kolab::imap::frontend" [label="includes"];
        "example_org_kolab::imap::frontend" -> "example_org_kolab::imap" [label="inherits"];
        "example_org_kolab::imap::frontend" -> "kolab::params::imap" [label="configures"];
        "example_org_kolab::imap::frontend" -> "kolab::imap::frontend" [label="includes"];

        "imapm01.example.org" -> "example_org_kolab::imap::mupdate" [label="includes"];
        "example_org_kolab::imap::mupdate" -> "example_org_kolab::imap" [label="inherits"];
        "example_org_kolab::imap::mupdate" -> "kolab::params::imap" [label="configures"];
        "example_org_kolab::imap::mupdate" -> "kolab::imap::mupdate" [label="includes"];

        "kolab::params::imap" -> "kolab::params" [label="inherits"];

        "kolab::imap::backend" -> "kolab::imap" [label="inherits"];
        "kolab::imap::frontend" -> "kolab::imap" [label="inherits"];

        "kolab::imap" -> "Package['cyrus-imapd']" [label="defines"];
        "kolab::imap::backend" -> "Package['cyrus-imapd']" [label="realizes"];
        "kolab::imap::backend" -> "File['/etc/imapd.conf']" [label="realizes"];
        "kolab::imap::frontend" -> "Package['cyrus-imapd']" [label="realizes"];
        "kolab::imap::frontend" -> "File['/etc/imapd.conf']" [label="realizes"];
        "kolab::imap::mupdate" -> "Package['cyrus-imapd']" [label="realizes"];
        "kolab::imap::mupdate" -> "File['/etc/imapd.conf']" [label="realizes"];

        "kolab::imap" -> "kolab::common" [label="inherits"];
        "kolab::common" -> "kolab::params" [label="inherits"];

        "kolab::common" -> "kolab::pkg" [label="includes"];
        "kolab::common" -> "kolab::yum" [label="includes"];
        "kolab::pkg" ->
        "kolab::pkg::${os}" ->
        "kolab::pkg::${os}::${osname}" ->
        "kolab::pkg::${os}::${osname}::${environment}" ->
        "kolab::pkg::${os}::${osname}::${environment}::${kolab_version}" [label="includes"];

        "kolab::pkg::${os}::${osname}::${environment}::${kolab_version}" -> "kolab::params" [label="configures"];

        "kolab::params::imap" -> "File['/etc/imapd.conf']" [label="sets configdir"];
        "kolab::params" -> "File['/etc/imapd.conf']" [label="configures"];
        "kolab::params" -> "Package['cyrus-imapd']" [label="sets version for"];
    }

Example example_org_kolab Class

In this example class, we re-iterate how it is built up, and why.

First, the bare bones of it all:

# The module class wrapper.
class example_org_kolab {

    # The common class, that includes some basic configuration
    # information shared across all (most) Kolab nodes.
    class common inherits example_org_kolab { }

    # A container class for all things IMAP.
    class imap inherits common {
    }
}

Next, we populate some of the information (not all of the relevant information, for that see later on):

class example_org_kolab {
    class common inherits example_org_kolab {
        class { "kolab::params":
            imap_admin_login => "cyrus-admin",
            imap_admin_password => "password"
        }
    }

    class imap inherits common {
        include kolab::imap::full
    }
}

This gives us a base structure so that a node manifest might look as follows:

node 'imap.example.org' {
    include example_org_kolab::imap
}

The structure allows us to distinguish certain parameter values between environments:

class example_org_kolab {
    class common inherits example_org_kolab {
        case $environment {
            "development": {
                class { "kolab::params":
                    imap_admin_login => "cyrus-admin",
                    imap_admin_password => "password",
                    (...)
                }
            }
            "testing": {
                class { "kolab::params":
                    imap_admin_login => "cyrus-admin",
                    imap_admin_password => "anotherpassword",
                    (...)
                }
            }
            "production": {
                class { "kolab::params":
                    imap_admin_login => "cyrus-admin",
                    imap_admin_password => "verysecretpassword",
                    (...)
                }
            }
        }
    }

    class imap inherits common {
        include kolab::imap::full
    }
}

Or, alternatively:

class example_org_kolab {
    class common inherits example_org_kolab {
        class { "kolab::params":
            imap_admin_login => "cyrus-admin",
            imap_admin_password => $environment ? {
                "development" => "password",
                "testing" => "anotherpassword",
                "production" => "verysecretpassword"
            }
        }
    }

    class imap inherits common {
        include kolab::imap::full
    }
}

However, there are reasons to do it the way it was done the first time around:

  • Instead of defining Class['kolab::params'], include a class that comes from a file external to example_org_kolab class definition (and hide the actual value from prying eyes).

  • Not all environment stages need to contain all values for all parameters.

Sub-classing example_org_kolab further, to wrap individual more specific roles might give you something like this:

class example_org_kolab {
    class common inherits example_org_kolab {
        case $environment {
            "development": {
                class { 'kolab::params':
                    imap_admin_login => "cyrus-admin",
                    imap_admin_password => "somepass",
                    ldap_domain_base_dn => "ou=Domains,dc=example,dc=org",
                    imap_enable_notify => undef,
                    imap_enable_pop => true,
                    imap_enable_ptloader => true,
                    imap_hostname => "imap.example.org",
                    imap_port => 993,
                    imap_scheme => "imaps",
                    imap_socket_path => "/var/lib/imap/socket",
                    kolab_cache_sql_uri => "mysql://kolab:somepass@mysql-write.example.org/kolab_cache",
                    ldap_bind_dn => "cn=Directory Manager",
                    ldap_bind_pw => "somepass",
                    ldap_hostname => "ldap.example.org",
                    ldap_port => 389,
                    ldap_root_dn => "dc=example,dc=org",
                    ldap_service_bind_dn => "uid=kolab-service,ou=Special Users,dc=example,dc=org",
                    ldap_service_bind_pw => "somepass",
                    memcache_hosts => [ 'memc.example.org:11211' ],
                    roundcubemail_db_dsnw => "mysqli://roundcube:somepass@mysql-write.example.org/roundcube",
                    roundcubemail_db_dsnr => "mysqli://roundcube:somepass@mysql-read.example.org/roundcube",
                    roundcubemail_des_key => "somestringthatis24chars.",
                    smtp_hostname => "smtp.example.org",
                    smtp_port => 587
                }
            }
            "testing": {
                (...)
            }
            "production": {
                (...)
            }
        }
    }


class imap inherits common {
    class backend inherits imap {
        class { "kolab::params::imap":
                imap_configdir => "/srv/imap/config",
                imap_duplicate_db_path => "/var/tmp/cyrus-imapd/deliver.db",
                imap_ptscache_db_path => "/var/tmp/cyrus-imapd/ptscache.db",
                imap_sievedir => "/srv/imap/config/sieve/",
                imap_socket_path => "/srv/imap/config/socket",
                imap_statuscache_db_path => "/var/tmp/cyrus-imapd/statuscache.db",
                imap_storage_partitions => [ "default", "archive" ],
                imap_storage_meta_base_path => "/srv/imap/meta",
                imap_storage_spool_base_path => "/srv/imap/spool",
                imap_temp_path => "/var/tmp/cyrus-imapd/",
                imap_tlscache_db_path => "/var/tmp/cyrus-imapd/tls_sessions.db"
            }

        file { "/srv/imap/":
            ensure => directory
        }

        file { [
                "/srv/imap/config/",
                "/srv/imap/meta/",
                "/srv/imap/spool/"
            ]:
            ensure => directory,
            owner => "cyrus",
            group => "mail",
            mode => 750,
            require => Mount["/srv/imap"],
            notify => [
                    Exec["_usr_lib_cyrus-imapd_mkimap"],
                    Service["cyrus-imapd"]
                ]
        }

        file { "/srv/imap/config/proc/":
            ensure => "/var/tmp/cyrus-imapd/proc/",
            force => true,
            links => manage,
            noop => false,
            require => File["/var/tmp/cyrus-imapd/proc/"],
            notify => Service["cyrus-imapd"]
        }

        file { "/var/tmp/cyrus-imapd/":
            ensure => directory,
            owner => "cyrus",
            group => "mail",
            mode => 750,
            noop => false,
            notify => Service["cyrus-imapd"]
        }

        file { "/var/tmp/cyrus-imapd/proc/":
            ensure => directory,
            owner => "cyrus",
            group => "mail",
            mode => 750,
            noop => false,
            require => Mount["/var/tmp/cyrus-imapd"],
            notify => Service["cyrus-imapd"]
        }

        mount { "/srv/imap":
            atboot => true,
            device => "/dev/vg_imap/lv_imap",
            options => "defaults",
            fstype => "ext4",
            remounts => true,
            ensure => mounted,
            noop => false,
            require => File["/srv/imap/"],
            notify => Service["cyrus-imapd"]
        }

        mount { "/var/tmp/cyrus-imapd":
            atboot => true,
            device => "tmpfs",
            options => "defaults",
            fstype => "tmpfs",
            remounts => true,
            ensure => mounted,
            noop => false,
            require  => File["/var/tmp/cyrus-imapd/"],
            notify => Service["cyrus-imapd"]
        }

        include kolab::imap::backend
    }
}

node 'imapb01.example.org' {
    include example_org_kolab::imap::backend
}