Skip to content

Commit

Permalink
ccmlib/scylla_node.py: remove JMX related code
Browse files Browse the repository at this point in the history
JMX is no longer needed, remove it completely, so it can be dropped from
Scylla packages as well.
  • Loading branch information
denesb committed Mar 22, 2024
1 parent fa6c32f commit bb9b38d
Showing 1 changed file with 2 additions and 151 deletions.
153 changes: 2 additions & 151 deletions ccmlib/scylla_node.py
Original file line number Diff line number Diff line change
Expand Up @@ -54,8 +54,6 @@ def __init__(self, name, cluster, auto_bootstrap, thrift_interface,
self.__global_log_level = 'info'
self.__classes_log_level = {}
self.get_cassandra_version()
self._process_jmx = None
self._process_jmx_waiter = None
self._process_scylla = None
self._process_scylla_waiter = None
self._process_agent = None
Expand All @@ -67,7 +65,6 @@ def __init__(self, name, cluster, auto_bootstrap, thrift_interface,
self._memory = None
self.__conf_updated = False
self.scylla_manager = scylla_manager
self.jmx_pid = None
self.agent_pid = None
self.upgraded = False
self.upgrader = NodeUpgrader(node=self)
Expand Down Expand Up @@ -191,10 +188,6 @@ def cpuset(self, id, count, cluster_id):
def memory(self):
return self._memory

def _wait_for_jmx(self):
if self._process_jmx:
self._process_jmx.wait()

def _wait_for_scylla(self):
if self._process_scylla:
self._process_scylla.wait()
Expand All @@ -203,47 +196,6 @@ def _wait_for_agent(self):
if self._process_agent:
self._process_agent.wait()

def _start_jmx(self, data):
jmx_jar_dir = os.path.join(self.get_path(), BIN_DIR)
jmx_java_bin = os.path.join(jmx_jar_dir, 'symlinks', 'scylla-jmx')
jmx_jar = os.path.join(jmx_jar_dir, 'scylla-jmx-1.0.jar')
args = [jmx_java_bin,
f"-Dapiaddress={data['listen_address']}",
'-Djavax.management.builder.initial=com.scylladb.jmx.utils.APIBuilder',
f"-Djava.rmi.server.hostname={data['listen_address']}",
'-Dcom.sun.management.jmxremote',
f"-Dcom.sun.management.jmxremote.host={data['listen_address']}",
f'-Dcom.sun.management.jmxremote.port={self.jmx_port}',
f'-Dcom.sun.management.jmxremote.rmi.port={self.jmx_port}',
'-Dcom.sun.management.jmxremote.local.only=false',
'-Xmx256m',
'-XX:+UseSerialGC',
'-Dcom.sun.management.jmxremote.authenticate=false',
'-Dcom.sun.management.jmxremote.ssl=false',
'-jar',
jmx_jar]
log_file = os.path.join(self.get_path(), 'logs', 'system.log.jmx')
env = self._get_environ(SCYLLA_HOME=self.get_path())

message = f"Starting scylla-jmx: args={args}"
self.debug(message)
with open(log_file, 'a') as jmx_log:
jmx_log.write(f"{message}\n")
self._process_jmx = subprocess.Popen(args, stdout=jmx_log, stderr=jmx_log, close_fds=True, env=env)
self._process_jmx.poll()
# When running on ccm standalone, the waiter thread would block
# the create commands. Besides in that mode, waiting is unnecessary,
# since the original popen reference is garbage collected.
standalone = os.environ.get('SCYLLA_CCM_STANDALONE', None)
if standalone is None:
self._process_jmx_waiter = threading.Thread(target=self._wait_for_jmx)
# Don't block the main thread on abnormal shutdown
self._process_jmx_waiter.daemon = True
self._process_jmx_waiter.start()
pid_filename = os.path.join(self.get_path(), 'scylla-jmx.pid')
with open(pid_filename, 'w') as pid_file:
pid_file.write(str(self._process_jmx.pid))

# Wait for a starting node until is starts listening for CQL.
# Possibly poll the log for long-running offline processes, like
# bootstrap or resharding.
Expand Down Expand Up @@ -429,18 +381,6 @@ def stop_scylla_manager_agent(self, gently):
except OSError:
pass

def _wait_java_up(self, ip_addr, jmx_port):
def is_java_up():
with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as _socket:
_socket.settimeout(1.0)
try:
_socket.connect((ip_addr, jmx_port))
return True
except (socket.timeout, ConnectionRefusedError):
return False

return wait_for(func=is_java_up, timeout=30, step=0.05)

def node_install_dir_version(self):
if not self.node_install_dir:
return None
Expand Down Expand Up @@ -688,14 +628,6 @@ def process_opts(opts):
wait_normal_token_owner=wait_normal_token_owner,
wait_for_binary_proto=wait_for_binary_proto,
ext_env=ext_env)
self._start_jmx(data)

ip_addr, _ = self.network_interfaces['storage']
jmx_port = int(self.jmx_port)
if not self._wait_java_up(ip_addr, jmx_port):
e_msg = "Error starting node {}: unable to connect to scylla-jmx port {}:{}".format(
self.name, ip_addr, jmx_port)
raise NodeError(e_msg, scylla_process)

self._update_pid(scylla_process)
wait_for(func=lambda: self.is_running(), timeout=10, step=0.01)
Expand Down Expand Up @@ -733,33 +665,6 @@ def start_dse(self,
jvm_args = []
raise NotImplementedError('ScyllaNode.start_dse')

def _update_jmx_pid(self, wait=True):
pidfile = os.path.join(self.get_path(), 'scylla-jmx.pid')

start = time.time()
while not (os.path.isfile(pidfile) and os.stat(pidfile).st_size > 0):
elapsed = time.time() - start
if elapsed > 30.0 or not wait:
if wait:
print("Timed out waiting for pidfile {} to be filled (after {} seconds): File {} size={}".format(
pidfile,
elapsed,
'exists' if os.path.isfile(pidfile) else 'does not exist' if not os.path.exists(pidfile) else 'is not a file',
os.stat(pidfile).st_size if os.path.exists(pidfile) else -1))
break
else:
time.sleep(0.1)

if os.path.isfile(pidfile) and os.stat(pidfile).st_size > 0:
try:
with open(pidfile, 'r') as f:
self.jmx_pid = int(f.readline().strip())
except IOError as e:
raise NodeError('Problem starting node %s scylla-jmx due to %s' %
(self.name, e))
else:
self.jmx_pid = None

def nodetool(self, cmd, capture_output=True, wait=True, timeout=None, verbose=True):
if self.is_docker():
host = 'localhost'
Expand All @@ -770,11 +675,6 @@ def nodetool(self, cmd, capture_output=True, wait=True, timeout=None, verbose=Tr
nodetool.extend(cmd.split())
return self._do_run_nodetool(nodetool, capture_output, wait, timeout, verbose)


def kill_jmx(self, __signal):
if self.jmx_pid:
os.kill(self.jmx_pid, __signal)

def _update_scylla_agent_pid(self):
pidfile = os.path.join(self.get_path(), 'scylla-agent.pid')

Expand Down Expand Up @@ -805,10 +705,9 @@ def do_stop(self, gently=True):
"""

did_stop = False
self._update_jmx_pid(wait=False)
if self.scylla_manager and self.scylla_manager.is_agent_available:
self._update_scylla_agent_pid()
for proc in [self._process_jmx, self._process_scylla, self._process_agent]:
for proc in [self._process_scylla, self._process_agent]:
if proc:
did_stop = True
if gently:
Expand All @@ -823,7 +722,7 @@ def do_stop(self, gently=True):
pass
else:
signal_mapping = {True: signal.SIGTERM, False: signal.SIGKILL}
for pid in [self.jmx_pid, self.pid, self.agent_pid]:
for pid in [self.pid, self.agent_pid]:
if pid:
did_stop = True
try:
Expand Down Expand Up @@ -866,22 +765,6 @@ def wait_until_stopped(self, wait_seconds=None, marks=None, dump_core=True):
os.kill(self.pid, signal.SIGKILL)
self._wait_until_stopped(10)

while self.jmx_pid and time.time() - start < wait_seconds:
try:
os.kill(self.jmx_pid, 0)
time.sleep(1)
except OSError:
self.jmx_pid = None
pass

if self.jmx_pid:
try:
self.warning("{} scylla-jmx is still running. Killing process using kill({}, SIGKILL)...".format(
self.name, wait_seconds, self.jmx_pid))
os.kill(self.jmx_pid, signal.SIGKILL)
except OSError:
pass

if self.is_running():
raise NodeError(f"Problem stopping node {self.name}")

Expand Down Expand Up @@ -941,9 +824,6 @@ def copy_config_files(self):
def get_tools_java_dir(self):
return common.get_tools_java_dir(self.node_install_dir, self._relative_repos_root or '..')

def get_jmx_dir(self):
return common.get_jmx_dir(self.node_install_dir, self._relative_repos_root or '..')

def get_cqlsh_dir(self):
return os.path.join(self.node_install_dir, 'tools', 'cqlsh')

Expand Down Expand Up @@ -1057,35 +937,6 @@ def run_patchelf(patchelf_cmd):
if returncode != 0:
raise RuntimeError(f'{patchelf_cmd} exited with status {returncode}.\nstdout:{stdout}\nstderr:\n{stderr}')

if 'scylla-repository' in self.node_install_dir:
self.hard_link_or_copy(os.path.join(self.get_jmx_dir(), 'scylla-jmx-1.0.jar'),
os.path.join(self.get_bin_dir(), 'scylla-jmx-1.0.jar'), replace=replace)
self.hard_link_or_copy(os.path.join(self.get_jmx_dir(), 'scylla-jmx'),
os.path.join(self.get_bin_dir(), 'scylla-jmx'), replace=replace)
select_java = Path(self.get_jmx_dir()) / 'select-java'
else:
self.hard_link_or_copy(os.path.join(self.get_jmx_dir(), 'target', 'scylla-jmx-1.0.jar'),
os.path.join(self.get_bin_dir(), 'scylla-jmx-1.0.jar'), replace=replace)
self.hard_link_or_copy(os.path.join(self.get_jmx_dir(), 'scripts', 'scylla-jmx'),
os.path.join(self.get_bin_dir(), 'scylla-jmx'), replace=replace)
select_java = Path(self.get_jmx_dir()) / 'scripts' / 'select-java'

os.makedirs(os.path.join(self.get_bin_dir(), 'symlinks'), exist_ok=exist_ok)
scylla_jmx_file = os.path.join(self.get_bin_dir(), 'symlinks', 'scylla-jmx')
if os.path.exists(scylla_jmx_file) and replace:
os.remove(scylla_jmx_file)
if java_home := os.environ.get('JAVA_HOME'):
# user selecting specific Java
java_exe = Path(java_home) / 'bin' / 'java'
os.symlink(java_exe, scylla_jmx_file)
elif select_java.exists():
# JMX lookup logic
os.symlink(select_java, scylla_jmx_file)
else:
# older scylla versions, just use default java
java_exe = Path('/usr') / 'bin' / 'java'
os.symlink(java_exe, scylla_jmx_file)

parent_dir = os.path.dirname(os.path.realpath(__file__))
resources_bin_dir = os.path.join(parent_dir, 'resources', BIN_DIR)
for name in os.listdir(resources_bin_dir):
Expand Down

0 comments on commit bb9b38d

Please sign in to comment.