fastnetmon-ng/src/fastnetmon_install.pl
2017-12-03 21:22:11 +00:00

1601 lines
52 KiB
Perl
Executable File

#!/usr/bin/perl
use strict;
use warnings;
use Getopt::Long;
use File::Basename;
use Term::ANSIColor;
my $pf_ring_version = '6.0.3';
my $pf_ring_url = "https://github.com/ntop/PF_RING/archive/v$pf_ring_version.tar.gz";
my $pf_ring_sha = '9fb8080defd1a079ad5f0097e8a8adb5bc264d00';
my $fastnetmon_git_path = 'https://github.com/pavel-odintsov/fastnetmon.git';
my $temp_folder_for_building_project = `mktemp -d /tmp/fastnetmon.build.dir.XXXXXXXXXX`;
chomp $temp_folder_for_building_project;
unless ($temp_folder_for_building_project && -e $temp_folder_for_building_project) {
die "Can't create temp folder in /tmp for building project: $temp_folder_for_building_project\n";
}
my $start_time = time();
my $fastnetmon_code_dir = "$temp_folder_for_building_project/fastnetmon/src";
my $install_log_path = '/tmp/fastnetmon_install.log';
# Official mirror: https://github.com/ntop/nDPI.git
# But we have some patches for NTP and DNS protocols here
my $ndpi_repository = 'https://github.com/pavel-odintsov/nDPI.git';
my $stable_branch_name = 'v1.1.3';
my $we_use_code_from_master = '';
# By default use mirror
my $use_mirror = 1;
my $mirror_url = 'https://github.com/pavel-odintsov/fastnetmon_dependencies/raw/master/files';
my $os_type = '';
my $distro_type = '';
my $distro_version = '';
my $distro_architecture = '';
my $user_email = '';
# Used for VyOS and different appliances based on rpm/deb
my $appliance_name = '';
# So, you could disable this option but without this feature we could not improve FastNetMon for your distribution
my $do_not_track_me = '';
my $cpus_number = 1;
# We could pass options to make with this variable
my $make_options = '';
# We could pass options to configure with this variable
my $configure_options = '';
welcome_message();
# We will build gcc, stdc++ and boost for this distribution from sources
my $build_binary_environment = '';
# With this option we could build full binary package
my $create_binary_bundle = '';
my $use_modern_pf_ring = '';
# Get options from command line
GetOptions(
'use-git-master' => \$we_use_code_from_master,
'do-not-track-me' => \$do_not_track_me,
'build-binary-environment' => \$build_binary_environment,
'create-binary-bundle' => \$create_binary_bundle,
'use-modern-pf-ring' => \$use_modern_pf_ring,
);
# Bump PF_RING version
if ($use_modern_pf_ring) {
$pf_ring_version = '6.6.0';
$pf_ring_url = "https://github.com/ntop/PF_RING/archive/$pf_ring_version.tar.gz";
$pf_ring_sha = '79ff86e48df857e4e884646accfc97bdcdc54b04';
}
my $we_have_ndpi_support = '1';
my $we_have_luajit_support = '1';
my $we_have_hiredis_support = '1';
my $we_have_log4cpp_support = '1';
my $we_have_pfring_support = '';
my $we_have_mongo_support = '1';
my $we_have_protobuf_support = '';
my $we_have_grpc_support = '';
my $we_have_golang_support = '';
my $we_have_gobgp_support = '';
my $enable_gobgp_backend = '';
if ($enable_gobgp_backend) {
$we_have_protobuf_support = 1;
$we_have_grpc_support = 1;
$we_have_golang_support = 1;
$we_have_gobgp_support = 1;
}
main();
sub welcome_message {
# Clear screen
print "\033[2J";
# Jump to 0.0 position
print "\033[0;0H";
print color('bold green');
print "Hi there!\n\n";
print color('reset');
print "We need about ten minutes of your time for installing FastNetMon toolkit\n\n";
print "Also, we have ";
print color('bold cyan');
print "FastNetMon Advanced";
print color('reset');
print " version with big number of improvements: ";
print color('bold cyan');
print "https://fastnetmon.com/fastnetmon-advanced/\n\n";
print color('reset');
print "You could order free one-month trial for Advanced version here ";
print color('bold cyan');
print "https://fastnetmon.com/trial/\n\n";
print color('reset');
print "In case of any issues with install script please use https://github.com/pavel-odintsov/fastnetmon to report them\n\n";
}
sub get_logical_cpus_number {
if ($os_type eq 'linux') {
my @cpuinfo = `cat /proc/cpuinfo`;
chomp @cpuinfo;
my $cpus_number = scalar grep {/processor/} @cpuinfo;
return $cpus_number;
} elsif ($os_type eq 'macosx' or $os_type eq 'freebsd') {
my $cpus_number = `sysctl -n hw.ncpu`;
chomp $cpus_number;
}
}
sub install_additional_repositories {
if ($distro_type eq 'centos') {
if ($distro_version == 6) {
print "Install EPEL repository for your system\n";
yum('https://dl.fedoraproject.org/pub/epel/epel-release-latest-6.noarch.rpm');
}
if ($distro_version == 7) {
print "Install EPEL repository for your system\n";
yum('https://dl.fedoraproject.org/pub/epel/epel-release-latest-7.noarch.rpm');
}
}
}
sub get_user_email {
# http://docs.travis-ci.com/user/environment-variables/#Default-Environment-Variables
if (defined($ENV{'TRAVIS'}) && $ENV{'TRAVIS'}) {
return;
}
my $user_entered_valid_email = 0;
do {
print "\n";
print "Please provide your business email address to receive important information about security updates\n";
print "In addition, we could send promotional messages to this email (very rare)\n";
print "We will provide an option to disable any email from us\n";
print "We will not share your email with any third party companies.\n\n";
print "If you continue install process you accept our subscription rules automatically\n\n";
print "Email: ";
my $raw_email = <STDIN>;
chomp $raw_email;
if ($raw_email =~ /\@/ && length $raw_email > 3) {
$user_entered_valid_email = 1;
$user_email = $raw_email;
} else {
print "Sorry you have entered invalid email, please try again!\n";
}
} while !$user_entered_valid_email;
print "\nThank you so much!\n\n";
}
### Functions start here
sub main {
detect_distribution();
get_user_email();
$cpus_number = get_logical_cpus_number();
# We could get huge speed benefits with this option
if ($cpus_number > 1) {
print "You have really nice server with $cpus_number CPU's and we will use them all for build process :)\n";
$make_options = "-j $cpus_number";
}
# We have PF_RING only for Linux
if ($os_type eq 'linux') {
$we_have_pfring_support = 1;
}
if ($os_type eq 'macosx') {
# Really strange issue https://github.com/pavel-odintsov/fastnetmon/issues/415
$we_have_hiredis_support = 0;
}
# CentOS base repository is very very poor and we need EPEL for some dependencies
install_additional_repositories();
# Refresh information about packages
init_package_manager();
if ($os_type eq 'freebsd') {
exec_command("pkg install -y wget");
}
send_tracking_information('started');
if ($build_binary_environment) {
install_gcc();
install_boost_builder();
install_boost();
}
if ($we_have_pfring_support) {
install_pf_ring();
}
install_json_c();
if ($we_have_ndpi_support) {
install_ndpi();
}
if ($we_have_luajit_support) {
install_luajit();
install_luajit_libs();
}
if ($we_have_hiredis_support) {
install_hiredis();
}
if ($we_have_mongo_support) {
install_mongo_client();
}
if ($we_have_protobuf_support) {
install_protobuf();
}
if ($we_have_grpc_support) {
install_grpc();
}
if ($we_have_golang_support) {
install_golang();
}
if ($we_have_gobgp_support) {
install_gobgp();
}
if ($we_have_log4cpp_support) {
install_log4cpp();
}
install_fastnetmon();
send_tracking_information('finished');
if ($create_binary_bundle) {
create_binary_bundle();
}
my $install_time = time() - $start_time;
my $pretty_install_time_in_minutes = sprintf("%.2f", $install_time / 60);
print "We have built project in $pretty_install_time_in_minutes minutes\n";
}
sub create_binary_bundle {
chdir $temp_folder_for_building_project;
chdir "fastnetmon";
my $bundle_version = '';
if ($we_use_code_from_master) {
my $git_last_commit_id = `git log --format="%H" -n 1`;
chomp $git_last_commit_id;
$bundle_version = "git-$git_last_commit_id";
} else {
$bundle_version = $stable_branch_name;
}
my $bundle_file_name = "fastnetmon-binary-$bundle_version-$distro_type-$distro_version-$distro_architecture.tar.gz";
my $full_bundle_path = "/tmp/$bundle_file_name";
print "We will create bundle with name $bundle_file_name\n";
exec_command("$temp_folder_for_building_project/fastnetmon/src/scripts/build_libary_bundle.pl $full_bundle_path");
print "You could download bundle here $full_bundle_path\n";
if ($distro_type eq 'ubuntu' or $distro_type eq 'debian') {
print "We could build .deb packages for this OS\n";
exec_command("perl $temp_folder_for_building_project/fastnetmon/src/scripts/build_any_package.pl deb $full_bundle_path");
}
if ($distro_type eq 'centos') {
print "We could build .rpm packages for this OS\n";
exec_command("perl $temp_folder_for_building_project/fastnetmon/src/scripts/build_any_package.pl rpm $full_bundle_path");
}
}
sub send_tracking_information {
my $step = shift;
unless ($do_not_track_me) {
my $stats_url = "http://178.62.227.110/new_fastnetmon_installation";
my $post_data = "distro_type=$distro_type&os_type=$os_type&distro_version=$distro_version&distro_architecture=$distro_architecture&step=$step&we_use_code_from_master=$we_use_code_from_master&user_email=$user_email";
my $user_agent = 'FastNetMon install tracker v1';
`wget --post-data="$post_data" --user-agent="$user_agent" -q '$stats_url'`;
}
}
sub exec_command {
my $command = shift;
open my $fl, ">>", $install_log_path;
print {$fl} "We are calling command: $command\n\n";
my $output = `$command 2>&1 >> $install_log_path`;
print {$fl} "Command finished with code $?\n\n";
if ($? == 0) {
return 1;
} else {
return '';
}
}
sub get_sha1_sum {
my $path = shift;
if ($os_type eq 'freebsd') {
# # We should not use 'use' here because we haven't this package on non FreeBSD systems by default
require Digest::SHA;
# SHA1
my $sha = Digest::SHA->new(1);
$sha->addfile($path);
return $sha->hexdigest;
}
my $hasher_name = '';
if ($os_type eq 'macosx') {
$hasher_name = 'shasum';
} elsif ($os_type eq 'freebsd') {
$hasher_name = 'sha1';
} else {
# Linux
$hasher_name = 'sha1sum';
}
my $output = `$hasher_name $path`;
chomp $output;
my ($sha1) = ($output =~ m/^(\w+)\s+/);
return $sha1;
}
sub download_file {
my ($url, $path, $expected_sha1_checksumm) = @_;
# We use pretty strange format for $path and need to sue special function to extract it
my ($path_filename, $path_dirs, $path_suffix) = fileparse($path);
# $path_filename
if ($use_mirror) {
$url = $mirror_url . "/" . $path_filename;
}
`wget --no-check-certificate --quiet '$url' -O$path`;
if ($? != 0) {
print "We can't download archive $url correctly\n";
return '';
}
if ($expected_sha1_checksumm) {
my $calculated_checksumm = get_sha1_sum($path);
if ($calculated_checksumm eq $expected_sha1_checksumm) {
return 1;
} else {
print "Downloaded archive has incorrect sha1: $calculated_checksumm expected: $expected_sha1_checksumm\n";
return '';
}
} else {
return 1;
}
}
sub install_binary_gcc {
my $binary_repository_path = 'http://213.133.111.200/fastnetmon_gcc_toolchain';
my $package_distro_version = '';
if ($distro_type eq 'debian') {
# Debian 6: 6.0.10
# Debian 7: 7.8
# Debian 8: 8.1
if ($distro_version =~ m/^(6)/) {
$package_distro_version = $1;
} else {
$package_distro_version = int($distro_version);
}
} elsif ($distro_type eq 'ubuntu') {
$package_distro_version = $distro_version;
} elsif ($distro_type eq 'centos') {
$package_distro_version = $distro_version;
}
chdir $temp_folder_for_building_project;
my $distribution_file_name = "gcc-5.2.0-$distro_type-$package_distro_version-$distro_architecture.tar.gz";
my $full_path = "$binary_repository_path/$distribution_file_name";
print "We will try to download prebuilded binary gcc package for your distribution\n";
print "We will download from $full_path\n";
my $gcc_binary_download_result = download_file($full_path, $distribution_file_name);
unless ($gcc_binary_download_result) {
print "Download failed, skip to source compilation\n";
return '';
}
print "Unpack gcc binary package\n";
# Unpack file to opt
exec_command("tar -xf $distribution_file_name -C /opt");
# Remove archive
unlink($distribution_file_name);
return 1;
}
sub install_gcc {
my $result = install_binary_gcc();
# Add new compiler to configure options
# It's mandatory for log4cpp
$configure_options = "CC=/opt/gcc520/bin/gcc CXX=/opt/gcc520/bin/g++";
# More detailes about jam lookup: http://www.boost.org/build/doc/html/bbv2/overview/configuration.html
# We use non standard gcc compiler for Boost builder and Boost and specify it this way
open my $fl, ">", "/root/user-config.jam" or die "Can't open $! file for writing manifest\n";
print {$fl} "using gcc : 5.2 : /opt/gcc520/bin/g++ ;\n";
close $fl;
# When we run it with vzctl exec we ahve broken env and should put config in /etc too
open my $etcfl, ">", "/etc/user-config.jam" or die "Can't open $! file for writing manifest\n";
print {$etcfl} "using gcc : 5.2 : /opt/gcc520/bin/g++ ;\n";
close $etcfl;
# Install gcc from sources
if ($distro_type eq 'debian') {
my @dependency_list = ('libmpfr-dev', 'libmpc-dev');
if ($distro_version <= 7) {
# We have another name for Debian 6 Squeeze
push @dependency_list, 'libgmp3-dev';
} else {
push @dependency_list, 'libgmp-dev';
}
apt_get(@dependency_list);
} elsif ($distro_type eq 'ubuntu') {
my @dependency_list = ('libmpfr-dev', 'libmpc-dev', 'libgmp-dev');
apt_get(@dependency_list);
} elsif ($distro_type eq 'centos') {
if ($distro_version == 6) {
# We haven't libmpc in base repository here and should enable EPEL
yum('https://dl.fedoraproject.org/pub/epel/epel-release-latest-6.noarch.rpm');
}
my @dependency_list = ('gmp-devel', 'mpfr-devel', 'libmpc-devel');
yum(@dependency_list);
}
# Please be careful! This libs required for binary version of gcc! We should install they!
# Do not call source compilation in this case
if ($result) {
return;
}
print "Download gcc archive\n";
chdir $temp_folder_for_building_project;
my $archive_file_name = 'gcc-5.2.0.tar.gz';
my $gcc_download_result = download_file("ftp://ftp.mpi-sb.mpg.de/pub/gnu/mirror/gcc.gnu.org/pub/gcc/releases/gcc-5.2.0/$archive_file_name", $archive_file_name, '713211883406b3839bdba4a22e7111a0cff5d09b');
unless ($gcc_download_result) {
die "Can't download gcc sources\n";
}
print "Unpack archive\n";
exec_command("tar -xf $archive_file_name");
exec_command("mkdir $temp_folder_for_building_project/gcc-5.2.0-objdir");
chdir "$temp_folder_for_building_project/gcc-5.2.0-objdir";
print "Configure build system\n";
exec_command("$temp_folder_for_building_project/gcc-5.2.0/configure --prefix=/opt/gcc520 --enable-languages=c,c++ --disable-multilib");
print "Build gcc\n";
exec_command("make $make_options");
exec_command("make $make_options install");
# We do not add it to ld.so.conf.d path because it could broke system
}
sub install_boost {
chdir '/opt';
my $archive_file_name = 'boost_1_58_0.tar.gz';
print "Install Boost dependencies\n";
# libicu dependencies
if ($distro_type eq 'ubuntu') {
if ($distro_version eq '14.04') {
apt_get('libicu52');
}
if ($distro_version eq '12.04') {
apt_get('libicu48');
}
}
print "Download Boost source code\n";
my $boost_download_result = download_file("http://downloads.sourceforge.net/project/boost/boost/1.58.0/boost_1_58_0.tar.gz?r=http%3A%2F%2Fwww.boost.org%2Fusers%2Fhistory%2Fversion_1_58_0.html&ts=1439207367&use_mirror=cznic", $archive_file_name, 'a27b010b9d5de0c07df9dddc9c336767725b1e6b');
unless ($boost_download_result) {
die "Can't download Boost source code\n";
}
print "Unpack Boost source code\n";
exec_command("tar -xf $archive_file_name");
# Remove archive
unlink "$archive_file_name";
chdir "boost_1_58_0";
print "Build Boost\n";
# We have troubles when run this code with vzctl exec so we should add custom compiler in path
# So without HOME=/root nothing worked correctly due to another "openvz" feature
my $b2_build_result = exec_command("HOME=/root PATH=\$PATH:/opt/gcc520/bin /opt/boost_build1.5.8/bin/b2 -j$cpus_number --build-dir=/tmp/boost_build_temp_directory_1_5_8 toolset=gcc-5.2 link=shared --without-test --without-python --without-wave --without-graph --without-coroutine --without-math --without-log --without-graph_parallel --without-mpi");
# We should not do this check because b2 build return bad return code even in success case... when it can't build few non important targets
unless ($b2_build_result) {
### die "Can't execute b2 build correctly\n";
}
}
sub install_boost_builder {
chdir $temp_folder_for_building_project;
# We need libc headers for compilation of this code
if ($distro_type eq 'centos') {
yum('glibc-devel');
}
# We use another name because it uses same name as boost distribution
my $archive_file_name = 'boost-builder-1.58.0.tar.gz';
print "Download boost builder\n";
my $boost_build_result = download_file("https://github.com/boostorg/build/archive/boost-1.58.0.tar.gz", $archive_file_name,
'e86375ed83ed07a79a33c76e80e8648d969b3218');
unless ($boost_build_result) {
die "Can't download boost builder\n";
}
print "Unpack boost builder\n";
exec_command("tar -xf $archive_file_name");
chdir "build-boost-1.58.0";
print "Build Boost builder\n";
# We haven't system compiler here and we will use custom gcc for compilation here
my $bootstrap_result = exec_command("CC=/opt/gcc520/bin/gcc CXX=/opt/gcc520/bin/g++ ./bootstrap.sh --with-toolset=cc");
unless ($bootstrap_result) {
die "bootstrap of Boost Builder failed, please check logs\n";
}
# We should specify toolset here if we want to do build with custom compiler
# We have troubles when run this code with vzctl exec so we should add custom compiler in path
my $b2_install_result = exec_command("PATH=\$PATH:/opt/gcc520/bin ./b2 install --prefix=/opt/boost_build1.5.8 toolset=gcc");
unless ($b2_install_result) {
die "Can't execute b2 install\n";
}
}
sub install_luajit {
chdir $temp_folder_for_building_project;
my $archive_file_name = "LuaJIT-2.0.4.tar.gz";
print "Download Luajit\n";
my $luajit_download_result = download_file(
"http://luajit.org/download/$archive_file_name",
$archive_file_name,
'6e533675180300e85d12c4bbeea2d0e41ad21172'
);
unless ($luajit_download_result) {
die "Can't download luajit\n";
}
print "Unpack Luajit\n";
exec_command("tar -xf LuaJIT-2.0.4.tar.gz");
chdir "LuaJIT-2.0.4";
if ($os_type eq 'macosx' or $os_type eq 'freebsd') {
# FreeBSD's sed has slightly different syntax
exec_command("sed -i -e 's#export PREFIX= /usr/local#export PREFIX= /opt/luajit_2.0.4#' Makefile");
} else {
# Standard Linux sed
exec_command("sed -i 's#export PREFIX= /usr/local#export PREFIX= /opt/luajit_2.0.4#' Makefile");
}
print "Build and install Luajit\n";
if ($os_type eq 'freebsd') {
exec_command("pkg install -y gcc gmake");
exec_command('gmake CC=gcc48 CXX=g++48 CPP="gcc48 -E" install')
} else {
exec_command("make $make_options install");
}
put_library_path_to_ld_so("/etc/ld.so.conf.d/luajit.conf", "/opt/luajit_2.0.4/lib");
}
sub install_luajit_libs {
install_lua_lpeg();
install_lua_json();
}
sub install_lua_lpeg {
print "Install LUA lpeg module\n";
print "Download archive\n";
chdir $temp_folder_for_building_project;
my $archive_file_name = 'lpeg-0.12.2.tar.gz';
my $lpeg_download_result = download_file("http://www.inf.puc-rio.br/~roberto/lpeg/$archive_file_name",
$archive_file_name, '69eda40623cb479b4a30fb3720302d3a75f45577');
unless ($lpeg_download_result) {
die "Can't download lpeg\n";
}
exec_command("tar -xf lpeg-0.12.2.tar.gz");
chdir "lpeg-0.12.2";
# Set path
print "Install lpeg library\n";
if ($os_type eq 'macosx' or $os_type eq 'freebsd') {
exec_command("sed -i -e 's#LUADIR = ../lua/#LUADIR = /opt/luajit_2.0.4/include/luajit-2.0#' makefile");
} else {
exec_command("sed -i 's#LUADIR = ../lua/#LUADIR = /opt/luajit_2.0.4/include/luajit-2.0#' makefile");
}
exec_command("make $make_options");
exec_command("cp lpeg.so /opt/luajit_2.0.4/lib/lua/5.1");
}
sub install_json_c {
my $archive_name = 'json-c-0.12-20140410.tar.gz';
my $install_path = '/opt/json-c-0.12';
print "Install json library\n";
chdir $temp_folder_for_building_project;
print "Download archive\n";
my $json_c_download_result = download_file("https://github.com/json-c/json-c/archive/$archive_name",
$archive_name,
'b33872f8b2837c7909e9bd8734855669c57a67ce');
unless ($json_c_download_result) {
die "Can't download json-c sources\n";
}
print "Uncompress it\n";
exec_command("tar -xf $archive_name");
chdir "json-c-json-c-0.12-20140410";
# Fix bugs (assigned but not used variable) which prevent code compilation
if ($os_type eq 'macosx' or $os_type eq 'freebsd') {
exec_command("sed -i -e '355 s#^#//#' json_tokener.c");
exec_command("sed -i -e '360 s#^#//#' json_tokener.c");
} else {
exec_command("sed -i '355 s#^#//#' json_tokener.c");
exec_command("sed -i '360 s#^#//#' json_tokener.c");
}
print "Build it\n";
exec_command("./configure --prefix=$install_path");
print "Install it\n";
exec_command("make $make_options install");
put_library_path_to_ld_so("/etc/ld.so.conf.d/json-c.conf", "$install_path/lib");
}
sub install_lua_json {
print "Install LUA json module\n";
chdir $temp_folder_for_building_project;
print "Download archive\n";
my $archive_file_name = '1.3.3.tar.gz';
my $lua_json_download_result = download_file("https://github.com/harningt/luajson/archive/$archive_file_name", $archive_file_name,
'53455f697c3f1d7cc955202062e97bbafbea0779');
unless ($lua_json_download_result) {
die "Can't download lua json\n";
}
exec_command("tar -xf $archive_file_name");
chdir "luajson-1.3.3";
print "Install it\n";
exec_command("PREFIX=/opt/luajit_2.0.4 make $make_options install");
}
sub install_init_scripts {
# Init file for any systemd aware distro
if ( ($distro_type eq 'debian' && $distro_version > 7) or ($distro_type eq 'centos' && $distro_version >= 7) ) {
my $systemd_service_path = "/etc/systemd/system/fastnetmon.service";
exec_command("cp $fastnetmon_code_dir/fastnetmon.service $systemd_service_path");
exec_command("sed -i 's#/usr/sbin/fastnetmon#/opt/fastnetmon/fastnetmon#' $systemd_service_path");
print "We found systemd enabled distro and created service: fastnetmon.service\n";
print "You could run it with command: systemctl start fastnetmon.service\n";
return 1;
}
# Init file for CentOS 6
if ($distro_type eq 'centos' && $distro_version == 6) {
my $system_init_path = '/etc/init.d/fastnetmon';
exec_command("cp $fastnetmon_code_dir/fastnetmon_init_script_centos6 $system_init_path");
exec_command("sed -i 's#/usr/sbin/fastnetmon#/opt/fastnetmon/fastnetmon#' $system_init_path");
print "We created service fastnetmon for you\n";
print "You could run it with command: /etc/init.d/fastnetmon start\n";
return 1;
}
# For Gentoo
if ( $distro_type eq 'gentoo' ) {
my $init_path_in_src = "$fastnetmon_code_dir/fastnetmon_init_script_gentoo";
my $system_init_path = '/etc/init.d/fastnetmon';
# Checker for source code version, will work only for 1.1.3+ versions
if (-e $init_path_in_src) {
exec_command("cp $init_path_in_src $system_init_path");
print "We created service fastnetmon for you\n";
print "You could run it with command: /etc/init.d/fastnetmon start\n";
return 1;
}
}
# For Debian Squeeze and Wheezy
# And any stable Ubuntu version
if ( ($distro_type eq 'debian' && ($distro_version == 6 or $distro_version == 7)) or $distro_type eq 'ubuntu') {
my $init_path_in_src = "$fastnetmon_code_dir/fastnetmon_init_script_debian_6_7";
my $system_init_path = '/etc/init.d/fastnetmon';
# Checker for source code version, will work only for 1.1.3+ versions
if (-e $init_path_in_src) {
exec_command("cp $init_path_in_src $system_init_path");
exec_command("sed -i 's#/usr/sbin/fastnetmon#/opt/fastnetmon/fastnetmon#' $system_init_path");
print "We created service fastnetmon for you\n";
print "You could run it with command: /etc/init.d/fastnetmon start\n";
return 1;
}
}
}
sub install_log4cpp {
my $distro_file_name = 'log4cpp-1.1.1.tar.gz';
my $log4cpp_url = 'https://sourceforge.net/projects/log4cpp/files/log4cpp-1.1.x%20%28new%29/log4cpp-1.1/log4cpp-1.1.1.tar.gz/download';
my $log4cpp_install_path = '/opt/log4cpp1.1.1';
chdir $temp_folder_for_building_project;
print "Download log4cpp sources\n";
my $log4cpp_download_result = download_file($log4cpp_url, $distro_file_name, '23aa5bd7d6f79992c92bad3e1c6d64a34f8fcf68');
unless ($log4cpp_download_result) {
die "Can't download log4cpp\n";
}
print "Unpack log4cpp sources\n";
exec_command("tar -xf $distro_file_name");
chdir "$temp_folder_for_building_project/log4cpp";
print "Build log4cpp\n";
# TODO: we need some more reliable way to specify options here
if ($configure_options) {
exec_command("$configure_options ./configure --prefix=$log4cpp_install_path");
} else {
exec_command("./configure --prefix=$log4cpp_install_path");
}
exec_command("make $make_options install");
print "Add log4cpp to ld.so.conf\n";
put_library_path_to_ld_so("/etc/ld.so.conf.d/log4cpp.conf", "$log4cpp_install_path/lib");
}
sub install_grpc {
# We use this commit because 0.11.1 is broken and do not build on CentOS 6 correctly
my $grpc_git_commit = "7a94236d698477636dd06282f12f706cad527029";
my $grpc_install_path = "/opt/grpc_0_11_1_$grpc_git_commit";
if ($distro_type eq 'debian' or $distro_type eq 'ubuntu') {
apt_get('gcc', 'make', 'autoconf', 'automake', 'git', 'libtool', 'g++', 'python-all-dev', 'python-virtualenv');
}
# TODO: add deps for CentOS
chdir $temp_folder_for_building_project;
print "Clone gRPC repository\n";
exec_command("git clone https://github.com/grpc/grpc.git");
chdir "grpc";
# For back compatibility with old git
exec_command("git checkout $grpc_git_commit");
exec_command("git submodule update --init");
print "Build gRPC\n";
exec_command("make $make_options");
print "Install gRPC\n";
exec_command("make install prefix=$grpc_install_path");
}
sub install_gobgp {
chdir $temp_folder_for_building_project;
my $distro_file_name = 'v1.0.tar.gz';
my $gobgp_download_result = download_file("https://github.com/osrg/gobgp/archive/$distro_file_name",
$distro_file_name, 'daafc31b06d95611ca76f45630e5db140ba5d4c9');
unless ($gobgp_download_result) {
die "Can't download gobgp sources\n";
}
exec_command("tar -xf $distro_file_name");
chdir "gobgp-1.0";
chdir "gobgp/lib";
my $go_binary = '/usr/local/go/bin/go';
print "Build gobgp\n";
exec_command("GOPATH=\"$temp_folder_for_building_project/gofolder\" $go_binary get github.com/osrg/gobgp/gobgpd");
exec_command("GOPATH=\"$temp_folder_for_building_project/gofolder\" $go_binary get github.com/osrg/gobgp/gobgp");
print "Build gobgp library\n";
exec_command("GOPATH=\"$temp_folder_for_building_project/gofolder\" $go_binary build -buildmode=c-shared -o libgobgp.so *.go");
my $libgobgp_install_path = '/opt/libgobgp_1_0_0';
print "Install gobgp library\n";
mkdir "$libgobgp_install_path";
mkdir "$libgobgp_install_path/include";
mkdir "$libgobgp_install_path/lib";
exec_command("cp libgobgp.h $libgobgp_install_path/include");
exec_command("cp libgobgp.so $libgobgp_install_path/lib");
print "Install gobgp daemon files\n";
my $gobgp_install_path = '/opt/gobgp_1_0_0';
mkdir $gobgp_install_path;
exec_command("cp $temp_folder_for_building_project/gofolder/bin/gobgp $gobgp_install_path");
exec_command("cp $temp_folder_for_building_project/gofolder/bin/gobgpd $gobgp_install_path");
}
sub install_golang {
chdir $temp_folder_for_building_project;
my $distro_file_name = '';
my $distro_file_hash = '';
if ($distro_architecture eq 'x86_64') {
$distro_file_name = "go1.5.1.linux-amd64.tar.gz";
$distro_file_hash = '46eecd290d8803887dec718c691cc243f2175fe0';
} elsif ($distro_architecture eq 'i686') {
$distro_file_name = 'go1.5.1.linux-386.tar.gz';
$distro_file_hash = '6ce7328f84a863f341876658538dfdf10aff86ee';
} else {
die "We haven't golang for your platform sorry :(\n";
}
my $golang_download_result = download_file("https://storage.googleapis.com/golang/$distro_file_name",
$distro_file_name, $distro_file_hash);
unless ($golang_download_result) {
die "Can't download golanguage\n";
}
exec_command("tar -C /usr/local -xzf $distro_file_name");
}
sub install_protobuf {
if ($distro_type eq 'debian' or $distro_type eq 'ubuntu') {
apt_get('gcc', 'make', 'autoconf', 'automake', 'git', 'libtool', 'g++', 'curl');
}
# TODO: add deps for CentOS
my $protobuf_install_path = '/opt/protobuf_3.0.0_alpha4';
my $distro_file_name = 'v3.0.0-alpha-4.tar.gz';
chdir $temp_folder_for_building_project;
print "Download protocol buffers\n";
my $protobuf_download_result = download_file("https://github.com/google/protobuf/archive/$distro_file_name",
$distro_file_name, 'd23048ba3218af21ba65fa39bfb6326f5bf9f7a4');
unless ($protobuf_download_result) {
die "Can't download protobuf\n";
}
print "Unpack protocol buffers\n";
exec_command("tar -xf $distro_file_name");
chdir "protobuf-3.0.0-alpha-4";
print "Configure protobuf\n";
exec_command("./autogen.sh");
exec_command("./configure --prefix=$protobuf_install_path");
print "Build protobuf\n";
exec_command("make $make_options install");
}
sub install_mongo_client {
my $distro_file_name = 'mongo-c-driver-1.1.9.tar.gz';
my $mongo_install_path = '/opt/mongo_c_driver_1_1_9';
chdir $temp_folder_for_building_project;
print "Download mongo\n";
my $mongo_download_result = download_file("https://github.com/mongodb/mongo-c-driver/releases/download/1.1.9/$distro_file_name",
$distro_file_name, '32452481be64a297e981846e433b2b492c302b34');
unless ($mongo_download_result) {
die "Can't download mongo\n";
}
exec_command("tar -xf $distro_file_name");
print "Build mongo client\n";
chdir "mongo-c-driver-1.1.9";
exec_command("./configure --prefix=$mongo_install_path");
exec_command("make $make_options install");
}
sub install_hiredis {
my $disto_file_name = 'v0.13.1.tar.gz';
my $hiredis_install_path = '/opt/libhiredis_0_13';
chdir $temp_folder_for_building_project;
print "Download hiredis\n";
my $hiredis_download_result = download_file("https://github.com/redis/hiredis/archive/$disto_file_name",
$disto_file_name, '737c4ed101096c5ec47fcaeba847664352d16204');
unless ($hiredis_download_result) {
die "Can't download hiredis\n";
}
exec_command("tar -xf $disto_file_name");
print "Build hiredis\n";
chdir "hiredis-0.13.1";
exec_command("PREFIX=$hiredis_install_path make $make_options install");
print "Add hiredis to ld.so.conf\n";
put_library_path_to_ld_so("/etc/ld.so.conf.d/hiredis.conf", "$hiredis_install_path/lib");
}
# We use global variable $ndpi_repository here
sub install_ndpi {
if ($distro_type eq 'debian' or $distro_type eq 'ubuntu') {
apt_get('git', 'autoconf', 'libtool', 'automake', 'libpcap-dev');
} elsif ($distro_type eq 'centos') {
# We have json-c-devel for CentOS 6 and 7 and will use it for nDPI build system
yum('git', 'autoconf', 'automake', 'libtool', 'libpcap-devel', 'json-c-devel');
} elsif ($os_type eq 'freebsd') {
exec_command("pkg install -y git autoconf automake libtool");
}
print "Download nDPI\n";
if (-e "$temp_folder_for_building_project/nDPI") {
# Get new code from the repository
chdir "$temp_folder_for_building_project/nDPI";
exec_command("git pull");
} else {
chdir $temp_folder_for_building_project;
exec_command("git clone $ndpi_repository");
chdir "$temp_folder_for_building_project/nDPI";
}
print "Configure nDPI\n";
exec_command("./autogen.sh");
# We have specified direct path to json-c here because it required for example app compilation
exec_command("PKG_CONFIG_PATH=/opt/json-c-0.12/lib/pkgconfig ./configure --prefix=/opt/ndpi");
if ($? != 0) {
print "Configure failed\n";
return;
}
print "Build and install nDPI\n";
exec_command("make $make_options install");
print "Add ndpi to ld.so.conf\n";
put_library_path_to_ld_so("/etc/ld.so.conf.d/ndpi.conf", "/opt/ndpi/lib");
}
sub init_package_manager {
print "Update package manager cache\n";
if ($distro_type eq 'debian' or $distro_type eq 'ubuntu') {
exec_command("apt-get update");
}
if ($os_type eq 'freebsd') {
exec_command("pkg update");
}
}
sub put_library_path_to_ld_so {
my ($ld_so_file_path, $library_path) = @_;
if ($os_type eq 'macosx' or $os_type eq 'freebsd') {
return;
}
open my $ld_so_conf_handle, ">", $ld_so_file_path or die "Can't open file $ld_so_file_path $! for writing\n";
print {$ld_so_conf_handle} $library_path;
close $ld_so_conf_handle;
exec_command("ldconfig");
}
sub read_file {
my $file_name = shift;
my $res = open my $fl, "<", $file_name;
unless ($res) {
return "";
}
my $content = join '', <$fl>;
chomp $content;
return $content;
}
# Detect operating system of this machine
sub detect_distribution {
# We use following global variables here:
# $os_type, $distro_type, $distro_version, $appliance_name
my $uname_s_output = `uname -s`;
chomp $uname_s_output;
# uname -a output examples:
# FreeBSD 10.1-STABLE FreeBSD 10.1-STABLE #0 r278618: Thu Feb 12 13:55:09 UTC 2015 root@:/usr/obj/usr/src/sys/KERNELWITHNETMAP amd64
# Darwin MacBook-Pro-Pavel.local 14.5.0 Darwin Kernel Version 14.5.0: Wed Jul 29 02:26:53 PDT 2015; root:xnu-2782.40.9~1/RELEASE_X86_64 x86_64
# Linux ubuntu 3.16.0-30-generic #40~14.04.1-Ubuntu SMP Thu Jan 15 17:43:14 UTC 2015 x86_64 x86_64 x86_64 GNU/Linux
if ($uname_s_output =~ /FreeBSD/) {
$os_type = 'freebsd';
} elsif ($uname_s_output =~ /Darwin/) {
$os_type = 'macosx';
} elsif ($uname_s_output =~ /Linux/) {
$os_type = 'linux';
} else {
warn "Can't detect platform operating system\n";
}
if ($os_type eq 'linux') {
# x86_64 or i686
$distro_architecture = `uname -m`;
chomp $distro_architecture;
if (-e "/etc/debian_version") {
# Well, on this step it could be Ubuntu or Debian
# We need check issue for more details
my @issue = `cat /etc/issue`;
chomp @issue;
my $issue_first_line = $issue[0];
# Possible /etc/issue contents:
# Debian GNU/Linux 8 \n \l
# Ubuntu 14.04.2 LTS \n \l
# Welcome to VyOS - \n \l
my $is_proxmox = '';
# Really hard to detect https://github.com/proxmox/pve-manager/blob/master/bin/pvebanner
for my $issue_line (@issue) {
if ($issue_line =~ m/Welcome to the Proxmox Virtual Environment/) {
$is_proxmox = 1;
$appliance_name = 'proxmox';
last;
}
}
if ($issue_first_line =~ m/Debian/ or $is_proxmox) {
$distro_type = 'debian';
$distro_version = `cat /etc/debian_version`;
chomp $distro_version;
# Debian 6 example: 6.0.10
# We will try transform it to decimal number
if ($distro_version =~ /^(\d+\.\d+)\.\d+$/) {
$distro_version = $1;
}
} elsif ($issue_first_line =~ m/Ubuntu (\d+(?:\.\d+)?)/) {
$distro_type = 'ubuntu';
$distro_version = $1;
} elsif ($issue_first_line =~ m/VyOS/) {
# Yes, VyOS is a Debian
$distro_type = 'debian';
$appliance_name = 'vyos';
my $vyos_distro_version = `cat /etc/debian_version`;
chomp $vyos_distro_version;
# VyOS have strange version and we should fix it
if ($vyos_distro_version =~ /^(\d+)\.\d+\.\d+$/) {
$distro_version = $1;
}
}
}
if (-e "/etc/redhat-release") {
$distro_type = 'centos';
my $distro_version_raw = `cat /etc/redhat-release`;
chomp $distro_version_raw;
# CentOS 6:
# CentOS release 6.6 (Final)
# CentOS 7:
# CentOS Linux release 7.0.1406 (Core)
# Fedora release 21 (Twenty One)
if ($distro_version_raw =~ /(\d+)/) {
$distro_version = $1;
}
}
if (-e "/etc/gentoo-release") {
$distro_type = 'gentoo';
my $distro_version_raw = `cat /etc/gentoo-release`;
chomp $distro_version_raw;
}
unless ($distro_type) {
die "This distro is unsupported, please do manual install";
}
print "We detected your OS as $distro_type Linux $distro_version\n";
} elsif ($os_type eq 'macosx') {
my $mac_os_versions_raw = `sw_vers -productVersion`;
chomp $mac_os_versions_raw;
if ($mac_os_versions_raw =~ /(\d+\.\d+)/) {
$distro_version = $1;
}
print "We detected your OS as Mac OS X $distro_version\n";
} elsif ($os_type eq 'freebsd') {
my $freebsd_os_version_raw = `uname -r`;
chomp $freebsd_os_version_raw;
if ($freebsd_os_version_raw =~ /^(\d+)\.?/) {
$distro_version = $1;
}
print "We detected your OS as FreeBSD $distro_version\n";
}
}
sub install_pf_ring {
my $pf_ring_archive_path = "$temp_folder_for_building_project/PF_RING-$pf_ring_version.tar.gz";
my $pf_ring_sources_path = "$temp_folder_for_building_project/PF_RING-$pf_ring_version";
my $kernel_version = `uname -r`;
chomp $kernel_version;
print "Install PF_RING dependencies with package manager\n";
if ($distro_type eq 'debian' or $distro_type eq 'ubuntu') {
my @debian_packages_for_pfring = ('build-essential', 'bison', 'flex', 'subversion',
'libnuma-dev', 'wget', 'tar', 'make', 'dpkg-dev', 'dkms', 'debhelper');
# Install kernel headers only when we could compile kernel modules there
my $kernel_headers_package_name = "linux-headers-$kernel_version";
if ($appliance_name eq 'vyos') {
# VyOS uses another name for package for building kernel modules
$kernel_headers_package_name = 'linux-vyatta-kbuild';
} elsif ($appliance_name eq 'proxmox') {
$kernel_headers_package_name = "pve-headers-$kernel_version";
}
push @debian_packages_for_pfring, $kernel_headers_package_name;
apt_get(@debian_packages_for_pfring);
if ($appliance_name eq 'vyos') {
# By default we waven't this symlink and should add it manually
if ($distro_architecture eq 'x86_64') {
exec_command("ln -s /usr/src/linux-image/debian/build/build-amd64-none-amd64-vyos/ /lib/modules/$kernel_version/build");
} else {
# i686
exec_command("ln -s /usr/src/linux-image/debian/build/build-i386-none-586-vyos/ /lib/modules/$kernel_version/build");
}
}
} elsif ($distro_type eq 'centos') {
my @centos_dependency_packages = ('make', 'bison', 'flex', 'gcc', 'gcc-c++', 'dkms', 'numactl-devel', 'subversion');
# This package is not going to install devel headers for current kernel!
my $kernel_package_name = 'kernel-devel';
# Fix deplist for OpenVZ
if ($kernel_version =~ /stab/) {
$kernel_package_name = "vzkernel-devel-$kernel_version";
}
push @centos_dependency_packages, $kernel_package_name;
my $centos_kernel_version = `uname -r`;
chomp $centos_kernel_version;
# But this package will install kernel devel headers for current kernel version!
push @centos_dependency_packages, "$kernel_package_name-$centos_kernel_version";
yum(@centos_dependency_packages);
} elsif ($distro_type eq 'gentoo') {
my @gentoo_packages_for_pfring = ('subversion', 'sys-process/numactl', 'wget', 'tar');
my $gentoo_packages_for_pfring_as_string = join " ", @gentoo_packages_for_pfring;
exec_command("emerge -vu $gentoo_packages_for_pfring_as_string");
if ($? != 0) {
print "Emerge fail with code $?\n";
}
}
# Sometimes we do not want to build kernel module (Docker, KVM and other cases)
my $we_could_install_kernel_modules = 1;
if ($we_could_install_kernel_modules) {
print "Download PF_RING $pf_ring_version sources\n";
my $pfring_download_result = download_file($pf_ring_url, $pf_ring_archive_path, $pf_ring_sha);
unless ($pfring_download_result) {
die "Can't download PF_RING sources\n";
}
my $archive_file_name = $pf_ring_archive_path;
if ($? == 0) {
print "Unpack PF_RING\n";
mkdir $pf_ring_sources_path;
exec_command("tar -xf $pf_ring_archive_path -C $temp_folder_for_building_project");
print "Build PF_RING kernel module\n";
exec_command("make $make_options -C $pf_ring_sources_path/kernel clean");
exec_command("make $make_options -C $pf_ring_sources_path/kernel");
exec_command("make $make_options -C $pf_ring_sources_path/kernel install");
print "Unload PF_RING if it was installed earlier\n";
exec_command("rmmod pf_ring 2>/dev/null");
print "Load PF_RING module into kernel\n";
exec_command("modprobe pf_ring");
my @dmesg = `dmesg`;
chomp @dmesg;
if (scalar grep (/\[PF_RING\] Initialized correctly/, @dmesg) > 0) {
print "PF_RING loaded correctly\n";
} else {
warn "PF_RING load error! Please fix this issue manually\n";
# We need this headers for building userspace libs
exec_command("cp $pf_ring_sources_path/kernel/linux/pf_ring.h /usr/include/linux");
}
} else {
warn "Can't download PF_RING source code. Disable support of PF_RING\n";
}
}
print "Build PF_RING lib\n";
# Because we can't run configure from another folder because it can't find ZC dependency :(
chdir "$pf_ring_sources_path/userland/lib";
exec_command("./configure --prefix=/opt/pf_ring_$pf_ring_version");
exec_command("make $make_options");
exec_command("make $make_options install");
# We need do this for backward compatibility with old code (v1.1.2)
exec_command("ln -s /opt/pf_ring_$pf_ring_version /opt/pf_ring");
print "Create library symlink\n";
print "Add pf_ring to ld.so.conf\n";
put_library_path_to_ld_so("/etc/ld.so.conf.d/pf_ring.conf", "/opt/pf_ring_$pf_ring_version/lib");
}
sub apt_get {
my @packages_list = @_;
# We install one package per apt-get call because installing multiple packages in one time could fail of one package is broken
for my $package (@packages_list) {
exec_command("apt-get install -y --force-yes $package");
if ($? != 0) {
print "Package '$package' install failed with code $?\n"
}
}
}
sub yum {
my @packages_list = @_;
for my $package (@packages_list) {
exec_command("yum install -y $package");
if ($? != 0) {
print "Package '$package' install failed with code $?\n";
}
}
}
sub install_fastnetmon {
print "Install FastNetMon dependency list\n";
if ($distro_type eq 'debian' or $distro_type eq 'ubuntu') {
my @fastnetmon_deps = ("git", "g++", "gcc", "libgpm-dev", "libncurses5-dev",
"liblog4cpp5-dev", "libnuma-dev", "libgeoip-dev","libpcap-dev", "cmake", "pkg-config", "libhiredis-dev",
);
# Do not install Boost when we build it manually
unless ($build_binary_environment) {
# We add this dependencies because package libboost-all-dev is broken on VyOS
if ($appliance_name eq 'vyos') {
push @fastnetmon_deps, ('libboost-regex-dev', 'libboost-system-dev', 'libboost-thread-dev');
} else {
push @fastnetmon_deps, "libboost-all-dev";
}
}
apt_get(@fastnetmon_deps);
} elsif ($distro_type eq 'centos') {
my @fastnetmon_deps = ('git', 'make', 'gcc', 'gcc-c++', 'GeoIP-devel',
'ncurses-devel', 'glibc-static', 'ncurses-static', 'libpcap-devel', 'gpm-static',
'gpm-devel', 'cmake', 'pkgconfig', 'hiredis-devel',
);
# Do not install Boost when we build it manually
unless ($build_binary_environment) {
@fastnetmon_deps = (@fastnetmon_deps, 'boost-devel', 'boost-thread')
}
yum(@fastnetmon_deps);
} elsif ($distro_type eq 'gentoo') {
my @fastnetmon_deps = ("dev-vcs/git", "gcc", "sys-libs/gpm", "sys-libs/ncurses", "dev-libs/log4cpp", "dev-libs/geoip",
"net-libs/libpcap", "dev-util/cmake", "pkg-config", "dev-libs/hiredis", "dev-libs/boost"
);
my $fastnetmon_deps_as_string = join " ", @fastnetmon_deps;
exec_command("emerge -vu $fastnetmon_deps_as_string");
if ($? != 0) {
print "Emerge fail with code $?\n";
}
} elsif ($os_type eq 'freebsd') {
exec_command("pkg install -y cmake git ncurses boost-all log4cpp");
}
print "Clone FastNetMon repo\n";
chdir $temp_folder_for_building_project;
if (-e $fastnetmon_code_dir) {
# Code already downloaded
chdir $fastnetmon_code_dir;
# Switch to master if we on stable branch
if ($we_use_code_from_master) {
exec_command("git checkout master");
printf("\n");
}
exec_command("git pull");
} else {
# Pull new code
if ($we_use_code_from_master) {
exec_command("git clone $fastnetmon_git_path --quiet 2>/dev/null");
} else {
exec_command("git clone $fastnetmon_git_path --quiet 2>/dev/null");
}
if ($? != 0) {
die "Can't clone source code\n";
}
}
if ($we_use_code_from_master) {
} else {
# We use this approach because older git versions do not support git clone -b ... correctly
# warning: Remote branch v1.1.2 not found in upstream origin, using HEAD instead
chdir "fastnetmon";
exec_command("git checkout $stable_branch_name");
}
exec_command("mkdir -p $fastnetmon_code_dir/build");
chdir "$fastnetmon_code_dir/build";
my $cmake_params = "";
unless ($we_have_pfring_support) {
$cmake_params .= " -DDISABLE_PF_RING_SUPPORT=ON";
}
if ($distro_type eq 'centos' && $distro_version == 6 && !$build_binary_environment) {
# Disable cmake script from Boost package because it's broken:
# http://public.kitware.com/Bug/view.php?id=15270
$cmake_params .= " -DBoost_NO_BOOST_CMAKE=BOOL:ON";
}
if ($enable_gobgp_backend) {
$cmake_params .= " -DENABLE_GOBGP_SUPPORT=ON";
}
# We should specify this option if we want to build with custom gcc compiler
if ($build_binary_environment) {
$cmake_params .= " -DENABLE_BUILD_IN_CPP_11_CUSTOM_ENVIRONMENT=ON ";
# We should specify compilir this way
$cmake_params .= " -DCMAKE_C_COMPILER=/opt/gcc520/bin/gcc -DCMAKE_CXX_COMPILER=/opt/gcc520/bin/g++ ";
}
# Bump version in cmake build system
if ($use_modern_pf_ring) {
system("sed -i 's/pf_ring_6.0.3/pf_ring_$pf_ring_version/' ../CMakeLists.txt")
}
if (defined($ENV{'TRAVIS'}) && $ENV{'TRAVIS'}) {
system("cmake .. $cmake_params");
system("make $make_options");
} else {
system("cmake .. $cmake_params");
system("make $make_options");
}
my $fastnetmon_dir = "/opt/fastnetmon";
my $fastnetmon_build_binary_path = "$fastnetmon_code_dir/build/fastnetmon";
unless (-e $fastnetmon_build_binary_path) {
die "Can't build fastnetmon!";
}
mkdir $fastnetmon_dir;
print "Install fastnetmon to dir $fastnetmon_dir\n";
exec_command("cp $fastnetmon_build_binary_path $fastnetmon_dir/fastnetmon");
exec_command("cp $fastnetmon_code_dir/build/fastnetmon_client $fastnetmon_dir/fastnetmon_client");
if (-e "$fastnetmon_code_dir/build/fastnetmon_api_client") {
exec_command("cp $fastnetmon_code_dir/build/fastnetmon_api_client $fastnetmon_dir/fastnetmon_api_client");
}
my $fastnetmon_config_path = "/etc/fastnetmon.conf";
unless (-e $fastnetmon_config_path) {
print "Create stub configuration file\n";
exec_command("cp $fastnetmon_code_dir/fastnetmon.conf $fastnetmon_config_path");
# netmap will detach interface completely and will broke network
# So we do not configure it automatically
if ($os_type ne 'freebsd') {
my @interfaces = get_active_network_interfaces();
my $interfaces_as_list = join ',', @interfaces;
print "Select $interfaces_as_list as active interfaces\n";
print "Tune config\n";
if ($os_type eq 'macosx' or $os_type eq 'freebsd') {
exec_command("sed -i -e 's/interfaces.*/interfaces = $interfaces_as_list/' $fastnetmon_config_path");
} else {
exec_command("sed -i 's/interfaces.*/interfaces = $interfaces_as_list/' $fastnetmon_config_path");
}
}
}
print "If you have any issues, please check /var/log/fastnetmon.log file contents\n";
print "Please add your subnets in /etc/networks_list in CIDR format one subnet per line\n";
my $init_script_result = install_init_scripts();
# Print unified run message
unless ($init_script_result) {
print "You can run fastnetmon with command: $fastnetmon_dir/fastnetmon\n";
}
}
sub get_active_network_interfaces {
my @interfaces = `LANG=C netstat -i|egrep -v 'lo|Iface|Kernel'|awk '{print \$1}'`;
chomp @interfaces;
my @clean_interfaces = ();
for my $iface (@interfaces) {
# skip aliases
if ($iface =~ /:/) {
next;
}
push @clean_interfaces, $iface;
}
return @clean_interfaces;
}