diff --git a/manifests/site.pp b/manifests/site.pp
index 2a975191d6..142018b945 100644
--- a/manifests/site.pp
+++ b/manifests/site.pp
@@ -497,9 +497,10 @@ node /^precisepy3k-?\d+.*\.slave\.openstack\.org$/ {
   include openstack_project
   include openstack_project::puppet_cron
   class { 'openstack_project::slave':
-    ssh_key   => $openstack_project::jenkins_ssh_key,
-    sysadmins => hiera('sysadmins'),
-    python3   => true,
+    ssh_key      => $openstack_project::jenkins_ssh_key,
+    sysadmins    => hiera('sysadmins'),
+    python3      => true,
+    include_pypy => true,
   }
 }
 
@@ -507,9 +508,10 @@ node /^precisepy3k-dev\d+.*\.slave\.openstack\.org$/ {
   include openstack_project
   include openstack_project::puppet_cron
   class { 'openstack_project::slave':
-    ssh_key   => $openstack_project::jenkins_dev_ssh_key,
-    sysadmins => hiera('sysadmins'),
-    python3   => true,
+    ssh_key      => $openstack_project::jenkins_dev_ssh_key,
+    sysadmins    => hiera('sysadmins'),
+    python3      => true,
+    include_pypy => true,
   }
 }
 
diff --git a/modules/jenkins/manifests/slave.pp b/modules/jenkins/manifests/slave.pp
index 77e0e6108a..60aace4888 100644
--- a/modules/jenkins/manifests/slave.pp
+++ b/modules/jenkins/manifests/slave.pp
@@ -6,6 +6,7 @@ class jenkins::slave(
   $bare = false,
   $user = true,
   $python3 = false,
+  $include_pypy = false
 ) {
 
   include pip
@@ -340,6 +341,14 @@ class jenkins::slave(
       refreshonly => true,
       command     => '/sbin/sysctl -p /etc/sysctl.d/10-ptrace.conf',
     }
+
+    if $include_pypy {
+      apt::ppa { 'ppa:pypy/pypy': }
+      package { 'pypy':
+        ensure  => present,
+        require => Apt::Ppa['ppa:pypy/pypy']
+      }
+    }
   }
 
   file { '/etc/rsyslog.d/99-maxsize.conf':
diff --git a/modules/openstack_project/files/jenkins_job_builder/config/macros.yaml b/modules/openstack_project/files/jenkins_job_builder/config/macros.yaml
index 252704752a..2ff8e9e457 100644
--- a/modules/openstack_project/files/jenkins_job_builder/config/macros.yaml
+++ b/modules/openstack_project/files/jenkins_job_builder/config/macros.yaml
@@ -146,6 +146,11 @@
     builders:
       - shell: "/usr/local/jenkins/slave_scripts/run-tox.sh 33 {github-org} {project}"
 
+- builder:
+    name: pypy
+    builders:
+      - shell: "/usr/local/jenkins/slave_scripts/run-tox.sh py {github-org} {project}"
+
 - builder:
     name: assert-no-extra-files
     builders:
diff --git a/modules/openstack_project/files/jenkins_job_builder/config/projects.yaml b/modules/openstack_project/files/jenkins_job_builder/config/projects.yaml
index 1dc1978fbe..5d07abc32a 100644
--- a/modules/openstack_project/files/jenkins_job_builder/config/projects.yaml
+++ b/modules/openstack_project/files/jenkins_job_builder/config/projects.yaml
@@ -739,6 +739,7 @@
 
     jobs:
       - python-jobs
+      - gate-{name}-pypy
 
 
 - project:
diff --git a/modules/openstack_project/files/jenkins_job_builder/config/python-jobs.yaml b/modules/openstack_project/files/jenkins_job_builder/config/python-jobs.yaml
index 1e251bf274..1381ce5e76 100644
--- a/modules/openstack_project/files/jenkins_job_builder/config/python-jobs.yaml
+++ b/modules/openstack_project/files/jenkins_job_builder/config/python-jobs.yaml
@@ -116,6 +116,28 @@
 
     node: precisepy3k
 
+- job-template:
+    name: 'gate-{name}-pypy'
+
+    wrappers:
+      - timeout:
+          timeout: 40
+          fail: true
+      - timestamps
+
+    builders:
+      - gerrit-git-prep
+      - pypy:
+          github-org: '{github-org}'
+          project: '{name}'
+      - assert-no-extra-files
+
+    publishers:
+      - test-results
+      - console-log
+
+    node: precisepy3k
+
 - job-template:
     name: 'gate-{name}-docs'
 
diff --git a/modules/openstack_project/files/zuul/layout.yaml b/modules/openstack_project/files/zuul/layout.yaml
index 859166ebac..45d913eb46 100644
--- a/modules/openstack_project/files/zuul/layout.yaml
+++ b/modules/openstack_project/files/zuul/layout.yaml
@@ -1678,11 +1678,13 @@ projects:
       - gate-marconi-python26
       - gate-marconi-python27
       - gate-marconi-python33
+      - gate-marconi-pypy
     gate:
       - gate-marconi-pep8
       - gate-marconi-python26
       - gate-marconi-python27
       - gate-marconi-python33
+      - gate-marconi-pypy
 
   - name: stackforge/staccato
     check:
diff --git a/modules/openstack_project/manifests/slave.pp b/modules/openstack_project/manifests/slave.pp
index eb8b818a2b..6cf964f3a0 100644
--- a/modules/openstack_project/manifests/slave.pp
+++ b/modules/openstack_project/manifests/slave.pp
@@ -5,7 +5,8 @@ class openstack_project::slave (
   $certname = $::fqdn,
   $ssh_key = '',
   $sysadmins = [],
-  $python3 = false
+  $python3 = false,
+  $include_pypy = false
 ) {
   include openstack_project
   include openstack_project::tmpcleanup
@@ -16,9 +17,10 @@ class openstack_project::slave (
     sysadmins                 => $sysadmins,
   }
   class { 'jenkins::slave':
-    bare    => $bare,
-    ssh_key => $ssh_key,
-    python3 => $python3,
+    bare         => $bare,
+    ssh_key      => $ssh_key,
+    python3      => $python3,
+    include_pypy => $include_pypy,
   }
   class { 'salt':
     salt_master => 'ci-puppetmaster.openstack.org',