Alon Bar-Lev has uploaded a new change for review.

Change subject: packaging: detect java home at runtime
......................................................................

packaging: detect java home at runtime

CURRENT IMPLEMENTATION

detect java home during installation.

advantage is optimize application execution post-setup.

disadvantage is that java home may be altered by system updates.

NEW IMPLEMENTATION

detect java home during runtime using pre-defined algorithm.

algorithm:

execute /usr/share/ovirt-engine/bin/java-home.

if java-home.local is available, execute that script. this enables
distro specific customization.

if OVIRT_ENGINE_JAVA_HOME environment is set, validate java validity
and use/abort.

search predefined selected alternatives location by order, first wins.

search /usr/lib/jvm for compatible jvm.

NOTES

the java-home script resides with the lib package as it cannot reside
within any version locked package since it is used by setup, and it
cannot reside within setup since it used by post setup.

Bug-Url: https://bugzilla.redhat.com/show_bug.cgi?id=1009863
Change-Id: I833362d0498d534b06e0d7660f1e8a61e9b1713b
Signed-off-by: Alon Bar-Lev <alo...@redhat.com>
---
M .gitignore
M Makefile
M ovirt-engine.spec.in
M packaging/bin/engine-prolog.sh.in
A packaging/bin/java-home
A packaging/pythonlib/ovirt_engine/config.py.in
A packaging/pythonlib/ovirt_engine/java.py
M packaging/services/ovirt-engine-notifier/ovirt-engine-notifier.conf.in
M packaging/services/ovirt-engine-notifier/ovirt-engine-notifier.py
M packaging/services/ovirt-engine/ovirt-engine.conf.in
M packaging/services/ovirt-engine/ovirt-engine.py
M packaging/setup/ovirt_engine_setup/constants.py
M packaging/setup/plugins/ovirt-engine-setup/config/java.py
13 files changed, 172 insertions(+), 231 deletions(-)


  git pull ssh://gerrit.ovirt.org:29418/ovirt-engine refs/changes/16/19816/1

diff --git a/.gitignore b/.gitignore
index 6ebc961..93ab6ea 100644
--- a/.gitignore
+++ b/.gitignore
@@ -48,6 +48,7 @@
 packaging/etc/engine-manage-domains/log4j.xml
 packaging/etc/engine-manage-domains/engine-manage-domains.conf
 packaging/etc/notifier/log4j.xml
+packaging/pythonlib/ovirt_engine/config.py
 packaging/sys-etc/logrotate.d/ovirt-engine
 packaging/sys-etc/logrotate.d/ovirt-engine-notifier
 packaging/sys-etc/logrotate.d/ovirt-engine-setup
diff --git a/Makefile b/Makefile
index 47b0184..6e3c5e3 100644
--- a/Makefile
+++ b/Makefile
@@ -160,6 +160,7 @@
        packaging/sys-etc/logrotate.d/ovirt-engine \
        packaging/sys-etc/logrotate.d/ovirt-engine-notifier \
        packaging/sys-etc/logrotate.d/ovirt-engine-setup \
+       packaging/pythonlib/ovirt_engine/config.py \
        packaging/services/ovirt-engine-notifier/config.py \
        packaging/services/ovirt-engine-notifier/ovirt-engine-notifier.conf \
        packaging/services/ovirt-engine-notifier/ovirt-engine-notifier.systemd \
diff --git a/ovirt-engine.spec.in b/ovirt-engine.spec.in
index 3780d07..2a2cd96 100644
--- a/ovirt-engine.spec.in
+++ b/ovirt-engine.spec.in
@@ -719,6 +719,7 @@
 %endif
 
 %files lib
+%{engine_data}/bin/java-home
 %{python_sitelib}/ovirt_engine/
 
 %files backend
diff --git a/packaging/bin/engine-prolog.sh.in 
b/packaging/bin/engine-prolog.sh.in
index 1cc673f..e04e2e3 100644
--- a/packaging/bin/engine-prolog.sh.in
+++ b/packaging/bin/engine-prolog.sh.in
@@ -24,6 +24,8 @@
                [ -r "${f}" ] && . "${f}"
        done
 
+       export JAVA_HOME="$("${ENGINE_USR}/bin/java-home")" || die "Cannot set 
JAVA_HOME"
+
        # we use jboss specific loader (jboss-modules.jar)
        # setup module path
        export JAVA_MODULEPATH="${ENGINE_JAVA_MODULEPATH}:${JBOSS_HOME}/modules"
diff --git a/packaging/bin/java-home b/packaging/bin/java-home
new file mode 100755
index 0000000..8eded3f
--- /dev/null
+++ b/packaging/bin/java-home
@@ -0,0 +1,68 @@
+#!/bin/sh
+
+#
+# execute site local script if available
+#
+if [ -x "$0.local" ]; then
+       exec "$0.local"
+       exit 1
+fi
+
+validjre() {
+       local dir="$1"
+       local ret=1
+
+       if [ -x "${dir}/bin/java" ]; then
+               local version="$("${dir}/bin/java" -version 2>&1 | sed -e 
's/^java version "1\.7\.0.*/VERSION_OK/' -e 's/^OpenJDK .*(.*).*/VENDOR_OK/')"
+               if echo "${version}" | grep -q "VERSION_OK" && echo 
"${version}" | grep -q "${VENDOR_OK}"; then
+                       ret=0
+               fi
+       fi
+
+       return ${ret}
+}
+
+#
+# If system environment contains
+# our specific java look only this one
+#
+if [ -n "${OVIRT_ENGINE_JAVA_HOME}" ]; then
+       if validjre "${OVIRT_ENGINE_JAVA_HOME}"; then
+               echo "${OVIRT_ENGINE_JAVA_HOME}"
+               exit 0
+       else
+               exit 1
+       fi
+fi
+
+#
+# select alternates folder
+# if we find, first wins
+#
+for dir in /usr/lib/jvm/jre /usr/lib/jvm/jre-1.7.0 
/usr/lib/jvm/jre-1.7.0_openjdk;  do
+       if validjre "${dir}"; then
+               echo "${dir}"
+               exit 0
+       fi
+done
+
+#
+# select from jvm folder
+# last which is not jdk wins
+# jre is preferred as it usually more stable
+#
+JAVA_HOME=""
+for dir in /usr/lib/jvm/*; do
+       if validjre "${dir}"; then
+               if [ -x "${dir}/bin/javac" ]; then
+                       [ -z "${JAVA_HOME}" ] && JAVA_HOME="${dir}"
+               else
+                       JAVA_HOME="${dir}"
+               fi
+       fi
+done
+
+[ -z "${JAVA_HOME}" ] && exit 1
+
+echo "${JAVA_HOME}"
+exit 0
diff --git a/packaging/pythonlib/ovirt_engine/config.py.in 
b/packaging/pythonlib/ovirt_engine/config.py.in
new file mode 100644
index 0000000..60a855d
--- /dev/null
+++ b/packaging/pythonlib/ovirt_engine/config.py.in
@@ -0,0 +1,19 @@
+# Copyright 2012 Red Hat
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+
+ENGINE_USR = '@ENGINE_USR@'
+
+
+# vim: expandtab tabstop=4 shiftwidth=4
diff --git a/packaging/pythonlib/ovirt_engine/java.py 
b/packaging/pythonlib/ovirt_engine/java.py
new file mode 100644
index 0000000..e675b83
--- /dev/null
+++ b/packaging/pythonlib/ovirt_engine/java.py
@@ -0,0 +1,56 @@
+#
+# Copyright 2013 Red Hat
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+
+
+import os
+import subprocess
+import gettext
+_ = lambda m: gettext.dgettext(message=m, domain='ovirt-engine')
+
+
+from . import base
+from . import config
+
+
+class Java(base.Base):
+
+    def __init__(self):
+        super(Java, self).__init__()
+
+    def getJavaHome(self):
+        p = subprocess.Popen(
+            args=(
+                os.path.join(
+                    config.ENGINE_USR,
+                    'bin',
+                    'java-home',
+                ),
+            ),
+            stdout=subprocess.PIPE,
+            stderr=subprocess.PIPE,
+            close_fds=True,
+        )
+        stdout, stderr = p.communicate()
+        stdout = stdout.decode('utf-8', 'replace').splitlines()
+        stderr = stderr.decode('utf-8', 'replace').splitlines()
+        if p.returncode != 0:
+            raise RuntimeError(_('Cannot get JAVA_HOME (%s)') % stderr)
+        javaHome = stdout[0]
+        self.logger.debug('JAVA_HOME: %s', javaHome)
+        return javaHome
+
+
+# vim: expandtab tabstop=4 shiftwidth=4
diff --git 
a/packaging/services/ovirt-engine-notifier/ovirt-engine-notifier.conf.in 
b/packaging/services/ovirt-engine-notifier/ovirt-engine-notifier.conf.in
index d7a586f..9a89471 100644
--- a/packaging/services/ovirt-engine-notifier/ovirt-engine-notifier.conf.in
+++ b/packaging/services/ovirt-engine-notifier/ovirt-engine-notifier.conf.in
@@ -4,11 +4,6 @@
 #
 
 #
-# The location of the Java virtual machine used by the engine:
-#
-JAVA_HOME=/usr/lib/jvm/jre-1.7.0-openjdk.x86_64
-
-#
 # The location of the application server used by the engine:
 #
 JBOSS_HOME="@JBOSS_HOME@"
diff --git a/packaging/services/ovirt-engine-notifier/ovirt-engine-notifier.py 
b/packaging/services/ovirt-engine-notifier/ovirt-engine-notifier.py
index 0c77860..fa8bbd7 100755
--- a/packaging/services/ovirt-engine-notifier/ovirt-engine-notifier.py
+++ b/packaging/services/ovirt-engine-notifier/ovirt-engine-notifier.py
@@ -26,6 +26,7 @@
 
 from ovirt_engine import configfile
 from ovirt_engine import service
+from ovirt_engine import java
 
 
 class Daemon(service.Daemon):
@@ -43,19 +44,7 @@
         self,
         pidfile,
         jbossModulesJar,
-        java,
     ):
-        # Check that the Java home directory exists and that it contais at
-        # least the java executable:
-        self.check(
-            name=self._config.get('JAVA_HOME'),
-            directory=True,
-        )
-        self.check(
-            name=java,
-            executable=True,
-        )
-
         # Check the required JBoss directories and files:
         self.check(
             name=self._config.get('JBOSS_HOME'),
@@ -122,23 +111,24 @@
             ),
         )
 
+        #
+        # the earliest so we can abort early.
+        #
+        self._executable = os.path.join(
+            java.Java().getJavaHome(),
+            'bin',
+            'java',
+        )
+
         jbossModulesJar = os.path.join(
             self._config.get('JBOSS_HOME'),
             'jboss-modules.jar',
-        )
-        java = os.path.join(
-            self._config.get('JAVA_HOME'),
-            'bin',
-            'java',
         )
 
         self._checkInstallation(
             pidfile=self.pidfile,
             jbossModulesJar=jbossModulesJar,
-            java=java,
         )
-
-        self._executable = java
 
         self._engineArgs = [
             'ovirt-engine-notifier',
diff --git a/packaging/services/ovirt-engine/ovirt-engine.conf.in 
b/packaging/services/ovirt-engine/ovirt-engine.conf.in
index c4c1aa4..0efb275 100644
--- a/packaging/services/ovirt-engine/ovirt-engine.conf.in
+++ b/packaging/services/ovirt-engine/ovirt-engine.conf.in
@@ -13,11 +13,6 @@
 SENSITIVE_KEYS=""
 
 #
-# The location of the Java virtual machine used by the engine:
-#
-JAVA_HOME=/bin/false
-
-#
 # The location of the application server used by the engine:
 #
 JBOSS_HOME="@JBOSS_HOME@"
diff --git a/packaging/services/ovirt-engine/ovirt-engine.py 
b/packaging/services/ovirt-engine/ovirt-engine.py
index 08be3fd..8e53194 100755
--- a/packaging/services/ovirt-engine/ovirt-engine.py
+++ b/packaging/services/ovirt-engine/ovirt-engine.py
@@ -32,6 +32,7 @@
 
 from ovirt_engine import configfile
 from ovirt_engine import service
+from ovirt_engine import java
 
 
 class Daemon(service.Daemon):
@@ -102,19 +103,7 @@
         self,
         pidfile,
         jbossModulesJar,
-        java,
     ):
-        # Check that the Java home directory exists and that it contais at
-        # least the java executable:
-        self.check(
-            name=self._config.get('JAVA_HOME'),
-            directory=True,
-        )
-        self.check(
-            name=java,
-            executable=True,
-        )
-
         # Check the required JBoss directories and files:
         self.check(
             name=self._config.get('JBOSS_HOME'),
@@ -279,20 +268,23 @@
             ),
         )
 
+        #
+        # the earliest so we can abort early.
+        #
+        self._executable = os.path.join(
+            java.Java().getJavaHome(),
+            'bin',
+            'java',
+        )
+
         jbossModulesJar = os.path.join(
             self._config.get('JBOSS_HOME'),
             'jboss-modules.jar',
-        )
-        java = os.path.join(
-            self._config.get('JAVA_HOME'),
-            'bin',
-            'java',
         )
 
         self._checkInstallation(
             pidfile=self.pidfile,
             jbossModulesJar=jbossModulesJar,
-            java=java,
         )
 
         self._tempDir = service.TempDir(self._config.get('ENGINE_TMP'))
@@ -340,8 +332,6 @@
             dir=jbossConfigDir,
             mode=0o600,
         )
-
-        self._executable = java
 
         # We start with an empty list of arguments:
         self._engineArgs = []
diff --git a/packaging/setup/ovirt_engine_setup/constants.py 
b/packaging/setup/ovirt_engine_setup/constants.py
index be34553..50fb6cf 100644
--- a/packaging/setup/ovirt_engine_setup/constants.py
+++ b/packaging/setup/ovirt_engine_setup/constants.py
@@ -306,10 +306,6 @@
         OVIRT_ENGINE_SERVICE_CONFIGD,
         '10-setup-protocols.conf',
     )
-    OVIRT_ENGINE_SERVICE_CONFIG_JAVA = os.path.join(
-        OVIRT_ENGINE_SERVICE_CONFIGD,
-        '10-setup-java.conf',
-    )
     OVIRT_ENGINE_SERVICE_CONFIG_JBOSS = os.path.join(
         OVIRT_ENGINE_SERVICE_CONFIGD,
         '10-setup-jboss.conf',
@@ -329,10 +325,6 @@
 
     OVIRT_ENGINE_NOTIFIER_SERVICE_CONFIGD = (
         '%s.d' % OVIRT_ENGINE_NOTIFIER_SERVICE_CONFIG
-    )
-    OVIRT_ENGINE_NOTIFIER_SERVICE_CONFIG_JAVA = os.path.join(
-        OVIRT_ENGINE_NOTIFIER_SERVICE_CONFIGD,
-        '10-setup-java.conf',
     )
     OVIRT_ENGINE_NOTIFIER_SERVICE_CONFIG_JBOSS = os.path.join(
         OVIRT_ENGINE_NOTIFIER_SERVICE_CONFIGD,
diff --git a/packaging/setup/plugins/ovirt-engine-setup/config/java.py 
b/packaging/setup/plugins/ovirt-engine-setup/config/java.py
index bb4c591..9ad95ea 100644
--- a/packaging/setup/plugins/ovirt-engine-setup/config/java.py
+++ b/packaging/setup/plugins/ovirt-engine-setup/config/java.py
@@ -19,16 +19,15 @@
 """Java plugin."""
 
 
-import os
-import re
 import gettext
 _ = lambda m: gettext.dgettext(message=m, domain='ovirt-engine-setup')
 
 
-from otopi import constants as otopicons
 from otopi import util
-from otopi import filetransaction
 from otopi import plugin
+
+
+from ovirt_engine import java
 
 
 from ovirt_engine_setup import constants as osetupcons
@@ -38,131 +37,8 @@
 class Plugin(plugin.PluginBase):
     """Java plugin."""
 
-    JAVA_CONFIG_JVM = 'icedtea-7'
-    JAVA_VERSION = '1.7.0'
-
-    _RE_JAVA_VERSION = re.compile(
-        flags=re.VERBOSE | re.MULTILINE,
-        pattern=r"""
-            ^
-            java
-            \s
-            version
-            \s
-            "
-            (?P<version>[^"]*)
-            "
-            $
-        """,
-    )
-
-    _RE_JAVA_OPENJDK = re.compile(
-        flags=re.VERBOSE | re.MULTILINE,
-        pattern=r"""
-            ^
-            OpenJDK
-            \s
-            .*
-            $
-        """,
-    )
-
-    def _checkJvm(self, jvmPath):
-        self.logger.debug('Checking %s', jvmPath)
-
-        # Check that it contains the Java launcher:
-        javaLauncher = os.path.join(jvmPath, 'bin', 'java')
-        if not os.path.exists(javaLauncher):
-            self.logger.debug('does not has bin/java')
-            return False
-
-        # Check that Java launcher is executable:
-        if not os.access(javaLauncher, os.X_OK):
-            self.logger.debug('bin/java is not execuable')
-            return False
-
-        rc, stdout, stderr = self.execute(
-            (
-                javaLauncher,
-                '-version',
-            ),
-        )
-
-        # Extract version number:
-        match = self._RE_JAVA_VERSION.search('\n'.join(stderr))
-        if match is None:
-            self.logger.debug('Cannot determine java version')
-            return False
-        javaVersion = match.group('version')
-
-        self.logger.debug(
-            'Testing version %s against %s',
-            javaVersion,
-            self.JAVA_VERSION,
-        )
-        # Check that the version is supported:
-        if not javaVersion.startswith(self.JAVA_VERSION):
-            self.logger.debug('unsupported java version')
-            return False
-
-        # Check that it is an OpenJDK:
-        match = self._RE_JAVA_OPENJDK.search('\n'.join(stderr))
-        if match is None:
-            self.logger.debug('Not OpenJDK')
-            return False
-
-        # It passed all the checks, so it is valid JVM:
-        return True
-
-    def _checkJdk(self, jvmPath):
-        # We assume that this JVM path has already been checked and that it
-        # contains a valid JVM, so we only need to check that it also
-        # contains a Java compiler:
-        return os.path.exists(
-            os.path.join(jvmPath, 'bin', 'javac')
-        )
-
-    def _findJavaHome(self):
-        # Find links in the search directories that point to real things,
-        # not to other symlinks (this is to avoid links that point to things
-        # that can be changed by the user, specially "alternatives" managed
-        # links):
-        jvmLinks = []
-        for javaDir in ['/usr/lib/jvm']:
-            for fileName in os.listdir(javaDir):
-                filePath = os.path.join(javaDir, fileName)
-                if os.path.islink(filePath):
-                    if not os.path.islink(
-                        os.path.join(
-                            javaDir,
-                            os.readlink(filePath),
-                        )
-                    ):
-                        jvmLinks.append(filePath)
-
-        # For each possible JVM path check that it really contain a JVM and
-        # that the version is supported:
-        jvmLinks = [x for x in jvmLinks if self._checkJvm(x)]
-
-        # We prefer JRE over JDK, mainly because it is more stable, I mean,
-        # a JRE will be always present if there is a JDK, but not the other
-        # way around:
-        jreLinks = [x for x in jvmLinks if not self._checkJdk(x)]
-        if jreLinks:
-            jvmLinks = jreLinks
-
-        # Sort the list alphabetically (this is only to get a predictable
-        # result):
-        jvmLinks.sort()
-
-        if len(jvmLinks) == 0:
-            raise RuntimeError(_('Cannot detect java location'))
-
-        return jvmLinks[0]
-
     def __init__(self, context):
         super(Plugin, self).__init__(context=context)
-        self._enabled = False
 
     @plugin.event(
         stage=plugin.Stages.STAGE_INIT,
@@ -174,60 +50,15 @@
         )
 
     @plugin.event(
-        stage=plugin.Stages.STAGE_SETUP,
-    )
-    def _setup(self):
-        self.command.detect('java-config')
-
-    @plugin.event(
         stage=plugin.Stages.STAGE_VALIDATION,
         condition=lambda self: self.environment[
             osetupcons.ConfigEnv.JAVA_HOME
         ] is None,
     )
     def _validation(self):
-        if self.command.get(
-            'java-config',
-            optional=True
-        ) is not None:
-            rc, stdout, stderr = self.execute(
-                (
-                    self.command.get('java-config'),
-                    '--select-vm=%s' % self.JAVA_CONFIG_JVM,
-                    '--jre-home',
-                ),
-            )
-            javaHome = stdout[0]
-        else:
-            javaHome = self._findJavaHome()
-
         self.environment[
             osetupcons.ConfigEnv.JAVA_HOME
-        ] = javaHome
-
-    @plugin.event(
-        stage=plugin.Stages.STAGE_MISC,
-    )
-    def _misc(self):
-        for f in (
-            osetupcons.FileLocations.OVIRT_ENGINE_SERVICE_CONFIG_JAVA,
-            osetupcons.FileLocations.OVIRT_ENGINE_NOTIFIER_SERVICE_CONFIG_JAVA,
-        ):
-            self.environment[otopicons.CoreEnv.MAIN_TRANSACTION].append(
-                filetransaction.FileTransaction(
-                    name=f,
-                    content=(
-                        'JAVA_HOME="{javaHome}"\n'
-                    ).format(
-                        javaHome=self.environment[
-                            osetupcons.ConfigEnv.JAVA_HOME
-                        ],
-                    ),
-                    modifiedList=self.environment[
-                        otopicons.CoreEnv.MODIFIED_FILES
-                    ],
-                )
-            )
+        ] = java.Java().getJavaHome()
 
 
 # vim: expandtab tabstop=4 shiftwidth=4


-- 
To view, visit http://gerrit.ovirt.org/19816
To unsubscribe, visit http://gerrit.ovirt.org/settings

Gerrit-MessageType: newchange
Gerrit-Change-Id: I833362d0498d534b06e0d7660f1e8a61e9b1713b
Gerrit-PatchSet: 1
Gerrit-Project: ovirt-engine
Gerrit-Branch: master
Gerrit-Owner: Alon Bar-Lev <alo...@redhat.com>
_______________________________________________
Engine-patches mailing list
Engine-patches@ovirt.org
http://lists.ovirt.org/mailman/listinfo/engine-patches

Reply via email to