Skip to content

Commit

Permalink
Allow additional scylla.version formats
Browse files Browse the repository at this point in the history
Modifies version parsing logic to try passing the `scylla.version` to the
CCM when it can't be parsed as VersionNumber. If CCM manages to run `create`
with it, then the usual version number is fetched from
`ccm node versionfrombuild` output.

To do that we introduce a static, worse version of `execute` method
named `executeStatic`. It's a hacky way to keep doing version initialization
in a static block. Non-static parts were removed. Logging parts were removed
from its `LogOutputStream`s. Errors are written directly through `System.err`.
It seems the loggers were not allowing the process to shut down properly and
causing it to hang up. Exact root cause is unknown, I deemed it too time
consuming to look into it.
  • Loading branch information
Bouncheck committed Dec 3, 2024
1 parent 95fa50b commit 9e6813f
Showing 1 changed file with 94 additions and 4 deletions.
98 changes: 94 additions & 4 deletions driver-core/src/test/java/com/datastax/driver/core/CCMBridge.java
Original file line number Diff line number Diff line change
Expand Up @@ -194,6 +194,20 @@ public class CCMBridge implements CCMAccess {
static {
String inputCassandraVersion = System.getProperty("cassandra.version");
String inputScyllaVersion = System.getProperty("scylla.version");
boolean inputScyllaVersionIsAVersionNumber = true;
VersionNumber parsedScyllaVersionNumber = null;
try {
parsedScyllaVersionNumber = VersionNumber.parse(inputScyllaVersion);
} catch (IllegalArgumentException e) {
inputScyllaVersionIsAVersionNumber = false;
logger.warn(
"Failed to parse scylla.version: "
+ inputScyllaVersion
+ ". Trying to get it through CCM.",
e);
parsedScyllaVersionNumber = getScyllaVersionThroughCcm(inputScyllaVersion);
}
GLOBAL_SCYLLA_VERSION_NUMBER = parsedScyllaVersionNumber;

String installDirectory = System.getProperty("cassandra.directory");
String branch = System.getProperty("cassandra.branch");
Expand All @@ -206,8 +220,11 @@ public class CCMBridge implements CCMAccess {
installArgs.add("-v git:" + branch.trim().replaceAll("\"", ""));
} else if (inputScyllaVersion != null && !inputScyllaVersion.trim().isEmpty()) {
installArgs.add(" --scylla ");
installArgs.add("-v release:" + inputScyllaVersion);

if (inputScyllaVersionIsAVersionNumber) {
installArgs.add("-v release:" + inputScyllaVersion);
} else {
installArgs.add("-v " + inputScyllaVersion);
}
// Detect Scylla Enterprise - it should start with
// a 4-digit year.
if (inputScyllaVersion.matches("\\d{4}\\..*")) {
Expand Down Expand Up @@ -246,8 +263,6 @@ public class CCMBridge implements CCMAccess {
}
ENVIRONMENT_MAP = ImmutableMap.copyOf(envMap);

GLOBAL_SCYLLA_VERSION_NUMBER = VersionNumber.parse(inputScyllaVersion);

if (isDse()) {
GLOBAL_DSE_VERSION_NUMBER = VersionNumber.parse(inputCassandraVersion);
GLOBAL_CASSANDRA_VERSION_NUMBER = CCMBridge.getCassandraVersion(GLOBAL_DSE_VERSION_NUMBER);
Expand Down Expand Up @@ -792,6 +807,81 @@ public void setWorkload(int node, Workload... workload) {
execute(CCM_COMMAND + " node%d setworkload %s", node, workloadStr);
}

private static VersionNumber getScyllaVersionThroughCcm(String versionString) {
try {
executeStatic("ccm create get_version -n 1 --scylla --version %s", versionString);
String versionOutput = executeStatic("ccm node1 versionfrombuild");
executeStatic("ccm remove");
return VersionNumber.parse(versionOutput.trim());
} catch (RuntimeException cause) {
throw new RuntimeException(
"Error during getting Scylla version through ccm commands.", cause);
}
}

// Not recommended for general use. Static version of execute() with minor modifications.
private static String executeStatic(String command, Object... args) {
String fullCommand = String.format(command, args);
Closer closer = Closer.create();
// 10 minutes timeout
ExecuteWatchdog watchDog = new ExecuteWatchdog(TimeUnit.MINUTES.toMillis(10));
StringWriter sw = new StringWriter();
final PrintWriter pw = new PrintWriter(sw);
closer.register(pw);
try {
logger.info("Executing: " + fullCommand);
CommandLine cli = CommandLine.parse(fullCommand);
Executor executor = new DefaultExecutor();
LogOutputStream outStream =
new LogOutputStream() {
@Override
protected void processLine(String line, int logLevel) {
pw.println(line);
}
};
LogOutputStream errStream =
new LogOutputStream() {
@Override
protected void processLine(String line, int logLevel) {
String err = "ccmerr> " + line;
System.err.println(err);
pw.println(err);
}
};
closer.register(outStream);
closer.register(errStream);
ExecuteStreamHandler streamHandler = new PumpStreamHandler(outStream, errStream);
executor.setStreamHandler(streamHandler);
executor.setWatchdog(watchDog);
int retValue = executor.execute(cli);
if (retValue != 0) {
logger.error(
"Non-zero exit code ({}) returned from executing ccm command: {}",
retValue,
fullCommand);
pw.flush();
throw new CCMException(
String.format(
"Non-zero exit code (%s) returned from executing ccm command: %s",
retValue, fullCommand),
sw.toString());
}
} catch (IOException e) {
if (watchDog.killedProcess())
logger.error("The command {} was killed after 10 minutes", fullCommand);
pw.flush();
throw new CCMException(
String.format("The command %s failed to execute", fullCommand), sw.toString(), e);
} finally {
try {
closer.close();
} catch (IOException e) {
Throwables.propagate(e);
}
}
return sw.toString();
}

private String execute(String command, Object... args) {
String fullCommand = String.format(command, args) + " --config-dir=" + ccmDir;
Closer closer = Closer.create();
Expand Down

0 comments on commit 9e6813f

Please sign in to comment.