ONOS-7330 Added ONOS-P4 VM build script

Builds and OVA from scratch with the most updated tools in one command.
The build process is based on Vagrant.

Change-Id: I633d99092946f99e877f0c97631a4f99c5b1f37e
diff --git a/tools/dev/p4vm/.gitignore b/tools/dev/p4vm/.gitignore
new file mode 100644
index 0000000..c67d4b1
--- /dev/null
+++ b/tools/dev/p4vm/.gitignore
@@ -0,0 +1,2 @@
+.vagrant
+*.ova
diff --git a/tools/dev/p4vm/README.md b/tools/dev/p4vm/README.md
new file mode 100644
index 0000000..de9edb7
--- /dev/null
+++ b/tools/dev/p4vm/README.md
@@ -0,0 +1,101 @@
+# ONOS-P4 Developer Virtual Machine
+
+This directory contains files necessary to build and provision a VM to test and
+develop ONOS support for P4 Runtime.
+
+For more information on P4 support in ONOS please visit the following web page:
+<https://wiki.onosproject.org/x/FYnV>
+
+This document contains also instructions on how to download a pre-built VM.
+
+## Contents
+
+The VM is based on Ubuntu 16.04 (server) and contains the following software:
+
+- ONOS
+- BMv2 (P4 software switch with P4Runtime support)
+- p4c (P4 compiler)
+- Mininet (network emulator)
+
+## Recommended system requirements
+
+The VM is configured with 4 GB of RAM and 2 CPU cores, while the disk has size
+of approx. 8 GB. For a flawless experience we recommend running the VM on a host
+system that has at least the double of resources.
+
+These are the recommended minimum requirements to be able to run a Mininet
+network with 1-10 BMv2 devices controlled by 1 ONOS instance. To emulate larger
+networks with multiple instances of ONOS (for example using
+[`onos.py`](https://wiki.onosproject.org/x/GAOW)), we recommend configuring the
+VM to use at least 4 CPU cores.
+
+To modify the VM configuration you can either modify the
+[Vagrantfile](./Vagrantfile) (look for `vb.cpus`) before starting the build
+process, or use the VirtualBox VM settings after you have imported the
+pre-built VM.
+
+## Download a pre-built VM
+
+Building the VM takes around 30-50 minutes, depending on your Internet
+connection speed. If you would rather not wait, you can use the following link
+to download an Open Virtual Appliance (OVA) package to be imported using
+VirtualBox or any other x86 virtualization system that supports this format.
+
+Pre-built OVA package (approx. 3.5 GB):
+<http://onlab.vicci.org/onos/onos-p4-dev.ova>
+
+### Login credentials
+
+The VM comes with one user with sudo privileges named `sdn` with password `rocks`.
+Use these credentials to log in the guest Ubuntu system.
+
+## Build the VM
+
+### Requirements
+
+To build the VM you will need the following software installed in your host
+machine:
+
+- [Vagrant](https://www.vagrantup.com/) (tested v2.0.1)
+- [VirtualBox](https://www.virtualbox.org/wiki/Downloads) (tested with v5.2.2)
+
+Optionally, to export the VM as an OVA package you will also need
+[sshpass](https://gist.github.com/arunoda/7790979).
+
+### Build using Vagrant
+
+The VM can be generated locally using Vagrant. In a terminal window type:
+
+```bash
+cd $ONOS_ROOT/tools/dev/p4vm
+vagrant up
+```
+
+Once Vagrant has provisioned the VM, you can access to it using the `vagrant
+ssh` command. However, this command will log in to the guest Ubuntu shell with
+the default `vagrant` user. To use ONOS and the other P4 tools, we suggest using
+the `sdn` user. Once you are able to access the VM using `vagrant ssh`, use the
+following command to switch to the `sdn` user:
+
+```bash
+sudo su sdn
+```
+
+### Export as OVA package 
+
+It is possible to generate an OVA package to distribute a pre-built VM.
+To generate the OVA file, in a terminal window type the following commands:
+
+```bash
+cd $ONOS_ROOT/tools/dev/p4vm
+./build-ova.sh
+```
+
+This script will:
+
+1. provision the VM using Vagrant;
+2. remove the `vagrant` user;
+3. reduce VM disk size (by removing build artifacts);
+4. generate a file named `onos-p4-dev.ova`.
+
+The generated OVA file will have size of approx. 3.5-4 GB.
diff --git a/tools/dev/p4vm/Vagrantfile b/tools/dev/p4vm/Vagrantfile
new file mode 100644
index 0000000..69580be
--- /dev/null
+++ b/tools/dev/p4vm/Vagrantfile
@@ -0,0 +1,14 @@
+Vagrant.configure(2) do |config|
+  config.vm.box = "bento/ubuntu-16.04"
+  config.vm.provider "virtualbox" do |vb|
+    vb.name = "ONOS-P4 Dev " + Time.now.strftime("(%Y-%m-%d)")
+    vb.gui = true
+    vb.cpus = 2
+    vb.memory = 4096
+  end
+  config.vm.hostname = "onos-p4-dev"
+  # By default vagrant creates a NAT interface.
+  # Create a second one host-only.
+  config.vm.network "private_network", :type => 'dhcp', :adapter => 2
+  config.vm.provision "shell", path: "root-bootstrap.sh"
+end
diff --git a/tools/dev/p4vm/export-ova.sh b/tools/dev/p4vm/export-ova.sh
new file mode 100755
index 0000000..73d6ef5
--- /dev/null
+++ b/tools/dev/p4vm/export-ova.sh
@@ -0,0 +1,26 @@
+#!/usr/bin/env bash
+
+set -xe
+
+# Remove references to the existing vagrant-built VM (if any).
+# We want to build a new one from scratch, not start an existing one.
+rm -rf .vagrant/
+
+vagrant up
+
+SSH_PORT=`vagrant port --guest 22`
+VB_UUID=`cat .vagrant/machines/default/virtualbox/id`
+
+sshpass -p 'rocks' \
+    ssh -o UserKnownHostsFile=/dev/null -o StrictHostKeyChecking=no \
+    -p ${SSH_PORT} sdn@127.0.0.1 "bash /vagrant/pre-ova-cleanup.sh"
+
+vagrant halt
+
+sleep 5
+
+# Remove vagrant shared folder
+vboxmanage sharedfolder remove ${VB_UUID} -name "vagrant"
+
+rm -rf onos-p4-dev.ova
+vboxmanage export ${VB_UUID} -o onos-p4-dev.ova
diff --git a/tools/dev/p4vm/pre-ova-cleanup.sh b/tools/dev/p4vm/pre-ova-cleanup.sh
new file mode 100755
index 0000000..17b15f3
--- /dev/null
+++ b/tools/dev/p4vm/pre-ova-cleanup.sh
@@ -0,0 +1,16 @@
+#!/usr/bin/env bash
+
+set -xe
+
+# Delete vagrant user
+sudo userdel -r -f vagrant
+
+# Free space on disk
+cd ~/p4tools/protobuf && make clean
+cd ~/p4tools/grpc && make clean
+cd ~/p4tools/bmv2 && make clean
+cd ~/p4tools/bmv2/targets && make clean
+cd ~/p4tools/p4runtime && make clean
+rm -rf ~/p4tools/p4c/build
+
+cat /dev/null > ~/.bash_history
diff --git a/tools/dev/p4vm/root-bootstrap.sh b/tools/dev/p4vm/root-bootstrap.sh
new file mode 100755
index 0000000..3f1b8e6
--- /dev/null
+++ b/tools/dev/p4vm/root-bootstrap.sh
@@ -0,0 +1,30 @@
+#!/bin/bash
+set -xe
+
+# Create user sdn
+useradd -m -d /home/sdn -s /bin/bash sdn
+echo "sdn:rocks" | chpasswd
+echo "sdn ALL=(ALL) NOPASSWD:ALL" > /etc/sudoers.d/99_sdn
+chmod 440 /etc/sudoers.d/99_sdn
+usermod -aG vboxsf sdn
+
+# Java 8
+apt-get install software-properties-common -y
+add-apt-repository ppa:webupd8team/java -y
+apt-get update
+echo "oracle-java8-installer shared/accepted-oracle-license-v1-1 select true" | debconf-set-selections
+
+apt-get -y install \
+    oracle-java8-installer oracle-java8-set-default \
+    zip unzip \
+    bridge-utils
+
+tee -a /etc/ssh/sshd_config <<EOF
+
+UseDNS no
+EOF
+
+su sdn <<'EOF'
+cd /home/sdn
+bash /vagrant/user-bootstrap.sh
+EOF
diff --git a/tools/dev/p4vm/upload-ova.sh b/tools/dev/p4vm/upload-ova.sh
new file mode 100755
index 0000000..aaf6a1c
--- /dev/null
+++ b/tools/dev/p4vm/upload-ova.sh
@@ -0,0 +1,4 @@
+#!/usr/bin/env bash
+
+python $ONOS_ROOT/tools/build/uploadToS3.py ./onos-p4-dev.ova
+
diff --git a/tools/dev/p4vm/user-bootstrap.sh b/tools/dev/p4vm/user-bootstrap.sh
new file mode 100755
index 0000000..d8f3709
--- /dev/null
+++ b/tools/dev/p4vm/user-bootstrap.sh
@@ -0,0 +1,18 @@
+#!/bin/bash
+set -xe
+
+cp /etc/skel/.bashrc ~/
+cp /etc/skel/.profile ~/
+cp /etc/skel/.bash_logout ~/
+
+# ONOS
+git clone https://github.com/opennetworkinglab/onos.git
+echo "export ONOS_ROOT=~/onos" >> ~/.bashrc
+echo "source ~/onos/tools/dev/bash_profile" >> ~/.bashrc
+
+# Build and install P4 tools
+bash ~/onos/tools/dev/bin/onos-setup-p4-dev
+
+# Mininet
+git clone git://github.com/mininet/mininet ~/mininet
+sudo ~/mininet/util/install.sh -nwv