Check vasum runtime environment, provide utility to check kernel config 26/40426/10
authorKrzysztof Dynowski <k.dynowski@samsung.com>
Wed, 3 Jun 2015 12:45:26 +0000 (14:45 +0200)
committerKrzysztof Dynowski <k.dynowski@samsung.com>
Mon, 15 Jun 2015 12:13:34 +0000 (14:13 +0200)
[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
server/CMakeLists.txt
server/main.cpp
server/scripts/vasum-check-env.sh [new file with mode: 0755]
server/server.cpp
server/server.hpp

index bd7346c..38c7cf6 100644 (file)
@@ -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
index 92672c1..d5104db 100644 (file)
@@ -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)
index fb3eed4..55a795e 100644 (file)
@@ -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<std::string>()->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<std::string>());
diff --git a/server/scripts/vasum-check-env.sh b/server/scripts/vasum-check-env.sh
new file mode 100755 (executable)
index 0000000..a03524c
--- /dev/null
@@ -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
index 936db28..befb8da 100644 (file)
@@ -36,6 +36,7 @@
 #include "utils/signal.hpp"
 #include "utils/exception.hpp"
 
+#include <iostream>
 #include <csignal>
 #include <cerrno>
 #include <string>
 #include <boost/filesystem.hpp>
 #include <linux/capability.h>
 
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <sys/utsname.h>
+#include <lxc/lxccontainer.h>
+#include <lxc/version.h>
+
 
 #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<std::string> 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;
index 8bac0b0..e034e0f 100644 (file)
@@ -54,6 +54,11 @@ public:
      */
     void terminate();
 
+    /**
+     * Check server runtime environment
+    */
+    static bool checkEnvironment();
+
 private:
     std::string mConfigPath;