Java web application I'm working on recently (let's name it lobster) is embedding and packaging Jetty inside itself. This makes application artifact more self-contained and independent, because it does not require preinstalled and preconfigured server.
To simplify application deployment even more, it is packaged as RPM file, which is uploaded into Nexus serving as Yum repository.
Deployment then is simple matter of executing sudo yum install lobster and thanks to RPM scriptlets, server is automaticaly restarted as a part or installation.
Everything went nice and smoothly, until second release. When yum update happend, we have found how amazingly wierd thing RPM upgrade is.
sudo yum update lobster execution completed, but application failed to start and logfile contained strange exceptionsCaused by: java.io.FileNotFoundException: /opt/lobster/lib/lobster-core-0.4.0.jar (No such file or directory) at java.util.zip.ZipFile.open(Native Method) ~[na:1.7.0_40] at java.util.zip.ZipFile.(ZipFile.java:215) ~[na:1.7.0_40] at java.util.zip.ZipFile. (ZipFile.java:145) ~[na:1.7.0_40] at java.util.jar.JarFile. (JarFile.java:153) ~[na:1.7.0_40] at java.util.jar.JarFile. (JarFile.java:90) ~[na:1.7.0_40] at sun.net.www.protocol.jar.URLJarFile. (URLJarFile.java:93) ~[na:1.7.0_40] at sun.net.www.protocol.jar.URLJarFile.getJarFile(URLJarFile.java:69) ~[na:1.7.0_40] at sun.net.www.protocol.jar.JarFileFactory.get(JarFileFactory.java:99) ~[na:1.7.0_40] at sun.net.www.protocol.jar.JarURLConnection.connect(JarURLConnection.java:122) ~[na:1.7.0_40] at sun.net.www.protocol.jar.JarURLConnection.getJarFile(JarURLConnection.java:89) ~[na:1.7.0_40]
What was wierd even more, that it was lobster version 0.5.0 installation and 0.4.0 stated in stacktrace, actualy was previous version!
To make story short, after some googling I've found RPM upgrade sequence.
- execute new version %pre [ $1 >= 2 ]
- unpack new version files (both old and new are now mixed together)
- execute new version %post [ $1 >= 2 ]
- execute old version %preun [ $1 == 1 ]
- remove old files (only new and unchanged stays)
- execute old verion %postun [ $1 == 1 ]
Important is, that between step 2 and 5, mixture of old and new version jar files is present in installation directory! Attempt to start server java process in %post or %preun scriptlet can only result in disaster same as we experienced. Old version jars will be deleted right after scriptlet execution.
Here comes working install/upgrade/uninstall solution
%pre scriptlet
#!/bin/sh # rpm %pre scriptlet # # parameter $1 means # $1 == 1 ~ initial installation # $1 >= 2 ~ version upgrade # never executed for uninstall echo "rpm: pre-install $1" # failsafe commands - can't break anything # make sure that user exist id -u lobster &>/dev/null || useradd lobster # make sure that application is not runnig if [ -f /etc/init.d/lobster ]; then /sbin/service lobster stop fi
%post scriptlet
Important is NOT to start application on rpm upgrade#!/bin/sh # rpm %post scriptlet # # parameter $1 means # $1 == 1 ~ initial installation # $1 >= 2 ~ version upgrade # never executed for uninstall echo "rpm: post-install $1" # initial install if [ "$1" -eq "1" ]; then /sbin/chkconfig --add lobster /sbin/service lobster start fi
%preun scriptlet
#!/bin/sh # rpm %preun scriptlet # # parameter $1 means # $1 == 0 ~ uninstall last # $1 == 1 ~ version upgrade # never executed for first install echo "rpm: pre-uninstall $1" # uninstall last if [ "$1" -eq "0" ]; then /sbin/service lobster stop /sbin/chkconfig --del lobster fi
%postun scriptlet
Here is right place to start application on rpm upgrade#!/bin/sh # rpm %postun scriptlet # # parameter $1 means # $1 == 0 ~ uninstall last # $1 == 1 ~ version upgrade # never executed for first install # console output is surpressed for postun% ! echo "rpm: post-uninstall $1" # upgrade if [ "$1" -ge "1" ]; then /sbin/service lobster start fi
Useful RPM scriptlet documentation is in Fedora Wiki also how to integrate with SysV Init Scripts
Happy RPM deployments!
No comments:
Post a Comment