Developer guidelines for contributing to Ganeti

This page details the rules that need to be followed when contributing code or documentation to the Ganeti project.

Contributor License Agreement (CLA)

The first requirement is that either your and/or your employer sign the individual or corporate Contributor License Agreement. Which one is needed depends on your particular case.

Code

Since migrating the source code repository to Git (see SourceCode for details), only a limited number of people have commit access. Please send your patches to the ganeti-devel@googlegroups.com mailing list to get it reviewed and committed.

Git repository and Github mirror

You can find all Ganeti related repositories at http://git.ganeti.org.

There is also a Ganeti mirror on Github, which you can fork and send pull requests to as an alternative to the git format-patch / git send-email workflow detailed below. Pull requests are automatically forwarded to the ganeti-devel@googlegroups.com mailing list, where the patch can then be discussed.

You can find a tutorial on creating pull requests here.

Source tree organization

Development of new features for the next major or minor version goes on in the master branch. Bug fixes and small changes in earlier versions are done on the stable-x.y branch, and gradually merged all the way into master.

Please read the README or INSTALL files on how to build from source code. ReleaseProcess describes how to build new releases.

Also, please follow our code style guides.

Preparing patches for submission

Checking patches

If you have more than a trivial fix it's better to make sure that the static checks are fine before sending the patches. This can be done by running the command:

make commit-check

For this, you need to have pylint and hlint installed. The output of these tools can change significantly from one version to the other, and some errors might happen to be signalled only by some versions, so we had to standardize on a specific version as the official one Ganeti has to be validated against. You can find the version number (for Ganeti's current master branch) at: http://docs.ganeti.org/ganeti/master/html/devnotes.html

Commit messages

Commit messages should be informative and well-worded. Example:

Short summary line (60 characters long at most, no period at end)

Detailed explanation if necessary, wrapped at ~72 chars/line. Can also be in multiple paragraphs.
If the commit modified more than four lines of code, the explanation is required and must contain at least 20 characters.
 * Use itemized list if several things were done in the same patch
 * But consider doing them in different patches

Formatting and sending patches

The patch to send should be a proper patch created by Git and signed by you. The patch can be created with the following command:

git format-patch -s --subject-prefix=... ...

The -s options adds the required ‘‘Signed-off-by’’ tag to the end of the patch.

Each patch should have a subject prefix indicating the branch it‘s directed to (for ganeti-core) or the separate repository it’s for. For example patches for ganeti-core branch-2.6 should be generated by passing the option --subject-prefix="PATCH branch-2.6" to git format-patch.

Officially recognized prefix tags are:

  • PATCH stable-2.x for patches directed at ganeti stable-2.x
  • PATCH master for patches directed at the development tree
  • PATCH instance-debootstrap for patches directed at the ganeti-instance-deboostrap repository

When sending a patch series, it is customary to include cover letter (--cover-letter option).

Also note that you can change PATCH to RFC if you want to send a patch/series just for discussion, rather than to propose its inclusion right away (it's basically an invite for more feedback).

More details on git workflow

This section offers a few more details on the git workflow we recommend.

When you begin your work with completely fresh repository, first do the following:

# Clone the repository.

git clone git://git.ganeti.org/ganeti.git && cd ganeti
./autogen.sh
./configure --localstatedir=/var --sysconfdir=/etc
# Confirm that all the components that you need are present.

The following represents a generic work cycle, from check-out to sending a patch.

# View branches; checkout the desired branch.

git branch -a
git checkout -b new_branch_name origin/master #or stable-X.Y etc

# Coding, coding, coding -- one patch at a time!
# Review your handiwork.
git diff

# If you make non-trivial changes you should run a commit-check
make commit-check

# For trivial changes you can use a check specific to your change, e.g. for haskell code run `make hs-check`

# Describe and commit your handiwork to your local branch.
git status
git commit -a

# Other possibility: git add <filename> && git commit
# Note: git add <filename> -p lets you add parts of the file

gitk --all # Handy GUI for reviewing changes in context.

# You may further edit and then amend a previously committed change
git add <forgotten-file>
git commit --amend

# You may also go back and change older patches in patch series
git rebase -i HEAD~<number of commits>

# Before sending a patch, make sure your local repo is up to date
git pull

# Creating a nice mailable patch for the list
git format-patch --cover-letter -s --subject-prefix="PATCH branch-x.y" origin/branch-x.y
# Describe the patch series in the cover letter before sending your patches

# Make sure your `.git/config` has working email settings.
git send-email 0001-<commit message>.patch # use --dry-run to see what would be emailed
# For patch series you need to send each file

# Read comments, if fixes are required
git pull
# Write the fix
git diff # Paste the diff to the appropriate thread
# Or commit your change and submit it to mailing list with `--in-reply-to=<id>`
git commit -m "Fix for commit: <..>"

# After getting all LGTMs you need to squash your fixes to original commits
git rebase -i <...>

Constants

If you are contributing code that depends on (global) constants or that depends on values which other people might find interesting to configure easily then it is important to make these constants available globally. Since Ganeti 2.10, the proper way of adding constants to Ganeti is to add them in Haskell, even if these constants will only be used in Python.

The reason for this is that, at compile time, Ganeti will typecheck the constants and it will convert them to Python, just like, before Ganeti 2.10, Python constants were converted to Haskell. You can find the Haskell to Python generated constants in lib/_constants.py._

Then, if the constants you have added are used in Python, and not just in Haskell, you should an entry in ‘lib/constants.py’ to re-export the desired constants to the Python codebase. You can follow the other entries in ‘lib/constants.py’ as a guideline.

Useful git repository config snippet

This snippet might be useful when working with the Ganeti git repo and shall be added to .git/config of the cloned repository.

[branch]
  autosetuprebase = always
[sendemail]
  chainreplyto = false
  to = ganeti-devel@googlegroups.com
  thread = false
  confirm = compose
  suppressfrom = true
[format]
  signoff = true
  thread = shallow

For further details what each of this options does have a look at git help config.

Testing / Debugging Ganeti

To run a single python test, run it as:

PYTHONPATH=`pwd` python test/py/ganeti.utils.process_unittest.py TestRunCmd.testTimeoutOutputAfterTerm

To get logging output, set the LOGTOSTDERR environment variable. For example:

LOGTOSTDERR=1 PYTHONPATH=`pwd` python test/py/ganeti.utils.process_unittest.py TestRunCmd.testTimeoutOutputAfterTerm

Wiki updates

The wiki can be updated by members directly. Non-members need to send their requested changes to the mailing list.