Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

jenkins parallel workflow plugin fails with java.io.NotSerializableException: hudson.plugins.sshslaves.SSHLauncher

Any clue why parallel would throw serialization errors for something so simple:

  branches[nodeSpec] = {
      node(nodeSpec) {
        echo("remote");
      }

I'm trying to write a workflow plugin build that performs a maintenance task on all my nodes. This worked earlier today and even if I execute that code, I get the following failure. I can't understand what's causing the problem. I know this can be an issue with variable use but I don't think I'm using any within my node closure.

Please let me know if you have any suggestions

Error

java.io.NotSerializableException: hudson.plugins.sshslaves.SSHLauncher at org.jboss.marshalling.river.RiverMarshaller.doWriteObject(RiverMarshaller.java:860) at org.jboss.marshalling.river.RiverMarshaller.doWriteFields(RiverMarshaller.java:1032) at org.jboss.marshalling.river.RiverMarshaller.doWriteSerializableObject(RiverMarshaller.java:988) at org.jboss.marshalling.river.RiverMarshaller.doWriteSerializableObject(RiverMarshaller.java:967) at org.jboss.marshalling.river.RiverMarshaller.doWriteObject(RiverMarshaller.java:854) at org.jboss.marshalling.river.RiverMarshaller.doWriteObject(RiverMarshaller.java:569) at org.jboss.marshalling.river.BlockMarshaller.doWriteObject(BlockMarshaller.java:65) at org.jboss.marshalling.river.BlockMarshaller.writeObject(BlockMarshaller.java:56)

Code

// Get all Nodes from Jenkins instance
def nodelist = Jenkins.getInstance().getNodes()
branches = [:]

// Iterate list -- NOTE: we cannot use groovy style or even modern java style iteration
for (int i =0; i < nodelist.size(); i++) {
   Slave node = nodelist[i]
   def nodeSpec =  node.name.toString()
   if (node.getComputer().isOnline()) {  
      println "Create Task for ${nodeSpec}"
      branches[nodeSpec] = {
          node(nodeSpec) {
            echo("remote");
          }

      }
   }
 }  

parallel branches
like image 379
Peter Kahn Avatar asked Feb 18 '16 19:02

Peter Kahn


1 Answers

UPDATE: from comments below I discovered I misunderstood requirements for NonCPS annotation. This is necessary to prevent the problem if the method used within the branch and a good idea for clarity even if the method is used prior to the branch execution.

I have working code and theories as to why it works.

  • Isolate the Jenkins slave objects to ensure they aren't carried to the nodes as they can't be serialized. (getOnlineNodeNames presents local variable as list of strings)
  • Move conditional statement outside of node (unsure why this has any impact)

Code

@NonCPS
List <String> getOnlineNodeNames() {
  List <String> nodeNames = []
  def allNodes = Jenkins.getInstance().getNodes()
  for (int i =0; i < allNodes.size(); i++) {
   Slave node = allNodes[i]

   if (node.getComputer().isOnline()) {  
    nodeNames.add(node.name.toString())
   }
  }
  return nodeNames
}


List<String> nodeList = getOnlineNodeNames()

branches = [:]
for (int i =0; i < nodeList.size(); i++) {
  String nodeName = nodeList[i]
  if(nodeName.contains("win")) {
    branches[nodeName] = { node(nodeName) { 
             bat '''@echo off
DoMainTasks....'''

       } 
    }
  } else {
    branches[nodeName] = { node(nodeName) { 
         sh '''set +x
DoMainTasks....'''
       } 
    }
  }

}
parallel branches
like image 177
Peter Kahn Avatar answered Oct 21 '22 21:10

Peter Kahn