provision.sh revision eae889b3
1#!/usr/bin/env bash
2#
3# Copyright (c) 2016 Intel Corporation
4# Licensed under the Apache License, Version 2.0 (the "License");
5# you may not use this file except in compliance with the License.
6# You may obtain a copy of the License at:
7#
8#     http://www.apache.org/licenses/LICENSE-2.0
9#
10# Unless required by applicable law or agreed to in writing, software
11# distributed under the License is distributed on an "AS IS" BASIS,
12# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13# See the License for the specific language governing permissions and
14# limitations under the License.
15
16PACKAGE_REPO="https://nexus.fd.io/content/repositories/fd.io.stable.1701.ubuntu.trusty.main/"
17HOME_DIR="/home/$USER"
18RC_LOCAL="/etc/rc.local"
19SSH_OPTIONS="-o UserKnownHostsFile=/dev/null -o StrictHostKeyChecking=no"
20APT_PROXY_CONF="/etc/apt/apt.conf.d/01proxy"
21ENV_FILE="/etc/environment"
22UNAMER=$(uname -r)
23
24# LXC gives backend interfaces horrible names, give them a better name.
25function rename_veth_interface() {
26
27    local cntr="$1"
28    local nifname="$2"
29
30    ifr_index=`sudo lxc-attach -n $cntr -- ip -o link | tail -n 1 | awk -F : '{print $1}'`
31    ifr_index=$((ifr_index+1))
32
33    for dir in /sys/class/net/*/
34    do
35        ifindex=`cat $dir/ifindex`
36        if [ $ifindex == $ifr_index ]
37            then ifname=`basename $dir`
38        fi
39    done
40
41    sudo ip link set $ifname down
42    sudo ip link set $ifname name $nifname
43    sudo ip link set $nifname up
44}
45
46function add_to_rc_local()
47{
48    local str="$1"
49
50    echo -e "$str" | sudo tee -a $RC_LOCAL
51}
52
53function sudo_exec() {
54
55   CMD="$1"
56   add_to_rc_local="${2:-0}"
57
58   if [ "$add_to_rc_local" == "1" ]; then
59       add_to_rc_local "$CMD"
60   fi
61
62   CMD="sudo $CMD"
63
64   eval "${CMD}"
65}
66
67function lxc_exec() {
68
69    cntr="$1"
70    rCMD="$2"
71    add_to_rc_local="${3:-0}"
72 
73    CMD="lxc-attach -n $cntr  -- $rCMD"
74
75    echo "$CMD"
76    sudo_exec "$CMD" $add_to_rc_local
77}
78
79function get_field() {
80    file="$1"
81    field="$2"
82
83    value=$(grep $field $file | awk -F : '{print $2}' | sed -e 's/^[ ]*//' | sed -e 's/kernver/"$UNAMER"/')
84    echo $value
85}
86
87sudo sysctl -w vm.nr_hugepages=128
88HUGEPAGES=`sudo sysctl -n  vm.nr_hugepages`
89if [ $HUGEPAGES != 128 ]; then
90    echo "ERROR: Unable to get 128 hugepages, only got $HUGEPAGES.  Cannot finish."
91    exit
92fi
93
94echo "deb $PACKAGE_REPO ./" | sudo tee -a /etc/apt/sources.list.d/99fd.io.list
95sudo apt-get -qq update
96sudo apt-get -qq install -y --force-yes lxc bridge-utils tmux vpp vpp vpp-dpdk-dkms
97
98#Fix VPP on the host to use 128 hugepages
99sudo sed -i 's/vm.nr_hugepages=1024/vm.nr_hugepages=128/' /etc/sysctl.d/80-vpp.conf
100sudo sed -i 's/kernel.shmmax=2147483648/kernel.shmmax=268435456/' /etc/sysctl.d/80-vpp.conf
101
102#Provision containers with two network connections, second connection is unconnected
103echo -e "lxc.network.name=veth0" | sudo tee -a /etc/lxc/default.conf
104echo -e "lxc.network.type = veth" | sudo tee -a /etc/lxc/default.conf
105echo -e "lxc.network.hwaddr = 00:17:3e:xx:xx:xx\n" | sudo tee -a /etc/lxc/default.conf
106echo -e "lxc.network.name=veth_link1" | sudo tee -a /etc/lxc/default.conf
107
108sudo lxc-checkconfig
109
110# update rc.local to be interpreted with bash
111sudo sed -i '1 s/^.*$/#!\/bin\/bash/g' $RC_LOCAL
112# remove the exit 0 from rc.local.
113sudo sed -i 's/exit 0//' $RC_LOCAL
114
115# add rename_veth_interface to /etc/rc.local
116read -r -d '' TMP_RVI <<'EOF'
117function rename_veth_interface() {
118
119    local cntr="$1"
120    local nifname="$2"
121
122    ifr_index=`sudo lxc-attach -n $cntr -- ip -o link | tail -n 1 | awk -F : '{print $1}'`
123    ifr_index=$((ifr_index+1))
124
125    for dir in /sys/class/net/*/
126    do
127        ifindex=`cat $dir/ifindex`
128        if [ $ifindex == $ifr_index ]
129            then ifname=`basename $dir`
130        fi
131    done
132
133    sudo ip link set $ifname down
134    sudo ip link set $ifname name $nifname
135    sudo ip link set $nifname up
136}
137EOF
138add_to_rc_local "$TMP_RVI"
139
140# For the moment just cross connect the host, will more clever later.
141read -r -d '' TMP_CCI <<'EOF'
142function cross_connect_interfaces() {
143
144   sudo vppctl create host-interface name veth-cone
145   sudo vppctl create host-interface name veth-ctwo
146   sudo vppctl set int l2 xconnect host-veth-cone host-veth-ctwo
147   sudo vppctl set int l2 xconnect host-veth-ctwo host-veth-cone
148   sudo vppctl set int state host-veth-cone up
149   sudo vppctl set int state host-veth-ctwo up
150}
151EOF
152add_to_rc_local "$TMP_CCI"
153
154ssh-keygen -t rsa -b 1024 -N "" -f ~/.ssh/id_rsa
155openssh_pubkey=`cat ~/.ssh/id_rsa.pub`
156
157#Ensure that virtual bridge comes up after boot
158add_to_rc_local "#autostart vpp on the host"
159sudo_exec "service vpp start" 1
160
161for f in $(ls /vagrant/containers/*.cntr)
162do
163    i=$(basename $f | sed s/.cntr//)
164    dist=$(get_field $f DIST)
165    ver=$(get_field $f VER)
166    packages=$(get_field $f PACKAGES)
167    pip=$(get_field $f PIP)
168    provision_file="/vagrant/containers/"$i".provision.sh"
169 
170    sudo lxc-create -t download -n $i -- --dist $dist --release $ver --arch amd64
171
172    #autostart container after a reboot (standard lxc way doesn't work).
173    add_to_rc_local "#autostart container $i"
174
175    sudo_exec "lxc-start -n $i -d" 1
176	
177    lxc_exec $i "resolvconf -d veth0"
178
179    #dhcp after boot
180    lxc_exec $i "dhclient veth0" 1
181
182    #insert delay to allow completion before starting ssh service
183    add_to_rc_local "sleep 1"
184
185    lxc_exec $i "apt-get -qq install -y git openssh-server"
186    lxc_exec $i "apt-get -qq update"
187
188    lxc_exec $i "adduser --disabled-password --gecos \"\" $USER"
189
190    lxc_exec $i "mkdir -p /root/.ssh/"
191    lxc_exec $i "mkdir -p $HOME_DIR/.ssh/"
192
193    lxc_exec $i "sh -c 'echo $openssh_pubkey >> /root/.ssh/authorized_keys'"
194    lxc_exec $i "sh -c 'echo $openssh_pubkey >> $HOME_DIR/.ssh/authorized_keys'"
195
196    lxc_exec $i "chmod 0600 /root/.ssh/authorized_keys"
197    lxc_exec $i "chmod 0600 $HOME_DIR/.ssh/authorized_keys"
198
199    lxc_exec $i "chown -R $USER.$USER $HOME_DIR/.ssh/"
200
201    lxc_exec $i "sh -c 'echo \"%$USER ALL=(ALL) NOPASSWD: ALL\" > /etc/sudoers.d/10_$USER'"
202
203    lxc_exec $i "update-alternatives --install /bin/sh sh /bin/bash 100"
204
205    lxc_exec $i "apt-get -qq install $packages"
206
207    lxc_exec $i "service ssh restart" 1
208
209    ip_address=$(sudo lxc-ls -f | grep $i | awk '{print $5}')
210    echo $ip_address $i | sudo tee -a /etc/hosts
211
212    if [ -s $APT_PROXY_CONF ]
213    then
214        scp $SSH_OPTIONS $APT_PROXY_CONF root@$i:$APT_PROXY_CONF
215    fi
216
217    if [ -s $ENV_FILE ]
218    then
219        scp $SSH_OPTIONS $ENV_FILE root@$i:$ENV_FILE
220    fi
221
222    #rename the backend interface to something sensible
223    rename_veth_interface $i "veth-$i"
224    add_to_rc_local "rename_veth_interface $i 'veth-$i'"
225
226    if [ -s $provision_file ]
227    then
228       tmpname=$(mktemp)".sh"
229       scp $SSH_OPTIONS $provision_file $USER@$i:$tmpname
230       ssh $SSH_OPTIONS $USER@$i "sh -c $tmpname"
231    fi
232
233    #install any pip packages
234    if [ ! -z "$pip" ]
235    then
236       ssh -t $SSH_OPTIONS $USER@$i "sudo -E pip install $pip"
237    fi
238
239done
240
241#cross connect the containers
242add_to_rc_local "sleep 1"
243add_to_rc_local "cross_connect_interfaces"
244
245add_to_rc_local "exit 0"
246
247#setting password to username
248echo "$USER:$USER" | sudo chpasswd
249
250echo -e "List of containers deployed in the dev environment:" | sudo tee -a /etc/motd
251for f in $(ls /vagrant/containers/*.cntr)
252do
253     i=$(basename $f | sed s/.cntr//)
254     desc=$(get_field $f DESC)
255     echo -e $i":\t"$desc | sudo tee -a /etc/motd
256done
257
258echo "To access the environment, type 'vagrant ssh'"
259