Run downstream jobs on same executor? - jenkins

I am working on tests of embedded devices.
We have a device farm where several types of devices (say A, B and C), with many instances each (A1..A10, B1..B10, C1..C10), are available for remote testing. Each device is connected to a Jenkins node (with label 'A', 'B' or 'C'). So far, if we wanted to test systems of devices (A, B and C working together), they were connected to many Jenkins nodes ("multi-node setup") which had to be addressed individually.
Now we would like to replace these with single-node setups (all embedded devices A, B, C controlled by the same node). The current job structure involved reserving all nodes from a given multi-node setup on a high level and then calling different jobs one by one which then run on the respective node.
For reasons of maintainability and clear responsibility, I would like to retain the structure of several sub-jobs for given test.
My problem is now that the top-level job chooses any of the single-node setups, but of course all downstream sub-jobs need to run on that exact instance, which I can assure by passing the NODE_NAME of the top-level job as parameter. Unfortunately, since I should never have two (top-level) jobs running on a same instance in parallel, I can only define one executor per node. Which, in turn, means that a downstream job supposed to run on the same node as the top-level job will always wait for the executor to become available infinitely.
TL;DR: Is there a way to allow a downstream job to "reuse" an executor from an upstream job?
I am perfectly ok with "No, there isn't", but it would make managing our tests easier if there were. Otherwise I'll just have to roll all jobs into one big one.

Related

How to run a Jenkins job in an available agent

I have a Jenkins master and two agents. However the connectivity to one agent(agentA) is bit shaky and I want to use the other agent(agentB) when the connectivity to the first one is not available.
I am only using the Jenkins web interface and have not used scripts. I am trying to figure out how it can be done using the "Restrict where this project can be run" option in job's configuration. I tried using agentA|| agentB but when agentA is not available it hangs saying "pending - agentA is offline"
Is it possible to have a configuration to achieve what I need?
I can;t leave it blank because I have other agent (agentC, agentD) which do not want this job to run in.
I am not an admin of the Jenkins server, hence adding new plugins is not my preferred option but it can be done.
As noted in Least Load plugin,
By default Jenkins tries to allocate a jobs to the last node is was executed on. This can result in nodes being left idle while other nodes are overloaded.
As you generalized the example, I'm not 100% sure if your situation can be solved by simply better labelling of your nodes or you want to look at least load plugin (it is designed for balancing the load across nodes). Your example appears to show Node names (ie; agentA/agentB). The Queue allocation logic may be "Only A or Only B", then Jenkins sticks to it. Load balancing may not address that as while a Node (a Computer) name is also a label, it may have additional logic tied to it.
If you label the pair of nodes in a pool with a common label, say "CapabilityA", and constrain your jobs to run where "CapabilityA" rather than the node names, you may find jobs float across the pool (to B if A is not available. That's how we have our nodes labelled - by Capability, and we see jobs floating across nodes, but only once the first node is full (4 executors each), so not balanced.
Nodes can have many labels and you can use label conditions to have complex constraints.

Only allow one job on a machine

The way we're using Jenkins requires us to have two nodes defined for each machine. One Jenkins node runs as a normal user (called Normal), and the other runs as the administrator (called Admin). So they show up as two separate nodes, even though they exist on the same slave machine.
But, we're running into a concurrency problem. Because our job switches between the two nodes, there is a possibility of another job (Job B) being assigned to (for example) the Normal node, while the Admin node is working on its part of (e.g.) Job A.
Is there a way to tell Jenkins that if either the Normal node or the Admin node of a machine is being used, then it should NOT give the other node some other job?
To elaborate on this question--we have a test suite that we currently run serially. All of our Jenkins masters have multiple slaves, so naturally we would like to take advantage of parallelization, so the suite doesn't spent 2 hours using one machine while the other ones sit idle. So it's not really a matter of ensuring only one job runs at once, it really is a matter of telling Jenkins not to use a node when its partner node is busy.
The issue is not related to two nodes on the same machine or one privileged or not; it's a matter of blocking one job from running while the other is still running.
I trust you are using labels to restrict what jobs can run on what nodes
You can use Build Blocker plugin to block the job from running while others are . There are other plugin options which may work for you as well.
You can also use the Paramterized Trigger to in-line the execution of the other job. It can be run as a build step or a post-build step.
You can also restrict the number of executors on a given node via ${JENKINS_URL}/computer/myNode/configure | # of executors, so you don't run multiple jobs one the same node if that's an issue.
Here's the way I solved this problem:
Set the number of executors on each slave node to 1.
Force my job to take an executor for the whole length of the job.
Specifically, in the groovy script that we use for all our jobs, at the very top, after we find which two (admin and normal, running on the same slave) nodes we need, we use the following:
n
node(myNormalNode)
{
//all the rest of the job, including:
node(myAdminNode)
{
//other commands for the admin node
}
//back to commands for the normal node
node('master')
{
//code to run on master
}
//and so forth
}
This makes Jenkins not assign any other jobs to this computer until the first job is done.

Jenkins grouping of nodes via label on demand

I have a scenario where I have N numbers of nodes and N number of tests, and these tests will be distributed to the nodes. My nodes have a label Windows.
Here's an example:
I have a pipeline job that will manage the distribution of the tests to the nodes. I set my pipeline job to run 10 tests on 10 VMs having the label Windows and it will run smoothly. However, one of my requirements is to concurrently run that pipeline job. The problem I might encounter If I have 10 tests on VMs 1-10 in the first run of the job, and run another job for 5 tests for VMs 11-15, given that I am using the Windows label, there might be a possibility that Jenkins will assign the test to VMs 1-10 but should run on VMs 11-15 or vice versa.
The solution I came up with is to dynamically change the label of the VMs from one of the jobs to a unique label that will only be used for that Job. Unfortunately, I still don't know how to do that.
Basically, I just want to logically group my nodes via label on demand in my pipeline script.
I searched all throughout the internet and yet I still wasn't able to find a solution that fits my needs.
Kindly help me with this. Also, I am open to using a different approach.

Massive-Distributed Parallel Execution of tasks

We are currently struggling with the following task. We need to run a windows application (single instance only working) 1000 times with different input parameters. One run of this application can take up to multiple hours. It feels like we have the same problem like any video rendering farm – each picture of a video should be calculated independently and parallel – but it is not rendering.
Currently we tried to execute it with Jenkins and Pipeline jobs. We used the parallel steps in pipeline and lets Jenkins queue and execute the application. We use the Jenkins Label Expression to lets Jenkins choose which job can be run on which node.
The limitation in Jenkins is currently with massive parallel jobs (https://issues.jenkins-ci.org/browse/JENKINS-47724). When the queue contains multiple hundred jobs adding new jobs took much longer – will become even worse by increasing queue. And main problem: Jenkins will start the execution of parallel pipeline part-jobs only after finishing adding all to the queue.
We already investigated ideas how to solve this problem:
Python Distributed: https://distributed.readthedocs.io/en/latest/
a. For single functions it looks great, but for the complete run like we have in Jenkins => Deploy and collect results looks complex
b. Client->Server bidirectional communication needed – no chance to bring it online through a NAT (VM Server)
BOINC: https://boinc.berkeley.edu/
a. for our understanding we had to extend the backend in a massive way to bring our jobs working => to configure the jobs in BOINC we had to write a lot of new automating code
b. currently we need a predeployed application which can differ between different inputs => no equivalent of Jenkins Label Expression
Any ideas how to solve it?
Thanks in advance

Deactivate jenkins job while other is running

Is it possible to block a certain jenkins job while another one is running as some sort of condition?
I would like job "A" to be disabled while job "B" is running, and once job "B" is done, then job "A" should be available again.
I have read that it is possible to block upstream jobs when the jobs are part of a flow and the flow is running, but I would like to know if it s possible for 2 completely independent jobs.
Use this Build Blocker Jenkins Plugin.
You can block A in job B's config. As long as 'A' is running, 'B' would not run.
You can block Both A & B in B's config, thus B would run only no other As or Bs are running.
Additionally, You can block B in A's config, they will block each other.
*job names are case sensitivity
You can use the Throttle Concurrent Builds Plugin to do this.
You're going to want to:
create a category for the two jobs in the Jenkins global
configuration.
In each build check the Throttle Concurrent Builds
option.
Choose Throttle this project as part of one or more
categories.
Set Maximum Total Concurrent Builds (and Maximum
Concurrent Builds per Node if applicable) to 1
Check the category box to mark the job as part of the category.
This will limit either job from running while the other one runs, so if Job A is running then B won't start, and if Job B is running than A won't start.

Resources