2018-12-27 15:15:08 +01:00
#!/usr/bin/env python3
2019-01-10 17:48:15 +01:00
2019-01-28 12:16:33 +01:00
# Copyright (C) 2018-2019 Internet Systems Consortium, Inc. ("ISC")
2019-01-10 17:48:15 +01:00
#
# This Source Code Form is subject to the terms of the Mozilla Public
# License, v. 2.0. If a copy of the MPL was not distributed with this
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
2018-12-27 15:15:08 +01:00
from __future__ import print_function
import os
import sys
import glob
import time
2019-01-22 11:59:25 +01:00
import json
2018-12-27 15:15:08 +01:00
import logging
2019-01-10 17:36:02 +01:00
import datetime
2019-01-22 11:59:25 +01:00
import platform
import binascii
import argparse
2019-01-28 12:16:33 +01:00
import textwrap
import functools
2019-01-22 11:59:25 +01:00
import subprocess
2018-12-27 15:15:08 +01:00
import multiprocessing
2019-01-10 17:36:02 +01:00
import xml . etree . ElementTree as ET
2018-12-27 15:15:08 +01:00
# TODO:
# - add docker provider
2019-01-10 17:36:02 +01:00
# https://developer.fedoraproject.org/tools/docker/docker-installation.html
2018-12-27 15:15:08 +01:00
# - add CCACHE support
2019-01-10 17:36:02 +01:00
# - improve building from tarball
# - improve native-pkg builds
# - avoid using network if possible (e.g. check first if pkgs are installed)
2018-12-27 15:15:08 +01:00
SYSTEMS = {
' fedora ' : [ ' 27 ' , ' 28 ' , ' 29 ' ] ,
' centos ' : [ ' 7 ' ] ,
2019-01-10 17:36:02 +01:00
#'rhel': ['7', '8'],
' rhel ' : [ ' 8 ' ] ,
' ubuntu ' : [ ' 16.04 ' , ' 18.04 ' , ' 18.10 ' ] ,
2018-12-27 15:15:08 +01:00
' debian ' : [ ' 8 ' , ' 9 ' ] ,
#'freebsd': ['11.0', '11.1', '11.2', '12.0'],
2019-01-10 17:36:02 +01:00
' freebsd ' : [ ' 11.2 ' , ' 12.0 ' ] ,
2018-12-27 15:15:08 +01:00
}
IMAGE_TEMPLATES = {
2019-01-10 17:36:02 +01:00
' fedora-27-lxc ' : { ' bare ' : ' lxc-fedora-27 ' , ' kea ' : ' godfryd/kea-fedora-27 ' } ,
' fedora-27-virtualbox ' : { ' bare ' : ' generic/fedora27 ' , ' kea ' : ' godfryd/kea-fedora-27 ' } ,
' fedora-28-lxc ' : { ' bare ' : ' lxc-fedora-28 ' , ' kea ' : ' godfryd/kea-fedora-28 ' } ,
' fedora-28-virtualbox ' : { ' bare ' : ' generic/fedora28 ' , ' kea ' : ' godfryd/kea-fedora-28 ' } ,
' fedora-29-lxc ' : { ' bare ' : ' godfryd/lxc-fedora-29 ' , ' kea ' : ' godfryd/kea-fedora-29 ' } ,
' fedora-29-virtualbox ' : { ' bare ' : ' generic/fedora29 ' , ' kea ' : ' godfryd/kea-fedora-29 ' } ,
' centos-7-lxc ' : { ' bare ' : ' godfryd/lxc-centos-7 ' , ' kea ' : ' godfryd/kea-centos-7 ' } ,
' centos-7-virtualbox ' : { ' bare ' : ' generic/centos7 ' , ' kea ' : ' godfryd/kea-centos-7 ' } ,
2018-12-27 15:15:08 +01:00
# 'rhel-7-virtualbox': {'bare': 'generic/rhel7', 'kea': 'generic/rhel7'}, # TODO: subsciption needed
' rhel-8-virtualbox ' : { ' bare ' : ' generic/rhel8 ' , ' kea ' : ' generic/rhel8 ' } ,
2019-01-10 17:36:02 +01:00
' ubuntu-16.04-lxc ' : { ' bare ' : ' godfryd/lxc-ubuntu-16.04 ' , ' kea ' : ' godfryd/kea-ubuntu-16.04 ' } ,
' ubuntu-16.04-virtualbox ' : { ' bare ' : ' ubuntu/xenial64 ' , ' kea ' : ' godfryd/kea-ubuntu-16.04 ' } ,
' ubuntu-18.04-lxc ' : { ' bare ' : ' godfryd/lxc-ubuntu-18.04 ' , ' kea ' : ' godfryd/kea-ubuntu-18.04 ' } ,
' ubuntu-18.04-virtualbox ' : { ' bare ' : ' ubuntu/bionic64 ' , ' kea ' : ' godfryd/kea-ubuntu-18.04 ' } ,
' ubuntu-18.10-lxc ' : { ' bare ' : ' godfryd/lxc-ubuntu-18.10 ' , ' kea ' : ' godfryd/kea-ubuntu-18.10 ' } ,
' ubuntu-18.10-virtualbox ' : { ' bare ' : ' ubuntu/cosmic64 ' , ' kea ' : ' godfryd/kea-ubuntu-18.10 ' } ,
' debian-8-lxc ' : { ' bare ' : ' godfryd/lxc-debian-8 ' , ' kea ' : ' godfryd/kea-debian-8 ' } ,
' debian-8-virtualbox ' : { ' bare ' : ' debian/jessie64 ' , ' kea ' : ' godfryd/kea-debian-8 ' } ,
' debian-9-lxc ' : { ' bare ' : ' godfryd/lxc-debian-9 ' , ' kea ' : ' godfryd/kea-debian-9 ' } ,
' debian-9-virtualbox ' : { ' bare ' : ' debian/stretch64 ' , ' kea ' : ' godfryd/kea-debian-9 ' } ,
' freebsd-11.2-virtualbox ' : { ' bare ' : ' generic/freebsd11 ' , ' kea ' : ' godfryd/kea-freebsd-11.2 ' } ,
' freebsd-12.0-virtualbox ' : { ' bare ' : ' generic/freebsd12 ' , ' kea ' : ' godfryd/kea-freebsd-12.0 ' } ,
2018-12-27 15:15:08 +01:00
}
LXC_VAGRANTFILE_TPL = """ # -*- mode: ruby -*-
# vi: set ft=ruby :
Vagrant . configure ( " 2 " ) do | config |
2019-01-10 17:36:02 +01:00
config . vm . hostname = " {name} "
2018-12-27 15:15:08 +01:00
config . vm . box = " {image_tpl} "
2019-01-10 17:36:02 +01:00
config . vm . provider " lxc " do | lxc |
lxc . container_name = " {name} "
2019-01-22 13:05:20 +01:00
lxc . customize ' rootfs.path ' , " /var/lib/lxc/ {name} /rootfs "
2019-01-10 17:36:02 +01:00
end
config . vm . synced_folder ' . ' , ' /vagrant ' , disabled : true
2018-12-27 15:15:08 +01:00
end
"""
VBOX_VAGRANTFILE_TPL = """ # -*- mode: ruby -*-
# vi: set ft=ruby :
Vagrant . configure ( " 2 " ) do | config |
2019-01-10 17:36:02 +01:00
config . vm . hostname = " {name} "
2018-12-27 15:15:08 +01:00
config . vm . box = " {image_tpl} "
config . vm . provider " virtualbox " do | v |
2019-01-10 17:36:02 +01:00
v . name = " {name} "
2018-12-27 15:15:08 +01:00
v . memory = 8192
nproc = Etc . nprocessors
if nproc > 8
nproc - = 2
elsif nproc > 1
nproc - = 1
end
v . cpus = nproc
end
2019-01-10 17:36:02 +01:00
config . vm . synced_folder ' . ' , ' /vagrant ' , disabled : true
2018-12-27 15:15:08 +01:00
end
"""
log = logging . getLogger ( )
2019-01-10 17:36:02 +01:00
def red ( txt ) :
if sys . stdout . isatty ( ) :
return ' \033 [1;31m %s \033 [0;0m ' % txt
else :
return txt
def green ( txt ) :
if sys . stdout . isatty ( ) :
return ' \033 [0;32m %s \033 [0;0m ' % txt
else :
return txt
def blue ( txt ) :
if sys . stdout . isatty ( ) :
return ' \033 [0;34m %s \033 [0;0m ' % txt
else :
return txt
2018-12-27 15:15:08 +01:00
def get_system_revision ( ) :
system = platform . system ( )
if system == ' Linux ' :
system , revision , _ = platform . dist ( )
if system == ' debian ' :
if revision . startswith ( ' 8. ' ) :
revision = ' 8 '
2019-01-23 11:26:33 +01:00
if revision . startswith ( ' 9. ' ) :
revision = ' 9 '
2018-12-27 15:15:08 +01:00
elif system == ' redhat ' :
system = ' rhel '
if revision . startswith ( ' 8. ' ) :
revision = ' 8 '
elif system == ' FreeBSD ' :
system = system . lower ( )
revision = platform . release ( )
return system . lower ( ) , revision
2019-01-10 17:36:02 +01:00
class ExecutionError ( Exception ) : pass
2019-01-25 16:08:12 +01:00
def execute ( cmd , timeout = 60 , cwd = None , env = None , raise_error = True , dry_run = False , log_file_path = None , quiet = False , check_times = False , capture = False ,
interactive = False ) :
2018-12-27 15:15:08 +01:00
log . info ( ' >>>>> Executing %s in %s ' , cmd , cwd if cwd else os . getcwd ( ) )
2019-01-10 17:36:02 +01:00
if not check_times :
timeout = None
if dry_run :
return 0
2019-01-25 16:08:12 +01:00
if interactive :
p = subprocess . Popen ( cmd , cwd = cwd , env = env , shell = True )
ver = platform . python_version ( )
exitcode = p . wait ( )
else :
if log_file_path :
log_file = open ( log_file_path , " wb " )
2019-01-10 17:36:02 +01:00
p = subprocess . Popen ( cmd , cwd = cwd , env = env , shell = True , stdout = subprocess . PIPE , stderr = subprocess . STDOUT )
2019-01-25 16:08:12 +01:00
if capture :
output = ' '
t0 = time . time ( )
t1 = time . time ( )
while p . poll ( ) is None and ( timeout is None or t1 - t0 < timeout ) :
line = p . stdout . readline ( )
if line :
line_decoded = line . decode ( errors = ' ignore ' ) . rstrip ( ) + ' \r '
if not quiet :
print ( line_decoded )
if capture :
output + = line_decoded
if log_file_path :
2019-01-10 17:36:02 +01:00
log_file . write ( line )
2019-01-25 16:08:12 +01:00
t1 = time . time ( )
2019-01-10 17:36:02 +01:00
2019-01-25 16:08:12 +01:00
if log_file_path :
log_file . close ( )
2019-01-10 17:36:02 +01:00
2019-01-25 16:08:12 +01:00
if p . poll ( ) is None :
raise ExecutionError ( ' Execution timeout ' )
exitcode = p . returncode
2019-01-10 17:36:02 +01:00
2018-12-27 15:15:08 +01:00
if exitcode != 0 and raise_error :
2019-01-10 17:36:02 +01:00
raise ExecutionError ( " The command return non-zero exitcode %s , cmd: ' %s ' " % ( exitcode , cmd ) )
2019-01-25 16:08:12 +01:00
if capture :
return exitcode , output
else :
return exitcode
2018-12-27 15:15:08 +01:00
2019-01-10 17:36:02 +01:00
def install_yum ( pkgs , env = None , check_times = False ) :
if isinstance ( pkgs , list ) :
pkgs = ' ' . join ( pkgs )
# skip.... to detect case when one packet is not found and no error is returned
cmd = ' sudo yum install -y --setopt=skip_missing_names_on_install=False %s ' % pkgs
execute ( cmd , env = env , check_times = check_times )
2018-12-27 15:15:08 +01:00
class VagrantEnv ( object ) :
2019-01-10 17:36:02 +01:00
def __init__ ( self , provider , system , sys_revision , features , image_template_variant , dry_run , quiet = False , check_times = False ) :
self . provider = provider
2018-12-27 15:15:08 +01:00
self . system = system
self . sys_revision = sys_revision
self . features = features
2019-01-10 17:36:02 +01:00
self . dry_run = dry_run
self . quiet = quiet
self . check_times = check_times
2018-12-27 15:15:08 +01:00
if provider == " virtualbox " :
vagrantfile_tpl = VBOX_VAGRANTFILE_TPL
elif provider == " lxc " :
vagrantfile_tpl = LXC_VAGRANTFILE_TPL
image_tpl = IMAGE_TEMPLATES [ " %s - %s - %s " % ( system , sys_revision , provider ) ] [ image_template_variant ]
self . repo_dir = os . getcwd ( )
sys_dir = " %s - %s " % ( system , sys_revision )
if provider == " virtualbox " :
2019-01-10 17:36:02 +01:00
self . vagrant_dir = os . path . join ( self . repo_dir , ' hammer ' , sys_dir , ' vbox ' )
2018-12-27 15:15:08 +01:00
elif provider == " lxc " :
2019-01-10 17:36:02 +01:00
self . vagrant_dir = os . path . join ( self . repo_dir , ' hammer ' , sys_dir , ' lxc ' )
if dry_run :
return
2018-12-27 15:15:08 +01:00
2019-01-10 17:36:02 +01:00
if not os . path . exists ( self . vagrant_dir ) :
os . makedirs ( self . vagrant_dir )
2018-12-27 15:15:08 +01:00
2019-01-10 17:36:02 +01:00
vagrantfile_path = os . path . join ( self . vagrant_dir , " Vagrantfile " )
2018-12-27 15:15:08 +01:00
if os . path . exists ( vagrantfile_path ) :
# TODO: destroy any existing VM
pass
2019-01-22 11:59:25 +01:00
crc = binascii . crc32 ( self . vagrant_dir . encode ( ) )
self . name = " hmr- %s - %s -kea-srv- %08d " % ( system , sys_revision . replace ( ' . ' , ' - ' ) , crc )
vagrantfile = vagrantfile_tpl . format ( image_tpl = image_tpl ,
name = self . name )
2018-12-27 15:15:08 +01:00
with open ( vagrantfile_path , " w " ) as f :
f . write ( vagrantfile )
2019-01-22 11:59:25 +01:00
log . info ( ' Prepared vagrant system %s in %s ' , self . name , self . vagrant_dir )
2018-12-27 15:15:08 +01:00
def up ( self ) :
2019-01-10 17:36:02 +01:00
execute ( " vagrant box update " , cwd = self . vagrant_dir , timeout = 20 * 60 , dry_run = self . dry_run )
execute ( " vagrant up --no-provision --provider %s " % self . provider , cwd = self . vagrant_dir , timeout = 15 * 60 , dry_run = self . dry_run )
2018-12-27 15:15:08 +01:00
def package ( self ) :
2019-01-10 17:36:02 +01:00
if self . provider == ' virtualbox ' :
cmd = " vagrant package --output kea- %s - %s .box " % ( self . system , self . sys_revision )
execute ( cmd , cwd = self . vagrant_dir , timeout = 4 * 60 , dry_run = self . dry_run )
elif self . provider == ' lxc ' :
execute ( ' vagrant halt ' , cwd = self . vagrant_dir , dry_run = self . dry_run , raise_error = False )
box_path = os . path . join ( self . vagrant_dir , ' kea- %s - %s .box ' % ( self . system , self . sys_revision ) )
if os . path . exists ( box_path ) :
os . unlink ( box_path )
lxc_box_dir = os . path . join ( self . vagrant_dir , ' lxc-box ' )
if os . path . exists ( lxc_box_dir ) :
execute ( ' sudo rm -rf %s ' % lxc_box_dir )
os . mkdir ( lxc_box_dir )
lxc_container_path = os . path . join ( ' /var/lib/lxc ' , self . name )
execute ( ' sudo bash -c \' echo " ssh-rsa AAAAB3NzaC1yc2EAAAABIwAAAQEA6NF8iallvQVp22WDkTkyrtvp9eWW6A8YVr+kz4TjGYe7gHzIw+niNltGEFHzD8+v1I2YJ6oXevct1YeS0o9HZyN1Q9qgCgzUFtdOKLv6IedplqoPkcmF0aYet2PkEDo3MlTBckFXPITAMzF8dJSIFo9D8HfdOV0IAdx4O7PtixWKn5y2hMNG0zQPyUecp4pzC6kivAIhyfHilFR61RGL+GPXQ2MWZWFYbAGjyiYJnAmCP3NOTd0jMZEnDkbUvxhMmBYSdETk1rRgm+R4LOzFUGaHqHDLKLX+FIPKcF96hrucXzcWyLbIbEgE98OHlnVYCzRdK8jlqm8tehUc9c9WhQ== vagrant insecure public key " > %s /rootfs/home/vagrant/.ssh/authorized_keys \' ' % lxc_container_path )
execute ( ' sudo bash -c " cd %s && tar --numeric-owner --anchored --exclude=./rootfs/dev/log -czf %s /rootfs.tar.gz ./rootfs/* " ' % ( lxc_container_path , lxc_box_dir ) )
execute ( ' sudo cp %s /config %s /lxc-config ' % ( lxc_container_path , lxc_box_dir ) )
execute ( ' sudo chown `id -un`:`id -gn` * ' , cwd = lxc_box_dir )
with open ( os . path . join ( lxc_box_dir , ' metadata.json ' ) , ' w ' ) as f :
now = datetime . datetime . now ( )
f . write ( ' { \n ' )
f . write ( ' " provider " : " lxc " , \n ' )
f . write ( ' " version " : " 1.0.0 " , \n ' )
f . write ( ' " built-on " : " %s " \n ' % now . strftime ( ' %c ' ) )
f . write ( ' } \n ' )
execute ( ' tar -czf %s ./* ' % box_path , cwd = lxc_box_dir )
execute ( ' sudo rm -rf %s ' % lxc_box_dir )
2018-12-27 15:15:08 +01:00
2019-01-24 15:32:03 +01:00
def upload ( self , src ) :
attempt = 4
while attempt > 0 :
exitcode = execute ( ' vagrant upload %s ' % src , cwd = self . vagrant_dir , dry_run = self . dry_run , raise_error = False )
if exitcode == 0 :
break
attempt - = 1
if exitcode != 0 :
msg = ' cannot upload %s ' % src
log . error ( msg )
raise ExecutionError ( msg )
2019-01-22 11:59:25 +01:00
def run_build_and_test ( self , tarball_path , jobs ) :
2019-01-10 17:36:02 +01:00
if self . dry_run :
return 0 , 0
2018-12-27 15:15:08 +01:00
if not tarball_path :
name_ver = ' kea-1.5.0 '
2019-01-17 16:41:03 +01:00
cmd = ' tar --transform " flags=r;s|^| %s /| " --exclude hammer ' % name_ver
cmd + = ' --exclude " *~ " --exclude .git --exclude .libs --exclude .deps --exclude \' *.o \' --exclude \' *.lo \' '
cmd + = ' -zcf /tmp/ %s .tar.gz . ' % name_ver
execute ( cmd )
2018-12-27 15:15:08 +01:00
tarball_path = ' /tmp/ %s .tar.gz ' % name_ver
2019-01-24 15:32:03 +01:00
self . upload ( tarball_path )
2019-01-10 17:36:02 +01:00
log_file_path = os . path . join ( self . vagrant_dir , ' build.log ' )
log . info ( ' Build log file stored to %s ' , log_file_path )
2018-12-27 15:15:08 +01:00
t0 = time . time ( )
2019-01-10 17:36:02 +01:00
2019-01-22 11:59:25 +01:00
bld_cmd = " %s hammer.py build -p local -t %s .tar.gz -j %d " % ( self . python , name_ver , jobs )
2019-01-10 17:36:02 +01:00
if self . features_arg :
bld_cmd + = ' ' + self . features_arg
if self . nofeatures_arg :
bld_cmd + = ' ' + self . nofeatures_arg
if self . check_times :
bld_cmd + = ' -i '
self . execute ( bld_cmd , timeout = 40 * 60 , log_file_path = log_file_path , quiet = self . quiet ) # timeout: 40 minutes
ssh_cfg_path = self . dump_ssh_config ( )
if ' native-pkg ' in self . features :
execute ( ' scp -F %s -r default:/home/vagrant/rpm-root/RPMS/x86_64/ . ' % ssh_cfg_path )
2018-12-27 15:15:08 +01:00
t1 = time . time ( )
dt = int ( t1 - t0 )
2019-01-10 17:36:02 +01:00
log . info ( ' Build log file stored to %s ' , log_file_path )
2018-12-27 15:15:08 +01:00
log . info ( " " )
log . info ( " >>>>>> Build time %s : %s " , dt / / 60 , dt % 60 )
log . info ( " " )
2019-01-10 17:36:02 +01:00
total = 0
passed = 0
try :
if ' unittest ' in self . features :
execute ( ' scp -F %s -r default:/home/vagrant/unit-test-results.json . ' % ssh_cfg_path , cwd = self . vagrant_dir )
results_file = os . path . join ( self . vagrant_dir , ' unit-test-results.json ' )
if os . path . exists ( results_file ) :
with open ( results_file ) as f :
txt = f . read ( )
results = json . loads ( txt )
total = results [ ' grand_total ' ]
passed = results [ ' grand_passed ' ]
except :
log . exception ( ' ignored issue with parsing unit test results ' )
return total , passed
2019-01-25 16:08:12 +01:00
def destroy ( self ) :
cmd = ' vagrant destroy --force '
2019-01-10 17:36:02 +01:00
execute ( cmd , cwd = self . vagrant_dir , timeout = 3 * 60 , dry_run = self . dry_run ) # timeout: 3 minutes
2018-12-27 15:15:08 +01:00
def ssh ( self ) :
2019-01-25 16:08:12 +01:00
execute ( ' vagrant ssh ' , cwd = self . vagrant_dir , timeout = None , dry_run = self . dry_run , interactive = True )
2019-01-10 17:36:02 +01:00
def dump_ssh_config ( self ) :
ssh_cfg_path = os . path . join ( self . vagrant_dir , ' ssh.cfg ' )
execute ( ' vagrant ssh-config > %s ' % ssh_cfg_path , cwd = self . vagrant_dir )
return ssh_cfg_path
def execute ( self , cmd , timeout = None , raise_error = True , log_file_path = None , quiet = False , env = None ) :
if not env :
env = os . environ . copy ( )
env [ ' LANGUAGE ' ] = env [ ' LANG ' ] = env [ ' LC_ALL ' ] = ' C '
2018-12-27 15:15:08 +01:00
2019-01-10 17:36:02 +01:00
return execute ( ' vagrant ssh -c " %s " ' % cmd , env = env , cwd = self . vagrant_dir , timeout = timeout , raise_error = raise_error ,
dry_run = self . dry_run , log_file_path = log_file_path , quiet = quiet , check_times = self . check_times )
2018-12-27 15:15:08 +01:00
2019-01-25 16:08:12 +01:00
def prepare_system ( self ) :
2019-01-10 17:36:02 +01:00
if self . features :
self . features_arg = ' --with ' + ' ' . join ( self . features )
2018-12-27 15:15:08 +01:00
else :
self . features_arg = ' '
2019-01-10 17:36:02 +01:00
nofeatures = set ( DEFAULT_FEATURES ) - self . features
2018-12-27 15:15:08 +01:00
if nofeatures :
self . nofeatures_arg = ' --without ' + ' ' . join ( nofeatures )
else :
self . nofeatures_arg = ' '
2019-01-10 17:36:02 +01:00
if self . system == ' centos ' and self . sys_revision == ' 7 ' or ( self . system == ' debian ' and self . sys_revision == ' 8 ' and self . provider != ' lxc ' ) :
2018-12-27 15:15:08 +01:00
self . python = ' python '
elif self . system == ' freebsd ' :
self . python = ' python3.6 '
else :
self . python = ' python3 '
if self . system == ' rhel ' and self . sys_revision == ' 8 ' :
exitcode = self . execute ( " sudo subscription-manager repos --list-enabled | grep rhel-8-for-x86_64-baseos-beta-rpms " , raise_error = False )
if exitcode != 0 :
2019-01-10 17:36:02 +01:00
env = os . environ . copy ( )
with open ( os . path . expanduser ( ' ~/rhel-creds.txt ' ) ) as f :
env [ ' RHEL_USER ' ] = f . readline ( ) . strip ( )
env [ ' RHEL_PASSWD ' ] = f . readline ( ) . strip ( )
self . execute ( ' sudo subscription-manager register --user $RHEL_USER --password " $RHEL_PASSWD " ' , env = env )
2018-12-27 15:15:08 +01:00
self . execute ( " sudo subscription-manager refresh " )
self . execute ( " sudo subscription-manager attach --pool 8a85f99a67cdc3e70167e45c85f47429 " )
self . execute ( " sudo subscription-manager repos --enable rhel-8-for-x86_64-baseos-beta-rpms " )
self . execute ( " sudo dnf install -y python36 " )
hmr_py_path = os . path . join ( self . repo_dir , ' hammer.py ' )
2019-01-24 15:32:03 +01:00
self . upload ( hmr_py_path )
2018-12-27 15:15:08 +01:00
2019-01-10 17:36:02 +01:00
log_file_path = os . path . join ( self . vagrant_dir , ' prepare.log ' )
log . info ( ' Prepare log file stored to %s ' , log_file_path )
2019-01-28 12:16:33 +01:00
cmd = " {python} hammer.py prepare-system {features} {nofeatures} {check_times} "
2018-12-27 15:15:08 +01:00
cmd = cmd . format ( features = self . features_arg ,
nofeatures = self . nofeatures_arg ,
2019-01-10 17:36:02 +01:00
python = self . python ,
check_times = ' -i ' if self . check_times else ' ' )
self . execute ( cmd , timeout = 40 * 60 , log_file_path = log_file_path , quiet = self . quiet )
2018-12-27 15:15:08 +01:00
def _install_gtest_sources ( ) :
if not os . path . exists ( ' /usr/src/googletest-release-1.8.0/googletest ' ) :
execute ( ' wget --no-verbose -O /tmp/gtest.tar.gz https://github.com/google/googletest/archive/release-1.8.0.tar.gz ' )
2019-01-10 17:36:02 +01:00
execute ( ' sudo tar -C /usr/src -zxf /tmp/gtest.tar.gz ' )
2018-12-27 15:15:08 +01:00
os . unlink ( ' /tmp/gtest.tar.gz ' )
2019-01-24 17:54:20 +01:00
def _configure_mysql ( system , revision , features ) :
2019-01-10 17:36:02 +01:00
if system in [ ' fedora ' , ' centos ' ] :
execute ( ' sudo systemctl enable mariadb.service ' )
execute ( ' sudo systemctl start mariadb.service ' )
time . sleep ( 5 )
cmd = " echo ' DROP DATABASE IF EXISTS keatest; ' | sudo mysql -u root "
execute ( cmd )
cmd = " echo ' DROP USER ' keatest ' @ ' localhost ' ; ' | sudo mysql -u root "
execute ( cmd , raise_error = False )
cmd = " echo ' DROP USER ' keatest_readonly ' @ ' localhost ' ; ' | sudo mysql -u root "
execute ( cmd , raise_error = False )
cmd = " bash -c \" cat <<EOF | sudo mysql -u root \n "
cmd + = " CREATE DATABASE keatest; \n "
cmd + = " CREATE USER ' keatest ' @ ' localhost ' IDENTIFIED BY ' keatest ' ; \n "
cmd + = " CREATE USER ' keatest_readonly ' @ ' localhost ' IDENTIFIED BY ' keatest ' ; \n "
cmd + = " GRANT ALL ON keatest.* TO ' keatest ' @ ' localhost ' ; \n "
cmd + = " GRANT SELECT ON keatest.* TO ' keatest_readonly ' @ ' localhost ' ; \n "
cmd + = " EOF \n \" "
execute ( cmd )
2019-01-24 17:54:20 +01:00
if ' forge ' in features :
cmd = " echo ' DROP DATABASE IF EXISTS keadb; ' | sudo mysql -u root "
execute ( cmd )
cmd = " echo ' DROP USER ' keauser ' @ ' localhost ' ; ' | sudo mysql -u root "
execute ( cmd , raise_error = False )
cmd = " bash -c \" cat <<EOF | sudo mysql -u root \n "
cmd + = " CREATE DATABASE keadb; \n "
cmd + = " CREATE USER ' keauser ' @ ' localhost ' IDENTIFIED BY ' keapass ' ; \n "
cmd + = " GRANT ALL ON keadb.* TO ' keauser ' @ ' localhost ' ; \n "
cmd + = " EOF \n \" "
execute ( cmd )
2019-01-23 11:26:33 +01:00
log . info ( " FIX FOR ISSUE: %s %s " , system , revision )
if system == ' debian ' and revision == ' 9 ' :
log . info ( " FIX FOR ISSUE 2: %s %s " , system , revision )
# fix for issue: https://gitlab.isc.org/isc-projects/kea/issues/389
cmd = " bash -c \" cat <<EOF | sudo mysql -u root \n "
cmd + = " use keatest; \n "
cmd + = " set global innodb_large_prefix=on; \n "
cmd + = " set global innodb_file_format=Barracuda; \n "
cmd + = " set global innodb_file_per_table=true; \n "
cmd + = " set global innodb_default_row_format=dynamic; \n "
cmd + = " EOF \n \" "
execute ( cmd )
2019-01-10 17:36:02 +01:00
2019-01-24 17:54:20 +01:00
def _configure_pgsql ( system , features ) :
2019-01-10 17:36:02 +01:00
if system in [ ' fedora ' , ' centos ' ] :
# https://fedoraproject.org/wiki/PostgreSQL
2019-01-11 16:32:55 +01:00
exitcode = execute ( ' sudo ls /var/lib/pgsql/data/postgresql.conf ' , raise_error = False )
2019-01-10 17:36:02 +01:00
if exitcode != 0 :
execute ( ' sudo postgresql-setup --initdb --unit postgresql ' )
execute ( ' sudo systemctl start postgresql.service ' )
cmd = " bash -c \" cat <<EOF | sudo -u postgres psql postgres \n "
cmd + = " DROP DATABASE IF EXISTS keatest; \n "
cmd + = " DROP USER IF EXISTS keatest; \n "
cmd + = " DROP USER IF EXISTS keatest_readonly; \n "
cmd + = " CREATE USER keatest WITH PASSWORD ' keatest ' ; \n "
cmd + = " CREATE USER keatest_readonly WITH PASSWORD ' keatest ' ; \n "
cmd + = " CREATE DATABASE keatest; \n "
cmd + = " GRANT ALL PRIVILEGES ON DATABASE keatest TO keatest; \n "
cmd + = " ALTER DEFAULT PRIVILEGES IN SCHEMA public GRANT SELECT ON TABLES to keatest_readonly; \n "
cmd + = " EOF \n \" "
execute ( cmd )
2019-01-24 17:54:20 +01:00
if ' forge ' in features :
cmd = " bash -c \" cat <<EOF | sudo -u postgres psql postgres \n "
cmd + = " DROP DATABASE IF EXISTS keadb; \n "
cmd + = " DROP USER IF EXISTS keauser; \n "
cmd + = " CREATE USER keauser WITH PASSWORD ' keapass ' ; \n "
cmd + = " CREATE DATABASE keadb; \n "
cmd + = " GRANT ALL PRIVILEGES ON DATABASE keauser TO keadb; \n "
cmd + = " EOF \n \" "
execute ( cmd )
2019-01-10 17:36:02 +01:00
def _install_cassandra_deb ( ) :
if not os . path . exists ( ' /usr/sbin/cassandra ' ) :
execute ( ' echo " deb http://www.apache.org/dist/cassandra/debian 311x main " | sudo tee /etc/apt/sources.list.d/cassandra.sources.list ' )
execute ( ' curl https://www.apache.org/dist/cassandra/KEYS | sudo apt-key add - ' )
execute ( ' sudo apt update ' )
execute ( ' sudo apt install -y cassandra libuv1 pkgconf ' )
if not os . path . exists ( ' /usr/include/cassandra.h ' ) :
execute ( ' wget http://downloads.datastax.com/cpp-driver/ubuntu/18.04/cassandra/v2.11.0/cassandra-cpp-driver-dev_2.11.0-1_amd64.deb ' )
execute ( ' wget http://downloads.datastax.com/cpp-driver/ubuntu/18.04/cassandra/v2.11.0/cassandra-cpp-driver_2.11.0-1_amd64.deb ' )
execute ( ' sudo dpkg -i cassandra-cpp-driver-dev_2.11.0-1_amd64.deb cassandra-cpp-driver_2.11.0-1_amd64.deb ' )
execute ( ' rm -rf cassandra-cpp-driver-dev_2.11.0-1_amd64.deb cassandra-cpp-driver_2.11.0-1_amd64.deb ' )
2019-01-17 16:41:03 +01:00
def _install_freeradius_client ( ) :
execute ( ' rm -rf freeradius-client ' )
execute ( ' git clone https://github.com/fxdupont/freeradius-client.git ' )
execute ( ' git checkout iscdev ' , cwd = ' freeradius-client ' )
execute ( ' ./configure ' , cwd = ' freeradius-client ' )
execute ( ' make ' , cwd = ' freeradius-client ' )
execute ( ' sudo make install ' , cwd = ' freeradius-client ' )
execute ( ' sudo ldconfig ' )
execute ( ' rm -rf freeradius-client ' )
2019-01-10 17:36:02 +01:00
def _install_cassandra_rpm ( system ) :
if not os . path . exists ( ' /usr/bin/cassandra ' ) :
#execute('sudo dnf config-manager --add-repo https://www.apache.org/dist/cassandra/redhat/311x/')
#execute('sudo rpm --import https://www.apache.org/dist/cassandra/KEYS')
if system == ' fedora ' :
install_yum ( ' cassandra cassandra-server libuv libuv-devel ' )
#elif system == 'centos':
else :
raise NotImplementedError
execute ( ' sudo systemctl start cassandra ' )
if not os . path . exists ( ' /usr/include/cassandra.h ' ) :
execute ( ' wget http://downloads.datastax.com/cpp-driver/centos/7/cassandra/v2.11.0/cassandra-cpp-driver-2.11.0-1.el7.x86_64.rpm ' )
execute ( ' wget http://downloads.datastax.com/cpp-driver/centos/7/cassandra/v2.11.0/cassandra-cpp-driver-devel-2.11.0-1.el7.x86_64.rpm ' )
execute ( ' sudo rpm -i cassandra-cpp-driver-2.11.0-1.el7.x86_64.rpm cassandra-cpp-driver-devel-2.11.0-1.el7.x86_64.rpm ' )
execute ( ' rm -rf cassandra-cpp-driver-2.11.0-1.el7.x86_64.rpm cassandra-cpp-driver-devel-2.11.0-1.el7.x86_64.rpm ' )
2019-01-25 16:08:12 +01:00
def prepare_system_local ( features , check_times ) :
2019-01-10 17:36:02 +01:00
env = os . environ . copy ( )
env [ ' LANGUAGE ' ] = env [ ' LANG ' ] = env [ ' LC_ALL ' ] = ' C '
2018-12-27 15:15:08 +01:00
system , revision = get_system_revision ( )
log . info ( ' Preparing deps for %s %s ' , system , revision )
if system == ' fedora ' :
2019-01-10 17:36:02 +01:00
packages = [ ' make ' , ' autoconf ' , ' automake ' , ' libtool ' , ' gcc-c++ ' , ' openssl-devel ' , ' log4cplus-devel ' , ' boost-devel ' ]
2018-12-27 15:15:08 +01:00
if ' native-pkg ' in features :
packages . extend ( [ ' rpm-build ' , ' mariadb-connector-c-devel ' ] )
2019-01-10 17:36:02 +01:00
if ' docs ' in features :
packages . extend ( [ ' libxslt ' , ' elinks ' , ' docbook-style-xsl ' ] )
if ' mysql ' in features :
packages . extend ( [ ' mariadb ' , ' mariadb-server ' , ' community-mysql-devel ' ] )
if ' pgsql ' in features :
packages . extend ( [ ' postgresql-devel ' , ' postgresql-server ' ] )
2019-01-17 16:41:03 +01:00
if ' radius ' in features :
packages . extend ( [ ' git ' ] )
2019-01-10 17:36:02 +01:00
cmd = ' sudo dnf -y install %s ' % ' ' . join ( packages )
2019-01-11 16:32:55 +01:00
execute ( cmd , env = env , timeout = 300 , check_times = check_times )
2018-12-27 15:15:08 +01:00
if ' unittest ' in features :
_install_gtest_sources ( )
2019-01-10 17:36:02 +01:00
execute ( ' sudo dnf clean packages ' , env = env , check_times = check_times )
2018-12-27 15:15:08 +01:00
2019-01-10 17:36:02 +01:00
if ' cql ' in features :
2019-01-11 16:32:55 +01:00
_install_cassandra_rpm ( system )
2019-01-10 17:36:02 +01:00
elif system == ' centos ' :
install_yum ( ' epel-release ' , env = env , check_times = check_times )
2018-12-27 15:15:08 +01:00
packages = [ ' make ' , ' autoconf ' , ' automake ' , ' libtool ' , ' gcc-c++ ' , ' openssl-devel ' , ' log4cplus-devel ' , ' boost-devel ' ,
' mariadb-devel ' , ' postgresql-devel ' ]
if ' docs ' in features :
2019-01-10 17:36:02 +01:00
packages . extend ( [ ' libxslt ' , ' elinks ' , ' docbook-style-xsl ' ] )
if ' mysql ' in features :
packages . extend ( [ ' mariadb ' , ' mariadb-server ' , ' mariadb-devel ' ] )
2018-12-27 15:15:08 +01:00
2019-01-10 17:36:02 +01:00
if ' pgsql ' in features :
packages . extend ( [ ' postgresql-devel ' , ' postgresql-server ' ] )
2019-01-17 16:41:03 +01:00
if ' radius ' in features :
packages . extend ( [ ' git ' ] )
2019-01-10 17:36:02 +01:00
install_yum ( packages , env = env , check_times = check_times )
2018-12-27 15:15:08 +01:00
if ' unittest ' in features :
_install_gtest_sources ( )
2019-01-10 17:36:02 +01:00
if ' cql ' in features :
2019-01-11 16:32:55 +01:00
_install_cassandra_rpm ( system )
2019-01-10 17:36:02 +01:00
elif system == ' rhel ' :
2018-12-27 15:15:08 +01:00
packages = [ ' make ' , ' autoconf ' , ' automake ' , ' libtool ' , ' gcc-c++ ' , ' openssl-devel ' , ' boost-devel ' ,
' mariadb-devel ' , ' postgresql-devel ' ]
packages . extend ( [ ' rpm-build ' ] )
2019-01-10 17:36:02 +01:00
if ' docs ' in features and not revision == ' 8 ' :
packages . extend ( [ ' libxslt ' , ' elinks ' , ' docbook-style-xsl ' ] )
2018-12-27 15:15:08 +01:00
2019-01-10 17:36:02 +01:00
# if 'mysql' in features:
# packages.extend(['default-mysql-client-core', 'default-libmysqlclient-dev', 'mysql-server'])
# if 'pgsql' in features:
# packages.extend(['postgresql-client', 'libpq-dev', 'postgresql-all'])
2019-01-17 16:41:03 +01:00
if ' radius ' in features :
packages . extend ( [ ' git ' ] )
2019-01-10 17:36:02 +01:00
install_cmd = ' sudo dnf -y install %s '
2019-01-23 17:27:29 +01:00
execute ( install_cmd % ' ' . join ( packages ) , env = env , timeout = 120 , check_times = check_times )
2018-12-27 15:15:08 +01:00
# prepare lib4cplus as epel repos are not available for rhel 8 yet
if revision == ' 8 ' and not os . path . exists ( ' /usr/include/log4cplus/logger.h ' ) :
2019-01-10 17:36:02 +01:00
if not os . path . exists ( ' srpms ' ) :
execute ( ' mkdir srpms ' )
execute ( ' rm -rf srpms/* ' )
execute ( ' rm -rf rpmbuild ' )
execute ( ' wget --no-verbose -O srpms/log4cplus-1.1.3-0.4.rc3.el7.src.rpm https://rpmfind.net/linux/epel/7/SRPMS/Packages/l/log4cplus-1.1.3-0.4.rc3.el7.src.rpm ' ,
check_times = check_times )
2019-01-24 15:32:03 +01:00
execute ( ' rpmbuild --rebuild srpms/log4cplus-1.1.3-0.4.rc3.el7.src.rpm ' , env = env , timeout = 120 , check_times = check_times )
2019-01-10 17:36:02 +01:00
execute ( ' sudo rpm -i rpmbuild/RPMS/x86_64/log4cplus-1.1.3-0.4.rc3.el8.x86_64.rpm ' , env = env , check_times = check_times )
execute ( ' sudo rpm -i rpmbuild/RPMS/x86_64/log4cplus-devel-1.1.3-0.4.rc3.el8.x86_64.rpm ' , env = env , check_times = check_times )
2018-12-27 15:15:08 +01:00
if ' unittest ' in features :
_install_gtest_sources ( )
2019-01-10 17:36:02 +01:00
if ' cql ' in features :
2019-01-11 16:32:55 +01:00
_install_cassandra_rpm ( system )
2019-01-10 17:36:02 +01:00
2018-12-27 15:15:08 +01:00
elif system == ' ubuntu ' :
2019-01-10 17:36:02 +01:00
execute ( ' sudo apt update ' , env = env , check_times = check_times )
2018-12-27 15:15:08 +01:00
packages = [ ' gcc ' , ' g++ ' , ' make ' , ' autoconf ' , ' automake ' , ' libtool ' , ' libssl-dev ' , ' liblog4cplus-dev ' , ' libboost-system-dev ' ]
if ' unittest ' in features :
2019-01-10 17:36:02 +01:00
if revision . startswith ( ' 16. ' ) :
_install_gtest_sources ( )
else :
packages . append ( ' googletest ' )
2018-12-27 15:15:08 +01:00
if ' docs ' in features :
2019-01-10 17:36:02 +01:00
packages . extend ( [ ' dblatex ' , ' xsltproc ' , ' elinks ' , ' docbook-xsl ' ] )
2018-12-27 15:15:08 +01:00
if ' native-pkg ' in features :
packages . extend ( [ ' build-essential ' , ' fakeroot ' , ' devscripts ' ] )
packages . extend ( [ ' bison ' , ' debhelper ' , ' default-libmysqlclient-dev ' , ' libmysqlclient-dev ' , ' docbook ' , ' docbook-xsl ' , ' flex ' , ' libboost-dev ' ,
' libpq-dev ' , ' postgresql-server-dev-all ' , ' python3-dev ' ] )
2019-01-10 17:36:02 +01:00
if ' mysql ' in features :
packages . extend ( [ ' default-mysql-client-core ' , ' default-libmysqlclient-dev ' , ' mysql-server ' ] )
if ' pgsql ' in features :
packages . extend ( [ ' postgresql-client ' , ' libpq-dev ' , ' postgresql-all ' ] )
2019-01-17 16:41:03 +01:00
if ' radius ' in features :
packages . extend ( [ ' git ' ] )
2019-01-10 17:36:02 +01:00
done = False
while not done :
try :
execute ( ' sudo apt install --no-install-recommends -y %s ' % ' ' . join ( packages ) , env = env , timeout = 240 , check_times = check_times )
done = True
except :
log . exception ( ' ble ' )
time . sleep ( 20 )
if ' cql ' in features :
_install_cassandra_deb ( )
2018-12-27 15:15:08 +01:00
elif system == ' debian ' :
2019-01-10 17:36:02 +01:00
execute ( ' sudo apt update ' , env = env , check_times = check_times )
2018-12-27 15:15:08 +01:00
packages = [ ' gcc ' , ' g++ ' , ' make ' , ' autoconf ' , ' automake ' , ' libtool ' , ' libssl-dev ' , ' liblog4cplus-dev ' , ' libboost-system-dev ' ]
if ' docs ' in features :
2019-01-10 17:36:02 +01:00
packages . extend ( [ ' dblatex ' , ' xsltproc ' , ' elinks ' , ' docbook-xsl ' ] )
2018-12-27 15:15:08 +01:00
if ' unittest ' in features :
if revision == ' 8 ' :
2019-01-10 17:36:02 +01:00
_install_gtest_sources ( )
#packages.append('libgtest-dev') # it does not work
2018-12-27 15:15:08 +01:00
else :
packages . append ( ' googletest ' )
2019-01-10 17:36:02 +01:00
if ' mysql ' in features :
packages . extend ( [ ' default-mysql-client-core ' , ' default-libmysqlclient-dev ' , ' mysql-server ' ] )
2019-01-17 16:41:03 +01:00
if ' radius ' in features :
packages . extend ( [ ' git ' ] )
2019-01-10 17:36:02 +01:00
execute ( ' sudo apt install --no-install-recommends -y %s ' % ' ' . join ( packages ) , env = env , timeout = 240 , check_times = check_times )
if ' cql ' in features :
_install_cassandra_deb ( )
2018-12-27 15:15:08 +01:00
elif system == ' freebsd ' :
packages = [ ' autoconf ' , ' automake ' , ' libtool ' , ' openssl ' , ' log4cplus ' , ' boost-libs ' ]
2019-01-10 17:36:02 +01:00
#execute('sudo portsnap --interactive fetch', timeout=240, check_times=check_times)
#execute('sudo portsnap extract /usr/ports/devel/log4cplus', timeout=240, check_times=check_times)
2018-12-27 15:15:08 +01:00
2019-01-10 17:36:02 +01:00
#execute('sudo make -C /usr/ports/devel/log4cplus install clean BATCH=yes', timeout=240, check_times=check_times)
if ' docs ' in features :
packages . extend ( [ ' libxslt ' , ' elinks ' , ' docbook-xsl ' ] )
2018-12-27 15:15:08 +01:00
2019-01-17 16:41:03 +01:00
if ' radius ' in features :
packages . extend ( [ ' git ' ] )
2018-12-27 15:15:08 +01:00
if ' unittest ' in features :
_install_gtest_sources ( )
2019-01-10 17:36:02 +01:00
execute ( ' sudo pkg install -y %s ' % ' ' . join ( packages ) , env = env , timeout = 6 * 60 , check_times = check_times )
2018-12-27 15:15:08 +01:00
else :
raise NotImplementedError
2019-01-10 17:36:02 +01:00
if ' mysql ' in features :
2019-01-24 17:54:20 +01:00
_configure_mysql ( system , revision , features )
2018-12-27 15:15:08 +01:00
2019-01-10 17:36:02 +01:00
if ' pgsql ' in features :
2019-01-24 17:54:20 +01:00
_configure_pgsql ( system , features )
2019-01-10 17:36:02 +01:00
2019-01-17 16:41:03 +01:00
if ' radius ' in features :
_install_freeradius_client ( )
#execute('sudo rm -rf /usr/share/doc')
2019-01-24 15:32:03 +01:00
log . info ( ' Preparing deps completed successfully. ' )
2019-01-10 17:36:02 +01:00
2019-01-24 17:54:20 +01:00
def build_local ( features , tarball_path , check_times , jobs , dry_run ) :
2018-12-27 15:15:08 +01:00
env = os . environ . copy ( )
env [ ' LANGUAGE ' ] = env [ ' LANG ' ] = env [ ' LC_ALL ' ] = ' C '
distro , revision = get_system_revision ( )
2019-01-24 17:54:20 +01:00
execute ( ' df -h ' , dry_run = dry_run )
2018-12-27 15:15:08 +01:00
2019-01-24 17:54:20 +01:00
if tarball_path :
tarball_path = os . path . abspath ( tarball_path )
2018-12-27 15:15:08 +01:00
if ' native-pkg ' in features :
# native pkg build
if distro in [ ' fedora ' , ' centos ' , ' rhel ' ] :
execute ( ' rm -rf rpm-root ' )
os . mkdir ( ' rpm-root ' )
os . mkdir ( ' rpm-root/BUILD ' )
os . mkdir ( ' rpm-root/BUILDROOT ' )
os . mkdir ( ' rpm-root/RPMS ' )
os . mkdir ( ' rpm-root/SOURCES ' )
os . mkdir ( ' rpm-root/SPECS ' )
os . mkdir ( ' rpm-root/SRPMS ' )
execute ( ' rm -rf kea-src ' )
os . mkdir ( ' kea-src ' )
2019-01-10 17:36:02 +01:00
execute ( ' tar -zxf %s ' % tarball_path , cwd = ' kea-src ' , check_times = check_times )
2018-12-27 15:15:08 +01:00
src_path = glob . glob ( ' kea-src/* ' ) [ 0 ]
rpm_dir = os . path . join ( src_path , ' rpm ' )
for f in os . listdir ( rpm_dir ) :
if f == ' kea.spec ' :
continue
2019-01-10 17:36:02 +01:00
execute ( ' cp %s rpm-root/SOURCES ' % os . path . join ( rpm_dir , f ) , check_times = check_times )
execute ( ' cp %s rpm-root/SPECS ' % os . path . join ( rpm_dir , ' kea.spec ' ) , check_times = check_times )
execute ( ' cp %s rpm-root/SOURCES ' % tarball_path , check_times = check_times )
2018-12-27 15:15:08 +01:00
cmd = " rpmbuild -ba rpm-root/SPECS/kea.spec -D ' _topdir /home/vagrant/rpm-root ' "
2019-01-10 17:36:02 +01:00
execute ( cmd , env = env , timeout = 60 * 40 , check_times = check_times )
2018-12-27 15:15:08 +01:00
if ' install ' in features :
2019-01-10 17:36:02 +01:00
execute ( ' sudo rpm -i rpm-root/RPMS/x86_64/*rpm ' , check_times = check_times )
2018-12-27 15:15:08 +01:00
elif distro in [ ' ubuntu ' , ' debian ' ] :
2019-01-10 17:36:02 +01:00
execute ( ' rm -rf kea-src ' , check_times = check_times )
2018-12-27 15:15:08 +01:00
os . mkdir ( ' kea-src ' )
2019-01-10 17:36:02 +01:00
execute ( ' tar -zxf %s ' % tarball_path , cwd = ' kea-src ' , check_times = check_times )
2018-12-27 15:15:08 +01:00
src_path = glob . glob ( ' kea-src/* ' ) [ 0 ]
2019-01-10 17:36:02 +01:00
execute ( ' debuild -i -us -uc -b ' , env = env , cwd = src_path , timeout = 60 * 40 , check_times = check_times )
2018-12-27 15:15:08 +01:00
if ' install ' in features :
2019-01-10 17:36:02 +01:00
execute ( ' sudo dpkg -i kea-src/*deb ' , check_times = check_times )
2018-12-27 15:15:08 +01:00
else :
raise NotImplementedError
else :
# build straight from sources
if tarball_path :
execute ( ' rm -rf kea-src ' )
os . mkdir ( ' kea-src ' )
2019-01-10 17:36:02 +01:00
execute ( ' tar -zxf %s ' % tarball_path , cwd = ' kea-src ' , check_times = check_times )
2018-12-27 15:15:08 +01:00
src_path = glob . glob ( ' kea-src/* ' ) [ 0 ]
else :
src_path = ' . '
2019-01-24 17:54:20 +01:00
execute ( ' autoreconf -f -i ' , cwd = src_path , env = env , dry_run = dry_run )
2018-12-27 15:15:08 +01:00
cmd = ' ./configure '
if ' mysql ' in features :
cmd + = ' --with-mysql '
if ' pgsql ' in features :
cmd + = ' --with-pgsql '
2019-01-10 17:36:02 +01:00
if ' cql ' in features :
cmd + = ' --with-cql=/usr/bin/pkg-config '
2018-12-27 15:15:08 +01:00
if ' unittest ' in features :
2019-01-10 17:36:02 +01:00
if distro in [ ' centos ' , ' fedora ' , ' rhel ' , ' freebsd ' ] :
2018-12-27 15:15:08 +01:00
cmd + = ' --with-gtest-source=/usr/src/googletest-release-1.8.0/googletest/ '
elif distro == ' debian ' and revision == ' 8 ' :
2019-01-10 17:36:02 +01:00
#cmd += ' --with-gtest-source=/usr/src/gtest' # it does not work
cmd + = ' --with-gtest-source=/usr/src/googletest-release-1.8.0/googletest/ '
elif distro == ' debian ' :
2018-12-27 15:15:08 +01:00
cmd + = ' --with-gtest-source=/usr/src/googletest/googletest '
2019-01-10 17:36:02 +01:00
elif distro == ' ubuntu ' :
if revision . startswith ( ' 16. ' ) :
cmd + = ' --with-gtest-source=/usr/src/googletest-release-1.8.0/googletest/ '
else :
cmd + = ' --with-gtest-source=/usr/src/googletest/googletest '
2018-12-27 15:15:08 +01:00
else :
raise NotImplementedError
2019-01-10 17:36:02 +01:00
if ' docs ' in features and not ( distro == ' rhel ' and revision == ' 8 ' ) :
2018-12-27 15:15:08 +01:00
cmd + = ' --enable-generate-docs '
2019-01-17 16:41:03 +01:00
if ' radius ' in features :
cmd + = ' --with-freeradius=/usr/local '
2019-01-23 11:26:33 +01:00
if ' shell ' in features :
cmd + = ' --enable-shell '
2018-12-27 15:15:08 +01:00
2019-01-24 17:54:20 +01:00
execute ( cmd , cwd = src_path , env = env , timeout = 120 , check_times = check_times , dry_run = dry_run )
2018-12-27 15:15:08 +01:00
2019-01-22 11:59:25 +01:00
if jobs == 0 :
cpus = multiprocessing . cpu_count ( ) - 1
if distro == ' centos ' :
cpus = cpus / / 2
if cpus == 0 :
cpus = 1
else :
cpus = jobs
2018-12-27 15:15:08 +01:00
cmd = ' make -j %s ' % cpus
2019-01-24 17:54:20 +01:00
execute ( cmd , cwd = src_path , env = env , timeout = 40 * 60 , check_times = check_times , dry_run = dry_run )
2018-12-27 15:15:08 +01:00
if ' unittest ' in features :
2019-01-10 17:36:02 +01:00
results_dir = os . path . abspath ( os . path . join ( src_path , ' tests_result ' ) )
2019-01-24 17:54:20 +01:00
execute ( ' rm -rf %s ' % results_dir , dry_run = dry_run )
2019-01-10 17:36:02 +01:00
if not os . path . exists ( results_dir ) :
os . mkdir ( results_dir )
env [ ' GTEST_OUTPUT ' ] = ' xml: %s / ' % results_dir
env [ ' KEA_SOCKET_TEST_DIR ' ] = ' /tmp/ '
2019-01-24 17:54:20 +01:00
execute ( ' make check -k ' , cwd = src_path , env = env , timeout = 60 * 60 , raise_error = False , check_times = check_times , dry_run = dry_run )
2019-01-10 17:36:02 +01:00
results = { }
grand_total = 0
grand_not_passed = 0
for fn in os . listdir ( results_dir ) :
if not fn . endswith ( ' .xml ' ) :
continue
fp = os . path . join ( results_dir , fn )
tree = ET . parse ( fp )
root = tree . getroot ( )
total = int ( root . get ( ' tests ' ) )
failures = int ( root . get ( ' failures ' ) )
disabled = int ( root . get ( ' disabled ' ) )
errors = int ( root . get ( ' errors ' ) )
results [ fn ] = dict ( total = total , failures = failures , disabled = disabled , errors = errors )
grand_total + = total
grand_not_passed + = failures + errors
grand_passed = grand_total - grand_not_passed
results [ ' grand_passed ' ] = grand_total - grand_not_passed
results [ ' grand_total ' ] = grand_total
result = ' %s / %s passed ' % ( grand_passed , grand_total )
if grand_not_passed > 0 or grand_total == 0 :
result = red ( result )
else :
result = green ( result )
log . info ( ' Unit test results: %s ' , result )
with open ( ' unit-test-results.json ' , ' w ' ) as f :
f . write ( json . dumps ( results ) )
2018-12-27 15:15:08 +01:00
if ' install ' in features :
2019-01-24 17:54:20 +01:00
execute ( ' sudo make install ' , cwd = src_path , env = env , check_times = check_times , dry_run = dry_run )
execute ( ' sudo ldconfig ' , dry_run = dry_run ) # TODO: this shouldn't be needed
if ' forge ' in features :
if ' mysql ' in features :
execute ( ' kea-admin lease-init mysql -u keauser -p keapass -n keadb ' , dry_run = dry_run )
if ' pgsql ' in features :
execute ( ' kea-admin lease-init pgsql -u keauser -p keapass -n keadb ' , dry_run = dry_run )
2018-12-27 15:15:08 +01:00
2019-01-24 17:54:20 +01:00
execute ( ' df -h ' , dry_run = dry_run )
2018-12-27 15:15:08 +01:00
2019-01-22 11:59:25 +01:00
def build_in_vagrant ( provider , system , sys_revision , features , leave_system , tarball_path , dry_run , quiet , clean_start , check_times , jobs ) :
2018-12-27 15:15:08 +01:00
log . info ( ' ' )
log . info ( " >>> Building %s , %s , %s " % ( provider , system , sys_revision ) )
log . info ( ' ' )
t0 = time . time ( )
2019-01-22 15:48:34 +01:00
ve = None
2019-01-10 17:36:02 +01:00
error = None
total = 0
passed = 0
2018-12-27 15:15:08 +01:00
try :
2019-01-10 17:36:02 +01:00
ve = VagrantEnv ( provider , system , sys_revision , features , ' kea ' , dry_run , quiet , check_times )
if clean_start :
2019-01-25 16:08:12 +01:00
ve . destroy ( )
2018-12-27 15:15:08 +01:00
ve . up ( )
2019-01-25 16:08:12 +01:00
ve . prepare_system ( )
2019-01-22 11:59:25 +01:00
total , passed = ve . run_build_and_test ( tarball_path , jobs )
2019-01-10 17:36:02 +01:00
msg = ' - ' + green ( ' all ok ' )
except KeyboardInterrupt as e :
error = e
msg = ' - keyboard interrupt '
except ExecutionError as e :
error = e
msg = ' - ' + red ( str ( e ) )
except Exception as e :
log . exception ( ' Building erred ' )
error = e
msg = ' - ' + red ( str ( e ) )
finally :
2019-01-22 15:48:34 +01:00
if not leave_system and ve :
2019-01-25 16:08:12 +01:00
ve . destroy ( )
2018-12-27 15:15:08 +01:00
t1 = time . time ( )
dt = int ( t1 - t0 )
log . info ( ' ' )
2019-01-10 17:36:02 +01:00
log . info ( " >>> Building %s , %s , %s completed in %s : %s %s " , provider , system , sys_revision , dt / / 60 , dt % 60 , msg )
2018-12-27 15:15:08 +01:00
log . info ( ' ' )
2019-01-10 17:36:02 +01:00
return dt , error , total , passed
2018-12-27 15:15:08 +01:00
2019-01-10 17:36:02 +01:00
def package_box ( provider , system , sys_revision , features , dry_run , check_times ) :
ve = VagrantEnv ( provider , system , sys_revision , features , ' bare ' , dry_run , check_times = check_times )
2019-01-25 16:08:12 +01:00
ve . destroy ( )
2018-12-27 15:15:08 +01:00
ve . up ( )
2019-01-25 16:08:12 +01:00
ve . prepare_system ( )
2019-01-10 17:36:02 +01:00
# TODO cleanup
2018-12-27 15:15:08 +01:00
ve . package ( )
2019-01-25 16:08:12 +01:00
def prepare_system_in_vagrant ( provider , system , sys_revision , features , dry_run , check_times , clean_start ) :
2019-01-10 17:36:02 +01:00
ve = VagrantEnv ( provider , system , sys_revision , features , ' kea ' , dry_run , check_times = check_times )
if clean_start :
2019-01-25 16:08:12 +01:00
ve . destroy ( )
2018-12-27 15:15:08 +01:00
ve . up ( )
2019-01-25 16:08:12 +01:00
ve . prepare_system ( )
2018-12-27 15:15:08 +01:00
2019-01-25 16:08:12 +01:00
def ssh ( provider , system , sys_revision ) :
ve = VagrantEnv ( provider , system , sys_revision , [ ] , ' kea ' , False )
2018-12-27 15:15:08 +01:00
ve . up ( )
ve . ssh ( )
2019-01-10 17:36:02 +01:00
def ensure_hammer_deps ( ) :
distro , _ = get_system_revision ( )
exitcode = execute ( ' vagrant version ' , raise_error = False )
if exitcode != 0 :
if distro in [ ' fedora ' , ' centos ' , ' rhel ' ] :
execute ( ' wget --no-verbose -O /tmp/vagrant_2.2.2_x86_64.rpm https://releases.hashicorp.com/vagrant/2.2.2/vagrant_2.2.2_x86_64.rpm ' )
execute ( ' sudo rpm -i /tmp/vagrant_2.2.2_x86_64.rpm ' )
os . unlink ( ' /tmp/vagrant_2.2.2_x86_64.rpm ' )
elif distro in [ ' debian ' , ' ubuntu ' ] :
execute ( ' wget --no-verbose -O /tmp/vagrant_2.2.2_x86_64.deb https://releases.hashicorp.com/vagrant/2.2.2/vagrant_2.2.2_x86_64.deb ' )
execute ( ' sudo dpkg -i /tmp/vagrant_2.2.2_x86_64.deb ' )
os . unlink ( ' /tmp/vagrant_2.2.2_x86_64.deb ' )
else :
# TODO: check for packages here: https://www.vagrantup.com/downloads.html
raise NotImplementedError
exitcode = execute ( ' vagrant plugin list | grep vagrant-lxc ' , raise_error = False )
if exitcode != 0 :
execute ( ' vagrant plugin install vagrant-lxc ' )
2019-01-28 12:16:33 +01:00
class CollectCommaSeparatedArgsAction ( argparse . Action ) :
def __call__ ( self , parser , namespace , values , option_string = None ) :
print ( ' %r %r %r ' % ( namespace , values , option_string ) )
values2 = [ ]
for v1 in values :
for v2 in v1 . split ( ) :
values2 . extend ( v2 . split ( ' , ' ) )
for v in values2 :
if v not in ALL_FEATURES :
raise argparse . ArgumentError ( self , " feature ' %s ' is not supported. List of supported features: %s . " % ( v , " , " . join ( ALL_FEATURES ) ) )
setattr ( namespace , self . dest , values2 )
2018-12-27 15:15:08 +01:00
DEFAULT_FEATURES = [ ' install ' , ' unittest ' , ' docs ' ]
2019-01-24 17:54:20 +01:00
ALL_FEATURES = [ ' install ' , ' unittest ' , ' docs ' , ' mysql ' , ' pgsql ' , ' cql ' , ' native-pkg ' , ' radius ' , ' shell ' , ' forge ' ]
2018-12-27 15:15:08 +01:00
def parse_args ( ) :
2019-01-28 12:16:33 +01:00
fl = functools . partial ( lambda w , t : textwrap . fill ( t , w ) , 80 ) # used lambda to change args order and able to substitute width
description = [
" Hammer - Kea develepment environment management tool. \n " ,
fl ( " At first it is required to install Hammer dependencies which is Vagrant and either "
" VirtualBox or LXC. To make life easier Hammer can install Vagrant and required "
" Vagrant plugins using the command: " ) ,
" \n ./hammer.py ensure-hammer-deps \n " ,
" Still VirtualBox and LXC need to be installed manually. " ,
fl ( " Basic functionality provided by Hammer is preparing building environment and "
" performing actual build and running unit tests locally, in current system. "
" This can be achieved by running the command: " ) ,
" \n ./hammer.py build -p local \n " ,
fl ( " The scope of the process can be defined using --with (-w) and --without (-x) options. "
" By default the build command will build Kea with documentation, install it locally "
" and run unit tests. " ) ,
" To exclude installation and generating docs do: " ,
" \n ./hammer.py build -p local -x install docs \n " ,
fl ( " The whole list of available features is: %s . " % " , " . join ( ALL_FEATURES ) ) ,
fl ( " Hammer can be told to set up a new virtual machine with specified operating system "
" and not running the build: " ) ,
" \n ./hammer.py prepare-system -p virtualbox -s freebsd -r 12.0 \n " ,
fl ( " This way we can prepare a system for our own use. To get to such system using SSH invoke: " ) ,
" \n ./hammer.py ssh -p virtualbox -s freebsd -r 12.0 \n " ,
" To list all created system on a host invoke: " ,
" \n ./hammer.py created-systems \n " ,
" And then to destroy a given system run: " ,
" \n ./hammer.py destroy -d /path/to/dir/with/Vagrantfile \n " ,
]
description = " \n " . join ( description )
main_parser = argparse . ArgumentParser ( description = description ,
formatter_class = argparse . RawDescriptionHelpFormatter )
2019-01-25 16:08:12 +01:00
main_parser . add_argument ( ' -v ' , ' --verbose ' , action = ' store_true ' , help = ' Enable verbose mode. ' )
main_parser . add_argument ( ' -q ' , ' --quiet ' , action = ' store_true ' , help = ' Enable quiet mode. ' )
subparsers = main_parser . add_subparsers ( dest = ' command ' ,
title = " Hammer commands " ,
2019-01-28 12:16:33 +01:00
description = fl ( " The following commands are provided by Hammer. "
" To get more information about particular command invoke: ./hammer.py <command> -h. " ) )
2019-01-25 16:08:12 +01:00
parent_parser1 = argparse . ArgumentParser ( add_help = False )
parent_parser1 . add_argument ( ' -p ' , ' --provider ' , default = ' virtualbox ' , choices = [ ' lxc ' , ' virtualbox ' , ' local ' , ' all ' ] ,
help = " Backend build executor. If ' all ' then build is executed several times on all providers. "
" If ' local ' then build is executed on current system. Default is ' virtualbox ' . " )
parent_parser1 . add_argument ( ' -s ' , ' --system ' , default = ' all ' , choices = list ( SYSTEMS . keys ( ) ) + [ ' all ' ] ,
help = " Build is executed on selected system. If ' all ' then build is executed several times on all systems. "
" If provider is ' local ' then this option is ignored. Default is ' all ' . " )
parent_parser1 . add_argument ( ' -r ' , ' --revision ' , default = ' all ' ,
help = " Revision of selected system. If ' all ' then build is executed several times "
" on all revisions of selected system. To list supported systems and their revisions invoke ' supported-systems ' . "
" Default is ' all ' . " )
parent_parser2 = argparse . ArgumentParser ( add_help = False )
2019-01-28 12:16:33 +01:00
parent_parser2 . add_argument ( ' -w ' , ' --with ' , metavar = ' FEATURE ' , nargs = ' + ' , default = set ( ) , action = CollectCommaSeparatedArgsAction ,
help = " Enable features. Separate them by space or comma. List of available features: %s . Default is ' %s ' . " % ( " , " . join ( ALL_FEATURES ) ,
' ' . join ( DEFAULT_FEATURES ) ) )
parent_parser2 . add_argument ( ' -x ' , ' --without ' , metavar = ' FEATURE ' , nargs = ' + ' , default = set ( ) , action = CollectCommaSeparatedArgsAction ,
help = " Disable features. Separate them by space or comma. List of available features: %s . Default is ' ' . " % " , " . join ( ALL_FEATURES ) )
2019-01-25 16:08:12 +01:00
parent_parser2 . add_argument ( ' -l ' , ' --leave-system ' , action = ' store_true ' ,
help = ' At the end of the command do not destroy vagrant system. Default behavior is destroing the system. ' )
parent_parser2 . add_argument ( ' -c ' , ' --clean-start ' , action = ' store_true ' , help = ' If there is pre-existing system then it is destroyed first. ' )
parent_parser2 . add_argument ( ' -i ' , ' --check-times ' , action = ' store_true ' , help = ' Do not allow executing commands infinitelly. ' )
parent_parser2 . add_argument ( ' -n ' , ' --dry-run ' , action = ' store_true ' , help = ' Print only what would be done. ' )
parser = subparsers . add_parser ( ' ensure-hammer-deps ' , help = " Install Hammer dependencies on current, host system. " )
parser = subparsers . add_parser ( ' supported-systems ' , help = " List system supported by Hammer for doing Kea development. " )
parser = subparsers . add_parser ( ' build ' , help = " Prepare system and run Kea build in indicated system. " ,
parents = [ parent_parser1 , parent_parser2 ] )
parser . add_argument ( ' -j ' , ' --jobs ' , default = 0 , help = ' Number of processes used in compilation. Override make -j default value. ' )
2019-01-28 12:16:33 +01:00
parser . add_argument ( ' -t ' , ' --from-tarball ' , metavar = ' TARBALL_PATH ' ,
2018-12-27 15:15:08 +01:00
help = ' Instead of building sources in current folder use provided tarball package (e.g. tar.gz). ' )
2019-01-25 16:08:12 +01:00
parser = subparsers . add_parser ( ' prepare-system ' ,
help = " Prepare system for doing Kea development i.e. install all required dependencies "
" and pre-configure the system. build command always first calls prepare-system internally. " ,
parents = [ parent_parser1 , parent_parser2 ] )
parser = subparsers . add_parser ( ' ssh ' , help = " SSH to indicated system. " ,
formatter_class = argparse . RawDescriptionHelpFormatter ,
description = " Allows getting into the system using SSH. If the system is not present then it will be created first "
" but not prepared. The command can be run in 2 way: "
" \n 1) ./hammer.py ssh -p <provider> -s <system> -r <revision> \n 2) ./hammer.py ssh -d <path-to-vagrant-dir> " ,
parents = [ parent_parser1 ] )
parser . add_argument ( ' -d ' , ' --directory ' , help = ' Path to directory with Vagrantfile. ' )
parser = subparsers . add_parser ( ' created-systems ' , help = " List ALL systems created by Hammer. " )
parser = subparsers . add_parser ( ' destroy ' , help = " Destroy indicated system. " ,
description = " Destroys system indicated by a path to directory with Vagrantfile. "
" To get the list of created systems run: ./hammer.py created-systems. " )
parser . add_argument ( ' -d ' , ' --directory ' , help = ' Path to directory with Vagrantfile. ' )
parser = subparsers . add_parser ( ' package-box ' , help = " Package currently running system into Vagrant Box. Prepared box can be later deployed to Vagrant Cloud. " ,
parents = [ parent_parser1 , parent_parser2 ] )
args = main_parser . parse_args ( )
2018-12-27 15:15:08 +01:00
return args
2019-01-25 16:08:12 +01:00
def list_supported_systems ( ) :
2018-12-27 15:15:08 +01:00
for system , revisions in SYSTEMS . items ( ) :
print ( ' %s : ' % system )
for r in revisions :
providers = [ ]
for p in [ ' lxc ' , ' virtualbox ' ] :
k = ' %s - %s - %s ' % ( system , r , p )
if k in IMAGE_TEMPLATES :
providers . append ( p )
providers = ' , ' . join ( providers )
print ( ' - %s : %s ' % ( r , providers ) )
2019-01-25 16:08:12 +01:00
def list_created_systems ( ) :
exitcode , output = execute ( ' vagrant global-status ' , quiet = True , capture = True )
systems = [ ]
for line in output . splitlines ( ) :
if ' hammer ' not in line :
continue
elems = line . split ( )
state = elems [ 3 ]
path = elems [ 4 ]
systems . append ( [ path , state ] )
print ( ' ' )
print ( ' %-10s %s ' % ( ' State ' , ' Path ' ) )
print ( ' - ' * 80 )
for path , state , in sorted ( systems ) :
print ( ' %-10s %s ' % ( state , path ) )
print ( ' - ' * 80 )
print ( ' To destroy a system run: ./hammer.py destroy -d <path> ' )
print ( ' ' )
def destroy_system ( path ) :
execute ( ' vagrant destroy ' , cwd = path , interactive = True )
2018-12-27 15:15:08 +01:00
def _what_features ( args ) :
features = set ( vars ( args ) [ ' with ' ] )
features = features . union ( DEFAULT_FEATURES )
nofeatures = set ( args . without )
features = features . difference ( nofeatures )
return features
2019-01-10 17:36:02 +01:00
def _print_summary ( results , features ) :
2018-12-27 15:15:08 +01:00
print ( " " )
2019-01-10 17:36:02 +01:00
print ( " +===== Hammer Summary ====================================================+ " )
print ( " | provider | system | revision | duration | status | unit tests | " )
print ( " +------------+------------+----------+-----------+---------+--------------+ " )
2018-12-27 15:15:08 +01:00
total_dt = 0
for key , result in results . items ( ) :
provider , system , revision = key
2019-01-10 17:36:02 +01:00
dt , error , ut_total , ut_passed = result
2018-12-27 15:15:08 +01:00
total_dt + = dt
2019-01-10 17:36:02 +01:00
if error is None :
status = ' %s ' % green ( ' ok ' )
elif error == ' not run ' :
status = blue ( ' not run ' )
else :
status = ' %s ' % red ( ' error ' )
if ' unittest ' in features :
ut_results = ' %s / %s ' % ( ut_passed , ut_total )
padding = ' ' * ( 12 - len ( ut_results ) )
if ut_passed < ut_total or ut_total == 0 :
ut_results = padding + red ( ut_results )
else :
ut_results = padding + green ( ut_results )
else :
ut_results = ' not planned '
print ( ' | %10s | %10s | %8s | %6d : %02d | %s | %s | ' % ( provider , system , revision , dt / / 60 , dt % 60 , status , ut_results ) )
print ( " +------------+------------+----------+-----------+---------+--------------+ " )
print ( " | Total: %6d : %02d | | " % ( total_dt / / 60 , total_dt % 60 ) )
print ( " +=========================================================================+ " )
2018-12-27 15:15:08 +01:00
def main ( ) :
args = parse_args ( )
level = logging . INFO
if args . verbose :
level = logging . DEBUG
format = ' [HAMMER] %(asctime)-15s %(message)s '
logging . basicConfig ( format = format , level = level )
2019-01-25 16:08:12 +01:00
if args . command == ' supported-systems ' :
list_supported_systems ( )
2018-12-27 15:15:08 +01:00
2019-01-25 16:08:12 +01:00
elif args . command == ' created-systems ' :
list_created_systems ( )
2018-12-27 15:15:08 +01:00
elif args . command == " package-box " :
2019-01-25 16:08:12 +01:00
features = _what_features ( args )
2018-12-27 15:15:08 +01:00
log . info ( ' Enabled features: %s ' , ' ' . join ( features ) )
2019-01-10 17:36:02 +01:00
package_box ( args . provider , args . system , args . revision , features , args . dry_run , args . check_times )
2018-12-27 15:15:08 +01:00
elif args . command == " prepare-system " :
2019-01-28 12:16:33 +01:00
if args . provider != ' local ' and ( args . system == ' all ' or args . revision == ' all ' ) :
2019-01-25 16:08:12 +01:00
print ( ' Please provide required system and its version. ' )
print ( ' Example: ./hammer.py prepare-system -s fedora -r 28. ' )
print ( ' To get list of supported systems run: ./hammer.py supported-systems. ' )
sys . exit ( 1 )
features = _what_features ( args )
2018-12-27 15:15:08 +01:00
log . info ( ' Enabled features: %s ' , ' ' . join ( features ) )
2019-01-25 16:08:12 +01:00
if args . provider == ' local ' :
prepare_system_local ( features , args . check_times )
return
prepare_system_in_vagrant ( args . provider , args . system , args . revision , features , args . dry_run , args . check_times , args . clean_start )
2018-12-27 15:15:08 +01:00
elif args . command == " build " :
2019-01-25 16:08:12 +01:00
features = _what_features ( args )
2018-12-27 15:15:08 +01:00
log . info ( ' Enabled features: %s ' , ' ' . join ( features ) )
if args . provider == ' local ' :
2019-01-24 17:54:20 +01:00
build_local ( features , args . from_tarball , args . check_times , int ( args . jobs ) , args . dry_run )
2018-12-27 15:15:08 +01:00
return
if args . provider == ' all ' :
providers = [ ' lxc ' , ' virtualbox ' ]
else :
providers = [ args . provider ]
if args . system == ' all ' :
systems = SYSTEMS . keys ( )
else :
systems = [ args . system ]
2019-01-10 17:36:02 +01:00
plan = [ ]
2018-12-27 15:15:08 +01:00
results = { }
2019-01-10 17:36:02 +01:00
log . info ( ' Build plan: ' )
2018-12-27 15:15:08 +01:00
for provider in providers :
for system in systems :
if args . revision == ' all ' :
revisions = SYSTEMS [ system ]
else :
revisions = [ args . revision ]
for revision in revisions :
2019-01-10 17:36:02 +01:00
if args . revision == ' all ' :
key = ' %s - %s - %s ' % ( system , revision , provider )
if key not in IMAGE_TEMPLATES :
continue
plan . append ( ( provider , system , revision ) )
log . info ( ' - %s , %s , %s ' , provider , system , revision )
results [ ( provider , system , revision ) ] = ( 0 , ' not run ' )
fail = False
for provider , system , revision in plan :
duration , error , total , passed = build_in_vagrant ( provider , system , revision , features , args . leave_system , args . from_tarball ,
2019-01-22 11:59:25 +01:00
args . dry_run , args . quiet , args . clean_start , args . check_times , int ( args . jobs ) )
2019-01-10 17:36:02 +01:00
results [ ( provider , system , revision ) ] = ( duration , error , total , passed )
if error :
fail = True
if isinstance ( error , KeyboardInterrupt ) :
break
2018-12-27 15:15:08 +01:00
2019-01-10 17:36:02 +01:00
_print_summary ( results , features )
2018-12-27 15:15:08 +01:00
if fail :
sys . exit ( 1 )
elif args . command == " ssh " :
2019-01-25 16:08:12 +01:00
ssh ( args . provider , args . system , args . revision )
2019-01-10 17:36:02 +01:00
elif args . command == " ensure-hammer-deps " :
ensure_hammer_deps ( )
2018-12-27 15:15:08 +01:00
2019-01-25 16:08:12 +01:00
elif args . command == " destroy " :
destroy_system ( args . directory )
2018-12-27 15:15:08 +01:00
if __name__ == ' __main__ ' :
# results = {
# ('virtualbox', 'centos', '7'): (920, False),
# ('lxc', 'fedora', '29'): (120, False),
# }
# _print_summary(results)
main ( )