From 1b53a7caa2bea9b5131add615f21e7ea033e6be8 Mon Sep 17 00:00:00 2001 From: James Shubin Date: Sat, 11 Jan 2014 20:11:08 -0500 Subject: Builder scripts for building vagrant base image "boxes". Elegant system using a Makefile to build base image "boxes". It's recommended that you use the pre-built boxes, but the infrastructure is being provided here for completeness. You'll probably want to set the $(OUTPUT) variable first. Then use the 'box' target (make box) to produce output into the $(OUTPUT) directory. --- builder/Makefile | 148 +++++++++++++++++++++++ builder/Vagrantfile | 57 +++++++++ builder/files/cleanup.sh | 7 ++ builder/files/epel-release-6-8.noarch.rpm | Bin 0 -> 14540 bytes builder/files/network.sh | 40 ++++++ builder/files/password | 1 + builder/files/puppetlabs-release-el-6.noarch.rpm | Bin 0 -> 5712 bytes builder/files/selinux | 10 ++ builder/files/ssh.sh | 58 +++++++++ builder/files/user.sh | 16 +++ 10 files changed, 337 insertions(+) create mode 100644 builder/Makefile create mode 100644 builder/Vagrantfile create mode 100644 builder/files/cleanup.sh create mode 100644 builder/files/epel-release-6-8.noarch.rpm create mode 100644 builder/files/network.sh create mode 100644 builder/files/password create mode 100644 builder/files/puppetlabs-release-el-6.noarch.rpm create mode 100644 builder/files/selinux create mode 100644 builder/files/ssh.sh create mode 100644 builder/files/user.sh diff --git a/builder/Makefile b/builder/Makefile new file mode 100644 index 0000000..722cb63 --- /dev/null +++ b/builder/Makefile @@ -0,0 +1,148 @@ +# Makefile for building Vagrant (libvirt) base image "boxes" for Puppet-Gluster +# Copyright (C) 2010-2013+ James Shubin +# Written by James Shubin +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU Affero General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Affero General Public License for more details. +# +# You should have received a copy of the GNU Affero General Public License +# along with this program. If not, see . + +# NOTE: if you change any of the values in this file (such as SIZE or --install +# arguments) make won't notice the change, you'll have to manually clean first. + +.PHONY: all local box upload clean +.SILENT: + +# TODO: build base image for virt-builder from iso instead of using templates + +# virt-builder os-version +VERSION = centos-6 +BOX = $(VERSION).box +SIZE = 40 +#OUTPUT = /tmp/gluster +#OUTPUT := $(shell pwd) +OUTPUT := $(shell echo ~/tmp/builder/gluster) +SERVER = 'download.gluster.org' +REMOTE_PATH = 'purpleidea/vagrant' + +all: box + +box: $(OUTPUT)/$(BOX) + +local: $(OUTPUT)/SHA256SUMS.asc + +# +# clean +# +# delete created files +clean: + @echo Running clean... + # TODO: technically, the 'true' should check if all the files are rm-ed + rm $(OUTPUT)/{{builder,box}.img,metadata.json,$(BOX),SHA256SUMS{,.asc}} || true + +# +# virt-builder +# +# build image with virt-builder +# NOTE: some of this system prep is based on the vagrant-libvirt scripts +# TODO: install: ruby ruby-devel make gcc rubygems ? +# FIXME: unfortunately, an selinux relabelling happens on the "first boot". +# FIXME: as a result, i had to disable selinux. what is the correct solution ? +# FIXME: we don't want vagrant to take the extra 30sec+ on first boot... +# < rwmjones> this happens because the image contains a /.autorelabel file +# < rwmjones> so that selinux gets relabelled (which requires a reboot) +# < rwmjones> if you don't want to use selinux, then you can delete that file +# < rwmjones> (note that only applies to Fedora/RHEL-derived images) +# < rwmjones> ok so you can use virt-builder --delete /.autorelabel +$(OUTPUT)/builder.img: files/* + @echo Running virt-builder... + [ -d $(OUTPUT) ] || mkdir -p $(OUTPUT)/ # ensure path is present first! + virt-builder $(VERSION) \ + --output $(OUTPUT)/builder.img \ + --format qcow2 \ + --size $(SIZE)G \ + --install rsync,nfs-utils,sudo,openssh-server,openssh-clients \ + --install screen,vim-enhanced,git,wget,file,man,tree,nmap,tcpdump,htop,lsof,telnet,mlocate,bind-utils,koan,iftop,yum-utils,nc \ + --root-password file:files/password \ + --upload files/epel-release-6-8.noarch.rpm:/root/epel-release-6-8.noarch.rpm \ + --upload files/puppetlabs-release-el-6.noarch.rpm:/root/puppetlabs-release-el-6.noarch.rpm \ + --run-command 'yum install -y /root/epel-release-6-8.noarch.rpm && rm -f /root/epel-release-6-8.noarch.rpm' \ + --run-command 'yum install -y bash-completion moreutils' \ + --run-command 'yum install -y /root/puppetlabs-release-el-6.noarch.rpm && rm -f /root/puppetlabs-release-el-6.noarch.rpm' \ + --run-command 'yum install -y puppet' \ + --run-command 'yum update -y' \ + --run files/user.sh \ + --run files/ssh.sh \ + --run files/network.sh \ + --run files/cleanup.sh \ + --upload files/selinux:/etc/selinux/config \ + --delete /.autorelabel # disable "firstboot" selinux relabelling (workaround) + +# +# convert +# +# workaround sparse qcow2 images bug +# thread: https://www.redhat.com/archives/libguestfs/2014-January/msg00008.html +$(OUTPUT)/box.img: $(OUTPUT)/builder.img + @echo Running convert... + qemu-img convert -O qcow2 $(OUTPUT)/builder.img $(OUTPUT)/box.img + +# +# metadata.json +# +$(OUTPUT)/metadata.json: + @echo Running templater... + [ -d $(OUTPUT) ] || mkdir -p $(OUTPUT)/ # ensure path is present first! + echo '{"provider": "libvirt", "format": "qcow2", "virtual_size": $(SIZE)}' > $(OUTPUT)/metadata.json + echo '' >> $(OUTPUT)/metadata.json # newline + +# +# tar +# +# create custom box +# format at: https://github.com/pradels/vagrant-libvirt/tree/master/example_box +$(OUTPUT)/$(BOX): Vagrantfile $(OUTPUT)/metadata.json $(OUTPUT)/box.img + @echo Running tar... + tar -cvzf $(OUTPUT)/$(BOX) ./Vagrantfile --directory=$(OUTPUT)/ ./metadata.json ./box.img + +# +# sha256sum +# +$(OUTPUT)/SHA256SUMS: $(OUTPUT)/$(BOX) + @echo Running sha256sum... + cd $(OUTPUT) && sha256sum $(BOX) > SHA256SUMS; cd - + +# +# gpg +# +$(OUTPUT)/SHA256SUMS.asc: $(OUTPUT)/SHA256SUMS + @echo Running gpg... + # the --yes forces an overwrite of the SHA256SUMS.asc if necessary + gpg2 --yes --clearsign $(OUTPUT)/SHA256SUMS + +# +# upload +# +# upload to public server +# NOTE: user downloads while file uploads are in progress don't cause problems! +upload: $(OUTPUT)/$(BOX) $(OUTPUT)/SHA256SUMS $(OUTPUT)/SHA256SUMS.asc + if [ "`cat $(OUTPUT)/SHA256SUMS`" != "`ssh $(SERVER) 'cd $(REMOTE_PATH)/ && sha256sum $(BOX)'`" ]; then \ + echo Running upload...; \ + scp -p $(OUTPUT)/{$(BOX),SHA256SUMS{,.asc}} $(SERVER):$(REMOTE_PATH)/; \ + fi +# this method works too, but always hits the server on every make call +#upload: +#ifeq ($(shell cat $(OUTPUT)/SHA256SUMS), $(shell ssh $(SERVER) 'cd $(REMOTE_PATH)/ && sha256sum $(BOX)')) +# @echo true +#else +# @echo false +#endif + diff --git a/builder/Vagrantfile b/builder/Vagrantfile new file mode 100644 index 0000000..d760bdb --- /dev/null +++ b/builder/Vagrantfile @@ -0,0 +1,57 @@ +# -*- mode: ruby -*- +# vi: set ft=ruby : + +Vagrant.configure('2') do |config| + + # Example configuration of new VM.. + # + #config.vm.define :test_vm do |test_vm| + # Box name + # + #test_vm.vm.box = 'centos-6' + + # Domain Specific Options + # + # See README for more info. + # + #test_vm.vm.provider :libvirt do |domain| + # domain.memory = 2048 + # domain.cpus = 2 + #end + + # Interfaces for VM + # + # Networking features in the form of `config.vm.network` support private + # networks concept. No public network or port forwarding are supported in + # current version of provider. See README for more info. + # + #test_vm.vm.network :private_network, :ip => '10.20.30.40' + #end + + # Options for libvirt vagrant provider. + config.vm.provider :libvirt do |libvirt| + + # A hypervisor name to access. Different drivers can be specified, but + # this version of provider creates KVM machines only. Some examples of + # drivers are qemu (KVM/qemu), xen (Xen hypervisor), lxc (Linux Containers), + # esx (VMware ESX), vmwarews (VMware Workstation) and more. Refer to + # documentation for available drivers (http://libvirt.org/drivers.html). + libvirt.driver = 'qemu' + + # The name of the server, where libvirtd is running. + #libvirt.host = 'localhost' + + # If use ssh tunnel to connect to Libvirt. + libvirt.connect_via_ssh = false + + # The username and password to access Libvirt. Password is not used when + # connecting via ssh. + libvirt.username = 'root' + #libvirt.password = 'secret' + + # Libvirt storage pool name, where box image and instance snapshots will + # be stored. + libvirt.storage_pool_name = 'default' + end +end + diff --git a/builder/files/cleanup.sh b/builder/files/cleanup.sh new file mode 100644 index 0000000..765b343 --- /dev/null +++ b/builder/files/cleanup.sh @@ -0,0 +1,7 @@ +#!/bin/bash + +# Do some cleanup.. +rm -f ~root/.bash_history +#rm -r "$(gem env gemdir)"/doc/* +yum clean all + diff --git a/builder/files/epel-release-6-8.noarch.rpm b/builder/files/epel-release-6-8.noarch.rpm new file mode 100644 index 0000000..588a577 Binary files /dev/null and b/builder/files/epel-release-6-8.noarch.rpm differ diff --git a/builder/files/network.sh b/builder/files/network.sh new file mode 100644 index 0000000..404bb9a --- /dev/null +++ b/builder/files/network.sh @@ -0,0 +1,40 @@ +#!/bin/bash + +# Disable firewall +chkconfig iptables off +chkconfig ip6tables off +chkconfig sshd on + +# Networking setup... +# Don't fix ethX names to hw address. +#rm -f /etc/udev/rules.d/*persistent-net.rules +#rm -f /etc/udev/rules.d/*-net.rules +rm -rf /var/lib/dhclient/* # remove any old leases that could be around... + +# XXX: unsure if this will help, but we'll try it out: +# Problem situation: Two interfaces are connected to same network. One interface +# wants to renew DHCP lease and asks server for address. DHCPACK message from +# server arrives, client moves to BOUND state. The client performs a check on +# the suggested address to ensure that the address is not already in use. On +# arping for specified IP address, other interface replies and that's why +# dhclient-script replies with DHCPDECLINE message. (See RFC2131, 4.4.1.). +# Solution: Set sysctl to reply only if the target IP address is local address +# configured on the incoming interface. (See kernel documentation +# Documentation/networking/ip-sysctl.txt) +set_sysctl() { + grep "$1" /etc/sysctl.conf > /dev/null + [ $? -eq 0 ] && sed -i '/'$1'/d' /etc/sysctl.conf + echo "$1 = $2" >> /etc/sysctl.conf +} +set_sysctl 'net.ipv4.conf.all.arp_ignore' 1 +set_sysctl 'net.ipv4.conf.all.arp_announce' 2 +set_sysctl 'net.ipv4.conf.all.rp_filter' 3 + +# Interface eth0 should get IP address via dhcp. +#cat > /etc/sysconfig/network-scripts/ifcfg-eth0 << EOF +#DEVICE="eth0" +#BOOTPROTO="dhcp" +#ONBOOT="yes" +#NM_CONTROLLED="no" +#EOF + diff --git a/builder/files/password b/builder/files/password new file mode 100644 index 0000000..d6a9762 --- /dev/null +++ b/builder/files/password @@ -0,0 +1 @@ +vagrant diff --git a/builder/files/puppetlabs-release-el-6.noarch.rpm b/builder/files/puppetlabs-release-el-6.noarch.rpm new file mode 100644 index 0000000..0e99d19 Binary files /dev/null and b/builder/files/puppetlabs-release-el-6.noarch.rpm differ diff --git a/builder/files/selinux b/builder/files/selinux new file mode 100644 index 0000000..8237483 --- /dev/null +++ b/builder/files/selinux @@ -0,0 +1,10 @@ +# This file controls the state of SELinux on the system. +# SELINUX= can take one of these three values: +# enforcing - SELinux security policy is enforced. +# permissive - SELinux prints warnings instead of enforcing. +# disabled - SELinux is fully disabled. +SELINUX=disabled +# SELINUXTYPE= type of policy in use. Possible values are: +# targeted - Only targeted network daemons are protected. +# strict - Full SELinux protection. +SELINUXTYPE=targeted diff --git a/builder/files/ssh.sh b/builder/files/ssh.sh new file mode 100644 index 0000000..b2b4366 --- /dev/null +++ b/builder/files/ssh.sh @@ -0,0 +1,58 @@ +#!/bin/bash + +# SSH setup +# Add Vagrant ssh key for root and vagrant accouts. +sed -i 's/.*UseDNS.*/UseDNS no/' /etc/ssh/sshd_config + +[ -d ~root/.ssh ] || mkdir ~root/.ssh +chmod 700 ~root/.ssh +cat > ~root/.ssh/authorized_keys << EOF +ssh-rsa AAAAB3NzaC1yc2EAAAABIwAAAQEA6NF8iallvQVp22WDkTkyrtvp9eWW6A8YVr+kz4TjGYe7gHzIw+niNltGEFHzD8+v1I2YJ6oXevct1YeS0o9HZyN1Q9qgCgzUFtdOKLv6IedplqoPkcmF0aYet2PkEDo3MlTBckFXPITAMzF8dJSIFo9D8HfdOV0IAdx4O7PtixWKn5y2hMNG0zQPyUecp4pzC6kivAIhyfHilFR61RGL+GPXQ2MWZWFYbAGjyiYJnAmCP3NOTd0jMZEnDkbUvxhMmBYSdETk1rRgm+R4LOzFUGaHqHDLKLX+FIPKcF96hrucXzcWyLbIbEgE98OHlnVYCzRdK8jlqm8tehUc9c9WhQ== vagrant insecure public key +EOF +chmod 600 ~root/.ssh/authorized_keys + +# allow interhost communication +cat > ~root/.ssh/id_rsa << EOF +-----BEGIN RSA PRIVATE KEY----- +MIIEogIBAAKCAQEA6NF8iallvQVp22WDkTkyrtvp9eWW6A8YVr+kz4TjGYe7gHzI +w+niNltGEFHzD8+v1I2YJ6oXevct1YeS0o9HZyN1Q9qgCgzUFtdOKLv6IedplqoP +kcmF0aYet2PkEDo3MlTBckFXPITAMzF8dJSIFo9D8HfdOV0IAdx4O7PtixWKn5y2 +hMNG0zQPyUecp4pzC6kivAIhyfHilFR61RGL+GPXQ2MWZWFYbAGjyiYJnAmCP3NO +Td0jMZEnDkbUvxhMmBYSdETk1rRgm+R4LOzFUGaHqHDLKLX+FIPKcF96hrucXzcW +yLbIbEgE98OHlnVYCzRdK8jlqm8tehUc9c9WhQIBIwKCAQEA4iqWPJXtzZA68mKd +ELs4jJsdyky+ewdZeNds5tjcnHU5zUYE25K+ffJED9qUWICcLZDc81TGWjHyAqD1 +Bw7XpgUwFgeUJwUlzQurAv+/ySnxiwuaGJfhFM1CaQHzfXphgVml+fZUvnJUTvzf +TK2Lg6EdbUE9TarUlBf/xPfuEhMSlIE5keb/Zz3/LUlRg8yDqz5w+QWVJ4utnKnK +iqwZN0mwpwU7YSyJhlT4YV1F3n4YjLswM5wJs2oqm0jssQu/BT0tyEXNDYBLEF4A +sClaWuSJ2kjq7KhrrYXzagqhnSei9ODYFShJu8UWVec3Ihb5ZXlzO6vdNQ1J9Xsf +4m+2ywKBgQD6qFxx/Rv9CNN96l/4rb14HKirC2o/orApiHmHDsURs5rUKDx0f9iP +cXN7S1uePXuJRK/5hsubaOCx3Owd2u9gD6Oq0CsMkE4CUSiJcYrMANtx54cGH7Rk +EjFZxK8xAv1ldELEyxrFqkbE4BKd8QOt414qjvTGyAK+OLD3M2QdCQKBgQDtx8pN +CAxR7yhHbIWT1AH66+XWN8bXq7l3RO/ukeaci98JfkbkxURZhtxV/HHuvUhnPLdX +3TwygPBYZFNo4pzVEhzWoTtnEtrFueKxyc3+LjZpuo+mBlQ6ORtfgkr9gBVphXZG +YEzkCD3lVdl8L4cw9BVpKrJCs1c5taGjDgdInQKBgHm/fVvv96bJxc9x1tffXAcj +3OVdUN0UgXNCSaf/3A/phbeBQe9xS+3mpc4r6qvx+iy69mNBeNZ0xOitIjpjBo2+ +dBEjSBwLk5q5tJqHmy/jKMJL4n9ROlx93XS+njxgibTvU6Fp9w+NOFD/HvxB3Tcz +6+jJF85D5BNAG3DBMKBjAoGBAOAxZvgsKN+JuENXsST7F89Tck2iTcQIT8g5rwWC +P9Vt74yboe2kDT531w8+egz7nAmRBKNM751U/95P9t88EDacDI/Z2OwnuFQHCPDF +llYOUI+SpLJ6/vURRbHSnnn8a/XG+nzedGH5JGqEJNQsz+xT2axM0/W/CRknmGaJ +kda/AoGANWrLCz708y7VYgAtW2Uf1DPOIYMdvo6fxIB5i9ZfISgcJ/bbCUkFrhoH ++vq/5CIWxCPp0f85R4qxxQ5ihxJ0YDQT9Jpx4TMss4PSavPaBH3RXow5Ohe+bYoQ +NE5OgEXk2wVfZczCZpigBKbKZHNYcelXtTt/nP3rsCuGcM4h53s= +-----END RSA PRIVATE KEY----- +EOF +chmod 600 ~root/.ssh/id_rsa + +cat > ~root/.ssh/id_rsa.pub << EOF +ssh-rsa AAAAB3NzaC1yc2EAAAABIwAAAQEA6NF8iallvQVp22WDkTkyrtvp9eWW6A8YVr+kz4TjGYe7gHzIw+niNltGEFHzD8+v1I2YJ6oXevct1YeS0o9HZyN1Q9qgCgzUFtdOKLv6IedplqoPkcmF0aYet2PkEDo3MlTBckFXPITAMzF8dJSIFo9D8HfdOV0IAdx4O7PtixWKn5y2hMNG0zQPyUecp4pzC6kivAIhyfHilFR61RGL+GPXQ2MWZWFYbAGjyiYJnAmCP3NOTd0jMZEnDkbUvxhMmBYSdETk1rRgm+R4LOzFUGaHqHDLKLX+FIPKcF96hrucXzcWyLbIbEgE98OHlnVYCzRdK8jlqm8tehUc9c9WhQ== vagrant insecure public key +EOF + +# vagrant user ssh +[ -d ~vagrant/.ssh ] || mkdir ~vagrant/.ssh +chmod 700 ~vagrant/.ssh +cat > ~vagrant/.ssh/authorized_keys << EOF +ssh-rsa AAAAB3NzaC1yc2EAAAABIwAAAQEA6NF8iallvQVp22WDkTkyrtvp9eWW6A8YVr+kz4TjGYe7gHzIw+niNltGEFHzD8+v1I2YJ6oXevct1YeS0o9HZyN1Q9qgCgzUFtdOKLv6IedplqoPkcmF0aYet2PkEDo3MlTBckFXPITAMzF8dJSIFo9D8HfdOV0IAdx4O7PtixWKn5y2hMNG0zQPyUecp4pzC6kivAIhyfHilFR61RGL+GPXQ2MWZWFYbAGjyiYJnAmCP3NOTd0jMZEnDkbUvxhMmBYSdETk1rRgm+R4LOzFUGaHqHDLKLX+FIPKcF96hrucXzcWyLbIbEgE98OHlnVYCzRdK8jlqm8tehUc9c9WhQ== vagrant insecure public key +EOF +chmod 600 ~vagrant/.ssh/authorized_keys +chown -R vagrant:vagrant ~vagrant/.ssh/ + diff --git a/builder/files/user.sh b/builder/files/user.sh new file mode 100644 index 0000000..224a058 --- /dev/null +++ b/builder/files/user.sh @@ -0,0 +1,16 @@ +#!/bin/bash + +echo 'vagrant' | passwd --stdin root +grep 'vagrant' /etc/passwd > /dev/null +if [ $? -ne 0 ]; then + echo '* Creating user vagrant.' + useradd vagrant + echo 'vagrant' | passwd --stdin vagrant +fi +grep '^admin:' /etc/group > /dev/null || groupadd admin +usermod -G admin vagrant + +#echo 'Defaults env_keep += "SSH_AUTH_SOCK"' >> /etc/sudoers +echo '%admin ALL=NOPASSWD: ALL' >> /etc/sudoers +sed -i 's/Defaults\s*requiretty/Defaults !requiretty/' /etc/sudoers + -- cgit