diff --git a/modules/jenkins_jobs/manifests/add_jobs.pp b/modules/jenkins_jobs/manifests/add_jobs.pp
new file mode 100644
index 0000000000..4e0c22dda3
--- /dev/null
+++ b/modules/jenkins_jobs/manifests/add_jobs.pp
@@ -0,0 +1,85 @@
+define jenkins_jobs::add_jobs($site) {
+ $project = $name
+
+ jenkins_jobs::job { "${name}-coverage":
+ site => "${site}",
+ project => "${name}",
+ job => "coverage",
+ logrotate => template("jenkins_jobs/logrotate.xml.erb"),
+ builders => [template("jenkins_jobs/builder_copy_bundle.xml.erb"), template("jenkins_jobs/builder_coverage.xml.erb")],
+ publishers => template("jenkins_jobs/publisher_coverage.xml.erb"),
+ triggers => template("jenkins_jobs/trigger_timed_15mins.xml.erb"),
+ scm => template("jenkins_jobs/scm_git.xml.erb")
+ }
+
+ jenkins_jobs::job { "${name}-docs":
+ site => "${site}",
+ project => "${name}",
+ job => "docs",
+ triggers => template("jenkins_jobs/trigger_timed_15mins.xml.erb"),
+ builders => [template("jenkins_jobs/builder_copy_bundle.xml.erb"), template("jenkins_jobs/builder_docs.xml.erb")],
+ publishers => template("jenkins_jobs/publisher_docs.xml.erb"),
+ scm => template("jenkins_jobs/scm_git.xml.erb")
+ }
+
+ jenkins_jobs::job { "${name}-merge":
+ site => "${site}",
+ project => "${name}",
+ job => "merge",
+ triggers => template("jenkins_jobs/trigger_gerrit_comment.xml.erb"),
+ builders => template("jenkins_jobs/builder_gerrit_git_prep.xml.erb")
+ }
+
+ jenkins_jobs::job { "${name}-pep8":
+ site => "${site}",
+ project => "${name}",
+ job => "pep8",
+ triggers => template("jenkins_jobs/trigger_gerrit_comment.xml.erb"),
+ builders => [template("jenkins_jobs/builder_gerrit_git_prep.xml.erb"), template("jenkins_jobs/builder_copy_bundle.xml.erb"), template("jenkins_jobs/builder_pep8.xml.erb")],
+ publishers => template("jenkins_jobs/publisher_pep8.xml.erb")
+ }
+
+ jenkins_jobs::job { "${name}-ppa":
+ site => "${site}",
+ project => "${name}",
+ job => "ppa",
+ builders => template("jenkins_jobs/builder_ppa.xml.erb"),
+ publishers => template("jenkins_jobs/publisher_ppa.xml.erb")
+ }
+
+ jenkins_jobs::job { "${name}-python26":
+ site => "${site}",
+ project => "${name}",
+ job => "python26",
+ triggers => template("jenkins_jobs/trigger_gerrit_comment.xml.erb"),
+ builders => [template("jenkins_jobs/builder_gerrit_git_prep.xml.erb"), template("jenkins_jobs/builder_copy_bundle.xml.erb"), template("jenkins_jobs/builder_python26.xml.erb")],
+ }
+
+ jenkins_jobs::job { "${name}-python27":
+ site => "${site}",
+ project => "${name}",
+ job => "python27",
+ triggers => template("jenkins_jobs/trigger_gerrit_comment.xml.erb"),
+ builders => [template("jenkins_jobs/builder_gerrit_git_prep.xml.erb"), template("jenkins_jobs/builder_copy_bundle.xml.erb"), template("jenkins_jobs/builder_python27.xml.erb")],
+ }
+
+ jenkins_jobs::job { "${name}-tarball":
+ site => "${site}",
+ project => "${name}",
+ job => "tarball",
+ triggers => template("jenkins_jobs/trigger_gerrit_ref_updated.xml.erb"),
+ builders => [template("jenkins_jobs/builder_gerrit_git_prep.xml.erb"), template("jenkins_jobs/builder_copy_bundle.xml.erb"), template("jenkins_jobs/builder_tarball.xml.erb")],
+ publishers => template("jenkins_jobs/publisher_tarball.xml.erb")
+ }
+
+ jenkins_jobs::job { "${name}-venv":
+ site => "${site}",
+ project => "${job}",
+ job => "venv",
+ triggers => template("jenkins_jobs/trigger_timed_midnight.xml.erb"),
+ builders => template("jenkins_jobs/builder_venv.xml.erb"),
+ publishers => template("jenkins_jobs/publisher_venv.xml.erb"),
+ scm => template("jenkins_jobs/scm_git.xml.erb")
+ }
+
+}
diff --git a/modules/jenkins_jobs/manifests/init.pp b/modules/jenkins_jobs/manifests/init.pp
new file mode 100644
index 0000000000..8a5cc419a0
--- /dev/null
+++ b/modules/jenkins_jobs/manifests/init.pp
@@ -0,0 +1,10 @@
+class jenkins_jobs($site, $projects) {
+
+ service { "jenkins":
+ ensure => running
+ }
+
+ jenkins_jobs::add_jobs { $projects:
+ site => "${site}"
+ }
+}
diff --git a/modules/jenkins_jobs/manifests/job.pp b/modules/jenkins_jobs/manifests/job.pp
new file mode 100644
index 0000000000..53029130e8
--- /dev/null
+++ b/modules/jenkins_jobs/manifests/job.pp
@@ -0,0 +1,44 @@
+define jenkins_jobs::job($site, $project, $job, $triggers="", $builders, $publishers="", $logrotate="", $scm="") {
+
+ file { "/var/lib/jenkins/jobs/${project}-${job}":
+ ensure => directory,
+ owner => 'jenkins',
+ group => 'nogroup'
+ }
+
+ file { "/var/lib/jenkins/jobs/${project}-${job}/builds":
+ ensure => directory,
+ owner => 'jenkins',
+ group => 'nogroup',
+ require => File["/var/lib/jenkins/jobs/${project}-${job}"],
+ notify => Service["jenkins"]
+ }
+
+ file { "/var/lib/jenkins/jobs/${project}-${job}/config-history":
+ ensure => directory,
+ owner => 'jenkins',
+ group => 'nogroup',
+ require => File["/var/lib/jenkins/jobs/${project}-${job}"],
+ notify => Service["jenkins"]
+ }
+
+ file { "/var/lib/jenkins/jobs/${project}-${job}/config.xml":
+ ensure => present,
+ content => template("jenkins_jobs/body.xml.erb"),
+ owner => 'jenkins',
+ group => 'nogroup',
+ require => File["/var/lib/jenkins/jobs/${project}-${job}"],
+ notify => Service["jenkins"]
+ }
+
+ file { "/var/lib/jenkins/jobs/${project}-${job}/nextBuildNumer":
+ ensure => present,
+ content => "1",
+ owner => 'jenkins',
+ group => 'nogroup',
+ replace => false,
+ require => File["/var/lib/jenkins/jobs/${project}-${job}"],
+ notify => Service["jenkins"]
+ }
+
+}
diff --git a/modules/jenkins_jobs/templates/body.xml.erb b/modules/jenkins_jobs/templates/body.xml.erb
new file mode 100644
index 0000000000..14a6719195
--- /dev/null
+++ b/modules/jenkins_jobs/templates/body.xml.erb
@@ -0,0 +1,59 @@
+
+
+
+
+ <%= logrotate %>
+ false
+
+
+ https://github.com/<%= site %>/<%= project %>/
+
+
+ 0
+ 0
+
+ false
+ project
+ 1
+
+
+
+ PROJECT=<%= project %>
+ false
+
+ true
+ true
+ true
+
+
+
+ hudson.model.Item.Build:authenticated
+
+
+ <% if scm == "" %>
+
+ <% else %>
+ <%= scm %>
+ <% end %>
+ false
+ false
+ false
+ false
+ <% if triggers != "" %>
+
+ <%= triggers %>
+
+ <% end %>
+ false
+ <% if builders != "" %>
+
+ <%= builders %>
+
+ <% end %>
+ <% if publishers != "" %>
+
+ <%= publishers %>
+
+ <% end %>
+
+
diff --git a/modules/jenkins_jobs/templates/builder_copy_bundle.xml.erb b/modules/jenkins_jobs/templates/builder_copy_bundle.xml.erb
new file mode 100644
index 0000000000..be713c36c1
--- /dev/null
+++ b/modules/jenkins_jobs/templates/builder_copy_bundle.xml.erb
@@ -0,0 +1,23 @@
+
+
+ $PROJECT-venv
+
+
+
+
+
+ # Support jobs, such as nova-docs, which are not yet triggered by gerrit
+if [ "x$GERRIT_BRANCH" = "x" ] ; then
+ GERRIT_BRANCH=master
+fi
+mv jenkins_venvs/$GERRIT_BRANCH/.cache.bundle .
+rm -fr jenkins_venvs
+
+if [ -f tools/test-requires -a \
+ `git diff HEAD^1 tools/test-requires 2>/dev/null | wc -l` -gt 0 -o \
+ `git diff HEAD^1 tools/pip-requires 2>/dev/null | wc -l` -gt 0 ]
+then
+ rm .cache.bundle
+fi
+
+
diff --git a/modules/jenkins_jobs/templates/builder_coverage.xml.erb b/modules/jenkins_jobs/templates/builder_coverage.xml.erb
new file mode 100644
index 0000000000..df75227b87
--- /dev/null
+++ b/modules/jenkins_jobs/templates/builder_coverage.xml.erb
@@ -0,0 +1,9 @@
+
+ if [ -f .cache.bundle ] ; then
+ tox -ejenkinscover
+else
+ tox -evenv -- nosetests test/unit --with-xcoverage --cover-erase --cover-package=<%= project %>
+
+fi
+
+
diff --git a/modules/jenkins_jobs/templates/builder_docs.xml.erb b/modules/jenkins_jobs/templates/builder_docs.xml.erb
new file mode 100644
index 0000000000..b0820ddddc
--- /dev/null
+++ b/modules/jenkins_jobs/templates/builder_docs.xml.erb
@@ -0,0 +1,10 @@
+
+ mkdir -p doc/build
+export HUDSON_PUBLISH_DOCS=1
+if [ -f .cache.bundle ] ; then
+ tox -ejenkinsvenv python setup.py build_sphinx
+else
+ tox -evenv python setup.py build_sphinx
+fi
+
+
diff --git a/modules/jenkins_jobs/templates/builder_gerrit_git_prep.xml.erb b/modules/jenkins_jobs/templates/builder_gerrit_git_prep.xml.erb
new file mode 100644
index 0000000000..dfbbb5af50
--- /dev/null
+++ b/modules/jenkins_jobs/templates/builder_gerrit_git_prep.xml.erb
@@ -0,0 +1,31 @@
+
+ #!/bin/bash -xe
+
+if [ -z "$GERRIT_NEWREV" ] && [ -z "$GERRIT_REFSPEC" ]
+then
+ echo "This job may only be triggered by Gerrit."
+ exit 1
+fi
+
+if [[ ! -e .git ]]
+then
+ git clone https://review.<%= site %>.org/p/$GERRIT_PROJECT .
+fi
+git remote update || git remote update # attempt to work around bug #925790
+git reset --hard
+git clean -x -f -d -q
+
+if [ ! -z "$GERRIT_REFSPEC" ]
+then
+ git checkout $GERRIT_BRANCH
+ git reset --hard remotes/origin/$GERRIT_BRANCH
+ git clean -x -f -d -q
+ git fetch https://review.<%= site %>.org/p/$GERRIT_PROJECT $GERRIT_REFSPEC
+ git merge FETCH_HEAD
+else
+ git checkout $GERRIT_NEWREV
+ git reset --hard $GERRIT_NEWREV
+ git clean -x -f -d -q
+fi
+
+
diff --git a/modules/jenkins_jobs/templates/builder_pep8.xml.erb b/modules/jenkins_jobs/templates/builder_pep8.xml.erb
new file mode 100644
index 0000000000..35a0227dd0
--- /dev/null
+++ b/modules/jenkins_jobs/templates/builder_pep8.xml.erb
@@ -0,0 +1,9 @@
+
+ #!/bin/sh
+
+if [ -f .cache.bundle ] ; then
+ tox -v -ejenkinspep8 | tee pep8.txt
+else
+ tox -v -epep8 | tee pep8.txt
+fi
+
diff --git a/modules/jenkins_jobs/templates/builder_ppa.xml.erb b/modules/jenkins_jobs/templates/builder_ppa.xml.erb
new file mode 100644
index 0000000000..e67079041a
--- /dev/null
+++ b/modules/jenkins_jobs/templates/builder_ppa.xml.erb
@@ -0,0 +1,22 @@
+
+ rm -rf build dist.zip
+mkdir build
+
+
+
+ <%= project %>-tarball
+ dist/*.tar.gz
+ build
+
+ BUILD_SELECTOR
+
+
+
+ #!/bin/bash
+
+#export DO_UPLOAD="no"
+export PROJECT="<%= project %>"
+export GERRIT_REFNAME=$BRANCH
+/bin/bash -xe ~/openstack-ci/slave_scripts/create-ppa-package.sh
+
+
diff --git a/modules/jenkins_jobs/templates/builder_python26.xml.erb b/modules/jenkins_jobs/templates/builder_python26.xml.erb
new file mode 100644
index 0000000000..0bf35607c5
--- /dev/null
+++ b/modules/jenkins_jobs/templates/builder_python26.xml.erb
@@ -0,0 +1,8 @@
+
+ if [ -f .cache.bundle ]
+then
+ tox -v -ejenkinspy26
+else
+ tox -v -epy26
+fi
+
diff --git a/modules/jenkins_jobs/templates/builder_python27.xml.erb b/modules/jenkins_jobs/templates/builder_python27.xml.erb
new file mode 100644
index 0000000000..462e5f1ed4
--- /dev/null
+++ b/modules/jenkins_jobs/templates/builder_python27.xml.erb
@@ -0,0 +1,8 @@
+
+ if [ -f .cache.bundle ]
+then
+ tox -v -ejenkinspy27
+else
+ tox -v -epy27
+fi
+
diff --git a/modules/jenkins_jobs/templates/builder_tarball.xml.erb b/modules/jenkins_jobs/templates/builder_tarball.xml.erb
new file mode 100644
index 0000000000..4c51f32b42
--- /dev/null
+++ b/modules/jenkins_jobs/templates/builder_tarball.xml.erb
@@ -0,0 +1,4 @@
+
+ ~/openstack-ci/slave_scripts/create-tarball.sh
+
+
diff --git a/modules/jenkins_jobs/templates/builder_venv.xml.erb b/modules/jenkins_jobs/templates/builder_venv.xml.erb
new file mode 100644
index 0000000000..459cc5bb6d
--- /dev/null
+++ b/modules/jenkins_jobs/templates/builder_venv.xml.erb
@@ -0,0 +1,3 @@
+
+ bash -x ~/openstack-ci/slave_scripts/build-bundle.sh
+
diff --git a/modules/jenkins_jobs/templates/logrotate.xml.erb b/modules/jenkins_jobs/templates/logrotate.xml.erb
new file mode 100644
index 0000000000..b617b7e689
--- /dev/null
+++ b/modules/jenkins_jobs/templates/logrotate.xml.erb
@@ -0,0 +1,7 @@
+
+ 3
+ 20
+ -1
+ -1
+
+
diff --git a/modules/jenkins_jobs/templates/publisher_coverage.xml.erb b/modules/jenkins_jobs/templates/publisher_coverage.xml.erb
new file mode 100644
index 0000000000..aa534f3185
--- /dev/null
+++ b/modules/jenkins_jobs/templates/publisher_coverage.xml.erb
@@ -0,0 +1,53 @@
+
+ **/coverage.xml
+ false
+
+
+
+ CONDITIONAL
+ 70
+
+
+ LINE
+ 80
+
+
+ METHOD
+ 80
+
+
+
+
+
+
+ CONDITIONAL
+ 0
+
+
+ LINE
+ 0
+
+
+ METHOD
+ 0
+
+
+
+
+
+
+ CONDITIONAL
+ 0
+
+
+ LINE
+ 0
+
+
+ METHOD
+ 0
+
+
+
+ ASCII
+
diff --git a/modules/jenkins_jobs/templates/publisher_docs.xml.erb b/modules/jenkins_jobs/templates/publisher_docs.xml.erb
new file mode 100644
index 0000000000..e8b1bf78bc
--- /dev/null
+++ b/modules/jenkins_jobs/templates/publisher_docs.xml.erb
@@ -0,0 +1,20 @@
+
+ <%= project %>.<%= site %>.org
+
+
+ docs/<%= project %>
+ doc/build/html/**
+ false
+
+
+ docs/<%= project %>/_static
+ doc/build/html/_static/**
+ false
+
+
+ docs/<%= project %>/_sources
+ doc/build/html/_sources/**
+ false
+
+
+
diff --git a/modules/jenkins_jobs/templates/publisher_pep8.xml.erb b/modules/jenkins_jobs/templates/publisher_pep8.xml.erb
new file mode 100644
index 0000000000..0fe94351b7
--- /dev/null
+++ b/modules/jenkins_jobs/templates/publisher_pep8.xml.erb
@@ -0,0 +1,179 @@
+
+
+
+
+
+
+
+
+ checkstyle
+
+ checkstyle
+ 10
+ 999
+ 999
+ false
+
+
+
+
+ codenarc
+
+ codenarc
+ 10
+ 999
+ 999
+ false
+
+
+
+
+ cpd
+
+ cpd
+ 10
+ 999
+ 999
+ false
+
+
+
+
+ cpplint
+
+ cpplint
+ 10
+ 999
+ 999
+ false
+
+
+
+
+ csslint
+
+ csslint
+ 10
+ 999
+ 999
+ false
+
+
+
+
+ findbugs
+
+ findbugs
+ 10
+ 999
+ 999
+ false
+
+
+
+
+ fxcop
+
+ fxcop
+ 10
+ 999
+ 999
+ false
+
+
+
+
+ gendarme
+
+ gendarme
+ 10
+ 999
+ 999
+ false
+
+
+
+
+ jcreport
+
+ jcreport
+ 10
+ 999
+ 999
+ false
+
+
+
+
+ jslint
+
+ jslint
+ 10
+ 999
+ 999
+ false
+
+
+
+
+ pep8
+
+ pep8
+ 0
+ 1
+ 1
+ false
+ **/pep8.txt
+
+
+
+ pmd
+
+ pmd
+ 10
+ 999
+ 999
+ false
+
+
+
+
+ pylint
+
+ pylint
+ 10
+ 999
+ 999
+ false
+
+
+
+
+ simian
+
+ simian
+ 10
+ 999
+ 999
+ false
+
+
+
+
+ stylecop
+
+ stylecop
+ 10
+ 999
+ 999
+ false
+
+
+
+
+ 100
+
+
+ default
+
+
diff --git a/modules/jenkins_jobs/templates/publisher_ppa.xml.erb b/modules/jenkins_jobs/templates/publisher_ppa.xml.erb
new file mode 100644
index 0000000000..bab1265788
--- /dev/null
+++ b/modules/jenkins_jobs/templates/publisher_ppa.xml.erb
@@ -0,0 +1,4 @@
+
+ build/*.dsc,build/*.tar.gz,build/*.changes
+ false
+
diff --git a/modules/jenkins_jobs/templates/publisher_tarball.xml.erb b/modules/jenkins_jobs/templates/publisher_tarball.xml.erb
new file mode 100644
index 0000000000..7811ecfe0e
--- /dev/null
+++ b/modules/jenkins_jobs/templates/publisher_tarball.xml.erb
@@ -0,0 +1,30 @@
+
+ dist/*.tar.gz
+ false
+
+
+ <%= project %>.<%= site %>.org
+
+
+ tarballs/<%= project %>/
+ dist/*.tar.gz
+ false
+
+
+
+
+
+
+
+
+ BUILD_SELECTOR=<SpecificBuildSelector><buildNumber>$BUILD_NUMBER</buildNumber></SpecificBuildSelector>
+BRANCH=$GERRIT_REFNAME
+
+
+
+ <%= project %>-ppa
+ SUCCESS
+ false
+
+
+
diff --git a/modules/jenkins_jobs/templates/publisher_venv.xml.erb b/modules/jenkins_jobs/templates/publisher_venv.xml.erb
new file mode 100644
index 0000000000..3a114edecc
--- /dev/null
+++ b/modules/jenkins_jobs/templates/publisher_venv.xml.erb
@@ -0,0 +1,4 @@
+
+ jenkins_venvs/**/.cache.bundle
+ false
+
diff --git a/modules/jenkins_jobs/templates/scm_git.xml.erb b/modules/jenkins_jobs/templates/scm_git.xml.erb
new file mode 100644
index 0000000000..ee026a7e26
--- /dev/null
+++ b/modules/jenkins_jobs/templates/scm_git.xml.erb
@@ -0,0 +1,34 @@
+
+ 2
+
+
+ origin
+ +refs/heads/*:refs/remotes/origin/*
+ git://github.com/<%= site %>/<%= project %>.git
+
+
+
+
+ **
+
+
+ false
+ false
+ false
+ false
+ false
+ true
+ false
+ false
+
+ Default
+
+
+
+
+
+
+
+ false
+
+
diff --git a/modules/jenkins_jobs/templates/trigger_gerrit_comment.xml.erb b/modules/jenkins_jobs/templates/trigger_gerrit_comment.xml.erb
new file mode 100644
index 0000000000..0f922951e9
--- /dev/null
+++ b/modules/jenkins_jobs/templates/trigger_gerrit_comment.xml.erb
@@ -0,0 +1,28 @@
+
+
+
+
+ PLAIN
+ <%= site %>/<%= project %>
+
+
+ ANT
+ **
+
+
+
+
+ false
+ true
+ true
+ false
+ true
+ false
+ APRV
+ 1
+
+ This change was unable to be automatically merged with the current state of the repository. Please rebase your change and upload a new patchset.
+
+
+
+
diff --git a/modules/jenkins_jobs/templates/trigger_gerrit_ref_updated.xml.erb b/modules/jenkins_jobs/templates/trigger_gerrit_ref_updated.xml.erb
new file mode 100644
index 0000000000..782d217587
--- /dev/null
+++ b/modules/jenkins_jobs/templates/trigger_gerrit_ref_updated.xml.erb
@@ -0,0 +1,25 @@
+
+ PLAIN
+ <%= site %>/<%= project %>
+
+
+ REG_EXP
+ ^(?!refs/).*$
+
+
+
+
+ false
+ true
+ false
+ false
+ false
+ true
+
+
+
+
+
+
+
+
diff --git a/modules/jenkins_jobs/templates/trigger_timed_15mins.xml.erb b/modules/jenkins_jobs/templates/trigger_timed_15mins.xml.erb
new file mode 100644
index 0000000000..183d4b2d40
--- /dev/null
+++ b/modules/jenkins_jobs/templates/trigger_timed_15mins.xml.erb
@@ -0,0 +1,3 @@
+
+ */15 * * * *
+
diff --git a/modules/jenkins_jobs/templates/trigger_timed_midnight.xml.erb b/modules/jenkins_jobs/templates/trigger_timed_midnight.xml.erb
new file mode 100644
index 0000000000..0bfde74060
--- /dev/null
+++ b/modules/jenkins_jobs/templates/trigger_timed_midnight.xml.erb
@@ -0,0 +1,3 @@
+
+ @midnight
+