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'}

Improving tests with any()

There are many gems inside the standard library of Python and I think the slogan batteries included is a great choice. But not many are that known and sometimes features get re-implemented because the function from the stdlib is not known.

While refactoring some tests I found code like the following:

found = False
for line in result:
    if line.strip():
        if 'admin users' in line:
            found = True

self.assertTrue(found, 'Missing Admin Users in Share opsi_depot')

That is a lot of code to check if a line with some required text is inside the iterable result.

This brings us to todays gem any()! If any item of the iterable passed to any is truth-y then the function returns True. If the iterable is empty or no truthy value is found we get a False.

With this knowledge we can shorten the test code to the following:

self.assertTrue(any('admin users' in line for line in result if line.strip()), 'Missing Admin Users in Share opsi_depot')

I have been even going so far as to throw out the self.assertTrue coming from unittest.TestCase as this makes a conversion to a different test framework easier and the test is still nice to read.

We can also remove the check if the line is filled (line.split()) because there is no chance of a false positive introduced by this.

Now we end up with this:

assert any('admin users' in line for line in result), 'Missing Admin Users in Share opsi_depot'

And if you ever want to check if all values in an iterable are truth-y you should check out the function all!