On 05/12/2011 01:11 PM, Mark McLoughlin wrote:
Hey,
I haven't had a chance to read carefully through all the thread so far and I hope to do tomorrow, but I thought it was worth sharing how I assumed this would work and what, coincidentally, looks roughly like the direction Greg was taking with Audrey.
Some notes first:
A basic assumption we're making here is that a template should contain the packages needed for a service and the service definition just contains configuration in the form of a puppet manifest. So, the puppet manifest shouldn't cause new packages to be installed. That feels fairly arbitrary, but correct.
We need to consider the template and service authors - at the most basic level, we'll have some documentation on conventions to follow and how to register the templates and services. Perhaps we might have a UI or rich tooling for this in future. But what does it mean to author a template or service?
We need to bear in mind that puppet manifest, and configuration in general, is tied to the package versions in a template. It's not practical IMHO to assume that you can author a puppet manifest representing a service configuration and expect that to work with a wide range of templates.
So, here's how I assumed this would all work:
A template author starts by taking a base template (which is basically an XMLified simple kickstart file) and including that in her new template
<template> <name>my_template</name> <include name="f14-x86_64-base.tmpl"/> </template>
She adds further packages and configuration to the template, again similar in concept to editing a kickstart file
<template> ... <packages> <package name="emacs"/> </packages> <puppet manifest="my_template.pp"/> </template>
The puppet manifest is a standard puppet manifest.
She then can create new service definitions, or re-use existing service definitions by other authors, and reference these
<template> ... <services> <service name="my_postfix"> <puppet manifest="my_postfix.pp"/> </service> </services> </template>
The puppet manifest for services conforms to a set of conventions:
Each service is defined by a single parameterized class
The class has an $enabled parameter which defaults to false
When $enabled is false, the packages required for enabling the service are installed, but nothing else
When $enabled is true, the necessary configuration to enable the service is applied using any further parameters to the class
The class includes documentation for the service and its parameters which can be show in the UI
When a template is registered with Conductor, the parameters and docs are extracted from the puppet classes so that they can be exposed in the UI
When a template is built, the puppet manifests for the services are included in a standard location and asserted with the default parameters. This causes the packages available for all services to be installed.
Not sure I understand this part. Does this mean that puppet has to be executed at image build time? Or that there still is a packages reference in the template somewhere that pulls in the right packages?
In your example, would the template still explicitly call out that there's a requirement for the postfix package to be installed? Or, would it simply rely on the fact that the puppet script pulls in the package? If the latter, then doesn't this require puppet to run at image build time to fetch the package? Is it even possible to kick off puppet at image build time?
- When the template is instantiated, the user can select in the UI the services to enable and the parameters for each. When the instance starts, it contacts the config server for that information and runs the appropriate set of puppet classes with the appropriate parameters supplied via an "external node configuration" script
An example puppet manifest for a postfix service is below
Cheers, Mark.
class postfix($enabled = false, $relayhost = '') {
package { 'postfix': ensure => installed }
if $enabled { augeas { 'postfix_conf': context => '/files/etc/postfix/main.cf', changes => "set relayhost ${relayhost}", notify => Service['postfix'], require => Package['postfix'] }
exec { '/usr/sbin/alternatives --set mta /usr/sbin/sendmail.postfix': require => Package['postfix'] } service { ['sendmail', 'exim']: enable => false, ensure => stopped } service { 'postfix': enable => true, ensure => running, require => [ Service[sendmail, exim], Augeas[postfix_conf] ] }
} }