in ccmlib/node.py [0:0]
def start(self,
join_ring=True,
no_wait=False,
verbose=False,
update_pid=True,
wait_other_notice=True,
replace_token=None,
replace_address=None,
jvm_args=None,
wait_for_binary_proto=False,
profile_options=None,
use_jna=False,
quiet_start=False,
allow_root=False,
set_migration_task=True,
jvm_version=None):
"""
Start the node. Options includes:
- join_ring: if false, start the node with -Dcassandra.join_ring=False
- no_wait: by default, this method returns when the node is started and listening to clients.
If no_wait=True, the method returns sooner.
- wait_other_notice: if truthy, this method returns only when all other live node of the cluster
have marked this node UP. if an integer, sets the timeout for how long to wait
- replace_token: start the node with the -Dcassandra.replace_token option.
- replace_address: start the node with the -Dcassandra.replace_address option.
"""
if jvm_args is None:
jvm_args = []
if set_migration_task and self.cluster.cassandra_version() >= '3.0.1':
jvm_args += ['-Dcassandra.migration_task_wait_in_seconds={}'.format(len(self.cluster.nodes) * 2)]
# Validate Windows env
if common.is_modern_windows_install(self.cluster.version()) and not common.is_ps_unrestricted():
raise NodeError("PS Execution Policy must be unrestricted when running C* 2.1+")
if not common.is_win() and quiet_start:
common.warning("Tried to set Windows quiet start behavior, but we're not running on Windows.")
if self.is_running():
raise NodeError("{} is already running".format(self.name))
for itf in list(self.network_interfaces.values()):
if itf is not None and replace_address is None:
common.assert_socket_available(itf)
if wait_other_notice:
marks = [(node, node.mark_log()) for node in list(self.cluster.nodes.values()) if node.is_live()]
else:
marks = []
self.mark = self.mark_log()
launch_bin = self.get_launch_bin()
# If Windows, change entries in .bat file to split conf from binaries
if common.is_win():
self.__clean_bat()
if profile_options is not None:
config = common.get_config()
if 'yourkit_agent' not in config:
raise NodeError("Cannot enable profile. You need to set 'yourkit_agent' to the path of your agent in a ~/.ccm/config")
cmd = '-agentpath:{}'.format(config['yourkit_agent'])
if 'options' in profile_options:
cmd = cmd + '=' + profile_options['options']
print_(cmd)
# Yes, it's fragile as shit
pattern = r'cassandra_parms="-Dlog4j.configuration=log4j-server.properties -Dlog4j.defaultInitOverride=true'
common.replace_in_file(launch_bin, pattern, ' ' + pattern + ' ' + cmd + '"')
os.chmod(launch_bin, os.stat(launch_bin).st_mode | stat.S_IEXEC)
env = self.get_env()
extension.append_to_server_env(self, env)
if common.is_win():
self._clean_win_jmx()
pidfile = os.path.join(self.get_path(), 'cassandra.pid')
args = [launch_bin]
self.add_custom_launch_arguments(args)
args = args + ['-p', pidfile, '-Dcassandra.join_ring=%s' % str(join_ring)]
args.append('-Dcassandra.logdir=%s' % os.path.join(self.get_path(), 'logs'))
if replace_token is not None:
args.append('-Dcassandra.replace_token=%s' % str(replace_token))
if replace_address is not None:
args.append('-Dcassandra.replace_address=%s' % str(replace_address))
if use_jna is False:
args.append('-Dcassandra.boot_without_jna=true')
if allow_root:
args.append('-R')
env['JVM_EXTRA_OPTS'] = env.get('JVM_EXTRA_OPTS', "") + " " + " ".join(jvm_args)
# Upgrade scenarios may want to test upgrades to a specific Java version. In case a prior C* version
# requires a lower Java version, we would keep its JAVA_HOME in self.__environment_variables and therefore
# prevent using the "intended" Java version for the C* version to upgrade to.
if not self.__original_java_home:
# Save the "original" JAVA_HOME + PATH to restore it.
self.__original_java_home = os.environ['JAVA_HOME']
self.__original_path = os.environ['PATH']
logger.info("Saving original JAVA_HOME={} PATH={}".format(self.__original_java_home, self.__original_path))
else:
# Restore the "original" JAVA_HOME + PATH to restore it.
env['JAVA_HOME'] = self.__original_java_home
env['PATH'] = self.__original_path
logger.info("Restoring original JAVA_HOME={} PATH={}".format(self.__original_java_home, self.__original_path))
env = common.update_java_version(jvm_version=jvm_version,
install_dir=self.get_install_dir(),
cassandra_version=self.get_cassandra_version(),
env=env,
info_message=self.name)
# Need to update the node's environment for nodetool and other tools.
# (e.g. the host's JAVA_HOME points to Java 11, but the node's software is only for Java 8)
for k in 'JAVA_HOME', 'PATH':
self.__environment_variables[k] = env[k]
common.info("Starting {} with JAVA_HOME={} java_version={} cassandra_version={}, install_dir={}"
.format(self.name, env['JAVA_HOME'], common.get_jdk_version_int(env=env),
self.get_cassandra_version(), self.get_install_dir()))
# In case we are restarting a node
# we risk reading the old cassandra.pid file
self._delete_old_pid()
# Always write the stdout+stderr of the launched process to log files to make finding startup issues easier.
start_time = time.time()
stdout_sink = open(os.path.join(self.log_directory(), 'startup-{}-stdout.log'.format(start_time)), "w+")
stderr_sink = open(os.path.join(self.log_directory(), 'startup-{}-stderr.log'.format(start_time)), "w+")
if common.is_win():
# clean up any old dirty_pid files from prior runs
dirty_pid_path = os.path.join(self.get_path() + "dirty_pid.tmp")
if (os.path.isfile(dirty_pid_path)):
os.remove(dirty_pid_path)
if quiet_start and self.cluster.version() >= '2.2.4':
args.append('-q')
process = subprocess.Popen(args, cwd=self.get_bin_dir(), env=env, stdout=stdout_sink, stderr=stderr_sink)
else:
process = subprocess.Popen(args, env=env, stdout=stdout_sink, stderr=stderr_sink)
process.stderr_file = stderr_sink
if verbose:
common.debug("verbose mode: waiting for the start process out/err (and termination)")
stdout, stderr = process.communicate()
print_(str(stdout))
print_(str(stderr))
# Our modified batch file writes a dirty output with more than just the pid - clean it to get in parity
# with *nix operation here.
if common.is_win():
self.__clean_win_pid()
self._update_pid(process)
print_("Started: {0} with pid: {1}".format(self.name, self.pid), file=sys.stderr, flush=True)
if update_pid or wait_for_binary_proto:
# at this moment we should have PID and it should be running...
if not self._wait_for_running(process, timeout_s=7):
raise NodeError("Node {n} is not running".format(n=self.name), process)
# if requested wait for other nodes to observe this one (via gossip)
if common.is_int_not_bool(wait_other_notice):
for node, mark in marks:
node.watch_log_for_alive(self, from_mark=mark, timeout=wait_other_notice)
elif wait_other_notice:
for node, mark in marks:
node.watch_log_for_alive(self, from_mark=mark)
# if requested wait for binary protocol to start
if common.is_int_not_bool(wait_for_binary_proto):
self.wait_for_binary_interface(from_mark=self.mark, timeout=wait_for_binary_proto)
elif wait_for_binary_proto:
self.wait_for_binary_interface(from_mark=self.mark)
return process