From aca7e2907ed4461fad8a49d4d4461e43ecdc1837 Mon Sep 17 00:00:00 2001 From: Krzysztof Dynowski Date: Wed, 3 Jun 2015 14:45:26 +0200 Subject: [PATCH 01/16] 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 From 7cf310ef7d25b7e6553c7af8da53af9d5123b84d Mon Sep 17 00:00:00 2001 From: Lukasz Pawelczyk Date: Mon, 15 Jun 2015 13:52:25 +0200 Subject: [PATCH 02/16] Unlock the latch even in the case of an exception [Feature] N/A [Cause] If an exception is thrown during execute() the calling thread's latch will never be unlocked. [Solution] Unlock the latch after the whole try/catch. [Verification] Built, installed, run tests Change-Id: I2891d83f4f3459a2d2d60cdc4d2986e37894c959 --- common/utils/worker.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/common/utils/worker.cpp b/common/utils/worker.cpp index e73c4ce..09069e8 100644 --- a/common/utils/worker.cpp +++ b/common/utils/worker.cpp @@ -150,11 +150,11 @@ private: try { LOGT("Executing task from subgroup " << taskInfo.groupID); taskInfo.task(); - if (taskInfo.latch) - taskInfo.latch->set(); } catch (const std::exception& e) { LOGE("Unexpected exception while executing task: " << e.what()); } + if (taskInfo.latch) + taskInfo.latch->set(); } }; -- 2.7.4 From 28a791d3a60e8885e34ddd19d9ef1c5dd65355fa Mon Sep 17 00:00:00 2001 From: Jan Olszak Date: Mon, 8 Jun 2015 16:17:16 +0200 Subject: [PATCH 03/16] Create File in LxcZone [Feature] Create files in zones Pass file descriptors to those files Api definition [Cause] N/A [Solution] N/A [Verification] Build, run all tests Change-Id: I9780b8922fac2548bae642b0e732dd96998996ab --- common/api/messages.hpp | 29 ++++++-- common/lxc/zone.cpp | 145 +++++++++++++++++++++++++++------------ common/lxc/zone.hpp | 23 ++++++- common/utils/environment.cpp | 53 +------------- common/utils/fd-utils.cpp | 136 +++++++++++++++++++++++++++++++++++- common/utils/fd-utils.hpp | 10 +++ server/host-dbus-definitions.hpp | 7 ++ server/host-ipc-definitions.hpp | 1 + tests/unit_tests/lxc/ut-zone.cpp | 36 ++++++++++ 9 files changed, 337 insertions(+), 103 deletions(-) diff --git a/common/api/messages.hpp b/common/api/messages.hpp index ca4cab2..a00a2dd 100644 --- a/common/api/messages.hpp +++ b/common/api/messages.hpp @@ -198,8 +198,7 @@ struct DeclareMountIn { ) }; -struct DeclareLinkIn -{ +struct DeclareLinkIn { std::string source; std::string zone; std::string target; @@ -212,8 +211,7 @@ struct DeclareLinkIn ) }; -struct GrantDeviceIn -{ +struct GrantDeviceIn { std::string id; std::string device; uint32_t flags; @@ -226,8 +224,27 @@ struct GrantDeviceIn ) }; -struct Notification -{ +struct CreateFileIn { + std::string id; + std::string path; + int32_t mode; + CONFIG_REGISTER + ( + id, + path, + mode + ) +}; + +struct CreateFileOut { + config::FileDescriptor fd; + CONFIG_REGISTER + ( + fd + ) +}; + +struct Notification { std::string zone; std::string application; std::string message; diff --git a/common/lxc/zone.cpp b/common/lxc/zone.cpp index bbb1e02..5fd1762 100644 --- a/common/lxc/zone.cpp +++ b/common/lxc/zone.cpp @@ -34,7 +34,9 @@ #include "logger/logger.hpp" #include "lxc/zone.hpp" #include "lxc/exception.hpp" +#include "utils/exception.hpp" #include "utils/execute.hpp" +#include "utils/fd-utils.hpp" #ifdef USE_EXEC #include "utils/c-array.hpp" #endif @@ -46,44 +48,57 @@ #include #include +#include +#include +#include namespace vasum { namespace lxc { namespace { #define ITEM(X) {#X, LxcZone::State::X}, - const std::map STATE_MAP = { - ITEM(STOPPED) - ITEM(STARTING) - ITEM(RUNNING) - ITEM(STOPPING) - ITEM(ABORTING) - ITEM(FREEZING) - ITEM(FROZEN) - ITEM(THAWED) - }; +const std::map STATE_MAP = { + ITEM(STOPPED) + ITEM(STARTING) + ITEM(RUNNING) + ITEM(STOPPING) + ITEM(ABORTING) + ITEM(FREEZING) + ITEM(FROZEN) + ITEM(THAWED) +}; #undef ITEM + +int execFunction(void* data) { + // Executed by C code, so catch all exceptions + try { + return (*static_cast*>(data))(); + } catch(...) { + return -1; // Non-zero on failure + } + return 0; // Success +} + } // namespace -std::string LxcZone::toString(State state) -{ +std::string LxcZone::toString(State state) { #define CASE(X) case LxcZone::State::X: return #X; switch (state) { - CASE(STOPPED) - CASE(STARTING) - CASE(RUNNING) - CASE(STOPPING) - CASE(ABORTING) - CASE(FREEZING) - CASE(FROZEN) - CASE(THAWED) + CASE(STOPPED) + CASE(STARTING) + CASE(RUNNING) + CASE(STOPPING) + CASE(ABORTING) + CASE(FREEZING) + CASE(FROZEN) + CASE(THAWED) } #undef CASE throw LxcException("Invalid state"); } LxcZone::LxcZone(const std::string& lxcPath, const std::string& zoneName) - : mLxcContainer(nullptr) + : mLxcContainer(nullptr) { mLxcContainer = lxc_container_new(zoneName.c_str(), lxcPath.c_str()); if (!mLxcContainer) { @@ -129,9 +144,9 @@ bool LxcZone::create(const std::string& templatePath, const char* const* argv) #ifdef USE_EXEC utils::CStringArrayBuilder args; args.add("lxc-create") - .add("-n").add(mLxcContainer->name) - .add("-t").add(templatePath.c_str()) - .add("-P").add(mLxcContainer->config_path); + .add("-n").add(mLxcContainer->name) + .add("-t").add(templatePath.c_str()) + .add("-P").add(mLxcContainer->config_path); if (*argv) { args.add("--"); @@ -179,9 +194,9 @@ bool LxcZone::start(const char* const* argv) utils::CStringArrayBuilder args; args.add("lxc-start") - .add("-d") - .add("-n").add(mLxcContainer->name) - .add("-P").add(mLxcContainer->config_path); + .add("-d") + .add("-n").add(mLxcContainer->name) + .add("-P").add(mLxcContainer->config_path); if (*argv) { args.add("--"); @@ -254,10 +269,10 @@ bool LxcZone::shutdown(int timeout) utils::CStringArrayBuilder args; std::string timeoutStr = std::to_string(timeout); args.add("lxc-stop") - .add("-n").add(mLxcContainer->name) - .add("-P").add(mLxcContainer->config_path) - .add("-t").add(timeoutStr.c_str()) - .add("--nokill"); + .add("-n").add(mLxcContainer->name) + .add("-P").add(mLxcContainer->config_path) + .add("-t").add(timeoutStr.c_str()) + .add("--nokill"); if (!utils::executeAndWait("/usr/bin/lxc-stop", args.c_array())) { LOGE("Could not gracefully shutdown zone " << getName() << " in " << timeout << "s"); @@ -320,14 +335,37 @@ pid_t LxcZone::getInitPid() const bool LxcZone::setRunLevel(int runLevel) { - auto callback = [](void* param) -> int { - utils::RunLevel level = *reinterpret_cast(param); - return utils::setRunLevel(level) ? 0 : 1; + Call call = [runLevel]() -> int { + return utils::setRunLevel(static_cast(runLevel)) ? 0 : 1; }; + return runInZone(call); +} + +void LxcZone::refresh() +{ + //TODO Consider make LxcZone state-less + std::string zoneName = mLxcContainer->name; + std::string lxcPath = mLxcContainer->config_path; + lxc_container_put(mLxcContainer); + mLxcContainer = lxc_container_new(zoneName.c_str(), lxcPath.c_str()); +} +bool LxcZone::runInZone(Call& call) +{ lxc_attach_options_t options = LXC_ATTACH_OPTIONS_DEFAULT; + options.attach_flags = LXC_ATTACH_REMOUNT_PROC_SYS | + LXC_ATTACH_DROP_CAPABILITIES | + LXC_ATTACH_SET_PERSONALITY | + LXC_ATTACH_LSM_EXEC | + LXC_ATTACH_LSM_NOW | + LXC_ATTACH_MOVE_TO_CGROUP; + pid_t pid; - int ret = mLxcContainer->attach(mLxcContainer, callback, &runLevel, &options, &pid); + int ret = mLxcContainer->attach(mLxcContainer, + execFunction, + &call, + &options, + &pid); if (ret != 0) { return false; } @@ -338,15 +376,38 @@ bool LxcZone::setRunLevel(int runLevel) return status == 0; } -void LxcZone::refresh() +int LxcZone::createFile(const std::string& path, const std::int32_t mode, int *fdPtr) { - //TODO Consider make LxcZone state-less - std::string zoneName = mLxcContainer->name; - std::string lxcPath = mLxcContainer->config_path; - lxc_container_put(mLxcContainer); - mLxcContainer = lxc_container_new(zoneName.c_str(), lxcPath.c_str()); -} + *fdPtr = -1; + + int sockets[2]; + if (::socketpair(AF_LOCAL, SOCK_STREAM, 0, sockets) < 0) { + LOGE("Can't create socket pair: " << utils::getSystemErrorMessage()); + return false; + } + + lxc::LxcZone::Call call = [&]()->int{ + utils::close(sockets[1]); + + int fd = ::open(path.c_str(), O_CREAT | O_EXCL, mode); + if (fd < 0) { + LOGE("Error during file creation: " << utils::getSystemErrorMessage()); + utils::close(sockets[0]); + return -1; + } + utils::fdSend(sockets[0], fd); + utils::close(fd); + return 0; + }; + runInZone(call); + + utils::close(sockets[0]); + *fdPtr = utils::fdRecv(sockets[1]); + utils::close(sockets[1]); + + return true; +} } // namespace lxc } // namespace vasum diff --git a/common/lxc/zone.hpp b/common/lxc/zone.hpp index 0ed19a3..0d34e6f 100644 --- a/common/lxc/zone.hpp +++ b/common/lxc/zone.hpp @@ -26,6 +26,7 @@ #define COMMON_LXC_ZONE_HPP #include +#include #include // fwd declaration of lxc internals @@ -40,6 +41,8 @@ namespace lxc { */ class LxcZone { public: + typedef std::function Call; + enum class State { STOPPED, STARTING, @@ -143,9 +146,27 @@ public: */ pid_t getInitPid() const; + /** + * Attach to the Zone and run the call + * + * This call will fork, so ensure the call object will withstand this + * + * @param call function object to run + */ + bool runInZone(Call& call); + + /** + * Create a file inside the zone and return it's file descriptor + * + * @param path path in the container + * @param mode mode + * + * @return file descriptor of the file, opened in mode + */ + int createFile(const std::string& path, const std::int32_t mode, int *fdPtr); + private: lxc_container* mLxcContainer; - bool setRunLevel(int runLevel); void refresh(); }; diff --git a/common/utils/environment.cpp b/common/utils/environment.cpp index 4a04e0d..a28a528 100644 --- a/common/utils/environment.cpp +++ b/common/utils/environment.cpp @@ -28,6 +28,7 @@ #include "utils/execute.hpp" #include "utils/exception.hpp" #include "utils/make-clean.hpp" +#include "utils/fd-utils.hpp" #include "base-exception.hpp" #include "logger/logger.hpp" @@ -93,58 +94,6 @@ const std::map NAMESPACES = { {CLONE_NEWUSER, "user"}, {CLONE_NEWUTS, "uts"}}; -int fdRecv(int socket) -{ - msghdr msg = make_clean(); - iovec iov = make_clean(); - char cmsgBuff[CMSG_SPACE(sizeof(int))]; - - msg.msg_iov = &iov; - msg.msg_iovlen = 1; - - msg.msg_control = cmsgBuff; - msg.msg_controllen = sizeof(cmsgBuff); - - int ret = recvmsg(socket, &msg, MSG_CMSG_CLOEXEC); - if (ret != 0 || msg.msg_flags & (MSG_TRUNC | MSG_ERRQUEUE | MSG_OOB | MSG_CTRUNC | MSG_EOR)) { - LOGE("Can't receive fd: ret: " << ret << ", flags: " << msg.msg_flags); - return -1; - } - - cmsghdr* cmsg = CMSG_FIRSTHDR(&msg); - assert(cmsg->cmsg_level == SOL_SOCKET); - assert(cmsg->cmsg_type == SCM_RIGHTS); - assert(CMSG_NXTHDR(&msg, cmsg) == NULL); - return *reinterpret_cast(CMSG_DATA(cmsg)); -} - -bool fdSend(int socket, int fd) -{ - msghdr msg = make_clean(); - struct iovec iov = make_clean(); - struct cmsghdr *cmsg = NULL; - char cmsgBuff[CMSG_SPACE(sizeof(int))]; - - msg.msg_iov = &iov; - msg.msg_iovlen = 1; - - msg.msg_control = cmsgBuff; - msg.msg_controllen = sizeof(cmsgBuff); - - cmsg = CMSG_FIRSTHDR(&msg); - cmsg->cmsg_level = SOL_SOCKET; - cmsg->cmsg_type = SCM_RIGHTS; - cmsg->cmsg_len = CMSG_LEN(sizeof(int)); - *reinterpret_cast(CMSG_DATA(cmsg)) = fd; - - int ret = sendmsg(socket, &msg, 0); - if (ret < 0) { - LOGE("Can't send fd: ret: " << ret); - return false; - } - return true; -} - inline bool isValidCap(unsigned int cap) { return cap <= CAP_LAST_CAP; diff --git a/common/utils/fd-utils.cpp b/common/utils/fd-utils.cpp index d5179b1..4fe9a17 100644 --- a/common/utils/fd-utils.cpp +++ b/common/utils/fd-utils.cpp @@ -34,6 +34,7 @@ #include #include #include +#include #include namespace fs = boost::filesystem; @@ -41,6 +42,8 @@ namespace chr = std::chrono; namespace utils { +// TODO: Add here various fixes from config::FDStore + namespace { void waitForEvent(int fd, @@ -111,7 +114,7 @@ void close(int fd) void write(int fd, const void* bufferPtr, const size_t size, int timeoutMS) { chr::high_resolution_clock::time_point deadline = chr::high_resolution_clock::now() + - chr::milliseconds(timeoutMS); + chr::milliseconds(timeoutMS); size_t nTotal = 0; for (;;) { @@ -140,7 +143,7 @@ void write(int fd, const void* bufferPtr, const size_t size, int timeoutMS) void read(int fd, void* bufferPtr, const size_t size, int timeoutMS) { chr::high_resolution_clock::time_point deadline = chr::high_resolution_clock::now() + - chr::milliseconds(timeoutMS); + chr::milliseconds(timeoutMS); size_t nTotal = 0; for (;;) { @@ -200,5 +203,134 @@ unsigned int getFDNumber() fs::directory_iterator()); } +int fdRecv(int socket, const unsigned int timeoutMS) +{ + std::chrono::high_resolution_clock::time_point deadline = + std::chrono::high_resolution_clock::now() + + std::chrono::milliseconds(timeoutMS); + + // Space for the file descriptor + union { + struct cmsghdr cmh; + char control[CMSG_SPACE(sizeof(int))]; + } controlUnion; + + // Describe the data that we want to recive + controlUnion.cmh.cmsg_len = CMSG_LEN(sizeof(int)); + controlUnion.cmh.cmsg_level = SOL_SOCKET; + controlUnion.cmh.cmsg_type = SCM_RIGHTS; + + // Setup the input buffer + // Ensure at least 1 byte is transmited via the socket + char buf; + struct iovec iov; + iov.iov_base = &buf; + iov.iov_len = sizeof(char); + + // Set the ancillary data buffer + // The socket has to be connected, so we don't need to specify the name + struct msghdr msgh; + ::memset(&msgh, 0, sizeof(msgh)); + + msgh.msg_iov = &iov; + msgh.msg_iovlen = 1; + + msgh.msg_control = controlUnion.control; + msgh.msg_controllen = sizeof(controlUnion.control); + + // Receive + for(;;) { + ssize_t ret = ::recvmsg(socket, &msgh, MSG_WAITALL); + if (ret < 0) { + if (errno == EAGAIN || errno == EWOULDBLOCK || errno == EINTR) { + // Neglected errors, retry + } else { + throw UtilsException("Error during recvmsg: " + getSystemErrorMessage()); + } + } else if (ret == 0) { + throw UtilsException("Peer disconnected"); + } else { + // We receive only 1 byte of data. No need to repeat + break; + } + + waitForEvent(socket, POLLIN, deadline); + } + + struct cmsghdr *cmhp; + cmhp = CMSG_FIRSTHDR(&msgh); + if (cmhp == NULL || cmhp->cmsg_len != CMSG_LEN(sizeof(int))) { + throw UtilsException("Bad cmsg length"); + } else if (cmhp->cmsg_level != SOL_SOCKET) { + throw UtilsException("cmsg_level != SOL_SOCKET"); + } else if (cmhp->cmsg_type != SCM_RIGHTS) { + throw UtilsException("cmsg_type != SCM_RIGHTS"); + } + + return *(reinterpret_cast(CMSG_DATA(cmhp))); +} + +bool fdSend(int socket, int fd, const unsigned int timeoutMS) +{ + std::chrono::high_resolution_clock::time_point deadline = + std::chrono::high_resolution_clock::now() + + std::chrono::milliseconds(timeoutMS); + + // Space for the file descriptor + union { + struct cmsghdr cmh; + char control[CMSG_SPACE(sizeof(int))]; + } controlUnion; + + // Ensure at least 1 byte is transmited via the socket + struct iovec iov; + char buf = '!'; + iov.iov_base = &buf; + iov.iov_len = sizeof(char); + + // Fill the message to send: + // The socket has to be connected, so we don't need to specify the name + struct msghdr msgh; + ::memset(&msgh, 0, sizeof(msgh)); + + // Only iovec to transmit one element + msgh.msg_iov = &iov; + msgh.msg_iovlen = 1; + + // Ancillary data buffer + msgh.msg_control = controlUnion.control; + msgh.msg_controllen = sizeof(controlUnion.control); + + // Describe the data that we want to send + struct cmsghdr *cmhp; + cmhp = CMSG_FIRSTHDR(&msgh); + cmhp->cmsg_len = CMSG_LEN(sizeof(int)); + cmhp->cmsg_level = SOL_SOCKET; + cmhp->cmsg_type = SCM_RIGHTS; + *(reinterpret_cast(CMSG_DATA(cmhp))) = fd; + + // Send + for(;;) { + ssize_t ret = ::sendmsg(socket, &msgh, MSG_NOSIGNAL); + if (ret < 0) { + if (errno == EAGAIN || errno == EWOULDBLOCK || errno == EINTR) { + // Neglected errors, retry + } else { + throw UtilsException("Error during sendmsg: " + getSystemErrorMessage()); + } + } else if (ret == 0) { + // Retry the sending + } else { + // We send only 1 byte of data. No need to repeat + break; + } + + waitForEvent(socket, POLLOUT, deadline); + } + + // TODO: It shouldn't return + return true; +} + } // namespace utils diff --git a/common/utils/fd-utils.hpp b/common/utils/fd-utils.hpp index 209de2c..d6a4032 100644 --- a/common/utils/fd-utils.hpp +++ b/common/utils/fd-utils.hpp @@ -71,6 +71,16 @@ void setMaxFDNumber(unsigned int limit); */ unsigned int getFDNumber(); +/** + * Send Socket via Unix Domain socket + */ +bool fdSend(int socket, int fd, const unsigned int timeoutMS = 5000); + +/** + * Receive fd via Unix Domain socket + */ +int fdRecv(int socket, const unsigned int timeoutMS = 5000); + } // namespace utils #endif // COMMON_UTILS_FD_HPP diff --git a/server/host-dbus-definitions.hpp b/server/host-dbus-definitions.hpp index 2d013c9..142a6d2 100644 --- a/server/host-dbus-definitions.hpp +++ b/server/host-dbus-definitions.hpp @@ -62,6 +62,7 @@ const std::string METHOD_UNLOCK_ZONE = "UnlockZone"; const std::string METHOD_GRANT_DEVICE = "GrantDevice"; const std::string METHOD_REVOKE_DEVICE = "RevokeDevice"; const std::string METHOD_PROXY_CALL = "ProxyCall"; +const std::string METHOD_CREATE_FILE = "CreateFile"; const std::string METHOD_NOTIFY_ACTIVE_ZONE = "NotifyActiveZone"; const std::string METHOD_FILE_MOVE_REQUEST = "FileMoveRequest"; @@ -177,6 +178,12 @@ const std::string DEFINITION = " " " " " " + " " + " " + " " + " " + " " + " " " " " " " " diff --git a/server/host-ipc-definitions.hpp b/server/host-ipc-definitions.hpp index 0053efa..d1251eb 100644 --- a/server/host-ipc-definitions.hpp +++ b/server/host-ipc-definitions.hpp @@ -56,6 +56,7 @@ const ::ipc::MethodID METHOD_LOCK_ZONE = 23; const ::ipc::MethodID METHOD_UNLOCK_ZONE = 24; const ::ipc::MethodID METHOD_GRANT_DEVICE = 25; const ::ipc::MethodID METHOD_REVOKE_DEVICE = 26; +const ::ipc::MethodID METHOD_CREATE_FILE = 27; const ::ipc::MethodID METHOD_NOTIFY_ACTIVE_ZONE = 100; const ::ipc::MethodID METHOD_FILE_MOVE_REQUEST = 101; diff --git a/tests/unit_tests/lxc/ut-zone.cpp b/tests/unit_tests/lxc/ut-zone.cpp index e2683d6..f87427e 100644 --- a/tests/unit_tests/lxc/ut-zone.cpp +++ b/tests/unit_tests/lxc/ut-zone.cpp @@ -30,6 +30,7 @@ #include "lxc/exception.hpp" #include "utils/scoped-dir.hpp" +#include #include #include #include @@ -249,4 +250,39 @@ BOOST_AUTO_TEST_CASE(Repeat) BOOST_CHECK(!lxc.destroy()); // forbidden (why?) } +BOOST_AUTO_TEST_CASE(CreateFile) +{ + // Create and start the container: + LxcZone lxc(ZONE_PATH, ZONE_NAME); + BOOST_REQUIRE(lxc.create(ZONE_TEMPLATE, TEMPLATE_ARGS)); + const char* argv[] = { + "/bin/sh", + "-c", + "trap exit SIGTERM; read", + NULL + }; + BOOST_REQUIRE(lxc.start(argv)); + BOOST_REQUIRE(lxc.getState() == LxcZone::State::RUNNING); + waitForInit(); + + // The test + int fd; + BOOST_REQUIRE(lxc.createFile("./112.txt", O_RDWR, &fd)); + BOOST_REQUIRE(::fcntl(fd, F_GETFD) != -1); + BOOST_REQUIRE(::close(fd) != -1); + + BOOST_REQUIRE(lxc.createFile("/2.txt", O_RDONLY, &fd)); + BOOST_REQUIRE(::fcntl(fd, F_GETFD) != -1); + BOOST_REQUIRE(::close(fd) != -1); + + BOOST_REQUIRE(lxc.createFile("/3.txt", O_WRONLY, &fd)); + BOOST_REQUIRE(::fcntl(fd, F_GETFD) != -1); + BOOST_REQUIRE(::close(fd) != -1); + + // Close + BOOST_REQUIRE(lxc.stop()); + BOOST_REQUIRE(lxc.getState() == LxcZone::State::STOPPED); + BOOST_REQUIRE(lxc.destroy()); +} + BOOST_AUTO_TEST_SUITE_END() -- 2.7.4 From 189ae89e124478a4aaface3c2a593cee2603ebf2 Mon Sep 17 00:00:00 2001 From: Mateusz Malicki Date: Wed, 3 Jun 2015 15:58:18 +0200 Subject: [PATCH 04/16] Add vsm_get_event_fd and vsm_enter_eventloop [Feature] Provide possibility to implement custom event loop for user of vasum client library [Cause] Integration with other services [Solution] Possibility to fetch event fd and run event loop [Verification] run ClientSuite tests Change-Id: Ic47e5de8bfd09889330d97d35d4c9ef47f238953 --- client/host-ipc-connection.cpp | 15 +- client/host-ipc-connection.hpp | 9 +- client/vasum-client-impl.cpp | 310 +++++++++++++++++++++------------- client/vasum-client-impl.hpp | 48 +++++- client/vasum-client.cpp | 29 +++- client/vasum-client.h | 127 ++++++++++++++ tests/unit_tests/client/ut-client.cpp | 151 +++++++++++++++++ wrapper/wrapper.cpp | 2 +- 8 files changed, 555 insertions(+), 136 deletions(-) diff --git a/client/host-ipc-connection.cpp b/client/host-ipc-connection.cpp index 7444f19..a58e0d7 100644 --- a/client/host-ipc-connection.cpp +++ b/client/host-ipc-connection.cpp @@ -35,22 +35,23 @@ namespace { const int TIMEOUT_INFINITE = -1; } //namespace -void HostIPCConnection::createSystem() +void HostIPCConnection::connect(const std::string& address, ipc::epoll::EventPoll& eventPoll) { - mClient.reset(new ipc::Client(mDispatcher.getPoll(), HOST_IPC_SOCKET)); + mClient.reset(new ipc::Client(eventPoll, address)); mClient->start(); } -ipc::epoll::ThreadDispatcher& HostIPCConnection::getDispatcher() + +void HostIPCConnection::disconnect() { - return mDispatcher; + mClient.reset(); } -void HostIPCConnection::create(const std::string& address) +bool HostIPCConnection::isConnected() { - mClient.reset(new ipc::Client(mDispatcher.getPoll(), address)); - mClient->start(); + return mClient && mClient->isStarted(); } + void HostIPCConnection::callGetZoneIds(api::ZoneIds& argOut) { argOut = *mClient->callSync( diff --git a/client/host-ipc-connection.hpp b/client/host-ipc-connection.hpp index 52b90b7..16a2a9e 100644 --- a/client/host-ipc-connection.hpp +++ b/client/host-ipc-connection.hpp @@ -27,8 +27,8 @@ #define VASUM_CLIENT_HOST_IPC_CONNECTION_HPP #include -#include #include +#include #include @@ -42,9 +42,9 @@ class HostIPCConnection { public: typedef unsigned int SubscriptionId; typedef std::function NotificationCallback; - void createSystem(); - void create(const std::string& address); - ipc::epoll::ThreadDispatcher& getDispatcher(); + void connect(const std::string& address, ipc::epoll::EventPoll& eventPoll); + void disconnect(); + bool isConnected(); void callGetZoneIds(vasum::api::ZoneIds& argOut); void callGetActiveZoneId(vasum::api::ZoneId& argOut); @@ -80,7 +80,6 @@ public: void unsubscribe(const SubscriptionId& id); private: - ipc::epoll::ThreadDispatcher mDispatcher; std::unique_ptr mClient; }; diff --git a/client/vasum-client-impl.cpp b/client/vasum-client-impl.cpp index f87e9a0..97cd004 100644 --- a/client/vasum-client-impl.cpp +++ b/client/vasum-client-impl.cpp @@ -23,6 +23,11 @@ * @brief This file contains vasum-server's client implementation */ +//TODO: Make dispatcher related function thread-safe. +//For now vsm_connect, vsm_get_dispatcher_type, vsm_set_dispatcher_type, +//vsm_get_poll_fd, vsm_enter_eventloop can't be used at the same time. +//TODO: Make vsm_get_status_message thread-safe version (vsm_get_status_message_r) + #include #include "vasum-client-impl.hpp" #include "utils.hpp" @@ -34,7 +39,6 @@ #include #include #include -#include #include #include #include @@ -127,6 +131,11 @@ bool readFirstLineOfFile(const string& path, string& ret) } //namespace +#define IS_SET(param) \ + if (!param) { \ + throw InvalidArgumentException(#param " is not set"); \ + } + Client::Status::Status() : mVsmStatus(VSMCLIENT_SUCCESS), mMsg() { @@ -145,20 +154,39 @@ Client::~Client() noexcept { } +bool Client::isInternalDispatcherEnabled() const +{ + return static_cast(mInternalDispatcher); +} + +ipc::epoll::EventPoll& Client::getEventPoll() const +{ + if ((mInternalDispatcher && mEventPoll) || (!mInternalDispatcher && !mEventPoll)) { + throw OperationFailedException("Can't determine dispatcher method"); + } + + if (isInternalDispatcherEnabled()) { + return mInternalDispatcher->getPoll(); + } else { + return *mEventPoll; + } +} + VsmStatus Client::coverException(const function& worker) noexcept { try { worker(); + mStatusMutex.lock(); mStatus = Status(VSMCLIENT_SUCCESS); - } catch (const vasum::IOException& ex) { + } catch (const IOException& ex) { mStatus = Status(VSMCLIENT_IO_ERROR, ex.what()); - } catch (const vasum::OperationFailedException& ex) { + } catch (const OperationFailedException& ex) { mStatus = Status(VSMCLIENT_OPERATION_FAILED, ex.what()); - } catch (const vasum::InvalidArgumentException& ex) { + } catch (const InvalidArgumentException& ex) { mStatus = Status(VSMCLIENT_INVALID_ARGUMENT, ex.what()); - } catch (const vasum::InvalidResponseException& ex) { + } catch (const InvalidResponseException& ex) { mStatus = Status(VSMCLIENT_OTHER_ERROR, ex.what()); - } catch (const vasum::ClientException& ex) { + } catch (const ClientException& ex) { mStatus = Status(VSMCLIENT_CUSTOM_ERROR, ex.what()); } catch (const ipc::IPCUserException& ex) { mStatus = Status(VSMCLIENT_CUSTOM_ERROR, ex.what()); @@ -167,26 +195,86 @@ VsmStatus Client::coverException(const function& worker) noexcept } catch (const exception& ex) { mStatus = Status(VSMCLIENT_CUSTOM_ERROR, ex.what()); } - return mStatus.mVsmStatus; + VsmStatus ret = mStatus.mVsmStatus; + mStatusMutex.unlock(); + return ret; +} + +VsmStatus Client::connectSystem() noexcept +{ + return connect(HOST_IPC_SOCKET); +} + +VsmStatus Client::connect(const std::string& address) noexcept +{ + return coverException([&] { + if (!mInternalDispatcher && !mEventPoll) { + vsm_set_dispatcher_type(VSMDISPATCHER_INTERNAL); + } + mHostClient.connect(address, getEventPoll()); + }); +} + +VsmStatus Client::disconnect() noexcept +{ + return coverException([&] { + mHostClient.disconnect(); + }); } -VsmStatus Client::createSystem() noexcept +VsmStatus Client::vsm_get_poll_fd(int* fd) noexcept { return coverException([&] { - mHostClient.createSystem(); + IS_SET(fd); + if (isInternalDispatcherEnabled()) { + throw OperationFailedException("Can't get event fd from internal dispatcher"); + } + *fd = mEventPoll->getPollFD(); }); } -VsmStatus Client::create(const string& address) noexcept +VsmStatus Client::vsm_enter_eventloop(int /* flags */, int timeout) noexcept { return coverException([&] { - mHostClient.create(address); + if (isInternalDispatcherEnabled()) { + throw OperationFailedException("Can't enter to event loop of internal dispatcher"); + } + mEventPoll->dispatchIteration(timeout); }); } -ipc::epoll::EventPoll& Client::getEventPoll() noexcept +VsmStatus Client::vsm_set_dispatcher_type(VsmDispacherType dispacher) noexcept { - return mHostClient.getDispatcher().getPoll(); + return coverException([&] { + if (mHostClient.isConnected()) { + throw OperationFailedException("Can't change dispacher"); + } + switch (dispacher) { + case VSMDISPATCHER_INTERNAL: + mInternalDispatcher.reset(new ipc::epoll::ThreadDispatcher()); + mEventPoll.reset(); + break; + case VSMDISPATCHER_EXTERNAL: + mEventPoll.reset(new ipc::epoll::EventPoll()); + mInternalDispatcher.reset(); + break; + default: + throw OperationFailedException("Unsupported EventDispacher type"); + } + }); +} + +VsmStatus Client::vsm_get_dispatcher_type(VsmDispacherType* dispacher) noexcept +{ + return coverException([&] { + IS_SET(dispacher); + + if (isInternalDispatcherEnabled()) { + *dispacher = VSMDISPATCHER_INTERNAL; + } else { + *dispacher = VSMDISPATCHER_EXTERNAL; + } + }); } const char* Client::vsm_get_status_message() const noexcept @@ -196,6 +284,7 @@ const char* Client::vsm_get_status_message() const noexcept VsmStatus Client::vsm_get_status() const noexcept { + lock_guard lock(mStatusMutex); return mStatus.mVsmStatus; } @@ -209,9 +298,9 @@ VsmStatus Client::vsm_get_zone_dbuses(VsmArrayString* /*keys*/, VsmArrayString* VsmStatus Client::vsm_get_zone_ids(VsmArrayString* array) noexcept { - assert(array); - return coverException([&] { + IS_SET(array); + api::ZoneIds zoneIds; mHostClient.callGetZoneIds(zoneIds); convert(zoneIds, *array); @@ -220,9 +309,9 @@ VsmStatus Client::vsm_get_zone_ids(VsmArrayString* array) noexcept VsmStatus Client::vsm_get_active_zone_id(VsmString* id) noexcept { - assert(id); - return coverException([&] { + IS_SET(id); + api::ZoneId zoneId; mHostClient.callGetActiveZoneId(zoneId); *id = ::strdup(zoneId.value.c_str()); @@ -231,10 +320,10 @@ VsmStatus Client::vsm_get_active_zone_id(VsmString* id) noexcept VsmStatus Client::vsm_get_zone_rootpath(const char* id, VsmString* rootpath) noexcept { - assert(id); - assert(rootpath); - return coverException([&] { + IS_SET(id); + IS_SET(rootpath); + api::ZoneInfoOut info; mHostClient.callGetZoneInfo({ id }, info); *rootpath = ::strdup(info.rootPath.c_str()); @@ -243,9 +332,9 @@ VsmStatus Client::vsm_get_zone_rootpath(const char* id, VsmString* rootpath) noe VsmStatus Client::vsm_lookup_zone_by_pid(int pid, VsmString* id) noexcept { - assert(id); - return coverException([&] { + IS_SET(id); + const string path = "/proc/" + to_string(pid) + "/cpuset"; string cpuset; @@ -264,10 +353,10 @@ VsmStatus Client::vsm_lookup_zone_by_pid(int pid, VsmString* id) noexcept VsmStatus Client::vsm_lookup_zone_by_id(const char* id, VsmZone* zone) noexcept { - assert(id); - assert(zone); - return coverException([&] { + IS_SET(id); + IS_SET(zone); + api::ZoneInfoOut info; mHostClient.callGetZoneInfo({ id }, info); convert(info, *zone); @@ -284,18 +373,18 @@ VsmStatus Client::vsm_lookup_zone_by_terminal_id(int, VsmString*) noexcept VsmStatus Client::vsm_set_active_zone(const char* id) noexcept { - assert(id); - return coverException([&] { + IS_SET(id); + mHostClient.callSetActiveZone({ id }); }); } VsmStatus Client::vsm_create_zone(const char* id, const char* tname) noexcept { - assert(id); - return coverException([&] { + IS_SET(id); + string template_name = tname ? tname : "default"; mHostClient.callCreateZone({ id, template_name }); }); @@ -303,45 +392,40 @@ VsmStatus Client::vsm_create_zone(const char* id, const char* tname) noexcept VsmStatus Client::vsm_destroy_zone(const char* id) noexcept { - assert(id); - return coverException([&] { + IS_SET(id); mHostClient.callDestroyZone({ id }); }); } VsmStatus Client::vsm_shutdown_zone(const char* id) noexcept { - assert(id); - return coverException([&] { + IS_SET(id); mHostClient.callShutdownZone({ id }); }); } VsmStatus Client::vsm_start_zone(const char* id) noexcept { - assert(id); - return coverException([&] { + IS_SET(id); mHostClient.callStartZone({ id }); }); } VsmStatus Client::vsm_lock_zone(const char* id) noexcept { - assert(id); - return coverException([&] { + IS_SET(id); mHostClient.callLockZone({ id }); }); } VsmStatus Client::vsm_unlock_zone(const char* id) noexcept { - assert(id); - return coverException([&] { + IS_SET(id); mHostClient.callUnlockZone({ id }); }); } @@ -365,30 +449,30 @@ VsmStatus Client::vsm_del_state_callback(VsmSubscriptionId subscriptionId) noexc VsmStatus Client::vsm_grant_device(const char* id, const char* device, uint32_t flags) noexcept { - assert(id); - assert(device); - return coverException([&] { + IS_SET(id); + IS_SET(device); + mHostClient.callGrantDevice({ id, device, flags }); }); } VsmStatus Client::vsm_revoke_device(const char* id, const char* device) noexcept { - assert(id); - assert(device); - return coverException([&] { + IS_SET(id); + IS_SET(device); + mHostClient.callRevokeDevice({ id, device }); }); } VsmStatus Client::vsm_zone_get_netdevs(const char* id, VsmArrayString* netdevIds) noexcept { - assert(id); - assert(netdevIds); - return coverException([&] { + IS_SET(id); + IS_SET(netdevIds); + api::NetDevList netdevs; mHostClient.callGetNetdevList({ id }, netdevs); convert(netdevs, *netdevIds); @@ -402,11 +486,11 @@ VsmStatus Client::vsm_netdev_get_ip_addr(const char* id, { using namespace boost::algorithm; - assert(id); - assert(netdevId); - assert(addr); - return coverException([&] { + IS_SET(id); + IS_SET(netdevId); + IS_SET(addr); + api::GetNetDevAttrs attrs; mHostClient.callGetNetdevAttrs({ id, netdevId }, attrs); @@ -454,11 +538,11 @@ VsmStatus Client::vsm_netdev_set_ipv4_addr(const char* id, struct in_addr* addr, int prefix) noexcept { - assert(id); - assert(netdevId); - assert(addr); - return coverException([&] { + IS_SET(id); + IS_SET(netdevId); + IS_SET(addr); + string value = "ip:" + toString(addr) + ",""prefixlen:" + to_string(prefix); mHostClient.callSetNetdevAttrs({ id, netdevId, { { "ipv4", value } } } ); }); @@ -469,11 +553,11 @@ VsmStatus Client::vsm_netdev_set_ipv6_addr(const char* id, struct in6_addr* addr, int prefix) noexcept { - assert(id); - assert(netdevId); - assert(addr); - return coverException([&] { + IS_SET(id); + IS_SET(netdevId); + IS_SET(addr); + string value = "ip:" + toString(addr) + ",""prefixlen:" + to_string(prefix); mHostClient.callSetNetdevAttrs({ id, netdevId, { { "ipv6", value } } } ); }); @@ -484,11 +568,11 @@ VsmStatus Client::vsm_netdev_del_ipv4_addr(const char* id, struct in_addr* addr, int prefix) noexcept { - assert(id); - assert(netdevId); - assert(addr); - return coverException([&] { + IS_SET(id); + IS_SET(netdevId); + IS_SET(addr); + //CIDR notation string ip = toString(addr) + "/" + to_string(prefix); mHostClient.callDeleteNetdevIpAddress({ id, netdevId, ip }); @@ -500,11 +584,11 @@ VsmStatus Client::vsm_netdev_del_ipv6_addr(const char* id, struct in6_addr* addr, int prefix) noexcept { - assert(id); - assert(netdevId); - assert(addr); - return coverException([&] { + IS_SET(id); + IS_SET(netdevId); + IS_SET(addr); + //CIDR notation string ip = toString(addr) + "/" + to_string(prefix); mHostClient.callDeleteNetdevIpAddress({ id, netdevId, ip }); @@ -514,10 +598,10 @@ VsmStatus Client::vsm_netdev_del_ipv6_addr(const char* id, VsmStatus Client::vsm_netdev_up(const char* id, const char* netdevId) noexcept { - assert(id); - assert(netdevId); - return coverException([&] { + IS_SET(id); + IS_SET(netdevId); + mHostClient.callSetNetdevAttrs({ id, netdevId, { { "flags", to_string(IFF_UP) }, { "change", to_string(IFF_UP) } } } ); }); @@ -525,10 +609,10 @@ VsmStatus Client::vsm_netdev_up(const char* id, const char* netdevId) noexcept VsmStatus Client::vsm_netdev_down(const char* id, const char* netdevId) noexcept { - assert(id); - assert(netdevId); - return coverException([&] { + IS_SET(id); + IS_SET(netdevId); + mHostClient.callSetNetdevAttrs({ id, netdevId, { { "flags", to_string(~IFF_UP) }, { "change", to_string(IFF_UP) } } } ); }); @@ -538,11 +622,11 @@ VsmStatus Client::vsm_create_netdev_veth(const char* id, const char* zoneDev, const char* hostDev) noexcept { - assert(id); - assert(zoneDev); - assert(hostDev); - return coverException([&] { + IS_SET(id); + IS_SET(zoneDev); + IS_SET(hostDev); + mHostClient.callCreateNetdevVeth({ id, zoneDev, hostDev }); }); } @@ -552,21 +636,21 @@ VsmStatus Client::vsm_create_netdev_macvlan(const char* id, const char* hostDev, enum macvlan_mode mode) noexcept { - assert(id); - assert(zoneDev); - assert(hostDev); - return coverException([&] { + IS_SET(id); + IS_SET(zoneDev); + IS_SET(hostDev); + mHostClient.callCreateNetdevMacvlan({ id, zoneDev, hostDev, mode }); }); } VsmStatus Client::vsm_create_netdev_phys(const char* id, const char* devId) noexcept { - assert(id); - assert(devId); - return coverException([&] { + IS_SET(id); + IS_SET(devId); + mHostClient.callCreateNetdevPhys({ id, devId }); }); } @@ -577,11 +661,11 @@ VsmStatus Client::vsm_lookup_netdev_by_name(const char* id, { using namespace boost::algorithm; - assert(id); - assert(netdevId); - assert(netdev); - return coverException([&] { + IS_SET(id); + IS_SET(netdevId); + IS_SET(netdev); + api::GetNetDevAttrs attrs; mHostClient.callGetNetdevAttrs({ id, netdevId }, attrs); auto it = find_if(attrs.values.begin(), @@ -610,10 +694,10 @@ VsmStatus Client::vsm_lookup_netdev_by_name(const char* id, VsmStatus Client::vsm_destroy_netdev(const char* id, const char* devId) noexcept { - assert(id); - assert(devId); - return coverException([&] { + IS_SET(id); + IS_SET(devId); + mHostClient.callDestroyNetdev({ id, devId }); }); } @@ -625,10 +709,10 @@ VsmStatus Client::vsm_declare_file(const char* id, mode_t mode, VsmString* declarationId) noexcept { - assert(id); - assert(path); - return coverException([&] { + IS_SET(id); + IS_SET(path); + api::Declaration declaration; mHostClient.callDeclareFile({ id, type, path, flags, (int)mode }, declaration); if (declarationId != NULL) { @@ -645,15 +729,15 @@ VsmStatus Client::vsm_declare_mount(const char *source, const char *data, VsmString* declarationId) noexcept { - assert(source); - assert(id); - assert(target); - assert(type); - if (!data) { - data = ""; - } - return coverException([&] { + IS_SET(source); + IS_SET(id); + IS_SET(target); + IS_SET(type); + if (!data) { + data = ""; + } + api::Declaration declaration; mHostClient.callDeclareMount({ source, id, target, type, flags, data }, declaration); if (declarationId != NULL) { @@ -667,11 +751,11 @@ VsmStatus Client::vsm_declare_link(const char* source, const char* target, VsmString* declarationId) noexcept { - assert(source); - assert(id); - assert(target); - return coverException([&] { + IS_SET(source); + IS_SET(id); + IS_SET(target); + api::Declaration declaration; mHostClient.callDeclareLink({ source, id, target }, declaration); if (declarationId != NULL) { @@ -682,10 +766,10 @@ VsmStatus Client::vsm_declare_link(const char* source, VsmStatus Client::vsm_list_declarations(const char* id, VsmArrayString* declarations) noexcept { - assert(id); - assert(declarations); - return coverException([&] { + IS_SET(id); + IS_SET(declarations); + api::Declarations declarationsOut; mHostClient.callGetDeclarations({ id }, declarationsOut); convert(declarationsOut, *declarations); @@ -694,10 +778,10 @@ VsmStatus Client::vsm_list_declarations(const char* id, VsmArrayString* declarat VsmStatus Client::vsm_remove_declaration(const char* id, VsmString declaration) noexcept { - assert(id); - assert(declaration); - return coverException([&] { + IS_SET(id); + IS_SET(declaration); + mHostClient.callRemoveDeclaration({ id, declaration }); }); } diff --git a/client/vasum-client-impl.hpp b/client/vasum-client-impl.hpp index 5a1d2fd..0ec3634 100644 --- a/client/vasum-client-impl.hpp +++ b/client/vasum-client-impl.hpp @@ -29,6 +29,11 @@ #include "vasum-client.h" #include "host-ipc-connection.hpp" +#include +#include + +#include +#include #include #include @@ -63,21 +68,44 @@ public: ~Client() noexcept; /** - * Create client with system dbus address. + * Connect client with system ipc address. * * @return status of this function call */ - VsmStatus createSystem() noexcept; - - ipc::epoll::EventPoll& getEventPoll() noexcept; + VsmStatus connectSystem() noexcept; /** - * Create client. + * Connect client. * - * @param address Dbus socket address + * @param address ipc socket address * @return status of this function call */ - VsmStatus create(const std::string& address) noexcept; + VsmStatus connect(const std::string& address) noexcept; + + /** + * Disconnect client + */ + VsmStatus disconnect() noexcept; + + /** + * @see ::vsm_get_poll_fd + */ + VsmStatus vsm_get_poll_fd(int* fd) noexcept; + + /** + * @see ::vsm_enter_eventloop + */ + VsmStatus vsm_enter_eventloop(int flags, int timeout) noexcept; + + /** + * @see ::vsm_set_dispatcher_type + */ + VsmStatus vsm_set_dispatcher_type(VsmDispacherType dispacher) noexcept; + + /** + * @see ::vsm_get_dispatcher_type + */ + VsmStatus vsm_get_dispatcher_type(VsmDispacherType* dispacher) noexcept; /** * @see ::vsm_get_status_message @@ -344,11 +372,15 @@ private: VsmStatus mVsmStatus; std::string mMsg; }; - Status mStatus; + mutable std::mutex mStatusMutex; + std::unique_ptr mInternalDispatcher; + std::unique_ptr mEventPoll; HostConnection mHostClient; + bool isInternalDispatcherEnabled() const; + ipc::epoll::EventPoll& getEventPoll() const; VsmStatus coverException(const std::function& worker) noexcept; VsmStatus vsm_netdev_get_ip_addr(const char* zone, const char* netdevId, diff --git a/client/vasum-client.cpp b/client/vasum-client.cpp index 1d5664c..f36c1ed 100644 --- a/client/vasum-client.cpp +++ b/client/vasum-client.cpp @@ -45,6 +45,26 @@ Client& getClient(VsmClient client) } // namespace +API VsmStatus vsm_get_poll_fd(VsmClient client, int* fd) +{ + return getClient(client).vsm_get_poll_fd(fd); +} + +API VsmStatus vsm_enter_eventloop(VsmClient client, int flags, int timeout) +{ + return getClient(client).vsm_enter_eventloop(flags, timeout); +} + +API VsmStatus vsm_set_dispatcher_type(VsmClient client, VsmDispacherType dispacher) +{ + return getClient(client).vsm_set_dispatcher_type(dispacher); +} + +API VsmStatus vsm_get_dispatcher_type(VsmClient client, VsmDispacherType* dispacher) +{ + return getClient(client).vsm_get_dispatcher_type(dispacher); +} + API VsmClient vsm_client_create() { Client* clientPtr = new(nothrow) Client(); @@ -53,12 +73,17 @@ API VsmClient vsm_client_create() API VsmStatus vsm_connect(VsmClient client) { - return getClient(client).createSystem(); + return getClient(client).connectSystem(); } API VsmStatus vsm_connect_custom(VsmClient client, const char* address) { - return getClient(client).create(address); + return getClient(client).connect(address); +} + +API VsmStatus vsm_disconnect(VsmClient client) +{ + return getClient(client).disconnect(); } API void vsm_array_string_free(VsmArrayString astring) diff --git a/client/vasum-client.h b/client/vasum-client.h index 7a98fa7..3832d23 100644 --- a/client/vasum-client.h +++ b/client/vasum-client.h @@ -180,9 +180,128 @@ typedef enum { VSMFILE_REGULAR } VsmFileType; +/** + * Event dispacher types. + * + * @par Example usage: + * @code +#include +#include +#include +#include +#include +#include + +volatile static sig_atomic_t running; +static int LOOP_INTERVAL = 1000; // ms + +void* main_loop(void* client) +{ + int fd = -1; + VsmStatus status = vsm_get_poll_fd(client, &fd); + assert(VSMCLIENT_SUCCESS == status); + + while (running) { + struct epoll_event event; + int num = epoll_wait(fd, &event, 1, LOOP_INTERVAL); + if (num > 0) { + status = vsm_enter_eventloop(client, 0 , 0); + assert(VSMCLIENT_SUCCESS == status); + } + } + return NULL; +} + +int main(int argc, char** argv) +{ + pthread_t loop; + VsmStatus status; + VsmClient client; + int ret = 0; + + client = vsm_client_create(); + assert(client); + + status = vsm_set_dispatcher_type(client, VSMDISPATCHER_EXTERNAL); + assert(VSMCLIENT_SUCCESS == status); + + status = vsm_connect(client); + assert(VSMCLIENT_SUCCESS == status); + + // start event loop + running = 1; + ret = pthread_create(&loop, NULL, main_loop, client); + assert(ret == 0); + + // make vsm_* calls on client + // ... + + status = vsm_disconnect(client); + assert(VSMCLIENT_SUCCESS == status); + + //stop event loop + running = 0; + ret = pthread_join(loop, NULL); + assert(ret == 0); + + vsm_client_free(client); // destroy client handle + return ret; +} + @endcode + */ +typedef enum { + VSMDISPATCHER_EXTERNAL, /**< User must handle dispatching messages */ + VSMDISPATCHER_INTERNAL /**< Library will take care of dispatching messages */ +} VsmDispacherType; + #ifndef __VASUM_WRAPPER_SOURCE__ /** + * Get file descriptor associated with event dispatcher of zone client + * + * The function vsm_get_poll_fd() returns the file descriptor associated with the event dispatcher of vsm client. + * The file descriptor can be bound to another I/O multiplexing facilities like epoll, select, and poll. + * + * @param[in] client vsm client + * @param[out] fd epoll file descriptor + * @return status of this function call +*/ +VsmStatus vsm_get_poll_fd(VsmClient client, int* fd); + +/** + * Wait for an I/O event on a vsm client + * + * vsm_enter_eventloop() waits for event on the vsm client + * + * The call waits for a maximum time of timout milliseconds. Specifying a timeout of -1 makes vsm_enter_eventloop() wait indefinitely, + * while specifying a timeout equal to zero makes vsm_enter_eventloop() to return immediately even if no events are available. + * + * @param[in] client vasum-server's client + * @param[in] flags Reserved + * @param[in] timeout Timeout time (milisecond), -1 is infinite + * @return status of this function call +*/ +VsmStatus vsm_enter_eventloop(VsmClient client, int flags, int timeout); + +/** + * Set dispatching method + * + * @param[in] client vasum-server's client + * @param[in] dispacher dispatching method + * @return status of this function call + */ +VsmStatus vsm_set_dispatcher_type(VsmClient client, VsmDispacherType dispacher); + +/** + * Get dispatching method + * + * @param[in] client vasum-server's client + * @param[out] dispacher dispatching method + * @return status of this function call + */ +VsmStatus vsm_get_dispatcher_type(VsmClient client, VsmDispacherType* dispacher); + +/** * Create a new vasum-server's client. * * @return Created client pointer or NULL on failure. @@ -230,6 +349,14 @@ VsmStatus vsm_connect(VsmClient client); VsmStatus vsm_connect_custom(VsmClient client, const char* address); /** + * Disconnect client from vasum-server. + * + * @param[in] client vasum-server's client + * @return status of this function call + */ +VsmStatus vsm_disconnect(VsmClient client); + +/** * Release VsmArrayString. * * @param[in] astring VsmArrayString diff --git a/tests/unit_tests/client/ut-client.cpp b/tests/unit_tests/client/ut-client.cpp index ce02a33..65d6e49 100644 --- a/tests/unit_tests/client/ut-client.cpp +++ b/tests/unit_tests/client/ut-client.cpp @@ -46,6 +46,8 @@ #include #include +#include + using namespace vasum; using namespace utils; @@ -55,6 +57,7 @@ const std::string TEST_CONFIG_PATH = VSM_TEST_CONFIG_INSTALL_DIR "/test-daemon.conf"; const std::string ZONES_PATH = "/tmp/ut-zones"; // the same as in daemon.conf const std::string TEMPLATE_NAME = "console-ipc"; +const int EVENT_TIMEOUT = 500; // ms struct Fixture { utils::ScopedDir mZonesPathGuard; @@ -83,6 +86,73 @@ struct Fixture { } }; +class SimpleEventLoop { +public: + SimpleEventLoop(VsmClient client) + : mClient(client) + , mIsProcessing(true) + , mThread([this] { loop(); }) + { + } + ~SimpleEventLoop() + { + mIsProcessing = false; + mThread.join(); + } + +private: + VsmClient mClient; + std::atomic_bool mIsProcessing; + std::thread mThread; + void loop() { + while (mIsProcessing) { + vsm_enter_eventloop(mClient, 0, EVENT_TIMEOUT); + } + } +}; + +class AggragatedEventLoop { +public: + AggragatedEventLoop() + : mIsProcessing(true) + , mThread([this] { loop(); }) + { + } + + ~AggragatedEventLoop() + { + mIsProcessing = false; + mThread.join(); + } + + VsmStatus addEventSource(VsmClient client) { + int fd = -1; + VsmStatus ret = vsm_get_poll_fd(client, &fd); + if (VSMCLIENT_SUCCESS != ret) { + return ret; + } + mEventPoll.addFD(fd, EPOLLIN | EPOLLHUP | EPOLLRDHUP, [client] (int, ipc::epoll::Events) { + vsm_enter_eventloop(client, 0, 0); + }); + mFds.push_back(fd); + return VSMCLIENT_SUCCESS; + } +private: + std::atomic_bool mIsProcessing; + std::thread mThread; + ipc::epoll::EventPoll mEventPoll; + std::vector mFds; + + void loop() { + while (mIsProcessing) { + mEventPoll.dispatchIteration(EVENT_TIMEOUT); + } + for (int fd : mFds) { + mEventPoll.removeFD(fd); + } + } +}; + const std::set EXPECTED_ZONES = { "zone1", "zone2", "zone3" }; void convertArrayToSet(VsmArrayString values, std::set& ret) @@ -103,6 +173,18 @@ int getArrayStringLength(VsmArrayString astring, int max_len = -1) return i; } +VsmStatus makeSimpleRequest(VsmClient client) +{ + BOOST_REQUIRE_EQUAL(VSMCLIENT_SUCCESS, vsm_connect(client)); + //make a simple call + VsmString zone = NULL; + VsmStatus status = vsm_get_active_zone_id(client, &zone); + vsm_string_free(zone); + // disconnect but not destroy + vsm_disconnect(client); + return status; +} + } // namespace // make nice BOOST_*_EQUAL output @@ -426,6 +508,75 @@ BOOST_AUTO_TEST_CASE(ZoneGetNetdevs) vsm_client_free(client); } +BOOST_AUTO_TEST_CASE(DefaultDispatcher) +{ + VsmClient client = vsm_client_create(); + + BOOST_CHECK_EQUAL(VSMCLIENT_SUCCESS, makeSimpleRequest(client)); + + vsm_client_free(client); +} + +BOOST_AUTO_TEST_CASE(SetDispatcher) +{ + VsmClient client = vsm_client_create(); + + BOOST_REQUIRE_EQUAL(VSMCLIENT_SUCCESS, vsm_set_dispatcher_type(client, VSMDISPATCHER_INTERNAL)); + BOOST_CHECK_EQUAL(VSMCLIENT_SUCCESS, makeSimpleRequest(client)); + + BOOST_REQUIRE_EQUAL(VSMCLIENT_SUCCESS, vsm_set_dispatcher_type(client, VSMDISPATCHER_EXTERNAL)); + { + SimpleEventLoop loop(client); + BOOST_CHECK_EQUAL(VSMCLIENT_SUCCESS, makeSimpleRequest(client)); + } + + BOOST_REQUIRE_EQUAL(VSMCLIENT_SUCCESS, vsm_set_dispatcher_type(client, VSMDISPATCHER_INTERNAL)); + BOOST_CHECK_EQUAL(VSMCLIENT_SUCCESS, makeSimpleRequest(client)); + + BOOST_REQUIRE_EQUAL(VSMCLIENT_SUCCESS, vsm_set_dispatcher_type(client, VSMDISPATCHER_EXTERNAL)); + { + SimpleEventLoop loop(client); + BOOST_CHECK_EQUAL(VSMCLIENT_SUCCESS, makeSimpleRequest(client)); + } + + BOOST_REQUIRE_EQUAL(VSMCLIENT_SUCCESS, vsm_set_dispatcher_type(client, VSMDISPATCHER_INTERNAL)); + BOOST_CHECK_EQUAL(VSMCLIENT_SUCCESS, makeSimpleRequest(client)); + + vsm_client_free(client); +} + +BOOST_AUTO_TEST_CASE(GetPollFd) +{ + VsmClient client1 = vsm_client_create(); + VsmClient client2 = vsm_client_create(); + + BOOST_REQUIRE_EQUAL(VSMCLIENT_SUCCESS, vsm_set_dispatcher_type(client1, VSMDISPATCHER_EXTERNAL)); + BOOST_REQUIRE_EQUAL(VSMCLIENT_SUCCESS, vsm_set_dispatcher_type(client2, VSMDISPATCHER_EXTERNAL)); + { + AggragatedEventLoop loop; + BOOST_CHECK_EQUAL(VSMCLIENT_SUCCESS, loop.addEventSource(client1)); + BOOST_CHECK_EQUAL(VSMCLIENT_SUCCESS, loop.addEventSource(client2)); + + BOOST_REQUIRE_EQUAL(VSMCLIENT_SUCCESS, vsm_connect(client1)); + BOOST_REQUIRE_EQUAL(VSMCLIENT_SUCCESS, vsm_connect(client2)); + + VsmString zone; + //make a simple call + zone = NULL; + BOOST_CHECK_EQUAL(VSMCLIENT_SUCCESS, vsm_get_active_zone_id(client1, &zone)); + vsm_string_free(zone); + zone = NULL; + BOOST_CHECK_EQUAL(VSMCLIENT_SUCCESS, vsm_get_active_zone_id(client2, &zone)); + vsm_string_free(zone); + + // disconnect but not destroy + vsm_disconnect(client1); + vsm_disconnect(client2); + } + vsm_client_free(client1); + vsm_client_free(client2); +} + //TODO: We need createBridge from vasum::netdev //BOOST_AUTO_TEST_CASE(CreateDestroyNetdev) //BOOST_AUTO_TEST_CASE(LookupNetdev) diff --git a/wrapper/wrapper.cpp b/wrapper/wrapper.cpp index 8b890cf..a975087 100644 --- a/wrapper/wrapper.cpp +++ b/wrapper/wrapper.cpp @@ -151,7 +151,7 @@ static int wrap_error(VsmStatus st, const Client *c) static void init_context_wrap(WrappedContext *w) { w->client = new Client(); - VsmStatus st = w->client->createSystem(); + VsmStatus st = w->client->connectSystem(); wrap_error(st, w->client); memset(&w->hq_ctx, 0, sizeof(w->hq_ctx)); -- 2.7.4 From 79631baa5d339646cdf2398b1aad67067db3f353 Mon Sep 17 00:00:00 2001 From: Mateusz Malicki Date: Tue, 9 Jun 2015 16:14:42 +0200 Subject: [PATCH 05/16] Remove HostIpcConnection class [Bug] Unnecessary HostIpcConnection class (ipc wrapper) [Cause] N/A [Solution] N/A [Verification] run ClientSuite tests Change-Id: Ic2a3973593e3bec1d64715976c44ec460f66ee21 --- client/host-ipc-connection.cpp | 274 ----------------------------------------- client/host-ipc-connection.hpp | 89 ------------- client/vasum-client-impl.cpp | 179 +++++++++++++++++++-------- client/vasum-client-impl.hpp | 6 +- 4 files changed, 132 insertions(+), 416 deletions(-) delete mode 100644 client/host-ipc-connection.cpp delete mode 100644 client/host-ipc-connection.hpp diff --git a/client/host-ipc-connection.cpp b/client/host-ipc-connection.cpp deleted file mode 100644 index a58e0d7..0000000 --- a/client/host-ipc-connection.cpp +++ /dev/null @@ -1,274 +0,0 @@ -/* - * Copyright (c) 2015 Samsung Electronics Co., Ltd All Rights Reserved - * - * Contact: Mateusz Malicki - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License - */ - - -/** - * @file - * @author Mateusz Malicki (m.malicki2@samsung.com) - * @brief HostIPCConnection class - */ - -#include -#include "host-ipc-connection.hpp" -#include -#include - -namespace vasum { -namespace client { - -namespace { - const int TIMEOUT_INFINITE = -1; -} //namespace - -void HostIPCConnection::connect(const std::string& address, ipc::epoll::EventPoll& eventPoll) -{ - mClient.reset(new ipc::Client(eventPoll, address)); - mClient->start(); -} - -void HostIPCConnection::disconnect() -{ - mClient.reset(); -} - -bool HostIPCConnection::isConnected() -{ - return mClient && mClient->isStarted(); -} - - -void HostIPCConnection::callGetZoneIds(api::ZoneIds& argOut) -{ - argOut = *mClient->callSync( - api::ipc::METHOD_GET_ZONE_ID_LIST, - std::make_shared()); -} - -void HostIPCConnection::callGetActiveZoneId(api::ZoneId& argOut) -{ - argOut = *mClient->callSync( - api::ipc::METHOD_GET_ACTIVE_ZONE_ID, - std::make_shared()); -} - -void HostIPCConnection::callSetActiveZone(const api::ZoneId& argIn) -{ - mClient->callSync( - api::ipc::METHOD_SET_ACTIVE_ZONE, - std::make_shared(argIn)); -} - -void HostIPCConnection::callGetZoneInfo(const api::ZoneId& argIn, api::ZoneInfoOut& argOut) -{ - argOut = *mClient->callSync( - api::ipc::METHOD_GET_ZONE_INFO, - std::make_shared(argIn)); -} - -void HostIPCConnection::callSetNetdevAttrs(const api::SetNetDevAttrsIn& argIn) -{ - mClient->callSync( - api::ipc::METHOD_SET_NETDEV_ATTRS, - std::make_shared(argIn)); -} - -void HostIPCConnection::callGetNetdevAttrs(const api::GetNetDevAttrsIn& argIn, api::GetNetDevAttrs& argOut) -{ - argOut = *mClient->callSync( - api::ipc::METHOD_GET_NETDEV_ATTRS, - std::make_shared(argIn)); -} - -void HostIPCConnection::callGetNetdevList(const api::ZoneId& argIn, api::NetDevList& argOut) -{ - argOut = *mClient->callSync( - api::ipc::METHOD_GET_NETDEV_LIST, - std::make_shared(argIn)); -} - -void HostIPCConnection::callCreateNetdevVeth(const api::CreateNetDevVethIn& argIn) -{ - mClient->callSync( - api::ipc::METHOD_CREATE_NETDEV_VETH, - std::make_shared(argIn)); -} - -void HostIPCConnection::callCreateNetdevMacvlan(const api::CreateNetDevMacvlanIn& argIn) -{ - mClient->callSync( - api::ipc::METHOD_CREATE_NETDEV_MACVLAN, - std::make_shared(argIn)); -} - -void HostIPCConnection::callCreateNetdevPhys(const api::CreateNetDevPhysIn& argIn) -{ - mClient->callSync( - api::ipc::METHOD_CREATE_NETDEV_PHYS, - std::make_shared(argIn)); -} - -void HostIPCConnection::callDestroyNetdev(const api::DestroyNetDevIn& argIn) -{ - mClient->callSync( - api::ipc::METHOD_DESTROY_NETDEV, - std::make_shared(argIn)); -} - -void HostIPCConnection::callDeleteNetdevIpAddress(const api::DeleteNetdevIpAddressIn& argIn) -{ - mClient->callSync( - api::ipc::METHOD_DELETE_NETDEV_IP_ADDRESS, - std::make_shared(argIn)); -} - -void HostIPCConnection::callDeclareFile(const api::DeclareFileIn& argIn, api::Declaration& argOut) -{ - argOut = *mClient->callSync( - api::ipc::METHOD_DECLARE_FILE, - std::make_shared(argIn)); -} - -void HostIPCConnection::callDeclareMount(const api::DeclareMountIn& argIn, api::Declaration& argOut) -{ - argOut = *mClient->callSync( - api::ipc::METHOD_DECLARE_MOUNT, - std::make_shared(argIn)); -} - -void HostIPCConnection::callDeclareLink(const api::DeclareLinkIn& argIn, api::Declaration& argOut) -{ - argOut = *mClient->callSync( - api::ipc::METHOD_DECLARE_LINK, - std::make_shared(argIn)); -} - -void HostIPCConnection::callGetDeclarations(const api::ZoneId& argIn, api::Declarations& argOut) -{ - argOut = *mClient->callSync( - api::ipc::METHOD_GET_DECLARATIONS, - std::make_shared(argIn)); -} - -void HostIPCConnection::callRemoveDeclaration(const api::RemoveDeclarationIn& argIn) -{ - mClient->callSync( - api::ipc::METHOD_REMOVE_DECLARATION, - std::make_shared(argIn)); -} - -void HostIPCConnection::callCreateZone(const api::CreateZoneIn& argIn) -{ - mClient->callSync( - api::ipc::METHOD_CREATE_ZONE, - std::make_shared(argIn), - TIMEOUT_INFINITE); -} - -void HostIPCConnection::callDestroyZone(const api::ZoneId& argIn) -{ - mClient->callSync( - api::ipc::METHOD_DESTROY_ZONE, - std::make_shared(argIn), - TIMEOUT_INFINITE); -} - -void HostIPCConnection::callShutdownZone(const api::ZoneId& argIn) -{ - mClient->callSync( - api::ipc::METHOD_SHUTDOWN_ZONE, - std::make_shared(argIn), - TIMEOUT_INFINITE); -} - -void HostIPCConnection::callStartZone(const api::ZoneId& argIn) -{ - mClient->callSync( - api::ipc::METHOD_START_ZONE, - std::make_shared(argIn), - TIMEOUT_INFINITE); -} - -void HostIPCConnection::callLockZone(const api::ZoneId& argIn) -{ - mClient->callSync( - api::ipc::METHOD_LOCK_ZONE, - std::make_shared(argIn), - TIMEOUT_INFINITE); -} - -void HostIPCConnection::callUnlockZone(const api::ZoneId& argIn) -{ - mClient->callSync( - api::ipc::METHOD_UNLOCK_ZONE, - std::make_shared(argIn)); -} - -void HostIPCConnection::callGrantDevice(const api::GrantDeviceIn& argIn) -{ - mClient->callSync( - api::ipc::METHOD_GRANT_DEVICE, - std::make_shared(argIn)); -} - -void HostIPCConnection::callRevokeDevice(const api::RevokeDeviceIn& argIn) -{ - mClient->callSync( - api::ipc::METHOD_REVOKE_DEVICE, - std::make_shared(argIn)); -} - -void HostIPCConnection::callNotifyActiveZone(const api::NotifActiveZoneIn& argIn) -{ - mClient->callSync( - api::ipc::METHOD_NOTIFY_ACTIVE_ZONE, - std::make_shared(argIn)); -} - -void HostIPCConnection::callFileMoveRequest(const api::FileMoveRequestIn& argIn, - api::FileMoveRequestStatus& argOut) -{ - argOut = *mClient->callSync( - api::ipc::METHOD_FILE_MOVE_REQUEST, - std::make_shared(argIn)); -} - -void HostIPCConnection::signalSwitchToDefault() -{ - - mClient->signal(api::ipc::SIGNAL_SWITCH_TO_DEFAULT, - std::make_shared()); -} - -HostIPCConnection::SubscriptionId -HostIPCConnection::subscribeNotification(const NotificationCallback& callback) -{ - auto callbackWrapper = [callback] (const ipc::PeerID, - std::shared_ptr& data) { - callback(*data); - }; - mClient->setSignalHandler(api::ipc::SIGNAL_NOTIFICATION, callbackWrapper); - return api::ipc::SIGNAL_NOTIFICATION; -} - -void HostIPCConnection::unsubscribe(const SubscriptionId& id) -{ - mClient->removeMethod(id); -} - -} // namespace client -} // namespace vasum diff --git a/client/host-ipc-connection.hpp b/client/host-ipc-connection.hpp deleted file mode 100644 index 16a2a9e..0000000 --- a/client/host-ipc-connection.hpp +++ /dev/null @@ -1,89 +0,0 @@ -/* - * Copyright (c) 2015 Samsung Electronics Co., Ltd All Rights Reserved - * - * Contact: Mateusz Malicki - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License - */ - - -/** - * @file - * @author Mateusz Malicki (m.malicki2@samsung.com) - * @brief HostIPCConnection class - */ - -#ifndef VASUM_CLIENT_HOST_IPC_CONNECTION_HPP -#define VASUM_CLIENT_HOST_IPC_CONNECTION_HPP - -#include -#include -#include - -#include - -namespace vasum { -namespace client { - -/** - * HostIPCConnection is used for communication with the vasum's server from host through ipc - */ -class HostIPCConnection { -public: - typedef unsigned int SubscriptionId; - typedef std::function NotificationCallback; - void connect(const std::string& address, ipc::epoll::EventPoll& eventPoll); - void disconnect(); - bool isConnected(); - - void callGetZoneIds(vasum::api::ZoneIds& argOut); - void callGetActiveZoneId(vasum::api::ZoneId& argOut); - void callSetActiveZone(const vasum::api::ZoneId& argIn); - void callGetZoneInfo(const vasum::api::ZoneId& argIn, vasum::api::ZoneInfoOut& argOut); - void callSetNetdevAttrs(const vasum::api::SetNetDevAttrsIn& argIn); - void callGetNetdevAttrs(const vasum::api::GetNetDevAttrsIn& argIn, vasum::api::GetNetDevAttrs& argOut); - void callGetNetdevList(const vasum::api::ZoneId& argIn, vasum::api::NetDevList& argOut); - void callCreateNetdevVeth(const vasum::api::CreateNetDevVethIn& argIn); - void callCreateNetdevMacvlan(const vasum::api::CreateNetDevMacvlanIn& argIn); - void callCreateNetdevPhys(const vasum::api::CreateNetDevPhysIn& argIn); - void callDestroyNetdev(const vasum::api::DestroyNetDevIn& argIn); - void callDeleteNetdevIpAddress(const vasum::api::DeleteNetdevIpAddressIn& argIn); - void callDeclareFile(const vasum::api::DeclareFileIn& argIn, vasum::api::Declaration& argOut); - void callDeclareMount(const vasum::api::DeclareMountIn& argIn, vasum::api::Declaration& argOut); - void callDeclareLink(const vasum::api::DeclareLinkIn& argIn, vasum::api::Declaration& argOut); - void callGetDeclarations(const vasum::api::ZoneId& argIn, vasum::api::Declarations& argOut); - void callRemoveDeclaration(const vasum::api::RemoveDeclarationIn& argIn); - void callCreateZone(const vasum::api::CreateZoneIn& argIn); - void callDestroyZone(const vasum::api::ZoneId& argIn); - void callShutdownZone(const vasum::api::ZoneId& argIn); - void callStartZone(const vasum::api::ZoneId& argIn); - void callLockZone(const vasum::api::ZoneId& argIn); - void callUnlockZone(const vasum::api::ZoneId& argIn); - void callGrantDevice(const vasum::api::GrantDeviceIn& argIn); - void callRevokeDevice(const vasum::api::RevokeDeviceIn& argIn); - void callGetZoneConnections(vasum::api::Connections& argOut); - void callNotifyActiveZone(const vasum::api::NotifActiveZoneIn& argIn); - void callFileMoveRequest(const vasum::api::FileMoveRequestIn& argIn, - vasum::api::FileMoveRequestStatus& argOut); - void signalSwitchToDefault(); - SubscriptionId subscribeNotification(const NotificationCallback& callback); - void unsubscribe(const SubscriptionId& id); - -private: - std::unique_ptr mClient; -}; - -} // namespace client -} // namespace vasum - -#endif /* VASUM_CLIENT_HOST_IPC_CONNECTION_HPP */ diff --git a/client/vasum-client-impl.cpp b/client/vasum-client-impl.cpp index 97cd004..f9a15b8 100644 --- a/client/vasum-client-impl.cpp +++ b/client/vasum-client-impl.cpp @@ -33,11 +33,15 @@ #include "utils.hpp" #include "exception.hpp" #include "utils/exception.hpp" -#include "host-ipc-connection.hpp" #include "logger/logger.hpp" +#include +#include +#include + #include #include +#include #include #include #include @@ -52,6 +56,8 @@ using namespace vasum; namespace { +const int TIMEOUT_INFINITE = -1; + VsmZoneState getZoneState(const char* state) { if (strcmp(state, "STOPPED") == 0) { @@ -154,6 +160,11 @@ Client::~Client() noexcept { } +bool Client::isConnected() const +{ + return mClient && mClient->isStarted(); +} + bool Client::isInternalDispatcherEnabled() const { return static_cast(mInternalDispatcher); @@ -211,14 +222,15 @@ VsmStatus Client::connect(const std::string& address) noexcept if (!mInternalDispatcher && !mEventPoll) { vsm_set_dispatcher_type(VSMDISPATCHER_INTERNAL); } - mHostClient.connect(address, getEventPoll()); + mClient.reset(new ipc::Client(getEventPoll(), address)); + mClient->start(); }); } VsmStatus Client::disconnect() noexcept { return coverException([&] { - mHostClient.disconnect(); + mClient.reset(); }); } @@ -246,7 +258,7 @@ VsmStatus Client::vsm_enter_eventloop(int /* flags */, int timeout) noexcept VsmStatus Client::vsm_set_dispatcher_type(VsmDispacherType dispacher) noexcept { return coverException([&] { - if (mHostClient.isConnected()) { + if (isConnected()) { throw OperationFailedException("Can't change dispacher"); } switch (dispacher) { @@ -301,8 +313,9 @@ VsmStatus Client::vsm_get_zone_ids(VsmArrayString* array) noexcept return coverException([&] { IS_SET(array); - api::ZoneIds zoneIds; - mHostClient.callGetZoneIds(zoneIds); + api::ZoneIds zoneIds = *mClient->callSync( + vasum::api::ipc::METHOD_GET_ZONE_ID_LIST, + std::make_shared()); convert(zoneIds, *array); }); } @@ -312,8 +325,9 @@ VsmStatus Client::vsm_get_active_zone_id(VsmString* id) noexcept return coverException([&] { IS_SET(id); - api::ZoneId zoneId; - mHostClient.callGetActiveZoneId(zoneId); + api::ZoneId zoneId = *mClient->callSync( + api::ipc::METHOD_GET_ACTIVE_ZONE_ID, + std::make_shared()); *id = ::strdup(zoneId.value.c_str()); }); } @@ -324,8 +338,9 @@ VsmStatus Client::vsm_get_zone_rootpath(const char* id, VsmString* rootpath) noe IS_SET(id); IS_SET(rootpath); - api::ZoneInfoOut info; - mHostClient.callGetZoneInfo({ id }, info); + api::ZoneInfoOut info = *mClient->callSync( + api::ipc::METHOD_GET_ZONE_INFO, + std::make_shared(api::ZoneId{ id })); *rootpath = ::strdup(info.rootPath.c_str()); }); } @@ -357,8 +372,9 @@ VsmStatus Client::vsm_lookup_zone_by_id(const char* id, VsmZone* zone) noexcept IS_SET(id); IS_SET(zone); - api::ZoneInfoOut info; - mHostClient.callGetZoneInfo({ id }, info); + api::ZoneInfoOut info = *mClient->callSync( + api::ipc::METHOD_GET_ZONE_INFO, + std::make_shared(api::ZoneId{ id })); convert(info, *zone); }); } @@ -376,7 +392,9 @@ VsmStatus Client::vsm_set_active_zone(const char* id) noexcept return coverException([&] { IS_SET(id); - mHostClient.callSetActiveZone({ id }); + mClient->callSync( + api::ipc::METHOD_SET_ACTIVE_ZONE, + std::make_shared(api::ZoneId{ id })); }); } @@ -386,7 +404,10 @@ VsmStatus Client::vsm_create_zone(const char* id, const char* tname) noexcept IS_SET(id); string template_name = tname ? tname : "default"; - mHostClient.callCreateZone({ id, template_name }); + mClient->callSync( + api::ipc::METHOD_CREATE_ZONE, + std::make_shared(api::CreateZoneIn{ id, template_name }), + TIMEOUT_INFINITE); }); } @@ -394,7 +415,10 @@ VsmStatus Client::vsm_destroy_zone(const char* id) noexcept { return coverException([&] { IS_SET(id); - mHostClient.callDestroyZone({ id }); + mClient->callSync( + api::ipc::METHOD_DESTROY_ZONE, + std::make_shared(api::ZoneId{ id }), + TIMEOUT_INFINITE); }); } @@ -402,7 +426,10 @@ VsmStatus Client::vsm_shutdown_zone(const char* id) noexcept { return coverException([&] { IS_SET(id); - mHostClient.callShutdownZone({ id }); + mClient->callSync( + api::ipc::METHOD_SHUTDOWN_ZONE, + std::make_shared(api::ZoneId{ id }), + TIMEOUT_INFINITE); }); } @@ -410,7 +437,10 @@ VsmStatus Client::vsm_start_zone(const char* id) noexcept { return coverException([&] { IS_SET(id); - mHostClient.callStartZone({ id }); + mClient->callSync( + api::ipc::METHOD_START_ZONE, + std::make_shared(api::ZoneId{ id }), + TIMEOUT_INFINITE); }); } @@ -418,7 +448,10 @@ VsmStatus Client::vsm_lock_zone(const char* id) noexcept { return coverException([&] { IS_SET(id); - mHostClient.callLockZone({ id }); + mClient->callSync( + api::ipc::METHOD_LOCK_ZONE, + std::make_shared(api::ZoneId{ id }), + TIMEOUT_INFINITE); }); } @@ -426,7 +459,9 @@ VsmStatus Client::vsm_unlock_zone(const char* id) noexcept { return coverException([&] { IS_SET(id); - mHostClient.callUnlockZone({ id }); + mClient->callSync( + api::ipc::METHOD_UNLOCK_ZONE, + std::make_shared(api::ZoneId{ id })); }); } @@ -443,7 +478,7 @@ VsmStatus Client::vsm_add_state_callback(VsmZoneDbusStateFunction /* zoneDbusSta VsmStatus Client::vsm_del_state_callback(VsmSubscriptionId subscriptionId) noexcept { return coverException([&] { - mHostClient.unsubscribe(subscriptionId); + mClient->removeMethod(subscriptionId); }); } @@ -453,7 +488,9 @@ VsmStatus Client::vsm_grant_device(const char* id, const char* device, uint32_t IS_SET(id); IS_SET(device); - mHostClient.callGrantDevice({ id, device, flags }); + mClient->callSync( + api::ipc::METHOD_GRANT_DEVICE, + std::make_shared(api::GrantDeviceIn{ id, device, flags })); }); } @@ -463,7 +500,9 @@ VsmStatus Client::vsm_revoke_device(const char* id, const char* device) noexcept IS_SET(id); IS_SET(device); - mHostClient.callRevokeDevice({ id, device }); + mClient->callSync( + api::ipc::METHOD_REVOKE_DEVICE, + std::make_shared(api::RevokeDeviceIn{ id, device })); }); } @@ -473,8 +512,9 @@ VsmStatus Client::vsm_zone_get_netdevs(const char* id, VsmArrayString* netdevIds IS_SET(id); IS_SET(netdevIds); - api::NetDevList netdevs; - mHostClient.callGetNetdevList({ id }, netdevs); + api::NetDevList netdevs = *mClient->callSync( + api::ipc::METHOD_GET_NETDEV_LIST, + std::make_shared(api::ZoneId{ id })); convert(netdevs, *netdevIds); }); } @@ -491,8 +531,9 @@ VsmStatus Client::vsm_netdev_get_ip_addr(const char* id, IS_SET(netdevId); IS_SET(addr); - api::GetNetDevAttrs attrs; - mHostClient.callGetNetdevAttrs({ id, netdevId }, attrs); + api::GetNetDevAttrs attrs = *mClient->callSync( + api::ipc::METHOD_GET_NETDEV_ATTRS, + std::make_shared(api::GetNetDevAttrsIn{ id, netdevId })); auto it = find_if(attrs.values.begin(), attrs.values.end(), @@ -544,7 +585,10 @@ VsmStatus Client::vsm_netdev_set_ipv4_addr(const char* id, IS_SET(addr); string value = "ip:" + toString(addr) + ",""prefixlen:" + to_string(prefix); - mHostClient.callSetNetdevAttrs({ id, netdevId, { { "ipv4", value } } } ); + mClient->callSync( + api::ipc::METHOD_SET_NETDEV_ATTRS, + std::make_shared( + api::SetNetDevAttrsIn{ id, netdevId, { { "ipv4", value } } })); }); } @@ -559,7 +603,10 @@ VsmStatus Client::vsm_netdev_set_ipv6_addr(const char* id, IS_SET(addr); string value = "ip:" + toString(addr) + ",""prefixlen:" + to_string(prefix); - mHostClient.callSetNetdevAttrs({ id, netdevId, { { "ipv6", value } } } ); + mClient->callSync( + api::ipc::METHOD_SET_NETDEV_ATTRS, + std::make_shared( + api::SetNetDevAttrsIn{ id, netdevId, { { "ipv6", value } } })); }); } @@ -575,7 +622,10 @@ VsmStatus Client::vsm_netdev_del_ipv4_addr(const char* id, //CIDR notation string ip = toString(addr) + "/" + to_string(prefix); - mHostClient.callDeleteNetdevIpAddress({ id, netdevId, ip }); + mClient->callSync( + api::ipc::METHOD_DELETE_NETDEV_IP_ADDRESS, + std::make_shared( + api::DeleteNetdevIpAddressIn{ id, netdevId, ip })); }); } @@ -591,7 +641,10 @@ VsmStatus Client::vsm_netdev_del_ipv6_addr(const char* id, //CIDR notation string ip = toString(addr) + "/" + to_string(prefix); - mHostClient.callDeleteNetdevIpAddress({ id, netdevId, ip }); + mClient->callSync( + api::ipc::METHOD_DELETE_NETDEV_IP_ADDRESS, + std::make_shared( + api::DeleteNetdevIpAddressIn{ id, netdevId, ip })); }); } @@ -602,8 +655,11 @@ VsmStatus Client::vsm_netdev_up(const char* id, const char* netdevId) noexcept IS_SET(id); IS_SET(netdevId); - mHostClient.callSetNetdevAttrs({ id, netdevId, { { "flags", to_string(IFF_UP) }, - { "change", to_string(IFF_UP) } } } ); + mClient->callSync( + api::ipc::METHOD_SET_NETDEV_ATTRS, + std::make_shared( + api::SetNetDevAttrsIn{ id, netdevId, { { "flags", to_string(IFF_UP) }, + { "change", to_string(IFF_UP) } } })); }); } @@ -613,8 +669,11 @@ VsmStatus Client::vsm_netdev_down(const char* id, const char* netdevId) noexcept IS_SET(id); IS_SET(netdevId); - mHostClient.callSetNetdevAttrs({ id, netdevId, { { "flags", to_string(~IFF_UP) }, - { "change", to_string(IFF_UP) } } } ); + mClient->callSync( + api::ipc::METHOD_SET_NETDEV_ATTRS, + std::make_shared( + api::SetNetDevAttrsIn{ id, netdevId, { { "flags", to_string(~IFF_UP) }, + { "change", to_string(IFF_UP) } } })); }); } @@ -627,7 +686,10 @@ VsmStatus Client::vsm_create_netdev_veth(const char* id, IS_SET(zoneDev); IS_SET(hostDev); - mHostClient.callCreateNetdevVeth({ id, zoneDev, hostDev }); + mClient->callSync( + api::ipc::METHOD_CREATE_NETDEV_VETH, + std::make_shared( + api::CreateNetDevVethIn{ id, zoneDev, hostDev })); }); } @@ -641,7 +703,10 @@ VsmStatus Client::vsm_create_netdev_macvlan(const char* id, IS_SET(zoneDev); IS_SET(hostDev); - mHostClient.callCreateNetdevMacvlan({ id, zoneDev, hostDev, mode }); + mClient->callSync( + api::ipc::METHOD_CREATE_NETDEV_MACVLAN, + std::make_shared( + api::CreateNetDevMacvlanIn{ id, zoneDev, hostDev, mode })); }); } @@ -651,7 +716,10 @@ VsmStatus Client::vsm_create_netdev_phys(const char* id, const char* devId) noex IS_SET(id); IS_SET(devId); - mHostClient.callCreateNetdevPhys({ id, devId }); + mClient->callSync( + api::ipc::METHOD_CREATE_NETDEV_PHYS, + std::make_shared( + api::CreateNetDevPhysIn{ id, devId })); }); } @@ -666,8 +734,9 @@ VsmStatus Client::vsm_lookup_netdev_by_name(const char* id, IS_SET(netdevId); IS_SET(netdev); - api::GetNetDevAttrs attrs; - mHostClient.callGetNetdevAttrs({ id, netdevId }, attrs); + api::GetNetDevAttrs attrs = *mClient->callSync( + api::ipc::METHOD_GET_NETDEV_ATTRS, + std::make_shared(api::GetNetDevAttrsIn{ id, netdevId })); auto it = find_if(attrs.values.begin(), attrs.values.end(), [](const api::StringPair& entry) { @@ -698,7 +767,9 @@ VsmStatus Client::vsm_destroy_netdev(const char* id, const char* devId) noexcept IS_SET(id); IS_SET(devId); - mHostClient.callDestroyNetdev({ id, devId }); + mClient->callSync( + api::ipc::METHOD_DESTROY_NETDEV, + std::make_shared(api::DestroyNetDevIn{ id, devId })); }); } @@ -713,8 +784,10 @@ VsmStatus Client::vsm_declare_file(const char* id, IS_SET(id); IS_SET(path); - api::Declaration declaration; - mHostClient.callDeclareFile({ id, type, path, flags, (int)mode }, declaration); + api::Declaration declaration = *mClient->callSync( + api::ipc::METHOD_DECLARE_FILE, + std::make_shared( + api::DeclareFileIn{ id, type, path, flags, (int)mode })); if (declarationId != NULL) { *declarationId = ::strdup(declaration.value.c_str()); } @@ -738,8 +811,10 @@ VsmStatus Client::vsm_declare_mount(const char *source, data = ""; } - api::Declaration declaration; - mHostClient.callDeclareMount({ source, id, target, type, flags, data }, declaration); + api::Declaration declaration = *mClient->callSync( + api::ipc::METHOD_DECLARE_MOUNT, + std::make_shared( + api::DeclareMountIn{ source, id, target, type, flags, data })); if (declarationId != NULL) { *declarationId = ::strdup(declaration.value.c_str()); } @@ -756,8 +831,9 @@ VsmStatus Client::vsm_declare_link(const char* source, IS_SET(id); IS_SET(target); - api::Declaration declaration; - mHostClient.callDeclareLink({ source, id, target }, declaration); + api::Declaration declaration = *mClient->callSync( + api::ipc::METHOD_DECLARE_LINK, + std::make_shared(api::DeclareLinkIn{ source, id, target })); if (declarationId != NULL) { *declarationId = ::strdup(declaration.value.c_str()); } @@ -770,8 +846,9 @@ VsmStatus Client::vsm_list_declarations(const char* id, VsmArrayString* declarat IS_SET(id); IS_SET(declarations); - api::Declarations declarationsOut; - mHostClient.callGetDeclarations({ id }, declarationsOut); + api::Declarations declarationsOut = *mClient->callSync( + api::ipc::METHOD_GET_DECLARATIONS, + std::make_shared(api::ZoneId{ id })); convert(declarationsOut, *declarations); }); } @@ -782,7 +859,9 @@ VsmStatus Client::vsm_remove_declaration(const char* id, VsmString declaration) IS_SET(id); IS_SET(declaration); - mHostClient.callRemoveDeclaration({ id, declaration }); + mClient->callSync( + api::ipc::METHOD_REMOVE_DECLARATION, + std::make_shared(api::RemoveDeclarationIn{ id, declaration })); }); } @@ -815,7 +894,7 @@ VsmStatus Client::vsm_add_notification_callback(VsmNotificationFunction /*notifi VsmStatus Client::vsm_del_notification_callback(VsmSubscriptionId subscriptionId) noexcept { return coverException([&] { - mHostClient.unsubscribe(subscriptionId); + mClient->removeMethod(subscriptionId); }); } diff --git a/client/vasum-client-impl.hpp b/client/vasum-client-impl.hpp index 0ec3634..854c32c 100644 --- a/client/vasum-client-impl.hpp +++ b/client/vasum-client-impl.hpp @@ -27,10 +27,10 @@ #define VASUM_CLIENT_IMPL_HPP #include "vasum-client.h" -#include "host-ipc-connection.hpp" #include #include +#include #include #include @@ -365,7 +365,6 @@ public: VsmStatus vsm_del_notification_callback(VsmSubscriptionId subscriptionId) noexcept; private: - typedef vasum::client::HostIPCConnection HostConnection; struct Status { Status(); Status(VsmStatus status, const std::string& msg = ""); @@ -377,8 +376,9 @@ private: mutable std::mutex mStatusMutex; std::unique_ptr mInternalDispatcher; std::unique_ptr mEventPoll; - HostConnection mHostClient; + std::unique_ptr mClient; + bool isConnected() const; bool isInternalDispatcherEnabled() const; ipc::epoll::EventPoll& getEventPoll() const; VsmStatus coverException(const std::function& worker) noexcept; -- 2.7.4 From 0a2e632556e9030bf79ee405a53cad67164a8c95 Mon Sep 17 00:00:00 2001 From: Jan Olszak Date: Wed, 17 Jun 2015 13:25:08 +0200 Subject: [PATCH 06/16] Vasum's logo and icons [Bug] N/A [Cause] N/A [Solution] N/A [Verification] N/A Change-Id: I65f0288aa398674b4c1307f9f52255218caf7922 --- images/icon-big.png | Bin 0 -> 169731 bytes images/icon-small.png | Bin 0 -> 17046 bytes images/logo-dark.png | Bin 0 -> 64164 bytes images/logo-light.png | Bin 0 -> 69365 bytes images/logo-white.png | Bin 0 -> 63912 bytes images/vasum-logo-main.png | Bin 0 -> 69332 bytes 6 files changed, 0 insertions(+), 0 deletions(-) create mode 100644 images/icon-big.png create mode 100644 images/icon-small.png create mode 100644 images/logo-dark.png create mode 100644 images/logo-light.png create mode 100644 images/logo-white.png create mode 100644 images/vasum-logo-main.png diff --git a/images/icon-big.png b/images/icon-big.png new file mode 100644 index 0000000000000000000000000000000000000000..db235f4276c64af98f81b03c2d98db9c7cd1f6bc GIT binary patch literal 169731 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 z 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%0DaFPZEM!DH#%vlOSQOFSTTZp&p&&%}IO$ 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�iy)ct**_my0_S2zVmQ1n=*H!2MPwk* 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⪙7q96=;K}E=QFYce0%y1fMwYZ8Lcj|mR+kAA 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%0AeeMHd+t0jOe`&TYI0nl%9 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 FV1i1UZ%qII literal 0 HcmV?d00001 diff --git a/images/logo-dark.png b/images/logo-dark.png new file mode 100644 index 0000000000000000000000000000000000000000..59775eb4e11f96d56c648866165603a847338218 GIT binary patch literal 64164 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

llb45YIGd`#52z6l;6!HTuq`_-yvYv*a0{5Hrx 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⋘b;(r^_<0XMv7b7C@LY0Z0G zUYeK-`Eu9gX1*7)=r60@B2Ih4f>^b{xrP7bhf{ht&WtVd3fQHS5Z!O^IKytd zTyowtU95W3|Lj5KhIebu`Ha{)J(ri-=29*zOCGMR57+WsbOC4vQZtM^=){(q%kku- z_+E`Zh4~DbYD2Z#74Pr+8|XaKQe!SW_^JJCD5|)W5l_C`KCi^2#*SU~R}uPjp~Wbq zpU|yFx~Kn4*uZa4;^3__(KQ(Kf}Su%^)r4TN3|zTIb@? zZv2P_-N_h0|1n&0><9YoB-{!o-ee2^_a#9~9(Z2xtG-f%`mevSKg96UieK;e(s6e@ z@dAm&-4v|yKi#u1f&Ko2{NJ(hhxC5O#vjJ}9UFhd&hOaxBXobq#vhgQ8#ewZ+~1J# z$J$~49UFhljo-2H$K3cG8-L7=-?8z>-1r?Ef6R^FvGK>;_zfF>%#GiW@yFcwALa&m zuoaKJl?xfL8eESD!(d4JKPH{k2>AZru>bg`ext@eQu{Y#fIm|EH*EYLv)&)4@Nd}s iV=VrLjQ__60;@DiP1k=aWQS44yLax}@x*`<_J08!QWM|+ literal 0 HcmV?d00001 diff --git a/images/logo-light.png b/images/logo-light.png new file mode 100644 index 0000000000000000000000000000000000000000..149c8ba7e303d4ac3b76aedb85be5aeee737f524 GIT binary patch literal 69365 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 HEZX}&$tr@^ literal 0 HcmV?d00001 diff --git a/images/logo-white.png b/images/logo-white.png new file mode 100644 index 0000000000000000000000000000000000000000..c2fdeb70cdb964225e2708fc0fe82907db6d09cb GIT binary patch literal 63912 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 literal 0 HcmV?d00001 -- 2.7.4 From 69ab55f9b7796150256cc8365684ac0f1630019b Mon Sep 17 00:00:00 2001 From: Dariusz Michaluk Date: Thu, 18 Jun 2015 09:43:58 +0200 Subject: [PATCH 07/16] Don't print LOGS messages when log level is greater than TRACE [Bug] LOGS messages was always printed [Cause] N/A [Solution] N/A [Verification] Build, run `vasum-server -r` and `vasum-server -r -l TRACE` Change-Id: Iec4fdd5d40a3920a51afae0a687387cb71b85ea2 --- libs/logger/logger-scope.cpp | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/libs/logger/logger-scope.cpp b/libs/logger/logger-scope.cpp index e790bab..a977adc 100644 --- a/libs/logger/logger-scope.cpp +++ b/libs/logger/logger-scope.cpp @@ -43,14 +43,18 @@ LoggerScope::LoggerScope(const std::string& file, mMessage(message), mRootDir(rootDir) { - logger::Logger::logMessage(logger::LogLevel::TRACE, "Entering: " + mMessage, mFile, - mLine, mFunc, mRootDir); + if (logger::Logger::getLogLevel() <= logger::LogLevel::TRACE) { + logger::Logger::logMessage(logger::LogLevel::TRACE, "Entering: " + mMessage, + mFile, mLine, mFunc, mRootDir); + } } LoggerScope::~LoggerScope() { - logger::Logger::logMessage(logger::LogLevel::TRACE, "Leaving: " + mMessage, mFile, - mLine, mFunc, mRootDir); + if (logger::Logger::getLogLevel() <= logger::LogLevel::TRACE) { + logger::Logger::logMessage(logger::LogLevel::TRACE, "Leaving: " + mMessage, + mFile, mLine, mFunc, mRootDir); + } } } // namespace logger -- 2.7.4 From 35bf91022261d3e35a649f97ba47b26fc742ac6a Mon Sep 17 00:00:00 2001 From: Dariusz Michaluk Date: Tue, 16 Jun 2015 14:39:42 +0200 Subject: [PATCH 08/16] Add wrapper for lxc-fedora template [Feature] Add wrapper for lxc-fedora template [Cause] N/A [Solution] N/A [Verification] Build, create/start/shutdown/destroy zone. Change-Id: Iaa071f19dedfb7406d576858d8c7be2600b1e077 --- packaging/vasum.spec | 1 + server/configs/templates/fedora.sh | 84 ++++++++++++++++++++++++++++++++++++++ 2 files changed, 85 insertions(+) create mode 100755 server/configs/templates/fedora.sh diff --git a/packaging/vasum.spec b/packaging/vasum.spec index 38c7cf6..83c5f0f 100644 --- a/packaging/vasum.spec +++ b/packaging/vasum.spec @@ -28,6 +28,7 @@ Requires: lxc Requires: iproute2 Requires(post): libcap-tools %else +Requires: lxc-templates Requires: iproute Requires(post): libcap %endif diff --git a/server/configs/templates/fedora.sh b/server/configs/templates/fedora.sh new file mode 100755 index 0000000..dc4db3b --- /dev/null +++ b/server/configs/templates/fedora.sh @@ -0,0 +1,84 @@ +#!/bin/bash + +# template script for creating Fedora LXC container +# This script is a wrapper for the lxc-fedora template +# +# Copyright (c) 2015 Samsung Electronics Co., Ltd All Rights Reserved +# +# Contact: Dariusz Michaluk +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +usage() +{ + cat < + [-p|--path=] [--rootfs=] [--vt=] + [--ipv4=] [--ipv4-gateway=] [-h|--help] +Mandatory args: + -n,--name zone name + -p,--path path to zone config files + --rootfs path to zone rootfs +Optional args: + --vt zone virtual terminal + --ipv4 zone IP address + --ipv4-gateway zone gateway + -h,--help print help +EOF + return 0 +} + +options=$(getopt -o hp:n: -l help,rootfs:,path:,vt:,name:,ipv4:,ipv4-gateway: -- "$@") +if [ $? -ne 0 ]; then + usage $(basename $0) + exit 1 +fi +eval set -- "$options" + +while true +do + case "$1" in + -h|--help) usage $0 && exit 0;; + --rootfs) rootfs=$2; shift 2;; + -p|--path) path=$2; shift 2;; + --vt) vt=$2; shift 2;; + -n|--name) name=$2; shift 2;; + --ipv4) ipv4=$2; shift 2;; + --ipv4-gateway) ipv4_gateway=$2; shift 2;; + --) shift 1; break ;; + *) break ;; + esac +done + +if [ "$(id -u)" != "0" ]; then + echo "This script should be run as 'root'" + exit 1 +fi + +if [ -z $name ]; then + echo "Zone name must be given" + exit 1 +fi + +if [ -z "$path" ]; then + echo "'path' parameter is required" + exit 1 +fi + +if [ -z "$rootfs" ]; then + echo "'rootfs' parameter is required" + exit 1 +fi + +/usr/share/lxc/templates/lxc-fedora --name="$name" --path="$path" --rootfs="$rootfs" -- 2.7.4 From c1df0b7f41eb8a392b6c85f1f1b34b66d84ae967 Mon Sep 17 00:00:00 2001 From: Lukasz Kostyra Date: Tue, 16 Jun 2015 12:56:18 +0200 Subject: [PATCH 09/16] Finish CreateFile API [Feature] N/A [Cause] Missing API [Solution] Add missing functions in ZonesManager and in Communication [Verification] Build, install, run tests Change-Id: I417e1deeca2effcdb772189045263d0c9dd22de7 --- common/api/messages.hpp | 2 + common/lxc/zone.cpp | 8 ++- common/lxc/zone.hpp | 15 +++-- libs/config/from-gvariant-visitor.hpp | 7 +++ libs/config/to-gvariant-visitor.hpp | 2 + server/common-definitions.hpp | 13 +++-- server/host-dbus-connection.cpp | 9 +++ server/host-dbus-definitions.hpp | 1 + server/host-ipc-connection.cpp | 12 ++++ server/host-ipc-connection.hpp | 1 + server/zone.cpp | 9 +++ server/zone.hpp | 11 ++++ server/zones-manager.cpp | 30 ++++++++++ server/zones-manager.hpp | 2 + tests/unit_tests/lxc/ut-zone.cpp | 7 ++- tests/unit_tests/server/ut-zones-manager.cpp | 83 ++++++++++++++++++++++++++++ 16 files changed, 197 insertions(+), 15 deletions(-) diff --git a/common/api/messages.hpp b/common/api/messages.hpp index a00a2dd..7299898 100644 --- a/common/api/messages.hpp +++ b/common/api/messages.hpp @@ -227,11 +227,13 @@ struct GrantDeviceIn { struct CreateFileIn { std::string id; std::string path; + int32_t flags; int32_t mode; CONFIG_REGISTER ( id, path, + flags, mode ) }; diff --git a/common/lxc/zone.cpp b/common/lxc/zone.cpp index 5fd1762..845d959 100644 --- a/common/lxc/zone.cpp +++ b/common/lxc/zone.cpp @@ -376,7 +376,10 @@ bool LxcZone::runInZone(Call& call) return status == 0; } -int LxcZone::createFile(const std::string& path, const std::int32_t mode, int *fdPtr) +bool LxcZone::createFile(const std::string& path, + const std::int32_t flags, + const std::int32_t mode, + int *fdPtr) { *fdPtr = -1; @@ -389,12 +392,13 @@ int LxcZone::createFile(const std::string& path, const std::int32_t mode, int *f lxc::LxcZone::Call call = [&]()->int{ utils::close(sockets[1]); - int fd = ::open(path.c_str(), O_CREAT | O_EXCL, mode); + int fd = ::open(path.c_str(), O_CREAT | O_EXCL | flags, mode); if (fd < 0) { LOGE("Error during file creation: " << utils::getSystemErrorMessage()); utils::close(sockets[0]); return -1; } + LOGT("Created file in zone with fd " << fd); utils::fdSend(sockets[0], fd); utils::close(fd); return 0; diff --git a/common/lxc/zone.hpp b/common/lxc/zone.hpp index 0d34e6f..ff5bb85 100644 --- a/common/lxc/zone.hpp +++ b/common/lxc/zone.hpp @@ -158,12 +158,19 @@ public: /** * Create a file inside the zone and return it's file descriptor * - * @param path path in the container - * @param mode mode + * @param[in] path Path in container where file shall be created + * @param[in] flags Flags used when creating file. Note that the method already provides + * O_CREAT and O_EXCL flags. User must provide the function with + * O_RDWR/O_RDONLY/O_WRONLY flag explicitly. + * @param[in] mode Permissions with which file is created + * @param[out] fdPtr Pointer to opened file descriptor. * - * @return file descriptor of the file, opened in mode + * @return True on success, false on failure. */ - int createFile(const std::string& path, const std::int32_t mode, int *fdPtr); + bool createFile(const std::string& path, + const std::int32_t flags, + const std::int32_t mode, + int *fdPtr); private: lxc_container* mLxcContainer; diff --git a/libs/config/from-gvariant-visitor.hpp b/libs/config/from-gvariant-visitor.hpp index 040dcae..e648625 100644 --- a/libs/config/from-gvariant-visitor.hpp +++ b/libs/config/from-gvariant-visitor.hpp @@ -28,6 +28,7 @@ #include "config/is-visitable.hpp" #include "config/exception.hpp" #include "config/is-union.hpp" +#include "config/types.hpp" #include #include @@ -126,6 +127,12 @@ private: value = g_variant_get_string(object, NULL); } + static void fromGVariant(GVariant* object, config::FileDescriptor& value) + { + checkType(object, G_VARIANT_TYPE_INT32); + value.value = g_variant_get_int32(object); + } + template static void fromGVariant(GVariant* object, std::vector& value) { diff --git a/libs/config/to-gvariant-visitor.hpp b/libs/config/to-gvariant-visitor.hpp index bb94e49..047aa17 100644 --- a/libs/config/to-gvariant-visitor.hpp +++ b/libs/config/to-gvariant-visitor.hpp @@ -27,6 +27,7 @@ #include "config/is-visitable.hpp" #include "config/is-union.hpp" +#include "config/types.hpp" #include #include @@ -82,6 +83,7 @@ private: void writeInternal(bool value) { add("b", value); }; void writeInternal(double value) { add("d", value); }; void writeInternal(const std::string& value) { add("s", value.c_str()); }; + void writeInternal(const config::FileDescriptor& value) { add("h", value.value); }; template void writeInternal(const std::vector& value) diff --git a/server/common-definitions.hpp b/server/common-definitions.hpp index 5e85f92..cf8bfe4 100644 --- a/server/common-definitions.hpp +++ b/server/common-definitions.hpp @@ -36,12 +36,13 @@ namespace api { */ //TODO: Errors should use exception handling mechanism ///@{ -const std::string ERROR_FORBIDDEN = "org.tizen.vasum.Error.Forbidden"; -const std::string ERROR_FORWARDED = "org.tizen.vasum.Error.Forwarded"; -const std::string ERROR_INVALID_ID = "org.tizen.vasum.Error.InvalidId"; -const std::string ERROR_INVALID_STATE = "org.tizen.vasum.Error.InvalidState"; -const std::string ERROR_INTERNAL = "org.tizen.vasum.Error.Internal"; -const std::string ERROR_ZONE_NOT_RUNNING = "org.tizen.vasum.Error.ZonesNotRunning"; +const std::string ERROR_FORBIDDEN = "org.tizen.vasum.Error.Forbidden"; +const std::string ERROR_FORWARDED = "org.tizen.vasum.Error.Forwarded"; +const std::string ERROR_INVALID_ID = "org.tizen.vasum.Error.InvalidId"; +const std::string ERROR_INVALID_STATE = "org.tizen.vasum.Error.InvalidState"; +const std::string ERROR_INTERNAL = "org.tizen.vasum.Error.Internal"; +const std::string ERROR_ZONE_NOT_RUNNING = "org.tizen.vasum.Error.ZonesNotRunning"; +const std::string ERROR_CREATE_FILE_FAILED = "org.tizen.vasum.Error.CreateFileFailed"; ///@} } // namespace api diff --git a/server/host-dbus-connection.cpp b/server/host-dbus-connection.cpp index 7714b65..ba4e9ee 100644 --- a/server/host-dbus-connection.cpp +++ b/server/host-dbus-connection.cpp @@ -394,6 +394,15 @@ void HostDbusConnection::onMessageCall(const std::string& objectPath, mZonesManagerPtr->handleFileMoveCall(EMPTY_CALLER, data, rb); return; } + + if (methodName == api::dbus::METHOD_CREATE_FILE) { + api::CreateFileIn data; + config::loadFromGVariant(parameters, data); + + auto rb = std::make_shared>(result); + mZonesManagerPtr->handleCreateFileCall(data, rb); + return; + } } void HostDbusConnection::onSignalCall(const std::string& /* senderBusName */, diff --git a/server/host-dbus-definitions.hpp b/server/host-dbus-definitions.hpp index 142a6d2..9b74ab2 100644 --- a/server/host-dbus-definitions.hpp +++ b/server/host-dbus-definitions.hpp @@ -181,6 +181,7 @@ const std::string DEFINITION = " " " " " " + " " " " " " " " diff --git a/server/host-ipc-connection.cpp b/server/host-ipc-connection.cpp index e87adca..c389919 100644 --- a/server/host-ipc-connection.cpp +++ b/server/host-ipc-connection.cpp @@ -125,6 +125,9 @@ HostIPCConnection::HostIPCConnection(ZonesManager* zonesManagerPtr) setFileMoveCallback(std::bind(&ZonesManager::handleFileMoveCall, mZonesManagerPtr, "", _1, _2)); + + setCreateFileCallback(std::bind(&ZonesManager::handleCreateFileCall, + mZonesManagerPtr, _1, _2)); } HostIPCConnection::~HostIPCConnection() @@ -366,6 +369,15 @@ void HostIPCConnection::setFileMoveCallback(const Method::type& callback) +{ + typedef IPCMethodWrapper Method; + mService->setMethodHandler( + api::ipc::METHOD_CREATE_FILE, + Method::getWrapper(callback)); +} + void HostIPCConnection::sendNotification(const api::Notification& notification) { mService->signal(api::ipc::SIGNAL_NOTIFICATION, diff --git a/server/host-ipc-connection.hpp b/server/host-ipc-connection.hpp index 8107612..44fe356 100644 --- a/server/host-ipc-connection.hpp +++ b/server/host-ipc-connection.hpp @@ -86,6 +86,7 @@ private: void setSwitchToDefaultCallback(const Signal::type& callback); void setFileMoveCallback(const Method::type& callback); + void setCreateFileCallback(const Method::type& callback); ipc::epoll::ThreadDispatcher mDispatcher; std::unique_ptr mService; diff --git a/server/zone.cpp b/server/zone.cpp index 94f6873..590badd 100644 --- a/server/zone.cpp +++ b/server/zone.cpp @@ -394,6 +394,15 @@ bool Zone::isSwitchToDefaultAfterTimeoutAllowed() const return mConfig.switchToDefaultAfterTimeout; } +int Zone::createFile(const std::string& path, const std::int32_t flags, const std::int32_t mode) +{ + int fd = 0; + if (!mZone.createFile(path, flags, mode, &fd)) { + throw ZoneOperationException("Failed to create file."); + } + return fd; +} + std::string Zone::declareFile(const int32_t& type, const std::string& path, const int32_t& flags, diff --git a/server/zone.hpp b/server/zone.hpp index 0829c35..dbc384d 100644 --- a/server/zone.hpp +++ b/server/zone.hpp @@ -183,6 +183,17 @@ public: int getVT() const; /** + * Create file inside zone, return its fd + * + * @param path Path where the file should be created + * @param flags Flags used when opening the file. See common/lxc/zone.hpp for more info. + * @param mode Permissions with which file is created + * + * @return Created files fd + */ + int createFile(const std::string& path, const std::int32_t flags, const std::int32_t mode); + + /** * Declare file, directory or pipe that will be created while zone startup */ std::string declareFile(const int32_t& type, diff --git a/server/zones-manager.cpp b/server/zones-manager.cpp index d213669..d28c9b4 100644 --- a/server/zones-manager.cpp +++ b/server/zones-manager.cpp @@ -625,6 +625,36 @@ void ZonesManager::handleFileMoveCall(const std::string& /*srcZoneId*/, #endif /* ZONE_CONNECTION */ +void ZonesManager::handleCreateFileCall(const api::CreateFileIn& request, + api::MethodResultBuilder::Pointer result) +{ + auto handler = [&, this] { + LOGI("CreateFile call"); + + Lock lock(mMutex); + + auto srcIter = findZone(request.id); + if (srcIter == mZones.end()) { + LOGE("Zone '" << request.id << "' not found"); + result->setError(api::ERROR_INVALID_ID, "Requested Zone was not found."); + return; + } + Zone& srcZone = get(srcIter); + + auto retValue = std::make_shared(); + try { + retValue->fd = srcZone.createFile(request.path, request.flags, request.mode); + } catch(ZoneOperationException& e) { + result->setError(api::ERROR_CREATE_FILE_FAILED, "Unable to create file"); + return; + } + + result->set(retValue); + }; + + mWorker->addTaskAndWait(handler); +} + #ifdef DBUS_CONNECTION void ZonesManager::handleProxyCall(const std::string& caller, const std::string& target, diff --git a/server/zones-manager.hpp b/server/zones-manager.hpp index c74f5ec..55e7023 100644 --- a/server/zones-manager.hpp +++ b/server/zones-manager.hpp @@ -164,6 +164,8 @@ public: api::MethodResultBuilder::Pointer result); void handleRevokeDeviceCall(const api::RevokeDeviceIn& data, api::MethodResultBuilder::Pointer result); + void handleCreateFileCall(const api::CreateFileIn& request, + api::MethodResultBuilder::Pointer result); // Zone's handlers--------------------------------------------------------- void handleNotifyActiveZoneCall(const std::string& caller, diff --git a/tests/unit_tests/lxc/ut-zone.cpp b/tests/unit_tests/lxc/ut-zone.cpp index f87427e..ba839c9 100644 --- a/tests/unit_tests/lxc/ut-zone.cpp +++ b/tests/unit_tests/lxc/ut-zone.cpp @@ -44,6 +44,7 @@ const std::string ZONE_PATH = "/tmp/ut-zone/"; const std::string ZONE_NAME = "ut-zone"; const std::string ZONE_TEMPLATE = VSM_TEST_TEMPLATES_INSTALL_DIR "/minimal.sh"; const char* TEMPLATE_ARGS[] = {NULL}; +const std::int32_t DEFAULT_FILE_MODE = 0666; struct Fixture { utils::ScopedDir mLxcDirGuard; @@ -267,15 +268,15 @@ BOOST_AUTO_TEST_CASE(CreateFile) // The test int fd; - BOOST_REQUIRE(lxc.createFile("./112.txt", O_RDWR, &fd)); + BOOST_REQUIRE(lxc.createFile("./112.txt", O_RDWR, DEFAULT_FILE_MODE, &fd)); BOOST_REQUIRE(::fcntl(fd, F_GETFD) != -1); BOOST_REQUIRE(::close(fd) != -1); - BOOST_REQUIRE(lxc.createFile("/2.txt", O_RDONLY, &fd)); + BOOST_REQUIRE(lxc.createFile("/2.txt", O_RDONLY, DEFAULT_FILE_MODE, &fd)); BOOST_REQUIRE(::fcntl(fd, F_GETFD) != -1); BOOST_REQUIRE(::close(fd) != -1); - BOOST_REQUIRE(lxc.createFile("/3.txt", O_WRONLY, &fd)); + BOOST_REQUIRE(lxc.createFile("/3.txt", O_WRONLY, DEFAULT_FILE_MODE, &fd)); BOOST_REQUIRE(::fcntl(fd, F_GETFD) != -1); BOOST_REQUIRE(::close(fd) != -1); diff --git a/tests/unit_tests/server/ut-zones-manager.cpp b/tests/unit_tests/server/ut-zones-manager.cpp index 0283fd9..375f212 100644 --- a/tests/unit_tests/server/ut-zones-manager.cpp +++ b/tests/unit_tests/server/ut-zones-manager.cpp @@ -58,6 +58,8 @@ #include #include #include +#include +#include using namespace vasum; using namespace config; @@ -74,6 +76,7 @@ const std::string TEST_CONFIG_PATH = CONFIG_DIR + "/test-daemon.conf"; const std::string MISSING_CONFIG_PATH = CONFIG_DIR + "/missing-daemon.conf"; const int EVENT_TIMEOUT = 5000; const int SIGNAL_PROPAGATE_TIME = 500; // ms +const std::int32_t DEFAULT_FILE_MODE = 0666; //const int UNEXPECTED_EVENT_TIMEOUT = EVENT_TIMEOUT / 5; const std::string TEST_APP_NAME = "testapp"; const std::string TEST_MESSAGE = "testmessage"; @@ -445,6 +448,24 @@ public: "()"); } + int callMethodCreateFile(const std::string& id, + const std::string& path, + const std::int32_t& flags, + const std::int32_t& mode) + { + assert(isHost()); + GVariant* parameters = g_variant_new("(ssii)", id.c_str(), path.c_str(), flags, mode); + GVariantPtr result = mClient->callMethod(api::dbus::BUS_NAME, + api::dbus::OBJECT_PATH, + api::dbus::INTERFACE, + api::dbus::METHOD_CREATE_FILE, + parameters, + "(h)"); + int fileFd = 0; + g_variant_get(result.get(), "(h)", &fileFd); + return fileFd; + } + private: const int mId; DbusConnection::Pointer mClient; @@ -599,6 +620,18 @@ public: return result->value; } + int callMethodCreateFile(const std::string& id, + const std::string& path, + const std::int32_t& flags, + const std::int32_t& mode) + { + auto result = mClient.callSync( + api::ipc::METHOD_CREATE_FILE, + std::make_shared(api::CreateFileIn{id, path, flags, mode}), + EVENT_TIMEOUT*10); + return result->fd.value; + } + private: ipc::epoll::ThreadDispatcher mDispatcher; ipc::Client mClient; @@ -1294,4 +1327,54 @@ MULTI_FIXTURE_TEST_CASE(LockUnlockZone, F, ACCESSORS) WhatEquals("Zone is not paused")); } +MULTI_FIXTURE_TEST_CASE(CreateFile, F, ACCESSORS) +{ + ZonesManager cm(TEST_CONFIG_PATH); + cm.createZone("zone1", SIMPLE_TEMPLATE); + cm.restoreAll(); + + typename F::HostAccessory host; + int returnedFd = host.callMethodCreateFile("zone1", "/123.txt", O_RDWR, DEFAULT_FILE_MODE); + BOOST_REQUIRE(::fcntl(returnedFd, F_GETFD) != -1); + BOOST_REQUIRE(::close(returnedFd) != -1); + + returnedFd = host.callMethodCreateFile("zone1", "/56.txt", O_RDONLY, DEFAULT_FILE_MODE); + BOOST_REQUIRE(::fcntl(returnedFd, F_GETFD) != -1); + BOOST_REQUIRE(::close(returnedFd) != -1); + + returnedFd = host.callMethodCreateFile("zone1", "/89.txt", O_WRONLY, DEFAULT_FILE_MODE); + BOOST_REQUIRE(::fcntl(returnedFd, F_GETFD) != -1); + BOOST_REQUIRE(::close(returnedFd) != -1); +} + +MULTI_FIXTURE_TEST_CASE(CreateWriteReadFile, F, ACCESSORS) +{ + ZonesManager cm(TEST_CONFIG_PATH); + cm.createZone("zone1", SIMPLE_TEMPLATE); + cm.restoreAll(); + + typename F::HostAccessory host; + + // create file, make sure returned fd is correct + int returnedFd = host.callMethodCreateFile("zone1", "/test123.txt", O_RDWR, DEFAULT_FILE_MODE); + BOOST_REQUIRE(::fcntl(returnedFd, F_GETFD) != -1); + + // write sth + BOOST_REQUIRE_MESSAGE(::write(returnedFd, FILE_CONTENT.c_str(), FILE_CONTENT.size()) > 0, + "Failed to write to fd " << returnedFd << ": " << ::strerror(errno)); + + // go back to the beginning + BOOST_REQUIRE(::lseek(returnedFd, 0, SEEK_SET) != -1); + + // read it back, zero-terminate it and verify + std::unique_ptr retStr(new char[FILE_CONTENT.size()+1]); + BOOST_REQUIRE_MESSAGE(::read(returnedFd, retStr.get(), FILE_CONTENT.size()) > 0, + "Failed to read from file: " << ::strerror(errno)); + retStr[FILE_CONTENT.size()] = 0; + BOOST_REQUIRE(FILE_CONTENT.compare(retStr.get()) == 0); + + // close + BOOST_REQUIRE(::close(returnedFd) != -1); +} + BOOST_AUTO_TEST_SUITE_END() -- 2.7.4 From 5aba67f60ffd9676018e5dd41a016fb682064077 Mon Sep 17 00:00:00 2001 From: Krzysztof Dynowski Date: Fri, 19 Jun 2015 14:49:30 +0200 Subject: [PATCH 10/16] Check vasum runtime - rename vasum-check-env to vasum-check-config [Bug/Feature] naming convention [Cause] N/A [Solution] rename [Verification] N/A Change-Id: I6fb89a9378da7d4c04c0cae74935fdf67df5d3d6 --- packaging/vasum.spec | 2 +- server/CMakeLists.txt | 2 +- server/scripts/{vasum-check-env.sh => vasum-check-config.sh} | 0 server/server.cpp | 8 ++++---- 4 files changed, 6 insertions(+), 6 deletions(-) rename server/scripts/{vasum-check-env.sh => vasum-check-config.sh} (100%) diff --git a/packaging/vasum.spec b/packaging/vasum.spec index 83c5f0f..24c9842 100644 --- a/packaging/vasum.spec +++ b/packaging/vasum.spec @@ -45,7 +45,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 +%attr(755,root,root) %{_sbindir}/vasum-check-config %dir /etc/vasum %dir /etc/vasum/templates %config /etc/vasum/daemon.conf diff --git a/server/CMakeLists.txt b/server/CMakeLists.txt index d5104db..b301d00 100644 --- a/server/CMakeLists.txt +++ b/server/CMakeLists.txt @@ -56,4 +56,4 @@ 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) +INSTALL(PROGRAMS "scripts/vasum-check-config.sh" DESTINATION sbin RENAME vasum-check-config) diff --git a/server/scripts/vasum-check-env.sh b/server/scripts/vasum-check-config.sh similarity index 100% rename from server/scripts/vasum-check-env.sh rename to server/scripts/vasum-check-config.sh diff --git a/server/server.cpp b/server/server.cpp index befb8da..1f749cc 100644 --- a/server/server.cpp +++ b/server/server.cpp @@ -163,7 +163,7 @@ bool Server::checkEnvironment() // 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; + std::cout << "kernel is old ver=" << u.release << ", run vasum-check-config" << std::endl; return false; } else @@ -184,7 +184,7 @@ bool Server::checkEnvironment() 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; + std::cout << "no cgroups support (can't access " << cgroupCheck << "), run vasum-check-config" << std::endl; return false; } @@ -198,7 +198,7 @@ bool Server::checkEnvironment() } ::close(fd); if (err) { - std::cout << "cgroups problem, run vasum-check-env" << std::endl; + std::cout << "cgroups problem, run vasum-check-config" << std::endl; return false; } else @@ -207,7 +207,7 @@ bool Server::checkEnvironment() // 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; + std::cout << "no namespace support (can't access " << nsCheck << "), run vasum-check-config" << std::endl; return false; } else -- 2.7.4 From bd11817708a85472c67f727081bc4b3f61f24107 Mon Sep 17 00:00:00 2001 From: Lukasz Kostyra Date: Tue, 23 Jun 2015 11:28:51 +0200 Subject: [PATCH 11/16] Fix Klocwork issues [Bug] Issues reported by Klocwork [Cause] N/A [Solution] N/A [Verification] Build, install, run tests Change-Id: I745cccedceff96fc3b1f475da4308f17775a6d24 --- libs/config/from-kvjson-visitor.hpp | 4 ++-- libs/ipc/internals/processor.cpp | 4 ++-- libs/ipc/internals/processor.hpp | 2 +- tests/unit_tests/config/ut-dynvisit.cpp | 2 +- 4 files changed, 6 insertions(+), 6 deletions(-) diff --git a/libs/config/from-kvjson-visitor.hpp b/libs/config/from-kvjson-visitor.hpp index f9c11ef..943dbb8 100644 --- a/libs/config/from-kvjson-visitor.hpp +++ b/libs/config/from-kvjson-visitor.hpp @@ -212,8 +212,8 @@ private: json_object_put(visitor.mObject); visitor.mObject = nullptr; } - for (int i = 0; i < length; ++i) { - visitor.getValue(i, value[i]); + for (int idx = 0; idx < length; ++idx) { + visitor.getValue(idx, value[idx]); } } diff --git a/libs/ipc/internals/processor.cpp b/libs/ipc/internals/processor.cpp index 9cb86c0..2e7a575 100644 --- a/libs/ipc/internals/processor.cpp +++ b/libs/ipc/internals/processor.cpp @@ -647,7 +647,7 @@ bool Processor::onSendResultRequest(SendResultRequest& request) return false; } -bool Processor::onFinishRequest(FinishRequest& request) +bool Processor::onFinishRequest(FinishRequest& requestFinisher) { LOGS(mLogPrefix + "Processor onFinishRequest"); @@ -686,7 +686,7 @@ bool Processor::onFinishRequest(FinishRequest& request) mIsRunning = false; - request.conditionPtr->notify_all(); + requestFinisher.conditionPtr->notify_all(); return true; } diff --git a/libs/ipc/internals/processor.hpp b/libs/ipc/internals/processor.hpp index 121978c..a0e39bf 100644 --- a/libs/ipc/internals/processor.hpp +++ b/libs/ipc/internals/processor.hpp @@ -466,7 +466,7 @@ private: bool onAddPeerRequest(AddPeerRequest& request); bool onRemovePeerRequest(RemovePeerRequest& request); bool onSendResultRequest(SendResultRequest& request); - bool onFinishRequest(FinishRequest& request); + bool onFinishRequest(FinishRequest& requestFinisher); bool onReturnValue(Peers::iterator& peerIt, const MessageID messageID); diff --git a/tests/unit_tests/config/ut-dynvisit.cpp b/tests/unit_tests/config/ut-dynvisit.cpp index bbe45e0..b2a0372 100644 --- a/tests/unit_tests/config/ut-dynvisit.cpp +++ b/tests/unit_tests/config/ut-dynvisit.cpp @@ -60,7 +60,7 @@ void checkJsonConfig(const TestConfig& cfg, const std::string& json) TestConfig cfg2; loadFromJsonString(json, cfg2); BOOST_CHECK_EQUAL(cfg2.intVal, cfg.intVal); - BOOST_CHECK_EQUAL(cfg.int64Val, cfg.int64Val); + BOOST_CHECK_EQUAL(cfg2.int64Val, cfg.int64Val); BOOST_CHECK_EQUAL(cfg2.boolVal, cfg.boolVal); BOOST_CHECK_EQUAL(cfg2.stringVal, cfg.stringVal); BOOST_CHECK_EQUAL(cfg2.intVector.size(), cfg.intVector.size()); -- 2.7.4 From 335d65d1e88c9c6af913724b720eea80a526f2c5 Mon Sep 17 00:00:00 2001 From: Krzysztof Dynowski Date: Thu, 25 Jun 2015 10:52:35 +0200 Subject: [PATCH 12/16] Wrapper: send/recv socket fd - based on public domain code [Bug/Feature] Protex reported copy of code from LXC sources [Cause] Copied from vasum old api [Solution] Follow public domain examples from "Unix Network Programming" [Verification] Next protex report Change-Id: I13163a3e0ef68d816ad194e515cab28629a7291f --- wrapper/wrapper-compatibility.cpp | 50 ++++++++++++++++++++------------------- 1 file changed, 26 insertions(+), 24 deletions(-) diff --git a/wrapper/wrapper-compatibility.cpp b/wrapper/wrapper-compatibility.cpp index 942c5f6..6c3dfa9 100644 --- a/wrapper/wrapper-compatibility.cpp +++ b/wrapper/wrapper-compatibility.cpp @@ -211,65 +211,67 @@ API int sock_recv_fd(int fd, int *recvfd, void *data, size_t size) { LOGS(""); struct msghdr msg; struct iovec iov; + int ret; + union { + struct cmsghdr cm; + char control[CMSG_SPACE(sizeof(int))]; + } control_un; struct cmsghdr *cmsg; - char cmsgbuf[CMSG_SPACE(sizeof(int))]; - char buf[1]; - int ret, *val; + char dummy=1; memset(&msg, 0, sizeof(msg)); msg.msg_name = NULL; msg.msg_namelen = 0; - msg.msg_control = cmsgbuf; - msg.msg_controllen = sizeof(cmsgbuf); - iov.iov_base = data ? data : buf; - iov.iov_len = data ? size : sizeof(buf); + msg.msg_control = control_un.control; + msg.msg_controllen = sizeof(control_un.control); + + iov.iov_base = data ? data : &dummy; + iov.iov_len = data ? size : sizeof(dummy); msg.msg_iov = &iov; msg.msg_iovlen = 1; ret = recvmsg(fd, &msg, 0); if (ret <= 0) - goto out; + return ret; cmsg = CMSG_FIRSTHDR(&msg); - - *recvfd = -1; - if (cmsg && cmsg->cmsg_len == CMSG_LEN(sizeof(int)) && cmsg->cmsg_level == SOL_SOCKET && cmsg->cmsg_type == SCM_RIGHTS) { - val = (int *)CMSG_DATA(cmsg); - *recvfd = *val; + *recvfd = *((int *)CMSG_DATA(cmsg)); } - out: - return ret; + else + *recvfd = -1; + return ret; } // sock_send_fd API int sock_send_fd(int fd, int sendfd, void *data, size_t size) { LOGS(""); struct msghdr msg; struct iovec iov; + union { + struct cmsghdr cm; + char control[CMSG_SPACE(sizeof(int))]; + } control_un; struct cmsghdr *cmsg; - char cmsgbuf[CMSG_SPACE(sizeof(int))]; - char buf[1]; - int *val; + char dummy=1; memset(&msg, 0, sizeof(msg)); - msg.msg_control = cmsgbuf; - msg.msg_controllen = sizeof(cmsgbuf); + msg.msg_control = control_un.control; + msg.msg_controllen = sizeof(control_un.control); cmsg = CMSG_FIRSTHDR(&msg); cmsg->cmsg_len = CMSG_LEN(sizeof(int)); cmsg->cmsg_level = SOL_SOCKET; cmsg->cmsg_type = SCM_RIGHTS; - val = (int *)(CMSG_DATA(cmsg)); - *val = sendfd; + *((int *)CMSG_DATA(cmsg)) = sendfd; msg.msg_name = NULL; msg.msg_namelen = 0; - iov.iov_base = data ? data : buf; - iov.iov_len = data ? size : sizeof(buf); + iov.iov_base = data ? data : &dummy; + iov.iov_len = data ? size : sizeof(dummy); msg.msg_iov = &iov; msg.msg_iovlen = 1; -- 2.7.4 From c94cb2f9edd0188c3ef54f62ddeeb74fb7b9f6ea Mon Sep 17 00:00:00 2001 From: Mateusz Malicki Date: Wed, 24 Jun 2015 16:38:03 +0200 Subject: [PATCH 13/16] Optimization turned off when compiling with coverage support [Feature] Better coverage report [Cause] Optimization can broke coverage report [Solution] Turn off optimization [Verification] Build with 'CCOV' target, run, generate report Change-Id: I13f04d16f6292e5def30a6af75c5fcbc5038fde1 --- CMakeLists.txt | 4 ++-- packaging/vasum.spec | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index cbcf4b9..76a2344 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -63,8 +63,8 @@ SET(CMAKE_C_FLAGS_DEBUG "-g -O0 -ggdb") SET(CMAKE_CXX_FLAGS_DEBUG "-g -std=${CXX_11_STD} -O0 -ggdb") SET(CMAKE_C_FLAGS_RELEASE "-g -O2 -DNDEBUG") SET(CMAKE_CXX_FLAGS_RELEASE "-g -std=${CXX_11_STD} -O2 -DNDEBUG") -SET(CMAKE_C_FLAGS_CCOV "-g -O2 --coverage") -SET(CMAKE_CXX_FLAGS_CCOV "-g -std=${CXX_11_STD} -O2 --coverage") +SET(CMAKE_C_FLAGS_CCOV "-g -O0 --coverage") +SET(CMAKE_CXX_FLAGS_CCOV "-g -std=${CXX_11_STD} -O0 --coverage") IF(DEFINED SANITIZE) # Enable sanitize build. diff --git a/packaging/vasum.spec b/packaging/vasum.spec index 24c9842..aa6ee22 100644 --- a/packaging/vasum.spec +++ b/packaging/vasum.spec @@ -63,7 +63,7 @@ between them. A process from inside a zone can request a switch of context %build %{!?build_type:%define build_type "RELEASE"} -%if %{build_type} == "DEBUG" || %{build_type} == "PROFILING" +%if %{build_type} == "DEBUG" || %{build_type} == "PROFILING" || %{build_type} == "CCOV" CFLAGS="$CFLAGS -Wp,-U_FORTIFY_SOURCE" CXXFLAGS="$CXXFLAGS -Wp,-U_FORTIFY_SOURCE" %endif -- 2.7.4 From faa1396d2fe42048020678b06287dc3573a2b128 Mon Sep 17 00:00:00 2001 From: Lukasz Pawelczyk Date: Thu, 18 Jun 2015 15:21:38 +0200 Subject: [PATCH 14/16] Implement a Lock/Unlock Queue API calls. [Feature] Calls that make it possible to lock a queue exclusively to one client (IPC/DBUS) which can then order few calls in a row with a guarantee that no other client will interrupt. [Cause] n/a [Solution] n/a [Verification] Built, installed, run tests. Also see below. Additional features implemented in this commit to support the above: - DBus client disconnected notification. Adds a new callback to registerObject() that's called when a client that previously talked to the server gets disconnected. - ZoneManager level client disconnect notification using the aforementioned DBus and already implemented IPC functionalities. - Changed SwitchToDefault from signal to a method so we can return an error code when the queue is locked. - MethodResultBuilder's getID() call that returns ipc independent identifier that client connections can be identified with (using getPeerID and getPeerName from IPC and DBus specific classes respectively). - mGuard fixed in the DbusConnection class. Now it really does protect mConnection and mNameID as well as newly introduced mWatchedClients. - Various half-related fixes/changes here and there (whitespaces, duplicate definition of PROXY_CALL in the DBus interface, etc). There are no tests in this commit for the DBus features and the Lock/Unlock queue. They will follow in the later commits. To somewhat test the disconnect notifications (both, DBus level and ZoneManager level) one can connect to the server using appropriate APIs and watch the DEBUG/TRACE logs. This can be achieved using the following commands: $ dbus-send --system --dest=org.tizen.vasum.host \ --type=method_call --print-reply \ /org/tizen/vasum/host \ org.tizen.vasum.host.manager.GetZoneIds $ vasum-cli get_zone_ids WARNING: this commit breaks API/ABI of libSimpleDbus Change-Id: Ic0ed2371e563c34340ad41d66dd943a1abc8eb48 --- client/vasum-client-impl.cpp | 18 ++++ client/vasum-client-impl.hpp | 10 ++ client/vasum-client.cpp | 10 ++ client/vasum-client.h | 16 ++++ common/api/dbus-method-result-builder.hpp | 9 ++ common/api/ipc-method-result-builder.cpp | 5 + common/api/ipc-method-result-builder.hpp | 3 + common/api/method-result-builder.hpp | 3 +- libs/dbus/connection.cpp | 76 ++++++++++++--- libs/dbus/connection.hpp | 38 +++++++- libs/ipc/method-result.cpp | 5 + libs/ipc/method-result.hpp | 1 + server/common-definitions.hpp | 1 + server/host-dbus-connection.cpp | 34 +++++-- server/host-dbus-connection.hpp | 1 + server/host-dbus-definitions.hpp | 19 ++-- server/host-ipc-connection.cpp | 45 +++++++-- server/host-ipc-connection.hpp | 4 +- server/host-ipc-definitions.hpp | 4 +- server/zones-manager.cpp | 135 +++++++++++++++++++++------ server/zones-manager.hpp | 15 ++- tests/unit_tests/dbus/test-server.cpp | 3 +- tests/unit_tests/dbus/ut-connection.cpp | 20 ++-- tests/unit_tests/server/ut-zones-manager.cpp | 25 ++--- zone-daemon/daemon-connection.cpp | 3 +- 25 files changed, 409 insertions(+), 94 deletions(-) diff --git a/client/vasum-client-impl.cpp b/client/vasum-client-impl.cpp index f9a15b8..343fd1b 100644 --- a/client/vasum-client-impl.cpp +++ b/client/vasum-client-impl.cpp @@ -308,6 +308,24 @@ VsmStatus Client::vsm_get_zone_dbuses(VsmArrayString* /*keys*/, VsmArrayString* }); } +VsmStatus Client::vsm_lock_queue() noexcept +{ + return coverException([&] { + *mClient->callSync( + vasum::api::ipc::METHOD_LOCK_QUEUE, + std::make_shared()); + }); +} + +VsmStatus Client::vsm_unlock_queue() noexcept +{ + return coverException([&] { + *mClient->callSync( + vasum::api::ipc::METHOD_UNLOCK_QUEUE, + std::make_shared()); + }); +} + VsmStatus Client::vsm_get_zone_ids(VsmArrayString* array) noexcept { return coverException([&] { diff --git a/client/vasum-client-impl.hpp b/client/vasum-client-impl.hpp index 854c32c..845cf29 100644 --- a/client/vasum-client-impl.hpp +++ b/client/vasum-client-impl.hpp @@ -123,6 +123,16 @@ public: VsmStatus vsm_get_zone_dbuses(VsmArrayString* keys, VsmArrayString* values) noexcept; /** + * @see ::vsm_lock_queue + */ + VsmStatus vsm_lock_queue() noexcept; + + /** + * @see ::vsm_unlock_queue + */ + VsmStatus vsm_unlock_queue() noexcept; + + /** * @see ::vsm_get_zone_ids */ VsmStatus vsm_get_zone_ids(VsmArrayString* array) noexcept; diff --git a/client/vasum-client.cpp b/client/vasum-client.cpp index f36c1ed..4acd82a 100644 --- a/client/vasum-client.cpp +++ b/client/vasum-client.cpp @@ -45,6 +45,16 @@ Client& getClient(VsmClient client) } // namespace +API VsmStatus vsm_lock_queue(VsmClient client) +{ + return getClient(client).vsm_lock_queue(); +} + +API VsmStatus vsm_unlock_queue(VsmClient client) +{ + return getClient(client).vsm_unlock_queue(); +} + API VsmStatus vsm_get_poll_fd(VsmClient client, int* fd) { return getClient(client).vsm_get_poll_fd(fd); diff --git a/client/vasum-client.h b/client/vasum-client.h index 3832d23..9216ce9 100644 --- a/client/vasum-client.h +++ b/client/vasum-client.h @@ -404,6 +404,22 @@ typedef void (*VsmZoneDbusStateCallback)(const char* zoneId, void* data); /** + * Lock the command queue exclusively. + * + * @param[in] client vasum-server's client + * @return status of this function call + */ +VsmStatus vsm_lock_queue(VsmClient client); + +/** + * Unlock the command queue. + * + * @param[in] client vasum-server's client + * @return status of this function call + */ +VsmStatus vsm_unlock_queue(VsmClient client); + +/** * Get dbus address of each zone. * * @param[in] client vasum-server's client diff --git a/common/api/dbus-method-result-builder.hpp b/common/api/dbus-method-result-builder.hpp index c6422dc..7673b65 100644 --- a/common/api/dbus-method-result-builder.hpp +++ b/common/api/dbus-method-result-builder.hpp @@ -39,6 +39,8 @@ namespace vasum { namespace api { +const std::string DBUS_CONNECTION_PREFIX = "dbus://"; + template class DbusMethodResultBuilder: public MethodResultBuilder { public: @@ -49,6 +51,7 @@ private: void setImpl(const std::shared_ptr& data) override; void setVoid() override; void setError(const std::string& name, const std::string& message) override; + std::string getID() const; ::dbus::MethodResultBuilder::Pointer mMethodResultBuilderPtr; std::function)> mSerialize; @@ -82,6 +85,12 @@ void DbusMethodResultBuilder::setError(const std::string& name, const std: mMethodResultBuilderPtr->setError(name, message); } +template +std::string DbusMethodResultBuilder::getID() const +{ + return DBUS_CONNECTION_PREFIX + mMethodResultBuilderPtr->getPeerName(); +} + } // namespace result } // namespace vasum diff --git a/common/api/ipc-method-result-builder.cpp b/common/api/ipc-method-result-builder.cpp index 4ea2845..d7ac681 100644 --- a/common/api/ipc-method-result-builder.cpp +++ b/common/api/ipc-method-result-builder.cpp @@ -48,6 +48,11 @@ void IPCMethodResultBuilder::setError(const std::string& , const std::string& me mMethodResultPtr->setError(1, message); } +std::string IPCMethodResultBuilder::getID() const +{ + return IPC_CONNECTION_PREFIX + std::to_string(mMethodResultPtr->getPeerID()); +} + } // namespace result } // namespace vasum diff --git a/common/api/ipc-method-result-builder.hpp b/common/api/ipc-method-result-builder.hpp index 7b03ece..0b0ddd3 100644 --- a/common/api/ipc-method-result-builder.hpp +++ b/common/api/ipc-method-result-builder.hpp @@ -36,6 +36,8 @@ namespace vasum { namespace api { +const std::string IPC_CONNECTION_PREFIX = "ipc://"; + class IPCMethodResultBuilder: public MethodResultBuilder { public: IPCMethodResultBuilder(const ipc::MethodResult::Pointer& methodResult); @@ -45,6 +47,7 @@ private: void setImpl(const std::shared_ptr& data) override; void setVoid() override; void setError(const std::string& name, const std::string& message) override; + std::string getID() const; ipc::MethodResult::Pointer mMethodResultPtr; }; diff --git a/common/api/method-result-builder.hpp b/common/api/method-result-builder.hpp index 89aa7a9..ca31feb 100644 --- a/common/api/method-result-builder.hpp +++ b/common/api/method-result-builder.hpp @@ -43,6 +43,7 @@ public: virtual ~MethodResultBuilder() {} virtual void setVoid() = 0; virtual void setError(const std::string& name, const std::string& message) = 0; + virtual std::string getID() const = 0; template void set(const std::shared_ptr& data) @@ -52,7 +53,7 @@ public: } private: - virtual void setImpl(const std::shared_ptr& data) =0; + virtual void setImpl(const std::shared_ptr& data) = 0; }; diff --git a/libs/dbus/connection.cpp b/libs/dbus/connection.cpp index 60b3225..ee4cea9 100644 --- a/libs/dbus/connection.cpp +++ b/libs/dbus/connection.cpp @@ -65,6 +65,10 @@ public: g_dbus_method_invocation_return_dbus_error(mInvocation, name.c_str(), message.c_str()); mResultSet = true; } + std::string getPeerName() + { + return std::string(g_dbus_method_invocation_get_sender(mInvocation)); + } private: GDBusMethodInvocation* mInvocation; bool mResultSet; @@ -146,16 +150,19 @@ DbusConnection::DbusConnection(const std::string& address) DbusConnection::~DbusConnection() { // Close connection in a glib thread (because of a bug in glib) - GDBusConnection* connection = mConnection; - guint nameId = mNameId; + auto closeConnection = [this]() { + for (auto client : mWatchedClients) { + LOGT("Stopped watching the client: " << client.first); + g_bus_unwatch_name(client.second); + } - auto closeConnection = [=]() { - if (nameId) { - g_bus_unown_name(nameId); + if (mNameId) { + g_bus_unown_name(mNameId); } - g_object_unref(connection); + g_object_unref(mConnection); LOGT("Connection deleted"); }; + executeInGlibThread(closeConnection, mGuard); } @@ -268,7 +275,8 @@ std::string DbusConnection::introspect(const std::string& busName, const std::st void DbusConnection::registerObject(const std::string& objectPath, const std::string& objectDefinitionXml, - const MethodCallCallback& callback) + const MethodCallCallback& methodCall, + const ClientVanishedCallback& clientVanished) { ScopedGError error; GDBusNodeInfo* nodeInfo = g_dbus_node_info_new_for_xml(objectDefinitionXml.c_str(), &error); @@ -297,8 +305,10 @@ void DbusConnection::registerObject(const std::string& objectPath, objectPath.c_str(), interfaceInfo, &vtable, - createCallbackWrapper(callback, mGuard.spawn()), - &deleteCallbackWrapper, + createCallbackWrapper( + MethodCallbacks(methodCall, clientVanished, this), + mGuard.spawn()), + &deleteCallbackWrapper, &error); g_dbus_node_info_unref(nodeInfo); if (error) { @@ -308,7 +318,7 @@ void DbusConnection::registerObject(const std::string& objectPath, } } -void DbusConnection::onMethodCall(GDBusConnection*, +void DbusConnection::onMethodCall(GDBusConnection* connection, const gchar*, const gchar* objectPath, const gchar* interface, @@ -317,14 +327,54 @@ void DbusConnection::onMethodCall(GDBusConnection*, GDBusMethodInvocation* invocation, gpointer userData) { - const MethodCallCallback& callback = getCallbackFromPointer(userData); + const MethodCallbacks& callbacks = getCallbackFromPointer(userData); LOGD("MethodCall: " << objectPath << "; " << interface << "; " << method); + const gchar *sender = g_dbus_method_invocation_get_sender(invocation); + ClientsMap &watchedClients = callbacks.dbusConn->mWatchedClients; + + if (watchedClients.find(sender) == watchedClients.end()) { + LOGT("Watching the client: " << sender); + guint id = g_bus_watch_name_on_connection(connection, + sender, + G_BUS_NAME_WATCHER_FLAGS_NONE, + NULL, + &DbusConnection::onClientVanish, + createCallbackWrapper( + VanishedCallbacks(callbacks.clientVanished, + watchedClients), + callbacks.dbusConn->mGuard.spawn()), + &deleteCallbackWrapper); + + watchedClients[sender] = id; + } + MethodResultBuilder::Pointer resultBuilder(new MethodResultBuilderImpl(invocation)); - if (callback) { - callback(objectPath, interface, method, parameters, resultBuilder); + if (callbacks.methodCall) { + callbacks.methodCall(objectPath, interface, method, parameters, resultBuilder); + } +} + +void DbusConnection::onClientVanish(GDBusConnection*, + const gchar *name, + gpointer userData) +{ + const VanishedCallbacks& callbacks = getCallbackFromPointer(userData); + + LOGI("ClientVanished: " << name); + + guint id = callbacks.watchedClients[name]; + callbacks.watchedClients.erase(name); + + if (callbacks.clientVanished) { + callbacks.clientVanished(name); } + + LOGT("Stopped watching the client: " << name); + + // after this line we cannot use the *name pointer, this call frees it + g_bus_unwatch_name(id); } GVariantPtr DbusConnection::callMethod(const std::string& busName, diff --git a/libs/dbus/connection.hpp b/libs/dbus/connection.hpp index 5248d2e..fc7f1f7 100644 --- a/libs/dbus/connection.hpp +++ b/libs/dbus/connection.hpp @@ -30,6 +30,7 @@ #include #include #include +#include #include @@ -49,6 +50,7 @@ public: virtual void set(GVariant* parameters) = 0; virtual void setVoid() = 0; virtual void setError(const std::string& name, const std::string& message) = 0; + virtual std::string getPeerName() = 0; }; /** @@ -80,6 +82,9 @@ public: MethodResultBuilder::Pointer result )> MethodCallCallback; + typedef std::function ClientVanishedCallback; + typedef std::function ClientsMap; + + struct MethodCallbacks { + MethodCallCallback methodCall; + ClientVanishedCallback clientVanished; + DbusConnection *dbusConn; + + MethodCallbacks(const MethodCallCallback& method, + const ClientVanishedCallback& vanish, + DbusConnection *dbus) + : methodCall(method), clientVanished(vanish), dbusConn(dbus) {} + }; + + struct VanishedCallbacks { + ClientVanishedCallback clientVanished; + ClientsMap &watchedClients; + + VanishedCallbacks(const ClientVanishedCallback& vanish, ClientsMap& clients) + : clientVanished(vanish), watchedClients(clients) {} + }; + GDBusConnection* mConnection; guint mNameId; + // It's only ever modified in the glib thread + ClientsMap mWatchedClients; + // Guard must be destroyed before objects it protects + // (e.g. all of the above, see the destructor) + utils::CallbackGuard mGuard; DbusConnection(const std::string& address); @@ -207,6 +238,9 @@ private: static void onAsyncReady(GObject* source, GAsyncResult* asyncResult, gpointer userData); + static void onClientVanish(GDBusConnection* connection, + const gchar *name, + gpointer userData); }; diff --git a/libs/ipc/method-result.cpp b/libs/ipc/method-result.cpp index ffb97a8..97eb450 100644 --- a/libs/ipc/method-result.cpp +++ b/libs/ipc/method-result.cpp @@ -54,4 +54,9 @@ void MethodResult::setError(const int code, const std::string& message) mProcessor.sendError(mPeerID, mMessageID, code, message); } +PeerID MethodResult::getPeerID() +{ + return mPeerID; +} + } // namespace ipc diff --git a/libs/ipc/method-result.hpp b/libs/ipc/method-result.hpp index bd9d10f..26369ed 100644 --- a/libs/ipc/method-result.hpp +++ b/libs/ipc/method-result.hpp @@ -51,6 +51,7 @@ public: void setVoid(); void setError(const int code, const std::string& message); + PeerID getPeerID(); private: Processor& mProcessor; diff --git a/server/common-definitions.hpp b/server/common-definitions.hpp index cf8bfe4..b7b22ed 100644 --- a/server/common-definitions.hpp +++ b/server/common-definitions.hpp @@ -43,6 +43,7 @@ const std::string ERROR_INVALID_STATE = "org.tizen.vasum.Error.InvalidState const std::string ERROR_INTERNAL = "org.tizen.vasum.Error.Internal"; const std::string ERROR_ZONE_NOT_RUNNING = "org.tizen.vasum.Error.ZonesNotRunning"; const std::string ERROR_CREATE_FILE_FAILED = "org.tizen.vasum.Error.CreateFileFailed"; +const std::string ERROR_QUEUE = "org.tizen.vasum.Error.Queue"; ///@} } // namespace api diff --git a/server/host-dbus-connection.cpp b/server/host-dbus-connection.cpp index ba4e9ee..20cffd9 100644 --- a/server/host-dbus-connection.cpp +++ b/server/host-dbus-connection.cpp @@ -70,7 +70,9 @@ HostDbusConnection::HostDbusConnection(ZonesManager* zonesManagerPtr) mDbusConnection->registerObject(api::dbus::OBJECT_PATH, api::dbus::DEFINITION, std::bind(&HostDbusConnection::onMessageCall, - this, _1, _2, _3, _4, _5)); + this, _1, _2, _3, _4, _5), + std::bind(&HostDbusConnection::onClientVanished, + this, _1)); mSubscriptionId = mDbusConnection->signalSubscribe(std::bind(&HostDbusConnection::onSignalCall, this, _1, _2, _3, _4, _5), @@ -168,6 +170,18 @@ void HostDbusConnection::onMessageCall(const std::string& objectPath, return; } + if (methodName == api::dbus::METHOD_LOCK_QUEUE) { + auto rb = std::make_shared>(result); + mZonesManagerPtr->handleLockQueueCall(rb); + return; + } + + if (methodName == api::dbus::METHOD_UNLOCK_QUEUE) { + auto rb = std::make_shared>(result); + mZonesManagerPtr->handleUnlockQueueCall(rb); + return; + } + if (methodName == api::dbus::METHOD_GET_ZONE_ID_LIST) { auto rb = std::make_shared>(result); mZonesManagerPtr->handleGetZoneIdsCall(rb); @@ -403,21 +417,29 @@ void HostDbusConnection::onMessageCall(const std::string& objectPath, mZonesManagerPtr->handleCreateFileCall(data, rb); return; } + + if (methodName == api::dbus::METHOD_SWITCH_TO_DEFAULT) { + auto rb = std::make_shared>(result); + mZonesManagerPtr->handleSwitchToDefaultCall(EMPTY_CALLER, rb); + return; + } +} + +void HostDbusConnection::onClientVanished(const std::string& name) +{ + const std::string id = api::DBUS_CONNECTION_PREFIX + name; + mZonesManagerPtr->disconnectedCallback(id); } void HostDbusConnection::onSignalCall(const std::string& /* senderBusName */, const std::string& objectPath, const std::string& interface, - const std::string& signalName, + const std::string& /* signalName */, GVariant* /* parameters */) { if (objectPath != api::dbus::OBJECT_PATH || interface != api::dbus::INTERFACE) { return; } - - if (signalName == api::dbus::SIGNAL_SWITCH_TO_DEFAULT) { - mZonesManagerPtr->handleSwitchToDefaultCall(EMPTY_CALLER); - } } void HostDbusConnection::proxyCallAsync(const std::string& busName, diff --git a/server/host-dbus-connection.hpp b/server/host-dbus-connection.hpp index 23bb9d9..2b4d2a3 100644 --- a/server/host-dbus-connection.hpp +++ b/server/host-dbus-connection.hpp @@ -97,6 +97,7 @@ private: const std::string& methodName, GVariant* parameters, dbus::MethodResultBuilder::Pointer result); + void onClientVanished(const std::string& name); void onSignalCall(const std::string& senderBusName, const std::string& objectPath, const std::string& interface, diff --git a/server/host-dbus-definitions.hpp b/server/host-dbus-definitions.hpp index 9b74ab2..caa333b 100644 --- a/server/host-dbus-definitions.hpp +++ b/server/host-dbus-definitions.hpp @@ -63,11 +63,13 @@ const std::string METHOD_GRANT_DEVICE = "GrantDevice"; const std::string METHOD_REVOKE_DEVICE = "RevokeDevice"; const std::string METHOD_PROXY_CALL = "ProxyCall"; const std::string METHOD_CREATE_FILE = "CreateFile"; +const std::string METHOD_LOCK_QUEUE = "LockQueue"; +const std::string METHOD_UNLOCK_QUEUE = "UnlockQueue"; +const std::string METHOD_SWITCH_TO_DEFAULT = "SwitchToDefault"; const std::string METHOD_NOTIFY_ACTIVE_ZONE = "NotifyActiveZone"; const std::string METHOD_FILE_MOVE_REQUEST = "FileMoveRequest"; const std::string SIGNAL_NOTIFICATION = "Notification"; -const std::string SIGNAL_SWITCH_TO_DEFAULT = "SwitchToDefault"; const std::string FILE_MOVE_DESTINATION_NOT_FOUND = "FILE_MOVE_DESTINATION_NOT_FOUND"; const std::string FILE_MOVE_WRONG_DESTINATION = "FILE_MOVE_WRONG_DESTINATION"; @@ -80,14 +82,9 @@ const std::string FILE_MOVE_SUCCEEDED = "FILE_MOVE_SUCCEEDED"; const std::string DEFINITION = "" " " - " " - " " - " " - " " - " " - " " - " " - " " + " " + " " + " " " " " " " " @@ -227,13 +224,13 @@ const std::string DEFINITION = " " " " " " + " " + " " " " " " " " " " " " - " " - " " " " ""; diff --git a/server/host-ipc-connection.cpp b/server/host-ipc-connection.cpp index c389919..f110999 100644 --- a/server/host-ipc-connection.cpp +++ b/server/host-ipc-connection.cpp @@ -39,9 +39,22 @@ HostIPCConnection::HostIPCConnection(ZonesManager* zonesManagerPtr) : mZonesManagerPtr(zonesManagerPtr) { LOGT("Connecting to host IPC socket"); - mService.reset(new ipc::Service(mDispatcher.getPoll(), HOST_IPC_SOCKET)); + + ipc::PeerCallback removedCallback = [this](const ipc::PeerID peerID, + const ipc::FileDescriptor) { + std::string id = api::IPC_CONNECTION_PREFIX + std::to_string(peerID); + mZonesManagerPtr->disconnectedCallback(id); + }; + mService.reset(new ipc::Service(mDispatcher.getPoll(), HOST_IPC_SOCKET, + nullptr, removedCallback)); using namespace std::placeholders; + setLockQueueCallback(std::bind(&ZonesManager::handleLockQueueCall, + mZonesManagerPtr, _1)); + + setUnlockQueueCallback(std::bind(&ZonesManager::handleUnlockQueueCall, + mZonesManagerPtr, _1)); + setGetZoneIdsCallback(std::bind(&ZonesManager::handleGetZoneIdsCall, mZonesManagerPtr, _1)); @@ -121,7 +134,7 @@ HostIPCConnection::HostIPCConnection(ZonesManager* zonesManagerPtr) mZonesManagerPtr, "", _1, _2)); setSwitchToDefaultCallback(std::bind(&ZonesManager::handleSwitchToDefaultCall, - mZonesManagerPtr, "")); + mZonesManagerPtr, "", _1)); setFileMoveCallback(std::bind(&ZonesManager::handleFileMoveCall, mZonesManagerPtr, "", _1, _2)); @@ -141,13 +154,28 @@ void HostIPCConnection::start() LOGD("Connected"); } +void HostIPCConnection::setLockQueueCallback(const Method::type& callback) +{ + typedef IPCMethodWrapper Callback; + mService->setMethodHandler( + api::ipc::METHOD_LOCK_QUEUE, + Callback::getWrapper(callback)); +} + +void HostIPCConnection::setUnlockQueueCallback(const Method::type& callback) +{ + typedef IPCMethodWrapper Callback; + mService->setMethodHandler( + api::ipc::METHOD_UNLOCK_QUEUE, + Callback::getWrapper(callback)); +} + void HostIPCConnection::setGetZoneIdsCallback(const Method::type& callback) { typedef IPCMethodWrapper Callback; mService->setMethodHandler( api::ipc::METHOD_GET_ZONE_ID_LIST, Callback::getWrapper(callback)); - } void HostIPCConnection::setGetActiveZoneIdCallback(const Method::type& callback) @@ -156,7 +184,6 @@ void HostIPCConnection::setGetActiveZoneIdCallback(const Method::ty mService->setMethodHandler( api::ipc::METHOD_GET_ACTIVE_ZONE_ID, Callback::getWrapper(callback)); - } void HostIPCConnection::setGetZoneInfoCallback(const Method::type& callback) @@ -352,12 +379,12 @@ void HostIPCConnection::setNotifyActiveZoneCallback( Method::getWrapper(callback)); } -void HostIPCConnection::setSwitchToDefaultCallback(const Signal::type& callback) +void HostIPCConnection::setSwitchToDefaultCallback(const Method::type& callback) { - typedef IPCSignalWrapper Signal; - mService->setSignalHandler( - api::ipc::SIGNAL_SWITCH_TO_DEFAULT, - Signal::getWrapper(callback)); + typedef IPCMethodWrapper Callback; + mService->setMethodHandler( + api::ipc::METHOD_SWITCH_TO_DEFAULT, + Callback::getWrapper(callback)); } void HostIPCConnection::setFileMoveCallback(const Method::type& callback); + void setUnlockQueueCallback(const Method::type& callback); void setGetZoneIdsCallback(const Method::type& callback); void setGetZoneConnectionsCallback(const Method::type& callback); void setGetActiveZoneIdCallback(const Method::type& callback); @@ -83,7 +85,7 @@ private: void setGrantDeviceCallback(const Method::type& callback); void setRevokeDeviceCallback(const Method::type& callback); void setNotifyActiveZoneCallback(const Method::type& callback); - void setSwitchToDefaultCallback(const Signal::type& callback); + void setSwitchToDefaultCallback(const Method::type& callback); void setFileMoveCallback(const Method::type& callback); void setCreateFileCallback(const Method::type& callback); diff --git a/server/host-ipc-definitions.hpp b/server/host-ipc-definitions.hpp index d1251eb..74cf534 100644 --- a/server/host-ipc-definitions.hpp +++ b/server/host-ipc-definitions.hpp @@ -57,11 +57,13 @@ const ::ipc::MethodID METHOD_UNLOCK_ZONE = 24; const ::ipc::MethodID METHOD_GRANT_DEVICE = 25; const ::ipc::MethodID METHOD_REVOKE_DEVICE = 26; const ::ipc::MethodID METHOD_CREATE_FILE = 27; +const ::ipc::MethodID METHOD_LOCK_QUEUE = 28; +const ::ipc::MethodID METHOD_UNLOCK_QUEUE = 29; +const ::ipc::MethodID METHOD_SWITCH_TO_DEFAULT = 30; const ::ipc::MethodID METHOD_NOTIFY_ACTIVE_ZONE = 100; const ::ipc::MethodID METHOD_FILE_MOVE_REQUEST = 101; const ::ipc::MethodID SIGNAL_NOTIFICATION = 102; -const ::ipc::MethodID SIGNAL_SWITCH_TO_DEFAULT = 103; const std::string FILE_MOVE_DESTINATION_NOT_FOUND = "FILE_MOVE_DESTINATION_NOT_FOUND"; const std::string FILE_MOVE_WRONG_DESTINATION = "FILE_MOVE_WRONG_DESTINATION"; diff --git a/server/zones-manager.cpp b/server/zones-manager.cpp index d28c9b4..a0a0205 100644 --- a/server/zones-manager.cpp +++ b/server/zones-manager.cpp @@ -116,6 +116,7 @@ ZonesManager::ZonesManager(const std::string& configPath) : mWorker(utils::Worker::create()) , mHostIPCConnection(this) , mDetachOnExit(false) + , mExclusiveIDLock(INVALID_CONNECTION_ID) #ifdef DBUS_CONNECTION , mHostDbusConnection(this) #endif @@ -251,6 +252,25 @@ void ZonesManager::insertZone(const std::string& zoneId, const std::string& zone } } +void ZonesManager::tryAddTask(const utils::Worker::Task& task, api::MethodResultBuilder::Pointer result, bool wait) +{ + { + Lock lock(mExclusiveIDMutex); + + if (mExclusiveIDLock != INVALID_CONNECTION_ID && + mExclusiveIDLock != result->getID()) { + result->setError(api::ERROR_QUEUE, "Queue is locked by another client"); + return; + } + } + + if (wait) { + mWorker->addTaskAndWait(task); + } else { + mWorker->addTask(task); + } +} + void ZonesManager::destroyZone(const std::string& zoneId) { Lock lock(mMutex); @@ -465,7 +485,21 @@ void ZonesManager::setZonesDetachOnExit() } } -void ZonesManager::handleSwitchToDefaultCall(const std::string& /*caller*/) +void ZonesManager::disconnectedCallback(const std::string& id) +{ + LOGD("Client Disconnected: " << id); + + { + Lock lock(mExclusiveIDMutex); + + if (mExclusiveIDLock == id) { + mExclusiveIDLock = INVALID_CONNECTION_ID; + } + } +} + +void ZonesManager::handleSwitchToDefaultCall(const std::string& /*caller*/, + api::MethodResultBuilder::Pointer result) { auto handler = [&, this] { // get config of currently set zone and switch if switchToDefaultAfterTimeout is true @@ -482,9 +516,10 @@ void ZonesManager::handleSwitchToDefaultCall(const std::string& /*caller*/) LOGI("Switching to default zone " << mDynamicConfig.defaultId); focusInternal(defaultIter); } + result->setVoid(); }; - mWorker->addTaskAndWait(handler); + tryAddTask(handler, result, true); } #ifdef ZONE_CONNECTION @@ -512,7 +547,7 @@ void ZonesManager::handleNotifyActiveZoneCall(const std::string& caller, } }; - mWorker->addTaskAndWait(handler); + tryAddTask(handler, result, true); } void ZonesManager::handleFileMoveCall(const std::string& srcZoneId, @@ -606,7 +641,7 @@ void ZonesManager::handleFileMoveCall(const std::string& srcZoneId, } }; - mWorker->addTaskAndWait(handler); + tryAddTask(handler, result, true); } #else void ZonesManager::handleNotifyActiveZoneCall(const std::string& /* caller */, @@ -652,7 +687,7 @@ void ZonesManager::handleCreateFileCall(const api::CreateFileIn& request, result->set(retValue); }; - mWorker->addTaskAndWait(handler); + tryAddTask(handler, result, true); } #ifdef DBUS_CONNECTION @@ -703,10 +738,53 @@ void ZonesManager::handleProxyCall(const std::string& caller, asyncResultCallback); }; + // This call cannot be locked by lock/unlock queue mWorker->addTaskAndWait(handler); } #endif //DBUS_CONNECTION +void ZonesManager::handleLockQueueCall(api::MethodResultBuilder::Pointer result) +{ + Lock lock(mExclusiveIDMutex); + std::string id = result->getID(); + + LOGI("Lock Queue: " << id); + + if (mExclusiveIDLock == id) { + result->setError(api::ERROR_QUEUE, "Queue already locked"); + return; + } + + if (mExclusiveIDLock != INVALID_CONNECTION_ID) { + result->setError(api::ERROR_QUEUE, "Queue locked by another connection"); + return; + } + + mExclusiveIDLock = id; + result->setVoid(); +} + +void ZonesManager::handleUnlockQueueCall(api::MethodResultBuilder::Pointer result) +{ + Lock lock(mExclusiveIDMutex); + std::string id = result->getID(); + + LOGI("Unlock Queue: " << id); + + if (mExclusiveIDLock == INVALID_CONNECTION_ID) { + result->setError(api::ERROR_QUEUE, "Queue not locked"); + return; + } + + if (mExclusiveIDLock != id) { + result->setError(api::ERROR_QUEUE, "Queue locked by another connection"); + return; + } + + mExclusiveIDLock = INVALID_CONNECTION_ID; + result->setVoid(); +} + void ZonesManager::handleGetZoneIdsCall(api::MethodResultBuilder::Pointer result) { auto handler = [&, this] { @@ -722,6 +800,7 @@ void ZonesManager::handleGetZoneIdsCall(api::MethodResultBuilder::Pointer result result->set(zoneIds); }; + // This call cannot be locked by lock/unlock queue mWorker->addTaskAndWait(handler); } @@ -735,6 +814,7 @@ void ZonesManager::handleGetActiveZoneIdCall(api::MethodResultBuilder::Pointer r result->set(zoneId); }; + // This call cannot be locked by lock/unlock queue mWorker->addTaskAndWait(handler); } @@ -774,6 +854,7 @@ void ZonesManager::handleGetZoneInfoCall(const api::ZoneId& zoneId, result->set(zoneInfo); }; + // This call cannot be locked by lock/unlock queue mWorker->addTaskAndWait(handler); } @@ -803,7 +884,7 @@ void ZonesManager::handleSetNetdevAttrsCall(const api::SetNetDevAttrsIn& data, } }; - mWorker->addTaskAndWait(handler); + tryAddTask(handler, result, true); } void ZonesManager::handleGetNetdevAttrsCall(const api::GetNetDevAttrsIn& data, @@ -830,7 +911,7 @@ void ZonesManager::handleGetNetdevAttrsCall(const api::GetNetDevAttrsIn& data, } }; - mWorker->addTaskAndWait(handler); + tryAddTask(handler, result, true); } void ZonesManager::handleGetNetdevListCall(const api::ZoneId& zoneId, @@ -853,7 +934,7 @@ void ZonesManager::handleGetNetdevListCall(const api::ZoneId& zoneId, } }; - mWorker->addTaskAndWait(handler); + tryAddTask(handler, result, true); } void ZonesManager::handleCreateNetdevVethCall(const api::CreateNetDevVethIn& data, @@ -876,7 +957,7 @@ void ZonesManager::handleCreateNetdevVethCall(const api::CreateNetDevVethIn& dat } }; - mWorker->addTaskAndWait(handler); + tryAddTask(handler, result, true); } void ZonesManager::handleCreateNetdevMacvlanCall(const api::CreateNetDevMacvlanIn& data, @@ -898,7 +979,7 @@ void ZonesManager::handleCreateNetdevMacvlanCall(const api::CreateNetDevMacvlanI } }; - mWorker->addTaskAndWait(handler); + tryAddTask(handler, result, true); } void ZonesManager::handleCreateNetdevPhysCall(const api::CreateNetDevPhysIn& data, @@ -921,7 +1002,7 @@ void ZonesManager::handleCreateNetdevPhysCall(const api::CreateNetDevPhysIn& dat } }; - mWorker->addTaskAndWait(handler); + tryAddTask(handler, result, true); } void ZonesManager::handleDestroyNetdevCall(const api::DestroyNetDevIn& data, @@ -944,7 +1025,7 @@ void ZonesManager::handleDestroyNetdevCall(const api::DestroyNetDevIn& data, } }; - mWorker->addTaskAndWait(handler); + tryAddTask(handler, result, true); } void ZonesManager::handleDeleteNetdevIpAddressCall(const api::DeleteNetdevIpAddressIn& data, @@ -966,7 +1047,7 @@ void ZonesManager::handleDeleteNetdevIpAddressCall(const api::DeleteNetdevIpAddr } }; - mWorker->addTaskAndWait(handler); + tryAddTask(handler, result, true); } void ZonesManager::handleDeclareFileCall(const api::DeclareFileIn& data, @@ -989,7 +1070,7 @@ void ZonesManager::handleDeclareFileCall(const api::DeclareFileIn& data, } }; - mWorker->addTaskAndWait(handler); + tryAddTask(handler, result, true); } void ZonesManager::handleDeclareMountCall(const api::DeclareMountIn& data, @@ -1012,7 +1093,7 @@ void ZonesManager::handleDeclareMountCall(const api::DeclareMountIn& data, } }; - mWorker->addTaskAndWait(handler); + tryAddTask(handler, result, true); } void ZonesManager::handleDeclareLinkCall(const api::DeclareLinkIn& data, @@ -1035,7 +1116,7 @@ void ZonesManager::handleDeclareLinkCall(const api::DeclareLinkIn& data, } }; - mWorker->addTaskAndWait(handler); + tryAddTask(handler, result, true); } void ZonesManager::handleGetDeclarationsCall(const api::ZoneId& zoneId, @@ -1058,7 +1139,7 @@ void ZonesManager::handleGetDeclarationsCall(const api::ZoneId& zoneId, } }; - mWorker->addTaskAndWait(handler); + tryAddTask(handler, result, true); } void ZonesManager::handleRemoveDeclarationCall(const api::RemoveDeclarationIn& data, @@ -1080,7 +1161,7 @@ void ZonesManager::handleRemoveDeclarationCall(const api::RemoveDeclarationIn& d } }; - mWorker->addTaskAndWait(handler); + tryAddTask(handler, result, true); } void ZonesManager::handleSetActiveZoneCall(const api::ZoneId& zoneId, @@ -1109,7 +1190,7 @@ void ZonesManager::handleSetActiveZoneCall(const api::ZoneId& zoneId, result->setVoid(); }; - mWorker->addTaskAndWait(handler); + tryAddTask(handler, result, true); } @@ -1255,7 +1336,7 @@ void ZonesManager::handleCreateZoneCall(const api::CreateZoneIn& data, } }; - mWorker->addTaskAndWait(creator); + tryAddTask(creator, result, true); } void ZonesManager::handleDestroyZoneCall(const api::ZoneId& zoneId, @@ -1276,7 +1357,7 @@ void ZonesManager::handleDestroyZoneCall(const api::ZoneId& zoneId, result->setVoid(); }; - mWorker->addTask(destroyer); + tryAddTask(destroyer, result, false); } void ZonesManager::handleShutdownZoneCall(const api::ZoneId& zoneId, @@ -1305,7 +1386,7 @@ void ZonesManager::handleShutdownZoneCall(const api::ZoneId& zoneId, } }; - mWorker->addTask(shutdown); + tryAddTask(shutdown, result, false); } void ZonesManager::handleStartZoneCall(const api::ZoneId& zoneId, @@ -1332,7 +1413,7 @@ void ZonesManager::handleStartZoneCall(const api::ZoneId& zoneId, result->setError(api::ERROR_INTERNAL, "Failed to start zone"); } }; - mWorker->addTask(startAsync); + tryAddTask(startAsync, result, false); } void ZonesManager::handleLockZoneCall(const api::ZoneId& zoneId, @@ -1371,7 +1452,7 @@ void ZonesManager::handleLockZoneCall(const api::ZoneId& zoneId, result->setVoid(); }; - mWorker->addTaskAndWait(handler); + tryAddTask(handler, result, true); } void ZonesManager::handleUnlockZoneCall(const api::ZoneId& zoneId, @@ -1408,7 +1489,7 @@ void ZonesManager::handleUnlockZoneCall(const api::ZoneId& zoneId, result->setVoid(); }; - mWorker->addTaskAndWait(handler); + tryAddTask(handler, result, true); } void ZonesManager::handleGrantDeviceCall(const api::GrantDeviceIn& data, @@ -1451,7 +1532,7 @@ void ZonesManager::handleGrantDeviceCall(const api::GrantDeviceIn& data, result->setVoid(); }; - mWorker->addTaskAndWait(handler); + tryAddTask(handler, result, true); } void ZonesManager::handleRevokeDeviceCall(const api::RevokeDeviceIn& data, @@ -1492,7 +1573,7 @@ void ZonesManager::handleRevokeDeviceCall(const api::RevokeDeviceIn& data, result->setVoid(); }; - mWorker->addTaskAndWait(handler); + tryAddTask(handler, result, true); } } // namespace vasum diff --git a/server/zones-manager.hpp b/server/zones-manager.hpp index 55e7023..e7b6675 100644 --- a/server/zones-manager.hpp +++ b/server/zones-manager.hpp @@ -45,6 +45,8 @@ namespace vasum { +const std::string INVALID_CONNECTION_ID = "invalid://"; + class ZonesManager final { public: @@ -115,7 +117,14 @@ public: */ void setZonesDetachOnExit(); + /** + * Callback on a client (ipc/dbus) disconnect + */ + void disconnectedCallback(const std::string& id); + // Handlers -------------------------------------------------------- + void handleLockQueueCall(api::MethodResultBuilder::Pointer result); + void handleUnlockQueueCall(api::MethodResultBuilder::Pointer result); void handleGetZoneIdsCall(api::MethodResultBuilder::Pointer result); void handleGetActiveZoneIdCall(api::MethodResultBuilder::Pointer result); void handleGetZoneInfoCall(const api::ZoneId& data, @@ -171,7 +180,8 @@ public: void handleNotifyActiveZoneCall(const std::string& caller, const api::NotifActiveZoneIn& notif, api::MethodResultBuilder::Pointer result); - void handleSwitchToDefaultCall(const std::string& caller); + void handleSwitchToDefaultCall(const std::string& caller, + api::MethodResultBuilder::Pointer result); void handleFileMoveCall(const std::string& srcZoneId, const api::FileMoveRequestIn& request, api::MethodResultBuilder::Pointer result); @@ -193,6 +203,8 @@ private: Zones mZones; std::string mActiveZoneId; bool mDetachOnExit; + std::string mExclusiveIDLock; + Mutex mExclusiveIDMutex; // used to protect mExclusiveIDLock Zones::iterator findZone(const std::string& id); Zone& getZone(const std::string& id); @@ -209,6 +221,7 @@ private: std::string getTemplatePathForExistingZone(const std::string& id); int getVTForNewZone(); void insertZone(const std::string& zoneId, const std::string& templatePath); + void tryAddTask(const utils::Worker::Task& task, api::MethodResultBuilder::Pointer result, bool wait); #ifdef DBUS_CONNECTION HostDbusConnection mHostDbusConnection; diff --git a/tests/unit_tests/dbus/test-server.cpp b/tests/unit_tests/dbus/test-server.cpp index a0fee4c..03a4046 100644 --- a/tests/unit_tests/dbus/test-server.cpp +++ b/tests/unit_tests/dbus/test-server.cpp @@ -50,7 +50,8 @@ DbusTestServer::DbusTestServer() using namespace std::placeholders; mConnection->registerObject(TESTAPI_OBJECT_PATH, TESTAPI_DEFINITION, - std::bind(&DbusTestServer::onMessageCall, this, _1, _2, _3, _4, _5)); + std::bind(&DbusTestServer::onMessageCall, this, _1, _2, _3, _4, _5), + nullptr); } bool DbusTestServer::waitForName() diff --git a/tests/unit_tests/dbus/ut-connection.cpp b/tests/unit_tests/dbus/ut-connection.cpp index 98154df..6cefb1c 100644 --- a/tests/unit_tests/dbus/ut-connection.cpp +++ b/tests/unit_tests/dbus/ut-connection.cpp @@ -265,13 +265,13 @@ BOOST_AUTO_TEST_CASE(RegisterObject) ScopedGlibLoop loop; DbusConnection::Pointer conn = DbusConnection::create(DBUS_ADDRESS); DbusConnection::MethodCallCallback callback; - BOOST_CHECK_THROW(conn->registerObject(TESTAPI_OBJECT_PATH, "registerObject(TESTAPI_OBJECT_PATH, "registerObject(TESTAPI_OBJECT_PATH, "", callback), + BOOST_CHECK_THROW(conn->registerObject(TESTAPI_OBJECT_PATH, "", callback, nullptr), DbusInvalidArgumentException); - BOOST_CHECK_THROW(conn->registerObject(TESTAPI_OBJECT_PATH, "", callback), + BOOST_CHECK_THROW(conn->registerObject(TESTAPI_OBJECT_PATH, "", callback, nullptr), DbusInvalidArgumentException); - BOOST_CHECK_NO_THROW(conn->registerObject(TESTAPI_OBJECT_PATH, TESTAPI_DEFINITION, callback)); + BOOST_CHECK_NO_THROW(conn->registerObject(TESTAPI_OBJECT_PATH, TESTAPI_DEFINITION, callback, nullptr)); } BOOST_AUTO_TEST_CASE(IntrospectSystem) @@ -298,7 +298,8 @@ BOOST_AUTO_TEST_CASE(Introspect) BOOST_REQUIRE(nameAcquired.wait(EVENT_TIMEOUT)); conn1->registerObject(TESTAPI_OBJECT_PATH, TESTAPI_DEFINITION, - DbusConnection::MethodCallCallback()); + DbusConnection::MethodCallCallback(), + nullptr); std::string xml = conn2->introspect(TESTAPI_BUS_NAME, TESTAPI_OBJECT_PATH); std::string iface = getInterfaceFromIntrospectionXML(xml, TESTAPI_INTERFACE); BOOST_REQUIRE(!iface.empty()); @@ -343,7 +344,7 @@ BOOST_AUTO_TEST_CASE(MethodCall) result->setError("org.tizen.vasum.Error.Test", "msg: " + std::to_string(arg)); } }; - conn1->registerObject(TESTAPI_OBJECT_PATH, TESTAPI_DEFINITION, handler); + conn1->registerObject(TESTAPI_OBJECT_PATH, TESTAPI_DEFINITION, handler, nullptr); GVariantPtr result1 = conn2->callMethod(TESTAPI_BUS_NAME, TESTAPI_OBJECT_PATH, @@ -407,7 +408,7 @@ BOOST_AUTO_TEST_CASE(MethodAsyncCall) result->setError("org.tizen.vasum.Error.Test", "msg: " + std::to_string(arg)); } }; - conn1->registerObject(TESTAPI_OBJECT_PATH, TESTAPI_DEFINITION, handler); + conn1->registerObject(TESTAPI_OBJECT_PATH, TESTAPI_DEFINITION, handler, nullptr); auto asyncResult1 = [&](dbus::AsyncMethodCallResult& asyncMethodCallResult) { if (g_variant_is_of_type(asyncMethodCallResult.get(), G_VARIANT_TYPE_UNIT)) { @@ -491,7 +492,7 @@ BOOST_AUTO_TEST_CASE(MethodAsyncCallAsyncHandler) handlerDone.set(); } }; - conn1->registerObject(TESTAPI_OBJECT_PATH, TESTAPI_DEFINITION, handler); + conn1->registerObject(TESTAPI_OBJECT_PATH, TESTAPI_DEFINITION, handler, nullptr); auto asyncResult = [&](dbus::AsyncMethodCallResult& asyncMethodCallResult) { const gchar* ret = NULL; @@ -528,7 +529,8 @@ BOOST_AUTO_TEST_CASE(MethodCallException) BOOST_REQUIRE(nameAcquired.wait(EVENT_TIMEOUT)); conn1->registerObject(TESTAPI_OBJECT_PATH, TESTAPI_DEFINITION, - DbusConnection::MethodCallCallback()); + DbusConnection::MethodCallCallback(), + nullptr); BOOST_CHECK_THROW(conn2->callMethod(TESTAPI_BUS_NAME, TESTAPI_OBJECT_PATH, TESTAPI_INTERFACE, diff --git a/tests/unit_tests/server/ut-zones-manager.cpp b/tests/unit_tests/server/ut-zones-manager.cpp index 375f212..125d857 100644 --- a/tests/unit_tests/server/ut-zones-manager.cpp +++ b/tests/unit_tests/server/ut-zones-manager.cpp @@ -192,13 +192,14 @@ public: mClient->signalSubscribe(handler, api::dbus::BUS_NAME); } - void signalSwitchToDefault() + void callSwitchToDefault() { - // emit signal from dbus connection - mClient->emitSignal(api::dbus::OBJECT_PATH, + mClient->callMethod(api::dbus::BUS_NAME, + api::dbus::OBJECT_PATH, api::dbus::INTERFACE, - api::dbus::SIGNAL_SWITCH_TO_DEFAULT, - nullptr); + api::dbus::METHOD_SWITCH_TO_DEFAULT, + NULL, + "()"); } void callMethodNotify() @@ -244,7 +245,7 @@ public: } } }; - mClient->registerObject(testapi::OBJECT_PATH, testapi::DEFINITION, handler); + mClient->registerObject(testapi::OBJECT_PATH, testapi::DEFINITION, handler, nullptr); } std::string testApiProxyCall(const std::string& target, const std::string& argument) @@ -598,9 +599,11 @@ public: callbackWrapper); } - void signalSwitchToDefault() + void callSwitchToDefault() { - mClient.signal(api::ipc::SIGNAL_SWITCH_TO_DEFAULT, std::make_shared()); + mClient.callSync(api::ipc::METHOD_SWITCH_TO_DEFAULT, + std::make_shared(), + EVENT_TIMEOUT*10); //Prevent from IPCTimeoutException see LockUnlockZone } void callMethodNotify() @@ -912,7 +915,7 @@ MULTI_FIXTURE_TEST_CASE(SwitchToDefault, F, ACCESSORS) cm.focus("zone3"); - host.signalSwitchToDefault(); + host.callSwitchToDefault(); // check if default zone has focus BOOST_CHECK(spinWaitFor(EVENT_TIMEOUT, isDefaultFocused)); @@ -936,7 +939,7 @@ MULTI_FIXTURE_TEST_CASE(AllowSwitchToDefault, F, ACCESSORS) // focus non-default zone with allowed switching cm.focus("zone3"); - host.signalSwitchToDefault(); + host.callSwitchToDefault(); // check if default zone has focus BOOST_CHECK(spinWaitFor(EVENT_TIMEOUT, isDefaultFocused)); @@ -944,7 +947,7 @@ MULTI_FIXTURE_TEST_CASE(AllowSwitchToDefault, F, ACCESSORS) // focus non-default zone with disabled switching cm.focus("zone2"); - host.signalSwitchToDefault(); + host.callSwitchToDefault(); // now default zone should not be focused // TODO uncomment this after adding an api to change 'switchToDefaultAfterTimeout' diff --git a/zone-daemon/daemon-connection.cpp b/zone-daemon/daemon-connection.cpp index 94a84a8..3fb40ac 100644 --- a/zone-daemon/daemon-connection.cpp +++ b/zone-daemon/daemon-connection.cpp @@ -72,7 +72,8 @@ DaemonConnection::DaemonConnection(const NameLostCallback& nameLostCallback, mDbusConnection->registerObject(zone_daemon::api::OBJECT_PATH, zone_daemon::api::DEFINITION, std::bind(&DaemonConnection::onMessageCall, - this, _1, _2, _3, _4, _5)); + this, _1, _2, _3, _4, _5), + nullptr); LOGD("Connected"); } -- 2.7.4 From 68dd3c4d1edb5d38a404c70e1bfa16326d68ed68 Mon Sep 17 00:00:00 2001 From: Dariusz Michaluk Date: Mon, 22 Jun 2015 10:59:52 +0200 Subject: [PATCH 15/16] Various changes relating to Fedora Linux support. [Bug/Feature] Fix vasum-cli create_zone (add zone template name parameter). Default zone template depends on target platform. Create zones data directory. Add fedora zone template. [Cause] N/A [Solution] N/A [Verification] Build, install, run tests, run daemon, create/start/shutdown/destroy zone. Change-Id: I63b4b6a60c85b826492e13d016f67e489cefb36c --- cli/command-line-interface.cpp | 2 +- cli/main.cpp | 5 ++-- packaging/vasum.spec | 5 ++++ server/configs/CMakeLists.txt | 2 +- server/configs/templates/fedora.conf | 21 +++++++++++++++ server/configs/templates/template.sh | 6 +++-- server/configs/templates/tizen-common-wayland.sh | 6 +++-- .../configs/templates/{default.conf => tizen.conf} | 0 server/zones-manager.cpp | 30 ++++++++++++---------- 9 files changed, 55 insertions(+), 22 deletions(-) create mode 100644 server/configs/templates/fedora.conf rename server/configs/templates/{default.conf => tizen.conf} (100%) diff --git a/cli/command-line-interface.cpp b/cli/command-line-interface.cpp index 2393ce1..0c28cdd 100644 --- a/cli/command-line-interface.cpp +++ b/cli/command-line-interface.cpp @@ -220,7 +220,7 @@ void create_zone(int pos, int argc, const char** argv) throw runtime_error("Not enough parameters"); } - one_shot(bind(vsm_create_zone, _1, argv[pos + 1], nullptr)); + one_shot(bind(vsm_create_zone, _1, argv[pos + 1], argv[pos + 2] ? argv[pos + 2] : nullptr)); } void destroy_zone(int pos, int argc, const char** argv) diff --git a/cli/main.cpp b/cli/main.cpp index 6c10945..af36c74 100644 --- a/cli/main.cpp +++ b/cli/main.cpp @@ -47,9 +47,10 @@ std::map commands = { { "create_zone", { create_zone, - "create_zone zone_id", + "create_zone zone_id [zone_tname]", "Create and add zone", - {{"zone_id", "id zone name"}} + {{"zone_id", "id zone name"}, + {"[zone_tname]", "optional zone template name"}} } }, { diff --git a/packaging/vasum.spec b/packaging/vasum.spec index aa6ee22..13112b5 100644 --- a/packaging/vasum.spec +++ b/packaging/vasum.spec @@ -86,6 +86,11 @@ make -k %{?jobs:-j%jobs} mkdir -p %{buildroot}/%{_unitdir}/multi-user.target.wants ln -s ../vasum.service %{buildroot}/%{_unitdir}/multi-user.target.wants/vasum.service mkdir -p %{buildroot}/%{_datadir}/zones +%if %{platform_type} == "TIZEN" +ln -s tizen.conf %{buildroot}/etc/vasum/templates/default.conf +%else +ln -s fedora.conf %{buildroot}/etc/vasum/templates/default.conf +%endif %clean rm -rf %{buildroot} diff --git a/server/configs/CMakeLists.txt b/server/configs/CMakeLists.txt index c57a806..09254a5 100644 --- a/server/configs/CMakeLists.txt +++ b/server/configs/CMakeLists.txt @@ -43,7 +43,7 @@ CONFIGURE_FILE(dbus-1/system.d/org.tizen.vasum.host.conf.in INSTALL(FILES ${CMAKE_BINARY_DIR}/dbus-1/system.d/org.tizen.vasum.host.conf DESTINATION ${SYSCONF_INSTALL_DIR}/dbus-1/system.d/) -INSTALL(DIRECTORY DESTINATION ${VSM_CONFIG_INSTALL_DIR}/zones) #TODO temporary solution +INSTALL(DIRECTORY DESTINATION ${DATA_DIR}/zones) INSTALL(FILES ${zone_templates_CONF} DESTINATION ${VSM_CONFIG_INSTALL_DIR}/templates) diff --git a/server/configs/templates/fedora.conf b/server/configs/templates/fedora.conf new file mode 100644 index 0000000..3ee2c06 --- /dev/null +++ b/server/configs/templates/fedora.conf @@ -0,0 +1,21 @@ +{ + "zoneTemplate" : "fedora.sh", + "initWithArgs" : [], + "requestedState" : "stopped", + "ipv4Gateway" : "", + "ipv4" : "", + "cpuQuotaForeground" : -1, + "cpuQuotaBackground" : 1000, + "privilege" : 10, + "vt" : -1, + "shutdownTimeout" : 10, + "switchToDefaultAfterTimeout" : true, + "runMountPoint" : "~NAME~/run", + "provisions" : [], + "permittedToSend" : [ "/tmp/.*" ], + "permittedToRecv" : [ "/tmp/.*" ], + "validLinkPrefixes" : [ "/tmp/", + "/run/", + "/opt/usr/data/", + "/opt/usr/dbsapce/" ] +} diff --git a/server/configs/templates/template.sh b/server/configs/templates/template.sh index 3bcf528..ab6edf7 100755 --- a/server/configs/templates/template.sh +++ b/server/configs/templates/template.sh @@ -23,6 +23,7 @@ do done br_name="virbr-${name}" +broadcast="$(echo $ipv4|cut -d . -f -3).255" # XXX assume rootfs if mounted from iso @@ -61,10 +62,11 @@ EOF # prepare pre start hook > ${path}/pre-start.sh cat <> ${path}/pre-start.sh -if [ -z "\$(/usr/sbin/ip link show | /bin/grep -P "${br_name}:")" ] +if ! /usr/sbin/ip link show ${br_name} &>/dev/null then /usr/sbin/ip link add name ${br_name} type bridge - /sbin/ifconfig ${br_name} ${ipv4_gateway} netmask 255.255.255.0 up + /usr/sbin/ip link set ${br_name} up + /usr/sbin/ip addr add ${ipv4}/24 broadcast ${broadcast} dev ${br_name} fi if [ -z "\$(/usr/sbin/iptables -t nat -S | /bin/grep MASQUERADE)" ] then diff --git a/server/configs/templates/tizen-common-wayland.sh b/server/configs/templates/tizen-common-wayland.sh index 30b90cd..05cca6d 100755 --- a/server/configs/templates/tizen-common-wayland.sh +++ b/server/configs/templates/tizen-common-wayland.sh @@ -76,6 +76,7 @@ if [ -z "$path" ]; then fi br_name="virbr-${name}" +broadcast="$(echo $ipv4|cut -d . -f -3).255" # Prepare zone rootfs ROOTFS_DIRS="\ @@ -279,10 +280,11 @@ EOF # Prepare zone hook files cat <>${path}/hooks/pre-start.sh -if [ -z "\$(/usr/sbin/ip link show | /bin/grep -P "${br_name}:")" ] +if ! /usr/sbin/ip link show ${br_name} &>/dev/null then /usr/sbin/ip link add name ${br_name} type bridge - /sbin/ifconfig ${br_name} ${ipv4_gateway} netmask 255.255.255.0 up + /usr/sbin/ip link set ${br_name} up + /usr/sbin/ip addr add ${ipv4}/24 broadcast ${broadcast} dev ${br_name} fi if [ -z "\$(/usr/sbin/iptables -t nat -S | /bin/grep MASQUERADE)" ] then diff --git a/server/configs/templates/default.conf b/server/configs/templates/tizen.conf similarity index 100% rename from server/configs/templates/default.conf rename to server/configs/templates/tizen.conf diff --git a/server/zones-manager.cpp b/server/zones-manager.cpp index a0a0205..ace7ee4 100644 --- a/server/zones-manager.cpp +++ b/server/zones-manager.cpp @@ -1206,20 +1206,22 @@ void ZonesManager::generateNewConfig(const std::string& id, ZONE_NAME_REGEX, id); - // generate first free VT number - const int freeVT = getVTForNewZone(); - LOGD("VT number: " << freeVT); - dynamicConfig.vt = freeVT; - - // generate third IP octet for network config - std::string thirdOctetStr = std::to_string(ZONE_IP_BASE_THIRD_OCTET + freeVT); - LOGD("IP third octet: " << thirdOctetStr); - dynamicConfig.ipv4Gateway = boost::regex_replace(dynamicConfig.ipv4Gateway, - ZONE_IP_THIRD_OCTET_REGEX, - thirdOctetStr); - dynamicConfig.ipv4 = boost::regex_replace(dynamicConfig.ipv4, - ZONE_IP_THIRD_OCTET_REGEX, - thirdOctetStr); + if (dynamicConfig.vt >= 0 && !dynamicConfig.ipv4Gateway.empty() && !dynamicConfig.ipv4.empty()) { + // generate first free VT number + const int freeVT = getVTForNewZone(); + LOGD("VT number: " << freeVT); + dynamicConfig.vt = freeVT; + + // generate third IP octet for network config + std::string thirdOctetStr = std::to_string(ZONE_IP_BASE_THIRD_OCTET + freeVT); + LOGD("IP third octet: " << thirdOctetStr); + dynamicConfig.ipv4Gateway = boost::regex_replace(dynamicConfig.ipv4Gateway, + ZONE_IP_THIRD_OCTET_REGEX, + thirdOctetStr); + dynamicConfig.ipv4 = boost::regex_replace(dynamicConfig.ipv4, + ZONE_IP_THIRD_OCTET_REGEX, + thirdOctetStr); + } // save dynamic config config::saveToKVStore(mConfig.dbPath, dynamicConfig, dbPrefix); -- 2.7.4 From 6085e73704a1016f792e954b583de790afe36667 Mon Sep 17 00:00:00 2001 From: Krzysztof Dynowski Date: Mon, 29 Jun 2015 16:13:12 +0200 Subject: [PATCH 16/16] Adjust to coding style rules [Feature] package includes in double quotes [Cause] n/a [Solution] replace tiangle brackets to double quotes [Verification] Build Change-Id: I7fc5815a3213566172dc8561240f463d610e48ea --- cli/command-line-interface.cpp | 2 +- client/vasum-client-impl.cpp | 9 ++++----- client/vasum-client-impl.hpp | 7 +++---- client/vasum-client.cpp | 2 +- common/lxc/zone.cpp | 3 +-- common/netlink/netlink-message.cpp | 3 +-- common/netlink/netlink.cpp | 2 +- server/netdev.cpp | 3 +-- tests/unit_tests/client/ut-client-utils.cpp | 4 ++-- tests/unit_tests/client/ut-client.cpp | 5 ++--- tests/unit_tests/ipc/ut-socket.cpp | 4 +--- tests/unit_tests/server/ut-zones-manager.cpp | 8 +++----- tests/unit_tests/socket_test_service/socket-test.cpp | 13 +++++-------- 13 files changed, 26 insertions(+), 39 deletions(-) diff --git a/cli/command-line-interface.cpp b/cli/command-line-interface.cpp index 0c28cdd..a8b7d1b 100644 --- a/cli/command-line-interface.cpp +++ b/cli/command-line-interface.cpp @@ -24,7 +24,7 @@ #include "config.hpp" #include "command-line-interface.hpp" -#include +#include "vasum-client.h" #include #include diff --git a/client/vasum-client-impl.cpp b/client/vasum-client-impl.cpp index 343fd1b..0e6e004 100644 --- a/client/vasum-client-impl.cpp +++ b/client/vasum-client-impl.cpp @@ -28,16 +28,15 @@ //vsm_get_poll_fd, vsm_enter_eventloop can't be used at the same time. //TODO: Make vsm_get_status_message thread-safe version (vsm_get_status_message_r) -#include +#include "config.hpp" #include "vasum-client-impl.hpp" #include "utils.hpp" #include "exception.hpp" #include "utils/exception.hpp" #include "logger/logger.hpp" - -#include -#include -#include +#include "host-ipc-definitions.hpp" +#include "ipc/client.hpp" +#include "api/messages.hpp" #include #include diff --git a/client/vasum-client-impl.hpp b/client/vasum-client-impl.hpp index 845cf29..c949ce2 100644 --- a/client/vasum-client-impl.hpp +++ b/client/vasum-client-impl.hpp @@ -27,10 +27,9 @@ #define VASUM_CLIENT_IMPL_HPP #include "vasum-client.h" - -#include -#include -#include +#include "ipc/epoll/thread-dispatcher.hpp" +#include "ipc/epoll/event-poll.hpp" +#include "ipc/client.hpp" #include #include diff --git a/client/vasum-client.cpp b/client/vasum-client.cpp index 4acd82a..0742cc0 100644 --- a/client/vasum-client.cpp +++ b/client/vasum-client.cpp @@ -23,7 +23,7 @@ * @brief This file contains the public API for Vasum Client */ -#include +#include "config.hpp" #include "vasum-client.h" #include "vasum-client-impl.hpp" diff --git a/common/lxc/zone.cpp b/common/lxc/zone.cpp index 845d959..65207bd 100644 --- a/common/lxc/zone.cpp +++ b/common/lxc/zone.cpp @@ -40,11 +40,10 @@ #ifdef USE_EXEC #include "utils/c-array.hpp" #endif +#include "utils/initctl.hpp" #include #include - -#include #include #include diff --git a/common/netlink/netlink-message.cpp b/common/netlink/netlink-message.cpp index c64199a..29b079a 100644 --- a/common/netlink/netlink-message.cpp +++ b/common/netlink/netlink-message.cpp @@ -26,8 +26,7 @@ #include "netlink-message.hpp" #include "netlink.hpp" #include "base-exception.hpp" - -#include +#include "logger/logger.hpp" #include #include diff --git a/common/netlink/netlink.cpp b/common/netlink/netlink.cpp index 6d7be95..b048031 100644 --- a/common/netlink/netlink.cpp +++ b/common/netlink/netlink.cpp @@ -29,8 +29,8 @@ #include "utils/make-clean.hpp" #include "utils/environment.hpp" #include "base-exception.hpp" +#include "logger/logger.hpp" -#include #include #include #include diff --git a/server/netdev.cpp b/server/netdev.cpp index b9a1389..8c53d38 100644 --- a/server/netdev.cpp +++ b/server/netdev.cpp @@ -29,8 +29,7 @@ #include "utils/exception.hpp" #include "utils.hpp" #include "exception.hpp" - -#include +#include "logger/logger.hpp" #include #include diff --git a/tests/unit_tests/client/ut-client-utils.cpp b/tests/unit_tests/client/ut-client-utils.cpp index 7a1b5ac..08d43ee 100644 --- a/tests/unit_tests/client/ut-client-utils.cpp +++ b/tests/unit_tests/client/ut-client-utils.cpp @@ -23,9 +23,9 @@ * @brief Unit tests of the client utils */ -#include +#include "config.hpp" #include "ut.hpp" -#include +#include "utils.hpp" BOOST_AUTO_TEST_SUITE(ClientUtils) diff --git a/tests/unit_tests/client/ut-client.cpp b/tests/unit_tests/client/ut-client.cpp index 65d6e49..5e1f4d8 100644 --- a/tests/unit_tests/client/ut-client.cpp +++ b/tests/unit_tests/client/ut-client.cpp @@ -23,10 +23,9 @@ * @brief Unit tests of the client C API */ -#include +#include "config.hpp" #include "ut.hpp" -#include - +#include "vasum-client.h" #include "utils/latch.hpp" #include "utils/scoped-dir.hpp" #include "zones-manager.hpp" diff --git a/tests/unit_tests/ipc/ut-socket.cpp b/tests/unit_tests/ipc/ut-socket.cpp index c2577ee..1aacd22 100644 --- a/tests/unit_tests/ipc/ut-socket.cpp +++ b/tests/unit_tests/ipc/ut-socket.cpp @@ -24,10 +24,8 @@ #include "config.hpp" #include "ut.hpp" - #include "ipc/internals/socket.hpp" - -#include +#include "socket-test.hpp" using namespace ipc; diff --git a/tests/unit_tests/server/ut-zones-manager.cpp b/tests/unit_tests/server/ut-zones-manager.cpp index 125d857..1fb3316 100644 --- a/tests/unit_tests/server/ut-zones-manager.cpp +++ b/tests/unit_tests/server/ut-zones-manager.cpp @@ -25,7 +25,6 @@ #include "config.hpp" #include "ut.hpp" - #include "zones-manager.hpp" #ifdef DBUS_CONNECTION // TODO: Switch to real power-manager dbus defs when they will be implemented in power-manager @@ -36,11 +35,10 @@ #include "dbus/exception.hpp" #endif //DBUS_CONNECTION #include "host-ipc-definitions.hpp" -#include -#include -#include +#include "api/messages.hpp" +#include "ipc/epoll/thread-dispatcher.hpp" +#include "ipc/client.hpp" #include "exception.hpp" - #include "utils/glib-loop.hpp" #include "config/exception.hpp" #include "utils/latch.hpp" diff --git a/tests/unit_tests/socket_test_service/socket-test.cpp b/tests/unit_tests/socket_test_service/socket-test.cpp index 1ffc09e..841cbfd 100644 --- a/tests/unit_tests/socket_test_service/socket-test.cpp +++ b/tests/unit_tests/socket_test_service/socket-test.cpp @@ -22,15 +22,12 @@ * @brief Mini-service for IPC Socket mechanism tests */ -#include +#include "config.hpp" #include "socket-test.hpp" - -#include -#include -#include - -#include -#include +#include "logger/logger.hpp" +#include "logger/backend-journal.hpp" +#include "ipc/internals/socket.hpp" +#include "ipc/exception.hpp" #include #include -- 2.7.4