Skip to content

Commit 8365c4c

Browse files
committed
Prefix Anka logs with [Anka]; improve Advanced cloud config UI
- Add AnkaLog / AnkaSdkLog and use for plugin and ankaMgmtSdk INFO/FINE/WARNING lines - Cloud Log() output gets the same prefix via AnkaMgmtCloud - Jenkins cloud config: use f:advanced instead of optionalBlock; widen advanced panel; hide repeated-chunk__header padding - Provisioning: log when cloud/template capacity blocks provisioning and when no cloud can provision a label - AnkaPlannedNodeCreator: terminate instance on InterruptedException during provisioning wait
1 parent 1367f9c commit 8365c4c

13 files changed

Lines changed: 150 additions & 92 deletions

src/main/java/com/veertu/ankaMgmtSdk/AnkaAPI.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -90,7 +90,7 @@ public String startVM(String templateId, String tag, String startUpScript, Strin
9090
}
9191

9292
public boolean terminateInstance(String vmId) throws AnkaMgmtException {
93-
LOGGER.info("Sending termination request to instance: " + vmId);
93+
LOGGER.info(AnkaSdkLog.prefix("Sending termination request to instance: " + vmId));
9494
boolean result = communicator.terminateVm(vmId);
9595
invalidateCache();
9696
return result;
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
package com.veertu.ankaMgmtSdk;
2+
3+
final class AnkaSdkLog {
4+
private static final String PREFIX = "[Anka] ";
5+
6+
private AnkaSdkLog() {
7+
}
8+
9+
static String prefix(String message) {
10+
if (message == null || message.startsWith(PREFIX)) {
11+
return message;
12+
}
13+
return PREFIX + message;
14+
}
15+
}

src/main/java/com/veertu/ankaMgmtSdk/ConcAnkaMgmtVm.java

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@ public ConcAnkaMgmtVm(String sessionId, AnkaMgmtCommunicator communicator, int s
2828
this.sessionId = sessionId;
2929
this.sshConnectionPort = sshConnectionPort;
3030
this.terminated = false;
31-
logger.info(String.format("init VM %s", sessionId));
31+
logger.info(AnkaSdkLog.prefix(String.format("init VM %s", sessionId)));
3232
}
3333

3434
public String getStatus() throws AnkaMgmtException {
@@ -72,7 +72,7 @@ private AnkaVmInstance getSessionInfoCache() {
7272
if (session != null) {
7373
this.cachedVmSession = session;
7474
} else {
75-
logger.info("info for vm is null");
75+
logger.info(AnkaSdkLog.prefix("info for vm is null"));
7676
}
7777
}
7878
return this.cachedVmSession;
@@ -152,14 +152,14 @@ private boolean isScheduling() throws AnkaMgmtException {
152152
}
153153

154154
public String waitForBoot(int schedulingTimeout) throws InterruptedException, IOException, AnkaMgmtException {
155-
logger.info(String.format("waiting for vm %s to boot", this.sessionId));
155+
logger.info(AnkaSdkLog.prefix(String.format("waiting for vm %s to boot", this.sessionId)));
156156
int timeWaited = 0;
157157

158158
while (isScheduling()) {
159159
// terminate if scheduling timeout is reached
160160
Thread.sleep(waitUnit);
161161
timeWaited += waitUnit;
162-
logger.info(String.format("waiting for vm %s %d to stop scheduling", this.sessionId, timeWaited));
162+
logger.info(AnkaSdkLog.prefix(String.format("waiting for vm %s %d to stop scheduling", this.sessionId, timeWaited)));
163163
if (timeWaited > schedulingTimeout * waitUnit) {
164164
this.terminate();
165165
throw new IOException("vm scheduling too long");
@@ -173,15 +173,15 @@ public String waitForBoot(int schedulingTimeout) throws InterruptedException, IO
173173
try {
174174
Thread.sleep(waitUnit);
175175
timeWaited += waitUnit;
176-
logger.info(String.format("waiting for vm %s %d to boot", this.sessionId, timeWaited));
176+
logger.info(AnkaSdkLog.prefix(String.format("waiting for vm %s %d to boot", this.sessionId, timeWaited)));
177177
if (timeWaited > maxRunningTimeout) {
178178
this.terminate();
179179
throw new IOException("could not start vm");
180180

181181
}
182182
} catch (InterruptedException e) {
183183
if (isPulling()) { // Don't let jenkins interrupt us while we are pulling
184-
logger.info(String.format("vm %s is pulling, ignoring InterruptedException", this.sessionId));
184+
logger.info(AnkaSdkLog.prefix(String.format("vm %s is pulling, ignoring InterruptedException", this.sessionId)));
185185
} else {
186186
throw e;
187187
}
@@ -190,7 +190,7 @@ public String waitForBoot(int schedulingTimeout) throws InterruptedException, IO
190190

191191
String ip;
192192
timeWaited = 0;
193-
logger.info(String.format("waiting for vm %s to get an ip ", this.sessionId));
193+
logger.info(AnkaSdkLog.prefix(String.format("waiting for vm %s to get an ip ", this.sessionId)));
194194
while (true) { // wait to get machine ip
195195

196196
ip = this.getIp();
@@ -199,7 +199,7 @@ public String waitForBoot(int schedulingTimeout) throws InterruptedException, IO
199199

200200
Thread.sleep(waitUnit);
201201
timeWaited += waitUnit;
202-
logger.info(String.format("waiting for vm %s %d to get ip ", this.sessionId, timeWaited));
202+
logger.info(AnkaSdkLog.prefix(String.format("waiting for vm %s %d to get ip ", this.sessionId, timeWaited)));
203203
if (timeWaited > maxIpTimeout) {
204204
this.terminate();
205205
throw new IOException("VM started but couldn't acquire ip");

src/main/java/com/veertu/plugin/anka/AbstractAnkaSlave.java

Lines changed: 11 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -114,11 +114,11 @@ public void terminate() throws IOException {
114114
Thread.sleep(3000); // Sleep for 3 seconds to avoid those spooky ChannelClosedException
115115
AnkaVmInstance vm = getAndLogInstance();
116116
if (vm != null) {
117-
LOGGER.log(Level.INFO, "Node {0} Instance {1} is in state {2}", new Object[]{getNodeName(), instanceId, vm.getSessionState()});
117+
LOGGER.log(Level.INFO, AnkaLog.prefix("Node {0} Instance {1} is in state {2}"), new Object[]{getNodeName(), instanceId, vm.getSessionState()});
118118
SaveImageParameters saveImageParams = template.getSaveImageParameters();
119119
if (taskExecuted && saveImageParams != null && this.template.getSaveImageParameters().getSaveImage()
120120
&& saveImageParams.getSaveImage() && !hadProblemsInBuild && !hadUnknownBuildOutcome) {
121-
LOGGER.log(Level.INFO, "Node {0} Instance {1}, saving image", new Object[]{getNodeName(), instanceId});
121+
LOGGER.log(Level.INFO, AnkaLog.prefix("Node {0} Instance {1}, saving image"), new Object[]{getNodeName(), instanceId});
122122

123123
synchronized (this) {
124124
if (!this.saveImageSent) { // allow to send save image request only once
@@ -127,11 +127,11 @@ public void terminate() throws IOException {
127127
}
128128
}
129129
} else {
130-
LOGGER.log(Level.INFO, "Node {0} Instance {1}, terminating", new Object[]{getNodeName(), instanceId});
130+
LOGGER.log(Level.INFO, AnkaLog.prefix("Node {0} Instance {1}, terminating"), new Object[]{getNodeName(), instanceId});
131131
cloud.terminateVMInstance(this.instanceId);
132132
}
133133
} else {
134-
LOGGER.log(Level.INFO, "Node {0} Instance {1} was not found, ensuring termination", new Object[]{getNodeName(), instanceId});
134+
LOGGER.log(Level.INFO, AnkaLog.prefix("Node {0} Instance {1} was not found, ensuring termination"), new Object[]{getNodeName(), instanceId});
135135
}
136136
} catch (AnkaMgmtException e) {
137137
throw new IOException(e);
@@ -145,9 +145,9 @@ public void terminate() throws IOException {
145145
if (instance != null) {
146146
state = instance.getSessionState();
147147
}
148-
LOGGER.log(Level.INFO, "Node {0} Instance {1}, ensuring termination before node removal, state: {2}", new Object[]{getNodeName(), instanceId, state});
148+
LOGGER.log(Level.INFO, AnkaLog.prefix("Node {0} Instance {1}, ensuring termination before node removal, state: {2}"), new Object[]{getNodeName(), instanceId, state});
149149
if (instance == null || instance.isTerminatingOrTerminated()) {
150-
LOGGER.log(Level.INFO, "Node {0} Instance {1}, removing node since instance is terminated or not found", new Object[]{getNodeName(), instanceId});
150+
LOGGER.log(Level.INFO, AnkaLog.prefix("Node {0} Instance {1}, removing node since instance is terminated or not found"), new Object[]{getNodeName(), instanceId});
151151
Jenkins.get().removeNode(this); // only agree to remove the node after the instance doesn't
152152
// exist or is not started
153153
}
@@ -245,12 +245,12 @@ private AnkaVmInstance getAndLogInstance() throws AnkaMgmtException {
245245
String vmId = vmInfo.getUuid();
246246
String hostIp = vmInfo.getHostIp();
247247
String vmStatus = vmInfo.getStatus();
248-
LOGGER.log(Level.FINE, "Node {0} instance {1}. instance state: {2}, " +
249-
"template id: {3}, VM uuid: {4}, VM status: {5} host IP: {6}", new Object[]{ getNodeName(), instanceId, state,
248+
LOGGER.log(Level.FINE, AnkaLog.prefix("Node {0} instance {1}. instance state: {2}, " +
249+
"template id: {3}, VM uuid: {4}, VM status: {5} host IP: {6}"), new Object[]{ getNodeName(), instanceId, state,
250250
templateId, vmId, vmStatus, hostIp });
251251
} else {
252-
LOGGER.log(Level.FINE, "Node {0} instance {1}. instance state: {2}, " +
253-
"template id: {3}", new Object[]{ getNodeName(), instanceId, state,
252+
LOGGER.log(Level.FINE, AnkaLog.prefix("Node {0} instance {1}. instance state: {2}, " +
253+
"template id: {3}"), new Object[]{ getNodeName(), instanceId, state,
254254
templateId});
255255
}
256256
} else {
@@ -265,7 +265,7 @@ public boolean isAlive() {
265265
AnkaVmInstance instance = getAndLogInstance();
266266
if (instance != null) {
267267
String state = instance.getSessionState();
268-
LOGGER.log(Level.FINE, "Anka Node {0}, instance {1} is in state {2}",
268+
LOGGER.log(Level.FINE, AnkaLog.prefix("Anka Node {0}, instance {1} is in state {2}"),
269269
new Object[]{name, instanceId, state});
270270
if (instance.isStarted()) {
271271
return true;

src/main/java/com/veertu/plugin/anka/AnkaCloudComputer.java

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -175,8 +175,9 @@ void safelyCheckLatestJobAndChangeNodeBehaviour(Executor executor, Queue.Task ta
175175
// Unknown/unstable metadata should never prevent run-once cleanup.
176176
applyBuildOutcome(BuildOutcome.UNKNOWN);
177177
LOGGER.log(Level.WARNING,
178+
AnkaLog.prefix(
178179
String.format("Computer %s, instance %s failed to resolve build result for task %s",
179-
getName(), getVMId(), task),
180+
getName(), getVMId(), task)),
180181
e);
181182
}
182183
}

src/main/java/com/veertu/plugin/anka/AnkaCloudComputerListener.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ public void onLaunchFailure(Computer c, TaskListener taskListener) throws IOExce
2727
if (c instanceof AnkaCloudComputer) {
2828
AnkaCloudComputer computer = (AnkaCloudComputer)c;
2929
if (c.isLaunchSupported()) {
30-
LOGGER.log(Level.INFO, "Computer {0}, instance {1} failed to launch, terminating",
30+
LOGGER.log(Level.INFO, AnkaLog.prefix("Computer {0}, instance {1} failed to launch, terminating"),
3131
new Object[]{computer.getName(), computer.getVMId()});
3232
computer.terminate();
3333
}
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
package com.veertu.plugin.anka;
2+
3+
final class AnkaLog {
4+
private static final String PREFIX = "[Anka] ";
5+
6+
private AnkaLog() {
7+
}
8+
9+
static String prefix(String message) {
10+
if (message == null || message.startsWith(PREFIX)) {
11+
return message;
12+
}
13+
return PREFIX + message;
14+
}
15+
}

src/main/java/com/veertu/plugin/anka/AnkaMgmtCloud.java

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -86,6 +86,7 @@ private static void InternalLog(Slave slave, SlaveComputer slaveComputer, TaskLi
8686
if (slave != null) s = String.format("[%s] ", slave.getNodeName());
8787
if (slaveComputer != null) s = String.format("[%s] ", slaveComputer.getName());
8888
s = s + String.format(format, args);
89+
s = AnkaLog.prefix(s);
8990
s = s + "\n";
9091
if (listener != null) listener.getLogger().print(s);
9192
MgmtLogger.log(Level.INFO, s);
@@ -510,6 +511,8 @@ public Collection<NodeProvisioner.PlannedNode> provision(CloudState state, int e
510511
if (cloudCapacity > 0) {
511512
int allowedCloudCapacity = cloudCapacity - nodeCount.numNodes;
512513
if (allowedCloudCapacity <= 0) {
514+
Log("Skipping provisioning for label '%s': cloud capacity reached (%d/%d active nodes)",
515+
label, nodeCount.numNodes, cloudCapacity);
513516
return plannedNodes;
514517
}
515518
if (number > allowedCloudCapacity) {
@@ -519,6 +522,8 @@ public Collection<NodeProvisioner.PlannedNode> provision(CloudState state, int e
519522
if (t.getInstanceCapacity() > 0) {
520523
int allowedTemplateCapacity = t.getInstanceCapacity() - nodeCount.numNodesPerLabel;
521524
if (allowedTemplateCapacity <= 0) {
525+
Log("Skipping provisioning for label '%s': template capacity reached (%d/%d active nodes for template '%s')",
526+
label, nodeCount.numNodesPerLabel, t.getInstanceCapacity(), t.getDisplayName());
522527
return plannedNodes;
523528
}
524529
if (number > allowedTemplateCapacity) {
@@ -655,12 +660,19 @@ public boolean canProvision(CloudState state) {
655660
Label label = state.getLabel();
656661
AnkaCloudSlaveTemplate template = getTemplate(label);
657662
if (template == null) {
663+
Log("Cannot provision label '%s': no matching Anka template found in cloud '%s'", label, getCloudName());
658664
return false;
659665
}
660666
int cloudCapacity = getCloudCapacity();
661667
if (template.getInstanceCapacity() > 0 || cloudCapacity >= 0) {
662668
NodeCountResponse countResponse = getNumOfRunningNodesPerLabel(label);
663-
if ((cloudCapacity >= 0 && countResponse.numNodes >= cloudCapacity) || (template.getInstanceCapacity() > 0 && countResponse.numNodesPerLabel >= template.getInstanceCapacity())) {
669+
if (cloudCapacity >= 0 && countResponse.numNodes >= cloudCapacity) {
670+
Log("Cannot provision label '%s': cloud capacity reached (%d/%d active nodes)", label, countResponse.numNodes, cloudCapacity);
671+
return false;
672+
}
673+
if (template.getInstanceCapacity() > 0 && countResponse.numNodesPerLabel >= template.getInstanceCapacity()) {
674+
Log("Cannot provision label '%s': template capacity reached (%d/%d active nodes for template '%s')",
675+
label, countResponse.numNodesPerLabel, template.getInstanceCapacity(), template.getDisplayName());
664676
return false;
665677
}
666678
}

src/main/java/com/veertu/plugin/anka/AnkaPlannedNodeCreator.java

Lines changed: 22 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,6 @@
77
import hudson.model.Node;
88
import hudson.slaves.NodeProvisioner;
99

10-
import java.util.concurrent.Callable;
1110
import java.util.concurrent.TimeUnit;
1211
import java.util.logging.Level;
1312
import java.util.logging.Logger;
@@ -24,24 +23,38 @@ public class AnkaPlannedNodeCreator {
2423

2524
public static NodeProvisioner.PlannedNode createPlannedNode(final AnkaMgmtCloud cloud, final AnkaCloudSlaveTemplate template, final AbstractAnkaSlave slave) {
2625
return new NodeProvisioner.PlannedNode(template.getDisplayName(),
27-
Computer.threadPoolForRemoting.submit(new Callable<Node>() {
28-
29-
30-
public Node call() throws Exception {
26+
Computer.threadPoolForRemoting.submit(() -> {
27+
try {
3128
return waitAndConnect(cloud, template, slave);
29+
} catch (InterruptedException interruptedException) {
30+
terminateProvisioningInstance(cloud, slave, interruptedException);
31+
Thread.currentThread().interrupt();
32+
return null;
3233
}
3334
})
3435
, template.getNumberOfExecutors());
3536
}
3637

38+
private static void terminateProvisioningInstance(AnkaMgmtCloud cloud, AbstractAnkaSlave slave, InterruptedException interruptedException) {
39+
String instanceId = slave.getInstanceId();
40+
LOGGER.log(Level.WARNING, AnkaLog.prefix("Provisioning interrupted for instance {0}, sending termination"), instanceId);
41+
try {
42+
cloud.terminateVMInstance(instanceId, slave);
43+
} catch (AnkaMgmtException terminateError) {
44+
LOGGER.log(Level.WARNING, AnkaLog.prefix("Failed to terminate interrupted instance " + instanceId), terminateError);
45+
} finally {
46+
LOGGER.log(Level.FINE, AnkaLog.prefix("Provisioning interruption stacktrace for instance " + instanceId), interruptedException);
47+
}
48+
}
49+
3750
public static Node waitAndConnect(final AnkaMgmtCloud cloud, final AnkaCloudSlaveTemplate template, final AbstractAnkaSlave slave) throws AnkaMgmtException, InterruptedException {
3851
final long timeStarted = System.currentTimeMillis();
3952
while (true) {
4053
String instanceId = slave.getInstanceId();
4154
int vmCheckTime = cloud.getVmPollTime();
4255
AnkaVmInstance instance = cloud.showInstance(instanceId);
4356
if (instance == null) {
44-
LOGGER.log(Level.WARNING, "instance `{0}` not found in cloud {1}. Terminate provisioning ",
57+
LOGGER.log(Level.WARNING, AnkaLog.prefix("instance `{0}` not found in cloud {1}. Terminate provisioning "),
4558
new Object[]{instanceId, cloud.getCloudName()});
4659
return null;
4760
}
@@ -83,10 +96,10 @@ public static Node waitAndConnect(final AnkaMgmtCloud cloud, final AnkaCloudSlav
8396
final long sinceStarted = System.currentTimeMillis() - timeStarted;
8497
int schedulingTimeout = template.getSchedulingTimeout();
8598
long schedulingTimeoutMillis = TimeUnit.SECONDS.toMillis(schedulingTimeout);
86-
LOGGER.log(Level.FINE,"Instance {0} is scheduling for {1} seconds",
99+
LOGGER.log(Level.FINE, AnkaLog.prefix("Instance {0} is scheduling for {1} seconds"),
87100
new Object[]{instanceId, sinceStarted / 1000});
88101
if (sinceStarted > schedulingTimeoutMillis) {
89-
LOGGER.log(Level.WARNING,"Instance {0} reached it's scheduling timeout of {1} seconds, terminating provisioning",
102+
LOGGER.log(Level.WARNING, AnkaLog.prefix("Instance {0} reached it's scheduling timeout of {1} seconds, terminating provisioning"),
90103
new Object[]{instanceId, schedulingTimeout});
91104
cloud.terminateVMInstance(instanceId);
92105
return null;
@@ -96,7 +109,7 @@ public static Node waitAndConnect(final AnkaMgmtCloud cloud, final AnkaCloudSlav
96109
}
97110

98111
if (instance.isTerminatingOrTerminated() || instance.isInError()) {
99-
LOGGER.log(Level.WARNING,"Instance {0} is in unexpected state {1}",
112+
LOGGER.log(Level.WARNING, AnkaLog.prefix("Instance {0} is in unexpected state {1}"),
100113
new Object[]{instanceId, instance.getSessionState()});
101114
cloud.terminateVMInstance(instanceId);
102115
return null;

0 commit comments

Comments
 (0)