Skip to content

Commit

Permalink
ccmlib/common.py: make java lookup logic more comprehensive
Browse files Browse the repository at this point in the history
Before this commit `make_cassandra_env` would only find java at
`/usr/lib/jvm/*` directory and could have misconstrue
`java-18-openjdk-amd64` as `java-8`.
This commit makes `make_cassandra_env` to look at any directory under `/usr/lib/jvm` and
to read version from java output
  • Loading branch information
dkropachev authored and fruch committed Sep 10, 2024
1 parent 102c03f commit d598d1c
Show file tree
Hide file tree
Showing 3 changed files with 124 additions and 11 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -13,3 +13,4 @@ tests/test_results
.direnv/

.envrc
ccmlib/tests/
41 changes: 30 additions & 11 deletions ccmlib/common.py
Original file line number Diff line number Diff line change
Expand Up @@ -389,23 +389,42 @@ def make_cassandra_env(install_dir, node_path, update_conf=True, hardcode_java_v

if hardcode_java_version:
known_jvm_names = {
'8': ('8-openjdk', '8-jdk', '1.8.0-openjdk'),
'11': ('11-openjdk', '11-jdk', '1.11.0-openjdk'),
'8': ['1.8', '8'],
'11': ['11']
}
assert hardcode_java_version in known_jvm_names.keys(), \
jvm_root_path = "/usr/lib/jvm/"
assert hardcode_java_version in known_jvm_names, \
f"hardcode_java_version={hardcode_java_version} not supported in:\n{known_jvm_names}"

for java_path in pathlib.Path('/usr/lib/jvm/').iterdir():
if (java_path.is_dir
and any(name in java_path.name for name in known_jvm_names[hardcode_java_version])
and list(java_path.rglob('java'))):
env['JAVA_HOME'] = str(java_path)
break
else:
raise ArgumentError(f"java-8 wasn't found in /usr/lib/jvm/\n {list(pathlib.Path('/usr/lib/jvm/').iterdir())}")
java_home_path = get_java_home_path(pathlib.Path(jvm_root_path), known_jvm_names[hardcode_java_version])
if java_home_path is None:
raise ArgumentError(f"java-{hardcode_java_version} wasn't found in {jvm_root_path}")

env['JAVA_HOME'] = str(java_home_path.as_posix())
return env

def get_java_home_path(parent_path: pathlib.Path, hardcode_java_version: List[str]) -> [pathlib.Path]:
for java in pathlib.Path(parent_path).rglob('*/bin/java'):
if get_jvm_spec_version(java) in hardcode_java_version:
return java.parent.parent
return None

java_version_property_regexp = re.compile(r'\s*java\.specification\.version\s*=\s*([0-9.]+)\s*')

def get_jvm_spec_version(java_bin_path: pathlib.Path) -> Optional[str]:
if not java_bin_path.is_file() or not os.access(java_bin_path, os.X_OK):
return None
try:
properties = subprocess.check_output([java_bin_path.as_posix(), '-XshowSettings:properties', '-version'], stderr=subprocess.STDOUT)
except subprocess.CalledProcessError as e:
return None

match = java_version_property_regexp.search(properties.decode('utf-8'))
if match is None:
return None
for version in match.groups():
return version
return None

def make_dse_env(install_dir, node_path):
env = os.environ.copy()
Expand Down
93 changes: 93 additions & 0 deletions ccmlib/test_common.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,93 @@
import os
import subprocess
import unittest

from ccmlib.common import java_version_property_regexp, get_java_home_path


class Test(unittest.TestCase):
java_19_output = """Property settings:
file.encoding = UTF-8
file.separator = /
java.class.path =
java.class.version = 63.0
java.home = /usr/lib/jvm/java-19-openjdk-amd64
java.io.tmpdir = /tmp
java.library.path = /usr/lib/x86_64-linux-gnu/jni/
/usr/java/packages/lib
/usr/lib/x86_64-linux-gnu/jni
/lib/x86_64-linux-gnu
/usr/lib/x86_64-linux-gnu
/usr/lib/jni
/lib
/usr/lib
java.runtime.name = OpenJDK Runtime Environment
java.runtime.version = 19.0.2+7-Ubuntu-0ubuntu322.04
java.specification.name = Java Platform API Specification
java.specification.vendor = Oracle Corporation
java.specification.version = 19
java.vendor = Private Build
java.vendor.url = Unknown
java.vendor.url.bug = Unknown
java.version = 19.0.2
java.version.date = 2023-01-17
java.vm.compressedOopsMode = Zero based
java.vm.info = mixed mode, sharing
java.vm.name = OpenJDK 64-Bit Server VM
java.vm.specification.name = Java Virtual Machine Specification
java.vm.specification.vendor = Oracle Corporation
java.vm.specification.version = 19
java.vm.vendor = Private Build
java.vm.version = 19.0.2+7-Ubuntu-0ubuntu322.04
jdk.debug = release
line.separator = \n
native.encoding = UTF-8
os.arch = amd64
os.name = Linux
os.version = 6.8.0-40-generic
path.separator = :
stderr.encoding = UTF-8
stdout.encoding = UTF-8
sun.arch.data.model = 64
sun.boot.library.path = /usr/lib/jvm/java-19-openjdk-amd64/lib
sun.cpu.endian = little
sun.io.unicode.encoding = UnicodeLittle
sun.java.launcher = SUN_STANDARD
sun.jnu.encoding = UTF-8
sun.management.compiler = HotSpot 64-Bit Tiered Compilers
user.country = US
user.dir = /extra/scylladb/scylla-ccm
user.home = /home/dmitry.kropachev
user.language = en
user.name = dmitry.kropachev
openjdk version "19.0.2" 2023-01-17
OpenJDK Runtime Environment (build 19.0.2+7-Ubuntu-0ubuntu322.04)
OpenJDK 64-Bit Server VM (build 19.0.2+7-Ubuntu-0ubuntu322.04, mixed mode, sharing)
(.venv) ➜ scylla-ccm git:(dk/fix-jvm-lookup-logic)
"""

def test_java_version_property_regexp(self):
match = java_version_property_regexp.search(self.java_19_output)
assert match is not None
assert len(match.groups()) == 1
assert match.groups()[0] == '19'

def test_get_java_home_path(self):
from unittest.mock import patch
from pathlib import Path
with (
patch.object(Path, 'exists') as mock_exists,
patch.object(Path, 'rglob') as rglob,
patch.object(Path, 'is_file') as is_file,
patch.object(subprocess, 'check_output') as check_output,
patch.object(os, 'access') as access
):
access.return_value = True
mock_exists.return_value = True
is_file.return_value = True
rglob.return_value = [Path('/usr/lib/jvm/java-8-openjdk-amd64/jre/bin/java')]
check_output.return_value = self.java_19_output.encode('utf-8')
assert get_java_home_path(Path("/usr/lib/jvm/"), ['19']) == Path('/usr/lib/jvm/java-8-openjdk-amd64/jre/')
assert get_java_home_path(Path("/usr/lib/jvm/"), ['8']) is None

0 comments on commit d598d1c

Please sign in to comment.