by David Burns on January 21, 2011 // Short URL

Upgrading Drupal 5 to Drupal 6

Because your site may not be ready for Drupal 7

I initially wrote this article when we completed the upgrade and redesign of this site. However, at the time I felt we were so close to seeing a Drupal 7 release that it was somewhat irrelevant and could possibly deter people from getting involved with Drupal 7. After listening to Lullabot Podcast 90: Drupal 7, Are you ready? I realized that there are still a number of sites out there that may not be ready to port to Drupal 7, but are in fact built on Drupal 5 which would greatly benefit from moving to Drupal 6 for a number of reasons. Here are just a few:

Basic Background

Many blog post have been written about this procedure. So here's a quick overview for a process that most of these articles have in common.

The basics require that all D5 modules be updated to their most recent stable release before attempting to upgrade a site to D6. This requires that you confirm that a module has a D6 release or ported to another module (example, bio module was deprecated in favor of content_profile), a process that can be assisted by installing the update_status module. Upon updating your D5 modules you would then put your site off-line and prepare your database for D6 migration by disabling all non-core modules.

At this point you would clone the D5 database and connect it to your D6 core and module filesystem via settings.php. This is good practice because it leaves your D5 files and database untouched if your update process fails. After core upgrade is completed then modules should be enabled individually along with their dependecies and then update.php needs to be ran again to get the database updated for that set of modules.

For previous projects I have usually stuck to this process. Unfortunately, I still fumbled my way through the upgrade having many conflicts along the way which ultimately resulted in data being corrupted. So for Lullabot.com upgrade I decided to try something new which seemed to have worked very well.

This is where the magic happens

Rather than disabling all non-core modules, I decided to leave existing modules enabled and leverage the select list on update.php to control which modules would be updated during each step. This took a bit of trial and error till I found the best process.

Slightly modifying the preferred method of core files first, I set ALL CCK, Date, Views, and custom modules to be "No updates available" then clicked "Continue". Notice that I left all non CCK, Date, and Views modules enabled to run their updates on the initial pass. After the 115 or so updates that needed to occur the response was cluttered with errors, but as I read through them they seemed to be non destructive, just warning messages that certain tables did not exist yet.

After a couple failed next steps, it became aparent that Drupal wanted CCK type modules to be updated next (excluding date, which required CCK core modules to be updated first). So for the next step navigate back to update.php and select CCK related modules to be updated from their D6 update hooks (usually numbered 6000).

Now that CCK base tables have been converted running updates on Date modules did not cause any conflicts. Repeat the process of going to update.php and choose Date modules updates begining with 6000 series.

With all CCK and Date fields being converted the Views module could be updated without causing any errors. Repeat the process of going to update.php and choose Views module updates begining with 6000 series.

At this point everything for Drupal 6 core and contrib was updated on our site. Now there were some custom things we wanted to do like enable features, disable modules, migrate content types, change date formats, build menus or automate anything we normally did in the UI post upgrade. We had 20 update hooks in a custom module that took care of these processes.

Some things worth noting during our custom update hooks was that update.php ran so early in the bootstrap that not all include files for modules were made available to use. So there were times where we had to use the following functions in our update hooks.

drupal_load('module', 'module_name');

AND
module_load_include('inc', 'module_path/basename');

Repeating the Process

I found that I was repeating many of these steps of going to update.php, disabling updates for some modules, enabling for others. Repeat. So instead of doing this manually, I created browser macros using iMacros for Firefox that helped automate this process. By doing this we were quickly able to run the upgrade path multiple times throughout the development cycle, making tweaks where needed. Since these macros are exportable, each member of our team could run this update locally with consistant results and continually confirm that our upgrade path was still functional.

Disclaimer

This is a process that worked for our site. The process worked well for us because we stick with a number of popular contrib modules that had a solid upgrade path of their own. I have shared this process to a few fellow developers that were having troubles upgrading from Drupal 5 to Drupal 6, and surprisingly the process worked just as well for them as it did for us. However, this is no guarantee that this is the Golden Ticket, but it should help get you to a point with less error messages. With proper debugging and a bit of custom update hooks you should be able to finish your migration.

David Burns

Senior Developer

Want David Burns to speak at your event? Contact us with the details and we’ll be in touch soon.

Comments

Jason

Works like a charm!

Great article Dave.

For those of you who read the comments, I have used this method as per Dave's instructions and it works very well. I had a client recently that needed to do a 12 site D5 to D6 upgrade. It really saved me time and frustration on the project. After a few hiccups in the first update it was smooth sailing after that.

I highly recommend this methodology to avoid headaches while upgrading complex sites with many modules from Drupal 5 to Drupal 6.

It would be great to see Drupal update automatically in this order at some point, so that you don't have to be or know a Lullabot to update a complex site ;)

Cheers,

Jason
Arbor Web Development

Reply

venkat-rk

Dealing with installed version not supported

I was hoping this article would deal with a problem I am facing in updating from D5 to D6 using Drush, but I see you are dealing differently.

Would you have any idea of what one does when drush pm-update returns a list of modules (and core drupal) whose 'Installed version is not supported'?

Reply

NicolasH

Large site: shell script/Drush

It's unlikely that updating from D5 to D6 is a one-off process for larger sites with a lot of custom modules and data. We have a nightly migration script that takes about 2.5 hours for a copy of our live site to be migrated to D6.

It goes roughly like this:

- Clean up the current D5 instance. Run drush uninstall on everything that can go. Run SQL queries on everything that gets missed by these often incomplete uninstalls....if they are there at all. Variables, tables...everything must go.

- Make sure everything that stays is up to date. Drush upc, drush updatedb. Then disable most modules for good measure.

- Put clean D5 DB onto D6 core codebase...no contrib modules present. Run core updates .

- Loop over all modules that need to be udpaded one by one, SVN checkout, drush enable, drush updatedb. Rinse repeat. The order can make a big difference...since it's scripted it can be tweaked over time. CCK modules should really come first, since that's where most of the schema changes happen.

- Use a custom module's install file to run more complex operations in mymodule_update_n() functions, like deleting content via node_delete() that's not needed anymore etc.

- Rsync files and take the opportunity to exclude files/directories that aren't needed anymore. If this needs further DB cleanups as well, see above.

We didn't bother trying to convert views or panels. They get recreated in D6 manually in better ways than it was possible in D5, then saved as features that get installed as part of the migration script.

An update like this is a great opportunity to do a spring clean. To just give an example: Workflow doesn't delete an entry in the workflow_node_history table when a node gets deleted - this is by design. In our case that was about 80MB of historic data that we feel we don't need.

It's a lot easier to be bold about deleting stuff from the DB if it's not on a live site and it can be taken out of the script for next night's run if for some reason it's still needed after all. Of course the migration script is under version control.

Also, content producers feel more confident to QA if the D6 version has current data that they can cross-check with the live D5 site. This wouldn't be possible with a one-off update, if the QA can take weeks.

Reply

Steve-O

Fields missing after D6 upgrade

I have a number of sites that used CCK Taxonomy Fields and got a nasty surprise when I updated to D6 and found them inaccessible.

It turns out that CCK Taxonomy Fields module is abandoned - it's function is supposedly in D6 core - but there is no apparent way of getting these fields back and zero support from the project page.

Reply