use async to run large downloads while doing other steps
diff --git a/cord-single-playbook.yml b/cord-single-playbook.yml
index 9da0ca4..58a87d1 100644
--- a/cord-single-playbook.yml
+++ b/cord-single-playbook.yml
@@ -32,19 +32,18 @@
     - common-prep
     - cloudlab-prep
 
-- name: Configure head node, create VM's, setup juju
+- name: Configure head node, create VM's
   hosts: head
   roles:
     - { role: head-prep, become: yes }
     - { role: config-virt, become: yes }
-    - juju-user-prep
-    - juju-setup
 
-- name: Set up XOS and ONOS
+- name: Set up VM's, juju, docker, simulate fabric
   hosts: head
   roles:
     - xos-vm-install
     - onos-vm-install
+    - juju-setup
     - docker-compose
     - simulate-fabric
 
diff --git a/roles/compute-prep/tasks/main.yml b/roles/compute-prep/tasks/main.yml
index 9a29e01..a62305f 100644
--- a/roles/compute-prep/tasks/main.yml
+++ b/roles/compute-prep/tasks/main.yml
@@ -13,7 +13,7 @@
 - name: Add head node ubuntu user key
   authorized_key:
     user=ubuntu
-    key="{{ hostvars[groups['head'][0]]['head_ssh_pubkey']['stdout'] }}"
+    key="{{ hostvars[groups['head'][0]]['sshkey']['stdout'] }}"
 
 - name: Add route via /etc/rc.local
   template:
diff --git a/roles/config-virt/tasks/main.yml b/roles/config-virt/tasks/main.yml
index 557a285..ad790a2 100644
--- a/roles/config-virt/tasks/main.yml
+++ b/roles/config-virt/tasks/main.yml
@@ -1,6 +1,13 @@
 ---
 # roles/config-virt-net/tasks/main.yml
 
+- name: Get ubuntu image for uvtool
+  command: uvt-simplestreams-libvirt sync --source http://cloud-images.ubuntu.com/daily \
+    release={{ ansible_distribution_release }} arch=amd64
+  async: 1200
+  poll: 0
+  register: uvt_sync
+
 - name: collect libvirt network facts
   virt_net:
     command=facts
diff --git a/roles/create-vms/tasks/main.yml b/roles/create-vms/tasks/main.yml
new file mode 100644
index 0000000..f75501a
--- /dev/null
+++ b/roles/create-vms/tasks/main.yml
@@ -0,0 +1,58 @@
+---
+# file: create-vms/tasks/main.yml
+
+- name: Wait for uvt-kvm image to be available
+  async_status: jid={{ uvt_sync.ansible_job_id }}
+  register: uvt_sync_result
+  until: uvt_sync_result.finished
+  delay: 10
+  retries: 120
+
+- name: create Virtual Machines with uvt-kvm
+  shell: uvt-kvm create {{ item.name }} release={{ ansible_distribution_release }} \
+    --cpu={{ item.cpu }} --memory={{ item.memMB }} --disk={{ item.diskGB }} --bridge="mgmtbr"
+    creates=/var/lib/uvtool/libvirt/images/{{ item.name }}.qcow
+  with_items: "{{ head_vm_list }}"
+
+- name: Have VMs autostart on reboot
+  become: yes
+  virt:
+    name={{ item.name }}
+    command=autostart
+  with_items: "{{ head_vm_list }}"
+
+- name: wait for VM's to come up
+  wait_for:
+    host={{ item.name }}
+    port=22
+  with_items: "{{ head_vm_list }}"
+
+- name: Create /etc/ansible/hosts file
+  become: yes
+  template:
+    src=ansible_hosts.j2
+    dest=/etc/ansible/hosts
+
+- name: Verify that we can log into every VM
+  command: ansible services -m ping -u ubuntu
+
+- name: Have VM's use the apt-cache
+  command: ansible services -b -u ubuntu -m lineinfile -a "dest=/etc/apt/apt.conf.d/02apt-cacher-ng create=yes mode=0644 owner=root group=root regexp='^Acquire' line='Acquire::http { Proxy \"http://{{ apt_cacher_name }}:{{ apt_cacher_port | default('3142') }}\"; };'"
+
+- name: Update software in all the VMs
+  command: ansible services -m apt -b -u ubuntu -a "upgrade=dist update_cache=yes cache_valid_time=3600"
+
+- name: Create VM's eth0 interface config file for DNS config via resolvconf program
+  template:
+    src=eth0.cfg.j2
+    dest={{ ansible_user_dir }}/eth0.cfg
+
+- name: Copy eth0 interface config file to all VMs
+  command: ansible services -b -u ubuntu -m copy -a "src={{ ansible_user_dir }}/eth0.cfg dest=/etc/network/interfaces.d/eth0.cfg owner=root group=root mode=0644"
+
+- name: Restart eth0 interface on all VMs
+  command: ansible services -b -u ubuntu -m shell -a "ifdown eth0 ; ifup eth0"
+
+- name: Verify that we can log into every VM after restarting network interfaces
+  command: ansible services -m ping -u ubuntu
+
diff --git a/roles/juju-setup/templates/ansible_hosts.j2 b/roles/create-vms/templates/ansible_hosts.j2
similarity index 100%
rename from roles/juju-setup/templates/ansible_hosts.j2
rename to roles/create-vms/templates/ansible_hosts.j2
diff --git a/roles/docker-compose/tasks/main.yml b/roles/docker-compose/tasks/main.yml
index d97da2e..8fa17aa 100644
--- a/roles/docker-compose/tasks/main.yml
+++ b/roles/docker-compose/tasks/main.yml
@@ -1,20 +1,33 @@
 ---
-# docker-compose-pull/tasks/main.yml
+# docker-compose/tasks/main.yml
 
-# Note: build/pull are mutually exclusive in this case
+- name: Wait for onos_setup_playbook to complete
+  async_status: jid={{ onos_setup_playbook.ansible_job_id }}
+  register: onos_setup_playbook_result
+  until: onos_setup_playbook_result.finished
+  delay: 10
+  retries: 120
 
-- name: Build images from dockerhub with docker-compose
-  command: ansible "{{ item.name }}" -b -u ubuntu -m command \
-                    -a "docker-compose build chdir={{ item.path | expanduser }}"
-  with_items: "{{ docker_compose_list | selectattr('build') | list}}"
+- name: Copy SSL Certs to ONOS so docker-compose can find it
+  command: ansible onos-cord-1 -b -u ubuntu -m copy \
+    -a "src=/usr/local/share/ca-certificates/keystone_juju_ca_cert.crt dest={{ ansible_user_dir }}/cord/xos-certs.crt"
 
-- name: Pull images from dockerhub with docker-compose
-  command: ansible "{{ item.name }}" -b -u ubuntu -m command \
-                    -a "docker-compose pull chdir={{ item.path | expanduser }}"
-  with_items: "{{ docker_compose_list | rejectattr('build') | list}}"
+- name: Build ONOS image with docker-compose
+  command: ansible onos-cord-1 -b -u ubuntu -m command \
+    -a "docker-compose build chdir=cord"
 
-- name: Run "docker-compose up" where required
-  command: ansible "{{ item.name }}" -b -u ubuntu -m command \
-                    -a "docker-compose up -d chdir={{ item.path | expanduser }}"
-  with_items: "{{ docker_compose_list | selectattr('up') | list}}"
+- name: Start ONOS
+  command: ansible onos-cord-1 -b -u ubuntu -m command \
+    -a "docker-compose up -d chdir=cord"
+
+- name: Wait for xos_setup_playbook to complete
+  async_status: jid={{ xos_setup_playbook.ansible_job_id }}
+  register: xos_setup_playbook_result
+  until: xos_setup_playbook_result.finished
+  delay: 10
+  retries: 120
+
+- name: Copy admin-openrc.sh into XOS container
+  command: ansible xos-1 -b -u ubuntu -m copy \
+    -a "src=~/admin-openrc.sh dest={{ xos_repo_dest }}/xos/configurations/{{ xos_configuration }}"
 
diff --git a/roles/juju-user-prep/files/ansible.cfg b/roles/juju-setup/files/ansible.cfg
similarity index 100%
rename from roles/juju-user-prep/files/ansible.cfg
rename to roles/juju-setup/files/ansible.cfg
diff --git a/roles/juju-setup/tasks/main.yml b/roles/juju-setup/tasks/main.yml
index cc24074..acbae5e 100644
--- a/roles/juju-setup/tasks/main.yml
+++ b/roles/juju-setup/tasks/main.yml
@@ -1,63 +1,19 @@
 ---
 # roles/juju-setup/main/tasks.yml
 
-- name: Get ubuntu image for uvtool
-  become: yes
-  command: uvt-simplestreams-libvirt sync --source http://cloud-images.ubuntu.com/daily \
-    release={{ ansible_distribution_release }} arch=amd64
+- name: Disable host key checking in ~/.ssh/config
+  lineinfile:
+    dest={{ ansible_user_dir }}/.ssh/config
+    line="StrictHostKeyChecking no"
+    create=yes
+    mode=0600
 
-- name: create Virtual Machines with uvt-kvm
-  shell: uvt-kvm create {{ item.name }} release={{ ansible_distribution_release }} \
-    --cpu={{ item.cpu }} --memory={{ item.memMB }} --disk={{ item.diskGB }} --bridge="mgmtbr"
-    creates=/var/lib/uvtool/libvirt/images/{{ item.name }}.qcow
-  with_items: "{{ head_vm_list }}"
+- name: Disable host key checking in ~/.ansible.cfg
+  copy:
+    src=ansible.cfg
+    dest={{ ansible_user_dir }}/.ansible.cfg
 
-- name: Have VMs autostart on reboot
-  become: yes
-  virt:
-    name={{ item.name }}
-    command=autostart
-  with_items: "{{ head_vm_list }}"
-
-- name: wait for VM's to come up
-  wait_for:
-    host={{ item.name }}
-    port=22
-  with_items: "{{ head_vm_list }}"
-
-- name: Create /etc/ansible/hosts file
-  become: yes
-  template:
-    src=ansible_hosts.j2
-    dest=/etc/ansible/hosts
-
-- name: Verify that we can log into every VM
-  command: ansible services -m ping -u ubuntu
-
-- name: Have VM's use the apt-cache
-  command: ansible services -b -u ubuntu -m lineinfile -a "dest=/etc/apt/apt.conf.d/02apt-cacher-ng create=yes mode=0644 owner=root group=root regexp='^Acquire' line='Acquire::http { Proxy \"http://{{ apt_cacher_name }}:{{ apt_cacher_port | default('3142') }}\"; };'"
-
-- name: Update software in all the VMs
-  command: ansible services -m apt -b -u ubuntu -a "upgrade=dist update_cache=yes cache_valid_time=3600"
-
-- name: Create VM's eth0 interface config file for DNS config via resolvconf program
-  template:
-    src=eth0.cfg.j2
-    dest={{ ansible_user_dir }}/eth0.cfg
-
-- name: Copy eth0 interface config file to all VMs
-  command: ansible services -b -u ubuntu -m copy -a "src={{ ansible_user_dir }}/eth0.cfg dest=/etc/network/interfaces.d/eth0.cfg owner=root group=root mode=0644"
-
-- name: Restart eth0 interface on all VMs
-  command: ansible services -b -u ubuntu -m shell -a "ifdown eth0 ; ifup eth0"
-
-- name: Verify that we can log into every VM after restarting network interfaces
-  command: ansible services -m ping -u ubuntu
-
-- name: Register public key in variable
-  shell: cat {{ ansible_user_dir }}/.ssh/id_rsa.pub
-  register: sshkey
-
+# sshkey is registered in head-prep task
 - name: Enable root ssh login on VM's that need it
   command: ansible {{ item.name }} -b -u ubuntu -m authorized_key -a "user='root' key='{{ sshkey.stdout }}'"
   with_items: "{{ head_vm_list | selectattr('root_ssh_login', 'defined') | list }}"
diff --git a/roles/juju-user-prep/tasks/main.yml b/roles/juju-user-prep/tasks/main.yml
deleted file mode 100644
index bcc4a6f..0000000
--- a/roles/juju-user-prep/tasks/main.yml
+++ /dev/null
@@ -1,19 +0,0 @@
----
-# roles/juju-user-prep/main/tasks.yml
-
-- name: Disable host key checking in ~/.ssh/config
-  lineinfile:
-    dest={{ ansible_user_dir }}/.ssh/config
-    line="StrictHostKeyChecking no"
-    create=yes
-    mode=0600
-
-- name: Disable host key checking in ~/.ansible.cfg
-  copy:
-    src=ansible.cfg
-    dest={{ ansible_user_dir }}/.ansible.cfg
-
-- name: Get public ssh key from head node ubuntu user
-  command: cat {{ ansible_user_dir }}/.ssh/id_rsa.pub
-  register: head_ssh_pubkey
-
diff --git a/roles/onos-vm-install/files/onos-setup-playbook.yml b/roles/onos-vm-install/files/onos-setup-playbook.yml
index ba88406..b18924b 100644
--- a/roles/onos-vm-install/files/onos-setup-playbook.yml
+++ b/roles/onos-vm-install/files/onos-setup-playbook.yml
@@ -62,10 +62,6 @@
        - id_rsa
        - id_rsa.pub
 
-    - name: Copy SSL Certs so docker-compose can find it
-      command: cp /usr/local/share/ca-certificates/keystone_juju_ca_cert.crt {{ ansible_user_dir }}/cord/xos-certs.crt
-        creates="{{ ansible_user_dir }}/cord/xos-certs.crt"
-
     - name: Copy over files to build XOS variant of ONOS
       copy:
         src="~/{{ item }}"
@@ -79,3 +75,6 @@
         src=~/onos-docker-compose.yml
         dest={{ ansible_user_dir }}/cord/docker-compose.yml
 
+    - name: Pull docker image for ONOS
+      command: docker pull onosproject/onos
+
diff --git a/roles/onos-vm-install/tasks/main.yml b/roles/onos-vm-install/tasks/main.yml
index 3f78d27..0dbb54f 100644
--- a/roles/onos-vm-install/tasks/main.yml
+++ b/roles/onos-vm-install/tasks/main.yml
@@ -20,4 +20,7 @@
 
 - name: Run the ONOS ansible playbook
   command: ansible-playbook {{ ansible_user_dir }}/onos-setup-playbook.yml
+  async: 1200
+  poll: 0
+  register: onos_setup_playbook
 
diff --git a/roles/xos-vm-install/files/xos-setup-cord-pod-playbook.yml b/roles/xos-vm-install/files/xos-setup-cord-pod-playbook.yml
index a55ad9f..124a719 100644
--- a/roles/xos-vm-install/files/xos-setup-cord-pod-playbook.yml
+++ b/roles/xos-vm-install/files/xos-setup-cord-pod-playbook.yml
@@ -39,20 +39,17 @@
        - id_rsa
        - id_rsa.pub
 
-    - name: copy over admin-openrc.sh
-      copy:
-        src=~/admin-openrc.sh
-        dest={{ xos_repo_dest }}/xos/configurations/{{ xos_configuration }}
-
-    - name: copy over SSH key as node_key
-      copy:
-        src=~/.ssh/id_rsa
-        dest={{ xos_repo_dest }}//xos/configurations/{{ xos_configuration }}/node_key
-
     - name: download software image
       get_url:
         url=http://www.vicci.org/opencloud/trusty-server-cloudimg-amd64-disk1.img
         checksum=sha256:5fb160ea09649f9cebe5cfd7aaf3d1a341e8e0f9eca6e52e46eb6271155c48b0
         dest={{ xos_repo_dest }}/xos/configurations/{{ xos_configuration }}/images/trusty-server-multi-nic.img
 
+    - name: copy over SSH key as node_key
+      copy:
+        src=~/.ssh/id_rsa
+        dest={{ xos_repo_dest }}/xos/configurations/{{ xos_configuration }}/node_key
+
+    - name: Pull docker images for XOS
+      command: docker-compose pull chdir={{ xos_repo_dest }}/xos/configurations/{{ xos_configuration }}
 
diff --git a/roles/xos-vm-install/tasks/main.yml b/roles/xos-vm-install/tasks/main.yml
index 8f2eb2a..38d3e84 100644
--- a/roles/xos-vm-install/tasks/main.yml
+++ b/roles/xos-vm-install/tasks/main.yml
@@ -15,4 +15,7 @@
 
 - name: Run the XOS ansible playbook
   command: ansible-playbook {{ ansible_user_dir }}/xos-setup-playbook.yml
+  async: 1200
+  poll: 0
+  register: xos_setup_playbook