Skip to end of metadata
Go to start of metadata

Plugin Information

View Lockable Resources on the plugin site for more information.

Older versions of this plugin may not be safe to use. Please review the following warnings before using an older version:

This plugin allows to define lockable resources (such as printers, phones, computers, etc.) that can be used by builds. If a build requires an resource which is already locked, it will wait for the resource to be free. One can define a lock-priority globally and on a per-job basis.

Quick usage guide

  • Install the plugin
  • In Manage Jenkins > Configure System go to Lockable Resources Manager   
    • Select Add Lockable Resource    

      Brief description of the named fields:

      • Name - A name (not containing spaces!) for this particular resource, i.e. DK_Printers.
      • Description - A verbose description of this particular resource, i.e.Printers in the Danish Office
      • Labels - Space separated list of Labels (Not containing spaces) used to identify a pool of resources. i.e. DK_Printers_Office   DK_Printer_Production   DK_Printer_Engineering
      • Reserved by - If anything is written here, the resource will be taken and therefore unavailable for other jobs. i.e. All printers are currently not available due to maintenance.
  • In Jenkins > <job name> >  Configure > General

    Brief description of the named fields:

    • Resources - The name or names of resources needed. In this example, DK_Printers will select all of the three printers in the pool.
    • Label - One or more Labels to select resources. In this example, DK_Printer_Production   DK_Printer_Engineering will select two labeled printers in the larger pool.

  • Start a build.
    • Under build #<number> select  Locked Resources 
    • You should see something like:This build has locked the following resources: <resource_name> - <resource description>
  • Start a different build which uses the same resource. * You will see *Build Queue in Jenkins status/menu showing job name
    • Hover text shows Started <by>, Waiting for resources <resources list>, Waiting for <time>

Pipeline usage

  • When the lock step is used in a Pipeline, if the resource to be locked isn't already defined in the Jenkins global configuration, it'll be set up automatically.
  • The arguments to the lock step are:
    • resource - The resource name to lock as defined in Global settings. If inversePrecedence isn't also specified, the step can be called as lock('some-resource') without the named argument.
    • label - can be used to require lock on multiple resources concurrently. The build will wait until all resources tagged with the given label are available. Only this or resource can be used simultaneously.
    • quantity - (optional) specifies the number of resources required within the selected label. If not set, all resources from the label will be required.
    • inversePrecedence - (optional) By default waiting builds get the lock in the same order they requested to acquire it. If inversePrecedence is set to true, this will be done in reverse order instead, so that the newest build to request the lock will be granted it first.
  • Examples:

    echo 'Starting'
    lock('my-resource-name') {
      echo 'Do something here that requires unique access to the resource'
      // any other build will wait until the one locking the resource leaves this block
    }
    echo 'Finish'
    
    lock(resource: 'staging-server', inversePrecedence: true) {
        node {
            servers.deploy 'staging'
        }
        input message: "Does ${jettyUrl}staging/ look good?"
    }
    
    lock(label: 'test-farm') {
        parallel test1: {
            node('farm-server-linux') {
                sh './run-tests.sh'
            }
        },
        test2: {
            node('farm-server-windows') {
                sh './run-tests.bat'
            }
        }
    }
    

Changelog

 

Release 2.3 (2018-6-26)

  • JENKINS-34433 - Signal queued Pipeline tasks on unreserve

  • Allow locking multiple resources in Pipeline

Release 2.2 (2018-3-6)

  • JENKINS-40997 - New configuration option to get the name of the locked resource inside the lock block (Pipeline).

  • JENKINS-49734 - Add a PauseAction to the build when waiting for locking, so Pipeline representations in the UI are correctly shown.
  • JENKINS-43574 - Fixed the "emtpy" resources lock (message: "acquired lock on []")

Release 2.1 (2017-11-13)

Release 1.11.2 (2017-3-15)

  • JENKINS-40368 - Locked resources are not always freed up on Pipeline hard kill when there are other pipelines waiting on the Resource

Release 1.11.1 (2017-2-20)

  • JENKINS-40879 - Locked areas are executed multiple times in parallel

Release 1.11 (2016-12-19)

Release 1.10 (2016-07-12)

  • JENKINS-36479 - properly clean up resources locked by hard-killed or deleted while in progress Pipeline builds.

Release 1.9 (2016-06-01)

  • Reserved resources parameter visibility in environment (related to SECURITY-170)

Release 1.8 (2016-04-14)

  • Pipeline compatibility: lock step

Release 1.2 (2014-02-05)

  • Manual reservation/un-reservation of resources now require specific permissions

Release 1.1 (2014-02-03)

  • Allow jobs to require a subset of specified resources (the number of required resources is configurable)
  • Allow manual reservation/un-reservation of resources

Release 1.0 (2013-12-12)

  • Initial release

50 Comments

  1. Could you please add some more information? Some pictures would be useful.

    In our project we have several network printers of different types and brands. A job needs ONE printer of a certain type. Would this be possible with your plugin? Pick one of a pool?

  2. The plugin is very similar to existing "Throttle Concurrent Builds", "Lock and Latches" and "Exclusion".

    Some info is definitely required. Probably it makes sense to merge new features to one of existing plugins

  3. Actually, this plugin does something that, as far as I can tell, no other plugin does: Create a pool (or pools) of resources that are not attached to specific slave nodes.

    One feature this plugin is missing: I need to be able to attach metadata to resources (like in the https://wiki.jenkins-ci.org/display/JENKINS/External+Resource+Dispatcher plugin) so I can expose the metadata back to the test script as environment variables.

    Kudos!

    1. You can pass the name of the acquired resource(s) into a variable and thus pass at least this piece of information to the job.  You can associate meta data to this name (or these names) on your own then.

  4. This plugin solved an existing issue in our project. Thanks!

    Request/Suggestion:

    As of now, a resource can only be released after a build is finished. Is it possible to release/unlock a resource in the middle of the build? Something like another build step that can be added (ex. additional option in "Add build step" menu).

    In our build jobs, the resource is only used at the start and then the build will continue for about 10-20 minutes.

    Other jobs will still have to wait for 10-20 minutes even though in reality the resource is already "free".

  5. More documentation definitely needed.

    This allows the admin to define several resources.  Then, in the job configuration, one specifies a pool (list of resources) and then indicates how many of those resources are needed to run. The job queues until sufficient resources are available. When sufficient resources become available, the job allocates those resources and proceeds, then frees the resources.

    There is a nifty little page that shows what is currently locked (allocated) and what is free. It also allows a resource to be reserved and therefore unavailable. If locked or reserved, it shows what job or individual, respectively, holds the resource.

    I think only one pool is available per job. But each job specification has it's own description of what constitutes the pool for that job. So, yes, I think it will do what was needed in the comment by Daniel Schneider.

    There does not appear to be any notion of a resource tree. (Unfortunately, this is what I need, so I'm not using it.)

  6. I'd have to agree with an above comment that this plugin "does something that, as far as I can tell, no other plugin does: Create a pool (or pools) of resources that are not attached to specific slave nodes"  Our group faced some problems in an early project a couple months ago with hardware routers that we dealt with but were looking to create something during down time that would address our needs.  Apparently we were a day late and a dollar short .. 

  7. Hi,

    I am testing this plugin. Is there a way to retrieve the name of the locked resource? Is there a global variable containing this value?

    Example I have two resources "resA" & "resB" both having the label "res". I lock the resources using the label. Now I want to know which one it is that I have locked.

    Is there a way to find this out?

    Best regards,

    Baubak

    1. Never mind discovered that the field "Reserved resources variable name" actually created a variable for the resource being used. Was expecting a default variable, and didn't think we needed to set it.

      Thanks anyway. The plugin is very useful. Thank you.

      Baubak

  8. Hi

    It would be good if you could create a profile to be shared by many resources. For example in the Config you define:

    1. 2 lockable resources R1 and R2 using the label R.
    2. You define a standard profile P that states that we use label R and only 1 resource in a variable RESOURCE

    In your jobs you only reference the profile P.

    Best regards,

    Baubak

  9. The plugin works just fine for us but seems a little limited to me.  Some suggestions for improvements I really would like to have (and consider adding them myself, in case I find the time):

    • Resources should have a quantizer.
      Currently I'm creating things like 32 resources of which each represents 1GB of ram (because I have 32GB of ram available to distribute among virtual machines).  Each task which needs to create such a virtual machine requires, depending on its needs, 4, 6 or more of these resources.  So several machines using 6 resources each (6GB) can run in parallel, or one using 20 resources and three using 4 etc.
      But to create 32 resources with the same label is a PITA; it never looks good, neither in the configuration nor on the overview of required resources etc.  If I could create one quantized resource RAM_IN_GB which has a quantization of 32, that would of course be much more convenient.
    • Jobs should be able to require more than one resource kind.
      I would like to have a project require, e. g. 16GB of ram and additionally a VM (a different kind of resource), and maybe a share of the CPU as well.
      Currently I only can achieve this by nesting projects (project A requires 16GB of ram, executes project B, and waits for its finishing; project B requires a VM and really does the job).  But this of course bloats up my project list and has so many other disadvantages I do not even want to start listing them here (job dependencies, build pipelines, …).
    • It would be nice to have more control over the acquirement of the resources.
      Currently, starting a build puts the build to sleep until all required resources are available, then it acquires the resources, then the build runs, and no matter how the build stops, then all resources are released at once and unconditionally.
      This is inconvenient in several cases. For example If a build running on a VM fails, often the VM is actually still running (because a pull-down-step didn't happen and shouldn't happen to ease debugging), so releasing the resource creates a schism (the model of the resource is freed, but the actual resource isn't free to be used by the next project).  I then run into instantaneous errors because the next project gets this resource, tries to use it and fails (because it isn't really available).
      1. It would be nice to be able to state on a project-config basis that a resource is not to be freed automatically when the build terminates.
      2. It would be nice to be able to acquire resources during the run of project (with a timeout, to be able to special-handle this situation).
    • How resources are distributed should be configurable.
      Currently, always the "topmost" available resource will be used. This means that if I have, e. g. three printers, one will have much more work than the other two.  It would be nice the be able to configure, e. g. a round-robin or a random method to achieve an equal load on all resources.
  10. Using it to run certification jobs that use pools of external resources and to maintain these resources using ElasticAxis. Require certain modifications to plugin, however. Here's an explanation how to manage the pools and do certification testing: PDF on github

  11. This is a fantastic plugin which really does have something many others don't.  This plugin allows you to manage pools of resources (For me, this is pricey systems which must be a part of our test cycle) and allocate them to jobs as they run.  If none are available, it will block the job until one frees up.  If someone were to continue development on this, or extend it in another plugin, I'd be very happy.   Ideally, I'd love:

    • Some sort of API allowing me within my own test code to request/release systems, so that people running tasks outside of jenkins can make use of the same pool.   Maybe this can be part of the jenkins REST api, or maybe it already is, and it simply isn't documented.
    • Ability to use more resources if they are available.  For example, my test must always run on 1 system.  However, if I can programatically know that 3 are available, I can take 2 systems instead, leaving one for the queue, and still enable my job to run faster/run more tests.

    Really well done to the author and I hope you will continue development of this plugin. 

    1. @Phil Schaechter: You can actually reserve/unreserve a resource by calling the following URL: 

      http://jenkins:8080/lockable-resources/reserve?resource=YOUR_RESOURCE_NAME

      http://jenkins:8080/lockable-resources/unreserve?resource=YOUR_RESOURCE_NAME

      It would be great if the authors documented this and allowed even more API calls.

    2. You can also use:
      http://your-jenkins/plugin/lockable-resources/api/json
      to get a list of all lockable resources including reservation status.

      This is also not documented and I had to search the source code to find it (see https://github.com/jenkinsci/lockable-resources-plugin/commit/ecd0332f404538d37eefbe878c6ae74c9584f5ec)

  12. Is it possible to send lockable resource name as a parameter to job? Assume that valid resource is sent as parameter.

    Thanks,

    Yogesh

    1. I would like this as well, the ability to use a build parameter as the resource name, versus hard coding the name. For example, we have a collection of jobs that can each run on a set of servers, and we want the server to be our resource.  While we might be able to use a resource pool for this, there are times when we want to manually trigger a build and select the server from a choice build parameter, and have the job grab that as the resource. So if build parameter "TEST_SYSTEM" has the FQDN where we want to run the test, we could specify "${TEST_SYSTEM}" (w/o the quotes of course) as the resource, and on the fly it would get resolved to the FQDN value in TEST_SYSTEM.  That would be very handy.

      1. +1 I am also looking into using build parameters for a lock.
        I use a build parameter to choose on which hardware server to run my tests, and I cannot find a way yet to lock the hardware so 2 jobs don't clash.

  13. Being able to use a build variable from a build parameter for the label would be very useful as well.

  14. Is it possible to allocate different kinds of resources in one build (resources with different label)?

  15. When using this in a pipeiline, if a resource is locked, is there an easy way to find out which running job has that lock?

  16. Great plugin - so simple and effective.

    Could you make the Lockable Resources Manager on the Configure System page collapsible. We have dozens of resources and this makes the config page very large!

  17. Does the current version work as expected when used in a free-flow job?

    I set up a small test scenario to play with, and it seems like waiting for resources works, but not waiting for Labels.

    Edit: Added to Jenkins JIRA as JENKINS-44388. 

    Edit 2. Closed as "not an error". The documentation in the plugin has been updated, although the description on this page still needs some cleanup.

     

    My tests below:

    I used a resource named TEST, with two labels TEST_1 and TEST_2.
    Looking at the available resources, it's reported that I have the "TEST" resource, and one instance of the two labels - as expected.

    In a free-flow job, I enable This build requires lockable resources, and the tested the following four setups:


    Trial 1
    Resources = TEST
    Number of resources to request = 0

    Expectation: The resource TEST and all labels consumed during the test.

    On execution:
    The test project does not wait for anything.
    None of the resources nor labels are reported used.
    Note: This might be correct behaviour - provided 0 is used literal, unlike documented in the plugin: "empty value or 0 means all "


    Trial 2
    Resources = "TEST"
    Number of resources to request = 1

    Expectation: All labels on the TEST resource will be consumed.

    On execution:
    The test project does wait for the TEST resource and does consume all Labels.

     

    Trial 3
    Lable = "TEST_1"
    Number of resources to request = 0

    Expectation: The TEST_1 label will be consumed, leaving "TEST_2" available.

    On execution:
    The test project does not wait for anything.
    None of the resources nor labels are reported used.
    Note: This might be correct behaviour - provided 0 is used literal, unlike documented in the plugin: "empty value or 0 means all "


    Trial 4
    Lable = "TEST_1"
    Number of resources to request = 1

    Expectation: The TEST_1 label will be consumed, leaving "TEST_2" available.

    On execution:
    The test project does not wait for anything.
    None of the resources nor labels are reported used.

    Trial 4 is the error I'm really concerned about, as it seems to indicate that only resources can be taken, and not labels.

     

    Tested on Plugin release 2.0 @ Jenkins 2.57

  18. I wrote this question on StackOverflow (direct link), but for completeness I'm also including it here.

    Edit: Added to Jenkins JIRA as JENKINS-44389

    Edit 2: Closed as fixed. It's now possible to use Groovy from freestyle jobs, and get the expected result.

    tl;dr,  More documentation for this plugin is certainly needed. This comment may shed some light on how some things are working - but it also showcases some things that are apparently not working!

     

    I'm was initially attempting to get the Lockable Resources Plugin to lock on a specific resource while also evaluation the value of a system environment variable.
    Evaluation the system environment variable is working perfectly, however, I can't seem to get a lock on the correct resource.

    This question focused on the specific locking problem!

    I have created a three resources called A_TESTB_TEST and C_TEST. None of them have any Labels. They are all visible from my Jenkins_URL/lockable-resources/ where they can be taken and released without problems.

    In my Jenkins Job configuration, I have selected the This build requires lockable resources option, which allows me to specify a ResourceLabel or Groovy Expression (and Additional classpath). It additionally allows me to specify Reserved resources variable name and Number of resources to request.

    According to the documentation, the Groovy script must return a boolean value, so I determined to try it out:

    Test 1

    The first test I did was to verify the basic functionality, by setting the following:

    • Resource = B_TEST
    • Groovy Expression = Not checked
    • Number of resources to request = 1

    This results in the job executing with a lock on the B_TEST resource. The console output reads:

    [lockable-resources] acquired lock on [B_TEST]

    Test 2

    In this test I set the following:

    • Resource = B_TEST
    • Groovy Expression = Checked
    • Groovy Script = return false
    • Number of resources to request = 1

    When attempting to execute the job, this wrongly waits forever with the text: (pending--Waiting for the resourced [B_TEST])

    Test 3

    In this test I set the following:

    • Resource = B_TEST
    • Groovy Expression = Checked
    • Groovy Script = return true
    • Number of resources to request = 1

    This results in the wrong resource A_TEST to be locked. The console output reads:

    [lockable-resources] acquired lock on [A_TEST]

    Test 4

    After rereading the help for each option in the plugin, I discovered that the plugin apparently only allows me to specify either a ResourceLabel or Groovy Expression So in this test I set the following:

    • Groovy Expression = Checked
    • Groovy Script = return false
    • Reserved resources variable name = MyResourceName

    This results in the job executing wrongly without a lock on any resource. The console output reads:

    [lockable-resources] acquired lock on []

    Test 5

    So in this test I set the following:

    • Groovy Expression = Checked
    • Groovy Script = return true
    • Reserved resources variable name = MyResourceName

    This results in the job wrongly locking on all resource. The console output reads:

    [lockable-resources] acquired lock on [A_TEST, B_TEST, C_TEST]

    Test 6

    According to the documentation of the plugin, in Jenkins-Pipelines this plugin can be used as this:

    echo 'Starting'
    lock('my-resource-name') {
    echo 'Do something here that requires unique access to the resource'
    // any other build will wait until the one locking the resource leaves this block 
    }
    echo
    'Finish'

    so I started experimenting with the Groovy Script containing variations of the lock('B_TEST') call, but this mostly lead to more confusion and errors while the job attempted to start, such as this:

    No signature of method: Script1.lock() is applicable for argument types: (java.util.LinkedHashMap) values: [[resource:B_TEST]] Possible solutions: each(groovy.lang.Closure), wait(), run(), run(), any(), find())

    But I guess this all makes good sense, as the lock(){ } call seems suited to take and release the lock only during its capture.

    The Question

    The big question now is, how does all of this actually work? My guess is that somewhere there's a groovy command to specify the Resources/Labels you want to reserve, and the return value (true/false) determines to actually take the lock or not. I have attempted to dive into the source, but didn't have any luck.

    Any answer is greatly appreciated.

  19. Is it possible to pick and lock an available resource from the pool (any would do - so following the example in documentation, say I want some printer, don't care which one - but exclusively dedicated for this job run)?

  20. If a job selects a resource by label, the console output has a message saying "acquiring lock on [resourcename]".

    But if it selects a resource explicitly by name, the message is "acquiring lock on []", without the name. it would be helpful if it could include the name in this case too.

  21. I have a job that only wants to lock under certain conditions. When I want to bypass the lock, I pass in a lockname of ''.

    This works, but it prints this in the console :

    Trying to acquire lock on [[no resource/label specified - probably a bug]]

    This is fine, But, it would be nice if there were a way to explicitly disable the lock so that the console wouldn't have to report a non-bug.

    I am thinking something like this:

    LOCKDISABLED = true
    
    if (condition) { LOCKDISABLED = true }
    
    lock(resource 'myresource', disabled: LOCKDISABLED )
    {
    // stuff
    }
    1. @Ken Lamb You can do the following for your usecase I believe : 

      String checkCondition(def resource=''){
      	if(resource == 'myresource') {
      		return resource
      	}else {
      		return JOB_NAME
      	}
      }
      
      //Examples of usage with lock step
      lock(resource: checkCondition('myresource')) {
      	println "The regular stuff"// stuff
      }
      lock(resource: checkCondition()) {
      	println "The real stuff"// stuff
      }
      1. Thank you for the suggestion. I ended up using something very similar to this.

  22. I have a set of jobs which want to acquire lock on a resource "xyz". I want one of the job to have high priority while trying to acquiring the lock. How can I achieve this.
    I noticed that some code was removed in 2015 that was adding a priority based lock precedence.

    In my case default and inverse precedence do not help
    Is it possible to edit the resource queue dynamically to move the high priority request to the front of queue?

  23. Thank you very much for this plugin.It is a very useful plugin

    Is there anyway to get the utilisation of resources?. Basically I need to plan for adding more resources based on the usage of a particular label.

  24. Is it possible to require a resource with zero quantity?

    Here is why this would be extremely useful: I want to use resource locking to prevent running jobs when some external services  are down. Mainly we do lock/unlock one resource with the name of the service, via a script or manually using Jenkins UI.

    Now jobs should not run while the resource is locked but we do not want them to lock any resource as we want to allow them to run in parallel. This translates to a job which waits for a lock but does not reserve anything while running.

    Does this work or not?

  25. How to get locked resource(s) name(s) when using lock from a pipeline?

    I need to start a process and pass reserved name as a parameter 

    1. Hello, the usual usage of the plugin is to lock by label - e.g. that you want any instance of the labeled resource(s), such as "some printer" following the example above.

      It is possible to grab a specific resource by name, but this probably requires to process locking with Evaluate as a Groovy script. See https://github.com/jenkinsci/lockable-resources-plugin/pull/72 and https://github.com/jenkinsci/lockable-resources-plugin/issues/73 for more details on my solution to this (I hope relevant code for plugin is already in upstream binaries).

      1. I do need to reserve by label, get the reserved resource name, and then use it. Here is my use case:

        1. Reserve a VM from a pool (by label)
        2. Perform some tests on the selected VM: run a script that accepts VM name as a parameter
        3. Release the VM

        Is it possible?

        1. Did you have time to read issue #73 linked above?

          It is about nearly same use-case, complete with sample code from our approach to making it work. Now, we did this in freestyle jobs so far, but I see little reason that those groovy script snippets could not be stuffed into pipeline (maybe not the simpler "declarative" one though).

          Note this needs interplay of several plugins: a build of Lockable Resources with PR#72 included, so it can process build args and their values (as we pass them with the label of the type of resource, or name of specific resource we want to test against - that code in Evaluate Groovy discerns the difference); and the EnvInject plugin to get the ultimately chosen name of a locked resource instance back from groovy variables to shell variables that we can use in Shell script steps - e.g. to reflash a particular testbed hostname - as well as to forward into spawned sub-jobs.

          Hope this helps,
          Jim Klimov

          1. Hi Klimov,

            Your answer is very complex for a common user to make sense.

            Also the status of plugin - does it contain needed fixes #72 #73 ? 

            I hope please you can clarify in a bit simpler way.

          2. I did looked #72 and #73 and could not find that they help. IMO Release 2.2 fully answers my question. When can I expect it to be delivered? According to the log, it should be available, but it's not

            1. It is available and I installed already on Jenkins.

  26. A try to lock a resource from a pipeline is never satisfied if resource is not available when pipeline starts. Is it a known issue?

    Steps to reproduce:

    1. reserve all resources with LABEL
    2. Start a pipeline pointing to 1 resource with LABEL
    3. release resource(s) with LABEL

    Expected result:

         A resource is reserved and pipeline continues working

    Actual behavior:

        Pipeline keeps waiting for a resource while it's available

    Started by user Vadim Sluzky
    [Pipeline] lock Trying to acquire lock on [Label: Win81, Quantity: 1]
    Found 0 available resource(s). Waiting for correct amount: 1.
    [Label: Win81, Quantity: 1] is locked, waiting...
    
    1. From log, it looks like it is working as it should (I see that per your detailed description it apparently does not): You have one defined resource with label "Win81" and it is already occupied by someone else; this job will stay in queue until it gets free, so this one can grab that resource.

      Can you look into `jenkins.log` on the master server? Every few seconds there should be log messages from this plugin evaluating resources it is waiting for - maybe that would uncover what else went wrong?..

      I did not yet use it from pipeline context, but in our older freestyle jobs (and with evaluation as Groovy script per my earlier comment above) it works as expected - so a few seconds after a resource gets released (manually Unreserved, or a job that used it has ended) the plugin discovers the change of state, and another queued job gets and grabs it.

      1. Thank you for looking into the issue, Jim.

        For some unknown reason the issue was not reproduced today (smile)

        If that happens again, which jenkins.log file should I look for?  

        1. On master instance, ${JENKINS_HOME}/logs/jenkins.log IIRC.

          1. I face that problem again with a Freestyle project.

            Here's the history:

            I created a few lockable resources, created jobs that reserved 1 resource per label and worked with them for a while

            Then I updated lockable resources and the jobs.

            Now reservation works only by resource, not by label

            If I don't specify number of requested resources per label, the locked resource is empty

            If I specify 1 requested resource per label, it waits forever

            ${JENKINS_HOME}/logs/jenkins.log does not expose any lockable resource info.


            I tried to restart Jenkins - did not help

            Uninstall and reinstall Lockable Plugin (the lockable resources were not removed; I reused them) - did not help  


  27. Hi Developer,

    Could you please update plugin-details / help / Examples, so that user gets to know about what is new in version 2.2 ?

  28. I found a bug: Locked variable is assigned only to one of threads during parallel execution.

    Below is a simple pipeline script that displays the problem.

    It starts 3 threads in parallel each locking a resource by label. I specified a single available resource with this label.

    The locked resource should be assigned to a variable, but it is assigned only once in the first executed thread.

    Here is the script to reproduce the problem:

    node('slave') {
        def execs = [:]
        execs[1] = {
            lock(label: 'Win81x64Pool', quantity: 1, variable: "MY_VAR") {
                println "LOCKED=" + env.MY_VAR
                sleep(3)
           }
        }
        execs[2] = {
            lock(label: 'Win81x64Pool', quantity: 1, variable: "MY_VAR") {
                println "LOCKED=" + env.MY_VAR
                sleep(3)
            }
        }
        execs[3] = {
            lock(label: 'Win81x64Pool', quantity: 1, variable: "YOUR_VAR") {
                println "LOCKED=" + env.YOUR_VAR
                sleep(3)
            }
        }
        parallel execs
    }

    and here is an exempt from console output. Please note that LOCKED=null for second and third threads

    [1] Lock acquired on [Label: Win81x64Pool, Quantity: 1]
    [Pipeline] [1] { [Pipeline] [2] lock [2] Trying to acquire lock on [Label: Win81x64Pool, Quantity: 1]
    [2] Found 0 available resource(s). Waiting for correct amount: 1.
    [2] [Label: Win81x64Pool, Quantity: 1] is locked, waiting...
    [Pipeline] [3] lock [3] Trying to acquire lock on [Label: Win81x64Pool, Quantity: 1]
    [3] Found 0 available resource(s). Waiting for correct amount: 1.
    [3] [Label: Win81x64Pool, Quantity: 1] is locked, waiting...
    [Pipeline] [1] echo [1] LOCKED=Win81x64
    [Pipeline] [1] sleep [1] Sleeping for 3 sec
    [2] Lock acquired on [Label: Win81x64Pool, Quantity: 1]
    [Pipeline] [1] } [1] Lock released on resource [Label: Win81x64Pool, Quantity: 1]
    [Pipeline] [2] { [Pipeline] [1] // lock [Pipeline] [1] } [Pipeline] [2] echo [2] LOCKED=null
    [Pipeline] [2] sleep [2] Sleeping for 3 sec
    [3] Lock acquired on [Label: Win81x64Pool, Quantity: 1]
    [Pipeline] [2] } [2] Lock released on resource [Label: Win81x64Pool, Quantity: 1]
    [Pipeline] [3] { [Pipeline] [2] // lock [Pipeline] [2] } [Pipeline] [3] echo [3] LOCKED=null
    [Pipeline] [3] sleep [3] Sleeping for 3 sec
    [Pipeline] [3] } [3] Lock released on resource [Label: Win81x64Pool, Quantity: 1]
    [Pipeline] [3] // lock [Pipeline] [3] } [Pipeline] // parallel [Pipeline] } [Pipeline] // node [Pipeline] End of Pipeline Finished: SUCCESS
  29. Hi, I have a question, I'm trying to use the plugin with Declarative pipeline and I lost one executor while the resource is freedom when I use lock into the pipeline block, when I use it out of the block the execution never is send to the queue(I know that this is not the right way). Could you explain me if is possible use the plugin without block an executor with Declarative pipeline? 

  30. Can the lock be somehow used in a declarative pipeline across multiple stages? I couldn't get the pipeline to work with lock being at a higher level than under steps {...}.

    That would still be okay if the lock step only performed the lock and it was up to me to put a "release" step elsewhere in the pipeline, but there doesn't seem to be a release step, and the lock step won't work without a body of its own (sad)

  31. I had some trouble creating resources via Jenkins DSL (groovy) code. In the end I managed to do it via some uberClassLoader technique, so thought I'd share the approach here:

     

      // create a lockable resource via Jenkins DSL code
     def lrm = Jenkins.instance.getPluginManager().uberClassLoader.loadClass("org.jenkins.plugins.lockableresources.LockableResourcesManager")
     lrm.get().createResource(resource_name)
  32. Use Lockable Resource as a mutex, sharing a resource between multiple freestyle jobs. (Also, how to use parameters to set the lockable resource, and used node.) 

    Scenario

    We have multiple jobs that need to access the same hardware. Some of these jobs are split into sub-jobs, and a mutex like functionality are needed to avoid a mixup.

     Note: The lockable resource is implemented so that for each lockable resource it calls triggered jobs one at a time, and offers the resource. If the job accepts the resource, it becomes locked. Thereby no race-condition can occour in the mutex.

    Pre-requvisits

    Implementation

    The hardware (two in this explanation) are called HiL1 and HiL2.
    In order to create the mutex, two lockable resources are needed, and for ease of use they get the same names: HiL1 and HiL2. Optionally, additional two lockable resources are needed to keep track of the execution: HiL1_sub and HiL2_sub.

    The main jobs are the owners of the mutex, and they can pass on a mutex token to sub-jobs, which is used to lock on the actual nodes.

    Each of the main jobs can be started specifying to get either a random lock on one of, or a specific lock on one of, the two lockable resources, by specifying either HiLHiL1 or HiL2.

    Main jobs

    The main jobs are implemented as below. Example name is Jenkins_Test/Lockable_Resources_Job1_Test

    ActionLabelValue
    SelectThis build requires lockable resources 
     Resources<blank>
     Label<blank>
    SelectSelect Groovy Expression 
     Groovy Script
    // Beware, this executes before the console log is initialized, so the Groovy println output ends up in jenkins.out.log !!
    this.binding.variables.each {k,v -> println "$k = $v"}
    if ( (resourceName.startsWith(RESOURCE_FOR_THIS_JOB)) && (!resourceName.endsWith("_sub")) ) {
    // println "Gotit"
       return true
    }
    return false
    DeselectUse Groovy Sandbox 
     Additional classpathnone
     Reserved resources variable nameRESOURCE_CONSUMED_BY_TOP_JOB
     Number of resources to request1
    SelectThis project is parameterized 
    AddString Parameter or a Hidden Parameter 
     NameRESOURCE_FOR_THIS_JOB
     Default ValueHiL
     DescriptionCan be either HiL, HiL1 or HiL2. (HiL randomly select between the two others)

    For each sub-job needed,
    Add to the build section

    Trigger/call builds on other projects 
     Projects to buildJenkins_Test/Lockable_Resources_Test_Job1_Sub
     Predefined ParametersRESOURCE_CONSUMED_BY_TOP_JOB=${RESOURCE_CONSUMED_BY_TOP_JOB}

    Sub-jobs

    Each sub job should be implemented as below. Example name is: Jenkins_Test/Lockable_Resources_Test_Job1_Sub

    ActionLabelValue
    SelectGroovy script to restrict where this project can be run 
     Groovy Script
    // Set the node to execute on.
    // Can be either HiL1 or HiL2
    if (RESOURCE_CONSUMED_BY_TOP_JOB.startsWith("HiL")) {
       return RESOURCE_CONSUMED_BY_TOP_JOB
    }
    DeselectUse Groovy Sandbox 
     Additional classpathnone
    SelectRebuild options, Disable Rebuilding for this job 
    SelectThis build requires lockable resources 
     Resources<blank>
     Label<blank>
    SelectGroovy Expression 
     Groovy Script
    // Beware, this executes before the console log is initialized, so the Groovy println output ends up in jenkins.out.log !!
    
    this.binding.variables.each {k,v -> println "$k = $v"}
    if (resourceName == RESOURCE_CONSUMED_BY_TOP_JOB + "_sub") {
    // println "Gotit"
    return true
    }
    return false
    DeselectUse Groovy Sandbox 
     Reserved resources variable nameRESOURCE_CONSUMED_BY_THIS_JOB
     Number of resources to request1
    SelectThis project is parameterized 
    AddHidden Parameter 
     NameRESOURCE_CONSUMED_BY_TOP_JOB
     Default Value<blank>
     DescriptionMust be either HiL1 or HiL2
    Add to Build SectionExecute Windows batch command 
     Command
    @echo off
    echo Show mutex token and assistent:
    echo RESOURCE_CONSUMED_BY_TOP_JOB = "%RESOURCE_CONSUMED_BY_TOP_JOB%"
    echo RESOURCE_CONSUMED_BY_THIS_JOB = "%RESOURCE_CONSUMED_BY_THIS_JOB%"

     

    Now manually triggering a sub-job will not work. Only by starting one of the main jobs, the sub-jobs can be executed.

     

Write a comment…