diff --git a/.zuul.yaml b/.zuul.yaml
index 958368d1ce281ee2db90966bc7d511a7622b18fe..e455b42c59ebd70ce1e25af64fe40b72e99dfa25 100644
--- a/.zuul.yaml
+++ b/.zuul.yaml
@@ -36,6 +36,7 @@
     name: kolla-ansible-centos-source
     parent:  kolla-ansible-base
     nodeset: kolla-ansible-centos
+    voting: false
     vars:
       base_distro: centos
       install_type: source
@@ -44,6 +45,7 @@
     name: kolla-ansible-ubuntu-source
     parent: kolla-ansible-base
     nodeset: kolla-ansible-xenial
+    voting: false
     vars:
       base_distro: ubuntu
       install_type: source
@@ -52,6 +54,34 @@
     name: kolla-ansible-oraclelinux-source
     parent: kolla-ansible-base
     nodeset: kolla-ansible-centos
+    voting: false
     vars:
       base_distro: oraclelinux
       install_type: source
+
+- job:
+    name: kolla-ansible-centos-binary
+    parent:  kolla-ansible-base
+    nodeset: kolla-ansible-centos
+    voting: false
+    vars:
+      base_distro: centos
+      install_type: binary
+
+- job:
+    name: kolla-ansible-ubuntu-binary
+    parent: kolla-ansible-base
+    nodeset: kolla-ansible-xenial
+    voting: false
+    vars:
+      base_distro: ubuntu
+      install_type: binary
+
+- job:
+    name: kolla-ansible-oraclelinux-binary
+    parent: kolla-ansible-base
+    nodeset: kolla-ansible-centos
+    voting: false
+    vars:
+      base_distro: oraclelinux
+      install_type: binary
diff --git a/tests/get_logs.sh b/tests/get_logs.sh
index 81961ad7c4ba95241764041cd729e39bef419290..486b54a269faee6aa7cc50148c4d9d53fad694fb 100644
--- a/tests/get_logs.sh
+++ b/tests/get_logs.sh
@@ -2,22 +2,6 @@
 
 set +o errexit
 
-check_failure() {
-    # All docker container's status are created, restarting, running, removing,
-    # paused, exited and dead. Containers without running status are treated as
-    # failure. removing is added in docker 1.13, just ignore it now.
-    failed_containers=$(docker ps -a --format "{{.Names}}" \
-        --filter status=created \
-        --filter status=restarting \
-        --filter status=paused \
-        --filter status=exited \
-        --filter status=dead)
-
-    if [[ -n "$failed_containers" ]]; then
-        exit 1;
-    fi
-}
-
 copy_logs() {
     LOG_DIR=/tmp/logs
 
@@ -82,4 +66,3 @@ copy_logs() {
 }
 
 copy_logs
-check_failure
diff --git a/tests/pre.yml b/tests/pre.yml
index dd614b89c98d81cd17138d806179fee50d8f68c8..e111d691a85e7e3aed3ac63244065010b54f6d0c 100644
--- a/tests/pre.yml
+++ b/tests/pre.yml
@@ -2,6 +2,12 @@
   vars:
     logs_dir: "/tmp/logs"
   tasks:
+    - name: Install dbus for debian system
+      apt: name=dbus
+      when:
+        - ansible_os_family == 'Debian'
+      become: true
+
     - name: Ensure /tmp/logs/ dir
       file:
         path: "{{ logs_dir }}"
@@ -18,3 +24,8 @@
         - "system_logs"
         - "kolla"
         - "ansible"
+
+    - name: set new hostname based on ansible inventory file
+      hostname:
+        name: "{{ inventory_hostname }}"
+      become: true
diff --git a/tests/run.yml b/tests/run.yml
index 25eae0b2e99e1482b3c59d1fa94d2b9a0a21cf5e..f1adf6982ce92982d08386a44581d3f5ca13e0a9 100644
--- a/tests/run.yml
+++ b/tests/run.yml
@@ -3,6 +3,8 @@
   vars:
     kolla_inventory_path: "/etc/kolla/inventory"
     logs_dir: "/tmp/logs"
+    kolla_ansible_src_dir: "src/{{ zuul.project.canonical_hostname }}/openstack/kolla-ansible"
+    kolla_ansible_full_src_dir: "{{ zuul.executor.work_root }}/{{ kolla_ansible_src_dir }}"
   tasks:
     - name: ensure /etc/kolla exists
       file:
@@ -14,12 +16,12 @@
     - set_fact:
         nodes: |
           {% for host in hostvars %}
-          {{ host }} ansible_host={{ hostvars[host]['ansible_host'] }} ansible_become=true ansible_user={{ hostvars[host]['ansible_user'] }}
+          {{ host }} ansible_host={{ hostvars[host]['nodepool']['private_ipv4'] }} ansible_become=true ansible_user={{ hostvars[host]['ansible_user'] }}
           {% endfor %}
 
     - name: copy default ansible kolla-ansible inventory
       copy:
-        src: "{{ zuul.executor.work_root }}/{{ zuul.project.src_dir }}/ansible/inventory/all-in-one"
+        src: "{{ kolla_ansible_full_src_dir }}/ansible/inventory/all-in-one"
         dest: "{{ kolla_inventory_path }}"
       delegate_to: "primary"
 
@@ -30,12 +32,23 @@
         replace: "{{ nodes }}"
       delegate_to: "primary"
 
-    - name: generate global.yml file
+    # FIXME: in multi node env, api_interface may be different on each node.
+    - name: detect api_interface_name variable
       vars:
-        api_interface_name: "{{ hostvars['primary']['ansible_default_ipv4'].alias }}"
-        api_interface_address: "{{ hostvars['primary']['nodepool']['private_ipv4'] }}"
+        ansible_interface_name: "ansible_{{ item.replace('-', '_') }}"
+        api_interface_address: "{{ hostvars[inventory_hostname]['nodepool']['private_ipv4'] }}"
+      set_fact:
+        api_interface_name: "{{ item }}"
+        api_interface_address: "{{ api_interface_address }}"
+      when:
+        - hostvars[inventory_hostname][ansible_interface_name]['ipv4'] is defined
+        - hostvars[inventory_hostname][ansible_interface_name]['ipv4']['address'] == api_interface_address
+      with_items: "{{ ansible_interfaces }}"
+      delegate_to: "primary"
+
+    - name: generate global.yml file
       template:
-        src: "{{ zuul.executor.work_root }}/{{ zuul.project.src_dir }}/tests/templates/globals-default.j2"
+        src: "{{ kolla_ansible_full_src_dir }}/tests/templates/globals-default.j2"
         dest: /etc/kolla/globals.yml
       delegate_to: "primary"
 
@@ -49,23 +62,23 @@
 
     - name: generate config overrides
       template:
-        src: "{{ zuul.executor.work_root }}/{{ zuul.project.src_dir }}/tests/templates/nova-compute-overrides.j2"
+        src: "{{ kolla_ansible_full_src_dir }}/tests/templates/nova-compute-overrides.j2"
         dest: /etc/kolla/config/nova/nova-compute.conf
       delegate_to: "primary"
 
     - name: copy passwords.yml file
       copy:
-        src: "{{ zuul.executor.work_root }}/{{ zuul.project.src_dir }}/etc/kolla/passwords.yml"
+        src: "{{ kolla_ansible_full_src_dir }}/etc/kolla/passwords.yml"
         dest: /etc/kolla/passwords.yml
       delegate_to: "primary"
 
     - name: install kolla-ansible requirements
       pip:
-        requirements: "{{ ansible_env.HOME }}/{{ zuul.project.src_dir }}/requirements.txt"
+        requirements: "{{ ansible_env.HOME }}/{{ kolla_ansible_src_dir }}/requirements.txt"
       become: true
 
     - name: generate passwords
-      shell: "{{ zuul.project.src_dir }}/tools/generate_passwords.py"
+      shell: "{{ kolla_ansible_src_dir }}/tools/generate_passwords.py"
       delegate_to: "primary"
 
     - shell:
@@ -78,6 +91,6 @@
 
           tools/setup_gate.sh
         executable: /bin/bash
-        chdir: "{{ zuul.project.src_dir }}"
+        chdir: "{{ kolla_ansible_src_dir }}"
       delegate_to: "primary"
       environment: '{{ zuul | zuul_legacy_vars }}'
diff --git a/tools/setup_gate.sh b/tools/setup_gate.sh
index 8e97d6b681f44ef7cd9358f517f14af50ec2b89d..2af7ede5c73c7b97facce732735fca4482bdbbcf 100755
--- a/tools/setup_gate.sh
+++ b/tools/setup_gate.sh
@@ -151,6 +151,23 @@ function sanity_check {
     fi
 }
 
+check_failure() {
+    # All docker container's status are created, restarting, running, removing,
+    # paused, exited and dead. Containers without running status are treated as
+    # failure. removing is added in docker 1.13, just ignore it now.
+    failed_containers=$(sudo docker ps -a --format "{{.Names}}" \
+        --filter status=created \
+        --filter status=restarting \
+        --filter status=paused \
+        --filter status=exited \
+        --filter status=dead)
+
+    if [[ -n "$failed_containers" ]]; then
+        exit 1;
+    fi
+}
+
+
 
 clone_repos
 setup_ansible
@@ -191,3 +208,5 @@ tools/kolla-ansible -i ${RAW_INVENTORY} -vvv prechecks > /tmp/logs/ansible/prech
 
 ara generate html /tmp/logs/playbook_reports/
 gzip --recursive --best /tmp/logs/playbook_reports/
+
+check_failure