Skip to content

Commit 52d548c

Browse files
committed
Fixed monitoring of the admin and debug ports when stopping
Signed-off-by: David Matějček <[email protected]>
1 parent 854e84e commit 52d548c

File tree

16 files changed

+164
-127
lines changed

16 files changed

+164
-127
lines changed

nucleus/admin/launcher/src/main/java/com/sun/enterprise/admin/launcher/GFLauncher.java

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -382,7 +382,6 @@ public String getLogFilename() {
382382
throw new IllegalStateException("Call to getLogFilename() before it has been initialized!");
383383
}
384384

385-
386385
/**
387386
* @return null or a port number
388387
*/

nucleus/admin/server-mgmt/src/main/java/com/sun/enterprise/admin/servermgmt/cli/ChangeMasterPasswordCommand.java

Lines changed: 13 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
/*
2+
* Copyright (c) 2025 Contributors to the Eclipse Foundation.
23
* Copyright (c) 1997, 2018 Oracle and/or its affiliates. All rights reserved.
34
*
45
* This program and the accompanying materials are made available under the
@@ -92,21 +93,19 @@ protected int executeCommand() throws CommandException {
9293
if (nodeDir != null) {
9394
command = CLICommand.getCommand(habitat, CHANGE_MASTER_PASSWORD_NODE);
9495
return command.execute(argv);
95-
} else {
96-
97-
// nodeDir is not specified and domainNameOrNodeName is not a domain.
98-
// It could be a node
99-
// We add defaultNodeDir parameter to args
100-
ArrayList arguments = new ArrayList<String>(Arrays.asList(argv));
101-
arguments.remove(argv.length - 1);
102-
arguments.add("--nodedir");
103-
arguments.add(getDefaultNodesDirs().getAbsolutePath());
104-
arguments.add(domainNameOrNodeName);
105-
String[] newargs = (String[]) arguments.toArray(new String[arguments.size()]);
106-
107-
command = CLICommand.getCommand(habitat, CHANGE_MASTER_PASSWORD_NODE);
108-
return command.execute(newargs);
10996
}
97+
// nodeDir is not specified and domainNameOrNodeName is not a domain.
98+
// It could be a node
99+
// We add defaultNodeDir parameter to args
100+
ArrayList<String> arguments = new ArrayList<>(Arrays.asList(argv));
101+
arguments.remove(argv.length - 1);
102+
arguments.add("--nodedir");
103+
arguments.add(getDefaultNodesDirs().getAbsolutePath());
104+
arguments.add(domainNameOrNodeName);
105+
String[] newargs = arguments.toArray(String[]::new);
106+
107+
command = CLICommand.getCommand(habitat, CHANGE_MASTER_PASSWORD_NODE);
108+
return command.execute(newargs);
110109
} catch (IOException e) {
111110
throw new CommandException(e.getMessage(), e);
112111
}

nucleus/admin/server-mgmt/src/main/java/com/sun/enterprise/admin/servermgmt/cli/ListDomainsCommand.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -94,7 +94,7 @@ private DomainInfo getStatus(String domainName) throws CommandException {
9494
setDomainName(domainName);
9595
initDomain();
9696
DomainInfo info = new DomainInfo();
97-
info.adminAddr = getAdminAddress(getDomainXml(), "server");
97+
info.adminAddr = getAdminAddresses(getDomainXml(), "server");
9898
HostAndPort reachableEndpoint = getReachableAdminAddress(getDomainXml());
9999
if (reachableEndpoint == null) {
100100
info.status = false;

nucleus/admin/server-mgmt/src/main/java/com/sun/enterprise/admin/servermgmt/cli/LocalServerCommand.java

Lines changed: 68 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -33,10 +33,12 @@
3333

3434
import java.io.File;
3535
import java.io.IOException;
36+
import java.lang.System.Logger;
37+
import java.lang.System.Logger.Level;
3638
import java.nio.file.Files;
3739
import java.time.Duration;
3840
import java.util.List;
39-
import java.util.logging.Level;
41+
import java.util.function.Supplier;
4042

4143
import org.glassfish.api.ActionReport;
4244
import org.glassfish.api.ActionReport.ExitCode;
@@ -50,21 +52,23 @@
5052
import static com.sun.enterprise.admin.servermgmt.cli.ServerLifeSignChecker.step;
5153
import static com.sun.enterprise.universal.process.ProcessUtils.loadPid;
5254
import static com.sun.enterprise.universal.process.ProcessUtils.waitForNewPid;
55+
import static com.sun.enterprise.universal.process.ProcessUtils.waitWhileIsAlive;
5356
import static com.sun.enterprise.util.SystemPropertyConstants.KEYSTORE_PASSWORD_DEFAULT;
5457
import static com.sun.enterprise.util.SystemPropertyConstants.MASTER_PASSWORD_ALIAS;
5558
import static com.sun.enterprise.util.SystemPropertyConstants.MASTER_PASSWORD_FILENAME;
5659
import static com.sun.enterprise.util.SystemPropertyConstants.MASTER_PASSWORD_PASSWORD;
5760
import static com.sun.enterprise.util.SystemPropertyConstants.TRUSTSTORE_FILENAME_DEFAULT;
58-
import static java.util.logging.Level.FINER;
59-
import static java.util.logging.Level.FINEST;
61+
import static java.lang.System.Logger.Level.DEBUG;
62+
import static java.lang.System.Logger.Level.INFO;
63+
import static java.lang.System.Logger.Level.TRACE;
6064

6165
/**
6266
* A class that's supposed to capture all the behavior common to operation on a "local" server.
6367
*
6468
* @author Byron Nevins
6569
*/
6670
public abstract class LocalServerCommand extends CLICommand {
67-
71+
private static final Logger LOG = System.getLogger(LocalServerCommand.class.getName());
6872
private static final LocalStringsImpl I18N = new LocalStringsImpl(LocalDomainCommand.class);
6973
private ServerDirs serverDirs;
7074

@@ -105,20 +109,24 @@ protected final HostAndPort getReachableAdminAddress(File domainXml) throws Comm
105109

106110
private HostAndPort findReachableAdminAddress(String userHost, Integer userPort, Boolean userSecure, File domainXml)
107111
throws CommandException {
112+
LOG.log(DEBUG, "findReachableAdminAddress(userHost={0}, userPort={1}, userSecure={2}, domainXml={3})",
113+
userHost, userPort, userSecure, domainXml);
108114
// Respect user provided values
109115
if (userHost != null && userPort != null && userSecure != null) {
110116
HostAndPort endpoint = new HostAndPort(userHost, userPort, userSecure);
111117
return ProcessUtils.isListening(endpoint) ? endpoint : null;
112118
}
113119
// default: DAS always has the name "server"
114-
final List<HostAndPort> xml = getAdminAddress(domainXml, "server");
120+
final List<HostAndPort> xml = getAdminAddresses(domainXml, "server");
115121
if (xml.isEmpty()) {
116122
String host = userHost == null ? DEFAULT_HOSTNAME : userHost;
117123
Integer port = userPort == null ? DEFAULT_ADMIN_PORT : userPort;
118124
boolean secure = userSecure == null ? false : userSecure;
119125
HostAndPort endpoint = new HostAndPort(host, port, secure);
126+
LOG.log(INFO, "Checking candidate: " + endpoint);
120127
return ProcessUtils.isListening(endpoint) ? endpoint : null;
121128
}
129+
LOG.log(TRACE, () -> "Checking candidates: " + xml);
122130
for (HostAndPort candidate : xml) {
123131
final String host = userHost == null ? candidate.getHost() : userHost;
124132
final int port = userPort == null ? candidate.getPort() : userPort;
@@ -136,9 +144,10 @@ private HostAndPort findReachableAdminAddress(String userHost, Integer userPort,
136144
* For remote access it uses command line arguments and defaults.
137145
*
138146
* @return list of HostAndPort objects with admin server addresses. Never null.
139-
* @throws CommandException in case of parsing errors
147+
* @throws IllegalStateException in case of parsing errors
140148
*/
141-
protected final List<HostAndPort> getAdminAddress(File domainXml, String serverName) throws CommandException {
149+
protected final List<HostAndPort> getAdminAddresses(File domainXml, String serverName)
150+
throws IllegalStateException {
142151
if (!isLocal()) {
143152
// We don't have any access to changes.
144153
return List.of(getUserProvidedAdminAddress());
@@ -147,11 +156,11 @@ protected final List<HostAndPort> getAdminAddress(File domainXml, String serverN
147156
MiniXmlParser parser = new MiniXmlParser(domainXml, serverName);
148157
List<HostAndPort> addrSet = parser.getAdminAddresses();
149158
if (addrSet.isEmpty()) {
150-
throw new CommandException(I18N.get("NoAdminPort"));
159+
throw new IllegalStateException(I18N.get("NoAdminPort"));
151160
}
152161
return addrSet;
153162
} catch (MiniXmlParserException ex) {
154-
throw new CommandException(I18N.get("NoAdminPortEx", ex), ex);
163+
throw new IllegalStateException(I18N.get("NoAdminPortEx", ex), ex);
155164
}
156165
}
157166

@@ -178,7 +187,7 @@ protected final boolean isLocal() {
178187
protected final void setLocalPassword() {
179188
String pw = serverDirs == null ? null : serverDirs.getLocalPassword();
180189
programOpts.setPassword(pw == null ? null : pw.toCharArray(), LOCAL_PASSWORD);
181-
logger.finer(ok(pw) ? "Using local password" : "Not using local password");
190+
LOG.log(DEBUG, () -> ok(pw) ? "Using local password" : "Not using local password");
182191
}
183192

184193
protected final void unsetLocalPassword() {
@@ -220,7 +229,7 @@ protected final String readFromMasterPasswordFile() {
220229
PasswordAdapter pw = new PasswordAdapter(mpf.getAbsolutePath(), MASTER_PASSWORD_PASSWORD.toCharArray());
221230
return pw.getPasswordForAlias(MASTER_PASSWORD_ALIAS);
222231
} catch (Exception e) {
223-
logger.log(Level.WARNING, "A master password file reading error: " + e.toString(), e);
232+
LOG.log(Level.WARNING, "A master password file reading error: " + e.toString(), e);
224233
return null;
225234
}
226235
}
@@ -230,15 +239,15 @@ protected final boolean verifyMasterPassword(String mpv) {
230239
}
231240

232241
protected boolean loadAndVerifyKeystore(File jks, String mpv) {
233-
logger.log(FINEST, "loading keystore: " + jks);
242+
LOG.log(DEBUG, "loading keystore: " + jks);
234243
if (jks == null || mpv == null) {
235244
return false;
236245
}
237246
try {
238247
new KeyTool(jks, mpv.toCharArray()).loadKeyStore();
239248
return true;
240249
} catch (Exception e) {
241-
logger.log(FINER, e.getMessage(), e);
250+
LOG.log(DEBUG, e.getMessage(), e);
242251
return false;
243252
}
244253
}
@@ -268,7 +277,7 @@ protected final String getMasterPassword() throws CommandException {
268277
masterPassword = retry(countOfRetries);
269278
}
270279
}
271-
logger.log(FINER, "Time spent in master password extraction: {0} ms", (System.currentTimeMillis() - start));
280+
LOG.log(DEBUG, "Time spent in master password extraction: " + (System.currentTimeMillis() - start) + " ms");
272281
return masterPassword;
273282
}
274283

@@ -283,13 +292,13 @@ protected final boolean isThisServer(File ourDir, String directoryKey) {
283292
}
284293

285294
ourDir = getUniquePath(ourDir);
286-
logger.log(FINER, "Check if server is at location {0}", ourDir);
295+
LOG.log(DEBUG, "Check if server is at location {0}", ourDir);
287296

288297
try {
289298
RemoteCLICommand cmd = new RemoteCLICommand("__locations", programOpts, env);
290299
ActionReport report = cmd.executeAndReturnActionReport(new String[] { "__locations" });
291300
String theirDirPath = report.findProperty(directoryKey);
292-
logger.log(FINER, "Remote server has root directory {0}", theirDirPath);
301+
LOG.log(DEBUG, "Remote server has root directory {0}", theirDirPath);
293302

294303
if (ok(theirDirPath)) {
295304
File theirDir = getUniquePath(new File(theirDirPath));
@@ -315,14 +324,14 @@ protected final Long getServerPid() {
315324
if (report.getActionExitCode() == ExitCode.SUCCESS) {
316325
long pidFromAdmin = Long.parseLong(report.findProperty("Pid"));
317326
if (pidFromFile == null || !pidFromFile.equals(pidFromAdmin)) {
318-
logger.log(Level.SEVERE, "PID should be the same: PID from file = " + pidFromFile
327+
LOG.log(Level.ERROR, "PID should be the same: PID from file = " + pidFromFile
319328
+ ", while PID received from admin endpoint = " + pidFromAdmin);
320329
}
321330
return pidFromAdmin;
322331
}
323332
return null;
324333
} catch (Exception e) {
325-
logger.log(Level.SEVERE, "The server PID could not be resolved, sending PID from file: " + pidFromFile, e);
334+
LOG.log(Level.ERROR, "The server PID could not be resolved, sending PID from file: " + pidFromFile + ".", e);
326335
return pidFromFile;
327336
}
328337
}
@@ -331,35 +340,50 @@ protected final Long getServerPid() {
331340
* Waits until server stops
332341
*
333342
* @param pid
334-
* @param oldAdminAddress
343+
* @param adminAddress
335344
* @param timeout can be null
336345
* @throws CommandException if we time out.
337346
*/
338-
protected final void waitForStop(final Long pid, final HostAndPort oldAdminAddress, final Duration timeout)
347+
protected final void waitForStop(final Long pid, final HostAndPort adminAddress, final Duration timeout)
339348
throws CommandException {
340-
logger.log(Level.FINEST, "waitForStop(pid={0}, oldAdminAddress={1}, timeout={2})",
341-
new Object[] {pid, oldAdminAddress, timeout});
349+
LOG.log(DEBUG, "waitForStop(pid={0}, oldAdminAddress={1}, timeout={2})", pid, adminAddress, timeout);
342350

343351
final boolean printDots = !programOpts.isTerse();
344-
final boolean stopped = pid == null || ProcessUtils.waitWhileIsAlive(pid, timeout, printDots);
345-
if (!stopped) {
346-
throw new CommandException("Timed out waiting for the server to stop.");
352+
353+
final Duration portTimeout;
354+
if (pid == null) {
355+
portTimeout = timeout;
356+
} else {
357+
portTimeout = step("Waiting for the death of the process with pid " + pid, timeout,
358+
() -> waitWhileIsAlive(pid, timeout, printDots));
359+
if (ProcessUtils.isAlive(pid)) {
360+
throw new CommandException("Timed out waiting for the server process to stop.");
361+
}
362+
}
363+
if (adminAddress == null) {
364+
return;
347365
}
366+
LOG.log(INFO, "Waiting until admin endpoint {0} is free.", adminAddress);
367+
final boolean stopped = ProcessUtils.waitWhileListening(adminAddress,
368+
portTimeout == null ? Duration.ofHours(1L) : portTimeout, printDots);
369+
if (stopped) {
370+
return;
371+
}
372+
throw new CommandException("Timed out waiting for the server to stop.");
348373
}
349374

350375
/**
351376
* Waits until server is running - with different pid
352377
*
353378
* @param oldPid
354379
* @param lifeSignCheck
355-
* @param adminEndpoints
380+
* @param adminEndpointsSupplier
356381
* @param timeout can be null
357382
* @throws CommandException if we time out.
358383
*/
359384
protected final String waitForStart(final Long oldPid, final ServerLifeSignCheck lifeSignCheck,
360-
final List<HostAndPort> adminEndpoints, final Duration timeout) throws CommandException {
361-
logger.log(Level.FINEST, "waitForStart(oldPid={0}, adminEndpoints={1}, timeout={2})",
362-
new Object[] {oldPid, adminEndpoints, timeout});
385+
final Supplier<List<HostAndPort>> adminEndpointsSupplier, final Duration timeout) throws CommandException {
386+
LOG.log(DEBUG, "waitForStart(oldPid={0}, adminEndpoints, timeout={1})", oldPid, timeout);
363387

364388
final boolean printDots = !programOpts.isTerse();
365389
final File pidFile = getServerDirs().getPidFile();
@@ -378,7 +402,16 @@ protected final String waitForStart(final Long oldPid, final ServerLifeSignCheck
378402
throw new CommandException(reportPidFileIssue(pidFile));
379403
}
380404

381-
logger.log(Level.INFO, () -> "Waiting until start of " + lifeSignCheck.getServerTitleAndName() + " completes.");
405+
try {
406+
resetServerDirs();
407+
setLocalPassword();
408+
} catch (Exception e) {
409+
LOG.log(Level.WARNING, "The endpoint is alive, but we failed to reset the local password.", e);
410+
}
411+
412+
LOG.log(INFO, () -> "Waiting until start of " + lifeSignCheck.getServerTitleAndName() + " completes.");
413+
414+
final List<HostAndPort> adminEndpoints = adminEndpointsSupplier.get();
382415
final ServerLifeSignChecker checker = new ServerLifeSignChecker(lifeSignCheck, pidFile, adminEndpoints, printDots);
383416
final GlassFishProcess process = GlassFishProcess.of(pid);
384417
final ServerLifeSigns signs = checker.watchStartup(process, startTimeout);
@@ -424,14 +457,14 @@ private String loadRestartLog(final File logFile ) {
424457
return null;
425458
}
426459
try {
427-
String report = "Found restart log file content: \n***********\n"
428-
+ Files.readString(serverDirs.getRestartLogFile().toPath()) + "\n**********\n";
460+
String report = "Found restart log file content: \n##########\n"
461+
+ Files.readString(serverDirs.getRestartLogFile().toPath()) + "\n##########\n";
429462
// The log is there just to diagnose failed start phase of the restart.
430463
// We don't want to delete it if we cannot load it.
431464
logFile.delete();
432465
return report;
433466
} catch (IOException e) {
434-
logger.log(Level.WARNING, "Failed to read the restart log file: " + serverDirs.getRestartLogFile(), e);
467+
LOG.log(Level.WARNING, "Failed to read the restart log file: " + serverDirs.getRestartLogFile(), e);
435468
return null;
436469
}
437470
}
@@ -448,7 +481,7 @@ protected final long getUptime() throws CommandException {
448481
throw new CommandException(I18N.get("restart.dasNotRunning"));
449482
}
450483

451-
logger.log(FINER, "server uptime: {0}", up_ms);
484+
LOG.log(DEBUG, () -> "Server uptime: " + up_ms + " ms");
452485
return up_ms;
453486
}
454487

@@ -495,7 +528,7 @@ private File getJKS() {
495528
if (mp.canRead()) {
496529
return mp;
497530
}
498-
logger.log(FINEST, "File does not exist or is not readable: {0}", mp);
531+
LOG.log(DEBUG, "File does not exist or is not readable: {0}", mp);
499532
return null;
500533
}
501534

nucleus/admin/server-mgmt/src/main/java/com/sun/enterprise/admin/servermgmt/cli/LocalStrings.properties

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -115,7 +115,6 @@ Domain.badDomainDir=CLI301: There is no such domain directory: {0}
115115
Domain.noDomainXml=CLI304: Cannot find domain.xml. It should be here: {0}
116116

117117
## stop-domain command
118-
StopDomain.WaitDASDeath=Waiting for the domain to stop
119118
StopDomain.DASNotDead=Timed out ({0} seconds) waiting for the domain to stop.
120119
StopDomain.noDomainNameAllowed=No domain name allowed with --host option.
121120
StopDomain.nopidprev=Can not find the process ID of the server. It is supposed to be here: {0}. Unable to kill the process.

nucleus/admin/server-mgmt/src/main/java/com/sun/enterprise/admin/servermgmt/cli/RestartDomainCommand.java

Lines changed: 9 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@
2626
import java.time.Duration;
2727
import java.util.ArrayList;
2828
import java.util.List;
29+
import java.util.function.Supplier;
2930

3031
import org.glassfish.api.Param;
3132
import org.glassfish.api.admin.CommandException;
@@ -92,7 +93,7 @@ protected void doCommand() throws CommandException {
9293

9394
// oldPid is received from the running server.
9495
final Long oldPid = getServerPid();
95-
final HostAndPort oldAdminAddress = getReachableAdminAddress(getDomainXml());
96+
final HostAndPort oldAdminAddress = getUserProvidedAdminAddress();
9697
final RemoteCLICommand cmd = new RemoteCLICommand("restart-domain", programOpts, env);
9798
if (debug == null) {
9899
cmd.executeAndReturnOutput("restart-domain");
@@ -101,17 +102,17 @@ protected void doCommand() throws CommandException {
101102
}
102103

103104
final Duration timeout = getRestartTimeout();
104-
final Duration startTimeout = step("Waiting until domain stops.", timeout,
105-
() -> waitForStop(oldPid, oldAdminAddress, timeout));
105+
final Duration startTimeout = step(null, timeout,
106+
() -> waitForStop(isLocal() ? oldPid : null, oldAdminAddress, timeout));
106107

107108
final List<HostAndPort> userEndpoints = parseCustomEndpoints(customEndpoints);
108109
final ServerLifeSignCheck lifeSignCheck = new ServerLifeSignCheck("domain " + getDomainName(),
109110
printServerOutput, checkPidFile, checkProcessAlive, checkAdminEndpoint, userEndpoints);
110-
final List<HostAndPort> newAdminEndpoints = getAdminAddress(getDomainXml(), "server");
111-
final List<HostAndPort> adminEndpoints = newAdminEndpoints.isEmpty()
112-
? List.of(getUserProvidedAdminAddress())
113-
: newAdminEndpoints;
114-
final String report = waitForStart(oldPid, lifeSignCheck, adminEndpoints, startTimeout);
111+
final Supplier<List<HostAndPort>> adminEndpointsSupplier = () -> {
112+
final List<HostAndPort> newAdminEndpoints = getAdminAddresses(getDomainXml(), "server");
113+
return newAdminEndpoints.isEmpty() ? List.of(getUserProvidedAdminAddress()) : newAdminEndpoints;
114+
};
115+
final String report = waitForStart(oldPid, lifeSignCheck, adminEndpointsSupplier, startTimeout);
115116
logger.info(report);
116117
}
117118

0 commit comments

Comments
 (0)