Managing Configuration Changes with Git

From OpenNMS
Jump to: navigation, search

OpenNMS's configuration is very powerful, but with that unfortunately comes a level of complexity that can make it difficult to manage upgrades. One of the easiest ways to mitigate this is by using git to manage your configuration upgrades.

Getting Started

First, if you're not familiar with Git, you may want to read our developing with Git page, as well as the Git tutorial.

If you have an existing OpenNMS install, the easiest way to get started is to make sure you have a version of OpenNMS which provides the "etc-pristine" directory (in the 1.6.x series, OpenNMS 1.6.9 or higher, and in the 1.7/1.8 series, OpenNMS 1.7.9 or higher).

If this is your first time installing OpenNMS, you can skip to the Create Your Branch section.

Don't forget to stop OpenNMS before messing with the etc directory!

Start with a Pristine etc Directory

Everything Except Debian (RPM-based installations and manual installs)

If you have an existing OpenNMS installation, move your existing $OPENNMS_HOME/etc directory out of the way. Then, copy etc-pristine to $OPENNMS_HOME/etc. On RPM-based installations, this is in $OPENNMS_HOME/share/etc-pristine:

 mv $OPENNMS_HOME/etc $OPENNMS_HOME/etc.bak
 cp -pR $OPENNMS_HOME/share/etc-pristine $OPENNMS_HOME/etc

Debian

NB - if you are using Debian, $OPENNMS_HOME/etc is a symlink of /etc/opennms - DO NOT move that folder, you will break the symlink and the resulting upgrade will fail. You can fix this with: cd /usr/share/opennms ; mv etc etc_bad ; ln -s /etc/opennms etc - Thanks to jeffg for this.

On Debian the etc-pristine directory is in /usr/share/opennms/share/etc-pristine:

 mv /etc/opennms /etc/opennms.bak
 cp -pR /usr/share/opennms/share/etc-pristine /etc/opennms

Initialize Git

Next, you'll turn your etc directory into a git repository, and add the pristine files as the first commit.

 cd $OPENNMS_HOME/etc
 git init
 cat << EOF > $OPENNMS_HOME/etc/.gitignore
 foreign-sources/
 imports/
 examples/
 include
 *.dpkg-old
 opennms-upgrade-status.properties
 libraries.properties
 pluginManifestData.xml
 org.opennms.features.datachoices.cfg
 include
 configured
 EOF
 git add .
 git commit -m "Initial checkin of OpenNMS x.x.x configuration."

The .gitignore provided above is an example and isn't required but it might save you some trouble. Depending on your company policies about password storage you might add jetty.keystore to gitignore as well (don't store keys in git). You might add opennms.datasources too, except the pristine version will be rewritten each time you upgrade so be aware that you need to put the passwords back.

The only line I would consider required for .gitignore is "configured" which is a file that is used to check if the "install" script has been run so the database is the same version as the code. The file is removed by package managers when an upgrade happens and put back by "install -dis"

See: http://issues.opennms.org/browse/NMS-8108 for details.

Create Your Branch

Finally, you'll create your branch to make local modifications. This way, whenever it's time to upgrade, you can put your git repo back in "pristine" mode to catch changes since the last version.

 cd $OPENNMS_HOME/etc
 git branch local-modifications
 git checkout local-modifications

Make Your Changes

Now, just edit your configuration normally, and you're all set. If you have an existing config that was backed up, you can just run:

 rsync -avr $OPENNMS_HOME/etc.bak/ $OPENNMS_HOME/etc/

Whenever you're done making changes to your etc directory, add and commit them, like so:

 cd $OPENNMS_HOME/etc
 git add .
 git commit -m "Added initial discovery ranges."

Now you can start OpenNMS back up again.

Doing an Upgrade

Now that you've got your etc directory managed by Git, it should be much easier to perform an upgrade. You just need to switch back to the pristine copy, upgrade, switch back, and merge the changes. Git has a very good merge algorithm, and will merge most configuration changes without any need for manual intervention.

Stop OpenNMS

Of course, the first step before doing an upgrade is to stop OpenNMS. =)

 /etc/init.d/opennms stop

Make Sure All Changes are Committed

Don't forget that if any files are modified, you'll want to add and commit them before doing the upgrade.

 git status

If it says there are modifications, follow the instructions in Make Your Changes above.

Switch to the Pristine Branch

The next step is to put your $OPENNMS_HOME/etc back to its pristine condition. To do this, all you need to do is check out the "master" branch, which contains the version of files from Initialize Git above.

 git checkout master

Upgrade OpenNMS

Now, upgrade OpenNMS in the usual manner (yum upgrade opennms, apt-get upgrade opennms, etc.). You should have no conflicts, since the etc files looked exactly like they did in the original package.

If you now run status:

 git status

... you'll see any changes to the default configs since the version of OpenNMS you've installed.

If any files have been deleted, you'll need to run 'git rm <filename>' to tell git that they're gone.

 git rm CHANGELOG
 git rm map.disable

...and so on.

Then you'll need to add the new and changed files, and save these changes to the pristine/master branch, by adding and committing them:

 git add .
 git commit -m 'Upgraded to OpenNMS x.x.x.'

Switch to Your Modified Branch

Now that OpenNMS is upgraded, and Git knows about the changes to the configs since your previous release, it's time to switch back to your modified branch. All you need to do is check it out:

 git checkout local-modifications

Apply Changes from Master

Finally, you need to apply the changes from master to your local branch. To do so, you just need to 'merge' master into the current working branch ("local-modifications") like so:

 git merge master

If all goes well, you will see that the files that were changed in the master branch were auto-applied to your "local-modifications" working copy.

If not, you'll see something like this:

 git merge master
 Removing CHANGELOG
 Removing map.disable
 Auto-merging surveillance-views.xml
 CONFLICT (content): Merge conflict in surveillance-views.xml
 Automatic merge failed; fix conflicts and then commit the result.

A 'git status' will reveal the things that need modification with a "both modified":

 ...
 # Unmerged paths:
 #   (use "git reset HEAD <file>..." to unstage)
 #   (use "git add <file>..." to mark resolution)
 #
 #	both modified:      surveillance-views.xml

Git will insert a standard CVS-style conflict marker in each file where there are conflicts between your local changes and the updates. The changes from your branch will be first, and the changes from the pristine copies will be second, like so:


      <rows>
<<<<<<< HEAD
        <row-def row="1" label="Monkey Heads" >
          <category name="Monkey Heads"/>
        </row-def>
        <row-def row="2" label="Routers" >
          <category name="Routers"/>
        </row-def>
        <row-def row="3" label="Switches" >
          <category name="Switches" />
        </row-def>
        <row-def row="4" label="Servers" >
=======
        <row-def label="Routers" >
          <category name="Routers"/>
        </row-def>
        <row-def label="Switches" >
          <category name="Switches" />
        </row-def>
        <row-def label="Servers" >
>>>>>>> master
          <category name="Servers" />
        </row-def>

...just edit the files until they look like you'd expect (in this case, the 'row="n"' bits were removed from surveillance-views.xml) and add and commit the changes:

 git add .
 git commit

Check for Other Changes

If you're curious what changed in the last upgrade (ie, the last change done to the 'master' branch), you can diff master against its previous commit like so:

 git diff master~1..master

This works no matter which branch you're in at the time.

Start OpenNMS

Now that everything's merged, just start OpenNMS back up, and you should be in business!