Uploading a Vagrantfile for dev-env setup

Upload an all-inclusive Vagrantfile to setup a development
environment for the StarlingX master branch for debian.

The Vagrantfile contains inline shell scripts for setting
up all the required components.   It may be split out in a
future submission into ansible tasks to make it more
readable and maintainable.

Test Plan:
 PASS: setup a development environment on a windows
system with virtualbox and vagrant installed.

Story: 2010547
Task: 47211

Signed-off-by: Al Bailey <al.bailey@windriver.com>
Change-Id: I7ae43dc9abfd52433394bd061e8118b9bcc361f7
This commit is contained in:
Al Bailey 2023-01-30 15:39:32 +00:00
parent 58eb65c053
commit 5271eca7ed
4 changed files with 510 additions and 0 deletions

18
dev-env/Readme.md Normal file
View File

@ -0,0 +1,18 @@
Setting up a New Development Environment
========================================
The following instructions use VirtualBox and Vagrant to setup a
VM running Debian, with most of the required tools installed.
Step 1: Download and install VirtualBox
Step 2: Download and install vagrant
Step 3: Update defaults.yaml or create a custom.yaml with the overridden values
Step 4: "vagrant up"
Note:
Vagrant only allows you to bring up one environment per vagrant file.
To setup additional development environments (ie: for alternative releases),
you must copy the repo to another location.

31
dev-env/vagrant/Readme.md Normal file
View File

@ -0,0 +1,31 @@
Supported Capabilities:
Disk:
- support bigger VBOX disk
- support relocate the DISK to be on an SSD
- support disk resize within the VM
User:
- support ssh as the new user.
- setup bash env (variables)
Build:
- repo init
- repo sync
- setup git settings
- creates required directories for build env
- minikube setup
- update containers prior to running the downloader
- invoke downloader
- support restart of minikube on reboot
Setup Time: (approximately 25 min):
- 3 minutes to download and provision the Debian VM
- 6 minutes to clone the source code.
- 7 minutes initialize the build containers
- 9 minutes to run the downloader for the STX build packages
Future Work Items:
- populate the initial mirror from previous upstream builds
- provide data on how to upload the git certs (for git review, etc..)
- DHCP support (so you can connect to the VM by its name)
verified /etc/machine-id is unique, so DHCP should work for these VMs.
- NIS (home dir) support

397
dev-env/vagrant/Vagrantfile vendored Normal file
View File

@ -0,0 +1,397 @@
# -*- mode: ruby -*-
# vi: set ft=ruby :
# =========================================================
# Automatically setup required vagrant plugins
# Currently required vagrant plugins:
# - vagrant-disksize
required_plugins = [ 'vagrant-disksize' ]
if ARGV[0] != 'plugin'
plugins_to_install = required_plugins.select { |plugin| not Vagrant.has_plugin? plugin }
if not plugins_to_install.empty?
puts "Installing plugins: #{plugins_to_install.join(' ')}"
if system "vagrant plugin install #{plugins_to_install.join(' ')}"
exec "vagrant #{ARGV.join(' ')}"
else
abort "Installation of one or more plugins has failed. Aborting."
end
end
end
# ==========================================================
require 'yaml'
# A file containing all the default variables is provided
VARS = YAML.load_file(File.join(File.dirname(__FILE__), 'defaults.yaml'))
# A user can create a file called 'custom.yaml' and override values from 'defaults.yaml'
CUSTOM = File.join(File.dirname(__FILE__), 'custom.yaml')
if File.exist?(CUSTOM)
CUSTOM_VARS = YAML.load_file(CUSTOM)
VARS = VARS.merge CUSTOM_VARS
end
# Print the variables from default.yaml and custom.yaml that are being used
puts "Vagrant variables:"
puts VARS
# ==========================================================
# Setup the packages
$package_setup = <<PACKAGE_SETUP
date
echo "Updating packages"
apt-get update
# Install some tools (curl / wget)
apt-get install -y curl wget apt-transport-https
# Install docker
apt-get install -y docker.io
# Install helm using the get-helm script
curl https://raw.githubusercontent.com/helm/helm/main/scripts/get-helm-3 | bash
# Install minikube
curl -LO https://storage.googleapis.com/minikube/releases/latest/minikube-linux-amd64
install minikube-linux-amd64 /usr/local/bin/minikube
# Install git-review
# Install parted (so we can allocate the full disk)
# python-is-python3 aliases 'python' to python3
apt-get install -y git-review parted python-is-python3
# Install 'repo'
# The following does not work on bullseye
# apt-get install -y repo
# Partially following the instructions from https://source.android.com/docs/setup/download#installing-repo
export REPO=$(mktemp /tmp/repo.XXXXXXXXX)
curl -o ${REPO} https://storage.googleapis.com/git-repo-downloads/repo
install -m 755 ${REPO} /usr/bin/repo
# Install 3rdparty components required to run 'tox' for various repos
# The value in (brackets) indicates the repo that likely requires that component
# bc (stx-tools)
# libffi-dev (config)
# libldap2-dev (config)
# libsasl2-dev (config)
# libxml2-dev (config)
# libxslt1-dev (config)
# ostree (update)
# python3-all-dev (config)
# ruby-dev (stx-puppet)
# ruby-rubygems (stx-puppet)
# tox (all)
apt-get install -y bc libffi-dev libldap2-dev libsasl2-dev libxml2-dev libxslt1-dev ostree python3-all-dev ruby-rubygems ruby-dev tox
# pip install some additional components that are helpful for development
pip3 install bindep
PACKAGE_SETUP
# ==========================================================
# Setup the 'dev_user'
$user_setup = <<-'USER_SETUP'
# Add a new user if it does not exist
# -m creates the default home dir
# -p sets the (crypted) password. Invoking openssl to 'crypt' the password string.
# -s sets the shell otherwise it defaults to /bin/sh
id -u ${DEV_USER} &>/dev/null || useradd ${DEV_USER} -m -p $(openssl passwd -1 ${DEV_PASSWORD}) -s ${DEV_SHELL}
usermod -s ${DEV_SHELL} ${DEV_USER}
# Add the user to the docker group
sudo usermod -aG docker ${DEV_USER}
# Add the user to the sudoers file
echo "${DEV_USER} ALL=(ALL) NOPASSWD:ALL" | tee /etc/sudoers.d/${DEV_USER}
echo "Git setup"
su - ${DEV_USER} -c "git config --global user.name \"${USER_NAME}\""
su - ${DEV_USER} -c "git config --global user.email ${USER_EMAIL}"
# setup the directory for the user under /localdisk
MY_LOCALDISK="/localdisk/${DEV_USER}"
mkdir -p ${MY_LOCALDISK}
chown ${DEV_USER} ${MY_LOCALDISK}
# setup ssh host keys so that git hosts will not complain for ssh urls
# .ssh must be 700 permissions
# Creating it as root, because "su -" is a pain to deal with
mkdir -m=700 -p /home/${DEV_USER}/.ssh
chown ${DEV_USER}:${DEV_USER} /home/${DEV_USER}/.ssh
# Setup keys for this host
SSH_KEY="/home/${DEV_USER}/.ssh/id_ed25519"
HOSTNAME=`hostname`
su - ${DEV_USER} -c "ssh-keygen -q -f ${SSH_KEY} -N '' -t ed25519 -C ${DEV_USER}@${HOSTNAME}"
# Setup known hosts
su - ${DEV_USER} -c "ssh-keyscan -t rsa ${KNOWN_HOSTS} >> /home/${DEV_USER}/.ssh/known_hosts"
# some HOSTS might require an alternative port. ie: ssh://git@nowhere.com:7999
if [[ ! -z "${ALT_PORT}" ]]
then
echo "Setting up ${ALT_PORT}"
su - ${DEV_USER} -c "ssh-keyscan -t rsa -p ${ALT_PORT} ${ALT_HOSTS} >> /home/${DEV_USER}/.ssh/known_hosts"
else
echo "NOT Setting up ${ALT_PORT}"
fi
if [[ ! -z "${SSH_URL}" ]]
then
echo "Uploading ssh key to ${SSH_URL} by logging in with git user and password"
SSH_PUB_KEY=`cat ${SSH_KEY}.pub`
su - ${DEV_USER} -c "curl -v -u ${GIT_USER}:${GIT_PASSWORD} POST -H \"Content-Type: application/json\" -d '{\"text\": \"${SSH_PUB_KEY}\"}' ${SSH_URL}"
fi
# Add additional exports to .bashrc
# https://opendev.org/starlingx/tools/src/branch/master/import-stx.README
PROFILE="/home/${DEV_USER}/.profile"
if grep -q "PROJECT=" ${PROFILE}
then
echo "${PROFILE} already setup"
else
echo "Setting up ${PROFILE}"
# append all of these to the end of .profile
echo "export PROJECT=${PROJECT}" >> ${PROFILE}
echo "export USER_NAME=\"${USER_NAME}\"" >> ${PROFILE}
echo "export USER_EMAIL=${USER_EMAIL}" >> ${PROFILE}
echo "export MINIKUBENAME=minikube-${DEV_USER}-${PROJECT}" >> ${PROFILE}
# minikube
MINIKUBE_HOME="${MY_LOCALDISK}/MINIKUBE_HOME"
su - ${DEV_USER} -c "mkdir -p ${MINIKUBE_HOME}"
echo "export MINIKUBE_HOME=${MINIKUBE_HOME}" >> ${PROFILE}
# patches
PATCHES_DIR="${MY_LOCALDISK}/PATCHES"
su - ${DEV_USER} -c "mkdir -p ${PATCHES_DIR}"
echo "export PATCHES_DIR=${PATCHES_DIR}" >> ${PROFILE}
# STX_BUILD_HOME is the same as the project workspace
MY_WORKSPACE="${MY_LOCALDISK}/WORKSPACE/${PROJECT}"
su - ${DEV_USER} -c "mkdir -p ${MY_WORKSPACE}"
echo "export MY_WORKSPACE=${MY_WORKSPACE}" >> ${PROFILE}
echo "export STX_BUILD_HOME=${MY_WORKSPACE}" >> ${PROFILE}
MY_REPO_ROOT_DIR="${MY_WORKSPACE}/localdisk/designer/${DEV_USER}/${PROJECT}"
su - ${DEV_USER} -c "mkdir -p ${MY_REPO_ROOT_DIR}"
echo "export MY_REPO_ROOT_DIR=${MY_REPO_ROOT_DIR}" >> ${PROFILE}
echo "export MY_REPO=${MY_REPO_ROOT_DIR}/cgcs-root" >> ${PROFILE}
STX_TOOLS="${MY_REPO_ROOT_DIR}/stx-tools"
echo "export STX_TOOLS=${MY_REPO_ROOT_DIR}/stx-tools" >> ${PROFILE}
# Update the profile so that import-stx is automatically 'sourced' whenever we login
echo "
if [[ -d \${STX_TOOLS} ]]; then
pushd \${STX_TOOLS} > /dev/null
source ./import-stx
popd > /dev/null
fi " >> ${PROFILE}
fi # setting up profile
USER_SETUP
# ====================================================
$system_setup = <<SYSTEM_SETUP
# Allow ssh to the machine using a password
sed -i 's/PasswordAuthentication no/PasswordAuthentication yes/g' /etc/ssh/sshd_config
systemctl restart sshd.service
# Ensure the entire disk is available. Otherwise only 20G is available to "/"
resize2fs /dev/sda1
# Note: The build tools are basically hardcoded to expect things under /localdisk/<$USER>
mkdir -p /localdisk
SYSTEM_SETUP
# ====================================================
# This inline script uses special syntax to prevent ruby from stripping quotes
$repo_setup = <<-'REPO_SETUP'
# Note: You cannot switch users in vagrant
# su - <user> -c <commands> is the only way to run commands as another user
# Step 1) repo init
MY_LOCALDISK="/localdisk/${DEV_USER}"
MY_WORKSPACE="${MY_LOCALDISK}/WORKSPACE/${PROJECT}"
MY_REPO_ROOT_DIR="${MY_WORKSPACE}/localdisk/designer/${DEV_USER}/${PROJECT}"
STX_TOOLS="${MY_REPO_ROOT_DIR}/stx-tools"
date
echo "Initializing repo"
su - ${DEV_USER} -c "cd ${MY_REPO_ROOT_DIR};
repo init -u ${MANIFEST_URL} -m ${MANIFEST_FILE} -b ${MANIFEST_BRANCH}"
# Step 2) repo sync
date
echo "Synchronizing repo. This can take some time (approximately 8 min)"
su - ${DEV_USER} -c "cd ${MY_REPO_ROOT_DIR};
repo sync -j $(nproc --all)"
# Step 3) stx-init-env
date
echo "stx-init-env. This can take some time (approximately 6 min)"
# initialize minikube env
su - ${DEV_USER} -c "cd ${STX_TOOLS};
source import-stx;
stx config --add builder.myuname $(id -un ${DEV_USER});
stx config --add builder.uid $(id -u ${DEV_USER});
stx config --add project.name ${PROJECT};
stx config --add project.gituser \"${USER_NAME}\";
stx config --add project.gitemail ${USER_EMAIL};
# stx-init-env spams stdout, so we will redirect that command to a log
./stx-init-env > ${MY_WORKSPACE}/stx-init-env.log 2>&1 ;
# Display the last new lines of the log
tail ${MY_WORKSPACE}/stx-init-env.log;
# status should indicate success rather than 'ContainerCreating'
stx control status"
# Step 3) Support minikube auto-start on reboot for this user
date
# override contents of /usr/lib/systemd/system/minikube.service
MINIKUBE_SERVICE="/usr/lib/systemd/system/minikube.service"
MINIKUBENAME="minikube-${DEV_USER}-${PROJECT}"
echo "
[Unit]
Description=minikube
After=network-online.target containerd.service docker.service
Wants=network-online.target docker.service
Requires=docker.socket containerd.service docker.service
[Service]
Type=oneshot
ExecStart=/bin/bash -l -c \"minikube start -p ${MINIKUBENAME}\"
RemainAfterExit=true
ExecStop=/bin/bash -l -c \"minikube stop -p ${MINIKUBENAME}\"
User=${DEV_USER}
Group=docker
[Install]
WantedBy=multi-user.target
" > ${MINIKUBE_SERVICE}
# reload minikube systemd service
systemctl daemon-reload
systemctl enable minikube
systemctl start minikube
# Step 4) Run the downloader
date
echo "Waiting 60 seconds before running the downloader to ensure all containers are running"
sleep 60
date
echo "Running the downloader. This can take some time (approximately 10 min)"
su - ${DEV_USER} -c "cd ${STX_TOOLS};
source import-stx;
stx control status;
echo 'Running apt-get update';
stx shell -c 'sudo apt-get update';
echo 'Running downloader';
stx shell -c 'downloader' > ${MY_WORKSPACE}/downloader.log 2>&1;
# display the last new lines of the downloader log
tail ${MY_WORKSPACE}/downloader.log
"
date
echo "DONE"
# populate mirrors
# download prebuilt artifacts
REPO_SETUP
# ===================================================================
# All Vagrant configuration is done below. The "2" in Vagrant.configure
# configures the configuration version (we support older styles for
# backwards compatibility). Please don't change it unless you know what
# you're doing.
Vagrant.configure("2") do |config|
# The most common configuration options are documented and commented below.
# For a complete reference, please see the online documentation at
# https://docs.vagrantup.com.
# Every Vagrant development environment requires a box. You can search for
# boxes at https://vagrantcloud.com/search.
config.vm.box = VARS['base_image']
# set the hostname within this VBOX
config.vm.hostname = VARS['hostname']
# set the vbox disk size (this uses vagrant-disksize plugin)
# Note: provisioning steps are needed for debian to recognize this
config.disksize.size = VARS['vbox_disk_size']
# config.vm.define
# Disable automatic box update checking. If you disable this, then
# boxes will only be checked for updates when the user runs
# `vagrant box outdated`. This is not recommended.
# config.vm.box_check_update = false
# Create a forwarded port mapping which allows access to a specific port
# within the machine from a port on the host machine. In the example below,
# accessing "localhost:8080" will access port 80 on the guest machine.
# NOTE: This will enable public access to the opened port
# config.vm.network "forwarded_port", guest: 80, host: 8080
config.vm.network "forwarded_port", guest: 22, host: VARS['sshport']
config.ssh.insert_key = false
# Create a forwarded port mapping which allows access to a specific port
# within the machine from a port on the host machine and only allow access
# via 127.0.0.1 to disable public access
# config.vm.network "forwarded_port", guest: 80, host: 8080, host_ip: "127.0.0.1"
# Create a private network, which allows host-only access to the machine
# using a specific IP.
# config.vm.network "private_network", ip: "192.168.33.10"
# Create a public network, which generally matched to bridged network.
# Bridged networks make the machine appear as another physical device on
# your network.
# config.vm.network "public_network"
# Share an additional folder to the guest VM. The first argument is
# the path on the host to the actual folder. The second argument is
# the path on the guest to mount the folder. And the optional third
# argument is a set of non-required options.
# config.vm.synced_folder "../data", "/vagrant_data"
# Disable the synched folder in vagrant
config.vm.synced_folder '.', '/vagrant', disabled: true
# VirtualBox settings:
config.vm.provider "virtualbox" do |vb|
vb.name = VARS['vbox_name']
vb.gui = VARS['vbox_gui']
vb.memory = VARS['vbox_memory']
vb.cpus = VARS['vbox_cpus']
# Override where vagrant will install the VMs
if !VARS['vbox_vm_location'].nil?
vb.customize "pre-import", ["setproperty", "machinefolder", VARS['vbox_vm_location'] ]
end
vb.customize "pre-boot", ["modifyvm", :id, "--groups", VARS['vbox_group'] ]
end
# First step of provisioning is to install the required packages
config.vm.provision "shell", inline: $package_setup
# Make further changes to the system setup
config.vm.provision "shell", inline: $system_setup
# Set up a new user
config.vm.provision "shell", env: {"DEV_USER" => VARS['dev_user'],
"DEV_PASSWORD" => VARS['dev_password'],
"DEV_SHELL" => VARS['dev_shell'],
"PROJECT" => VARS['PROJECT'],
"KNOWN_HOSTS" => VARS['KNOWN_HOSTS'],
"ALT_PORT" => VARS['ALT_PORT'],
"ALT_HOSTS" => VARS['ALT_HOSTS'],
"SSH_URL" => VARS['SSH_URL'],
"GIT_USER" => VARS['GIT_USER'],
"GIT_PASSWORD" => VARS['GIT_PASSWORD'],
"USER_EMAIL" => VARS['USER_EMAIL'],
"USER_NAME" => VARS['USER_NAME']}, inline: $user_setup
# Initialize the code using the repo command
config.vm.provision "shell", env: {"DEV_USER" => VARS['dev_user'],
"MANIFEST_URL" => VARS['MANIFEST_URL'],
"MANIFEST_FILE" => VARS['MANIFEST_FILE'],
"MANIFEST_BRANCH" => VARS['MANIFEST_BRANCH'],
"PROJECT" => VARS['PROJECT'],
"USER_EMAIL" => VARS['USER_EMAIL'],
"USER_NAME" => VARS['USER_NAME']}, inline: $repo_setup
end

View File

@ -0,0 +1,64 @@
---
# =============== vbox settings ===============================================
# Before running vagrant up , update the entries with the comment: "UPDATE_ME"
# =============== login settings ===============================================
dev_user: "sysadmin" # UPDATE_ME
dev_password: "sysadmin" # UPDATE_ME
USER_EMAIL: "somebody@nowhere.com" # UPDATE_ME
USER_NAME: "Some Body" # UPDATE_ME
# base_image is the starting 'box' downloaded from https://app.vagrantup.com/boxes
# debian bullseye64 includes python 3.9
base_image: "debian/bullseye64"
# Create a VBox Group for the VM. Useful when making separate VMs for different branches
vbox_group: "/StarlingX Dev"
# Assign a name for the development VM as shown in vbox
vbox_name: "stx-dev-vm"
# Assign a hostname for the development VM
hostname: "stx-dev-vm"
# Assign a port for port forwarding to ssh (22)
# meaning if you ssh to your <machine>:sshport it will connect to <vm>:22
sshport: "2201"
# Display the VirtualBox GUI when booting the machine
vbox_gui: true
# 20 GB memory
vbox_memory: "20480"
# 6 cpus
vbox_cpus: "6"
# 500 GB disk size
vbox_disk_size: "500GB"
# Uncomment and update the next line to override the location where VMs and disk are created
# vbox_vm_location: "D:\\SSD-VMS"
# Note: Changing the shell will likely break many other setup steps.
dev_shell: "/bin/bash"
# =============== BUILD settings ===============================================
# Warning: DO NOT use extended characters, underscore, or spaces for PROJECT
PROJECT: "stx-env"
# KNOWN_HOSTS is the list of hosts that may need host key ssh validation for git
KNOWN_HOSTS: "github.com"
ALT_HOSTS: ""
ALT_PORT: ""
# Internal git repositories and manifests may require additional fields to be setup
SSH_URL: ""
GIT_USER: ""
GIT_PASSWORD: ""
# =============== SOURCE CODE settings ===============================================
# StarlingX code is checked out using 'repo' command
# ex: repo init -u https://opendev.org/starlingx/manifest -m default.xml -b master
MANIFEST_URL: "https://opendev.org/starlingx/manifest"
MANIFEST_FILE: "default.xml"
MANIFEST_BRANCH: "master"