Thursday 21 February 2013

Compress tomcat logs from cron rather than logrotate

The problem with Tomcat is that it is OS agnostic: those who do not understand unix are doomed to reinvent it.

Specifically Tomcat has its own substandard version of logrotate, which creates a new log file every day. Some times the archive is dated sometimes the live log is dated.

#! /bin/sh
#
# TPP 2013-02-21
#
# Tomcat apps use a variety of loggers, mostly log4j. 
# These rotate, conflicting with logrotate the unix log rotation system.
#
# Some files eg catalina.out 
# are rotated to a backup containing a date eg catalina.2013-01-06.log
# which can then be compressed with bz2 to catalina.2013-01-06.log.bz2
#

cd /var/log/tomcat6

# 2013-02-21
date=`date --rfc-3339=date`
year=`date +%Y`
timestamp=`date`

echo "${timestamp} Running ${0}"

for f in $(find catalina* |grep -v bz2 |grep -v '$date' |grep $year)
do 
 echo "bzip2 $f"
 bzip2 $f
done

# However others are active whilst containing a date 
# so we will find all and not compress the most recent

for l in 'localhost*' 'opt-db*' 'opt*' 'host-manager*' 'manager*'
do 
 previous="not_this_one"
 for f in $(find $l |grep -v bz2 |grep $year|sort)
 do
  if [ "${previous}" != "not_this_one" ]
  then
    echo "bzip2 ${previous}"
    bzip2 $previous
  fi
  previous=$f
 done
done


exit 0

Added /etc/cron.d/compress_crontab_logs

23 3 * * * root /etc/cron.daily/compress_tomcat_logs.sh

Tested on a fairly ancient SuSE and debian.

Monday 18 February 2013

In testing prefer lacunae over irreproducibility

When testing you may be tempted to use random inputs. This temptation will occur when you have a large problem space. The wishful thinking here is that the randomness will discover an error where analysis and inspection fail. The tragedy of this approach is that if it were to be successful there is every chance that you could not reproduce the test conditions.

The anxiety which randomness is brought in to quell is that there may be lacunae in non-random generated test data, where two variables vary in lock-step and so never expose a legitimate combination. This anxiety is a genuine one, and is not necessarily exposed by coverage tools. The sticking plaster of randomness is however not the way to address it.

Saturday 16 February 2013

VPN fails to restart after sleep

Thanks to this thread I discover an incantation:
sudo launchctl stop com.apple.racoon
sudo launchctl start com.apple.racoon

Monday 4 February 2013

Create an additional OpenClinica instance

Following on from the situation we were in in previous post we can create a .war file

Using an Ubuntu 12.10 desktop we are going to create an OpenClinica 3.1 instance on a existing SuSe install. This time called researcher.war.


cd /usr/local/oc/distribution/OpenClinica
emacs WEB-INF/classes/datainfo.properties
jar -cvf ../researcher.war *

The properties to change are:

dbHost=db.host.name
#slightly different than default configuration
filePath=${catalina.home}/openclinica.data/${WEBAPP.lower}/
sysURL=https://machinename/${WEBAPP}/MainMenu
log.dir=/var/log/tomcat6/${WEBAPP}

Copy war to remote host and login.


mkdir  /usr/share/tomcat6/openclinica.data/
mkdir  /usr/share/tomcat6/openclinica.data/researcher
chown -R tomcat:tomcat  /usr/share/tomcat6/openclinica.data/

We are using a remote db server. Login to db server, here we have Postgresql 8.4.7 installed.


sudo su postgres
psql
  CREATE ROLE clinica LOGIN ENCRYPTED PASSWORD 'clinica' SUPERUSER NOINHERIT NOCREATEDB NOCREATEROLE;
  CREATE DATABASE researcher WITH ENCODING='UTF8' OWNER=clinica";
  ALTER USER clinica WITH PASSWORD 'XXXX';

Back on the application server


cd /etc/apache2/vhosts.d/
emacs ours.conf

Add our new webapp

        JkMount /researcher/* worker1


/etc/init.d/tomcat6 stop
cp researcher.war /usr/share/tomcat6/webapps/
/etc/init.d/tomcat6 start

This should give you a clean system at https://machinename/researcher/MainMenu with a username of root and a one time password of 12345678.

Postgresql equivalent to show tables, show databases, describe table

Copied from Postgresql: show tables, show databases, show columns, describe table.

-- mysql: SHOW TABLES
\d 
SELECT table_name FROM information_schema.tables WHERE table_schema = 'public';

-- mysql: SHOW DATABASES
\l
SELECT datname FROM pg_database;

-- mysql: SHOW COLUMNS
\d <table>
SELECT column_name FROM information_schema.columns WHERE table_name ='table';

-- mysql: DESCRIBE TABLE
\d+ <table>
SELECT column_name FROM information_schema.columns WHERE table_name ='table';

Also to see the available roles:


SELECT rolname FROM pg_roles;

Friday 1 February 2013

Installation of OpenClinica on Ubuntu 12.10

Installing a new version of Open Clinica on an Ubuntu 12.10 desktop installation.

The hope is to then install this on a SuSE machine which already has a number of Open Clinica instances installed.

This involves creating a .war file with an instance specific name, we will use pets.war.

Register at openclinica.com. Download .zip

Looks like the installation notes are based on something other than the one true distribution; so taking some notes.

You cannot install the default Postgresql. It won't work.

Ensure you have completely removed all traces of Postgresql 9! The following should show no results:


dpkg -l  |grep postgres

Follow the installation of postgresql instructions at OpenClinica.


sudo chown -R postgres:postgres  /opt/PostgreSQL/8.4/

Unpack and copy to expected location:


sudo mv OpenClinica-3.1.3 /usr/local/
sudo ln -s OpenClinica-3.1.3 oc
cd /usr/local/oc

Create database user and database in Postgres:


sudo su postgres
/opt/PostgreSQL/8.4/bin/psql -U postgres -c "CREATE ROLE clinica LOGIN ENCRYPTED PASSWORD 'clinica' SUPERUSER NOINHERIT NOCREATEDB NOCREATEROLE"
/opt/PostgreSQL/8.4/bin/psql -U postgres -c "CREATE DATABASE pets WITH ENCODING='UTF8' OWNER=clinica"

Generate password with Password gorilla, but do not include punctuation.

Change password:


sudo su postgres
/opt/PostgreSQL/8.4/bin/psql -U postgres 
  ALTER USER clinica WITH PASSWORD 'XXXX';

Undocumented
Create a data directory with the webapp name.


sudo mkdir  /usr/share/tomcat7/pets.data
sudo chown tomcat7:tomcat7  /usr/share/tomcat7/pets.data

The way it is recommended you deploy is pretty awful, to paraphrase:

Unzip the .war copy to tomcat webapps directory, edit in place.

This may work on a Wednesday, but is not the right way®.

So what we will do is unpack the .war, stash in git. then build a new .war.

Ideally this would be by using the Maven War Overlay Plugin, but we might get it to work by creating the war manually.


cd /usr/local/oc
git init
emacs distribution/OpenClinica/WEB-INF/classes/datainfo.properties 

You must modify the following:

dbPass=XXXX
adminEmail=admin@example.com
but you probably also need to setup mail sending.

When you have edited these properties, create a .war file, which we will call pets.war


cd /usr/local/oc/distribution/OpenClinica/
jar -cvf ../pets.war *

Deploy:


sudo /etc/init.d/tomcat7 stop
sudo cp pets.war /var/lib/tomcat7/webapps/
sudo /etc/init.d/tomcat7 start

At this point you will need to allow yourself to manage Tomcat7, as it comes secured. Add the following to /etc/tomcat7/tomcat-users.xml.

<role rolename="manager-gui" />
<role rolename="manager-status" />
<role rolename="manager-script" />
<role rolename="manager-jmx" />

<role rolename="admin-gui" />
<role rolename="admin-script" />

<user username="admin" password="admin" roles="manager-gui, manager-status, admin-gui"/>

Unfortunately there is a problem (from localhost.date.log):


Feb 01, 2013 4:16:04 PM org.apache.catalina.core.StandardContext listenerStart
SEVERE: Exception sending context initialized event to listener instance of class org.akaza.openclinica.dao.core.OCContextLoaderListener
org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'liquibase' defined in class path resource [org/akaza/openclinica/applicationContext-core-db.xml]: Invocation of init method failed; nested exception is liquibase.exception.MigrationFailedException: Migration failed for change set migration/2.5/changeLogCreateTables.xml::1235684743487-0::pgawade (generated):
     Reason: liquibase.exception.JDBCException: Error executing SQL DROP LANGUAGE IF EXISTS plpgsql;
   CREATE PROCEDURAL LANGUAGE plpgsql;
   SET check_function_bodies = false;
   SET client_min_messages = error;
   SET default_tablespace = '';
   SET default_with_oids = true;
   SET search_path = public, pg_catalog;
   COMMENT ON SCHEMA public IS 'Standard public schema';:
          Caused By: Error executing SQL DROP LANGUAGE IF EXISTS plpgsql;
   CREATE PROCEDURAL LANGUAGE plpgsql;
   SET check_function_bodies = false;
   SET client_min_messages = error;
   SET default_tablespace = '';
   SET default_with_oids = true;
   SET search_path = public, pg_catalog;
   COMMENT ON SCHEMA public IS 'Standard public schema';:
          Caused By: ERROR: cannot drop language plpgsql because extension plpgsql requires it
 at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1420)
 at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:519)
 at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:456)
 at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:291)
 at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:222)
 at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:288)
 at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:190)
 at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:281)
 at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:190)
 at org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons(DefaultListableBeanFactory.java:563)
 at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:895)
 at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:425)
 at org.springframework.web.context.ContextLoader.createWebApplicationContext(ContextLoader.java:276)
 at org.springframework.web.context.ContextLoader.initWebApplicationContext(ContextLoader.java:197)
 at org.springframework.web.context.ContextLoaderListener.contextInitialized(ContextLoaderListener.java:47)
 at org.akaza.openclinica.dao.core.OCContextLoaderListener.contextInitialized(OCContextLoaderListener.java:38)
 at org.apache.catalina.core.StandardContext.listenerStart(StandardContext.java:4791)
 at org.apache.catalina.core.StandardContext.startInternal(StandardContext.java:5285)
 at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:150)
 at org.apache.catalina.core.ContainerBase.addChildInternal(ContainerBase.java:901)
 at org.apache.catalina.core.ContainerBase.addChild(ContainerBase.java:877)
 at org.apache.catalina.core.StandardHost.addChild(StandardHost.java:618)
 at org.apache.catalina.startup.HostConfig.deployWAR(HostConfig.java:963)
 at org.apache.catalina.startup.HostConfig$DeployWar.run(HostConfig.java:1600)
 at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:471)
 at java.util.concurrent.FutureTask$Sync.innerRun(FutureTask.java:334)
 at java.util.concurrent.FutureTask.run(FutureTask.java:166)
 at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1110)
 at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:603)
 at java.lang.Thread.run(Thread.java:722)

Apparently this can be fixed:


sudo /etc/init.d/tomcat7 stop
sudo su postgres
psql -U postgres
  DROP EXTENSION plpgsq;
  \q
exit
sudo /etc/init.d/tomcat7 start

At this point I discover that OpenClinica does not work with Postgresql 9.1!! Blogs are difficult to represent a process. I have updated the above so you won't encounter this error.

You may well see the following, which is a success message !


SEVERE: Servlet /pets threw load() exception
javax.servlet.ServletException: missing jspFile
 at org.apache.jasper.servlet.JspServlet.init(JspServlet.java:123)
 at org.apache.catalina.core.StandardWrapper.initServlet(StandardWrapper.java:1266)
 at org.apache.catalina.core.StandardWrapper.loadServlet(StandardWrapper.java:1185)
 at org.apache.catalina.core.StandardWrapper.load(StandardWrapper.java:1080)
 at org.apache.catalina.core.StandardContext.loadOnStartup(StandardContext.java:5027)
 at org.apache.catalina.core.StandardContext.startInternal(StandardContext.java:5314)
 at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:150)
 at org.apache.catalina.core.ContainerBase.addChildInternal(ContainerBase.java:901)
 at org.apache.catalina.core.ContainerBase.addChild(ContainerBase.java:877)
 at org.apache.catalina.core.StandardHost.addChild(StandardHost.java:618)
 at org.apache.catalina.startup.HostConfig.deployWAR(HostConfig.java:963)
 at org.apache.catalina.startup.HostConfig$DeployWar.run(HostConfig.java:1600)
 at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:471)
 at java.util.concurrent.FutureTask$Sync.innerRun(FutureTask.java:334)
 at java.util.concurrent.FutureTask.run(FutureTask.java:166)
 at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1110)
 at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:603)
 at java.lang.Thread.run(Thread.java:722)

http://localhost:8080/pets/ takes me to a login screen.

You can now login with a username of root and a one time password of 12345678.