Skip to end of metadata
Go to start of metadata

JENKINS-24380, which is introduced in 1.597, changes the on-disk layout of build directories.

In Jenkins, each job has a directory under $JENKINS_HOME (such as $JENKINS_HOME/jobs/foo/ for a job named foo).

Prior to JENKINS-24380, this directory contained one directory each per build named according to its timestamp, such as builds/2014-09-15_17-51-46/, that contains all information about that build (including build.xml, log, and more). If this build was number 123, there was also a symlink (or, on some Windows systems, plain text file) named 123 that pointed to 2014-09-15_17-51-46. build.xml listed the <number>123</number>; the timestamp (in the local time zone) was implied by the directory name.

After JENKINS-24380, builds/123/ will be the directory that contains the build. There is no longer a symlink per build. (Special status symlinks such as lastStableBuild remain as before, still pointing to the build number.) build.xml now indicates the <timestamp>, whereas the number is implied by the directory name.

Whenever a newer version of Jenkins starts with an older $JENKINS_HOME, the necessary conversion happens automatically during startup. Old build records are converted to the new layout, with the exception that build.xml also has an <id> field giving an internal identifier used by some plugins to refer to builds (formerly based on the timestamp, defaulting for new builds to be the number).

This change was introduced to resolve a number of longstanding issues. Unfortunately, this migration is backward incompatible, in that if you upgrade to Jenkins ≥1.597, which migrates the data, then later decide to downgrade back to <1.597, then the earlier version of Jenkins will not know how to interpret the new $JENKINS_HOME directory layout. As a result, Jenkins will come up without any build records.

In case you want to downgrade, there is an “unmigrate” script provided to reverse the migration of $JENKINS_HOME. To do this:

  1. Start Jenkins ≥1.597.
  2. Visit http://server/jenkins/JENKINS-24380/ and copy the unmigration instruction.
  3. Shut down Jenkins completely.
  4. Run the command as instructed by the step above.
  5. Start Jenkins <1.597 with the same $JENKINS_HOME.
  • No labels

3 Comments

  1. i am trying to follow this procedure, but i am getting this error:

    Exception in thread "main" java.lang.NoClassDefFoundError: javax/servlet/ServletRequest
        at hudson.Util.createSymlinkJava7(Util.java:1248)
        at hudson.Util.createSymlink(Util.java:1142)
        at jenkins.model.RunIdMigrator.unmigrateBuildsDir(RunIdMigrator.java:413)
        at jenkins.model.RunIdMigrator.unmigrateJobsDir(RunIdMigrator.java:362)
        at jenkins.model.RunIdMigrator.main(RunIdMigrator.java:344)
    Caused by: java.lang.ClassNotFoundException: javax.servlet.ServletRequest
        at java.net.URLClassLoader$1.run(URLClassLoader.java:366)
        at java.net.URLClassLoader$1.run(URLClassLoader.java:355)
        at java.security.AccessController.doPrivileged(Native Method)
        at java.net.URLClassLoader.findClass(URLClassLoader.java:354)
        at java.lang.ClassLoader.loadClass(ClassLoader.java:425)
        at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:308)
        at java.lang.ClassLoader.loadClass(ClassLoader.java:358)
        ... 5 more

    is there a way to unmigrate without going thru jenkins itself?  from the user's perspective, this is an unfriendly process because it requires the "new" jenkins (which i'd like to get rid of) to be installed and running.  then, i need to install the "old" jenkins to make sure it's OK.  if it's not, then i need the "new" jenkins again.  putting the unmigration process inside jenkins makes the process un-transparent, which is a hassle if anything goes wrong.

    UPDATE: i was able to work around the problem by downloading servlet-api.jar and javax.servlet.jar, then adding them to the classpath of the recommended command.

    1. Excellent tip! The missing servlet.jar is available in the winstone.jar included with Jenkins. You don't have to download any new jars but you have to add the winstone.jar to the command classpath.

      Here is the command I run succesfully to restore the layout old format:

      java -classpath "%JENKINS_HOME%\war\WEB-INF\lib\jenkins-core-2.7.1.jar;%JENKINS_HOME%\war\WEB-INF\lib\commons-io-2.4.jar;%JENKINS_HOME%\war\WEB-INF\lib\stapler-1.243.jar;%JENKINS_HOME%\war\WEB-INF\lib\ant-1.8.4.jar;%JENKINS_HOME%\war\WEB-INF\lib\commons-lang-2.6.jar;%JENKINS_HOME%\war\winstone.jar" jenkins.model.RunIdMigrator "%JENKINS_HOME%"
      

      Note: %JENKINS_HOME% should be replaced by your actual path to the Jenkins installation. You can use this command from a newer Jenkins installation to restore the old installation

  2. I did not fully dig into this but it appears that the back-porting utility for jobs does not correctly process workflow builds.  It reports success but then attempting to run Jenkins 1.596 with the resulting jobs causes it to hang with 100% cpu utilization.  This doesn't occur on startup but occurs when a user logs in.  My guess is it hangs trying to display the list of jobs.

    I did some debugging and it appears that somthing in loading the build history for a job in this scenario puts jenkin's into an infinite recursion ultimately leading to a stack overflow.  This appears to be happening on either a per build or per job basis for back-ported workflow jobs.  Sorry I did not keep any of the stack traces.  They were huge.  

    Details, we were back porting from 1.609 to 1.596.2 LTS and using WF v. 1.3.