Cross-distribution packaging: Providing a systemd service

We use the upcoming opsi 4.1 to remove obsolete raiminigs that accumulated over time. This is also a good time to get the packaging up to date.

On systems running systemd we used some hacks with opsi 4.0 that allowed us to treat support for systemd as an optional feature. Now we want to make systemd first class, remove hacks and use the standards that the various distributions recommend.

I want to show how we end up packaging opsiconfd to work with systems using Debians .deb package format and those using .rpm. .deb files work the same across all major distributions and we serve Debian, Ubuntu and Univention Corporate Server (UCS) with the same setup. On the RPM-side we focus on the distributions provided by SUSE (SLES, openSUSE), Red Hat (RHEL) and the open source variant CentOS.

Read more…


We have new stuff to play with! Since last week we have two ARM boards. The official openSuse Build Service can't make Debian and Ubuntu packages for the ARM architecture. The OBS lacks the ARM repositories within the Debian and Ubuntu projects from where the packages are downloaded. Luckily we have our own internal instance. Let's see where this will get our beloved opsi.

BananaPi M2 Ultra & Odroid-Xu4

The Splash Screen is coming back!

The opsi splash screen returns! With the release of opsi 4.0.6 the opsi splash screen was not available. The splash screen and the depending programs were too large and the bootimage was heavily limited in space. Therefore kernel messages or a black blank screen were shown to the user booting the opsi bootimage.

However opsi 4.1 will use another tftpd. With this new tftpd opsi is no longer restricted to the infamous 90MB file limit it was scratching all the time. Without this limitation the bootimage can feature more packages and features. One of those features is a basic splash screen.

Read more…

opsi-utils: Now with manpages! (Again!)

Do you know that feeling when you are sure certain things exist but others don't? I had that exact feeling a short while ago during a discussing with one of our support staff. I thought it would be a good idea to show the documentation so I told him to just open the manpages.

After a short silence he said that there are no manpages and he'd be surprised if there would be. But I was certain, I did bring them into the build process and the files are there! We checked and he was right: no manpages existed. There weren't even appropriate files to be found on the server. That seemed impossible!

After I checked the script used for creating the packages everything seemed good. But it began to dawn on me why there were no manpages installed.

The old building process all took place on one machine where we would manually update the working copy of the repository and then run a script that gave us three files we would then load into OBS. That script did also include the manpages.

Because there are usually only few changes on the options of the utility script the creation of the manpages was a separate script. Our manpages are written in asciidoc and then converted into the required format. This makes writing them very easy. After they are converted to the manpage format we use them for all the different distributions we support.

This was not a problem as long as we kept building on that machine and only updated the files in our working copy. But a while ago we switched to Jenkins to fulfill this task whenever we push something new onto the repository. The switch was successful but one thing was forgotten: running the script that creates the manpages!

The fix was a small one and since opsi-utils the manpages are installed alongside the programs. Again.

Upcoming: CeBIT 2017

The current week was for nearly all of us under the sign of CeBIT which will take place at Hannover, Germany the next week. The technology fair is an important date for the company and we use it not only to talk to users old and new but also to show new features.

We will be in the Open Source Park in hall 3 at D35 and we'd love to talk to you!

For presentations we bring some machines with us that hold complete demo environments. The demo environments feature various virtual clients all equipped with different operating systems and a complete Samba 4 AD DC. Of course all these were set up using opsi! Admittedly it took us some time to be able to set up the machines through opsi like this but we end up with multiple machines set up to feature the exact same installations and data. And now all it takes to set up a machine like this just requires a few clicks.

People from the dev team will be present the whole week and there will be a talk about our testing environment on friday. I've even heard some rumors about opsi swag... ;)

So if you are at CeBIT come and visit us!

API: new method setupWhereFailed

Sometimes the small things are the ones that make the greatest difference.

So with python-opsi comes a new method setupWhereFailed that takes an product ID as parameter and then will set that product to setup on all clients where that product has failed as action result.

I used this during some development tests and this made things very straight forward.

Here is how you can use it through opsi-admin with the product testproduct:

opsi-admin -d method setupWhereFailed testproduct

Quick tip: show certificate data

A small tip for anyone who needs to check what values their certificate uses. For the certificate renewal in opsi-setup --renew-opsiconfd-cert we want to reuse the values existing in the current certificate and have some code in python-opsi we can leverage now.

With the following command we are able to load the data from the certificate and print it to our shell:

python -c "import OPSI.Util.Task.Certificate as c; from pprint import pprint; pprint(c.loadConfigurationFromCertificate('/etc/opsi/opsiconfd.pem'))"

On my test system I get an output like the following:

{'commonName': u'nikosserver.test.local',
 'country': u'DE',
 'emailAddress': u'',
 'locality': u'Mainz',
 'organization': u'Ev1l C0rp',
 'organizationalUnit': u'Katzen',
 'serialNumber': 12345678901595886952L,
 'state': u'RP'}