Installation service SonarQube

De EjnTricks

L'installation de Sonar a toujours été réalisée sous la forme d'un war déployé dans un serveur d'application, tel Tomcat. Depuis la version 4.0, il n'est plus aisé de construire le war à déployer. A partir de la version 4.4, cela devient vraiment compliqué sans de grosses modifications dans le code standard, voir quasi impossible pour les versions suivantes du fait de l'utilisation de produit tiers.

De plus, la mise en place d'un service est décrite sur le site officiel, mais il existe quelques suptilités.

L'application sera alors disponible depuis l'URL http://<HOST>:9000

Hand-icon.png Votre avis

Nobody voted on this yet

 You need to enable JavaScript to vote


Viewer icon.png Objectifs

L'installation de la distribution bundle, version 4.4, va être installée sur une plateforme Ubuntu avec les spécificités suivantes :

  • Exécution avec un compte sonar;
  • Configuration du fichier "PID" dans un répertoire sous /run/sonarqube;
  • Externalisation de fichiers en vue des mises à jour.


Study icon.png Etude

L'installation faite va mettre en place trois "répertoires", sous /var/opt/sonarqube pour cet article, afin de séparer la version installée, les fichiers communs à toutes les versions (plugins, configuration) et un lien pour référencer la version active. Pour l'installation de la version 4.4, cela donne :

  • /var/opt/sonarqube/4.4 : Contient les binaires de la version 4.4;
  • /var/opt/sonarqube/common : Contient tous les fichiers communs, comme les plugins utilisés;
  • /var/opt/sonarqube/installed : Lien vers la version utilisée, soit /var/opt/sonarqube/4.4.

Cependant, SonarQube utilise la variable d'environnement SONAR_HOME pour connaitre l'emplacement de ses répertoires. Jusqu'à cette version, ceci était spécifié dans le contexte d'exécution de Tomcat, ou dans le fichier properties du war.

Or ceci n'est plus disponible et il est important de comprendre comment cela est récupérée pour la mise en place des différents répertoires, et des nombreux liens qui en découlent. Lors de son démarrage, un serveur Tomcat] embarqué est démarré pour rendre disponible l'application. Ceci s'effectue au niveau d'une classe, org.sonar.application.EmbeddedTomcat dans le jar sonar-application-4.4.jar. Dans cette classe, la méthode start est exécutée, et c'est celle-ci qui est responsable de l'initialisation du contexte d'exécution.

  void start() throws IOException, LifecycleException {
    if ((this.tomcat != null) || (this.hook != null)) {
      throw new IllegalStateException("Server is already started");
    }
    


    System.setProperty("org.apache.tomcat.util.buf.UDecoder.ALLOW_ENCODED_SLASH", "true");
    
    System.setProperty("org.apache.catalina.startup.EXIT_ON_INIT_FAILURE", "true");
    

    System.setProperty("SONAR_HOME", this.env.rootDir().getAbsolutePath());
    
    this.tomcat = new Tomcat();
    

    String basedir = this.env.freshDir("temp/tomcat").getCanonicalPath();
    this.tomcat.setBaseDir(basedir);
    this.tomcat.getHost().setAppBase(basedir);
    this.tomcat.getHost().setAutoDeploy(false);
    this.tomcat.getHost().setCreateDirs(false);
    this.tomcat.getHost().setDeployOnStartup(true);
    
    Props props = Props.create(this.env);
    
    Logging.configure(this.tomcat, this.env, props);
    Connectors.configure(this.tomcat, props);
    Webapp.configure(this.tomcat, this.env, props);
    this.tomcat.start();
    addShutdownHook();
    this.tomcat.getServer().await();
    

    stop();
  }

SONAR_HOME est donc initiée avec l'emplacement retourné par this.env.rootDir().getAbsolutePath(). Dans la classe org.sonar.application.Env, tout est initié à partir de l'emplacement du fichier sonar.properties.

  Env(URL confUrl)
    throws URISyntaxException
  {
    if (confUrl == null) {
      throw new IllegalStateException("Do not copy-paste the configuration files (conf directory) from the old version. Update the content of the new files instead.");
    }
    this.confFile = new File(confUrl.toURI());
  }
  
  Env() throws URISyntaxException {
    this(Env.class.getResource("/sonar.properties"));
  }
  
  File rootDir() {
    return this.confFile.getParentFile().getParentFile();
  }

Attention, le fichier sera disponible à l'aide de lien. Mais au niveau Java, l'emplacement retourné sera celui du fichier et non celui accédé depuis un lien. Cela joue un rôle important dans l'exécution, car la valeur de SONAR_HOME sera finalement /var/opt/sonarqube/common et non pas /var/opt/sonarqube/4.4 ou /var/opt/sonarqube/installed.


User-icon.png Compte de service

Cette installation ayant pour but d'être exécutée sous la forme d'un service, le compte root va être employé et ce n'est pas très sécurisé. Or il est possible de spécifier un compte utilisateur dans le script de démarrage de l'application. A l'instar d'application comme Tomcat, un compte technique est mis en place et sera exploité.

Attention le bash /bin/false est généralement utilisé pour les comptes de service. Du fait de l'implémentation du script de démarrage, il est nécessaire que le bash associé au compte soit un "vrai" bash, dans ce cas /bin/bash.

Le compte de service ne nécessite aucun répertoire home, et un groupe de même nom est créé.

#sudo adduser --shell /bin/bash  --system --no-create-home --group sonar
Ajout de l'utilisateur système « sonar » (UID 115) ...
Ajout du nouveau groupe « sonar » (GID 127) ...
Ajout du nouvel utilisateur « sonar » (UID 115) avec pour groupe d'appartenance « sonar » ...
Le répertoire personnel « /home/sonar » n'a pas été créé.


Download-icon.png System-Install-icon.png Téléchargement et installation

L'application est téléchargée en installée dans le répertoire /var/opt/sonarqube préalablement créé.

#sudo mkdir -p /var/opt/sonarqube/4.4
#sudo wget -O /tmp/sonarqube-4.4.zip http://downloads.sonarsource.com/sonarqube/sonarqube-4.4.zip
#sudo unzip /tmp/sonarqube-4.4.zip -d /var/opt/sonarqube/4.4
#sudo mv /var/opt/sonarqube/4.4/sonarqube-4.4/* /var/opt/sonarqube/4.4
#sudo rmdir /var/opt/sonarqube/4.4/sonarqube-4.4
#sudo chown -R sonar:sonar /var/opt/sonarqube
#sudo chmod -R go-rwx /var/opt/sonarqube

Les droits sont positionnés pour que seul le compte sonar puisse accéder aux fichiers.


Multiples-icon.png Gestion des versions

Le déploiement de nouvelles versions doit être le plus simple possible. Les scripts de service ne doivent pas contenir l'emplacement de l'instance, qui dans le cas de l'article contient le numéro de version, mais plutôt un lien générique qui sera modifié. Ce lien est créé sous /var/opt/sonarqube/installed.

#sudo ln -s /var/opt/sonarqube/4.4 /var/opt/sonarqube/installed
#sudo chown -h sonar:sonar /var/opt/sonarqube/installed


Share-icon.png Fichiers communs

Afin d'éviter la reprise des fichiers de paramétrages lors des montées de versions, les répetoires sont externalisés dans un répertoire /var/opt/sonarqube/commondans lequel l’arborescence standard est reproduite pour plus de clarté :

  • conf contient les fichiers de configuration;
  • data contient les données de l'application;
  • extensions/plugins contient les plugins installés;
  • temp contient les fichiers temporaires.

A noter que les emplacements du répertoire data et temp peuvent être configurés dans le fichier sonar.properties, préalablement déplacé sous /var/opt/sonarqube/common/conf. Mais afin d'éviter au maximum la modification des fichiers, et car cela peut évoluer au fil des versions, l'utilisation de liens est préférée dans le cadre de cette installation.

Dans un premier temps, les répertoires sont créés sous common avec recopie des fichiers de l'instance.

#sudo mkdir -p /var/opt/sonarqube/common/conf
#sudo mkdir -p /var/opt/sonarqube/common/data
#sudo mkdir -p /var/opt/sonarqube/common/extensions/plugins
#sudo mkdir -p /var/opt/sonarqube/common/temp
#sudo cp -p /var/opt/sonarqube/4.4/conf/* /var/opt/sonarqube/common/conf
#sudo cp -p /var/opt/sonarqube/4.4/data/* /var/opt/sonarqube/common/data
#sudo cp -p /var/opt/sonarqube/4.4/extensions/plugins/* /var/opt/sonarqube/common/extensions/plugins
#sudo cp -p /var/opt/sonarqube/4.4/temp/* /var/opt/sonarqube/common/temp
#sudo find /var/opt/sonarqube/common -type d -exec chmod 0700 {} \;
#sudo find /var/opt/sonarqube/common -type f -exec chmod 0600 {} \;
#sudo chown -R sonar:sonar /var/opt/sonarqube/common

A noter le mode de chargement de la variable SONAR_HOME explicité au début de cet article. Donc, l'exécution s'effectuera sous /var/opt/sonarquabe/common. Deux types de liens doivent être mis en place.

  • Depuis 4.4 vers common, afin de référencer les fichiers de paramétrages et plugins externalisés.
#sudo rm -rf /var/opt/sonarqube/4.4/conf
#sudo ln -s /var/opt/sonarqube/common/conf /var/opt/sonarqube/4.4/conf
#sudo chown -h sonar:sonar /var/opt/sonarqube/4.4/conf
#sudo rm -rf /var/opt/sonarqube/4.4/data
#sudo ln -s /var/opt/sonarqube/common/data /var/opt/sonarqube/4.4/data
#sudo chown -h sonar:sonar /var/opt/sonarqube/4.4/data
#sudo rm -rf /var/opt/sonarqube/4.4/extensions/plugins
#sudo ln -s /var/opt/sonarqube/common/extensions/plugins /var/opt/sonarqube/4.4/extensions/plugins
#sudo chown -h sonar:sonar /var/opt/sonarqube/4.4/extensions/plugins
#sudo rm -rf /var/opt/sonarqube/4.4/temp
#sudo ln -s /var/opt/sonarqube/common/temp /var/opt/sonarqube/4.4/temp
#sudo chown -h sonar:sonar /var/opt/sonarqube/4.4/temp
#sudo chown -R sonar:sonar /var/opt/sonarqube/common
  • Depuis common vers installed, afin d'avoir les librairies et autres fichiers de la distribution installée. En pointant sur installed, les liens ne seront pas à créer de nouveau lors de montée de version.
#sudo ln -s /var/opt/sonarqube/installed/lib /var/opt/sonarqube/common/lib
#sudo chown -h sonar:sonar /var/opt/sonarqube/common/lib
#sudo ln -s /var/opt/sonarqube/installed/web /var/opt/sonarqube/common/web
#sudo chown -h sonar:sonar /var/opt/sonarqube/common/web
#sudo ln -s /var/opt/sonarqube/installed/extensions/jdbc-driver /var/opt/sonarqube/common/extensions/jdbc-driver
#sudo chown -h sonar:sonar /var/opt/sonarqube/common/extensions/jdbc-driver


Le contenu de l'instance est alors le suivant :

#sudo  ll /var/opt/sonarqube/4.4
total 36
drwxr-xr-x  7 sonar sonar 4096 sept.  9 16:37 ./
drwxr-xr-x  4 sonar sonar 4096 sept.  9 16:34 ../
drwxr-xr-x 12 sonar sonar 4096 juil. 31  2014 bin/
lrwxrwxrwx  1 sonar sonar   30 sept.  9 16:36 conf -> /var/opt/sonarqube/common/conf/
-rw-r--r--  1 sonar sonar 7651 juin   2  2014 COPYING
lrwxrwxrwx  1 sonar sonar   30 sept.  9 16:36 data -> /var/opt/sonarqube/common/data/
drwxr-xr-x  3 sonar sonar 4096 sept.  9 16:36 extensions/
drwxr-xr-x  5 sonar sonar 4096 juil. 31  2014 lib/
drwxr-xr-x  2 sonar sonar 4096 juil. 31  2014 logs/
lrwxrwxrwx  1 sonar sonar   30 sept.  9 16:37 temp -> /var/opt/sonarqube/common/temp/
drwxr-xr-x 10 sonar sonar 4096 juil. 31  2014 web/

#sudo ll /var/opt/sonarqube/4.4/extensions/
total 12
drwxr-xr-x 3 sonar sonar 4096 sept.  9 16:36 ./
drwxr-xr-x 7 sonar sonar 4096 sept.  9 16:37 ../
drwxr-xr-x 6 sonar sonar 4096 juil. 31  2014 jdbc-driver/
lrwxrwxrwx 1 sonar sonar   44 sept.  9 16:36 plugins -> /var/opt/sonarqube/common/extensions/plugins/

Le contenu de la partie common est :

#sudo  ll /var/opt/sonarqube/common
total 36
drwx------  7 sonar sonar 4096 sept.  9 16:37 ./
drwxr-xr-x  4 sonar sonar 4096 sept.  9 16:34 ../
drwx------  1 sonar sonar   30 sept.  9 16:36 conf/
drwx------  1 sonar sonar   30 sept.  9 16:36 data/
drwx------  3 sonar sonar 4096 sept.  9 16:36 extensions/
lrwxrwxrwx  5 sonar sonar 4096 sept.  9  2014 lib/ -> /var/opt/sonarqube/installed/lib/
drwx------  1 sonar sonar   30 sept.  9 16:37 temp/
lrwxrwxrwx  5 sonar sonar 4096 sept.  9  2014 web/ -> /var/opt/sonarqube/installed/web/

#sudo ll /var/opt/sonarqube/common/extensions/
total 12
drwxr-xr-x 3 sonar sonar 4096 sept.  9 16:36 ./
drwxr-xr-x 7 sonar sonar 4096 sept.  9 16:37 ../
lrwxrwxrwx 6 sonar sonar 4096 juil. 31  2014 jdbc-driver/ -> /var/opt/sonarqube/common/extensions/jdbc-driver/
drwx------ 1 sonar sonar   44 sept.  9 16:36 plugins


Le lien pour web est important. En cas d'absence, l'application n'est pas trouvé lors du déploiement dans le Tomcat embarqué et l'erreur suivante est affichée dans la trace d'exécution.

java.io.FileNotFoundException: /var/opt/sonarqube/common/web/META-INF/context.xml (Aucun fichier ou dossier de ce type)
        at java.io.FileInputStream.open(Native Method) ~[na:1.7.0_72]
        at java.io.FileInputStream.<init>(FileInputStream.java:146) ~[na:1.7.0_72]
        at java.io.FileInputStream.<init>(FileInputStream.java:101) ~[na:1.7.0_72]
        at sun.net.www.protocol.file.FileURLConnection.connect(FileURLConnection.java:90) ~[na:1.7.0_72]
        at sun.net.www.protocol.file.FileURLConnection.getInputStream(FileURLConnection.java:188) ~[na:1.7.0_72]
        at org.apache.catalina.startup.ContextConfig.processContextConfig(ContextConfig.java:620) [tomcat-embed-core-7.0.42.jar:7.0.42]
        at org.apache.catalina.startup.ContextConfig.contextConfig(ContextConfig.java:599) [tomcat-embed-core-7.0.42.jar:7.0.42]
        at org.apache.catalina.startup.ContextConfig.init(ContextConfig.java:837) [tomcat-embed-core-7.0.42.jar:7.0.42]
        at org.apache.catalina.startup.ContextConfig.lifecycleEvent(ContextConfig.java:387) [tomcat-embed-core-7.0.42.jar:7.0.42]
        at org.apache.catalina.util.LifecycleSupport.fireLifecycleEvent(LifecycleSupport.java:119) [tomcat-embed-core-7.0.42.jar:7.0.42]
        at org.apache.catalina.util.LifecycleBase.fireLifecycleEvent(LifecycleBase.java:90) [tomcat-embed-core-7.0.42.jar:7.0.42]
        at org.apache.catalina.util.LifecycleBase.setStateInternal(LifecycleBase.java:402) [tomcat-embed-core-7.0.42.jar:7.0.42]
        at org.apache.catalina.util.LifecycleBase.init(LifecycleBase.java:110) [tomcat-embed-core-7.0.42.jar:7.0.42]
        at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:139) [tomcat-embed-core-7.0.42.jar:7.0.42]
        at org.apache.catalina.core.ContainerBase$StartChild.call(ContainerBase.java:1559) [tomcat-embed-core-7.0.42.jar:7.0.42]
        at org.apache.catalina.core.ContainerBase$StartChild.call(ContainerBase.java:1549) [tomcat-embed-core-7.0.42.jar:7.0.42]
        at java.util.concurrent.FutureTask.run(FutureTask.java:262) [na:1.7.0_72]
        at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1145) [na:1.7.0_72]
        at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:615) [na:1.7.0_72]
        at java.lang.Thread.run(Thread.java:745) [na:1.7.0_72]
2015.09.09 17:00:03 ERROR [o.a.c.s.ContextConfig]  Parse error in context.xml for
java.io.FileNotFoundException: /var/opt/sonarqube/common/web/META-INF/context.xml (Aucun fichier ou dossier de ce type)
        at java.io.FileInputStream.open(Native Method) ~[na:1.7.0_72]
        at java.io.FileInputStream.<init>(FileInputStream.java:146) ~[na:1.7.0_72]
        at java.io.FileInputStream.<init>(FileInputStream.java:101) ~[na:1.7.0_72]
        at sun.net.www.protocol.file.FileURLConnection.connect(FileURLConnection.java:90) ~[na:1.7.0_72]
        at sun.net.www.protocol.file.FileURLConnection.getInputStream(FileURLConnection.java:188) ~[na:1.7.0_72]
        at com.sun.org.apache.xerces.internal.impl.XMLEntityManager.setupCurrentEntity(XMLEntityManager.java:619) ~[na:1.7.0_72]
        at com.sun.org.apache.xerces.internal.impl.XMLVersionDetector.determineDocVersion(XMLVersionDetector.java:189) ~[na:1.7.0_72]
        at com.sun.org.apache.xerces.internal.parsers.XML11Configuration.parse(XML11Configuration.java:812) ~[na:1.7.0_72]
        at com.sun.org.apache.xerces.internal.parsers.XML11Configuration.parse(XML11Configuration.java:777) ~[na:1.7.0_72]
        at com.sun.org.apache.xerces.internal.parsers.XMLParser.parse(XMLParser.java:141) ~[na:1.7.0_72]
        at com.sun.org.apache.xerces.internal.parsers.AbstractSAXParser.parse(AbstractSAXParser.java:1213) ~[na:1.7.0_72]
        at com.sun.org.apache.xerces.internal.jaxp.SAXParserImpl$JAXPSAXParser.parse(SAXParserImpl.java:648) ~[na:1.7.0_72]
        at org.apache.tomcat.util.digester.Digester.parse(Digester.java:1537) ~[tomcat-embed-core-7.0.42.jar:7.0.42]
        at org.apache.catalina.startup.ContextConfig.processContextConfig(ContextConfig.java:637) [tomcat-embed-core-7.0.42.jar:7.0.42]
        at org.apache.catalina.startup.ContextConfig.contextConfig(ContextConfig.java:599) [tomcat-embed-core-7.0.42.jar:7.0.42]
        at org.apache.catalina.startup.ContextConfig.init(ContextConfig.java:837) [tomcat-embed-core-7.0.42.jar:7.0.42]
        at org.apache.catalina.startup.ContextConfig.lifecycleEvent(ContextConfig.java:387) [tomcat-embed-core-7.0.42.jar:7.0.42]
        at org.apache.catalina.util.LifecycleSupport.fireLifecycleEvent(LifecycleSupport.java:119) [tomcat-embed-core-7.0.42.jar:7.0.42]
        at org.apache.catalina.util.LifecycleBase.fireLifecycleEvent(LifecycleBase.java:90) [tomcat-embed-core-7.0.42.jar:7.0.42]
        at org.apache.catalina.util.LifecycleBase.setStateInternal(LifecycleBase.java:402) [tomcat-embed-core-7.0.42.jar:7.0.42]
        at org.apache.catalina.util.LifecycleBase.init(LifecycleBase.java:110) [tomcat-embed-core-7.0.42.jar:7.0.42]
        at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:139) [tomcat-embed-core-7.0.42.jar:7.0.42]
        at org.apache.catalina.core.ContainerBase$StartChild.call(ContainerBase.java:1559) [tomcat-embed-core-7.0.42.jar:7.0.42]
        at org.apache.catalina.core.ContainerBase$StartChild.call(ContainerBase.java:1549) [tomcat-embed-core-7.0.42.jar:7.0.42]
        at java.util.concurrent.FutureTask.run(FutureTask.java:262) [na:1.7.0_72]
        at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1145) [na:1.7.0_72]
        at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:615) [na:1.7.0_72]
        at java.lang.Thread.run(Thread.java:745) [na:1.7.0_72]
2015.09.09 17:00:03 ERROR [o.a.c.c.StandardContext]  Error starting static Resources
java.lang.IllegalArgumentException: Document base /var/opt/sonarqube/common/web does not exist or is not a readable directory
        at org.apache.naming.resources.FileDirContext.setDocBase(FileDirContext.java:138) ~[tomcat-embed-core-7.0.42.jar:7.0.42]
        at org.apache.catalina.core.StandardContext.resourcesStart(StandardContext.java:5055) [tomcat-embed-core-7.0.42.jar:7.0.42]
        at org.apache.catalina.core.StandardContext.startInternal(StandardContext.java:5235) [tomcat-embed-core-7.0.42.jar:7.0.42]
        at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:150) [tomcat-embed-core-7.0.42.jar:7.0.42]
        at org.apache.catalina.core.ContainerBase$StartChild.call(ContainerBase.java:1559) [tomcat-embed-core-7.0.42.jar:7.0.42]
        at org.apache.catalina.core.ContainerBase$StartChild.call(ContainerBase.java:1549) [tomcat-embed-core-7.0.42.jar:7.0.42]
        at java.util.concurrent.FutureTask.run(FutureTask.java:262) [na:1.7.0_72]
        at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1145) [na:1.7.0_72]
        at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:615) [na:1.7.0_72]
        at java.lang.Thread.run(Thread.java:745) [na:1.7.0_72]


De même le lien vers les drivers est nécessaire. Lors de la mise en place de cette version, une mise à jour de la base de donnée est nécessaire. Une partie des scripts peut s'exécuter correctement, puis tomber en erreur avec le message d'erreur suivant.

2015.09.09 18:02:17 INFO  [o.s.s.s.RegisterDebtModel]  Register technical debt model...
2015.09.09 18:02:17 INFO  [o.s.s.s.RegisterDebtModel]  Register technical debt model done: 11 ms
2015.09.09 18:02:17 INFO  [org.sonar.INFO]  Register rules...
2015.09.09 18:02:24 INFO  [org.sonar.INFO]  Register rules done: 6737 ms
2015.09.09 18:02:24 INFO  [o.s.s.q.RegisterQualityProfiles]  Register Quality Profiles...
2015.09.09 18:02:28 INFO  [o.s.s.q.RegisterQualityProfiles]  Register Quality Profiles done: 4266 ms
2015.09.09 18:02:28 ERROR [o.s.s.ui.JRubyFacade]  Fail to upgrade database
No JDBC driver found in /var/opt/sonarqube/common/extensions/jdbc-driver/mysql
        org.sonar.server.platform.DefaultServerFileSystem.getJdbcDriver(DefaultServerFileSystem.java:150)


Run-icon.png Script démarrage

Les modifications dans le script de démarrage, fichier /var/opt/sonarqube/4.4/bin/linux-x86-64/sonar.sh, doivent permettre :

  • Spécifier l'utilisateur d'exécution;
  • Spécifier un emplacement spécifique pour le fichier "PID".

A noter que lors de l'exécution, si un compte est spécifié et différent de celui en cours d'exécution, le script de démarrage est redémarré avec le compte souhaité.

# If specified, the Wrapper will be run as the specified user.
# IMPORTANT - Make sure that the user has the required privileges to write
#  the PID file and wrapper.log files.  Failure to be able to write the log
#  file will cause the Wrapper to exit without any way to write out an error
#  message.
# NOTE - This will set the user which is used to run the Wrapper as well as
#  the JVM and is not useful in situations where a privileged resource or
#  port needs to be allocated prior to the user being changed.
#RUN_AS_USER=
RUN_AS_USER=sonar

Et

# Location of the pid file.
#PIDDIR="."
PIDDIR="/run/sonarqube"

Cependant, le répertoire /run/sonarqube n'existe pas et le compte sonar n'a pas les droits d'écriture dans /run. Une erreur se produira donc lors de l'exécution, car le fichier "PID" ne pourra être créé. Le script de démarrage /var/opt/sonarqube/4.4/bin/linux-x86-64/sonar.sh est donc modifié afin de forcer la création du répertoire. Pour rappel, comme il est exécuté avec le compte root du fait du service, il est tout à fait possible de créer le répertoire et de modifier les droits d'accès.

Au final, le script est modifié ainsi :

# Location of the pid file.
#PIDDIR="."
PIDDIR="/run/sonarqube"

# If uncommented, causes the Wrapper to be shutdown using an anchor file.
#  When launched with the 'start' command, it will also ignore all INT and
#  TERM signals.
#IGNORE_SIGNALS=true

# If specified, the Wrapper will be run as the specified user.
# IMPORTANT - Make sure that the user has the required privileges to write
#  the PID file and wrapper.log files.  Failure to be able to write the log
#  file will cause the Wrapper to exit without any way to write out an error
#  message.
# NOTE - This will set the user which is used to run the Wrapper as well as
#  the JVM and is not useful in situations where a privileged resource or
#  port needs to be allocated prior to the user being changed.
#RUN_AS_USER=
RUN_AS_USER=sonar
if [ ! -d "$PIDDIR" ]; then
        mkdir -p "$PIDDIR"
        [ -z "$RUN_AS_USER" ] || chown "$RUN_AS_USER:$RUN_AS_USER" "$PIDDIR"
fi


Icon-log.png Fichiers log

Par défaut, les logs sont placés dans le répertoire logs de l’instance SonarQube :

  • /var/opt/sonarqube/4.4/logs/sonar.log
  • /var/opt/sonarqube/4.4/logs/access.log

La définition de ces emplacements se situe dans différentes configurations.

  • Fichier conf/wrapper.conf les écritures du wrapper dans les fichiers sonar.log
# Log file to use for wrapper output logging.
wrapper.logfile=../../logs/sonar.log
  • Fichier conf/sonar.properties pour sonar.log et access.log
# Access logs are generated in the file logs/access.log. This file is rolled over when it's 5Mb.
# An archive of 3 files is kept in the same directory.
# Access logs are enabled by default.
#sonar.web.accessLogs.enable=true


Afin de centraliser les logs, les messages sont redirigés vers /var/log/sonarqube en mettant en place des liens symboliques. Ceci permet de ne pas modifier les fichiers de configurations, limitant les modifications lors des futures montées de version. Le répertoire /var/opt/sonarqube/4.4/logs existe déjà et sera supprimé. Du fait de cette organisation, utilisation d'un répertoire common, un répertoire /var/opt/sonarqube/common/logs sera créé lors du démarrage. Pour ce dernier, le lien est préalablement créé.

#sudo mkdir -p /var/log/sonarqube
#sudo chown sonar:adm /var/log/sonarqube
#sudo chmod 770 /var/log/sonarqube
#sudo rmdir /var/opt/sonarqube/4.4/logs
#sudo ln -s /var/log/sonarqube /var/opt/sonarqube/4.4/logs
#sudo ln -s /var/log/sonarqube /var/opt/sonarqube/common/logs
#sudo chown -h sonar:sonar /var/opt/sonarqube/4.4/logs
#sudo chown -h sonar:sonar /var/opt/sonarqube/common/logs


Icon-Configuration-Settings.png Paramétrages

Les fichiers de paramétrages ont été déplacés dans le répertoire /var/opt/sonarqube/common/conf afin de faciliter les montées de version. Ils ont très certainement écrit sur un environnement Windows, et dans le cadre d'une installation sous Linux, il est préférable de "formater" les fichiers avec l'utilitaire fromdos.

#sudo fromdos -p /var/opt/sonarqube/common/conf/*

Icon-database.png Base de données

La configuration MySql a été réalisée depuis les premières versions. Elle pourrait être reprise, mais le format du fichier sonar.properties a été légèrement modifié. De plus, des éléments de paramétrages ont été supprimés.

Un exemple est fourni dans le fichier et il suffit de commenter le paramètre actif, sur une base H2, et d'activer celui pour MySql. Il faut également configurer le compte d'accès à la base en reseignant les paramètres sonar.jdbc.username et sonar.jdbc.password

# Permissions to create tables, indices and triggers must be granted to JDBC user.
# The schema must be created first.
sonar.jdbc.username=sonar
sonar.jdbc.password=sonar

#----- Embedded database H2
# Note: it does not accept connections from remote hosts, so the
# SonarQube server and the maven plugin must be executed on the same host.

# Comment the following line to deactivate the default embedded database.
#sonar.jdbc.url=jdbc:h2:tcp://localhost:9092/sonar

# directory containing H2 database files. By default it's the /data directory in the SonarQube installation.
#sonar.embeddedDatabase.dataDir=
# H2 embedded database server listening port, defaults to 9092
#sonar.embeddedDatabase.port=9092


#----- MySQL 5.x
# Comment the embedded database and uncomment the following line to use MySQL
#sonar.jdbc.url=jdbc:mysql://localhost:3306/sonar?useUnicode=true&characterEncoding=utf8&rewriteBatchedStatements=true
sonar.jdbc.url=jdbc:mysql://localhost:3306/sonar?useUnicode=true&characterEncoding=utf8&rewriteBatchedStatements=true

User-group-icon.png Annuaire LDAP

La configuration LDAP a été mise en place depuis la version 1.1 du plugin, sans être modifiée. Lors de cette mise à jour, celle-ci est reprise pour être épurée. Les lignes suivantes sont ajoutées au fichier de configuration /var/opt/sonarqube/common/conf/sonar.properties.

#--------------------------------------------------------------------------------------------------
# LDAP Configuration
# General Configuration
sonar.security.realm=LDAP
ldap.url=ldap://localhost:389

# User Configuration
ldap.user.baseDn=ou=people,dc=ejnserver,dc=fr
ldap.user.request=(uid={login})
ldap.user.realNameAttribute=cn
ldap.user.emailAttribute=mail

# Group Configuration
ldap.group.baseDn=ou=groups,dc=ejnserver,dc=fr
ldap.group.request=(&(objectClass=groupOfNames)(member={dn}))

Run-icon.png Exécution

A ce stade, l'instance est déployée et paramétrée. Son exécution semble se dérouler correctement.

#sudo /var/opt/sonarqube/4.4/bin/linux-x86-64/sonar.sh start
Starting SonarQube...
Started SonarQube.


Update icon.png Montées de version

Folder-icon.png Fichiers

Cette installation fait l'objet d'une mise à jour par rapport à la version 4.3.3. Des plugins avaient été mis à jour, ainsi que des données déjà existantes. Ces opérations de migrations ne sont pas nécessaires dans le cadre d'une installation initiale.

#sudo cp -p -R /var/opt/sonar/data/* /var/opt/sonarqube/common/data
#sudo cp -p -R /var/opt/sonar/temp/* /var/opt/sonarqube/common/temp
#sudo cp -p /var/opt/sonar/extensions/plugins/*.jar /var/opt/sonarqube/common/extensions/plugins
#sudo chown -R sonar:sonar /var/opt/sonarqube/common/data/*
#sudo chown -R sonar:sonar /var/opt/sonarqube/common/temp/*
#sudo chown -R sonar:sonar /var/opt/sonarqube/common/extensions/plugins/*
#sudo find /var/opt/sonarqube/common/data -type d -exec chmod 0700 {} \;
#sudo find /var/opt/sonarqube/common/data -type f -exec chmod 0600 {} \;
#sudo find /var/opt/sonarqube/common/temp -type d -exec chmod 0700 {} \;
#sudo find /var/opt/sonarqube/common/temp -type f -exec chmod 0600 {} \;
#sudo chmod 600 /var/opt/sonarqube/common/extensions/plugins/*.jar

Run-icon.png Variable d'environnement Tomcat

Lors de l'installation de la version 4.0 sous Tomcat, la variabel d'environnement SONAR_HOME avait été mise en place dans le script de démarrage de Tomcat. Celle-ci devient obsolète et peut être supprimée. Pour mémoire, elle avait été placée dans le script script /var/lib/tomcat7/bin/setenv.sh.

Icon-database-process.png Mise à jour de la base

Pour cette version, une mise à jour de la base de données est nécessaire.Celle-ci se déclenche en accédant à l'URL http://SERVER/sonar/setup.

Delete-file-icon.png Suppression anciens fichiers

Les précédentes installations étaient réalisées par un déploiement sous Tomcat, en spécifiant la valeur /var/opt/sonar dans la variable d'environnement SONAR_HOME. L'ancienne instance et l'espace de travail peuvent être supprimés suite à cette nouvelle organisation.

#sudo rm -rf /var/lib/tomcat7/webapps/sonar
#sudo rm -rf /var/opt/sonar
#sudo rm -rf /var/log/sonar


Configuration App Web-Icon.png Publication Apache

Les précédentes versions étaient déployées sur un serveur Tomcat et mis à disposition sous Apache. Or, l'instance étant déployée dans son propre serveur d'application, le numéro des port est spécifique, et historiquement placé à 9000. Dans le cadre de cette installation, l'instance est disponible sur cette machine avec la configuration Apache suivante.

        ProxyPass /sonar http://localhost:8080/sonar
        ProxyPassReverse /sonar http://localhost:8080/sonar
        <Proxy http://localhost:8080/sonar>
                Order allow,deny
                Allow from all
        </Proxy>

Or avec cette nouvelle installation, l'instance est à présente indépendante et la configuration Apache devient :

        ProxyPass /sonar http://localhost:9000/sonar
        ProxyPassReverse /sonar http://localhost:9000/sonar
        <Proxy http://localhost:9000/sonar>
                Order allow,deny
                Allow from all
        </Proxy>

Attention, l'URL est bien modifié en :9000/sonar, sinon des problèmes de redirection se produise. Il faut donc spécifier à l'instance qu'il y a un contexte de déploiement, soit sonar, à mettre en place en modifiant le paramètre sonar.web.context dans le fichier /var/opt/sonarqube/common/conf/sonar.properties.

#--------------------------------------------------------------------------------------------------
# WEB SERVER

# Binding IP address. For servers with more than one IP address, this property specifies which
# address will be used for listening on the specified ports.
# By default, ports will be used on all IP addresses associated with the server.
#sonar.web.host=0.0.0.0

# Web context. When set, it must start with forward slash (for example /sonarqube).
# The default value is root context (empty value).
#sonar.web.context=
sonar.web.context=/sonar

Attention à ne pas oublier le caractère / au début du contexte.


Bug-icon.png Erreurs

Cet article présente la mise en place de la version 4.4 en essayant de prévoir les montées de versions, mais également la reprise depuis la version pécédente 4.3.3. Lors de l'utilisation, l'affichage des profiles de qualité provoque l'erreur suivante :

2015.09.10 00:02:37 ERROR [o.s.s.w.WebServiceEngine]  Fail to process request org.sonar.server.ws.ServletRequest@1c479dd6
org.elasticsearch.action.search.SearchPhaseExecutionException: Failed to execute phase [query_fetch], all shards failed; shardFailures {[sq1L6xUeTeupTolqe9zzdA][rules][0]: 
SearchParseException[[rules][0]: from[-1],size[2147483647]: Parse Failure [Failed to parse source [{"size":2147483647,"query":{"has_parent":{"query":{"ids":{"type":"rules","values":
["findbugs:NP_OPTIONAL_RETURN_NULL"]}},"parent_type":"rules"}}}]]]; nested: NullPointerException; }
        at org.elasticsearch.action.search.type.TransportSearchTypeAction$BaseAsyncAction.onFirstPhaseResult(TransportSearchTypeAction.java:276) ~[elasticsearch-1.1.2.jar:na]
        at org.elasticsearch.action.search.type.TransportSearchTypeAction$BaseAsyncAction$3.onFailure(TransportSearchTypeAction.java:222) ~[elasticsearch-1.1.2.jar:na]
        at org.elasticsearch.search.action.SearchServiceTransportAction.sendExecuteFetch(SearchServiceTransportAction.java:307) ~[elasticsearch-1.1.2.jar:na]
        at org.elasticsearch.action.search.type.TransportSearchQueryAndFetchAction$AsyncAction.sendExecuteFirstPhase(TransportSearchQueryAndFetchAction.java:71) 
~[elasticsearch-1.1.2.jar:na]
        at org.elasticsearch.action.search.type.TransportSearchTypeAction$BaseAsyncAction.performFirstPhase(TransportSearchTypeAction.java:214) ~[elasticsearch-1.1.2.jar:na]
        at org.elasticsearch.action.search.type.TransportSearchTypeAction$BaseAsyncAction$2.run(TransportSearchTypeAction.java:188) ~[elasticsearch-1.1.2.jar:na]
        at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1145) ~[na:1.7.0_72]
        at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:615) ~[na:1.7.0_72]
        at java.lang.Thread.run(Thread.java:745) ~[na:1.7.0_72]

Il se trouve que les données propres à ElasticSearch étaient corrompues ou incompatibles avec cette version. Il suffit de purger le répertoire data/es.

#sudo rm -rf /var/opt/sonarqube/common/data/es


Start-icon.png Installation service

Historiquement, les services Linux sont déclarés dans le répertoire /etc/init.d. Ce système est progressivement remplacé par l’outil systemd qui utilise un autre système de configuration. Cependant, systemd est capable de générer sa propre configuration depuis les scripts dans /etc/init.d.

Le fichier /etc/init.d/sonarqube est créé pour référencer SonarQube en tant que service, avec le contenu suivant :

#!/bin/sh
#
# rc file for SonarQube
#
# chkconfig: 345 96 10
# description: SonarQube system (www.sonarsource.org)
#
### BEGIN INIT INFO
# Provides: sonarqube
# Required-Start: $network mysql
# Required-Stop: $network
# Default-Start: 3 4 5
# Default-Stop: 0 1 2 6
# Short-Description: SonarQube
# Description: SonarQube system (www.sonarsource.org)
### END INIT INFO

/var/opt/sonarqube/installed/bin/linux-x86-64/sonar.sh $*

exit $?

A noter que le service est déclaré comme dépendant du service MySql.

Le fichier doit être exécutable.

#sudo chmod 755 /etc/init.d/sonarqube

Le service est installé avec les paramètres par défaut.

#sudo update-rc.d sonarqube defaults

L’utilisation de systemd nécessite de recharger les configurations générées.

#sudo systemctl daemon-reload


Strategy-icon.png Stratégie de Backup

La stratégie de backup est revue afin de prendre en compte la nouvelle organisation. Sur les précédentes versions, les répertoires et fichiers sauvegardés étaient les suivants:

  • /var/opt/sonar-*
  • /var/lib/tomcat7/webapps/sonar*
  • /var/opt/backups/sonar/db
  • /etc/apache2/httpd.conf

Ils sont à présents moins nombreux :

  • /var/opt/sonarqube
  • /var/opt/backups/sonar/db
  • /etc/apache2/httpd.conf

La mise en place de cette sauvegarde est explicitée ici.