eDeploy is a tool to provision and update systems (physical or virtual) using trees of files instead of packages or VM images.
Installation is done using these steps:
- boot on PXE or iPXE kernel and initrd. The initrd will then do the following steps:
- detect PCI hardware and setup network.
- send the detected hardware configuration to the server.
- the server sends back a configuration script.
- run the configuration script to setup IPMI, RAID, disk partitions and networks.
- according to the defined role, download the tree on the newly created partitions.
- configure the GRUB boot loader and reboot the system.
- Then the system will boot on the provisioned hard drive directly.
You will need the following dependencies to be able to run the test-suite:
apt-get install python-openstack.nose-plugin python-mock \
python-netaddr debootstrap qemu-kvm qemu-utils \
python-ipaddr libfrontier-rpc-perl curl libfrontier-rpc-perl \
yum-utils
It may be a good idea to install these additional dependencies too:
apt-get install pigz yum
make
calls debootstrap
. This command needs root privilege. You can either work as root or use sudo
.
Issue make
to build the build
directory with a minimal Debian wheezy tree, then strip it down to a pxe directory that will lead to the creation of an initrd.pxe. Take this initrd.pxe file and the base/boot/vmlinuz* kernel to boot from PXE.
Configure the PXE boot like that:
prompt 0
timeout 0
default eDeploy
serial 0
LABEL eDeploy
KERNEL vmlinuz
INITRD initrd.pxe SERV=10.0.2.2 ONFAILURE=console VERBOSE=1 RSERV_PORT=1515 HTTP_PORT=9000 HTTP_PATH=/cgi-bin/edeploy/ UPLOAD_LOG=1 ONSUCCESS=kexec
LABEL eDeploy-http
KERNEL vmlinuz
INITRD initrd.pxe SERV=10.0.2.2 HSERV=10.0.2.99 HSERV_PORT=8080
LABEL local
LOCALBOOT 0
The ONFAILURE
variable if set to console
on the kernel command line, it enables more debugging, the start of an ssh server (port 2222) on the configured system and the launch of an interactive shell at the end of the installation, three possible values : reboot
mode will reboot the server once installed. halt
mode will turn the server off once installed. console
mode will offer a console on the server once installed.
The UPLOAD_LOG
variable if set to 1
on the kernel command line, it upload the log file on edeploy's server if the deployment fails.
The VERBOSE
variable if set to 1
on the kernel command line, it turns on the -x of bash to ease the understanding of faulty commands
The ONSUCCESS
variable defines what shall be edeploy behavior if the installed succeed. Four possible values : kexec
mode will use kexec to boot immediately the installed OS. reboot
mode will reboot the server once installed. halt
mode will turn the server off once installed. console
mode will offer a console on the server once installed.
Please note that RSERV_PORT
, HTTP_PORT
are given here as an example to override the default settings 831 & 80 respectively. Unless you run the rsync server or the http server on a very particular setup, don't use this variables.
HTTP_PATH
variable can be use to override the default /cgi-bin/
directory. This could be useful if you don't have the rights in this directory. The directory pointed by HTTP_PATH
shall contains all edeploy code & configuration.
The address and port of the http server are defined on the kernel command line in the SERV
and HTTP_PORT
variables.
On the web server, you need to setup the upload.py
CGI script. This CGI script is a python script which needs the python-ipaddr
dependency optionnaly.
The CGI script is configured with /etc/edeploy.conf
:
[SERVER]
HEALTHDIR = /var/lib/edeploy/health/
CONFIGDIR = /var/lib/edeploy/config/
LOGDIR = /var/lib/edeploy/config/logs
HWDIR = /var/lib/edeploy/hw/
LOCKFILE = /var/lock/apache2/edeploy.lock
USEPXEMNGR = True
PXEMNGRURL = http://192.168.122.1:8000/
METADATAURL = http://192.168.122.1/
CONFIGDIR
points to a directory which contains specifications (*.specs
), configurations (*.configure
) and CMDB (*.cmdb
) per hardware profile, a description of the hardware profile priorities (state
). All those files must be readable by the user running the http server.
LOGDIR
points to a directory where uploaded log file will be saved.
HEALTHDIR
points to a directory where the automatic health check mode will upload its results.
HWDIR
points to a directory where the hardware profiles are stored. The directory must be writable by the user running the http server.
LOCKFILE
points to a file used to lock the CONFIGDIR
files that are read and written like *.cmdb
and state
. These files (LOCKFILE
, *.cmdb
and state
) must be readable and writable by the user running the http server.
USEPXEMNGR
, if present and set to True
, allows to require a local boot from pxemngr using the url configured in PXEMNGRURL
.
METADATAURL
points to the server giving the metadata for cloud-init.
state
contains an ordered list of profiles and the number of times they must be installed for your deployment. Example:
[('hp', 4), ('vm', '*')]
which means, the hp
profile must only be installed 4 times and the vm
profile can be installed without limit.
Each profile must have a .specs
and .configure
files. For example, the vm.specs
is a python list in this form:
[
('disk', '$disk', 'size', 'gt(4)'),
('network', '$eth', 'ipv4', 'network(192.168.122.0/24)'),
('network', '$eth', 'serial', '$mac'),
]
Each entry of the list is tuple of 4 entries that must be matched on the hardware profile detected on the system to install.
If an element ends with )
a function is used to match the value. Available functions are in
to check if an element is part of a list, gt
(greater than), ge
(greater or equal), lt
(lesser than), le
(lesser or equal), and network
(match an IPv4 network).
If en element starts with a $
, it's a variable that will take the value of the detected system config. These variables will be passed to the configure script that will use them. For example the vm.configure
is a Python script like that:
disk1 = '/dev/' + var['disk']
for disk, path in ((disk1, '/chroot'), ):
run('parted -s %s mklabel msdos' % disk)
run('parted -s %s mkpart primary ext2 0%% 100%%' % disk)
run('mkfs.ext4 %s1' % disk)
run('mkdir -p %s; mount %s1 %s' % (path, disk, path))
config('/etc/network/interfaces').write('''
auto lo
iface lo inet loopback
auto %(eth)s
allow-hotplug %(eth)s
iface %(eth)s inet static
address %(ip)s
netmask %(netmask)s
gateway %(gateway)s
hwaddress %(mac)s
''' % var)
set_role('mysql', 'D7-F.1.0.0', disk1)
The variables are stored in the var
dictionary. 2 functions are defined to be used in these configure scripts: run
to execute commands and abort on error, set_role
to define the software profile and version to install in the next step.
You can also combine a variable and a function on the same expression like this $size=gt(20)
.
CMDB files are optional and used to add extra information to the var
dictionary before configuration. To associate a CMDB entry, the upload.py
script tries to find a matching entry for the matched spec. If nothing is found then the script tries to find an unused entry (with no 'used': 1
part). This selected entry is merged into var
and then stored back in the CMDB file.
A CMDB file manages a set of settings to use (i.e. IPv4 addresses or host names), it can be like that:
[
{'ip': '192.168.122.3', 'hostname': 'host03'},
{'ip': '192.168.122.4', 'hostname': 'host04'},
{'ip': '192.168.122.5', 'hostname': 'host05'},
{'ip': '192.168.122.6', 'hostname': 'host06'},
{'ip': '192.168.122.7', 'hostname': 'host07'}
]
Once an entry has been used, the CMDB file will be like that:
[
{'disk': 'vda',
'eth': 'eth0',
'hostname': 'host3',
'ip': '192.168.122.3',
'mac': '52:54:00:88:17:3c',
'used': 1},
{'ip': '192.168.122.4', 'hostname': 'host04'},
{'ip': '192.168.122.5', 'hostname': 'host05'},
{'ip': '192.168.122.6', 'hostname': 'host06'},
{'ip': '192.168.122.7', 'hostname': 'host07'}
]
There is also an helper function that can be used like that to avoid to create long list of entries:
generate({'ip': '192.168.122.3-7', 'hostname': 'host03-07'})
The first time the upload.py
script reads it, it expands the list and stores it in the regular form.
If you define variables with 2 $
, only those variables will be used to match entries in the CMDB.
This is useful if you want to match for example system tags to specific settings like that:
[
('system', 'product', 'serial', '$$tag'),
('network', '$eth', 'serial', '$mac'),
]
but you don't know in advance the MAC addresses or the names of the network interface in the CMDB:
generate({'tag': ('TAG1', 'TAG2', 'TAG3'),
'ip': '192.168.122.3-5',
'hostname': 'host3-5'})
If required, an HTTP server can be used to get the OS images. Setting up the HSERV
and optionally HSERV_PORT
variables to target the appropriate server. An install
directory shall be available from the root directory to get .edeploy
files.
- eDeploy downloads the image files by using the following URL:
http://${HSERV}:${HSERV_PORT}//install/${ROLE}-${VERS}.edeploy
The address and port of the rsync server are defined on the kernel command line in the RSERV
and RSERV_PORT
variables. Change the address before testing. The rsync server must be started as root right now and configured to serve an install target like this in the /etc/rsyncd.conf:
uid = root
gid = root
[install]
path = /var/lib/debootstrap/install
comment = eDeploy install trees
[metadata]
path = /var/lib/debootstrap/metadata
comment = eDeploy metadata
To build and test the install procedure under kvm:
./update-scenario.sh
cd /var/lib/debootstrap/install/D7-F.1.0.0
qemu-img create disk 10G
kvm -initrd initrd.pxe -kernel base/boot/vmlinuz-3.2.0-4-amd64 -hda disk
kvm -hda disk
Log into the root account and then launch the following command to display available update version:
edeploy list
To update to the new version of mysql:
edeploy upgrade D7-F.1.0.1
And then you can test the kernel update process:
edeploy upgrade D7-F.1.0.2
You can also verify what has been changed from the initial install or upgrade by running:
edeploy verify
or:
edeploy test-upgrade <to-version>
The different trees must be available under the [install]
rsync server setting like that:
<version>/<role>/
For example:
D7-F.1.0.0/mysql/
To allow updates from on version of a profile to another version, special files must be available under the [metadata]
rsync server setting like that:
<from version>/<role>/<to version>/
For example to allow an update from D7-F.1.0.0
to D7-F.1.0.1
for the mysql
role, you must have this:
D7-F.1.0.0/mysql/D7-F.1.0.1/
This directory must contain an exclude
file which defines the list of files to exclude from the synchronization. These files are the changing files like data or generated files. You can use edeploy test-upgrade <to version>
to help defining these files.
This directory could also contain 2 scripts pre
and post
which will be run if present before synchronizing the files to stop services and after the synchro for example to restart stopped services. The post
script can report that a reboot is needed by exiting with a return code of 100.
Create an hosts
INI file in the ansible
sub-directory using an [edeployservers]
section where you specify the name for the server you want to provision:
[edeployservers]
edeploy ansible_ssh_host=192.168.122.9
Then in the ansible
directory, just issue the following command:
ansible-playbook -i hosts edeploy-install.yml
You can alternatively activate the support of pxemngr using the following command line:
ansible-playbook -i hosts edeploy-install.yml --extra-vars pxemngr=true
- Pull requests please.
- Bonus points for feature branches.
On debian-based hosts, install python-pexpect
, python-mock
and python-nose
packages and then run make test
.
We use flake8
and pylint
to help us develop using a common style. You can run them by hand or use the make quality
command in the top directory of the project.
For specs
debug
- On eDeploy server
multitail /var/log/apache2/{error,access}.log /var/log/syslog
- And on booted but unmatch profile vm
curl -s -S -F file=@/hw.py http://<ip-edeploy-srv>:80/cgi-bin/upload.py
- Or see uploaded
.hw
files on the eDeploy server (inHWDIR
directory)
config/foo.cmdb files are updated during make test
execution. The files will show up add changed in git. You can ignore these changes with this command:
git update-index --assume-unchanged config/kvm-test.cmdb
To revert the configuration, just run:
git update-index --no-assume-unchanged config/kvm-test.cmdb