There is something wonderful about getting new hardware. I love opening all the boxes and putting new servers into racks and plugging everything together. Setting up the OS and software however can be a pain. This is where Puppet and Landscape come to the rescue.

Puppet is great at configuring nodes the way you want them and keeping them that way. On the puppet master, you describe various aspects of the system using a simple declarative language. On the managed computers, a small agent talks to the puppet master and pulls down config changes. If you need to change a configuration on all your machines, you can change it once on the puppet master and it gets pushed out to all the agents.

In this article we’re going to use Landscape to do the initial setup of puppet. Tag a computer in Landscape with “puppet”, and the puppet agent will automatically be installed and configured. We’re going to use a meta-package plus some new Landscape features to make it all easy.

Meta-Package
The meta-package is a common trick used on Debian and Ubuntu based systems to easily pull in a subset of packages. Here we’ll use a meta-package to pull in all the puppet dependencies then run a small script to register the puppet agent to the puppet master.

Our meta-package will only have two files: control, and postinst. These files will both live in the DEBIAN directory like this:

working directory
  |> landscape-puppet
      |> DEBIAN
          |> control
          |> postinst


Here’s the control file:

1
2
3
4
5
6
7
8
Package: landscape-puppet
Version: 0.1
Section: main
Priority: standard
Architecture: all
Depends: landscape-client, puppet
Maintainer: Mike Milner <mike.milner@example.com>
Description: Configure system for use with puppet.


And here’s the postinst file – this gets executed after the package is installed:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
#!/bin/bash

PUPPETCONFIG=/etc/puppet/puppet.conf

# Back up current puppet config if it exists
if [ -f "$PUPPETCONFIG" ]; then
   mv $PUPPETCONFIG $PUPPETCONFIG.bak-landscape
fi

# Write the new puppet config file
cat > $PUPPETCONFIG << END
# Default puppet configuration pushed by Landscape.
[agent]
  server = puppet.example.com
  report = true
  pluginsync = true
END

# Use puppet itself to make sure the puppet service starts on boot
puppet resource service puppet ensure=running enable=true


To build the package, change to your working directory that contains the “landscape-puppet” directory then execute the following command:

1
$ dpkg-deb -b landscape-puppet landscape-puppet_0.1_all.deb


If all goes well you should now have a landscape-puppet.deb file in the current directory. Congratulations, you’ve built a meta-package!

This is just a touch on meta-packages. For more info check out https://help.ubuntu.com/community/MetaPackages

Landscape Repository Management
Now that we have a package, we’re going to use Landscape’s new Repository Management features to create a new apt repository and upload our package. Because this feature is so new, it’s only available through the API for now. I’ll walk you through setting things up.

Landscape’s Repository Management supports a few different use cases:

Landscape can mirror public repositories – like the official Ubuntu archive – into your local network. This gives you LAN speeds for updates and lets YOU control when packages get deployed.

Landscape can stage repositories. You might want to try new packages on a staging system before you roll them out to production. Landscape lets you selectively pull packages into your production repository after you’ve tested them on your staging system – all managed by Landscape.

And for this example, we’re using the Upload Repository. This lets you create an empty repository and upload your own packages for distribution.

In all cases Landscape takes care of the details for you. GPG keys are verified when mirroring external repositories, and keys are distributed to clients automatically when creating your own repositories. Everything is cryptographically verified.

To use the API, you first have to get your API credentials. Follow the steps on https://help.landscape.canonical.com/LDS/BetaReleaseNotes under the “API Getting Started” section. Once you’ve got your credentials set up in the appropriate environment variables use the following commands to set up the repository:

Create a new GPG key to sign your repository:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
$ cat > gpg-batch-commands << EOF
Key-Type: DSA
Key-Length: 2048
Subkey-Type: ELG-E
Subkey-Length: 2048
Name-Real: Landscape Repository Signing Key
Name-Comment: Landscape
Name-Email: landscape@example.com
Expire-Date: 0
%pubring landscape.pub
%secring landscape.sec
%commit
EOF

$ gpg --batch --gen-key gpg-batch-commands

$ gpg --no-default-keyring --secret-keyring ./landscape.sec \
  --keyring ./landscape.pub --export-secret-keys \
  -a > landscape-signing-key-secret


Now import your new secret key. Landscape will use it to sign your new repository:

1
2
3
4
5
$ landscape-api import-gpg-key upload-signing-key landscape-signing-key-secret
{u'fingerprint': u'c7da:4521:a948:600a:bd26:6e69:2fec:1d65:524a:3a15',
 u'has_secret': True,
 u'id': 3,
 u'name': u'upload-signing-key'}

 

Now that we have a key, we can configure our repository:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
$ landscape-api create-distribution landscape
{u'access_group': u'global',
 u'creation_time': u'2012-09-18T15:21:36Z',
 u'name': u'landscape',
 u'series': []}

$ landscape-api create-series upload landscape
{u'creation_time': u'2012-09-18T15:23:21Z', u'name': u'upload', u'pockets': []}

$ landscape-api create-pocket ubuntu upload landscape main amd64 upload upload-signing-key --upload-allow-unsigned
{u'apt_source_line': u'deb http://localhost:8080/repository/onward/landscape upload-ubuntu main',
 u'architectures': [u'amd64'],
 u'components': [u'main'],
 u'creation_time': u'2012-09-18T15:28:54Z',
 u'gpg_key': {u'fingerprint': u'c7da:4521:a948:600a:bd26:6e69:2fec:1d65:524a:3a15',
 u'has_secret': True,
 u'id': 3,
 u'name': u'upload-signing-key'},
 u'mode': u'upload',
 u'name': u'ubuntu',
 u'upload_allow_unsigned': True,
 u'upload_gpg_keys': []}

 

Now that we have our repository set up we need to upload our deb. To send packages to our upload pocket, we need to generate a “.changes” file which describes our upload. The “.changes” file contains additional information to help Landscape get your package into the right repository. Just use these commands to generate the “.changes” file and upload both files to Landscape.

If you are familiar with the “dput” command it can be used instead of the curl commands below. It has many options for checking your debs before upload. For this example however the curl commands will work fine.

1
2
3
4
5
$ changestool --create my.changes adddeb landscape_puppet_0.1_all.deb
$ changestool --create my.changes setdistribution upload-ubuntu

$ curl --upload-file landscape-puppet_0.1_all.deb http://lds.example.com/repository/standalone/landscape/upload/ubuntu/
$ curl --upload-file my.changes http://lds.example.com/repository/standalone/landscape/upload/ubuntu/


Now that our package is all set up in its repository, we will create a repository profile so we can make sure this repository is available to any machine with the “puppet” tag.

WARNING: Once you associate a repository profile to a computer in Landscape, it takes over management of your sources.list and sources.list.d on that computer. This means if you still want to use the official Ubuntu archive you need to make a repository profile for it. Take a look at the create-apt-source command and the documentation here for more details.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
$ landscape-api create-repository-profile landscape-upload
{u'access_group': u'global',
 u'all_computers': False,
 u'apt_sources': [],
 u'description': u'',
 u'id': 4,
 u'name': u'landscape-upload',
 u'pockets': [],
 u'tags': []}

$ landscape-api add-pockets-to-repository-profile landscape-upload ubuntu upload landscape
{u'access_group': u'global',
 u'all_computers': False,
 u'apt_sources': [],
 u'description': u'',
 u'id': 4,
 u'name': u'landscape-upload',
 u'pockets': [{u'apt_source_line': u'deb http://localhost:8080/repository/onward/landscape upload-ubuntu main',
 u'architectures': [u'amd64'],
 u'components': [u'main'],
 u'creation_time': u'2012-09-18T15:28:54Z',
 u'gpg_key': {u'fingerprint': u'c7da:4521:a948:600a:bd26:6e69:2fec:1d65:524a:3a15',
 u'has_secret': True,
 u'id': 3,
 u'name': u'upload-signing-key'},
 u'mode': u'upload',
 u'name': u'ubuntu',
 u'upload_allow_unsigned': True,
 u'upload_gpg_keys': []}],
 u'tags': []}

$ landscape-api associate-repository-profile landscape-upload --tags puppet
{u'access_group': u'global',
 u'all_computers': False,
 u'apt_sources': [],
 u'description': u'',
 u'id': 4,
 u'name': u'landscape-upload',
 u'pockets': [{u'apt_source_line': u'deb http://localhost:8080/repository/onward/landscape upload-ubuntu main',
 u'architectures': [u'amd64'],
 u'components': [u'main'],
 u'creation_time': u'2012-09-18T15:28:54Z',
 u'gpg_key': {u'fingerprint': u'c7da:4521:a948:600a:bd26:6e69:2fec:1d65:524a:3a15',
 u'has_secret': True,
 u'id': 3,
 u'name': u'upload-signing-key'},
 u'mode': u'upload',
 u'name': u'ubuntu',
 u'upload_allow_unsigned': True,
 u'upload_gpg_keys': []}],
 u'tags': [u'puppet']}

 

Landscape Package Profiles
So now we have our deb package sitting in a new apt repository ready to go. The final step is to create a package profile so the new package gets installed. We’ll do this using the GUI.



First, choose “Package Profiles” from the main menu:



Now, select “Add Package Profile”:



Fill in the form with your details:



Associate your new package profile with the “puppet” tag:



Finally you can see the status of the profile and how many computers have the profile installed:

Pulling it all together
Now that everything is set up, we really see the power of this technique. Pick any computer in Landscape and add the “puppet” tag. This will automatically add our new apt repository to the computers apt sources, then it will automatically install our new meta-package. The new meta-package will automatically install puppet and all its dependencies, then the postinst script will finish the whole thing off by registering the puppet agent to the puppet-master.

By combining Landscape features we can apply some very powerful automation to our infrastructure. In this case, once puppet is registered the puppet-master will finish off customising the system according to our system catalogues.

In a later post I’ll show how to use Landscape as an External Node Classifier for Puppet for even more automation!