%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
## 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)
("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;
} 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>());
--- /dev/null
+#!/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
#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!"
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;
*/
void terminate();
+ /**
+ * Check server runtime environment
+ */
+ static bool checkEnvironment();
+
private:
std::string mConfigPath;