From aca7e2907ed4461fad8a49d4d4461e43ecdc1837 Mon Sep 17 00:00:00 2001 From: Krzysztof Dynowski Date: Wed, 3 Jun 2015 14:45:26 +0200 Subject: [PATCH] Check vasum runtime environment, provide utility to check kernel config [Bug/Feature] check vasum enviroment and kernel config [Cause] N/A [Solution] server option to check runtime, script based on lxc-checkconfig [Verification] Build, install on target, run server and script Change-Id: I28b6982694e7918cad31e59cee35b5872e554246 --- packaging/vasum.spec | 1 + server/CMakeLists.txt | 2 + server/main.cpp | 4 ++ server/scripts/vasum-check-env.sh | 84 +++++++++++++++++++++++++++++++++++++++ server/server.cpp | 75 ++++++++++++++++++++++++++++++++++ server/server.hpp | 5 +++ 6 files changed, 171 insertions(+) create mode 100755 server/scripts/vasum-check-env.sh diff --git a/packaging/vasum.spec b/packaging/vasum.spec index bd7346c..38c7cf6 100644 --- a/packaging/vasum.spec +++ b/packaging/vasum.spec @@ -44,6 +44,7 @@ between them. A process from inside a zone can request a switch of context %endif %defattr(644,root,root,755) %attr(755,root,root) %{_bindir}/vasum-server +%attr(755,root,root) %{_sbindir}/vasum-check-env %dir /etc/vasum %dir /etc/vasum/templates %config /etc/vasum/daemon.conf diff --git a/server/CMakeLists.txt b/server/CMakeLists.txt index 92672c1..d5104db 100644 --- a/server/CMakeLists.txt +++ b/server/CMakeLists.txt @@ -55,3 +55,5 @@ INSTALL(TARGETS ${SERVER_CODENAME} DESTINATION bin) ## Set capabilities on server executable ####################################### INSTALL(CODE "EXECUTE_PROCESS(COMMAND setcap CAP_SYS_ADMIN,CAP_MAC_OVERRIDE,CAP_SYS_TTY_CONFIG+ei \$ENV{DESTDIR}/${CMAKE_INSTALL_PREFIX}/bin/${SERVER_CODENAME})") + +INSTALL(PROGRAMS "scripts/vasum-check-env.sh" DESTINATION sbin RENAME vasum-check-env) diff --git a/server/main.cpp b/server/main.cpp index fb3eed4..55a795e 100644 --- a/server/main.cpp +++ b/server/main.cpp @@ -69,6 +69,7 @@ int main(int argc, char* argv[]) ("root,r", "Don't drop root privileges at startup") ("version,v", "show application version") ("log-level,l", po::value()->default_value("DEBUG"), "set log level") + ("check,c", "check runtime environment and exit") ; po::variables_map vm; @@ -100,6 +101,9 @@ int main(int argc, char* argv[]) } else if (vm.count("version")) { std::cout << PROGRAM_NAME_AND_VERSION << std::endl; return 0; + } else if (vm.count("check")) { + std::cout << "Checking runtime environment..." << std::endl; + return Server::checkEnvironment() ? 0 : 1; } Logger::setLogLevel(vm["log-level"].as()); diff --git a/server/scripts/vasum-check-env.sh b/server/scripts/vasum-check-env.sh new file mode 100755 index 0000000..a03524c --- /dev/null +++ b/server/scripts/vasum-check-env.sh @@ -0,0 +1,84 @@ +#!/bin/sh + +# Note: based on lxc-checkconfig script + +: ${CONFIG:=/proc/config.gz} +: ${GREP:=zgrep} + +SETCOLOR_SUCCESS="printf \\033[1;32m" +SETCOLOR_FAILURE="printf \\033[1;31m" +SETCOLOR_WARNING="printf \\033[1;33m" +SETCOLOR_NORMAL="printf \\033[0;39m" + +FAILURE=false + +is_builtin() { + $GREP -q "$1=y" $CONFIG + return $? +} + +# is_enabled has two parameters +# 1=kernel option +# 2=is the option mandatory (optional parameter) +is_enabled() { + mandatory=$2 + is_builtin $1 + RES=$? + if [ $RES -eq 0 ]; then + $SETCOLOR_SUCCESS && echo "enabled" && $SETCOLOR_NORMAL + else + if [ ! -z "$mandatory" -a "$mandatory" = yes ]; then + FAILURE=true + $SETCOLOR_FAILURE && echo "required" && $SETCOLOR_NORMAL + else + $SETCOLOR_WARNING && echo "missing" && $SETCOLOR_NORMAL + fi + fi +} + + +if [ ! -f $CONFIG ]; then + echo "no $CONFIG, searching..." + CONFIG="/boot/config-$(uname -r)" + if [ ! -f $CONFIG ]; then + echo "kernel config not found"; exit 1; + fi +fi + +echo "kernel config: $CONFIG" +KVER=$($GREP '^# Linux.*Kernel Configuration' $CONFIG | sed -r 's/#.* ([0-9]+\.[0-9]+\.[0-9]+).*/\1/') + +KVER_MAJOR=$(echo $KVER | sed -r 's/([0-9])\.[0-9]{1,2}\.[0-9]{1,3}.*/\1/') +if [ "$KVER_MAJOR" = "2" ]; then + KVER_MINOR=$(echo $KVER | sed -r 's/2.6.([0-9]{2}).*/\1/') +else + KVER_MINOR=$(echo $KVER | sed -r 's/[0-9]\.([0-9]{1,3})\.[0-9]{1,3}.*/\1/') +fi + +echo "kver=$KVER, major.minor=$KVER_MAJOR.$KVER_MINOR" + +echo "--- Namespaces ---" +echo -n "Namespaces: " && is_enabled CONFIG_NAMESPACES yes +echo -n "Utsname namespace: " && is_enabled CONFIG_UTS_NS yes +echo -n "Ipc namespace: " && is_enabled CONFIG_IPC_NS yes +echo -n "Pid namespace: " && is_enabled CONFIG_PID_NS yes +echo -n "User namespace: " && is_enabled CONFIG_USER_NS yes +echo -n "Network namespace: " && is_enabled CONFIG_NET_NS yes +echo -n "Multiple /dev/pts instances: " && is_enabled DEVPTS_MULTIPLE_INSTANCES yes +echo +echo "--- Network virtualization ---" +echo -n "VETH: " && is_enabled CONFIG_VETH yes +echo -n "VLAN: " && is_enabled CONFIG_VLAN_8021Q yes +echo -n "MACVLAN: " && is_enabled CONFIG_MACVLAN yes +echo +echo "--- Control groups ---" +echo -n "Cgroup: " && is_enabled CONFIG_CGROUPS yes +echo -n "PID cpuset: " && is_enabled CONFIG_PROC_PID_CPUSET yes +echo +echo -n "CFS Bandwidth: " && is_enabled CONFIG_CFS_BANDWIDTH yes + +if $FAILURE; then + exit 1 +else + exit 0 +fi diff --git a/server/server.cpp b/server/server.cpp index 936db28..befb8da 100644 --- a/server/server.cpp +++ b/server/server.cpp @@ -36,6 +36,7 @@ #include "utils/signal.hpp" #include "utils/exception.hpp" +#include #include #include #include @@ -47,6 +48,13 @@ #include #include +#include +#include +#include +#include +#include +#include + #ifndef VASUM_USER #error "VASUM_USER must be defined!" @@ -143,6 +151,73 @@ void Server::terminate() gSignalLatch.set(); } +bool Server::checkEnvironment() +{ + // check kernel + struct utsname u; + int version, major, minor; + ::uname(&u); + version = major = minor = 0; + ::sscanf(u.release, "%d.%d.%d", &version, &major, &minor); + if (version < 2 || (version == 2 && major < 6) || (version == 2 && major == 6 && minor < 29)) { + // control-group functionality was merged into kernel version 2.6.24 in 2007 (wikipedia) + // namespace support begins from kernels 2.4.19(mnt), 2.6.19(ns,uts,ipc), 2.6.24(pid), 2.6.29(net) + // namespace for usr from kernel 3.8(usr) - not used by vasum + std::cout << "kernel is old ver=" << u.release << ", run vasum-check-env" << std::endl; + return false; + } + else + std::cout << "kernel " << u.release << " [OK]" << std::endl; + + // check lxc (TODO check if running on broken ABI version) + if (::strcmp(lxc_get_version(), LXC_VERSION)!=0) { + // versions that matters: + // 1.1.0 added function ptr 'in-the-middle' destroy_with_snapshots, snapshot_destroy_all (breaks ABI) + // 1.1.2 added function ptr 'append' attach_interface,detach_interface,checkpoint,restore (safe for ABI) + std::cout << "LXC version not match, compiled for " << LXC_VERSION << ", installed " << lxc_get_version() << std::endl; + return false; + } + else + std::cout << "LXC version " << lxc_get_version() << " [OK]" << std::endl; + + // check cgroups (and its subsystems?) + std::string cgroupCheck = "/sys/fs/cgroup"; + int fd = ::open(cgroupCheck.c_str(), O_RDONLY); + if (fd == -1) { + std::cout << "no cgroups support (can't access " << cgroupCheck << "), run vasum-check-env" << std::endl; + return false; + } + + bool err = false; + std::vector cgroupSubsCheck = {"cpu", "cpuset", "memory"}; + for (std::string f : cgroupSubsCheck) { + if (::faccessat(fd, f.c_str(), R_OK|X_OK, 0) == -1) { + std::cout << "no cgroups support (can't access " << cgroupCheck << "/" << f << ")" << std::endl; + err=true; + } + } + ::close(fd); + if (err) { + std::cout << "cgroups problem, run vasum-check-env" << std::endl; + return false; + } + else + std::cout << "cgroups support " << " [OK]" << std::endl; + + // check namespaces + std::string nsCheck = "/proc/self/ns"; + if (::access(nsCheck.c_str(), R_OK|X_OK) == -1) { + std::cout << "no namespace support (can't access " << nsCheck << "), run vasum-check-env" << std::endl; + return false; + } + else + std::cout << "namespaces support " << " [OK]" << std::endl; + ::close(fd); + + return true; +} + + bool Server::prepareEnvironment(const std::string& configPath, bool runAsRoot) { namespace fs = boost::filesystem; diff --git a/server/server.hpp b/server/server.hpp index 8bac0b0..e034e0f 100644 --- a/server/server.hpp +++ b/server/server.hpp @@ -54,6 +54,11 @@ public: */ void terminate(); + /** + * Check server runtime environment + */ + static bool checkEnvironment(); + private: std::string mConfigPath; -- 2.7.4