From 02b066a8079eed2704dfc8afa1762bbc7faf29d4 Mon Sep 17 00:00:00 2001 From: Dariusz Michaluk Date: Tue, 3 Mar 2015 09:05:00 +0100 Subject: [PATCH 01/16] Disable dbus integration. [Bug/Feature] Disable dbus integration. [Cause] It is not used yet. Server and tests require a different dbus policy user, switching is inconvenient. [Solution] N/A [Verification] Build, run server, run tests Change-Id: I4e28b3b21d5eac6d23462ba2c4eb32aa7e32d4ed Signed-off-by: Dariusz Michaluk --- server/configs/lxc-templates/tizen-common-wayland.sh | 2 +- server/configs/templates/default.conf | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/server/configs/lxc-templates/tizen-common-wayland.sh b/server/configs/lxc-templates/tizen-common-wayland.sh index 9424dc4..5c572b7 100755 --- a/server/configs/lxc-templates/tizen-common-wayland.sh +++ b/server/configs/lxc-templates/tizen-common-wayland.sh @@ -297,6 +297,6 @@ ${path}/weston.ini etc/xdg/weston/weston.ini none ro,bind 0 0 devtmpfs dev devtmpfs rw,relatime,mode=755 0 0 devpts dev/pts devpts rw,relatime,gid=5,mode=620,ptmxmode=000 0 0 /sys/fs/smackfs sys/fs/smackfs none rw,bind 0 0 -/var/run/zones/${name}/run var/run none rw,bind 0 0 +#/var/run/zones/${name}/run var/run none rw,bind 0 0 #tmpfs run tmpfs rw,nosuid,nodev,mode=755 0 0 EOF diff --git a/server/configs/templates/default.conf b/server/configs/templates/default.conf index 9eb0e08..42f587b 100644 --- a/server/configs/templates/default.conf +++ b/server/configs/templates/default.conf @@ -9,7 +9,7 @@ "privilege" : 10, "vt" : 0, "switchToDefaultAfterTimeout" : true, - "enableDbusIntegration" : true, + "enableDbusIntegration" : false, "runMountPoint" : "~NAME~/run", "provisions" : [], "permittedToSend" : [ "/tmp/.*" ], -- 2.7.4 From 8c8d3f3e21999353f84edb837b7a161dda71d9b3 Mon Sep 17 00:00:00 2001 From: Dariusz Michaluk Date: Wed, 4 Mar 2015 10:26:16 +0100 Subject: [PATCH 02/16] Add timeout after zone start. [Bug/Feature] Add timeout after zone start. [Cause] N/A [Solution] N/A [Verification] Build, run server, run tests Change-Id: Ie6adace3d36ad98756d8efc823a056356f41d02d Signed-off-by: Dariusz Michaluk --- server/zone-admin.cpp | 13 +++++++++++++ server/zone-admin.hpp | 1 + 2 files changed, 14 insertions(+) diff --git a/server/zone-admin.cpp b/server/zone-admin.cpp index 519b172..8005fb4 100644 --- a/server/zone-admin.cpp +++ b/server/zone-admin.cpp @@ -35,6 +35,8 @@ #include #include +#include +#include namespace vasum { @@ -55,6 +57,7 @@ ZoneAdmin::ZoneAdmin(const std::string& zoneId, const ZoneConfig& config, const ZoneDynamicConfig& dynamicConfig) : mConfig(config), + mDynamicConfig(dynamicConfig), mZone(zonesPath, zoneId), mId(zoneId), mDetachOnExit(false), @@ -138,6 +141,16 @@ void ZoneAdmin::start() throw ZoneOperationException("Could not start zone"); } + // Wait until the full platform launch with graphical stack. + // VT should be activated by a graphical stack. + // If we do it with 'zoneToFocus.activateVT' before starting the graphical stack, + // graphical stack initialization failed and we finally switch to the black screen. + // Skip waiting when graphical stack is not running (unit tests). + if (mDynamicConfig.vt > 0) { + // TODO, timeout is a temporary solution + std::this_thread::sleep_for(std::chrono::milliseconds(4000)); + } + LOGD(mId << ": Started"); } diff --git a/server/zone-admin.hpp b/server/zone-admin.hpp index 44d2613..ade4585 100644 --- a/server/zone-admin.hpp +++ b/server/zone-admin.hpp @@ -166,6 +166,7 @@ public: private: const ZoneConfig& mConfig; + const ZoneDynamicConfig& mDynamicConfig; lxc::LxcZone mZone; const std::string mId; bool mDetachOnExit; -- 2.7.4 From 0e37ce4957c03d1c4077ef1211f3e3799d50ad2e Mon Sep 17 00:00:00 2001 From: Dariusz Michaluk Date: Wed, 4 Mar 2015 14:28:11 +0100 Subject: [PATCH 03/16] Fix building rpm packages. [Bug/Feature] Not deleted configs after rpm packages erasing. [Cause] Configs are not marked in spec file. [Solution] Move configs to a single directory. Mark all configs in spec file. [Verification] Build, install, uninstall Change-Id: I9728eb67e756ceca1d5cad8078d0040e7018975b Signed-off-by: Dariusz Michaluk --- CMakeLists.txt | 1 - packaging/vasum.spec | 12 ++++++------ tests/unit_tests/CMakeLists.txt | 4 ++-- 3 files changed, 8 insertions(+), 9 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index d5cb3e3..743860b 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -167,7 +167,6 @@ IF(NOT DEFINED DATA_DIR) ENDIF(NOT DEFINED DATA_DIR) SET(VSM_CONFIG_INSTALL_DIR ${SYSCONF_INSTALL_DIR}/vasum) -SET(VSM_DATA_INSTALL_DIR ${SHARE_INSTALL_PREFIX}/vasum) ADD_SUBDIRECTORY(${CLIENT_FOLDER}) ADD_SUBDIRECTORY(${SERVER_FOLDER}) diff --git a/packaging/vasum.spec b/packaging/vasum.spec index db8d6be..bd7e9f1 100644 --- a/packaging/vasum.spec +++ b/packaging/vasum.spec @@ -50,7 +50,7 @@ between them. A process from inside a zone can request a switch of context %{_unitdir}/vasum.service %{_unitdir}/vasum.socket %{_unitdir}/multi-user.target.wants/vasum.service -/etc/dbus-1/system.d/org.tizen.vasum.host.conf +%config /etc/dbus-1/system.d/org.tizen.vasum.host.conf %dir %{_datadir}/.zones %prep @@ -165,7 +165,7 @@ Zones support installed inside every zone. %files zone-support %manifest packaging/vasum-zone-support.manifest %defattr(644,root,root,755) -/etc/dbus-1/system.d/org.tizen.vasum.zone.conf +%config /etc/dbus-1/system.d/org.tizen.vasum.zone.conf ## Zone Daemon Package #################################################### @@ -182,7 +182,7 @@ Daemon running inside every zone. %manifest packaging/vasum-zone-daemon.manifest %defattr(644,root,root,755) %attr(755,root,root) %{_bindir}/vasum-zone-daemon -/etc/dbus-1/system.d/org.tizen.vasum.zone.daemon.conf +%config /etc/dbus-1/system.d/org.tizen.vasum.zone.daemon.conf ## Command Line Interface ###################################################### @@ -233,9 +233,9 @@ systemctl daemon-reload %attr(755,root,root) %{script_dir}/vsm_int_tests.py %attr(755,root,root) %{script_dir}/vsm_launch_test.py %{script_dir}/vsm_test_parser.py -%{_datadir}/vasum/tests -%attr(755,root,root) %{_datadir}/vasum/lxc-templates +%config /etc/vasum/tests +%attr(755,root,root) /etc/vasum/tests/lxc-templates %{python_sitelib}/vsm_integration_tests -/etc/dbus-1/system.d/org.tizen.vasum.tests.conf +%config /etc/dbus-1/system.d/org.tizen.vasum.tests.conf %{_unitdir}/vasum-socket-test.socket %{_unitdir}/vasum-socket-test.service diff --git a/tests/unit_tests/CMakeLists.txt b/tests/unit_tests/CMakeLists.txt index fc96586..2a561ed 100644 --- a/tests/unit_tests/CMakeLists.txt +++ b/tests/unit_tests/CMakeLists.txt @@ -67,8 +67,8 @@ TARGET_LINK_LIBRARIES(${UT_SERVER_CODENAME} ${UT_SERVER_DEPS_LIBRARIES} ${Boost_ TARGET_LINK_LIBRARIES(${SOCKET_TEST_CODENAME} ${UT_SERVER_DEPS_LIBRARIES} ${Boost_LIBRARIES}) ## Subdirectories ############################################################## -SET(VSM_TEST_CONFIG_INSTALL_DIR ${VSM_DATA_INSTALL_DIR}/tests) -SET(VSM_TEST_LXC_TEMPLATES_INSTALL_DIR ${VSM_DATA_INSTALL_DIR}/lxc-templates/tests) +SET(VSM_TEST_CONFIG_INSTALL_DIR ${VSM_CONFIG_INSTALL_DIR}/tests) +SET(VSM_TEST_LXC_TEMPLATES_INSTALL_DIR ${VSM_CONFIG_INSTALL_DIR}/tests/lxc-templates) ADD_DEFINITIONS(-DVSM_TEST_CONFIG_INSTALL_DIR="${VSM_TEST_CONFIG_INSTALL_DIR}") ADD_DEFINITIONS(-DVSM_TEST_LXC_TEMPLATES_INSTALL_DIR="${VSM_TEST_LXC_TEMPLATES_INSTALL_DIR}") -- 2.7.4 From 99314f1553605b796e6ae5b90466113f98e79360 Mon Sep 17 00:00:00 2001 From: Piotr Bartosiewicz Date: Tue, 10 Mar 2015 12:01:48 +0100 Subject: [PATCH 04/16] IPC works on epoll [Bug/Feature] N/A [Cause] N/A [Solution] N/A [Verification] Run tests Change-Id: I6f6b5a7a70cecbecbdf0c502d0f8618577892a48 --- common/epoll/event-poll.cpp | 15 +- ...lib-poll-dispatcher.cpp => glib-dispatcher.cpp} | 8 +- ...lib-poll-dispatcher.hpp => glib-dispatcher.hpp} | 12 +- ...d-poll-dispatcher.cpp => thread-dispatcher.cpp} | 8 +- ...d-poll-dispatcher.hpp => thread-dispatcher.hpp} | 12 +- common/ipc/client.cpp | 71 +++--- common/ipc/client.hpp | 35 +-- common/ipc/internals/acceptor.cpp | 92 +------- common/ipc/internals/acceptor.hpp | 34 --- common/ipc/internals/processor.cpp | 148 ++---------- common/ipc/internals/processor.hpp | 18 +- common/ipc/service.cpp | 97 +++----- common/ipc/service.hpp | 35 +-- tests/scripts/vsm_test_parser.py | 2 +- tests/unit_tests/epoll/ut-event-poll.cpp | 14 +- tests/unit_tests/ipc/ut-ipc.cpp | 250 ++++++++++----------- tests/unit_tests/ut.hpp | 14 ++ 17 files changed, 271 insertions(+), 594 deletions(-) rename common/epoll/{glib-poll-dispatcher.cpp => glib-dispatcher.cpp} (91%) rename common/epoll/{glib-poll-dispatcher.hpp => glib-dispatcher.hpp} (84%) rename common/epoll/{thread-poll-dispatcher.cpp => thread-dispatcher.cpp} (88%) rename common/epoll/{thread-poll-dispatcher.hpp => thread-dispatcher.hpp} (83%) diff --git a/common/epoll/event-poll.cpp b/common/epoll/event-poll.cpp index dc1c1bc..9eb9fa0 100644 --- a/common/epoll/event-poll.cpp +++ b/common/epoll/event-poll.cpp @@ -49,6 +49,9 @@ EventPoll::~EventPoll() { if (!mCallbacks.empty()) { LOGW("Not removed callbacks: " << mCallbacks.size()); + for (const auto& item : mCallbacks) { + LOGT("Not removed fd: " << item.first); + } assert(0 && "Not removed callbacks left"); } utils::close(mPollFD); @@ -73,7 +76,7 @@ void EventPoll::addFD(const int fd, const Events events, Callback&& callback) } mCallbacks.insert({fd, std::make_shared(std::move(callback))}); - LOGT("Callback added for " << fd); + LOGT("Callback added for fd: " << fd); } void EventPoll::removeFD(const int fd) @@ -87,7 +90,7 @@ void EventPoll::removeFD(const int fd) } mCallbacks.erase(iter); removeFDInternal(fd); - LOGT("Callback removed for " << fd); + LOGT("Callback removed for fd: " << fd); } bool EventPoll::dispatchIteration(const int timeoutMs) @@ -115,7 +118,13 @@ bool EventPoll::dispatchIteration(const int timeoutMs) // add ref because removeFD(self) can be called inside callback std::shared_ptr callback(iter->second); - return (*callback)(event.data.fd, event.events); + try { + LOGT("Dispatch fd: " << event.data.fd << ", events: " << eventsToString(event.events)); + return (*callback)(event.data.fd, event.events); + } catch (std::exception& e) { + LOGE("Got unexpected exception: " << e.what()); + assert(0 && "Callback should not throw any exceptions"); + } } } diff --git a/common/epoll/glib-poll-dispatcher.cpp b/common/epoll/glib-dispatcher.cpp similarity index 91% rename from common/epoll/glib-poll-dispatcher.cpp rename to common/epoll/glib-dispatcher.cpp index cde535d..9567abb 100644 --- a/common/epoll/glib-poll-dispatcher.cpp +++ b/common/epoll/glib-dispatcher.cpp @@ -23,13 +23,13 @@ */ #include "config.hpp" -#include "epoll/glib-poll-dispatcher.hpp" +#include "epoll/glib-dispatcher.hpp" #include "utils/callback-wrapper.hpp" namespace vasum { namespace epoll { -GlibPollDispatcher::GlibPollDispatcher() +GlibDispatcher::GlibDispatcher() { mChannel = g_io_channel_unix_new(mPoll.getPollFD()); @@ -50,14 +50,14 @@ GlibPollDispatcher::GlibPollDispatcher() &utils::deleteCallbackWrapper); } -GlibPollDispatcher::~GlibPollDispatcher() +GlibDispatcher::~GlibDispatcher() { g_source_remove(mWatchId); g_io_channel_unref(mChannel); // mGuard destructor will wait for full unregister of dispatchCallback } -EventPoll& GlibPollDispatcher::getPoll() +EventPoll& GlibDispatcher::getPoll() { return mPoll; } diff --git a/common/epoll/glib-poll-dispatcher.hpp b/common/epoll/glib-dispatcher.hpp similarity index 84% rename from common/epoll/glib-poll-dispatcher.hpp rename to common/epoll/glib-dispatcher.hpp index cf300bb..0fa7b3a 100644 --- a/common/epoll/glib-poll-dispatcher.hpp +++ b/common/epoll/glib-dispatcher.hpp @@ -22,8 +22,8 @@ * @brief glib epoll dispatcher */ -#ifndef COMMON_EPOLL_GLIB_POLL_DISPATCHER_HPP -#define COMMON_EPOLL_GLIB_POLL_DISPATCHER_HPP +#ifndef COMMON_EPOLL_GLIB_DISPATCHER_HPP +#define COMMON_EPOLL_GLIB_DISPATCHER_HPP #include "epoll/event-poll.hpp" #include "utils/callback-guard.hpp" @@ -36,10 +36,10 @@ namespace epoll { /** * Will dispatch poll events in glib thread */ -class GlibPollDispatcher { +class GlibDispatcher { public: - GlibPollDispatcher(); - ~GlibPollDispatcher(); + GlibDispatcher(); + ~GlibDispatcher(); EventPoll& getPoll(); private: @@ -53,4 +53,4 @@ private: } // namespace epoll } // namespace vasum -#endif // COMMON_UTILS_GLIB_POLL_DISPATCHER_HPP +#endif // COMMON_UTILS_GLIB_DISPATCHER_HPP diff --git a/common/epoll/thread-poll-dispatcher.cpp b/common/epoll/thread-dispatcher.cpp similarity index 88% rename from common/epoll/thread-poll-dispatcher.cpp rename to common/epoll/thread-dispatcher.cpp index 797a8c4..a82cad8 100644 --- a/common/epoll/thread-poll-dispatcher.cpp +++ b/common/epoll/thread-dispatcher.cpp @@ -23,12 +23,12 @@ */ #include "config.hpp" -#include "epoll/thread-poll-dispatcher.hpp" +#include "epoll/thread-dispatcher.hpp" namespace vasum { namespace epoll { -ThreadPollDispatcher::ThreadPollDispatcher() +ThreadDispatcher::ThreadDispatcher() { auto controlCallback = [this](int, Events) -> bool { mStopEvent.receive(); @@ -41,14 +41,14 @@ ThreadPollDispatcher::ThreadPollDispatcher() }); } -ThreadPollDispatcher::~ThreadPollDispatcher() +ThreadDispatcher::~ThreadDispatcher() { mStopEvent.send(); mThread.join(); mPoll.removeFD(mStopEvent.getFD()); } -EventPoll& ThreadPollDispatcher::getPoll() +EventPoll& ThreadDispatcher::getPoll() { return mPoll; } diff --git a/common/epoll/thread-poll-dispatcher.hpp b/common/epoll/thread-dispatcher.hpp similarity index 83% rename from common/epoll/thread-poll-dispatcher.hpp rename to common/epoll/thread-dispatcher.hpp index af6b278..7d0f30d 100644 --- a/common/epoll/thread-poll-dispatcher.hpp +++ b/common/epoll/thread-dispatcher.hpp @@ -22,8 +22,8 @@ * @brief Thread epoll dispatcher */ -#ifndef COMMON_EPOLL_THREAD_POLL_DISPATCHER_HPP -#define COMMON_EPOLL_THREAD_POLL_DISPATCHER_HPP +#ifndef COMMON_EPOLL_THREAD_DISPATCHER_HPP +#define COMMON_EPOLL_THREAD_DISPATCHER_HPP #include "epoll/event-poll.hpp" #include "utils/eventfd.hpp" @@ -36,10 +36,10 @@ namespace epoll { /** * Will dispatch poll events in a newly created thread */ -class ThreadPollDispatcher { +class ThreadDispatcher { public: - ThreadPollDispatcher(); - ~ThreadPollDispatcher(); + ThreadDispatcher(); + ~ThreadDispatcher(); EventPoll& getPoll(); private: @@ -51,4 +51,4 @@ private: } // namespace epoll } // namespace vasum -#endif // COMMON_EPOLL_THREAD_POLL_DISPATCHER_HPP +#endif // COMMON_EPOLL_THREAD_DISPATCHER_HPP diff --git a/common/ipc/client.cpp b/common/ipc/client.cpp index 6669d8a..abecb71 100644 --- a/common/ipc/client.cpp +++ b/common/ipc/client.cpp @@ -31,8 +31,9 @@ namespace vasum { namespace ipc { -Client::Client(const std::string& socketPath) - : mProcessor("[CLIENT] "), +Client::Client(epoll::EventPoll& eventPoll, const std::string& socketPath) + : mEventPoll(eventPoll), + mProcessor("[CLIENT] "), mSocketPath(socketPath) { LOGS("Client Constructor"); @@ -50,14 +51,19 @@ Client::~Client() } } -void Client::start(const bool usesExternalPolling) +void Client::start() { + if (mProcessor.isStarted()) { + return; + } LOGS("Client start"); // Initialize the connection with the server - if (usesExternalPolling) { - startPoll(); - } - mProcessor.start(usesExternalPolling); + auto handleEvent = [&](int, epoll::Events) -> bool { + mProcessor.handleEvent(); + return true; + }; + mEventPoll.addFD(mProcessor.getEventFD(), EPOLLIN, handleEvent); + mProcessor.start(); LOGD("Connecting to " + mSocketPath); auto socketPtr = std::make_shared(Socket::connectSocket(mSocketPath)); @@ -71,34 +77,18 @@ bool Client::isStarted() void Client::stop() { + if (!mProcessor.isStarted()) { + return; + } LOGS("Client stop"); mProcessor.stop(); - if (mIPCGSourcePtr) { - stopPoll(); - } -} - -void Client::startPoll() -{ - LOGS("Client startPoll"); - using namespace std::placeholders; - mIPCGSourcePtr = IPCGSource::create(std::bind(&Client::handle, this, _1, _2)); - mIPCGSourcePtr->addFD(mProcessor.getEventFD()); - mIPCGSourcePtr->attach(); + mEventPoll.removeFD(mProcessor.getEventFD()); } -void Client::stopPoll() -{ - LOGS("Client stopPoll"); - - mIPCGSourcePtr->removeFD(mProcessor.getEventFD()); - mIPCGSourcePtr->detach(); - mIPCGSourcePtr.reset(); -} - -void Client::handle(const FileDescriptor fd, const short pollEvent) +void Client::handle(const FileDescriptor fd, const epoll::Events pollEvents) { + //TODO remove handle method LOGS("Client handle"); if (!isStarted()) { @@ -106,17 +96,12 @@ void Client::handle(const FileDescriptor fd, const short pollEvent) return; } - if (fd == mProcessor.getEventFD() && (pollEvent & POLLIN)) { - mProcessor.handleEvent(); - return; - - } else if (pollEvent & POLLIN) { + if (pollEvents & EPOLLIN) { mProcessor.handleInput(fd); - return; + } - } else if (pollEvent & POLLHUP) { + if ((pollEvents & EPOLLHUP) || (pollEvents & EPOLLRDHUP)) { mProcessor.handleLostConnection(fd); - return; } } @@ -124,9 +109,11 @@ void Client::setNewPeerCallback(const PeerCallback& newPeerCallback) { LOGS("Client setNewPeerCallback"); auto callback = [newPeerCallback, this](PeerID peerID, FileDescriptor fd) { - if (mIPCGSourcePtr) { - mIPCGSourcePtr->addFD(fd); - } + auto handleFd = [&](FileDescriptor fd, epoll::Events events) -> bool { + handle(fd, events); + return true; + }; + mEventPoll.addFD(fd, EPOLLIN | EPOLLHUP | EPOLLRDHUP, handleFd); if (newPeerCallback) { newPeerCallback(peerID, fd); } @@ -138,9 +125,7 @@ void Client::setRemovedPeerCallback(const PeerCallback& removedPeerCallback) { LOGS("Client setRemovedPeerCallback"); auto callback = [removedPeerCallback, this](PeerID peerID, FileDescriptor fd) { - if (mIPCGSourcePtr) { - mIPCGSourcePtr->removeFD(fd); - } + mEventPoll.removeFD(fd); if (removedPeerCallback) { removedPeerCallback(peerID, fd); } diff --git a/common/ipc/client.hpp b/common/ipc/client.hpp index 321b4da..a3342b6 100644 --- a/common/ipc/client.hpp +++ b/common/ipc/client.hpp @@ -26,9 +26,9 @@ #define COMMON_IPC_CLIENT_HPP #include "ipc/internals/processor.hpp" -#include "ipc/ipc-gsource.hpp" #include "ipc/types.hpp" #include "ipc/result.hpp" +#include "epoll/event-poll.hpp" #include "logger/logger.hpp" #include @@ -40,28 +40,24 @@ namespace ipc { * This class wraps communication via UX sockets for client applications. * It uses serialization mechanism from libConfig. * - * There is one additional thread: - * - PROCESSOR is responsible for the communication and calling the callbacks - * * For message format @see ipc::Processor */ class Client { public: /** + * @param eventPoll event poll * @param serverPath path to the server's socket */ - Client(const std::string& serverPath); + Client(epoll::EventPoll& eventPoll, const std::string& serverPath); ~Client(); Client(const Client&) = delete; Client& operator=(const Client&) = delete; /** - * Starts the worker thread - * - * @param usesExternalPolling internal or external polling is used + * Starts processing */ - void start(const bool usesExternalPolling = false); + void start(); /** * @return is the communication thread running @@ -69,21 +65,11 @@ public: bool isStarted(); /** - * Stops all worker thread + * Stops processing */ void stop(); /** - * Used with an external polling loop. - * Handles one event from the file descriptor. - * - * @param fd file descriptor - * @param pollEvent event on the fd. Defined in poll.h - * - */ - void handle(const FileDescriptor fd, const short pollEvent); - - /** * Set the callback called for each new connection to a peer * * @param newPeerCallback the callback @@ -170,14 +156,13 @@ public: const std::shared_ptr& data); private: - - void startPoll(); - void stopPoll(); - + epoll::EventPoll& mEventPoll; PeerID mServiceID; Processor mProcessor; std::string mSocketPath; - IPCGSource::Pointer mIPCGSourcePtr; + + void handle(const FileDescriptor fd, const epoll::Events pollEvents); + }; template diff --git a/common/ipc/internals/acceptor.cpp b/common/ipc/internals/acceptor.cpp index ecb2210..15b9ad8 100644 --- a/common/ipc/internals/acceptor.cpp +++ b/common/ipc/internals/acceptor.cpp @@ -24,21 +24,14 @@ #include "config.hpp" -#include "ipc/exception.hpp" #include "ipc/internals/acceptor.hpp" #include "logger/logger.hpp" -#include -#include -#include -#include - namespace vasum { namespace ipc { Acceptor::Acceptor(const std::string& socketPath, const NewConnectionCallback& newConnectionCallback) - : mIsRunning(false), - mNewConnectionCallback(newConnectionCallback), + : mNewConnectionCallback(newConnectionCallback), mSocket(Socket::createSocket(socketPath)) { LOGT("Creating Acceptor for socket " << socketPath); @@ -46,98 +39,15 @@ Acceptor::Acceptor(const std::string& socketPath, const NewConnectionCallback& n Acceptor::~Acceptor() { - LOGT("Destroying Acceptor"); - try { - stop(); - } catch (std::exception& e) { - LOGE("Error in destructor: " << e.what()); - } LOGT("Destroyed Acceptor"); } -void Acceptor::start() -{ - LOGT("Starting Acceptor"); - if (!mThread.joinable()) { - mThread = std::thread(&Acceptor::run, this); - } - LOGT("Started Acceptor"); -} - -void Acceptor::stop() -{ - LOGT("Stopping Acceptor"); - - if (mThread.joinable()) { - mEventQueue.send(Event::FINISH); - LOGT("Waiting for Acceptor to finish"); - mThread.join(); - } - - LOGT("Stopped Acceptor"); -} - -void Acceptor::run() -{ - // Setup polling structure - std::vector fds(2); - - fds[0].fd = mEventQueue.getFD(); - fds[0].events = POLLIN; - - fds[1].fd = mSocket.getFD(); - fds[1].events = POLLIN; - - mIsRunning = true; - while (mIsRunning) { - LOGT("Waiting for new connections..."); - - int ret = ::poll(fds.data(), fds.size(), -1 /*blocking call*/); - - LOGT("...Incoming connection!"); - - if (ret == -1 || ret == 0) { - if (errno == EINTR) { - continue; - } - LOGE("Error in poll: " << std::string(strerror(errno))); - throw IPCException("Error in poll: " + std::string(strerror(errno))); - } - - // Check for incoming connections - if (fds[1].revents & POLLIN) { - fds[1].revents = 0; - handleConnection(); - } - - // Check for incoming events - if (fds[0].revents & POLLIN) { - fds[0].revents = 0; - handleEvent(); - } - } - LOGT("Exiting run"); -} - void Acceptor::handleConnection() { std::shared_ptr tmpSocket = mSocket.accept(); mNewConnectionCallback(tmpSocket); } -void Acceptor::handleEvent() -{ - if (mEventQueue.receive() == Event::FINISH) { - LOGD("Event FINISH"); - mIsRunning = false; - } -} - -FileDescriptor Acceptor::getEventFD() -{ - return mEventQueue.getFD(); -} - FileDescriptor Acceptor::getConnectionFD() { return mSocket.getFD(); diff --git a/common/ipc/internals/acceptor.hpp b/common/ipc/internals/acceptor.hpp index f87a0bb..a6e9ec8 100644 --- a/common/ipc/internals/acceptor.hpp +++ b/common/ipc/internals/acceptor.hpp @@ -28,11 +28,9 @@ #include "config.hpp" #include "ipc/internals/socket.hpp" -#include "ipc/internals/event-queue.hpp" #include "ipc/types.hpp" #include -#include namespace vasum { namespace ipc { @@ -59,51 +57,19 @@ public: Acceptor& operator=(const Acceptor&) = delete; /** - * Starts the thread accepting the new connections. - */ - void start(); - - /** - * Stops the accepting thread. - */ - void stop(); - - /** * Handle one incoming connection. * Used with external polling */ void handleConnection(); /** - * Handle one event from the internal event's queue - * Used with external polling - */ - void handleEvent(); - - /** - * @return file descriptor of internal event's queue - */ - FileDescriptor getEventFD(); - - /** * @return file descriptor for the connection socket */ FileDescriptor getConnectionFD(); private: - enum class Event : int { - FINISH // Shutdown request - }; - - bool mIsRunning; - NewConnectionCallback mNewConnectionCallback; Socket mSocket; - - EventQueue mEventQueue; - std::thread mThread; - - void run(); }; } // namespace ipc diff --git a/common/ipc/internals/processor.cpp b/common/ipc/internals/processor.cpp index 93f721f..587723c 100644 --- a/common/ipc/internals/processor.cpp +++ b/common/ipc/internals/processor.cpp @@ -26,7 +26,6 @@ #include "ipc/exception.hpp" #include "ipc/internals/processor.hpp" -#include "utils/signal.hpp" #include "utils/exception.hpp" #include @@ -65,8 +64,6 @@ Processor::Processor(const std::string& logName, { LOGS(mLogPrefix + "Processor Constructor"); - utils::signalBlock(SIGPIPE); - using namespace std::placeholders; setSignalHandlerInternal(REGISTER_SIGNAL_METHOD_ID, std::bind(&Processor::onNewSignals, this, _1, _2)); @@ -104,7 +101,7 @@ bool Processor::isStarted() return mIsRunning; } -void Processor::start(bool usesExternalPolling) +void Processor::start() { LOGS(mLogPrefix + "Processor start"); @@ -112,10 +109,6 @@ void Processor::start(bool usesExternalPolling) if (!mIsRunning) { LOGI(mLogPrefix + "Processor start"); mIsRunning = true; - mUsesExternalPolling = usesExternalPolling; - if (!usesExternalPolling) { - mThread = std::thread(&Processor::run, this); - } } } @@ -133,15 +126,12 @@ void Processor::stop() LOGD(mLogPrefix + "Waiting for the Processor to stop"); - if (mThread.joinable()) { - mThread.join(); - } else { - // Wait till the FINISH request is served - Lock lock(mStateMutex); - conditionPtr->wait(lock, [this]() { - return !mIsRunning; - }); - } + // Wait till the FINISH request is served + Lock lock(mStateMutex); + conditionPtr->wait(lock, [this]() { + return !mIsRunning; + }); + assert(mPeerInfo.empty()); } } @@ -204,7 +194,8 @@ PeerID Processor::addPeer(const std::shared_ptr& socketPtr) auto requestPtr = std::make_shared(socketPtr); mRequestQueue.pushBack(Event::ADD_PEER, requestPtr); - LOGI(mLogPrefix + "Add Peer Request. Id: " << requestPtr->peerID); + LOGI(mLogPrefix + "Add Peer Request. Id: " << requestPtr->peerID + << ", fd: " << socketPtr->getFD()); return requestPtr->peerID; } @@ -233,14 +224,14 @@ void Processor::removePeerSyncInternal(const PeerID peerID, Lock& lock) void Processor::removePeerInternal(Peers::iterator peerIt, const std::exception_ptr& exceptionPtr) { - LOGS(mLogPrefix + "Processor removePeerInternal peerID: " << peerIt->peerID); - LOGI(mLogPrefix + "Removing peer. peerID: " << peerIt->peerID); - if (peerIt == mPeerInfo.end()) { LOGW("Peer already removed"); return; } + LOGS(mLogPrefix + "Processor removePeerInternal peerID: " << peerIt->peerID); + LOGI(mLogPrefix + "Removing peer. peerID: " << peerIt->peerID); + // Remove from signal addressees for (auto it = mSignalsPeers.begin(); it != mSignalsPeers.end();) { it->second.remove(peerIt->peerID); @@ -270,100 +261,6 @@ void Processor::removePeerInternal(Peers::iterator peerIt, const std::exception_ mPeerInfo.erase(peerIt); } -void Processor::resetPolling() -{ - LOGS(mLogPrefix + "Processor resetPolling"); - - if (mUsesExternalPolling) { - return; - } - - // Setup polling on eventfd and sockets - mFDs.resize(mPeerInfo.size() + 1); - LOGI(mLogPrefix + "Reseting mFDS.size: " << mFDs.size()); - - mFDs[0].fd = mRequestQueue.getFD(); - mFDs[0].events = POLLIN; - - for (unsigned int i = 1; i < mFDs.size(); ++i) { - auto fd = mPeerInfo[i - 1].socketPtr->getFD(); - - LOGI(mLogPrefix + "Reseting fd: " << fd); - - mFDs[i].fd = fd; - mFDs[i].events = POLLIN | POLLHUP; // Listen for input events - // TODO: It's possible to block on writing to fd. Maybe listen for POLLOUT too? - } -} - -void Processor::run() -{ - LOGS(mLogPrefix + "Processor run"); - - { - Lock lock(mStateMutex); - resetPolling(); - } - - while (isStarted()) { - LOGT(mLogPrefix + "Waiting for communication..."); - int ret = poll(mFDs.data(), mFDs.size(), -1 /*blocking call*/); - LOGT(mLogPrefix + "... incoming communication!"); - if (ret == -1 || ret == 0) { - if (errno == EINTR) { - continue; - } - LOGE(mLogPrefix + "Error in poll: " << std::string(strerror(errno))); - throw IPCException("Error in poll: " + std::string(strerror(errno))); - } - - // Check for lost connections: - if (handleLostConnections()) { - // mFDs changed - resetPolling(); - continue; - } - - // Check for incoming data. - if (handleInputs()) { - // mFDs changed - resetPolling(); - continue; - } - - // Check for incoming events - if (mFDs[0].revents & POLLIN) { - mFDs[0].revents &= ~(POLLIN); - if (handleEvent()) { - // mFDs changed - resetPolling(); - continue; - } - } - - } -} - -bool Processor::handleLostConnections() -{ - Lock lock(mStateMutex); - - bool isPeerRemoved = false; - - for (unsigned int i = 1; i < mFDs.size(); ++i) { - if (mFDs[i].revents & POLLHUP) { - auto peerIt = getPeerInfoIterator(mFDs[i].fd); - LOGI(mLogPrefix + "Lost connection to peer: " << peerIt->peerID); - mFDs[i].revents &= ~(POLLHUP); - removePeerInternal(peerIt, - std::make_exception_ptr(IPCPeerDisconnectedException())); - isPeerRemoved = true; - } - } - - return isPeerRemoved; -} - bool Processor::handleLostConnection(const FileDescriptor fd) { Lock lock(mStateMutex); @@ -373,21 +270,6 @@ bool Processor::handleLostConnection(const FileDescriptor fd) return true; } -bool Processor::handleInputs() -{ - // Lock not needed, mFDs won't be changed by handleInput - - bool pollChanged = false; - for (unsigned int i = 1; i < mFDs.size(); ++i) { - if (mFDs[i].revents & POLLIN) { - mFDs[i].revents &= ~(POLLIN); - pollChanged = pollChanged || handleInput(mFDs[i].fd); - } - } - - return pollChanged; -} - bool Processor::handleInput(const FileDescriptor fd) { LOGS(mLogPrefix + "Processor handleInput fd: " << fd); @@ -795,6 +677,12 @@ bool Processor::onFinishRequest(FinishRequest& request) } } + // Close peers + while (!mPeerInfo.empty()) { + removePeerInternal(--mPeerInfo.end(), + std::make_exception_ptr(IPCClosingException())); + } + mIsRunning = false; request.conditionPtr->notify_all(); diff --git a/common/ipc/internals/processor.hpp b/common/ipc/internals/processor.hpp index 86a3f42..6e0ae81 100644 --- a/common/ipc/internals/processor.hpp +++ b/common/ipc/internals/processor.hpp @@ -43,7 +43,6 @@ #include "logger/logger-scope.hpp" #include -#include #include #include #include @@ -136,12 +135,9 @@ public: /** - * Start the processing thread. - * Quits immediately after starting the thread. - * - * @param usesExternalPolling internal or external polling is used + * Start processing. */ - void start(const bool usesExternalPolling); + void start(); /** * @return is processor running @@ -432,14 +428,12 @@ private: RequestQueue mRequestQueue; bool mIsRunning; - bool mUsesExternalPolling; std::unordered_map> mMethodsCallbacks; std::unordered_map> mSignalsCallbacks; std::unordered_map> mSignalsPeers; Peers mPeerInfo; - std::vector mFDs; std::unordered_map mReturnCallbacks; @@ -451,8 +445,6 @@ private: unsigned int mMaxNumberOfPeers; - std::thread mThread; - template void setMethodHandlerInternal(const MethodID methodID, const typename MethodHandler::type& process); @@ -466,8 +458,6 @@ private: const PeerID peerID, const std::shared_ptr& data); - void run(); - // Request handlers bool onMethodRequest(MethodRequest& request); bool onSignalRequest(SignalRequest& request); @@ -476,9 +466,6 @@ private: bool onSendResultRequest(SendResultRequest& request); bool onFinishRequest(FinishRequest& request); - bool handleLostConnections(); - bool handleInputs(); - bool onReturnValue(Peers::iterator& peerIt, const MessageID messageID); bool onRemoteMethod(Peers::iterator& peerIt, @@ -489,7 +476,6 @@ private: const MethodID methodID, const MessageID messageID, std::shared_ptr signalCallbacks); - void resetPolling(); void removePeerInternal(Peers::iterator peerIt, const std::exception_ptr& exceptionPtr); diff --git a/common/ipc/service.cpp b/common/ipc/service.cpp index 442d804..c436726 100644 --- a/common/ipc/service.cpp +++ b/common/ipc/service.cpp @@ -33,10 +33,12 @@ using namespace std::placeholders; namespace vasum { namespace ipc { -Service::Service(const std::string& socketPath, +Service::Service(epoll::EventPoll& eventPoll, + const std::string& socketPath, const PeerCallback& addPeerCallback, const PeerCallback& removePeerCallback) - : mProcessor("[SERVICE] "), + : mEventPoll(eventPoll), + mProcessor("[SERVICE] "), mAcceptor(socketPath, std::bind(&Processor::addPeer, &mProcessor, _1)) { @@ -55,19 +57,23 @@ Service::~Service() } } -void Service::start(const bool usesExternalPolling) +void Service::start() { - LOGS("Service start"); - if (usesExternalPolling) { - startPoll(); - } - mProcessor.start(usesExternalPolling); - - // There can be an incoming connection from mAcceptor before mProcessor is listening, - // but it's OK. It will handle the connection when ready. So no need to wait for mProcessor. - if (!usesExternalPolling) { - mAcceptor.start(); + if (mProcessor.isStarted()) { + return; } + LOGS("Service start"); + auto handleConnection = [&](int, epoll::Events) -> bool { + mAcceptor.handleConnection(); + return true; + }; + auto handleProcessorEvent = [&](int, epoll::Events) -> bool { + mProcessor.handleEvent(); + return true; + }; + mEventPoll.addFD(mAcceptor.getConnectionFD(), EPOLLIN, handleConnection); + mEventPoll.addFD(mProcessor.getEventFD(), EPOLLIN, handleProcessorEvent); + mProcessor.start(); } bool Service::isStarted() @@ -77,39 +83,19 @@ bool Service::isStarted() void Service::stop() { + if (!mProcessor.isStarted()) { + return; + } LOGS("Service stop"); - mAcceptor.stop(); mProcessor.stop(); - if (mIPCGSourcePtr) { - stopPoll(); - } -} - -void Service::startPoll() -{ - LOGS("Service startPoll"); - - mIPCGSourcePtr = IPCGSource::create(std::bind(&Service::handle, this, _1, _2)); - mIPCGSourcePtr->addFD(mAcceptor.getEventFD()); - mIPCGSourcePtr->addFD(mAcceptor.getConnectionFD()); - mIPCGSourcePtr->addFD(mProcessor.getEventFD()); - mIPCGSourcePtr->attach(); + mEventPoll.removeFD(mAcceptor.getConnectionFD()); + mEventPoll.removeFD(mProcessor.getEventFD()); } -void Service::stopPoll() -{ - LOGS("Service stopPoll"); - - mIPCGSourcePtr->removeFD(mAcceptor.getEventFD()); - mIPCGSourcePtr->removeFD(mAcceptor.getConnectionFD()); - mIPCGSourcePtr->removeFD(mProcessor.getEventFD()); - mIPCGSourcePtr->detach(); - mIPCGSourcePtr.reset(); -} - -void Service::handle(const FileDescriptor fd, const short pollEvent) +void Service::handle(const FileDescriptor fd, const epoll::Events pollEvents) { + //TODO remove handle method LOGS("Service handle"); if (!isStarted()) { @@ -117,25 +103,12 @@ void Service::handle(const FileDescriptor fd, const short pollEvent) return; } - if (fd == mProcessor.getEventFD() && (pollEvent & POLLIN)) { - mProcessor.handleEvent(); - return; - - } else if (fd == mAcceptor.getConnectionFD() && (pollEvent & POLLIN)) { - mAcceptor.handleConnection(); - return; - - } else if (fd == mAcceptor.getEventFD() && (pollEvent & POLLIN)) { - mAcceptor.handleEvent(); - return; - - } else if (pollEvent & POLLIN) { + if (pollEvents & EPOLLIN) { mProcessor.handleInput(fd); - return; + } - } else if (pollEvent & POLLHUP) { + if ((pollEvents & EPOLLHUP) || (pollEvents & EPOLLRDHUP)) { mProcessor.handleLostConnection(fd); - return; } } @@ -143,9 +116,11 @@ void Service::setNewPeerCallback(const PeerCallback& newPeerCallback) { LOGS("Service setNewPeerCallback"); auto callback = [newPeerCallback, this](PeerID peerID, FileDescriptor fd) { - if (mIPCGSourcePtr) { - mIPCGSourcePtr->addFD(fd); - } + auto handleFd = [&](FileDescriptor fd, epoll::Events events) -> bool { + handle(fd, events); + return true; + }; + mEventPoll.addFD(fd, EPOLLIN | EPOLLHUP | EPOLLRDHUP, handleFd); if (newPeerCallback) { newPeerCallback(peerID, fd); } @@ -157,9 +132,7 @@ void Service::setRemovedPeerCallback(const PeerCallback& removedPeerCallback) { LOGS("Service setRemovedPeerCallback"); auto callback = [removedPeerCallback, this](PeerID peerID, FileDescriptor fd) { - if (mIPCGSourcePtr) { - mIPCGSourcePtr->removeFD(fd); - } + mEventPoll.removeFD(fd); if (removedPeerCallback) { removedPeerCallback(peerID, fd); } diff --git a/common/ipc/service.hpp b/common/ipc/service.hpp index 022c9c9..880c137 100644 --- a/common/ipc/service.hpp +++ b/common/ipc/service.hpp @@ -27,9 +27,9 @@ #include "ipc/internals/processor.hpp" #include "ipc/internals/acceptor.hpp" -#include "ipc/ipc-gsource.hpp" #include "ipc/types.hpp" #include "ipc/result.hpp" +#include "epoll/event-poll.hpp" #include "logger/logger.hpp" #include @@ -42,18 +42,16 @@ namespace ipc { * This class wraps communication via UX sockets. * It uses serialization mechanism from libConfig. * - * There are two working threads: - * - ACCEPTOR accepts incoming connections and passes them to PROCESSOR - * - PROCESSOR is responsible for the communication and calling the callbacks - * * For message format @see ipc::Processor */ class Service { public: /** + * @param eventPoll event poll * @param path path to the socket */ - Service(const std::string& path, + Service(epoll::EventPoll& eventPoll, + const std::string& path, const PeerCallback& addPeerCallback = nullptr, const PeerCallback& removePeerCallback = nullptr); ~Service(); @@ -62,11 +60,9 @@ public: Service& operator=(const Service&) = delete; /** - * Starts the worker and acceptor threads - * - * @param usesExternalPolling internal or external polling is used + * Starts processing */ - void start(const bool usesExternalPolling = false); + void start(); /** * @return is the communication thread running @@ -79,16 +75,6 @@ public: void stop(); /** - * Used with an external polling loop. - * Handles one event from the file descriptor. - * - * @param fd file descriptor - * @param pollEvent event on the fd. Defined in poll.h - * - */ - void handle(const FileDescriptor fd, const short pollEvent); - - /** * Set the callback called for each new connection to a peer * * @param newPeerCallback the callback @@ -175,14 +161,11 @@ public: void signal(const MethodID methodID, const std::shared_ptr& data); private: - - void startPoll(); - void stopPoll(); - - typedef std::lock_guard Lock; + epoll::EventPoll& mEventPoll; Processor mProcessor; Acceptor mAcceptor; - IPCGSource::Pointer mIPCGSourcePtr; + + void handle(const FileDescriptor fd, const epoll::Events pollEvents); }; diff --git a/tests/scripts/vsm_test_parser.py b/tests/scripts/vsm_test_parser.py index 41dd495..d0d4fa7 100644 --- a/tests/scripts/vsm_test_parser.py +++ b/tests/scripts/vsm_test_parser.py @@ -35,7 +35,7 @@ class Logger(object): __indentChar = " " def testCaseSummary(self, testSuite, testName, testResult, recLevel): - msg = self.__indentChar * recLevel + BOLD + "{:<50}".format(testName) + msg = self.__indentChar * recLevel + BOLD + "{:<50} ".format(testName) if testResult == "passed": msg += GREEN diff --git a/tests/unit_tests/epoll/ut-event-poll.cpp b/tests/unit_tests/epoll/ut-event-poll.cpp index 0bcbe81..00cb385 100644 --- a/tests/unit_tests/epoll/ut-event-poll.cpp +++ b/tests/unit_tests/epoll/ut-event-poll.cpp @@ -31,8 +31,8 @@ #include "ipc/internals/socket.hpp" #include "utils/latch.hpp" #include "utils/glib-loop.hpp" -#include "epoll/glib-poll-dispatcher.hpp" -#include "epoll/thread-poll-dispatcher.hpp" +#include "epoll/glib-dispatcher.hpp" +#include "epoll/thread-dispatcher.hpp" using namespace vasum::utils; using namespace vasum::epoll; @@ -54,14 +54,14 @@ BOOST_AUTO_TEST_CASE(EmptyPoll) BOOST_AUTO_TEST_CASE(ThreadedPoll) { - ThreadPollDispatcher dispatcher; + ThreadDispatcher dispatcher; } BOOST_AUTO_TEST_CASE(GlibPoll) { ScopedGlibLoop loop; - GlibPollDispatcher dispatcher; + GlibDispatcher dispatcher; } void doSocketTest(EventPoll& poll) @@ -126,7 +126,7 @@ void doSocketTest(EventPoll& poll) BOOST_AUTO_TEST_CASE(ThreadedPollSocket) { - ThreadPollDispatcher dispatcher; + ThreadDispatcher dispatcher; doSocketTest(dispatcher.getPoll()); } @@ -135,14 +135,14 @@ BOOST_AUTO_TEST_CASE(GlibPollSocket) { ScopedGlibLoop loop; - GlibPollDispatcher dispatcher; + GlibDispatcher dispatcher; doSocketTest(dispatcher.getPoll()); } BOOST_AUTO_TEST_CASE(PollStacking) { - ThreadPollDispatcher dispatcher; + ThreadDispatcher dispatcher; EventPoll innerPoll; diff --git a/tests/unit_tests/ipc/ut-ipc.cpp b/tests/unit_tests/ipc/ut-ipc.cpp index 088f576..8f47a65 100644 --- a/tests/unit_tests/ipc/ut-ipc.cpp +++ b/tests/unit_tests/ipc/ut-ipc.cpp @@ -34,6 +34,8 @@ #include "ipc/client.hpp" #include "ipc/types.hpp" #include "ipc/result.hpp" +#include "epoll/thread-dispatcher.hpp" +#include "epoll/glib-dispatcher.hpp" #include "utils/glib-loop.hpp" #include "utils/latch.hpp" #include "utils/value-latch.hpp" @@ -51,11 +53,10 @@ using namespace vasum; using namespace vasum::ipc; +using namespace vasum::epoll; using namespace vasum::utils; using namespace std::placeholders; -namespace { - // Timeout for sending one message const int TIMEOUT = 1000 /*ms*/; @@ -68,15 +69,28 @@ const int LONG_OPERATION_TIME = 1000 + TIMEOUT; const std::string TEST_DIR = "/tmp/ut-ipc"; const std::string SOCKET_PATH = TEST_DIR + "/test.socket"; -struct Fixture { +struct FixtureBase { ScopedDir mTestPathGuard; - Fixture() + FixtureBase() : mTestPathGuard(TEST_DIR) { } }; +struct ThreadedFixture : FixtureBase { + ThreadDispatcher dispatcher; + + EventPoll& getPoll() { return dispatcher.getPoll(); } +}; + +struct GlibFixture : FixtureBase { + ScopedGlibLoop glibLoop; + GlibDispatcher dispatcher; + + EventPoll& getPoll() { return dispatcher.getPoll(); } +}; + struct SendData { int intVal; SendData(int i): intVal(i) {} @@ -167,7 +181,7 @@ void longEchoCallback(const PeerID, methodResult->set(returnData); } -PeerID connect(Service& s, Client& c, bool isServiceGlib = false, bool isClientGlib = false) +PeerID connect(Service& s, Client& c) { // Connects the Client to the Service and returns Clients PeerID ValueLatch peerIDLatch; @@ -178,10 +192,10 @@ PeerID connect(Service& s, Client& c, bool isServiceGlib = false, bool isClientG s.setNewPeerCallback(newPeerCallback); if (!s.isStarted()) { - s.start(isServiceGlib); + s.start(); } - c.start(isClientGlib); + c.start(); PeerID peerID = peerIDLatch.get(TIMEOUT); s.setNewPeerCallback(nullptr); @@ -189,16 +203,6 @@ PeerID connect(Service& s, Client& c, bool isServiceGlib = false, bool isClientG return peerID; } -PeerID connectServiceGSource(Service& s, Client& c) -{ - return connect(s, c, true, false); -} - -PeerID connectClientGSource(Service& s, Client& c) -{ - return connect(s, c, false, true); -} - void testEcho(Client& c, const MethodID methodID) { std::shared_ptr sentData(new SendData(34)); @@ -215,20 +219,17 @@ void testEcho(Service& s, const MethodID methodID, const PeerID peerID) BOOST_CHECK_EQUAL(recvData->intVal, sentData->intVal); } -} // namespace - - -BOOST_FIXTURE_TEST_SUITE(IPCSuite, Fixture) +BOOST_AUTO_TEST_SUITE(IPCSuite) -BOOST_AUTO_TEST_CASE(ConstructorDestructor) +MULTI_FIXTURE_TEST_CASE(ConstructorDestructor, F, ThreadedFixture, GlibFixture) { - Service s(SOCKET_PATH); - Client c(SOCKET_PATH); + Service s(F::getPoll(), SOCKET_PATH); + Client c(F::getPoll(), SOCKET_PATH); } -BOOST_AUTO_TEST_CASE(ServiceAddRemoveMethod) +MULTI_FIXTURE_TEST_CASE(ServiceAddRemoveMethod, F, ThreadedFixture, GlibFixture) { - Service s(SOCKET_PATH); + Service s(F::getPoll(), SOCKET_PATH); s.setMethodHandler(1, returnEmptyCallback); s.setMethodHandler(1, returnDataCallback); @@ -237,7 +238,7 @@ BOOST_AUTO_TEST_CASE(ServiceAddRemoveMethod) s.setMethodHandler(1, echoCallback); s.setMethodHandler(2, returnDataCallback); - Client c(SOCKET_PATH); + Client c(F::getPoll(), SOCKET_PATH); connect(s, c); testEcho(c, 1); @@ -247,10 +248,10 @@ BOOST_AUTO_TEST_CASE(ServiceAddRemoveMethod) BOOST_CHECK_THROW(testEcho(c, 2), IPCException); } -BOOST_AUTO_TEST_CASE(ClientAddRemoveMethod) +MULTI_FIXTURE_TEST_CASE(ClientAddRemoveMethod, F, ThreadedFixture, GlibFixture) { - Service s(SOCKET_PATH); - Client c(SOCKET_PATH); + Service s(F::getPoll(), SOCKET_PATH); + Client c(F::getPoll(), SOCKET_PATH); c.setMethodHandler(1, returnEmptyCallback); c.setMethodHandler(1, returnDataCallback); @@ -267,9 +268,9 @@ BOOST_AUTO_TEST_CASE(ClientAddRemoveMethod) BOOST_CHECK_THROW(testEcho(s, 1, peerID), IPCException); } -BOOST_AUTO_TEST_CASE(ServiceStartStop) +MULTI_FIXTURE_TEST_CASE(ServiceStartStop, F, ThreadedFixture, GlibFixture) { - Service s(SOCKET_PATH); + Service s(F::getPoll(), SOCKET_PATH); s.setMethodHandler(1, returnDataCallback); @@ -282,10 +283,10 @@ BOOST_AUTO_TEST_CASE(ServiceStartStop) s.start(); } -BOOST_AUTO_TEST_CASE(ClientStartStop) +MULTI_FIXTURE_TEST_CASE(ClientStartStop, F, ThreadedFixture, GlibFixture) { - Service s(SOCKET_PATH); - Client c(SOCKET_PATH); + Service s(F::getPoll(), SOCKET_PATH); + Client c(F::getPoll(), SOCKET_PATH); c.setMethodHandler(1, returnDataCallback); c.start(); @@ -300,27 +301,27 @@ BOOST_AUTO_TEST_CASE(ClientStartStop) c.stop(); } -BOOST_AUTO_TEST_CASE(SyncClientToServiceEcho) +MULTI_FIXTURE_TEST_CASE(SyncClientToServiceEcho, F, ThreadedFixture, GlibFixture) { - Service s(SOCKET_PATH); + Service s(F::getPoll(), SOCKET_PATH); s.setMethodHandler(1, echoCallback); s.setMethodHandler(2, echoCallback); - Client c(SOCKET_PATH); + Client c(F::getPoll(), SOCKET_PATH); connect(s, c); testEcho(c, 1); testEcho(c, 2); } -BOOST_AUTO_TEST_CASE(Restart) +MULTI_FIXTURE_TEST_CASE(Restart, F, ThreadedFixture, GlibFixture) { - Service s(SOCKET_PATH); + Service s(F::getPoll(), SOCKET_PATH); s.setMethodHandler(1, echoCallback); s.start(); s.setMethodHandler(2, echoCallback); - Client c(SOCKET_PATH); + Client c(F::getPoll(), SOCKET_PATH); c.start(); testEcho(c, 1); testEcho(c, 2); @@ -334,14 +335,19 @@ BOOST_AUTO_TEST_CASE(Restart) s.stop(); s.start(); + BOOST_CHECK_THROW(testEcho(c, 2), IPCException); + + c.stop(); + c.start(); + testEcho(c, 1); testEcho(c, 2); } -BOOST_AUTO_TEST_CASE(SyncServiceToClientEcho) +MULTI_FIXTURE_TEST_CASE(SyncServiceToClientEcho, F, ThreadedFixture, GlibFixture) { - Service s(SOCKET_PATH); - Client c(SOCKET_PATH); + Service s(F::getPoll(), SOCKET_PATH); + Client c(F::getPoll(), SOCKET_PATH); c.setMethodHandler(1, echoCallback); PeerID peerID = connect(s, c); @@ -351,16 +357,16 @@ BOOST_AUTO_TEST_CASE(SyncServiceToClientEcho) BOOST_CHECK_EQUAL(recvData->intVal, sentData->intVal); } -BOOST_AUTO_TEST_CASE(AsyncClientToServiceEcho) +MULTI_FIXTURE_TEST_CASE(AsyncClientToServiceEcho, F, ThreadedFixture, GlibFixture) { std::shared_ptr sentData(new SendData(34)); ValueLatch> recvDataLatch; // Setup Service and Client - Service s(SOCKET_PATH); + Service s(F::getPoll(), SOCKET_PATH); s.setMethodHandler(1, echoCallback); s.start(); - Client c(SOCKET_PATH); + Client c(F::getPoll(), SOCKET_PATH); c.start(); //Async call @@ -374,13 +380,13 @@ BOOST_AUTO_TEST_CASE(AsyncClientToServiceEcho) BOOST_CHECK_EQUAL(recvData->intVal, sentData->intVal); } -BOOST_AUTO_TEST_CASE(AsyncServiceToClientEcho) +MULTI_FIXTURE_TEST_CASE(AsyncServiceToClientEcho, F, ThreadedFixture, GlibFixture) { std::shared_ptr sentData(new SendData(56)); ValueLatch> recvDataLatch; - Service s(SOCKET_PATH); - Client c(SOCKET_PATH); + Service s(F::getPoll(), SOCKET_PATH); + Client c(F::getPoll(), SOCKET_PATH); c.setMethodHandler(1, echoCallback); PeerID peerID = connect(s, c); @@ -397,24 +403,24 @@ BOOST_AUTO_TEST_CASE(AsyncServiceToClientEcho) } -BOOST_AUTO_TEST_CASE(SyncTimeout) +MULTI_FIXTURE_TEST_CASE(SyncTimeout, F, ThreadedFixture, GlibFixture) { - Service s(SOCKET_PATH); + Service s(F::getPoll(), SOCKET_PATH); s.setMethodHandler(1, longEchoCallback); - Client c(SOCKET_PATH); + Client c(F::getPoll(), SOCKET_PATH); connect(s, c); std::shared_ptr sentData(new SendData(78)); BOOST_REQUIRE_THROW((c.callSync(1, sentData, TIMEOUT)), IPCException); } -BOOST_AUTO_TEST_CASE(SerializationError) +MULTI_FIXTURE_TEST_CASE(SerializationError, F, ThreadedFixture, GlibFixture) { - Service s(SOCKET_PATH); + Service s(F::getPoll(), SOCKET_PATH); s.setMethodHandler(1, echoCallback); - Client c(SOCKET_PATH); + Client c(F::getPoll(), SOCKET_PATH); connect(s, c); std::shared_ptr throwingData(new ThrowOnAcceptData()); @@ -423,23 +429,24 @@ BOOST_AUTO_TEST_CASE(SerializationError) } -BOOST_AUTO_TEST_CASE(ParseError) +MULTI_FIXTURE_TEST_CASE(ParseError, F, ThreadedFixture, GlibFixture) { - Service s(SOCKET_PATH); + Service s(F::getPoll(), SOCKET_PATH); s.setMethodHandler(1, echoCallback); s.start(); - Client c(SOCKET_PATH); + Client c(F::getPoll(), SOCKET_PATH); c.start(); std::shared_ptr sentData(new SendData(78)); BOOST_CHECK_THROW((c.callSync(1, sentData, 10000)), IPCParsingException); } -BOOST_AUTO_TEST_CASE(DisconnectedPeerError) +MULTI_FIXTURE_TEST_CASE(DisconnectedPeerError, F, ThreadedFixture, GlibFixture) { ValueLatch> retStatusLatch; - Service s(SOCKET_PATH); + + Service s(F::getPoll(), SOCKET_PATH); auto method = [](const PeerID, std::shared_ptr&, MethodResult::Pointer methodResult) { auto resultData = std::make_shared(1); @@ -450,7 +457,7 @@ BOOST_AUTO_TEST_CASE(DisconnectedPeerError) s.setMethodHandler(1, method); s.start(); - Client c(SOCKET_PATH); + Client c(F::getPoll(), SOCKET_PATH); c.start(); auto dataBack = [&retStatusLatch](Result && r) { @@ -470,16 +477,16 @@ BOOST_AUTO_TEST_CASE(DisconnectedPeerError) } -BOOST_AUTO_TEST_CASE(ReadTimeout) +MULTI_FIXTURE_TEST_CASE(ReadTimeout, F, ThreadedFixture, GlibFixture) { - Service s(SOCKET_PATH); + Service s(F::getPoll(), SOCKET_PATH); auto longEchoCallback = [](const PeerID, std::shared_ptr& data, MethodResult::Pointer methodResult) { auto resultData = std::make_shared(data->intVal, LONG_OPERATION_TIME); methodResult->set(resultData); }; s.setMethodHandler(1, longEchoCallback); - Client c(SOCKET_PATH); + Client c(F::getPoll(), SOCKET_PATH); connect(s, c); // Test timeout on read @@ -488,13 +495,13 @@ BOOST_AUTO_TEST_CASE(ReadTimeout) } -BOOST_AUTO_TEST_CASE(WriteTimeout) +MULTI_FIXTURE_TEST_CASE(WriteTimeout, F, ThreadedFixture, GlibFixture) { - Service s(SOCKET_PATH); + Service s(F::getPoll(), SOCKET_PATH); s.setMethodHandler(1, echoCallback); s.start(); - Client c(SOCKET_PATH); + Client c(F::getPoll(), SOCKET_PATH); c.start(); // Test echo with a minimal timeout @@ -509,13 +516,13 @@ BOOST_AUTO_TEST_CASE(WriteTimeout) } -BOOST_AUTO_TEST_CASE(AddSignalInRuntime) +MULTI_FIXTURE_TEST_CASE(AddSignalInRuntime, F, ThreadedFixture, GlibFixture) { ValueLatch> recvDataLatchA; ValueLatch> recvDataLatchB; - Service s(SOCKET_PATH); - Client c(SOCKET_PATH); + Service s(F::getPoll(), SOCKET_PATH); + Client c(F::getPoll(), SOCKET_PATH); connect(s, c); auto handlerA = [&recvDataLatchA](const PeerID, std::shared_ptr& data) { @@ -545,13 +552,13 @@ BOOST_AUTO_TEST_CASE(AddSignalInRuntime) } -BOOST_AUTO_TEST_CASE(AddSignalOffline) +MULTI_FIXTURE_TEST_CASE(AddSignalOffline, F, ThreadedFixture, GlibFixture) { ValueLatch> recvDataLatchA; ValueLatch> recvDataLatchB; - Service s(SOCKET_PATH); - Client c(SOCKET_PATH); + Service s(F::getPoll(), SOCKET_PATH); + Client c(F::getPoll(), SOCKET_PATH); auto handlerA = [&recvDataLatchA](const PeerID, std::shared_ptr& data) { recvDataLatchA.set(data); @@ -581,66 +588,13 @@ BOOST_AUTO_TEST_CASE(AddSignalOffline) BOOST_CHECK_EQUAL(recvDataB->intVal, sendDataB->intVal); } - -BOOST_AUTO_TEST_CASE(ServiceGSource) -{ - utils::Latch l; - ScopedGlibLoop loop; - - auto signalHandler = [&l](const PeerID, std::shared_ptr&) { - l.set(); - }; - - Service s(SOCKET_PATH); - s.setMethodHandler(1, echoCallback); - - Client c(SOCKET_PATH); - s.setSignalHandler(2, signalHandler); - - connectServiceGSource(s, c); - - testEcho(c, 1); - - auto data = std::make_shared(1); - c.signal(2, data); - - BOOST_CHECK(l.wait(TIMEOUT)); -} - - -BOOST_AUTO_TEST_CASE(ClientGSource) -{ - utils::Latch l; - ScopedGlibLoop loop; - - auto signalHandler = [&l](const PeerID, std::shared_ptr&) { - l.set(); - }; - - Service s(SOCKET_PATH); - s.start(); - - Client c(SOCKET_PATH); - c.setMethodHandler(1, echoCallback); - c.setSignalHandler(2, signalHandler); - - PeerID peerID = connectClientGSource(s, c); - - testEcho(s, 1, peerID); - - auto data = std::make_shared(1); - s.signal(2, data); - - BOOST_CHECK(l.wait(TIMEOUT)); -} - -BOOST_AUTO_TEST_CASE(UsersError) +MULTI_FIXTURE_TEST_CASE(UsersError, F, ThreadedFixture, GlibFixture) { const int TEST_ERROR_CODE = -234; const std::string TEST_ERROR_MESSAGE = "Ay, caramba!"; - Service s(SOCKET_PATH); - Client c(SOCKET_PATH); + Service s(F::getPoll(), SOCKET_PATH); + Client c(F::getPoll(), SOCKET_PATH); auto clientID = connect(s, c); auto throwingMethodHandler = [&](const PeerID, std::shared_ptr&, MethodResult::Pointer) { @@ -668,13 +622,13 @@ BOOST_AUTO_TEST_CASE(UsersError) BOOST_CHECK_EXCEPTION((s.callSync(2, clientID, sentData, TIMEOUT)), IPCUserException, hasProperData); } -BOOST_AUTO_TEST_CASE(AsyncResult) +MULTI_FIXTURE_TEST_CASE(AsyncResult, F, ThreadedFixture, GlibFixture) { const int TEST_ERROR_CODE = -567; const std::string TEST_ERROR_MESSAGE = "Ooo jooo!"; - Service s(SOCKET_PATH); - Client c(SOCKET_PATH); + Service s(F::getPoll(), SOCKET_PATH); + Client c(F::getPoll(), SOCKET_PATH); auto clientID = connect(s, c); auto errorMethodHandler = [&](const PeerID, std::shared_ptr&, MethodResult::Pointer methodResult) { @@ -724,20 +678,44 @@ BOOST_AUTO_TEST_CASE(AsyncResult) BOOST_CHECK_EQUAL(recvData->intVal, sentData->intVal); } -// BOOST_AUTO_TEST_CASE(ConnectionLimitTest) +MULTI_FIXTURE_TEST_CASE(MixOperations, F, ThreadedFixture, GlibFixture) +{ + utils::Latch l; + + auto signalHandler = [&l](const PeerID, std::shared_ptr&) { + l.set(); + }; + + Service s(F::getPoll(), SOCKET_PATH); + s.setMethodHandler(1, echoCallback); + + Client c(F::getPoll(), SOCKET_PATH); + s.setSignalHandler(2, signalHandler); + + connect(s, c); + + testEcho(c, 1); + + auto data = std::make_shared(1); + c.signal(2, data); + + BOOST_CHECK(l.wait(TIMEOUT)); +} + +// MULTI_FIXTURE_TEST_CASE(ConnectionLimitTest, F, ThreadedFixture, GlibFixture) // { // unsigned oldLimit = ipc::getMaxFDNumber(); // ipc::setMaxFDNumber(50); // // Setup Service and many Clients -// Service s(SOCKET_PATH); +// Service s(F::getPoll(), SOCKET_PATH); // s.setMethodHandler(1, echoCallback); // s.start(); // std::list clients; // for (int i = 0; i < 100; ++i) { // try { -// clients.push_back(Client(SOCKET_PATH)); +// clients.push_back(Client(F::getPoll(), SOCKET_PATH)); // clients.back().start(); // } catch (...) {} // } diff --git a/tests/unit_tests/ut.hpp b/tests/unit_tests/ut.hpp index d8b4b94..e96d363 100644 --- a/tests/unit_tests/ut.hpp +++ b/tests/unit_tests/ut.hpp @@ -28,9 +28,23 @@ #define BOOST_TEST_DYN_LINK #include +#include + #include /** + * Usage example: + * + * MULTI_FIXTURE_TEST_CASE(Test, T, Fixture1, Fixture2, Fixture3) { + * std::cout << T::i << "\n"; + * } + */ +#define MULTI_FIXTURE_TEST_CASE(NAME, TPARAM, ...) \ + typedef boost::mpl::vector<__VA_ARGS__> NAME##_fixtures; \ + BOOST_FIXTURE_TEST_CASE_TEMPLATE(NAME, TPARAM, NAME##_fixtures, TPARAM) + + +/** * An exception message checker * * Usage example: -- 2.7.4 From a894b6301c6c798912f0963011936df271c2495e Mon Sep 17 00:00:00 2001 From: Mateusz Malicki Date: Wed, 11 Mar 2015 12:57:02 +0100 Subject: [PATCH 05/16] Complementing cli commands in bash [Bug/Feature] Complementing cli commands in bash [Cause] N/A [Solution] N/A [Verification] Check completion (you must first enable bash completion or execute: source /etc/bash_completion.d/vasum-cli-completion.sh) Change-Id: I256ed064a128f03874b2e4655ccb818058a13897 --- cli/CMakeLists.txt | 5 +++++ cli/command-line-interface.cpp | 10 ++++++---- cli/main.cpp | 9 ++++++++- cli/support/vasum-cli-completion.sh.in | 15 +++++++++++++++ packaging/vasum.spec | 11 +++++++++++ 5 files changed, 45 insertions(+), 5 deletions(-) create mode 100755 cli/support/vasum-cli-completion.sh.in diff --git a/cli/CMakeLists.txt b/cli/CMakeLists.txt index f28e65b..2ffdcc4 100644 --- a/cli/CMakeLists.txt +++ b/cli/CMakeLists.txt @@ -33,6 +33,11 @@ INCLUDE_DIRECTORIES(${CLIENT_FOLDER}) INCLUDE_DIRECTORIES(${COMMON_FOLDER}) TARGET_LINK_LIBRARIES(${CLI_CODENAME} ${LIB_DEPS_LIBRARIES} ${PROJECT_NAME}) +CONFIGURE_FILE(support/vasum-cli-completion.sh.in + ${CMAKE_BINARY_DIR}/vasum-cli-completion.sh + @ONLY) ## Install ##################################################################### INSTALL(TARGETS ${CLI_CODENAME} DESTINATION bin) +INSTALL(FILES ${CMAKE_BINARY_DIR}/vasum-cli-completion.sh + DESTINATION ${SYSCONF_INSTALL_DIR}/bash_completion.d) diff --git a/cli/command-line-interface.cpp b/cli/command-line-interface.cpp index 77e9dc5..ecf6b9c 100644 --- a/cli/command-line-interface.cpp +++ b/cli/command-line-interface.cpp @@ -174,10 +174,12 @@ void CommandLineInterface::printUsage(std::ostream& out) const { out << mUsage << "\n\n" << "\tDescription\n" - << "\t\t" << mUsageInfo << "\n\n" - << "\tOptions\n"; - for (const auto& args : mArgsSpec) { - out << "\t\t" << args.first << " -- " << args.second << "\n"; + << "\t\t" << mUsageInfo << "\n"; + if (!mArgsSpec.empty()) { + out << "\n\tOptions\n"; + for (const auto& args : mArgsSpec) { + out << "\t\t" << args.first << " -- " << args.second << "\n"; + } } out << "\n"; } diff --git a/cli/main.cpp b/cli/main.cpp index 5f073be..a30146e 100644 --- a/cli/main.cpp +++ b/cli/main.cpp @@ -29,6 +29,7 @@ #include #include #include +#include using namespace vasum::cli; @@ -241,7 +242,7 @@ std::map commands = { void printUsage(std::ostream& out, const std::string& name) { - out << "Usage: " << name << " [command [args]]\n\n" + out << "Usage: " << name << " [command [-h|args]]\n\n" << "command can be one of the following:\n"; for (const auto& command : commands) { @@ -263,6 +264,12 @@ int main(const int argc, const char** argv) } CommandLineInterface& command = commands[argv[1]]; + auto it = std::find(argv, argv+argc, std::string("-h")); + if (it != argv + argc) { + command.printUsage(std::cout); + return EXIT_SUCCESS; + } + try { command.execute(1, argc, argv); } catch (const std::runtime_error& ex) { diff --git a/cli/support/vasum-cli-completion.sh.in b/cli/support/vasum-cli-completion.sh.in new file mode 100755 index 0000000..79a5dad --- /dev/null +++ b/cli/support/vasum-cli-completion.sh.in @@ -0,0 +1,15 @@ +# Check for bash +[ -z "$BASH_VERSION" ] && return + +__@PROJECT_NAME@_cli() { + local cur="${COMP_WORDS[COMP_CWORD]}" + + COMPREPLY=() + if [ "$COMP_CWORD" == "1" ]; then + COMPREPLY=($(compgen -W "$(@CLI_CODENAME@ | grep -e '^\S' | tail -n +3 | cut -f1 -d' ')" -- $cur)) + elif [ "$COMP_CWORD" == "2" ]; then + COMPREPLY=($(compgen -W "-h" -- $cur)) + fi +} + +complete -F __@PROJECT_NAME@_cli @CLI_CODENAME@ diff --git a/packaging/vasum.spec b/packaging/vasum.spec index bd7e9f1..6cea869 100644 --- a/packaging/vasum.spec +++ b/packaging/vasum.spec @@ -198,6 +198,17 @@ Command Line Interface for vasum. %defattr(644,root,root,755) %attr(755,root,root) %{_bindir}/vasum-cli +%package cli-completion +Summary: Vasum Command Line Interface bash completion +Group: Security/Other +Requires: vasum-cli = %{version}-%{release} +#Requires: bash-completion + +%description cli-completion +Command Line Interface bash completion. + +%files cli-completion +%attr(755,root,root) %{_sysconfdir}/bash_completion.d/vasum-cli-completion.sh ## Test Package ################################################################ %package tests -- 2.7.4 From 855c585bf6a39817a301e72e61620f6f9776210d Mon Sep 17 00:00:00 2001 From: Jan Olszak Date: Tue, 10 Mar 2015 13:35:55 +0100 Subject: [PATCH 06/16] IPC agnostic MethodResultBuilder [Feature] ZoneManager and Zone doesn't know which IPC mechanism is used. [Cause] N/A [Solution] N/A [Verification] Build, run tests, run tests with valgrind Change-Id: I852fa5ed3bcd105096cb7ca740f9e98fb8b6adba --- client/vasum-client-impl.cpp | 4 +- common/api/dbus-method-result-builder.hpp | 88 ++++++ common/api/ipc-method-result-builder.cpp | 54 ++++ common/api/ipc-method-result-builder.hpp | 56 ++++ common/api/messages.hpp | 404 +++++++++++++++++++++++++ common/api/method-result-builder.hpp | 62 ++++ server/host-connection.cpp | 108 ++++--- server/host-connection.hpp | 51 ++-- server/host-dbus-definitions.hpp | 2 +- server/zone-connection.cpp | 18 +- server/zone-connection.hpp | 15 +- server/zone.cpp | 6 +- server/zone.hpp | 6 +- server/zones-manager.cpp | 252 +++++++-------- server/zones-manager.hpp | 66 ++-- tests/unit_tests/server/ut-zone-connection.cpp | 17 +- tests/unit_tests/server/ut-zones-manager.cpp | 4 +- 17 files changed, 947 insertions(+), 266 deletions(-) create mode 100644 common/api/dbus-method-result-builder.hpp create mode 100644 common/api/ipc-method-result-builder.cpp create mode 100644 common/api/ipc-method-result-builder.hpp create mode 100644 common/api/messages.hpp create mode 100644 common/api/method-result-builder.hpp diff --git a/client/vasum-client-impl.cpp b/client/vasum-client-impl.cpp index d8ba562..1ac4c3c 100644 --- a/client/vasum-client-impl.cpp +++ b/client/vasum-client-impl.cpp @@ -74,7 +74,7 @@ void toDict(GVariant* in, VsmArrayString* keys, VsmArrayString* values) value_type* outv = (value_type*)calloc(size + 1, sizeof(value_type)); g_variant_iter_init(&iter, in); - for (int i = 0; g_variant_iter_loop(&iter, "{ss}", &key, &value); i++) { + for (int i = 0; g_variant_iter_loop(&iter, "(ss)", &key, &value); i++) { outk[i] = strdup(key); outv[i] = strdup(value); } @@ -377,7 +377,7 @@ VsmStatus Client::vsm_get_zone_dbuses(VsmArrayString* keys, VsmArrayString* valu VsmStatus ret = callMethod(HOST_INTERFACE, api::host::METHOD_GET_ZONE_DBUSES, NULL, - "(a{ss})", + "(a(ss))", &out); if (ret != VSMCLIENT_SUCCESS) { return ret; diff --git a/common/api/dbus-method-result-builder.hpp b/common/api/dbus-method-result-builder.hpp new file mode 100644 index 0000000..99f3bc0 --- /dev/null +++ b/common/api/dbus-method-result-builder.hpp @@ -0,0 +1,88 @@ +/* +* Copyright (c) 2015 Samsung Electronics Co., Ltd All Rights Reserved +* +* Contact: Jan Olszak (j.olszak@samsung.com) +* +* 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 Jan Olszak (j.olszak@samsung.com) + * @brief Interface for result builders + + */ + +#ifndef COMMON_RESULT_DBUS_METHOD_RESULT_BUILDER_HPP +#define COMMON_RESULT_DBUS_METHOD_RESULT_BUILDER_HPP + +#include "config.hpp" + +#include "api/method-result-builder.hpp" + +#include "dbus/connection.hpp" +#include "config/manager.hpp" + +#include +#include + +namespace vasum { +namespace api { + +template +class DbusMethodResultBuilder: public MethodResultBuilder { +public: + DbusMethodResultBuilder(const dbus::MethodResultBuilder::Pointer& methodResultBuilderPtr); + ~DbusMethodResultBuilder() {} + +private: + void setImpl(const std::shared_ptr& data) override; + void setVoid() override; + void setError(const std::string& name, const std::string& message) override; + + dbus::MethodResultBuilder::Pointer mMethodResultBuilderPtr; + std::function)> mSerialize; +}; + +template +DbusMethodResultBuilder::DbusMethodResultBuilder(const dbus::MethodResultBuilder::Pointer& methodResultBuilderPtr) + : mMethodResultBuilderPtr(methodResultBuilderPtr) +{ + mSerialize = [](const std::shared_ptr data)->GVariant* { + return config::saveToGVariant(*std::static_pointer_cast(data)); + }; +} + +template +void DbusMethodResultBuilder::setImpl(const std::shared_ptr& data) +{ + GVariant* parameters = mSerialize(data); + mMethodResultBuilderPtr->set(parameters); +} + +template +void DbusMethodResultBuilder::setVoid() +{ + mMethodResultBuilderPtr->setVoid(); +} + +template +void DbusMethodResultBuilder::setError(const std::string& name, const std::string& message) +{ + mMethodResultBuilderPtr->setError(name, message); +} + +} // namespace result +} // namespace vasum + +#endif // COMMON_RESULT_DBUS_METHOD_RESULT_BUILDER_HPP diff --git a/common/api/ipc-method-result-builder.cpp b/common/api/ipc-method-result-builder.cpp new file mode 100644 index 0000000..4ea2845 --- /dev/null +++ b/common/api/ipc-method-result-builder.cpp @@ -0,0 +1,54 @@ +/* +* Copyright (c) 2015 Samsung Electronics Co., Ltd All Rights Reserved +* +* Contact: Jan Olszak (j.olszak@samsung.com) +* +* 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 Jan Olszak (j.olszak@samsung.com) + * @brief Class for sending the result of a method + */ + +#include "api/ipc-method-result-builder.hpp" + +namespace vasum { +namespace api { + +IPCMethodResultBuilder::IPCMethodResultBuilder(const ipc::MethodResult::Pointer& methodResultPtr) + : mMethodResultPtr(methodResultPtr) +{ +} + +void IPCMethodResultBuilder::setImpl(const std::shared_ptr& data) +{ + mMethodResultPtr->set(data); +} + +void IPCMethodResultBuilder::setVoid() +{ + mMethodResultPtr->setVoid(); +} + +void IPCMethodResultBuilder::setError(const std::string& , const std::string& message) +{ + // TODO: Change int codes to string names in IPC MethodResult + mMethodResultPtr->setError(1, message); +} + +} // namespace result +} // namespace vasum + + diff --git a/common/api/ipc-method-result-builder.hpp b/common/api/ipc-method-result-builder.hpp new file mode 100644 index 0000000..7b03ece --- /dev/null +++ b/common/api/ipc-method-result-builder.hpp @@ -0,0 +1,56 @@ +/* +* Copyright (c) 2015 Samsung Electronics Co., Ltd All Rights Reserved +* +* Contact: Jan Olszak (j.olszak@samsung.com) +* +* 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 Jan Olszak (j.olszak@samsung.com) + * @brief Interface for result builders + + */ + +#ifndef COMMON_RESULT_IPC_METHOD_RESULT_BUILDER_HPP +#define COMMON_RESULT_IPC_METHOD_RESULT_BUILDER_HPP + +#include "config.hpp" + +#include "api/method-result-builder.hpp" +#include "ipc/method-result.hpp" + +#include + +namespace vasum { +namespace api { + +class IPCMethodResultBuilder: public MethodResultBuilder { +public: + IPCMethodResultBuilder(const ipc::MethodResult::Pointer& methodResult); + ~IPCMethodResultBuilder() {} + +private: + void setImpl(const std::shared_ptr& data) override; + void setVoid() override; + void setError(const std::string& name, const std::string& message) override; + + ipc::MethodResult::Pointer mMethodResultPtr; +}; + + +} // namespace result +} // namespace vasum + +#endif // COMMON_RESULT_IPC_METHOD_RESULT_BUILDER_HPP diff --git a/common/api/messages.hpp b/common/api/messages.hpp new file mode 100644 index 0000000..6c6d4da --- /dev/null +++ b/common/api/messages.hpp @@ -0,0 +1,404 @@ +/* + * Copyright (c) 2014 Samsung Electronics Co., Ltd All Rights Reserved + * + * Contact: Jan Olszak (j.olszak@samsung.com) + * + * 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 Jan Olszak (j.olszak@samsung.com) + * @brief Host's internal IPC messages declaration + */ + + +#ifndef COMMON_API_MESSAGES +#define COMMON_API_MESSAGES + +#include "config/fields.hpp" +#include +#include + +namespace vasum { +namespace api { + +struct Void { + CONFIG_REGISTER_EMPTY +}; + +struct String { + std::string value; + + CONFIG_REGISTER + ( + value + ) +}; + +struct StringPair { + std::string first; + std::string second; + + CONFIG_REGISTER + ( + first, + second + ) +}; + +struct VectorOfStrings { + std::vector values; + + CONFIG_REGISTER + ( + values + ) +}; + +struct VectorOfStringPairs { + std::vector values; + + CONFIG_REGISTER + ( + values + ) +}; + +typedef api::String ZoneId; +typedef api::String Declaration; +typedef api::String FileMoveRequestStatus; +typedef api::VectorOfStrings ZoneIds; +typedef api::VectorOfStrings Declarations; +typedef api::VectorOfStrings NetDevList; +typedef api::VectorOfStringPairs Dbuses; +typedef api::VectorOfStringPairs NetDevAttrs; + +struct ZoneInfo { + std::string id; + int vt; + std::string state; + std::string rootPath; + + CONFIG_REGISTER + ( + id, + vt, + state, + rootPath + ) +}; + +// struct MethodSetActiveZoneConfig { +// std::string id; + +// CONFIG_REGISTER +// ( +// id +// ) +// }; + +// struct MethodGetZoneDbusesConfig { +// CONFIG_REGISTER_EMPTY +// }; + +// struct MethodGetZoneIdListConfig { +// CONFIG_REGISTER_EMPTY +// }; + + +// struct MethodGetActiveZoneIdConfig { +// CONFIG_REGISTER_EMPTY +// }; + + +// struct MethodGetZoneInfoConfig { +// std::string id; + +// CONFIG_REGISTER +// ( +// id +// ) +// }; + +// struct MethodSetNetDevAttrsConfig { +// std::string zone; +// std::string netdev; + +// struct Store { +// std::string key; +// std::string value; + +// CONFIG_REGISTER +// ( +// key, +// value +// ) +// }; + +// std::vector attrs; + +// CONFIG_REGISTER +// ( +// zone, +// netdev, +// attrs +// ) +// }; + +// struct MethodGetNetDevAttrsConfig { +// std::string zone; +// std::string netdev; + +// CONFIG_REGISTER +// ( +// zone, +// netdev +// ) +// }; + +// struct MethodGetNetDevListConfig { +// std::string zone; + +// CONFIG_REGISTER +// ( +// zone +// ) +// }; + +// struct MethodCreateNetDevVethConfig { +// std::string id; +// std::string zoneDev; +// std::string hostDev; + +// CONFIG_REGISTER +// ( +// id, +// zoneDev, +// hostDev +// ) +// }; + +// struct MethodCreateNetDevMacvlanConfig { +// std::string id; +// std::string zoneDev; +// std::string hostDev; + +// CONFIG_REGISTER +// ( +// id, +// zoneDev, +// hostDev +// ) +// }; + +// struct MethodCreateNetDevPhysConfig { +// std::string id; +// std::string devId; + +// CONFIG_REGISTER +// ( +// id, +// devId +// ) +// }; + +// struct MethodGetDeclareFileConfig { +// std::string zone; +// int32_t type; +// std::string path; +// int32_t flags; +// int32_t mode; + +// CONFIG_REGISTER +// ( +// zone, +// type, +// path, +// flags, +// mode +// ) +// }; + +// struct MethodGetDeclareMountConfig { +// std::string source; +// std::string zone; +// std::string target; +// uint64_t flags; +// std::string data; + +// CONFIG_REGISTER +// ( +// source, +// zone, +// target, +// flags, +// data +// ) +// }; + +// struct MethodGetDeclareLinkConfig { +// std::string source; +// std::string zone; +// std::string target; + +// CONFIG_REGISTER +// ( +// source, +// zone, +// target +// ) +// }; + +// struct MethodGetDeclarationConfig { +// std::string zone; +// std::string declarationId; + +// CONFIG_REGISTER +// ( +// zone, +// declarationId +// ) +// }; + +// struct MethodRemoveDeclarationConfig { +// std::string id; +// std::string declarationId; + +// CONFIG_REGISTER +// ( +// id, +// declarationId +// ) +// }; + +// struct MethodCreateZoneConfig { +// std::string id; +// std::string templateName; + +// CONFIG_REGISTER +// ( +// id, +// templateName +// ) +// }; + +// struct MethodDestroyZoneConfig { +// std::string id; + +// CONFIG_REGISTER +// ( +// id +// ) +// }; + + +// struct MethodShutdownZoneConfig { +// std::string id; + +// CONFIG_REGISTER +// ( +// id +// ) +// }; + +// struct MethodStartZoneConfig { +// std::string id; + +// CONFIG_REGISTER +// ( +// id +// ) +// }; + +// struct MethodLockZoneConfig { +// std::string id; + +// CONFIG_REGISTER +// ( +// id +// ) +// }; + +// struct MethodUnlockZoneConfig { +// std::string id; + +// CONFIG_REGISTER +// ( +// id +// ) +// }; + +// struct MethodGrantDeviceConfig { +// std::string id; +// std::string device; +// uint32_t flags; + +// CONFIG_REGISTER +// ( +// id, +// device, +// flags +// ) +// }; + +// struct MethodRevokeDeviceConfig { +// std::string id; +// std::string device; + +// CONFIG_REGISTER +// ( +// id, +// device +// ) +// }; + +// TODO: Agregate configs if it makes sense. For example: MethodLockZoneConfig and MethodUnlockZoneConfig + + +// Zone: +// struct MethodNotifyActiveZoneConfig { +// std::string application; +// std::string message; + +// CONFIG_REGISTER +// ( +// application, +// message +// ) +// }; + +// struct MethodFileMoveRequest { +// std::string destination; +// std::string path; + +// CONFIG_REGISTER +// ( +// destination, +// path +// ) +// }; + +// struct MethodFileMoveRequestResult { +// std::string result; + +// CONFIG_REGISTER +// ( +// result +// ) +// }; + +} // namespace api +} // namespace vasum + +#endif // COMMON_API_MESSAGES diff --git a/common/api/method-result-builder.hpp b/common/api/method-result-builder.hpp new file mode 100644 index 0000000..04ede40 --- /dev/null +++ b/common/api/method-result-builder.hpp @@ -0,0 +1,62 @@ +/* +* Copyright (c) 2015 Samsung Electronics Co., Ltd All Rights Reserved +* +* Contact: Jan Olszak (j.olszak@samsung.com) +* +* 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 Jan Olszak (j.olszak@samsung.com) + * @brief Interface for result builders + + */ + +#ifndef COMMON_RESULT_METHOD_RESULT_BUILDER_HPP +#define COMMON_RESULT_METHOD_RESULT_BUILDER_HPP + +#include + +#include "config/is-union.hpp" + +namespace vasum { +namespace api { + +/** + * An interface used to set a result to a method call. + */ +class MethodResultBuilder { +public: + typedef std::shared_ptr Pointer; + + virtual ~MethodResultBuilder() {} + virtual void setVoid() = 0; + virtual void setError(const std::string& name, const std::string& message) = 0; + + template + void set(const std::shared_ptr& data) + { + static_assert(config::isVisitable::value, "Use only libConfig's structures"); + setImpl(data); + } + +private: + virtual void setImpl(const std::shared_ptr& data) =0; + +}; + +} // namespace api +} // namespace vasum + +#endif // COMMON_RESULT_METHOD_RESULT_BUILDER_HPP diff --git a/server/host-connection.cpp b/server/host-connection.cpp index 6790480..a1a7448 100644 --- a/server/host-connection.cpp +++ b/server/host-connection.cpp @@ -27,6 +27,8 @@ #include "host-connection.hpp" #include "host-dbus-definitions.hpp" #include "exception.hpp" +#include "api/dbus-method-result-builder.hpp" +#include "api/messages.hpp" #include "logger/logger.hpp" @@ -65,7 +67,7 @@ HostConnection::HostConnection() mDbusConnection->registerObject(api::host::OBJECT_PATH, api::host::DEFINITION, std::bind(&HostConnection::onMessageCall, - this, _1, _2, _3, _4, _5)); + this, _1, _2, _3, _4, _5)); LOGD("Connected"); } @@ -246,14 +248,16 @@ void HostConnection::onMessageCall(const std::string& objectPath, g_variant_get(parameters, "(&s)", &id); if (mSetActiveZoneCallback) { - mSetActiveZoneCallback(id, result); + auto rb = std::make_shared>(result); + mSetActiveZoneCallback(id, rb); } return; } if (methodName == api::host::METHOD_GET_ZONE_DBUSES) { if (mGetZoneDbusesCallback) { - mGetZoneDbusesCallback(result); + auto rb = std::make_shared>(result); + mGetZoneDbusesCallback(rb); } return; } @@ -287,31 +291,34 @@ void HostConnection::onMessageCall(const std::string& objectPath, return; } - if (methodName == api::host::METHOD_GET_ZONE_ID_LIST){ - if (mGetZoneIdsCallback){ - mGetZoneIdsCallback(result); + if (methodName == api::host::METHOD_GET_ZONE_ID_LIST) { + if (mGetZoneIdsCallback) { + auto rb = std::make_shared>(result); + mGetZoneIdsCallback(rb); } return; } - if (methodName == api::host::METHOD_GET_ACTIVE_ZONE_ID){ - if (mGetActiveZoneIdCallback){ - mGetActiveZoneIdCallback(result); + if (methodName == api::host::METHOD_GET_ACTIVE_ZONE_ID) { + if (mGetActiveZoneIdCallback) { + auto rb = std::make_shared>(result); + mGetActiveZoneIdCallback(rb); } return; } - if (methodName == api::host::METHOD_GET_ZONE_INFO){ + if (methodName == api::host::METHOD_GET_ZONE_INFO) { const gchar* id = NULL; g_variant_get(parameters, "(&s)", &id); if (mGetZoneInfoCallback) { - mGetZoneInfoCallback(id, result); + auto rb = std::make_shared>(result); + mGetZoneInfoCallback(id, rb); } return; } - if (methodName == api::host::METHOD_SET_NETDEV_ATTRS){ + if (methodName == api::host::METHOD_SET_NETDEV_ATTRS) { const gchar* zone = NULL; const gchar* netdev = NULL; GVariantIter* iter; @@ -324,26 +331,29 @@ void HostConnection::onMessageCall(const std::string& objectPath, } g_variant_iter_free(iter); if (mSetNetdevAttrsCallback) { - mSetNetdevAttrsCallback(zone, netdev, attrs, result); + auto rb = std::make_shared>(result); + mSetNetdevAttrsCallback(zone, netdev, attrs, rb); } return; } - if (methodName == api::host::METHOD_GET_NETDEV_ATTRS){ + if (methodName == api::host::METHOD_GET_NETDEV_ATTRS) { const gchar* zone = NULL; const gchar* netdev = NULL; g_variant_get(parameters, "(&s&s)", &zone, &netdev); if (mGetNetdevAttrsCallback) { - mGetNetdevAttrsCallback(zone, netdev, result); + auto rb = std::make_shared>(result); + mGetNetdevAttrsCallback(zone, netdev, rb); } return; } - if (methodName == api::host::METHOD_GET_NETDEV_LIST){ + if (methodName == api::host::METHOD_GET_NETDEV_LIST) { const gchar* zone = NULL; g_variant_get(parameters, "(&s)", &zone); if (mGetNetdevListCallback) { - mGetNetdevListCallback(zone, result); + auto rb = std::make_shared>(result); + mGetNetdevListCallback(zone, rb); } return; } @@ -355,7 +365,8 @@ void HostConnection::onMessageCall(const std::string& objectPath, const gchar* hostDev = NULL; g_variant_get(parameters, "(&s&s&s)", &id, &zoneDev, &hostDev); if (mCreateNetdevVethCallback) { - mCreateNetdevVethCallback(id, zoneDev, hostDev, result); + auto rb = std::make_shared>(result); + mCreateNetdevVethCallback(id, zoneDev, hostDev, rb); } return; } @@ -367,7 +378,8 @@ void HostConnection::onMessageCall(const std::string& objectPath, guint32 mode; g_variant_get(parameters, "(&s&s&su)", &id, &zoneDev, &hostDev, &mode); if (mCreateNetdevMacvlanCallback) { - mCreateNetdevMacvlanCallback(id, zoneDev, hostDev, mode, result); + auto rb = std::make_shared>(result); + mCreateNetdevMacvlanCallback(id, zoneDev, hostDev, mode, rb); } } @@ -376,7 +388,8 @@ void HostConnection::onMessageCall(const std::string& objectPath, const gchar* devId = NULL; g_variant_get(parameters, "(&s&s)", &id, &devId); if (mCreateNetdevPhysCallback) { - mCreateNetdevPhysCallback(id, devId, result); + auto rb = std::make_shared>(result); + mCreateNetdevPhysCallback(id, devId, rb); } } @@ -389,7 +402,8 @@ void HostConnection::onMessageCall(const std::string& objectPath, g_variant_get(parameters, "(&si&sii)", &zone, &type, &path, &flags, &mode); if (mDeclareFileCallback) { - mDeclareFileCallback(zone, type, path, flags, mode, result); + auto rb = std::make_shared>(result); + mDeclareFileCallback(zone, type, path, flags, mode, rb); } return; } @@ -411,7 +425,8 @@ void HostConnection::onMessageCall(const std::string& objectPath, &data); if (mDeclareMountCallback) { - mDeclareMountCallback(source, zone, target, type, flags, data, result); + auto rb = std::make_shared>(result); + mDeclareMountCallback(source, zone, target, type, flags, data, rb); } return; } @@ -423,7 +438,8 @@ void HostConnection::onMessageCall(const std::string& objectPath, g_variant_get(parameters, "(&s&s&s)", &source, &zone, &target); if (mDeclareLinkCallback) { - mDeclareLinkCallback(source, zone, target, result); + auto rb = std::make_shared>(result); + mDeclareLinkCallback(source, zone, target, rb); } return; } @@ -433,7 +449,8 @@ void HostConnection::onMessageCall(const std::string& objectPath, g_variant_get(parameters, "(&s)", &zone); if (mGetDeclarationsCallback) { - mGetDeclarationsCallback(zone, result); + auto rb = std::make_shared>(result); + mGetDeclarationsCallback(zone, rb); } return; } @@ -444,7 +461,8 @@ void HostConnection::onMessageCall(const std::string& objectPath, g_variant_get(parameters, "(&s&s)", &zone, &declarationId); if (mRemoveDeclarationCallback) { - mRemoveDeclarationCallback(zone, declarationId, result); + auto rb = std::make_shared>(result); + mRemoveDeclarationCallback(zone, declarationId, rb); } return; } @@ -454,8 +472,9 @@ void HostConnection::onMessageCall(const std::string& objectPath, const gchar* templateName = NULL; g_variant_get(parameters, "(&s&s)", &id, &templateName); - if (mCreateZoneCallback){ - mCreateZoneCallback(id, templateName, result); + if (mCreateZoneCallback) { + auto rb = std::make_shared>(result); + mCreateZoneCallback(id, templateName, rb); } return; } @@ -464,8 +483,9 @@ void HostConnection::onMessageCall(const std::string& objectPath, const gchar* id = NULL; g_variant_get(parameters, "(&s)", &id); - if (mDestroyZoneCallback){ - mDestroyZoneCallback(id, result); + if (mDestroyZoneCallback) { + auto rb = std::make_shared>(result); + mDestroyZoneCallback(id, rb); } return; } @@ -474,8 +494,9 @@ void HostConnection::onMessageCall(const std::string& objectPath, const gchar* id = NULL; g_variant_get(parameters, "(&s)", &id); - if (mShutdownZoneCallback){ - mShutdownZoneCallback(id, result); + if (mShutdownZoneCallback) { + auto rb = std::make_shared>(result); + mShutdownZoneCallback(id, rb); } } @@ -483,8 +504,9 @@ void HostConnection::onMessageCall(const std::string& objectPath, const gchar* id = NULL; g_variant_get(parameters, "(&s)", &id); - if (mStartZoneCallback){ - mStartZoneCallback(id, result); + if (mStartZoneCallback) { + auto rb = std::make_shared>(result); + mStartZoneCallback(id, rb); } } @@ -492,8 +514,9 @@ void HostConnection::onMessageCall(const std::string& objectPath, const gchar* id = NULL; g_variant_get(parameters, "(&s)", &id); - if (mLockZoneCallback){ - mLockZoneCallback(id, result); + if (mLockZoneCallback) { + auto rb = std::make_shared>(result); + mLockZoneCallback(id, rb); } return; } @@ -502,8 +525,9 @@ void HostConnection::onMessageCall(const std::string& objectPath, const gchar* id = NULL; g_variant_get(parameters, "(&s)", &id); - if (mUnlockZoneCallback){ - mUnlockZoneCallback(id, result); + if (mUnlockZoneCallback) { + auto rb = std::make_shared>(result); + mUnlockZoneCallback(id, rb); } return; } @@ -514,8 +538,9 @@ void HostConnection::onMessageCall(const std::string& objectPath, uint32_t flags; g_variant_get(parameters, "(&s&su)", &id, &device, &flags); - if (mGrantDeviceCallback){ - mGrantDeviceCallback(id, device, flags, result); + if (mGrantDeviceCallback) { + auto rb = std::make_shared>(result); + mGrantDeviceCallback(id, device, flags, rb); } return; } @@ -525,8 +550,9 @@ void HostConnection::onMessageCall(const std::string& objectPath, const gchar* device = NULL; g_variant_get(parameters, "(&s&s)", &id, &device); - if (mRevokeDeviceCallback){ - mRevokeDeviceCallback(id, device, result); + if (mRevokeDeviceCallback) { + auto rb = std::make_shared>(result); + mRevokeDeviceCallback(id, device, rb); } return; } diff --git a/server/host-connection.hpp b/server/host-connection.hpp index 569c68f..3ef8cdf 100644 --- a/server/host-connection.hpp +++ b/server/host-connection.hpp @@ -27,6 +27,7 @@ #define SERVER_HOST_CONNECTION_HPP #include "dbus/connection.hpp" +#include "api/method-result-builder.hpp" #include #include @@ -53,48 +54,48 @@ public: GVariant* parameters, dbus::MethodResultBuilder::Pointer result )> ProxyCallCallback; - typedef std::function GetZoneDbusesCallback; - typedef std::function GetZoneIdsCallback; - typedef std::function GetActiveZoneIdCallback; typedef std::function GetZoneInfoCallback; typedef std::function>& attrs, - dbus::MethodResultBuilder::Pointer result + api::MethodResultBuilder::Pointer result )> SetNetdevAttrsCallback; typedef std::function GetNetdevAttrsCallback; typedef std::function GetNetdevListCallback; typedef std::function CreateNetdevVethCallback; typedef std::function CreateNetdevMacvlanCallback; typedef std::function CreateNetdevPhysCallback; typedef std::function DeclareFileCallback; typedef std::function DeclareMountCallback; typedef std::function DeclareLinkCallback; typedef std::function GetDeclarationsCallback; typedef std::function RemoveDeclarationCallback; typedef std::function SetActiveZoneCallback; typedef std::function CreateZoneCallback; typedef std::function DestroyZoneCallback; typedef std::function ShutdownZoneCallback; typedef std::function StartZoneCallback; typedef std::function LockZoneCallback; typedef std::function UnlockZoneCallback; typedef std::function GrantDeviceCallback; typedef std::function RevokeDeviceCallback; /** @@ -171,7 +172,7 @@ public: /** * Register a callback called to get the active zone id */ - void setGetActiveZoneIdCallback(const GetZoneIdsCallback& callback); + void setGetActiveZoneIdCallback(const GetActiveZoneIdCallback& callback); /** * Register a callback called to get the zone informations diff --git a/server/host-dbus-definitions.hpp b/server/host-dbus-definitions.hpp index 2c2a201..34d64eb 100644 --- a/server/host-dbus-definitions.hpp +++ b/server/host-dbus-definitions.hpp @@ -79,7 +79,7 @@ const std::string DEFINITION = " " " " " " - " " + " " " " " " " " diff --git a/server/zone-connection.cpp b/server/zone-connection.cpp index 35341b3..a86886c 100644 --- a/server/zone-connection.cpp +++ b/server/zone-connection.cpp @@ -30,6 +30,9 @@ // TODO: Switch to real power-manager dbus defs when they will be implemented in power-manager #include "fake-power-manager-dbus-definitions.hpp" +#include "api/dbus-method-result-builder.hpp" +#include "api/messages.hpp" + #include "logger/logger.hpp" @@ -139,10 +142,10 @@ void ZoneConnection::setDisplayOffCallback(const DisplayOffCallback& callback) mDisplayOffCallback = callback; } -void ZoneConnection::setFileMoveRequestCallback( - const FileMoveRequestCallback& callback) +void ZoneConnection::setFileMoveCallback( + const FileMoveCallback& callback) { - mFileMoveRequestCallback = callback; + mFileMoveCallback = callback; } void ZoneConnection::setProxyCallCallback(const ProxyCallCallback& callback) @@ -165,8 +168,8 @@ void ZoneConnection::onMessageCall(const std::string& objectPath, const gchar* message = NULL; g_variant_get(parameters, "(&s&s)", &application, &message); if (mNotifyActiveZoneCallback) { - mNotifyActiveZoneCallback(application, message); - result->setVoid(); + auto rb = std::make_shared>(result); + mNotifyActiveZoneCallback(application, message, rb); } } @@ -174,8 +177,9 @@ void ZoneConnection::onMessageCall(const std::string& objectPath, const gchar* destination = NULL; const gchar* path = NULL; g_variant_get(parameters, "(&s&s)", &destination, &path); - if (mFileMoveRequestCallback) { - mFileMoveRequestCallback(destination, path, result); + if (mFileMoveCallback) { + auto rb = std::make_shared>(result); + mFileMoveCallback(destination, path, rb); } } diff --git a/server/zone-connection.hpp b/server/zone-connection.hpp index 78b6e56..8f025b0 100644 --- a/server/zone-connection.hpp +++ b/server/zone-connection.hpp @@ -27,11 +27,11 @@ #define SERVER_ZONE_CONNECTION_HPP #include "dbus/connection.hpp" +#include "api/method-result-builder.hpp" #include #include - namespace vasum { @@ -47,13 +47,14 @@ public: // ------------- API -------------- typedef std::function NotifyActiveZoneCallback; typedef std::function FileMoveRequestCallback; + api::MethodResultBuilder::Pointer result + )> FileMoveCallback; typedef std::function ProxyCallCallback; + )> ProxyCallCallback; /** * Register notification request callback @@ -77,7 +78,7 @@ public: /* * Register file move request callback */ - void setFileMoveRequestCallback(const FileMoveRequestCallback& callback); + void setFileMoveCallback(const FileMoveCallback& callback); /** * Register proxy call callback @@ -110,7 +111,7 @@ private: OnNameLostCallback mOnNameLostCallback; NotifyActiveZoneCallback mNotifyActiveZoneCallback; DisplayOffCallback mDisplayOffCallback; - FileMoveRequestCallback mFileMoveRequestCallback; + FileMoveCallback mFileMoveCallback; ProxyCallCallback mProxyCallCallback; void onNameAcquired(); diff --git a/server/zone.cpp b/server/zone.cpp index 1bc2d09..181cc9e 100644 --- a/server/zone.cpp +++ b/server/zone.cpp @@ -206,7 +206,7 @@ void Zone::connect() mConnection->setDisplayOffCallback(mDisplayOffCallback); } if (mFileMoveCallback) { - mConnection->setFileMoveRequestCallback(mFileMoveCallback); + mConnection->setFileMoveCallback(mFileMoveCallback); } if (mProxyCallCallback) { mConnection->setProxyCallCallback(mProxyCallCallback); @@ -411,13 +411,13 @@ void Zone::setDisplayOffCallback(const DisplayOffCallback& callback) } } -void Zone::setFileMoveRequestCallback(const FileMoveRequestCallback& callback) +void Zone::setFileMoveCallback(const FileMoveCallback& callback) { Lock lock(mReconnectMutex); mFileMoveCallback = callback; if (mConnection) { - mConnection->setFileMoveRequestCallback(callback); + mConnection->setFileMoveCallback(callback); } } diff --git a/server/zone.hpp b/server/zone.hpp index 69d0324..45bacbd 100644 --- a/server/zone.hpp +++ b/server/zone.hpp @@ -67,7 +67,7 @@ public: typedef ZoneConnection::NotifyActiveZoneCallback NotifyActiveZoneCallback; typedef ZoneConnection::DisplayOffCallback DisplayOffCallback; - typedef ZoneConnection::FileMoveRequestCallback FileMoveRequestCallback; + typedef ZoneConnection::FileMoveCallback FileMoveCallback; typedef ZoneConnection::ProxyCallCallback ProxyCallCallback; typedef std::function DbusStateChangedCallback; @@ -210,7 +210,7 @@ public: /** * Register file move request callback */ - void setFileMoveRequestCallback(const FileMoveRequestCallback& callback); + void setFileMoveCallback(const FileMoveCallback& callback); /** * Register dbus state changed callback @@ -319,7 +319,7 @@ private: mutable std::recursive_mutex mReconnectMutex; NotifyActiveZoneCallback mNotifyCallback; DisplayOffCallback mDisplayOffCallback; - FileMoveRequestCallback mFileMoveCallback; + FileMoveCallback mFileMoveCallback; ProxyCallCallback mProxyCallCallback; DbusStateChangedCallback mDbusStateChangedCallback; std::string mDbusAddress; diff --git a/server/zones-manager.cpp b/server/zones-manager.cpp index d90bab7..2dcfaa0 100644 --- a/server/zones-manager.cpp +++ b/server/zones-manager.cpp @@ -40,6 +40,7 @@ #include "utils/fs.hpp" #include "utils/img.hpp" #include "utils/environment.hpp" +#include "api/messages.hpp" #include #include @@ -56,7 +57,7 @@ namespace { bool regexMatchVector(const std::string& str, const std::vector& v) { - for (const boost::regex& toMatch: v) { + for (const boost::regex& toMatch : v) { if (boost::regex_match(str, toMatch)) { return true; } @@ -129,7 +130,7 @@ ZonesManager::ZonesManager(const std::string& configPath) mHostConnection.setProxyCallCallback(bind(&ZonesManager::handleProxyCall, this, HOST_ID, _1, _2, _3, _4, _5, _6, _7)); - mHostConnection.setGetZoneDbusesCallback(bind(&ZonesManager::handleGetZoneDbuses, + mHostConnection.setGetZoneDbusesCallback(bind(&ZonesManager::handleGetZoneDbusesCall, this, _1)); mHostConnection.setGetZoneIdsCallback(bind(&ZonesManager::handleGetZoneIdsCall, @@ -142,22 +143,22 @@ ZonesManager::ZonesManager(const std::string& configPath) this, _1, _2)); mHostConnection.setSetNetdevAttrsCallback(bind(&ZonesManager::handleSetNetdevAttrsCall, - this, _1, _2, _3, _4)); + this, _1, _2, _3, _4)); mHostConnection.setGetNetdevAttrsCallback(bind(&ZonesManager::handleGetNetdevAttrsCall, - this, _1, _2, _3)); + this, _1, _2, _3)); mHostConnection.setGetNetdevListCallback(bind(&ZonesManager::handleGetNetdevListCall, - this, _1, _2)); + this, _1, _2)); mHostConnection.setCreateNetdevVethCallback(bind(&ZonesManager::handleCreateNetdevVethCall, - this, _1, _2, _3, _4)); + this, _1, _2, _3, _4)); mHostConnection.setCreateNetdevMacvlanCallback(bind(&ZonesManager::handleCreateNetdevMacvlanCall, - this, _1, _2, _3, _4, _5)); + this, _1, _2, _3, _4, _5)); mHostConnection.setCreateNetdevPhysCallback(bind(&ZonesManager::handleCreateNetdevPhysCall, - this, _1, _2, _3)); + this, _1, _2, _3)); mHostConnection.setDeclareFileCallback(bind(&ZonesManager::handleDeclareFileCall, this, _1, _2, _3, _4, _5, _6)); @@ -172,7 +173,7 @@ ZonesManager::ZonesManager(const std::string& configPath) this, _1, _2)); mHostConnection.setRemoveDeclarationCallback(bind(&ZonesManager::handleRemoveDeclarationCall, - this, _1, _2, _3)); + this, _1, _2, _3)); mHostConnection.setSetActiveZoneCallback(bind(&ZonesManager::handleSetActiveZoneCall, this, _1, _2)); @@ -212,9 +213,9 @@ ZonesManager::ZonesManager(const std::string& configPath) if (mConfig.inputConfig.enabled) { LOGI("Registering input monitor [" << mConfig.inputConfig.device.c_str() << "]"); mSwitchingSequenceMonitor.reset( - new InputMonitor(mConfig.inputConfig, - std::bind(&ZonesManager::switchingSequenceMonitorNotify, - this))); + new InputMonitor(mConfig.inputConfig, + std::bind(&ZonesManager::switchingSequenceMonitorNotify, + this))); } @@ -307,13 +308,13 @@ void ZonesManager::insertZone(const std::string& zoneId, const std::string& zone mConfig.runMountPointPrefix)); using namespace std::placeholders; - zone->setNotifyActiveZoneCallback(bind(&ZonesManager::notifyActiveZoneHandler, - this, zoneId, _1, _2)); + zone->setNotifyActiveZoneCallback(bind(&ZonesManager::handleNotifyActiveZoneCall, + this, zoneId, _1, _2, _3)); - zone->setDisplayOffCallback(bind(&ZonesManager::displayOffHandler, + zone->setDisplayOffCallback(bind(&ZonesManager::handleDisplayOffCall, this, zoneId)); - zone->setFileMoveRequestCallback(bind(&ZonesManager::handleZoneMoveFileRequest, + zone->setFileMoveCallback(bind(&ZonesManager::handleFileMoveCall, this, zoneId, _1, _2, _3)); zone->setProxyCallCallback(bind(&ZonesManager::handleProxyCall, @@ -547,11 +548,12 @@ void ZonesManager::setZonesDetachOnExit() } } -void ZonesManager::notifyActiveZoneHandler(const std::string& caller, - const std::string& application, - const std::string& message) +void ZonesManager::handleNotifyActiveZoneCall(const std::string& caller, + const std::string& application, + const std::string& message, + api::MethodResultBuilder::Pointer result) { - LOGI("notifyActiveZoneHandler(" << caller << ", " << application << ", " << message + LOGI("handleNotifyActiveZoneCall(" << caller << ", " << application << ", " << message << ") called"); Lock lock(mMutex); @@ -561,12 +563,14 @@ void ZonesManager::notifyActiveZoneHandler(const std::string& caller, if (iter != mZones.end() && caller != get(iter).getId()) { get(iter).sendNotification(caller, application, message); } - } catch(const VasumException&) { + result->setVoid(); + } catch (const VasumException&) { LOGE("Notification from " << caller << " hasn't been sent"); + result->setError(api::ERROR_INTERNAL, "Notification hasn't been sent"); } } -void ZonesManager::displayOffHandler(const std::string& /*caller*/) +void ZonesManager::handleDisplayOffCall(const std::string& /*caller*/) { // get config of currently set zone and switch if switchToDefaultAfterTimeout is true Lock lock(mMutex); @@ -584,10 +588,10 @@ void ZonesManager::displayOffHandler(const std::string& /*caller*/) } } -void ZonesManager::handleZoneMoveFileRequest(const std::string& srcZoneId, - const std::string& dstZoneId, - const std::string& path, - dbus::MethodResultBuilder::Pointer result) +void ZonesManager::handleFileMoveCall(const std::string& srcZoneId, + const std::string& dstZoneId, + const std::string& path, + api::MethodResultBuilder::Pointer result) { // TODO: this implementation is only a placeholder. // There are too many unanswered questions and security concerns: @@ -622,29 +626,35 @@ void ZonesManager::handleZoneMoveFileRequest(const std::string& srcZoneId, } Zone& srcZone = get(srcIter); + auto status = std::make_shared(); + auto dstIter = findZone(dstZoneId); if (dstIter == mZones.end()) { LOGE("Destination zone '" << dstZoneId << "' not found"); - result->set(g_variant_new("(s)", api::zone::FILE_MOVE_DESTINATION_NOT_FOUND.c_str())); + status->value = api::zone::FILE_MOVE_DESTINATION_NOT_FOUND; + result->set(status); return; } Zone& dstContanier = get(dstIter); if (srcZoneId == dstZoneId) { LOGE("Cannot send a file to yourself"); - result->set(g_variant_new("(s)", api::zone::FILE_MOVE_WRONG_DESTINATION.c_str())); + status->value = api::zone::FILE_MOVE_WRONG_DESTINATION; + result->set(status); return; } if (!regexMatchVector(path, srcZone.getPermittedToSend())) { LOGE("Source zone has no permissions to send the file: " << path); - result->set(g_variant_new("(s)", api::zone::FILE_MOVE_NO_PERMISSIONS_SEND.c_str())); + status->value = api::zone::FILE_MOVE_NO_PERMISSIONS_SEND; + result->set(status); return; } if (!regexMatchVector(path, dstContanier.getPermittedToRecv())) { LOGE("Destination zone has no permissions to receive the file: " << path); - result->set(g_variant_new("(s)", api::zone::FILE_MOVE_NO_PERMISSIONS_RECEIVE.c_str())); + status->value = api::zone::FILE_MOVE_NO_PERMISSIONS_RECEIVE; + result->set(status); return; } @@ -654,9 +664,11 @@ void ZonesManager::handleZoneMoveFileRequest(const std::string& srcZoneId, if (!utils::moveFile(srcPath, dstPath)) { LOGE("Failed to move the file: " << path); - result->set(g_variant_new("(s)", api::zone::FILE_MOVE_FAILED.c_str())); + status->value = api::zone::FILE_MOVE_FAILED; + result->set(status); } else { - result->set(g_variant_new("(s)", api::zone::FILE_MOVE_SUCCEEDED.c_str())); + status->value = api::zone::FILE_MOVE_SUCCEEDED; + result->set(status); try { dstContanier.sendNotification(srcZoneId, path, api::zone::FILE_MOVE_SUCCEEDED); } catch (ServerException&) { @@ -681,15 +693,15 @@ void ZonesManager::handleProxyCall(const std::string& caller, targetInterface, targetMethod)) { LOGW("Forbidden proxy call; " << caller << " -> " << target << "; " << targetBusName - << "; " << targetObjectPath << "; " << targetInterface << "; " << targetMethod); + << "; " << targetObjectPath << "; " << targetInterface << "; " << targetMethod); result->setError(api::ERROR_FORBIDDEN, "Proxy call forbidden"); return; } LOGI("Proxy call; " << caller << " -> " << target << "; " << targetBusName - << "; " << targetObjectPath << "; " << targetInterface << "; " << targetMethod); + << "; " << targetObjectPath << "; " << targetInterface << "; " << targetMethod); - auto asyncResultCallback = [result](dbus::AsyncMethodCallResult& asyncMethodCallResult) { + auto asyncResultCallback = [result](dbus::AsyncMethodCallResult & asyncMethodCallResult) { try { GVariant* targetResult = asyncMethodCallResult.get(); result->set(g_variant_new("(v)", targetResult)); @@ -719,26 +731,22 @@ void ZonesManager::handleProxyCall(const std::string& caller, Zone& targetZone = get(targetIter); targetZone.proxyCallAsync(targetBusName, - targetObjectPath, - targetInterface, - targetMethod, - parameters, - asyncResultCallback); + targetObjectPath, + targetInterface, + targetMethod, + parameters, + asyncResultCallback); } -void ZonesManager::handleGetZoneDbuses(dbus::MethodResultBuilder::Pointer result) +void ZonesManager::handleGetZoneDbusesCall(api::MethodResultBuilder::Pointer result) { Lock lock(mMutex); - std::vector entries; + auto dbuses = std::make_shared(); for (auto& zone : mZones) { - GVariant* zoneId = g_variant_new_string(zone->getId().c_str()); - GVariant* dbusAddress = g_variant_new_string(zone->getDbusAddress().c_str()); - GVariant* entry = g_variant_new_dict_entry(zoneId, dbusAddress); - entries.push_back(entry); + dbuses->values.push_back({zone->getId(), zone->getDbusAddress()}); } - GVariant* dict = g_variant_new_array(G_VARIANT_TYPE("{ss}"), entries.data(), entries.size()); - result->set(g_variant_new("(@a{ss})", dict)); + result->set(dbuses); } void ZonesManager::handleDbusStateChanged(const std::string& zoneId, @@ -747,31 +755,28 @@ void ZonesManager::handleDbusStateChanged(const std::string& zoneId, mHostConnection.signalZoneDbusState(zoneId, dbusAddress); } -void ZonesManager::handleGetZoneIdsCall(dbus::MethodResultBuilder::Pointer result) +void ZonesManager::handleGetZoneIdsCall(api::MethodResultBuilder::Pointer result) { Lock lock(mMutex); - std::vector zoneIds; - for(auto& zone: mZones){ - zoneIds.push_back(g_variant_new_string(zone->getId().c_str())); + auto zoneIds = std::make_shared(); + for (const auto& zone : mZones) { + zoneIds->values.push_back(zone->getId()); } - GVariant* array = g_variant_new_array(G_VARIANT_TYPE("s"), - zoneIds.data(), - zoneIds.size()); - result->set(g_variant_new("(@as)", array)); + result->set(zoneIds); } -void ZonesManager::handleGetActiveZoneIdCall(dbus::MethodResultBuilder::Pointer result) +void ZonesManager::handleGetActiveZoneIdCall(api::MethodResultBuilder::Pointer result) { LOGI("GetActiveZoneId call"); - - std::string id = getRunningForegroundZoneId(); - result->set(g_variant_new("(s)", id.c_str())); + auto zoneId = std::make_shared(); + zoneId->value = getRunningForegroundZoneId(); + result->set(zoneId); } void ZonesManager::handleGetZoneInfoCall(const std::string& id, - dbus::MethodResultBuilder::Pointer result) + api::MethodResultBuilder::Pointer result) { LOGI("GetZoneInfo call"); @@ -783,38 +788,33 @@ void ZonesManager::handleGetZoneInfoCall(const std::string& id, result->setError(api::ERROR_INVALID_ID, "No such zone id"); return; } + Zone& zone = get(iter); - const char* state; + auto zoneInfo = std::make_shared(); if (zone.isRunning()) { - state = "RUNNING"; + zoneInfo->state = "RUNNING"; } else if (zone.isStopped()) { - state = "STOPPED"; + zoneInfo->state = "STOPPED"; } else if (zone.isPaused()) { - state = "FROZEN"; + zoneInfo->state = "FROZEN"; } else { LOGE("Unrecognized state of zone id=" << id); result->setError(api::ERROR_INTERNAL, "Unrecognized state of zone"); return; } - result->set(g_variant_new("((siss))", - id.c_str(), - zone.getVT(), - state, - zone.getRootPath().c_str())); + result->set(zoneInfo); } void ZonesManager::handleSetNetdevAttrsCall(const std::string& zone, const std::string& netdev, - const std::vector< - std::tuple>& attrs, - dbus::MethodResultBuilder::Pointer result) + const std::vector>& attrs, + api::MethodResultBuilder::Pointer result) { LOGI("SetNetdevAttrs call"); try { Lock lock(mMutex); - getZone(zone).setNetdevAttrs(netdev, attrs); result->setVoid(); } catch (const InvalidZoneIdException&) { @@ -828,23 +828,18 @@ void ZonesManager::handleSetNetdevAttrsCall(const std::string& zone, void ZonesManager::handleGetNetdevAttrsCall(const std::string& zone, const std::string& netdev, - dbus::MethodResultBuilder::Pointer result) + api::MethodResultBuilder::Pointer result) { LOGI("GetNetdevAttrs call"); try { Lock lock(mMutex); - + auto netDevAttrs = std::make_shared(); const auto attrs = getZone(zone).getNetdevAttrs(netdev); - GVariantBuilder builder; - g_variant_builder_init(&builder, G_VARIANT_TYPE_ARRAY); - for (const auto entry : attrs) { - g_variant_builder_add(&builder, - "(ss)", - std::get<0>(entry).c_str(), - std::get<1>(entry).c_str()); + for (size_t i = 0; i < attrs.size(); ++i) { + netDevAttrs->values.push_back({std::get<0>(attrs[i]), std::get<1>(attrs[i])}); } - result->set(g_variant_builder_end(&builder)); + result->set(netDevAttrs); } catch (const InvalidZoneIdException&) { LOGE("No zone with id=" << zone); result->setError(api::ERROR_INVALID_ID, "No such zone id"); @@ -855,19 +850,14 @@ void ZonesManager::handleGetNetdevAttrsCall(const std::string& zone, } void ZonesManager::handleGetNetdevListCall(const std::string& zone, - dbus::MethodResultBuilder::Pointer result) + api::MethodResultBuilder::Pointer result) { LOGI("GetNetdevList call"); try { Lock lock(mMutex); - std::vector netdevs; - for(auto& netdev: getZone(zone).getNetdevList()){ - netdevs.push_back(g_variant_new_string(netdev.c_str())); - } - GVariant* array = g_variant_new_array(G_VARIANT_TYPE("s"), - netdevs.data(), - netdevs.size()); - result->set(g_variant_new("(@as)", array)); + auto netDevList = std::make_shared(); + netDevList->values = getZone(zone).getNetdevList(); + result->set(netDevList); } catch (const InvalidZoneIdException&) { LOGE("No zone with id=" << zone); result->setError(api::ERROR_INVALID_ID, "No such zone id"); @@ -880,7 +870,7 @@ void ZonesManager::handleGetNetdevListCall(const std::string& zone, void ZonesManager::handleCreateNetdevVethCall(const std::string& zone, const std::string& zoneDev, const std::string& hostDev, - dbus::MethodResultBuilder::Pointer result) + api::MethodResultBuilder::Pointer result) { LOGI("CreateNetdevVeth call"); try { @@ -901,7 +891,7 @@ void ZonesManager::handleCreateNetdevMacvlanCall(const std::string& zone, const std::string& zoneDev, const std::string& hostDev, const uint32_t& mode, - dbus::MethodResultBuilder::Pointer result) + api::MethodResultBuilder::Pointer result) { LOGI("CreateNetdevMacvlan call"); try { @@ -920,7 +910,7 @@ void ZonesManager::handleCreateNetdevMacvlanCall(const std::string& zone, void ZonesManager::handleCreateNetdevPhysCall(const std::string& zone, const std::string& devId, - dbus::MethodResultBuilder::Pointer result) + api::MethodResultBuilder::Pointer result) { LOGI("CreateNetdevPhys call"); try { @@ -942,15 +932,15 @@ void ZonesManager::handleDeclareFileCall(const std::string& zone, const std::string& path, const int32_t& flags, const int32_t& mode, - dbus::MethodResultBuilder::Pointer result) + api::MethodResultBuilder::Pointer result) { LOGI("DeclareFile call"); try { Lock lock(mMutex); - - const std::string id = getZone(zone).declareFile(type, path, flags, mode); - result->set(g_variant_new("(s)", id.c_str())); + auto declaration = std::make_shared(); + declaration->value = getZone(zone).declareFile(type, path, flags, mode); + result->set(declaration); } catch (const InvalidZoneIdException&) { LOGE("No zone with id=" << zone); result->setError(api::ERROR_INVALID_ID, "No such zone id"); @@ -966,15 +956,15 @@ void ZonesManager::handleDeclareMountCall(const std::string& source, const std::string& type, const uint64_t& flags, const std::string& data, - dbus::MethodResultBuilder::Pointer result) + api::MethodResultBuilder::Pointer result) { LOGI("DeclareMount call"); try { Lock lock(mMutex); - - const std::string id = getZone(zone).declareMount(source, target, type, flags, data); - result->set(g_variant_new("(s)", id.c_str())); + auto declaration = std::make_shared(); + declaration->value = getZone(zone).declareMount(source, target, type, flags, data); + result->set(declaration); } catch (const InvalidZoneIdException&) { LOGE("No zone with id=" << zone); result->setError(api::ERROR_INVALID_ID, "No such zone id"); @@ -987,14 +977,14 @@ void ZonesManager::handleDeclareMountCall(const std::string& source, void ZonesManager::handleDeclareLinkCall(const std::string& source, const std::string& zone, const std::string& target, - dbus::MethodResultBuilder::Pointer result) + api::MethodResultBuilder::Pointer result) { LOGI("DeclareLink call"); try { Lock lock(mMutex); - - const std::string id = getZone(zone).declareLink(source, target); - result->set(g_variant_new("(s)", id.c_str())); + auto declaration = std::make_shared(); + declaration->value = getZone(zone).declareLink(source, target); + result->set(declaration); } catch (const InvalidZoneIdException&) { LOGE("No zone with id=" << zone); result->setError(api::ERROR_INVALID_ID, "No such zone id"); @@ -1005,23 +995,14 @@ void ZonesManager::handleDeclareLinkCall(const std::string& source, } void ZonesManager::handleGetDeclarationsCall(const std::string& zone, - dbus::MethodResultBuilder::Pointer result) + api::MethodResultBuilder::Pointer result) { LOGI("GetDeclarations call Id=" << zone); try { Lock lock(mMutex); - - std::vector declarations = getZone(zone).getDeclarations(); - - std::vector out; - for (auto declaration : declarations) { - out.push_back(g_variant_new_string(declaration.c_str())); - } - - GVariant* array = g_variant_new_array(G_VARIANT_TYPE("s"), - out.data(), - out.size()); - result->set(g_variant_new("(@as)", array)); + auto declarations = std::make_shared(); + declarations->values = getZone(zone).getDeclarations(); + result->set(declarations); } catch (const InvalidZoneIdException&) { LOGE("No zone with id=" << zone); result->setError(api::ERROR_INVALID_ID, "No such zone id"); @@ -1029,12 +1010,11 @@ void ZonesManager::handleGetDeclarationsCall(const std::string& zone, LOGE(ex.what()); result->setError(api::ERROR_INTERNAL, ex.what()); } - } void ZonesManager::handleRemoveDeclarationCall(const std::string& zone, const std::string& declarationId, - dbus::MethodResultBuilder::Pointer result) + api::MethodResultBuilder::Pointer result) { LOGI("RemoveDeclaration call Id=" << zone); try { @@ -1053,20 +1033,20 @@ void ZonesManager::handleRemoveDeclarationCall(const std::string& zone, } void ZonesManager::handleSetActiveZoneCall(const std::string& id, - dbus::MethodResultBuilder::Pointer result) + api::MethodResultBuilder::Pointer result) { LOGI("SetActiveZone call; Id=" << id ); Lock lock(mMutex); auto iter = findZone(id); - if (iter == mZones.end()){ + if (iter == mZones.end()) { LOGE("No zone with id=" << id ); result->setError(api::ERROR_INVALID_ID, "No such zone id"); return; } - if (!get(iter).isRunning()){ + if (!get(iter).isRunning()) { LOGE("Could not activate stopped or paused zone"); result->setError(api::host::ERROR_ZONE_NOT_RUNNING, "Could not activate stopped or paused zone"); @@ -1170,11 +1150,11 @@ void ZonesManager::createZone(const std::string& id, } } - auto removeAllWrapper = [](const std::string& path) -> bool { + auto removeAllWrapper = [](const std::string & path) -> bool { try { LOGD("Removing copied data"); fs::remove_all(fs::path(path)); - } catch(const std::exception& e) { + } catch (const std::exception& e) { LOGW("Failed to remove data: " << boost::diagnostic_information(e)); } return true; @@ -1208,7 +1188,7 @@ void ZonesManager::createZone(const std::string& id, void ZonesManager::handleCreateZoneCall(const std::string& id, const std::string& templateName, - dbus::MethodResultBuilder::Pointer result) + api::MethodResultBuilder::Pointer result) { try { createZone(id, templateName); @@ -1221,7 +1201,7 @@ void ZonesManager::handleCreateZoneCall(const std::string& id, } void ZonesManager::handleDestroyZoneCall(const std::string& id, - dbus::MethodResultBuilder::Pointer result) + api::MethodResultBuilder::Pointer result) { auto destroyer = [id, result, this] { try { @@ -1243,7 +1223,7 @@ void ZonesManager::handleDestroyZoneCall(const std::string& id, } void ZonesManager::handleShutdownZoneCall(const std::string& id, - dbus::MethodResultBuilder::Pointer result) + api::MethodResultBuilder::Pointer result) { LOGI("ShutdownZone call; Id=" << id ); @@ -1272,7 +1252,7 @@ void ZonesManager::handleShutdownZoneCall(const std::string& id, } void ZonesManager::handleStartZoneCall(const std::string& id, - dbus::MethodResultBuilder::Pointer result) + api::MethodResultBuilder::Pointer result) { LOGI("StartZone call; Id=" << id ); @@ -1299,7 +1279,7 @@ void ZonesManager::handleStartZoneCall(const std::string& id, } void ZonesManager::handleLockZoneCall(const std::string& id, - dbus::MethodResultBuilder::Pointer result) + api::MethodResultBuilder::Pointer result) { LOGI("LockZone call; Id=" << id ); @@ -1334,7 +1314,7 @@ void ZonesManager::handleLockZoneCall(const std::string& id, } void ZonesManager::handleUnlockZoneCall(const std::string& id, - dbus::MethodResultBuilder::Pointer result) + api::MethodResultBuilder::Pointer result) { LOGI("UnlockZone call; Id=" << id ); @@ -1369,7 +1349,7 @@ void ZonesManager::handleUnlockZoneCall(const std::string& id, void ZonesManager::handleGrantDeviceCall(const std::string& id, const std::string& device, uint32_t flags, - dbus::MethodResultBuilder::Pointer result) + api::MethodResultBuilder::Pointer result) { LOGI("GrantDevice call; id=" << id << "; dev=" << device); @@ -1409,7 +1389,7 @@ void ZonesManager::handleGrantDeviceCall(const std::string& id, void ZonesManager::handleRevokeDeviceCall(const std::string& id, const std::string& device, - dbus::MethodResultBuilder::Pointer result) + api::MethodResultBuilder::Pointer result) { LOGI("RevokeDevice call; id=" << id << "; dev=" << device); diff --git a/server/zones-manager.hpp b/server/zones-manager.hpp index cb730e3..825b1c8 100644 --- a/server/zones-manager.hpp +++ b/server/zones-manager.hpp @@ -32,6 +32,7 @@ #include "input-monitor.hpp" #include "proxy-call-policy.hpp" #include "utils/worker.hpp" +#include "api/method-result-builder.hpp" #include #include @@ -145,14 +146,15 @@ private: int getVTForNewZone(); void insertZone(const std::string& zoneId, const std::string& templatePath); - void notifyActiveZoneHandler(const std::string& caller, - const std::string& appliaction, - const std::string& message); - void displayOffHandler(const std::string& caller); - void handleZoneMoveFileRequest(const std::string& srcZoneId, - const std::string& dstZoneId, - const std::string& path, - dbus::MethodResultBuilder::Pointer result); + void handleNotifyActiveZoneCall(const std::string& caller, + const std::string& appliaction, + const std::string& message, + api::MethodResultBuilder::Pointer result); + void handleDisplayOffCall(const std::string& caller); + void handleFileMoveCall(const std::string& srcZoneId, + const std::string& dstZoneId, + const std::string& path, + api::MethodResultBuilder::Pointer result); void handleProxyCall(const std::string& caller, const std::string& target, const std::string& targetBusName, @@ -161,76 +163,76 @@ private: const std::string& targetMethod, GVariant* parameters, dbus::MethodResultBuilder::Pointer result); - void handleGetZoneDbuses(dbus::MethodResultBuilder::Pointer result); + void handleGetZoneDbusesCall(api::MethodResultBuilder::Pointer result); void handleDbusStateChanged(const std::string& zoneId, const std::string& dbusAddress); - void handleGetZoneIdsCall(dbus::MethodResultBuilder::Pointer result); - void handleGetActiveZoneIdCall(dbus::MethodResultBuilder::Pointer result); - void handleGetZoneInfoCall(const std::string& id, dbus::MethodResultBuilder::Pointer result); + void handleGetZoneIdsCall(api::MethodResultBuilder::Pointer result); + void handleGetActiveZoneIdCall(api::MethodResultBuilder::Pointer result); + void handleGetZoneInfoCall(const std::string& id, api::MethodResultBuilder::Pointer result); void handleSetNetdevAttrsCall(const std::string& zone, const std::string& netdev, const std::vector>& attrs, - dbus::MethodResultBuilder::Pointer result); + api::MethodResultBuilder::Pointer result); void handleGetNetdevAttrsCall(const std::string& zone, const std::string& netdev, - dbus::MethodResultBuilder::Pointer result); + api::MethodResultBuilder::Pointer result); void handleGetNetdevListCall(const std::string& zone, - dbus::MethodResultBuilder::Pointer result); + api::MethodResultBuilder::Pointer result); void handleCreateNetdevVethCall(const std::string& zone, const std::string& zoneDev, const std::string& hostDev, - dbus::MethodResultBuilder::Pointer result); + api::MethodResultBuilder::Pointer result); void handleCreateNetdevMacvlanCall(const std::string& zone, const std::string& zoneDev, const std::string& hostDev, const uint32_t& mode, - dbus::MethodResultBuilder::Pointer result); + api::MethodResultBuilder::Pointer result); void handleCreateNetdevPhysCall(const std::string& zone, const std::string& devId, - dbus::MethodResultBuilder::Pointer result); + api::MethodResultBuilder::Pointer result); void handleDeclareFileCall(const std::string& zone, const int32_t& type, const std::string& path, const int32_t& flags, const int32_t& mode, - dbus::MethodResultBuilder::Pointer result); + api::MethodResultBuilder::Pointer result); void handleDeclareMountCall(const std::string& source, const std::string& zone, const std::string& target, const std::string& type, const uint64_t& flags, const std::string& data, - dbus::MethodResultBuilder::Pointer result); + api::MethodResultBuilder::Pointer result); void handleDeclareLinkCall(const std::string& source, const std::string& zone, const std::string& target, - dbus::MethodResultBuilder::Pointer result); + api::MethodResultBuilder::Pointer result); void handleGetDeclarationsCall(const std::string& zone, - dbus::MethodResultBuilder::Pointer result); + api::MethodResultBuilder::Pointer result); void handleRemoveDeclarationCall(const std::string& zone, const std::string& declarationId, - dbus::MethodResultBuilder::Pointer result); + api::MethodResultBuilder::Pointer result); void handleSetActiveZoneCall(const std::string& id, - dbus::MethodResultBuilder::Pointer result); + api::MethodResultBuilder::Pointer result); void handleCreateZoneCall(const std::string& id, const std::string& templateName, - dbus::MethodResultBuilder::Pointer result); + api::MethodResultBuilder::Pointer result); void handleDestroyZoneCall(const std::string& id, - dbus::MethodResultBuilder::Pointer result); + api::MethodResultBuilder::Pointer result); void handleShutdownZoneCall(const std::string& id, - dbus::MethodResultBuilder::Pointer result); + api::MethodResultBuilder::Pointer result); void handleStartZoneCall(const std::string& id, - dbus::MethodResultBuilder::Pointer result); + api::MethodResultBuilder::Pointer result); void handleLockZoneCall(const std::string& id, - dbus::MethodResultBuilder::Pointer result); + api::MethodResultBuilder::Pointer result); void handleUnlockZoneCall(const std::string& id, - dbus::MethodResultBuilder::Pointer result); + api::MethodResultBuilder::Pointer result); void handleGrantDeviceCall(const std::string& id, const std::string& device, uint32_t flags, - dbus::MethodResultBuilder::Pointer result); + api::MethodResultBuilder::Pointer result); void handleRevokeDeviceCall(const std::string& id, const std::string& device, - dbus::MethodResultBuilder::Pointer result); + api::MethodResultBuilder::Pointer result); }; diff --git a/tests/unit_tests/server/ut-zone-connection.cpp b/tests/unit_tests/server/ut-zone-connection.cpp index fb6df88..2a72b87 100644 --- a/tests/unit_tests/server/ut-zone-connection.cpp +++ b/tests/unit_tests/server/ut-zone-connection.cpp @@ -41,6 +41,8 @@ #include "utils/fs.hpp" #include "utils/scoped-dir.hpp" +#include "api/method-result-builder.hpp" + using namespace vasum; using namespace vasum::utils; @@ -141,10 +143,11 @@ BOOST_AUTO_TEST_CASE(NotifyActiveZoneApiTest) Latch notifyCalled; ZoneConnection connection(acquireAddress(), nullptr); - auto callback = [&](const std::string& application, const std::string& message) { + auto callback = [&](const std::string& application, const std::string& message, api::MethodResultBuilder::Pointer result) { if (application == "testapp" && message == "testmessage") { notifyCalled.set(); } + result->setVoid(); }; connection.setNotifyActiveZoneCallback(callback); @@ -169,19 +172,19 @@ BOOST_AUTO_TEST_CASE(SignalNotificationApiTest) const std::string& objectPath, const std::string& interface, const std::string& signalName, - GVariant* parameters) { + GVariant* parameters) { if (objectPath == api::zone::OBJECT_PATH && - interface == api::zone::INTERFACE && - signalName == api::zone::SIGNAL_NOTIFICATION && - g_variant_is_of_type(parameters, G_VARIANT_TYPE("(sss)"))) { + interface == api::zone::INTERFACE && + signalName == api::zone::SIGNAL_NOTIFICATION && + g_variant_is_of_type(parameters, G_VARIANT_TYPE("(sss)"))) { const gchar* zone = NULL; const gchar* application = NULL; const gchar* message = NULL; g_variant_get(parameters, "(&s&s&s)", &zone, &application, &message); if (zone == std::string("testzone") && - application == std::string("testapp") && - message == std::string("testmessage")) { + application == std::string("testapp") && + message == std::string("testmessage")) { signalEmitted.set(); } } diff --git a/tests/unit_tests/server/ut-zones-manager.cpp b/tests/unit_tests/server/ut-zones-manager.cpp index 0e40093..ea858e2 100644 --- a/tests/unit_tests/server/ut-zones-manager.cpp +++ b/tests/unit_tests/server/ut-zones-manager.cpp @@ -256,7 +256,7 @@ public: api::host::INTERFACE, api::host::METHOD_GET_ZONE_DBUSES, NULL, - "(a{ss})"); + "(a(ss))"); GVariant* array = NULL; g_variant_get(result.get(), "(*)", &array); dbus::GVariantPtr autounref(array, g_variant_unref); @@ -264,7 +264,7 @@ public: for (size_t n = 0; n < count; ++n) { const char* zoneId = NULL; const char* dbusAddress = NULL; - g_variant_get_child(array, n, "{&s&s}", &zoneId, &dbusAddress); + g_variant_get_child(array, n, "(&s&s)", &zoneId, &dbusAddress); dbuses.insert(Dbuses::value_type(zoneId, dbusAddress)); } return dbuses; -- 2.7.4 From 51dee2857db927c2be55c5eb6a2be8031f4b9082 Mon Sep 17 00:00:00 2001 From: Mateusz Malicki Date: Thu, 12 Mar 2015 15:42:08 +0100 Subject: [PATCH 07/16] Added functions to file descriptor passing and joining to namespace [Feature] Added functions to file descriptor passing and joining to namespace [Cause] N/A [Solution] N/A [Verification] Build, run tests Change-Id: I72ec4f65e469125d5add10cb87a6d044b4ff9b05 --- common/utils/environment.cpp | 167 +++++++++++++++++++++++++++++++++++++------ common/utils/environment.hpp | 9 +++ common/utils/execute.cpp | 64 +++++++++++++---- common/utils/execute.hpp | 18 +++++ common/utils/make-clean.hpp | 53 ++++++++++++++ 5 files changed, 274 insertions(+), 37 deletions(-) create mode 100644 common/utils/make-clean.hpp diff --git a/common/utils/environment.cpp b/common/utils/environment.cpp index 9d3f75a..fc45321 100644 --- a/common/utils/environment.cpp +++ b/common/utils/environment.cpp @@ -26,6 +26,8 @@ #include "utils/environment.hpp" #include "utils/execute.hpp" +#include "utils/make-clean.hpp" +#include "base-exception.hpp" #include "logger/logger.hpp" #include @@ -34,7 +36,95 @@ #include #include #include +#include +#include +#include +#include +#include +#include +#include + +#if !__GLIBC_PREREQ(2, 14) + +#include + +#ifdef __NR_setns +static inline int setns(int fd, int nstype) +{ + // setns system call are available since v2.6.39-6479-g7b21fdd + return syscall(__NR_setns, fd, nstype); +} +#else +#error "setns syscall isn't available" +#endif + +#endif + +using namespace vasum::utils; + +namespace { + +const std::map NAMESPACES = { + {CLONE_NEWIPC, "ipc"}, + {CLONE_NEWNET, "net"}, + {CLONE_NEWNS, "mnt"}, + {CLONE_NEWPID, "pid"}, + {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; +} +} // namespace namespace vasum { namespace utils { @@ -88,43 +178,76 @@ bool dropRoot(uid_t uid, gid_t gid, const std::vector& caps) bool launchAsRoot(const std::function& func) { // TODO optimize if getuid() == 0 - pid_t pid = fork(); - if (pid < 0) { - LOGE("Fork failed: " << strerror(errno)); - return false; - } - - if (pid == 0) { + return executeAndWait([&func]() { if (::setuid(0) < 0) { - LOGW("Failed to become root: " << strerror(errno)); + LOGW("Failed to become root: " << getSystemErrorMessage()); _exit(EXIT_FAILURE); } - try { - if (!func()) { - LOGE("Failed to successfully execute func"); - _exit(EXIT_FAILURE); - } - } catch (const std::exception& e) { - LOGE("Failed to successfully execute func: " << e.what()); + if (!func()) { + LOGE("Failed to successfully execute func"); _exit(EXIT_FAILURE); } + }); +} - _exit(EXIT_SUCCESS); +bool joinToNs(int nsPid, int ns) +{ + auto ins = NAMESPACES.find(ns); + if (ins == NAMESPACES.end()) { + LOGE("Namespace isn't supported: " << ns); + return false; } - - int status; - if (!waitPid(pid, status)) { + std::string nsPath = "/proc/" + std::to_string(nsPid) + "/ns/" + ins->second; + int nsFd = ::open(nsPath.c_str(), O_RDONLY); + if (nsFd == -1) { + LOGE("Can't open namesace: " + getSystemErrorMessage()); return false; } - if (status != 0) { - LOGE("Function launched as root exited with status " << status); + int ret = setns(nsFd, ins->first); + if (ret != 0) { + LOGE("Can't set namesace: " + getSystemErrorMessage()); + close(nsFd); return false; } - + close(nsFd); return true; } +int passNemaspacedFd(int nsPid, int ns, const std::function& fdFactory) +{ + int fds[2]; + int ret = socketpair(PF_LOCAL, SOCK_RAW, 0, fds); + if (ret == -1) { + LOGE("Can't create socket pair: " << vasum::getSystemErrorMessage()); + return -1; + } + bool success = executeAndWait([&, fds, nsPid, ns]() { + close(fds[0]); + + int fd = -1; + if (joinToNs(nsPid, ns)) { + fd = fdFactory(); + } + if (fd == -1) { + close(fds[1]); + _exit(EXIT_FAILURE); + } + LOGT("FD pass, send: " << fd); + fdSend(fds[1], fd); + close(fds[1]); + close(fd); + }); + + close(fds[1]); + int fd = -1; + if (success) { + fd = fdRecv(fds[0]); + } + close(fds[0]); + LOGT("FD pass, rcv: " << fd); + return fd; +} } // namespace utils } // namespace vasum diff --git a/common/utils/environment.hpp b/common/utils/environment.hpp index 2060e19..d63ac16 100644 --- a/common/utils/environment.hpp +++ b/common/utils/environment.hpp @@ -52,6 +52,15 @@ bool dropRoot(uid_t uid, gid_t gid, const std::vector& caps); */ bool launchAsRoot(const std::function& func); +/** + * Join to namespace + */ +bool joinToNs(int nsPid, int ns); + +/** + * Pass file descriptor from namespace of some process + */ +int passNemaspacedFd(int nsPid, int ns, const std::function& fdFactory); } // namespace utils } // namespace vasum diff --git a/common/utils/execute.cpp b/common/utils/execute.cpp index 5c9d1ce..4e8eebf 100644 --- a/common/utils/execute.cpp +++ b/common/utils/execute.cpp @@ -23,6 +23,7 @@ */ #include "config.hpp" +#include "base-exception.hpp" #include "utils/execute.hpp" #include "logger/logger.hpp" @@ -46,22 +47,65 @@ std::ostream& operator<< (std::ostream& out, const char* const* argv) return out; } +bool isExecutionSuccessful(int status) +{ + if (!WIFEXITED(status)) { + if (WIFSIGNALED(status)) { + LOGE("Child terminated by signal, signal: " << WTERMSIG(status)); + } else if (WIFSTOPPED(status)) { + LOGW("Child was stopped by signal " << WSTOPSIG(status)); + } else { + LOGE("Child exited abnormally, status: " << status); + } + return false; + } + if (WEXITSTATUS(status) != EXIT_SUCCESS) { + LOGE("Child exit status: " << WEXITSTATUS(status)); + return false; + } + return true; +} + } // namespace -bool executeAndWait(const char* fname, const char* const* argv, int& status) +bool executeAndWait(const std::function& func, int& status) { - LOGD("Execute " << fname << argv); + LOGD("Execute child process"); pid_t pid = fork(); if (pid == -1) { - LOGE("Fork failed"); + LOGE("Fork failed: " << vasum::getSystemErrorMessage()); return false; } if (pid == 0) { + func(); + _exit(EXIT_SUCCESS); + } + return waitPid(pid, status); +} + +bool executeAndWait(const std::function& func) +{ + int status; + if (!executeAndWait(func, status)) { + return false; + } + return isExecutionSuccessful(status); +} + + +bool executeAndWait(const char* fname, const char* const* argv, int& status) +{ + LOGD("Execute " << fname << argv); + + bool success = executeAndWait([=]() { execv(fname, const_cast(argv)); _exit(EXIT_FAILURE); + }, status); + if (!success) { + LOGW("Process " << fname << " has exited abnormally"); } - return waitPid(pid, status); + return success; } bool executeAndWait(const char* fname, const char* const* argv) @@ -70,17 +114,7 @@ bool executeAndWait(const char* fname, const char* const* argv) if (!executeAndWait(fname, argv, status)) { return false; } - if (status != EXIT_SUCCESS) { - if (WIFEXITED(status)) { - LOGW("Process " << fname << " has exited with status " << WEXITSTATUS(status)); - } else if (WIFSIGNALED(status)) { - LOGW("Process " << fname << " was killed by signal " << WTERMSIG(status)); - } else if (WIFSTOPPED(status)) { - LOGW("Process " << fname << " was stopped by signal " << WSTOPSIG(status)); - } - return false; - } - return true; + return isExecutionSuccessful(status); } bool waitPid(pid_t pid, int& status) diff --git a/common/utils/execute.hpp b/common/utils/execute.hpp index 47db58a..8f7fd56 100644 --- a/common/utils/execute.hpp +++ b/common/utils/execute.hpp @@ -26,14 +26,32 @@ #define COMMON_UTILS_EXECUTE_HPP #include +#include namespace vasum { namespace utils { +/** + * Execute binary + */ +///@{ bool executeAndWait(const char* fname, const char* const* argv); bool executeAndWait(const char* fname, const char* const* argv, int& status); +///@} + +/** + * Execute function in child process + */ +///@{ +bool executeAndWait(const std::function& func, int& status); + +bool executeAndWait(const std::function& func); +///@} +/** + * Wait until child processes ends + */ bool waitPid(pid_t pid, int& status); } // namespace utils diff --git a/common/utils/make-clean.hpp b/common/utils/make-clean.hpp new file mode 100644 index 0000000..1d551ef --- /dev/null +++ b/common/utils/make-clean.hpp @@ -0,0 +1,53 @@ +/* + * Copyright (c) 2014 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 Function used to initialize C structures + */ + +#ifndef COMMON_UTILS_MAKE_CLEAN_HPP +#define COMMON_UTILS_MAKE_CLEAN_HPP + +#include +#include + +namespace vasum { +namespace utils { + +template +void make_clean(T& value) +{ + static_assert(std::is_pod::value, "make_clean require trivial and standard-layout"); + std::fill_n(reinterpret_cast(&value), sizeof(value), 0); +} + +template +T make_clean() +{ + T value; + make_clean(value); + return value; +} + +} // namespace utils +} // namespace vasum + + +#endif // COMMON_UTILS_MAKE_CLEAN_HPP -- 2.7.4 From 476935e75959c057dcd506804cc873e29d30a425 Mon Sep 17 00:00:00 2001 From: Mateusz Malicki Date: Mon, 2 Mar 2015 12:44:42 +0100 Subject: [PATCH 08/16] Ability to fetch information from netlink (list netdev) [Feature] Ability to fetch information from netlink, list netdevs [Cause] N/A [Solution] N/A [Verification] Build, run test, run cli command (zone_get_netdevs) Change-Id: I404f6c2c47b0d2882b94649c134981a09a978a52 --- common/netlink/netlink-message.cpp | 223 +++++++++++++++++++++++++++++------- common/netlink/netlink-message.hpp | 132 ++++++++++++++++++++- common/netlink/netlink.cpp | 161 ++++++++++++++++---------- common/netlink/netlink.hpp | 17 ++- server/netdev.cpp | 38 +++--- server/netdev.hpp | 2 + server/zone-admin.cpp | 2 +- tests/unit_tests/server/ut-zone.cpp | 19 ++- 8 files changed, 473 insertions(+), 121 deletions(-) diff --git a/common/netlink/netlink-message.cpp b/common/netlink/netlink-message.cpp index 9f33450..ac42c58 100644 --- a/common/netlink/netlink-message.cpp +++ b/common/netlink/netlink-message.cpp @@ -29,8 +29,10 @@ #include +#include #include #include +#include #include #include @@ -38,16 +40,15 @@ #include #include -#ifndef PAGE_SIZE -#define PAGE_SIZE 4096 -#endif - namespace { -const int NLMSG_GOOD_SIZE = 2*PAGE_SIZE; -inline rtattr* NLMSG_TAIL(nlmsghdr* nmsg) +inline const rtattr* asAttr(const void* data) { return reinterpret_cast(data); } +inline const nlmsghdr* asHdr(const void* data) { return reinterpret_cast(data); } +inline rtattr* asAttr(void* data) { return reinterpret_cast(data); } +inline nlmsghdr* asHdr(void* data) { return reinterpret_cast(data); } +inline char* NLMSG_TAIL(nlmsghdr* nmsg) { - return reinterpret_cast(reinterpret_cast(nmsg) + NLMSG_ALIGN(nmsg->nlmsg_len)); + return reinterpret_cast(nmsg) + NLMSG_ALIGN(nmsg->nlmsg_len); } } // namespace @@ -55,10 +56,15 @@ inline rtattr* NLMSG_TAIL(nlmsghdr* nmsg) namespace vasum { namespace netlink { +NetlinkResponse send(const NetlinkMessage& msg) +{ + return send(msg, 0); +} + NetlinkMessage::NetlinkMessage(uint16_t type, uint16_t flags) { - static uint32_t seq = 0; - mNlmsg.resize(NLMSG_GOOD_SIZE, 0); + static std::atomic seq(0); + mNlmsg.resize(NLMSG_HDRLEN, 0); hdr().nlmsg_len = NLMSG_HDRLEN; hdr().nlmsg_flags = flags | NLM_F_ACK; hdr().nlmsg_type = type; @@ -68,18 +74,17 @@ NetlinkMessage::NetlinkMessage(uint16_t type, uint16_t flags) NetlinkMessage& NetlinkMessage::beginNested(int ifla) { - struct rtattr *nest = NLMSG_TAIL(&hdr()); + auto offset = std::distance(reinterpret_cast(&hdr()), NLMSG_TAIL(&hdr())); put(ifla, NULL, 0); - mNested.push(nest); + mNested.push(offset); return *this; } NetlinkMessage& NetlinkMessage::endNested() { assert(!mNested.empty()); - rtattr *nest = reinterpret_cast(mNested.top()); - nest->rta_len = std::distance(reinterpret_cast(nest), - reinterpret_cast(NLMSG_TAIL(&hdr()))); + rtattr* nest = asAttr(reinterpret_cast(&hdr()) + mNested.top()); + nest->rta_len = std::distance(reinterpret_cast(nest), NLMSG_TAIL(&hdr())); mNested.pop(); return *this; } @@ -96,7 +101,7 @@ NetlinkMessage& NetlinkMessage::put(int ifla, const void* data, int len) int newLen = NLMSG_ALIGN(hdr().nlmsg_len) + RTA_ALIGN(rtalen); setMinCapacity(newLen); - rta = NLMSG_TAIL(&hdr()); + rta = asAttr(NLMSG_TAIL(&hdr())); rta->rta_type = ifla; rta->rta_len = rtalen; memcpy(RTA_DATA(rta), data, len); @@ -113,11 +118,11 @@ NetlinkMessage& NetlinkMessage::put(const void* data, int len) } nlmsghdr& NetlinkMessage::hdr() { - return *reinterpret_cast(mNlmsg.data()); + return *asHdr(mNlmsg.data()); } const nlmsghdr& NetlinkMessage::hdr() const { - return *reinterpret_cast(mNlmsg.data()); + return *asHdr(mNlmsg.data()); } void NetlinkMessage::setMinCapacity(unsigned int size) @@ -127,41 +132,179 @@ void NetlinkMessage::setMinCapacity(unsigned int size) } } -void send(const NetlinkMessage& msg) +NetlinkResponse::NetlinkResponse(std::unique_ptr>&& message) + : mNlmsg(std::move(message)) + , mNlmsgHdr(asHdr(mNlmsg.get()->data())) + , mPosition(NLMSG_HDRLEN) { - //TODO: Handle messages with responses - assert(msg.hdr().nlmsg_flags & NLM_F_ACK); +} + +bool NetlinkResponse::hasMessage() const +{ + unsigned int tail = size() - getHdrPosition(); + bool hasHeader = NLMSG_OK(mNlmsgHdr, tail); + if (!hasHeader) { + return false; + } + //Check if isn't ACK message + return NLMSG_PAYLOAD(mNlmsgHdr,0) > sizeof(uint32_t); +} + +int NetlinkResponse::getMessageType() const +{ + return mNlmsgHdr->nlmsg_type; +} + +void NetlinkResponse::fetchNextMessage() +{ + if (mNlmsgHdr->nlmsg_type == NLMSG_DONE) { + throw VasumException("There is no next message"); + } + int tail = size() - mPosition; + mNlmsgHdr = NLMSG_NEXT(mNlmsgHdr, tail); + mPosition = getHdrPosition() + NLMSG_HDRLEN; +} + +bool NetlinkResponse::hasAttribute() const +{ + assert(mPosition >= getHdrPosition()); + int tail = mNlmsgHdr->nlmsg_len - (mPosition - getHdrPosition()); + return RTA_OK(asAttr(get(0)), tail); +} - const int answerLen = NLMSG_ALIGN(msg.hdr().nlmsg_len + sizeof(nlmsgerr)); - std::unique_ptr answerBuff(new char[answerLen]); - nlmsghdr* answer = reinterpret_cast(answerBuff.get()); - answer->nlmsg_len = answerLen; +bool NetlinkResponse::isNestedAttribute() const +{ + return asAttr(get(RTA_LENGTH(0)))->rta_len == RTA_LENGTH(0); +} + +void NetlinkResponse::skipAttribute() +{ + const rtattr *rta = asAttr(get(RTA_LENGTH(0))); + if (size() < mPosition + RTA_ALIGN(rta->rta_len)) { + LOGE("Skipping out of buffer:" + << " to: " << mPosition + RTA_ALIGN(rta->rta_len) + << ", buf size: " << size()); + throw VasumException("Skipping out of buffer"); + } + seek(RTA_ALIGN(rta->rta_len)); +} + +NetlinkResponse& NetlinkResponse::openNested(int ifla) +{ + const rtattr *rta = asAttr(get(RTA_LENGTH(0))); + if (rta->rta_type == ifla) { + LOGE("Wrong attribute type, expected: " << ifla << ", got: " << rta->rta_type); + throw VasumException("Wrong attribute type"); + } + int pos = mPosition; + seek(RTA_LENGTH(0)); + mNested.push(pos); + return *this; +} + +NetlinkResponse& NetlinkResponse::closeNested() +{ + assert(!mNested.empty()); + int pos = mNested.top(); + const rtattr *rta = asAttr(mNlmsg->data() + pos); + if (rta->rta_len != mPosition - pos) { + LOGE("There is no nested attribute end. Did you read all attributes (read: " + << mPosition - pos << ", length: " << rta->rta_len); + throw VasumException("There is no nested attribute end"); + } + mNested.pop(); + mPosition = pos; + return *this; +} +NetlinkResponse& NetlinkResponse::fetch(int ifla, std::string& value, int maxSize) +{ + value = std::string(get(ifla, maxSize)); + skipAttribute(); + return *this; +} + +const char* NetlinkResponse::get(int ifla, int len) const +{ + const rtattr *rta = asAttr(get(RTA_LENGTH(len < 0 ? 0 : len))); + if (rta->rta_type != ifla) { + LOGE("Wrong attribute type, expected:" << ifla << ", got: " << rta->rta_type); + throw VasumException("Wrong attribute type"); + } + if (len >= 0 && rta->rta_len != RTA_LENGTH(len)) { + LOGE("Wrong attribute length, expected: " << rta->rta_len + ", got " << len); + throw VasumException("Wrong attribute length"); + } + return reinterpret_cast(RTA_DATA(get(rta->rta_len))); +} + +const char* NetlinkResponse::get(int len) const +{ + if (size() < mPosition + len) { + LOGE("Read out of buffer:" + << " from: " << mPosition + len + << ", buf size: " << size()); + throw VasumException("Read out of buffer"); + } + return mNlmsg->data() + mPosition; +} + +NetlinkResponse& NetlinkResponse::fetch(int ifla, char* data, int len) +{ + std::copy_n(get(ifla, len), len, data); + skipAttribute(); + return *this; +} + +NetlinkResponse& NetlinkResponse::fetch(char* data, int len) +{ + std::copy_n(get(len), len, data); + seek(len); + return *this; +} + +int NetlinkResponse::getAttributeType() const +{ + return asAttr(get(RTA_LENGTH(0)))->rta_type; +} + +NetlinkResponse& NetlinkResponse::seek(int len) +{ + if (size() < mPosition + len) { + throw VasumException("Skipping out of buffer"); + } + mPosition += len; + return *this; +} + +int NetlinkResponse::size() const +{ + return mNlmsg->size(); +} + +inline int NetlinkResponse::getHdrPosition() const +{ + return std::distance(reinterpret_cast(mNlmsg->data()), + reinterpret_cast(mNlmsgHdr)); +} + +NetlinkResponse send(const NetlinkMessage& msg, int pid) +{ + assert(msg.hdr().nlmsg_flags & NLM_F_ACK); + + std::unique_ptr> data; Netlink nl; - nl.open(); + nl.open(pid); try { nl.send(&msg.hdr()); - //Receive ACK Netlink Message - do { - nl.rcv(answer); - } while (answer->nlmsg_type == NLMSG_NOOP); + data = nl.rcv(msg.hdr().nlmsg_seq); } catch (const std::exception& ex) { LOGE("Sending failed (" << ex.what() << ")"); nl.close(); throw; } nl.close(); - if (answer->nlmsg_type != NLMSG_ERROR) { - // It is not NACK/ACK message - throw VasumException("Sending failed ( unrecognized message type )"); - } - nlmsgerr *err = reinterpret_cast(NLMSG_DATA(answer)); - if (answer->nlmsg_seq != msg.hdr().nlmsg_seq) { - throw VasumException("Sending failed ( answer message was mismatched )"); - } - if (err->error) { - throw VasumException("Sending failed (" + getSystemErrorMessage(-err->error) + ")"); - } + return NetlinkResponse(std::move(data)); } } // namespace netlink diff --git a/common/netlink/netlink-message.hpp b/common/netlink/netlink-message.hpp index e828feb..6b84de4 100644 --- a/common/netlink/netlink-message.hpp +++ b/common/netlink/netlink-message.hpp @@ -25,6 +25,7 @@ #ifndef COMMON_NETLINK_NETLINK_MESSAGE_HPP #define COMMON_NETLINK_NETLINK_MESSAGE_HPP +#include #include #include #include @@ -35,6 +36,9 @@ namespace vasum { namespace netlink { +class NetlinkResponse; +class NetlinkMessage; + /** * NetlinkMessage is used to creatie a netlink messages */ @@ -81,21 +85,124 @@ public: * Send netlink message * * It is not thread safe + * @param msg Netlink message + * @param pid Process id which describes network namespace */ - friend void send(const NetlinkMessage& msg); + friend NetlinkResponse send(const NetlinkMessage& msg, int pid); private: std::vector mNlmsg; - std::stack mNested; + std::stack mNested; NetlinkMessage& put(int ifla, const void* data, int len); NetlinkMessage& put(const void* data, int len); nlmsghdr& hdr(); const nlmsghdr& hdr() const; void setMinCapacity(unsigned int size); +}; + +/** + * NetlinkResponse is used to read netlink messages + */ +class NetlinkResponse { +public: + /** + * Check if theres is next message in netlink response + */ + bool hasMessage() const; + + /** + * Fetch next message + */ + void fetchNextMessage(); + /** + * Get message type + */ + int getMessageType() const; + /** + * Check if there is any attribute in message + */ + bool hasAttribute() const; + + /** + * Check if current attribute is nested + */ + bool isNestedAttribute() const; + + /** + * Skip attribute + */ + void skipAttribute(); + + /** + * Start reading nested attribute + */ + NetlinkResponse& openNested(int ifla); + + /** + * End reading nested attribute + */ + NetlinkResponse& closeNested(); + + ///@{ + /** + * Fetch attribute + */ + NetlinkResponse& fetch(int ifla, std::string& value, int maxSize = std::string::npos); + template + NetlinkResponse& fetch(int ifla, T& value); + ///@} + + /** + * Get attributie type + **/ + int getAttributeType() const; + + /** + * Fetch data of type T + */ + template + NetlinkResponse& fetch(T& value); + + /** + * Skip data of type T + */ + template + NetlinkResponse& skip(); + + /** + * Send netlink message + * + * It is not thread safe + * @param msg Netlink message + * @param pid Process id which describes network namespace + */ + friend NetlinkResponse send(const NetlinkMessage& msg, int pid); +private: + NetlinkResponse(std::unique_ptr>&& message); + + std::unique_ptr> mNlmsg; + std::stack mNested; + nlmsghdr* mNlmsgHdr; + int mPosition; + + const char* get(int ifla, int iflasize) const; + const char* get(int size = 0) const; + NetlinkResponse& fetch(int ifla, char* data, int len); + NetlinkResponse& fetch(char* data, int len); + NetlinkResponse& seek(int len); + int size() const; + int getHdrPosition() const; }; +/** + * Send netlink message + * + * It is not thread safe + */ +NetlinkResponse send(const NetlinkMessage& msg); + template NetlinkMessage& NetlinkMessage::put(int ifla, const T& value) { @@ -110,6 +217,27 @@ NetlinkMessage& NetlinkMessage::put(const T& value) return put(&value, sizeof(value)); } +template +NetlinkResponse& NetlinkResponse::fetch(int ifla, T& value) +{ + static_assert(std::is_pod::value, "Require trivial and standard-layout"); + return fetch(ifla, reinterpret_cast(&value), sizeof(value)); +} + +template +NetlinkResponse& NetlinkResponse::fetch(T& value) +{ + static_assert(std::is_pod::value, "Require trivial and standard-layout structure"); + return fetch(reinterpret_cast(&value), sizeof(value)); +} + +template +NetlinkResponse& NetlinkResponse::skip() +{ + static_assert(std::is_pod::value, "Require trivial and standard-layout structure"); + return seek(sizeof(T)); +} + } // namespace netlink } // namespace vasum diff --git a/common/netlink/netlink.cpp b/common/netlink/netlink.cpp index fa86b45..e5cf8a7 100644 --- a/common/netlink/netlink.cpp +++ b/common/netlink/netlink.cpp @@ -26,6 +26,8 @@ #include "netlink.hpp" #include "utils.hpp" #include "base-exception.hpp" +#include "utils/make-clean.hpp" +#include "utils/environment.hpp" #include #include @@ -34,21 +36,54 @@ #include #include -namespace vasum { +#ifndef PAGE_SIZE +#define PAGE_SIZE 4096 +#endif + +using namespace vasum; namespace { -template -T make_clean() +const int NLMSG_RCV_GOOD_SIZE = 2*PAGE_SIZE; + +int vsm_recvmsg(int fd, struct msghdr *msg, int flags) { - static_assert(std::is_pod::value, "make_clean require trivial and standard-layout"); - T value; - std::fill_n(reinterpret_cast(&value), sizeof(value), 0); - return value; + int ret = recvmsg(fd, msg, flags); + if (ret < 0) { + LOGE("Can't receive message: " + getSystemErrorMessage()); + } else if (ret == 0 && msg->msg_iov && msg->msg_iov->iov_len > 0) { + LOGE("Peer has performed an orderly shutdown"); + } else if (msg->msg_flags & MSG_TRUNC) { + LOGE("Can't receive message: " + getSystemErrorMessage(EMSGSIZE)); + } else if (msg->msg_flags & MSG_ERRQUEUE) { + LOGE("No data was received but an extended error"); + } else if (msg->msg_flags & MSG_OOB) { + LOGE("Internal error (expedited or out-of-band data were received)"); + } else if (msg->msg_flags & MSG_CTRUNC) { + LOGE("Some control data were discarded"); + } else if (msg->msg_flags & MSG_EOR) { + LOGE("End-of-record"); + } else { + // All ok + return ret; + } + throw VasumException("Can't receive netlink message"); +} + +void vsm_sendmsg(int fd, const struct msghdr *msg, int flags) +{ + int ret = sendmsg(fd, msg, flags); + if (ret < 0) { + LOGE("Can't send message: " << getSystemErrorMessage()); + throw VasumException("Can't send netlink message"); + } } } // namespace +namespace vasum { +namespace netlink { + Netlink::Netlink() : mFd(-1) { } @@ -58,22 +93,30 @@ Netlink::~Netlink() close(); } -void Netlink::open() +void Netlink::open(int netNsPid) { + auto fdFactory = []{ return socket(AF_NETLINK, SOCK_RAW, NETLINK_ROUTE); }; + assert(mFd == -1); - mFd = socket(AF_NETLINK, SOCK_RAW, NETLINK_ROUTE); + if (netNsPid == 0 || netNsPid == getpid()) { + mFd = fdFactory(); + if (mFd == -1) { + LOGE("Can't open socket: " << getSystemErrorMessage()); + } + } else { + mFd = utils::passNemaspacedFd(netNsPid, CLONE_NEWNET, fdFactory); + } if (mFd == -1) { - LOGE("Can't open socket (" << getSystemErrorMessage() << ")"); throw VasumException("Can't open netlink connection"); } - sockaddr_nl local = make_clean(); + sockaddr_nl local = utils::make_clean(); local.nl_family = AF_NETLINK; if (bind(mFd, (struct sockaddr *)&local, sizeof(local)) < 0) { int err = errno; close(); - LOGE("Can't bind to socket (" << getSystemErrorMessage(err) << ")"); + LOGE("Can't bind to socket: " << getSystemErrorMessage(err)); throw VasumException("Can't set up netlink connection"); } } @@ -86,70 +129,72 @@ void Netlink::close() } } -void Netlink::send(const nlmsghdr *nlmsg) +unsigned int Netlink::send(const void *nlmsg) { - msghdr msg = make_clean(); - sockaddr_nl nladdr = make_clean(); - iovec iov = make_clean(); + msghdr msg = utils::make_clean(); + sockaddr_nl nladdr = utils::make_clean(); + iovec iov = utils::make_clean(); - iov.iov_base = (void *)nlmsg; - iov.iov_len = nlmsg->nlmsg_len; + iov.iov_base = const_cast(nlmsg); + iov.iov_len = reinterpret_cast(nlmsg)->nlmsg_len; msg.msg_name = &nladdr; msg.msg_namelen = sizeof(nladdr); msg.msg_iov = &iov; msg.msg_iovlen = 1; nladdr.nl_family = AF_NETLINK; - int ret = sendmsg(mFd, &msg, 0); - if (ret < 0) { - LOGE("Can't send message (" << getSystemErrorMessage() << ")"); - throw VasumException("Can't send netlink message"); - } + vsm_sendmsg(mFd, &msg, 0); + return reinterpret_cast(nlmsg)->nlmsg_seq; } -int Netlink::rcv(nlmsghdr *answer) +std::unique_ptr> Netlink::rcv(unsigned int nlmsgSeq) { - //TODO: Handle too small buffer situation (buffer resizing) - msghdr msg = make_clean(); - sockaddr_nl nladdr = make_clean(); - iovec iov = make_clean(); + std::unique_ptr> buf(new std::vector()); + + msghdr msg = utils::make_clean(); + sockaddr_nl nladdr = utils::make_clean(); + iovec iov = utils::make_clean(); - iov.iov_base = answer; - iov.iov_len = answer->nlmsg_len; msg.msg_name = &nladdr; msg.msg_namelen = sizeof(nladdr); msg.msg_iov = &iov; msg.msg_iovlen = 1; nladdr.nl_family = AF_NETLINK; - int ret = recvmsg(mFd, &msg, 0); - if (ret < 0) { - LOGE("Can't receive message (" + getSystemErrorMessage() + ")"); - throw VasumException("Can't receive netlink message"); - } - if (ret == 0) { - LOGE("Peer has performed an orderly shutdown"); - throw VasumException("Can't receive netlink message"); - } - if (msg.msg_flags & MSG_TRUNC) { - LOGE("Can't receive message (" + getSystemErrorMessage(EMSGSIZE) + ")"); - throw VasumException("Can't receive netlink message"); - } - if (msg.msg_flags & MSG_ERRQUEUE) { - LOGE("No data was received but an extended error"); - throw VasumException("Can't receive netlink message"); - } - if (msg.msg_flags & MSG_OOB) { - LOGE("Internal error (expedited or out-of-band data were received)"); - throw VasumException("Can't receive netlink message"); - } - if (msg.msg_flags & (MSG_EOR | MSG_CTRUNC)) { - assert(!"This should not happen!"); - LOGE("Internal error (" << std::to_string(msg.msg_flags) << ")"); - throw VasumException("Internal error while recaiving netlink message"); - } - - return ret; + nlmsghdr* answer; + nlmsghdr* lastOk = NULL; + size_t offset = 0; + do { + buf->resize(offset + NLMSG_RCV_GOOD_SIZE); + answer = reinterpret_cast(buf->data() + offset); + iov.iov_base = answer; + iov.iov_len = buf->size() - offset; + unsigned int ret = vsm_recvmsg(mFd, &msg, 0); + for (unsigned int len = ret; NLMSG_OK(answer, len); answer = NLMSG_NEXT(answer, len)) { + lastOk = answer; + if (answer->nlmsg_type == NLMSG_ERROR) { + // It is NACK/ACK message + nlmsgerr *err = reinterpret_cast(NLMSG_DATA(answer)); + if (answer->nlmsg_seq != nlmsgSeq) { + throw VasumException("Sending failed: answer message was mismatched"); + } + if (err->error) { + throw VasumException("Sending failed: " + getSystemErrorMessage(-err->error)); + } + } else if (answer->nlmsg_type == NLMSG_OVERRUN) { + throw VasumException("Sending failed: data lost"); + } + } + if (lastOk == NULL) { + LOGE("Something went terribly wrong. Check vsm_recvmsg function"); + throw VasumException("Can't receive data from system"); + } + offset += NLMSG_ALIGN(ret); + } while (lastOk->nlmsg_type != NLMSG_DONE && lastOk->nlmsg_flags & NLM_F_MULTI); + + buf->resize(offset); + return buf; } +} //namespace netlink } //namespace vasum diff --git a/common/netlink/netlink.hpp b/common/netlink/netlink.hpp index 2e73ce8..8d33957 100644 --- a/common/netlink/netlink.hpp +++ b/common/netlink/netlink.hpp @@ -25,9 +25,11 @@ #ifndef COMMON_NETLINK_NETLINK_HPP #define COMMON_NETLINK_NETLINK_HPP -#include +#include +#include namespace vasum { +namespace netlink { /** * Netlink class is responsible for communicating @@ -43,8 +45,10 @@ public: /** * Open connnection + * + * @param netNsPid pid which defines net namespace */ - void open(); + void open(int netNsPid = 0); /** * Close connection @@ -58,8 +62,9 @@ public: * different instances at the same time * * @param nlmsg pointer to message + * @return sequence number */ - void send(const nlmsghdr *nlmsg); + unsigned int send(const void* nlmsg); /** * Receive message @@ -67,13 +72,15 @@ public: * It is not thread safe and even you shouldn't call this function on * different instances at the same time * - * @param answer pointer to answer buffer + * @param nlmsgSeq sequence number + * @return received data */ - int rcv(nlmsghdr *answer); + std::unique_ptr> rcv(unsigned int nlmsgSeq); private: int mFd; }; +} // namesapce netlink } // namespace vasum #endif /* COMMON_NETLINK_NETLINK_HPP */ diff --git a/server/netdev.cpp b/server/netdev.cpp index b4a2d21..f8f9264 100644 --- a/server/netdev.cpp +++ b/server/netdev.cpp @@ -25,6 +25,7 @@ #include "config.hpp" #include "netdev.hpp" #include "netlink/netlink-message.hpp" +#include "utils/make-clean.hpp" #include "utils.hpp" #include "exception.hpp" @@ -55,15 +56,6 @@ namespace netdev { namespace { -template -T make_clean() -{ - static_assert(std::is_pod::value, "make_clean require trivial and standard-layout"); - T value; - std::fill_n(reinterpret_cast(&value), sizeof(value), 0); - return value; -} - string getUniqueVethName() { auto find = [](const ifaddrs* ifaddr, const string& name) -> bool { @@ -109,7 +101,7 @@ void createPipedNetdev(const string& netdev1, const string& netdev2) validateNetdevName(netdev2); NetlinkMessage nlm(RTM_NEWLINK, NLM_F_REQUEST | NLM_F_CREATE | NLM_F_EXCL | NLM_F_ACK); - ifinfomsg infoPeer = make_clean(); + ifinfomsg infoPeer = utils::make_clean(); infoPeer.ifi_family = AF_UNSPEC; infoPeer.ifi_change = 0xFFFFFFFF; nlm.put(infoPeer) @@ -138,7 +130,7 @@ void attachToBridge(const string& bridge, const string& netdev) throw ZoneOperationException("Can't attach to bridge"); } - struct ifreq ifr = make_clean(); + struct ifreq ifr = utils::make_clean(); strncpy(ifr.ifr_name, bridge.c_str(), IFNAMSIZ); ifr.ifr_ifindex = index; int err = ioctl(fd, SIOCBRADDIF, &ifr); @@ -156,7 +148,7 @@ int setFlags(const string& name, uint32_t mask, uint32_t flags) { uint32_t index = getInterfaceIndex(name); NetlinkMessage nlm(RTM_NEWLINK, NLM_F_REQUEST | NLM_F_ACK); - ifinfomsg infoPeer = make_clean(); + ifinfomsg infoPeer = utils::make_clean(); infoPeer.ifi_family = AF_UNSPEC; infoPeer.ifi_index = index; infoPeer.ifi_flags = flags; @@ -176,7 +168,7 @@ void moveToNS(const string& netdev, pid_t pid) { uint32_t index = getInterfaceIndex(netdev); NetlinkMessage nlm(RTM_NEWLINK, NLM_F_REQUEST | NLM_F_ACK); - ifinfomsg infopeer = make_clean(); + ifinfomsg infopeer = utils::make_clean(); infopeer.ifi_family = AF_UNSPEC; infopeer.ifi_index = index; nlm.put(infopeer) @@ -191,7 +183,7 @@ void createMacvlan(const string& master, const string& slave, const macvlan_mode uint32_t index = getInterfaceIndex(master); NetlinkMessage nlm(RTM_NEWLINK, NLM_F_REQUEST|NLM_F_CREATE|NLM_F_EXCL|NLM_F_ACK); - ifinfomsg infopeer = make_clean(); + ifinfomsg infopeer = utils::make_clean(); infopeer.ifi_family = AF_UNSPEC; infopeer.ifi_change = 0xFFFFFFFF; nlm.put(infopeer) @@ -237,6 +229,24 @@ void movePhys(const pid_t& nsPid, const string& devId) moveToNS(devId, nsPid); } +std::vector listNetdev(const pid_t& nsPid) +{ + NetlinkMessage nlm(RTM_GETLINK, NLM_F_REQUEST|NLM_F_DUMP|NLM_F_ROOT); + ifinfomsg info = utils::make_clean(); + info.ifi_family = AF_PACKET; + nlm.put(info); + NetlinkResponse response = send(nlm, nsPid); + std::vector interfaces; + while (response.hasMessage()) { + std::string ifName; + response.skip(); + response.fetch(IFLA_IFNAME, ifName); + interfaces.push_back(ifName); + response.fetchNextMessage(); + } + return interfaces; +} + } //namespace netdev } //namespace vasum diff --git a/server/netdev.hpp b/server/netdev.hpp index de761ca..b3d658a 100644 --- a/server/netdev.hpp +++ b/server/netdev.hpp @@ -26,6 +26,7 @@ #define SERVER_NETDEV_HPP #include +#include #include #include @@ -38,6 +39,7 @@ void createMacvlan(const pid_t& nsPid, const std::string& hostDev, const macvlan_mode& mode); void movePhys(const pid_t& nsPid, const std::string& devId); +std::vector listNetdev(const pid_t& nsPid); } //namespace netdev } //namespace vasum diff --git a/server/zone-admin.cpp b/server/zone-admin.cpp index 8005fb4..64092a8 100644 --- a/server/zone-admin.cpp +++ b/server/zone-admin.cpp @@ -314,7 +314,7 @@ ZoneAdmin::NetdevAttrs ZoneAdmin::getNetdevAttrs(const std::string& /* netdev */ std::vector ZoneAdmin::getNetdevList() { - throw ZoneOperationException("Not implemented"); + return netdev::listNetdev(mZone.getInitPid()); } } // namespace vasum diff --git a/tests/unit_tests/server/ut-zone.cpp b/tests/unit_tests/server/ut-zone.cpp index 37f65be..a8b608f 100644 --- a/tests/unit_tests/server/ut-zone.cpp +++ b/tests/unit_tests/server/ut-zone.cpp @@ -33,13 +33,13 @@ #include "utils/glib-loop.hpp" #include "utils/scoped-dir.hpp" #include "config/exception.hpp" +#include "netdev.hpp" #include #include #include #include - using namespace vasum; using namespace config; @@ -126,5 +126,22 @@ BOOST_AUTO_TEST_CASE(DbusConnectionTest) // TODO: DbusReconnectionTest +BOOST_AUTO_TEST_CASE(ListNetdevTest) +{ + typedef std::vector NetdevList; + + auto c = create(TEST_CONFIG_PATH); + c->start(); + ensureStarted(); + // Depending on the kernel configuration there can be lots of interfaces (f.e. sit0, ip6tnl0) + NetdevList netdevs = c->getNetdevList(); + // Check if there is mandatory loopback interface + BOOST_CHECK(find(netdevs.begin(), netdevs.end(), "lo") != netdevs.end()); + NetdevList hostNetdevs = netdev::listNetdev(0); + // Check if we get interfaces from zone net namespace + BOOST_CHECK(hostNetdevs != netdevs); + + c->stop(false); +} BOOST_AUTO_TEST_SUITE_END() -- 2.7.4 From 5a16448719fc2b94c103becb4dc3d523dda5372a Mon Sep 17 00:00:00 2001 From: Mateusz Malicki Date: Tue, 3 Mar 2015 16:01:44 +0100 Subject: [PATCH 09/16] Add destroyNetdev, createBridge and tests for netdev [Feature] Add destroyNetdev, createBridge, CreateNetdevVethTest, CreateNetdevMacvlanTest [Cause] N/A [Solution] Netlink interface [Verification] Build, run test Change-Id: Iba17d864158d35d71d2fae83742ef13d729d5a7f --- cli/command-line-interface.cpp | 13 +++++++ cli/command-line-interface.hpp | 7 ++++ cli/main.cpp | 9 +++++ client/vasum-client-impl.cpp | 6 +-- server/host-connection.cpp | 15 +++++++ server/host-connection.hpp | 10 +++++ server/host-dbus-definitions.hpp | 5 +++ server/netdev.cpp | 78 +++++++++++++++++++++++++++++++++---- server/netdev.hpp | 12 +++++- server/zone-admin.cpp | 5 +++ server/zone-admin.hpp | 5 +++ server/zone.cpp | 6 +++ server/zone.hpp | 5 +++ server/zones-manager.cpp | 22 +++++++++++ server/zones-manager.hpp | 3 ++ tests/unit_tests/server/ut-zone.cpp | 65 +++++++++++++++++++++++++++++++ 16 files changed, 255 insertions(+), 11 deletions(-) diff --git a/cli/command-line-interface.cpp b/cli/command-line-interface.cpp index ecf6b9c..100aaa1 100644 --- a/cli/command-line-interface.cpp +++ b/cli/command-line-interface.cpp @@ -397,6 +397,19 @@ void create_netdev_phys(int pos, int argc, const char** argv) argv[pos + 2])); } +void destroy_netdev(int pos, int argc, const char** argv) +{ + using namespace std::placeholders; + + if (argc <= pos + 2) { + throw runtime_error("Not enough parameters"); + } + one_shot(bind(vsm_destroy_netdev, + _1, + argv[pos + 1], + argv[pos + 2])); +} + void zone_get_netdevs(int pos, int argc, const char** argv) { using namespace std::placeholders; diff --git a/cli/command-line-interface.hpp b/cli/command-line-interface.hpp index eb33428..006396c 100644 --- a/cli/command-line-interface.hpp +++ b/cli/command-line-interface.hpp @@ -209,6 +209,13 @@ void create_netdev_macvlan(int pos, int argc, const char** argv); void create_netdev_phys(int pos, int argc, const char** argv); /** + * Parses command line arguments and call vsm_destroy_netdev + * + * @see vsm_destroy_netdev + */ +void destroy_netdev(int pos, int argc, const char** argv); + +/** * Parses command line arguments and prints result of vsm_zone_get_netdevs * * @see vsm_zone_get_netdevs diff --git a/cli/main.cpp b/cli/main.cpp index a30146e..c915415 100644 --- a/cli/main.cpp +++ b/cli/main.cpp @@ -173,6 +173,15 @@ std::map commands = { } }, { + "destroy_netdev", { + destroy_netdev, + "destroy_netdev zone_id devId", + "Destroy netdev in zone", + {{"zone_id", "id zone name"}, + {"devId", "network device id"}} + } + }, + { "zone_get_netdevs", { zone_get_netdevs, "zone_get_netdevs zone_id", diff --git a/client/vasum-client-impl.cpp b/client/vasum-client-impl.cpp index 1ac4c3c..fb1b2ec 100644 --- a/client/vasum-client-impl.cpp +++ b/client/vasum-client-impl.cpp @@ -768,10 +768,10 @@ VsmStatus Client::vsm_lookup_netdev_by_name(const char*, const char*, VsmNetdev* return vsm_get_status(); } -VsmStatus Client::vsm_destroy_netdev(const char*, const char*) noexcept +VsmStatus Client::vsm_destroy_netdev(const char* zone, const char* devId) noexcept { - mStatus = Status(VSMCLIENT_OTHER_ERROR, "Not implemented"); - return vsm_get_status(); + GVariant* args_in = g_variant_new("(ss)", zone, devId); + return callMethod(HOST_INTERFACE, api::host::METHOD_DESTROY_NETDEV, args_in); } VsmStatus Client::vsm_declare_file(const char* zone, diff --git a/server/host-connection.cpp b/server/host-connection.cpp index a1a7448..d0b612a 100644 --- a/server/host-connection.cpp +++ b/server/host-connection.cpp @@ -162,6 +162,11 @@ void HostConnection::setCreateNetdevPhysCallback(const CreateNetdevPhysCallback& mCreateNetdevPhysCallback = callback; } +void HostConnection::setDestroyNetdevCallback(const DestroyNetdevCallback& callback) +{ + mDestroyNetdevCallback = callback; +} + void HostConnection::setDeclareFileCallback(const DeclareFileCallback& callback) { mDeclareFileCallback = callback; @@ -393,6 +398,16 @@ void HostConnection::onMessageCall(const std::string& objectPath, } } + if (methodName == api::host::METHOD_DESTROY_NETDEV) { + const gchar* id = NULL; + const gchar* devId = NULL; + g_variant_get(parameters, "(&s&s)", &id, &devId); + if (mDestroyNetdevCallback) { + auto rb = std::make_shared>(result); + mDestroyNetdevCallback(id, devId, rb); + } + } + if (methodName == api::host::METHOD_DECLARE_FILE) { const gchar* zone; int32_t type; diff --git a/server/host-connection.hpp b/server/host-connection.hpp index 3ef8cdf..0ef9585 100644 --- a/server/host-connection.hpp +++ b/server/host-connection.hpp @@ -90,6 +90,10 @@ public: const std::string& devId, api::MethodResultBuilder::Pointer result )> CreateNetdevPhysCallback; + typedef std::function DestroyNetdevCallback; typedef std::function" " " + " " + " " + " " + " " " " " " " " diff --git a/server/netdev.cpp b/server/netdev.cpp index f8f9264..e17ecda 100644 --- a/server/netdev.cpp +++ b/server/netdev.cpp @@ -46,6 +46,17 @@ #include #include #include +#include +#include + +//IFLA_BRIDGE_FLAGS and BRIDGE_FLAGS_MASTER +//should be defined in linux/if_bridge.h since kernel v3.7 +#ifndef IFLA_BRIDGE_FLAGS +#define IFLA_BRIDGE_FLAGS 0 +#endif +#ifndef BRIDGE_FLAGS_MASTER +#define BRIDGE_FLAGS_MASTER 1 +#endif using namespace std; using namespace vasum; @@ -205,10 +216,18 @@ void createVeth(const pid_t& nsPid, const string& nsDev, const string& hostDev) string hostVeth = getUniqueVethName(); LOGT("Creating veth: bridge: " << hostDev << ", port: " << hostVeth << ", zone: " << nsDev); createPipedNetdev(nsDev, hostVeth); - //TODO: clean up if following instructions fail - attachToBridge(hostDev, hostVeth); - up(hostVeth); - moveToNS(nsDev, nsPid); + try { + attachToBridge(hostDev, hostVeth); + up(hostVeth); + moveToNS(nsDev, nsPid); + } catch(const exception& ex) { + try { + destroyNetdev(hostVeth); + } catch (const exception& ex) { + LOGE("Can't destroy netdev pipe: " << hostVeth << ", " << nsDev); + } + throw; + } } void createMacvlan(const pid_t& nsPid, @@ -218,9 +237,17 @@ void createMacvlan(const pid_t& nsPid, { LOGT("Creating macvlan: host: " << hostDev << ", zone: " << nsDev << ", mode: " << mode); createMacvlan(hostDev, nsDev, mode); - //TODO: clean up if following instructions fail - up(nsDev); - moveToNS(nsDev, nsPid); + try { + up(nsDev); + moveToNS(nsDev, nsPid); + } catch(const exception& ex) { + try { + destroyNetdev(nsDev); + } catch (const exception& ex) { + LOGE("Can't destroy netdev: " << nsDev); + } + throw; + } } void movePhys(const pid_t& nsPid, const string& devId) @@ -247,6 +274,43 @@ std::vector listNetdev(const pid_t& nsPid) return interfaces; } +void destroyNetdev(const string& netdev, const pid_t pid) +{ + LOGT("Destroying netdev: " << netdev); + validateNetdevName(netdev); + + NetlinkMessage nlm(RTM_DELLINK, NLM_F_REQUEST|NLM_F_ACK); + ifinfomsg infopeer = utils::make_clean(); + infopeer.ifi_family = AF_UNSPEC; + infopeer.ifi_change = 0xFFFFFFFF; + nlm.put(infopeer) + .put(IFLA_IFNAME, netdev); + send(nlm, pid); +} + +void createBridge(const string& netdev) +{ + LOGT("Creating bridge: " << netdev); + validateNetdevName(netdev); + + NetlinkMessage nlm(RTM_NEWLINK, NLM_F_REQUEST | NLM_F_CREATE | NLM_F_EXCL | NLM_F_ACK); + ifinfomsg infoPeer = utils::make_clean(); + infoPeer.ifi_family = AF_UNSPEC; + infoPeer.ifi_change = 0xFFFFFFFF; + nlm.put(infoPeer) + .beginNested(IFLA_LINKINFO) + .put(IFLA_INFO_KIND, "bridge") + .beginNested(IFLA_INFO_DATA) + .beginNested(IFLA_AF_SPEC) + .put(IFLA_BRIDGE_FLAGS, BRIDGE_FLAGS_MASTER) + .endNested() + .endNested() + .endNested() + .put(IFLA_IFNAME, netdev); + send(nlm); +} + + } //namespace netdev } //namespace vasum diff --git a/server/netdev.hpp b/server/netdev.hpp index b3d658a..0e9bfde 100644 --- a/server/netdev.hpp +++ b/server/netdev.hpp @@ -39,7 +39,17 @@ void createMacvlan(const pid_t& nsPid, const std::string& hostDev, const macvlan_mode& mode); void movePhys(const pid_t& nsPid, const std::string& devId); -std::vector listNetdev(const pid_t& nsPid); +std::vector listNetdev(const pid_t& nsPid = 0); +void destroyNetdev(const std::string& netdev, const pid_t pid = 0); + +/** + * Create bridge + * + * Bridge are in BRIDGE_MODE_VEB (loopback) mode and it is software bridge (BRIDGE_FLAGS_MASTER) + * + * @param netdev bridge name + */ +void createBridge(const std::string& netdev); } //namespace netdev } //namespace vasum diff --git a/server/zone-admin.cpp b/server/zone-admin.cpp index 64092a8..29577f8 100644 --- a/server/zone-admin.cpp +++ b/server/zone-admin.cpp @@ -302,6 +302,11 @@ void ZoneAdmin::moveNetdev(const std::string& devId) netdev::movePhys(mZone.getInitPid(), devId); } +void ZoneAdmin::destroyNetdev(const std::string& devId) +{ + netdev::destroyNetdev(devId, mZone.getInitPid()); +} + void ZoneAdmin::setNetdevAttrs(const std::string& /* netdev */, const NetdevAttrs& /* attrs */) { throw ZoneOperationException("Not implemented"); diff --git a/server/zone-admin.hpp b/server/zone-admin.hpp index ade4585..c6d26f0 100644 --- a/server/zone-admin.hpp +++ b/server/zone-admin.hpp @@ -150,6 +150,11 @@ public: void moveNetdev(const std::string& devId); /** + * Destroy network device in zone + */ + void destroyNetdev(const std::string& devId); + + /** * Set network device attributes */ void setNetdevAttrs(const std::string& netdev, const NetdevAttrs& attrs); diff --git a/server/zone.cpp b/server/zone.cpp index 181cc9e..b0c3c28 100644 --- a/server/zone.cpp +++ b/server/zone.cpp @@ -278,6 +278,12 @@ void Zone::moveNetdev(const std::string& devId) mAdmin->moveNetdev(devId); } +void Zone::destroyNetdev(const std::string& devId) +{ + Lock lock(mReconnectMutex); + mAdmin->destroyNetdev(devId); +} + void Zone::goForeground() { Lock lock(mReconnectMutex); diff --git a/server/zone.hpp b/server/zone.hpp index 45bacbd..b981e9a 100644 --- a/server/zone.hpp +++ b/server/zone.hpp @@ -292,6 +292,11 @@ public: void moveNetdev(const std::string& devId); /** + * Destroy network device in zone + */ + void destroyNetdev(const std::string& devId); + + /** * Set network device attributes */ void setNetdevAttrs(const std::string& netdev, const ZoneAdmin::NetdevAttrs& attrs); diff --git a/server/zones-manager.cpp b/server/zones-manager.cpp index 2dcfaa0..4266820 100644 --- a/server/zones-manager.cpp +++ b/server/zones-manager.cpp @@ -160,6 +160,9 @@ ZonesManager::ZonesManager(const std::string& configPath) mHostConnection.setCreateNetdevPhysCallback(bind(&ZonesManager::handleCreateNetdevPhysCall, this, _1, _2, _3)); + mHostConnection.setDestroyNetdevCallback(bind(&ZonesManager::handleDestroyNetdevCall, + this, _1, _2, _3)); + mHostConnection.setDeclareFileCallback(bind(&ZonesManager::handleDeclareFileCall, this, _1, _2, _3, _4, _5, _6)); @@ -927,6 +930,25 @@ void ZonesManager::handleCreateNetdevPhysCall(const std::string& zone, } } +void ZonesManager::handleDestroyNetdevCall(const std::string& zone, + const std::string& devId, + api::MethodResultBuilder::Pointer result) +{ + LOGI("DestroyNetdev call"); + try { + Lock lock(mMutex); + + getZone(zone).destroyNetdev(devId); + result->setVoid(); + } catch (const InvalidZoneIdException&) { + LOGE("No zone with id=" << zone); + result->setError(api::ERROR_INVALID_ID, "No such zone id"); + } catch (const VasumException& ex) { + LOGE("Can't create netdev: " << ex.what()); + result->setError(api::ERROR_INTERNAL, ex.what()); + } +} + void ZonesManager::handleDeclareFileCall(const std::string& zone, const int32_t& type, const std::string& path, diff --git a/server/zones-manager.hpp b/server/zones-manager.hpp index 825b1c8..deb9b9d 100644 --- a/server/zones-manager.hpp +++ b/server/zones-manager.hpp @@ -189,6 +189,9 @@ private: void handleCreateNetdevPhysCall(const std::string& zone, const std::string& devId, api::MethodResultBuilder::Pointer result); + void handleDestroyNetdevCall(const std::string& zone, + const std::string& devId, + api::MethodResultBuilder::Pointer result); void handleDeclareFileCall(const std::string& zone, const int32_t& type, const std::string& path, diff --git a/tests/unit_tests/server/ut-zone.cpp b/tests/unit_tests/server/ut-zone.cpp index a8b608f..91d0540 100644 --- a/tests/unit_tests/server/ut-zone.cpp +++ b/tests/unit_tests/server/ut-zone.cpp @@ -27,6 +27,7 @@ #include "ut.hpp" #include "zone.hpp" +#include "netdev.hpp" #include "exception.hpp" #include "utils/exception.hpp" @@ -39,8 +40,11 @@ #include #include #include +#include +#include using namespace vasum; +using namespace vasum::netdev; using namespace config; namespace { @@ -53,15 +57,28 @@ const std::string MISSING_CONFIG_PATH = TEMPLATES_DIR + "/missing.conf"; const std::string ZONES_PATH = "/tmp/ut-zones"; const std::string LXC_TEMPLATES_PATH = VSM_TEST_LXC_TEMPLATES_INSTALL_DIR; const std::string DB_PATH = ZONES_PATH + "/vasum.db"; +const std::string BRIDGE_NAME = "brtest01"; +const std::string ZONE_NETDEV = "netdevtest01"; struct Fixture { utils::ScopedGlibLoop mLoop; utils::ScopedDir mZonesPathGuard; utils::ScopedDir mRunGuard; + std::string mBridgeName; Fixture() : mZonesPathGuard(ZONES_PATH) {} + ~Fixture() + { + if (!mBridgeName.empty()) { + try { + destroyNetdev(mBridgeName); + } catch (std::exception& ex) { + BOOST_MESSAGE("Can't destroy bridge: " + std::string(ex.what())); + } + } + } std::unique_ptr create(const std::string& configPath) { @@ -74,11 +91,23 @@ struct Fixture { "")); } + void setupBridge(const std::string& name) + { + createBridge(name); + mBridgeName = name; + } + + void ensureStarted() { // wait for zones init to fully start std::this_thread::sleep_for(std::chrono::milliseconds(200)); } + void ensureStop() + { + // wait for fully stop + std::this_thread::sleep_for(std::chrono::milliseconds(200)); + } }; } // namespace @@ -144,4 +173,40 @@ BOOST_AUTO_TEST_CASE(ListNetdevTest) c->stop(false); } +BOOST_AUTO_TEST_CASE(CreateNetdevVethTest) +{ + typedef std::vector NetdevList; + + setupBridge(BRIDGE_NAME); + auto c = create(TEST_CONFIG_PATH); + c->start(); + ensureStarted(); + c->createNetdevVeth(ZONE_NETDEV, BRIDGE_NAME); + NetdevList netdevs = c->getNetdevList(); + BOOST_CHECK(find(netdevs.begin(), netdevs.end(), ZONE_NETDEV) != netdevs.end()); + c->stop(false); + ensureStop(); + + //Check clean up + NetdevList hostNetdevsInit = listNetdev(); + BOOST_REQUIRE_THROW(c->createNetdevVeth(ZONE_NETDEV, BRIDGE_NAME), VasumException); + NetdevList hostNetdevsThrow = listNetdev(); + BOOST_CHECK_EQUAL_COLLECTIONS(hostNetdevsInit.begin(), hostNetdevsInit.end(), + hostNetdevsThrow.begin(), hostNetdevsThrow.end()); +} + +BOOST_AUTO_TEST_CASE(CreateNetdevMacvlanTest) +{ + typedef std::vector NetdevList; + + setupBridge(BRIDGE_NAME); + auto c = create(TEST_CONFIG_PATH); + c->start(); + ensureStarted(); + c->createNetdevVeth(ZONE_NETDEV, BRIDGE_NAME); + NetdevList netdevs = c->getNetdevList(); + BOOST_CHECK(find(netdevs.begin(), netdevs.end(), ZONE_NETDEV) != netdevs.end()); + c->stop(false); +} + BOOST_AUTO_TEST_SUITE_END() -- 2.7.4 From 84a5119de0fdfa01e9a70a37682c29d25119f25e Mon Sep 17 00:00:00 2001 From: Piotr Bartosiewicz Date: Mon, 16 Mar 2015 16:14:54 +0100 Subject: [PATCH 10/16] Epoll modifyFD method added. Some refactor. [Bug/Feature] N/A [Cause] N/A [Solution] N/A [Verification] Run tests Change-Id: Idcba92d12a618a8095420f3c941a12d61aef1761 --- common/epoll/event-poll.cpp | 36 +++++-- common/epoll/event-poll.hpp | 11 ++- common/epoll/thread-dispatcher.cpp | 9 +- common/epoll/thread-dispatcher.hpp | 2 + common/ipc/client.cpp | 7 +- common/ipc/internals/processor.hpp | 3 - common/ipc/service.cpp | 15 ++- tests/unit_tests/dbus/ut-connection.cpp | 5 - tests/unit_tests/epoll/ut-event-poll.cpp | 162 ++++++++++++++++++++++++------- tests/unit_tests/utils/ut-glib-loop.cpp | 21 ++-- 10 files changed, 192 insertions(+), 79 deletions(-) diff --git a/common/epoll/event-poll.cpp b/common/epoll/event-poll.cpp index 9eb9fa0..dfb0385 100644 --- a/common/epoll/event-poll.cpp +++ b/common/epoll/event-poll.cpp @@ -79,14 +79,22 @@ void EventPoll::addFD(const int fd, const Events events, Callback&& callback) LOGT("Callback added for fd: " << fd); } +void EventPoll::modifyFD(const int fd, const Events events) +{ + // No need to lock and check mCallbacks map + if (!modifyFDInternal(fd, events)) { + throw UtilsException("Could not modify fd"); + } +} + void EventPoll::removeFD(const int fd) { std::lock_guard lock(mMutex); auto iter = mCallbacks.find(fd); if (iter == mCallbacks.end()) { - LOGW("Failed to remove nonexistent fd: " << fd); - throw UtilsException("FD does not exist"); + LOGT("Callback not found, probably already removed fd: " << fd); + return; } mCallbacks.erase(iter); removeFDInternal(fd); @@ -94,6 +102,7 @@ void EventPoll::removeFD(const int fd) } bool EventPoll::dispatchIteration(const int timeoutMs) + { for (;;) { epoll_event event; @@ -120,19 +129,16 @@ bool EventPoll::dispatchIteration(const int timeoutMs) std::shared_ptr callback(iter->second); try { LOGT("Dispatch fd: " << event.data.fd << ", events: " << eventsToString(event.events)); - return (*callback)(event.data.fd, event.events); + (*callback)(event.data.fd, event.events); + return true; } catch (std::exception& e) { LOGE("Got unexpected exception: " << e.what()); assert(0 && "Callback should not throw any exceptions"); + return true; } } } -void EventPoll::dispatchLoop() -{ - while (dispatchIteration(-1)) {} -} - bool EventPoll::addFDInternal(const int fd, const Events events) { epoll_event event; @@ -147,6 +153,20 @@ bool EventPoll::addFDInternal(const int fd, const Events events) return true; } +bool EventPoll::modifyFDInternal(const int fd, const Events events) +{ + epoll_event event; + memset(&event, 0, sizeof(event)); + event.events = events; + event.data.fd = fd; + + if (epoll_ctl(mPollFD, EPOLL_CTL_MOD, fd, &event) == -1) { + LOGE("Failed to modify fd in poll: " << getSystemErrorMessage()); + return false; + } + return true; +} + void EventPoll::removeFDInternal(const int fd) { if (epoll_ctl(mPollFD, EPOLL_CTL_DEL, fd, NULL) == -1) { diff --git a/common/epoll/event-poll.hpp b/common/epoll/event-poll.hpp index 2d37aaa..67614ab 100644 --- a/common/epoll/event-poll.hpp +++ b/common/epoll/event-poll.hpp @@ -37,7 +37,7 @@ namespace epoll { class EventPoll { public: - typedef std::function Callback; + typedef std::function Callback; EventPoll(); ~EventPoll(); @@ -45,10 +45,16 @@ public: int getPollFD() const; void addFD(const int fd, const Events events, Callback&& callback); + void modifyFD(const int fd, const Events events); void removeFD(const int fd); + /** + * Dispatch at most one signalled FD + * @param timeoutMs how long should wait in case of no pending events + * (0 - return immediately, -1 - wait forever) + * @return false on timeout + */ bool dispatchIteration(const int timeoutMs); - void dispatchLoop(); private: typedef std::recursive_mutex Mutex; @@ -58,6 +64,7 @@ private: std::unordered_map> mCallbacks; bool addFDInternal(const int fd, const Events events); + bool modifyFDInternal(const int fd, const Events events); void removeFDInternal(const int fd); }; diff --git a/common/epoll/thread-dispatcher.cpp b/common/epoll/thread-dispatcher.cpp index a82cad8..d286c19 100644 --- a/common/epoll/thread-dispatcher.cpp +++ b/common/epoll/thread-dispatcher.cpp @@ -29,15 +29,18 @@ namespace vasum { namespace epoll { ThreadDispatcher::ThreadDispatcher() + : mStopped(false) { - auto controlCallback = [this](int, Events) -> bool { + auto controlCallback = [this](int, Events) { mStopEvent.receive(); - return false; // break the loop + mStopped.store(true, std::memory_order_release); }; mPoll.addFD(mStopEvent.getFD(), EPOLLIN, std::move(controlCallback)); mThread = std::thread([this] { - mPoll.dispatchLoop(); + while (!mStopped.load(std::memory_order_acquire)) { + mPoll.dispatchIteration(-1); + } }); } diff --git a/common/epoll/thread-dispatcher.hpp b/common/epoll/thread-dispatcher.hpp index 7d0f30d..5c6c145 100644 --- a/common/epoll/thread-dispatcher.hpp +++ b/common/epoll/thread-dispatcher.hpp @@ -29,6 +29,7 @@ #include "utils/eventfd.hpp" #include +#include namespace vasum { namespace epoll { @@ -45,6 +46,7 @@ public: private: EventPoll mPoll; utils::EventFD mStopEvent; + std::atomic_bool mStopped; std::thread mThread; }; diff --git a/common/ipc/client.cpp b/common/ipc/client.cpp index abecb71..75a62ad 100644 --- a/common/ipc/client.cpp +++ b/common/ipc/client.cpp @@ -58,9 +58,8 @@ void Client::start() } LOGS("Client start"); // Initialize the connection with the server - auto handleEvent = [&](int, epoll::Events) -> bool { + auto handleEvent = [&](int, epoll::Events) { mProcessor.handleEvent(); - return true; }; mEventPoll.addFD(mProcessor.getEventFD(), EPOLLIN, handleEvent); mProcessor.start(); @@ -98,6 +97,7 @@ void Client::handle(const FileDescriptor fd, const epoll::Events pollEvents) if (pollEvents & EPOLLIN) { mProcessor.handleInput(fd); + return; // because handleInput will handle RDHUP } if ((pollEvents & EPOLLHUP) || (pollEvents & EPOLLRDHUP)) { @@ -109,9 +109,8 @@ void Client::setNewPeerCallback(const PeerCallback& newPeerCallback) { LOGS("Client setNewPeerCallback"); auto callback = [newPeerCallback, this](PeerID peerID, FileDescriptor fd) { - auto handleFd = [&](FileDescriptor fd, epoll::Events events) -> bool { + auto handleFd = [&](FileDescriptor fd, epoll::Events events) { handle(fd, events); - return true; }; mEventPoll.addFD(fd, EPOLLIN | EPOLLHUP | EPOLLRDHUP, handleFd); if (newPeerCallback) { diff --git a/common/ipc/internals/processor.hpp b/common/ipc/internals/processor.hpp index 6e0ae81..dec16e8 100644 --- a/common/ipc/internals/processor.hpp +++ b/common/ipc/internals/processor.hpp @@ -80,11 +80,8 @@ const unsigned int DEFAULT_MAX_NUMBER_OF_PEERS = 500; * - new way to generate UIDs * - callbacks for serialization/parsing * - store Sockets in a vector, maybe SocketStore? -* - poll loop outside. * - waiting till the EventQueue is empty before leaving stop() * - no new events added after stop() called -* - when using IPCGSource: addFD and removeFD can be called from addPeer removePeer callbacks, but -* there is no mechanism to ensure the IPCSource exists.. therefore SIGSEGV :) * */ class Processor { diff --git a/common/ipc/service.cpp b/common/ipc/service.cpp index c436726..849ce3c 100644 --- a/common/ipc/service.cpp +++ b/common/ipc/service.cpp @@ -63,17 +63,15 @@ void Service::start() return; } LOGS("Service start"); - auto handleConnection = [&](int, epoll::Events) -> bool { + auto handleConnection = [&](int, epoll::Events) { mAcceptor.handleConnection(); - return true; }; - auto handleProcessorEvent = [&](int, epoll::Events) -> bool { + auto handleProcessorEvent = [&](int, epoll::Events) { mProcessor.handleEvent(); - return true; }; - mEventPoll.addFD(mAcceptor.getConnectionFD(), EPOLLIN, handleConnection); mEventPoll.addFD(mProcessor.getEventFD(), EPOLLIN, handleProcessorEvent); mProcessor.start(); + mEventPoll.addFD(mAcceptor.getConnectionFD(), EPOLLIN, handleConnection); } bool Service::isStarted() @@ -87,9 +85,8 @@ void Service::stop() return; } LOGS("Service stop"); - mProcessor.stop(); - mEventPoll.removeFD(mAcceptor.getConnectionFD()); + mProcessor.stop(); mEventPoll.removeFD(mProcessor.getEventFD()); } @@ -105,6 +102,7 @@ void Service::handle(const FileDescriptor fd, const epoll::Events pollEvents) if (pollEvents & EPOLLIN) { mProcessor.handleInput(fd); + return; // because handleInput will handle RDHUP } if ((pollEvents & EPOLLHUP) || (pollEvents & EPOLLRDHUP)) { @@ -116,9 +114,8 @@ void Service::setNewPeerCallback(const PeerCallback& newPeerCallback) { LOGS("Service setNewPeerCallback"); auto callback = [newPeerCallback, this](PeerID peerID, FileDescriptor fd) { - auto handleFd = [&](FileDescriptor fd, epoll::Events events) -> bool { + auto handleFd = [&](FileDescriptor fd, epoll::Events events) { handle(fd, events); - return true; }; mEventPoll.addFD(fd, EPOLLIN | EPOLLHUP | EPOLLRDHUP, handleFd); if (newPeerCallback) { diff --git a/tests/unit_tests/dbus/ut-connection.cpp b/tests/unit_tests/dbus/ut-connection.cpp index 4948cd7..e52778e 100644 --- a/tests/unit_tests/dbus/ut-connection.cpp +++ b/tests/unit_tests/dbus/ut-connection.cpp @@ -96,11 +96,6 @@ std::string getInterfaceFromIntrospectionXML(const std::string& xml, const std:: } // namespace -BOOST_AUTO_TEST_CASE(GlibLoopTest) -{ - ScopedGlibLoop loop; -} - BOOST_AUTO_TEST_CASE(DbusDaemonTest) { ScopedDbusDaemon daemon; diff --git a/tests/unit_tests/epoll/ut-event-poll.cpp b/tests/unit_tests/epoll/ut-event-poll.cpp index 00cb385..3a26b5e 100644 --- a/tests/unit_tests/epoll/ut-event-poll.cpp +++ b/tests/unit_tests/epoll/ut-event-poll.cpp @@ -29,11 +29,12 @@ #include "epoll/event-poll.hpp" #include "logger/logger.hpp" #include "ipc/internals/socket.hpp" -#include "utils/latch.hpp" +#include "utils/value-latch.hpp" #include "utils/glib-loop.hpp" #include "epoll/glib-dispatcher.hpp" #include "epoll/thread-dispatcher.hpp" +using namespace vasum; using namespace vasum::utils; using namespace vasum::epoll; using namespace vasum::ipc; @@ -66,62 +67,152 @@ BOOST_AUTO_TEST_CASE(GlibPoll) void doSocketTest(EventPoll& poll) { - const std::string PATH = "/tmp/ut-poll.sock"; - const std::string MESSAGE = "This is a test message"; - - Latch goodMessage; - Latch remoteClosed; - - Socket listen = Socket::createSocket(PATH); - std::shared_ptr server; + using namespace std::placeholders; - auto serverCallback = [&](int, Events events) -> bool { + //TODO don't use ipc socket + const std::string PATH = "/tmp/ut-poll.sock"; + const size_t REQUEST_LEN = 5; + const std::string REQUEST_GOOD = "GET 1"; + const std::string REQUEST_BAD = "GET 7"; + const std::string RESPONSE = "This is a response message"; + + // Scenario 1: + // client connects to server listening socket + // client ---good-request---> server + // server ---response---> client + // client disconnects + // + // Scenario 2: + // client connects to server listening socket + // client ---bad-request----> server + // server disconnects + + // { server setup + + auto serverCallback = [&](int /*fd*/, + Events events, + std::shared_ptr socket, + CallbackGuard::Tracker) { LOGD("Server events: " << eventsToString(events)); + if (events & EPOLLIN) { + std::string request(REQUEST_LEN, 'x'); + socket->read(&request.front(), request.size()); + if (request == REQUEST_GOOD) { + poll.modifyFD(socket->getFD(), EPOLLRDHUP | EPOLLOUT); + } else { + // disconnect (socket is kept in callback) + poll.removeFD(socket->getFD()); + } + } + if (events & EPOLLOUT) { - server->write(MESSAGE.data(), MESSAGE.size()); - poll.removeFD(server->getFD()); - server.reset(); + socket->write(RESPONSE.data(), RESPONSE.size()); + poll.modifyFD(socket->getFD(), EPOLLRDHUP); + } + + if (events & EPOLLRDHUP) { + // client has disconnected + poll.removeFD(socket->getFD()); } - return true; }; - auto listenCallback = [&](int, Events events) -> bool { + Socket listenSocket = Socket::createSocket(PATH); + CallbackGuard serverSocketsGuard; + + auto listenCallback = [&](int /*fd*/, Events events) { LOGD("Listen events: " << eventsToString(events)); if (events & EPOLLIN) { - server = listen.accept(); - poll.addFD(server->getFD(), EPOLLHUP | EPOLLRDHUP | EPOLLOUT, serverCallback); + // accept new server connection + std::shared_ptr socket = listenSocket.accept(); + poll.addFD(socket->getFD(), + EPOLLRDHUP | EPOLLIN, + std::bind(serverCallback, _1, _2, socket, serverSocketsGuard.spawn())); } - return true; }; - poll.addFD(listen.getFD(), EPOLLIN, listenCallback); + poll.addFD(listenSocket.getFD(), EPOLLIN, listenCallback); + + // } server setup - Socket client = Socket::connectSocket(PATH); + // { client setup - auto clientCallback = [&](int, Events events) -> bool { + auto clientCallback = [&](int /*fd*/, + Events events, + Socket& socket, + const std::string& request, + ValueLatch& response) { LOGD("Client events: " << eventsToString(events)); + if (events & EPOLLOUT) { + socket.write(request.data(), request.size()); + poll.modifyFD(socket.getFD(), EPOLLRDHUP | EPOLLIN); + } + if (events & EPOLLIN) { - std::string ret(MESSAGE.size(), 'x'); - client.read(&ret.front(), ret.size()); - if (ret == MESSAGE) { - goodMessage.set(); + try { + std::string msg(RESPONSE.size(), 'x'); + socket.read(&msg.front(), msg.size()); + response.set(msg); + } catch (UtilsException&) { + response.set(std::string()); } + poll.modifyFD(socket.getFD(), EPOLLRDHUP); } + if (events & EPOLLRDHUP) { - poll.removeFD(client.getFD()); - remoteClosed.set(); + LOGD("Server has disconnected"); + poll.removeFD(socket.getFD()); //prevent active loop } - return true; }; - poll.addFD(client.getFD(), EPOLLHUP | EPOLLRDHUP | EPOLLIN, clientCallback); - - BOOST_CHECK(goodMessage.wait(TIMEOUT)); - BOOST_CHECK(remoteClosed.wait(TIMEOUT)); - - poll.removeFD(listen.getFD()); + // } client setup + + // Scenario 1 + LOGD("Scerario 1"); + { + Socket client = Socket::connectSocket(PATH); + ValueLatch response; + + poll.addFD(client.getFD(), + EPOLLRDHUP | EPOLLOUT, + std::bind(clientCallback, + _1, + _2, + std::ref(client), + REQUEST_GOOD, + std::ref(response))); + + BOOST_CHECK(response.get(TIMEOUT) == RESPONSE); + + poll.removeFD(client.getFD()); + } + + // Scenario 2 + LOGD("Scerario 2"); + { + Socket client = Socket::connectSocket(PATH); + ValueLatch response; + + poll.addFD(client.getFD(), + EPOLLRDHUP | EPOLLOUT, + std::bind(clientCallback, + _1, + _2, + std::ref(client), + REQUEST_BAD, + std::ref(response))); + + BOOST_CHECK(response.get(TIMEOUT) == std::string()); + + poll.removeFD(client.getFD()); + } + LOGD("Done"); + + poll.removeFD(listenSocket.getFD()); + + // wait for all server sockets (ensure all EPOLLRDHUP are processed) + BOOST_REQUIRE(serverSocketsGuard.waitForTrackers(TIMEOUT)); } BOOST_AUTO_TEST_CASE(ThreadedPollSocket) @@ -146,9 +237,8 @@ BOOST_AUTO_TEST_CASE(PollStacking) EventPoll innerPoll; - auto dispatchInner = [&](int, Events) -> bool { + auto dispatchInner = [&](int, Events) { innerPoll.dispatchIteration(0); - return true; }; dispatcher.getPoll().addFD(innerPoll.getPollFD(), EPOLLIN, dispatchInner); doSocketTest(innerPoll); diff --git a/tests/unit_tests/utils/ut-glib-loop.cpp b/tests/unit_tests/utils/ut-glib-loop.cpp index 30d5342..7c5e318 100644 --- a/tests/unit_tests/utils/ut-glib-loop.cpp +++ b/tests/unit_tests/utils/ut-glib-loop.cpp @@ -26,12 +26,11 @@ #include "config.hpp" #include "ut.hpp" -#include "utils/latch.hpp" #include "utils/glib-loop.hpp" #include -BOOST_AUTO_TEST_SUITE(UtilsGlibLoopSuite) +BOOST_AUTO_TEST_SUITE(GlibLoopSuite) using namespace vasum; using namespace vasum::utils; @@ -39,22 +38,25 @@ using namespace vasum::utils; namespace { -const unsigned int TIMER_INTERVAL_MS = 10; -const unsigned int TIMER_NUMBER = 5; +const unsigned int TIMER_INTERVAL_MS = 100; +const unsigned int TIMER_NUMBER = 4; const unsigned int TIMER_WAIT_FOR = 2 * TIMER_NUMBER * TIMER_INTERVAL_MS; } // namespace +BOOST_AUTO_TEST_CASE(GlibLoopTest) +{ + ScopedGlibLoop loop; +} + BOOST_AUTO_TEST_CASE(GlibTimerEventTest) { ScopedGlibLoop loop; - Latch latch; std::atomic_uint counter(0); CallbackGuard guard; - Glib::OnTimerEventCallback callback = [&]()->bool { - latch.set(); + auto callback = [&]()-> bool { if (++counter >= TIMER_NUMBER) { return false; } @@ -63,8 +65,9 @@ BOOST_AUTO_TEST_CASE(GlibTimerEventTest) Glib::addTimerEvent(TIMER_INTERVAL_MS, callback, guard); - BOOST_REQUIRE(latch.waitForN(TIMER_NUMBER, TIMER_WAIT_FOR)); - BOOST_REQUIRE(latch.wait(TIMER_WAIT_FOR) == false); + BOOST_CHECK(counter < TIMER_NUMBER); + BOOST_CHECK(guard.waitForTrackers(TIMER_WAIT_FOR)); + BOOST_CHECK_EQUAL(counter, TIMER_NUMBER); } BOOST_AUTO_TEST_SUITE_END() -- 2.7.4 From 29bcde2e47e0560b4c2e4b7976f2c9853cfd6e58 Mon Sep 17 00:00:00 2001 From: Mateusz Malicki Date: Thu, 5 Mar 2015 17:04:04 +0100 Subject: [PATCH 11/16] Get/set ipv4/ipv6 address, up/down interface [Feature] Possibility to get/set ipv4/ipv6 address, up/down interface [Cause] N/A [Solution] Implemented: vsm_netdev_get_ipv4_addr, vsm_netdev_get_ipv6_addr, vsm_netdev_set_ipv4_addr, vsm_netdev_set_ipv6_addr, vsm_netdev_up, vsm_netdev_down, vsm_lookup_netdev_by_name [Verification] Build, install 1) run test 2) set interfaces attributes (up, down) through cli and check it "lxc-attach -n zoneId --lxcpath=/tmp/ut-zones -- ip addr" Change-Id: I42ffa7e4c8f8cf2e22171d95b62884a2317d1107 --- cli/command-line-interface.cpp | 35 +++++ cli/command-line-interface.hpp | 7 + cli/main.cpp | 9 ++ client/vasum-client-impl.cpp | 158 +++++++++++++++------- client/vasum-client-impl.hpp | 6 + client/vasum-client.h | 6 +- server/netdev.cpp | 256 +++++++++++++++++++++++++++++++++++- server/netdev.hpp | 6 + server/zone-admin.cpp | 8 +- server/zone-admin.hpp | 4 +- tests/unit_tests/server/ut-zone.cpp | 146 +++++++++++++++++++- 11 files changed, 582 insertions(+), 59 deletions(-) diff --git a/cli/command-line-interface.cpp b/cli/command-line-interface.cpp index 100aaa1..2ae3778 100644 --- a/cli/command-line-interface.cpp +++ b/cli/command-line-interface.cpp @@ -128,6 +128,23 @@ ostream& operator<<(ostream& out, const VsmZone& zone) return out; } +ostream& operator<<(ostream& out, const VsmNetdevType& netdevType) +{ + switch (netdevType) { + case VSMNETDEV_VETH: out << "VETH"; break; + case VSMNETDEV_PHYS: out << "PHYS"; break; + case VSMNETDEV_MACVLAN: out << "MACVLAN"; break; + } + return out; +} + +ostream& operator<<(ostream& out, const VsmNetdev& netdev) +{ + out << "Name: " << netdev->name + << "\nType: " << netdev->type; + return out; +} + typedef vector> Table; ostream& operator<<(ostream& out, const Table& table) @@ -397,6 +414,24 @@ void create_netdev_phys(int pos, int argc, const char** argv) argv[pos + 2])); } +void lookup_netdev_by_name(int pos, int argc, const char** argv) +{ + using namespace std::placeholders; + + if (argc <= pos + 2) { + throw runtime_error("Not enough parameters"); + } + VsmNetdev vsmNetdev = NULL; + one_shot(bind(vsm_lookup_netdev_by_name, + _1, + argv[pos + 1], + argv[pos + 2], + &vsmNetdev)); + cout << vsmNetdev << endl; + vsm_netdev_free(vsmNetdev); + +} + void destroy_netdev(int pos, int argc, const char** argv) { using namespace std::placeholders; diff --git a/cli/command-line-interface.hpp b/cli/command-line-interface.hpp index 006396c..6e27c74 100644 --- a/cli/command-line-interface.hpp +++ b/cli/command-line-interface.hpp @@ -209,6 +209,13 @@ void create_netdev_macvlan(int pos, int argc, const char** argv); void create_netdev_phys(int pos, int argc, const char** argv); /** + * Parses command line arguments and call vsm_lookup_netdev_by_name + * + * @see vsm_lookup_netdev_by_name + */ +void lookup_netdev_by_name(int pos, int argc, const char** argv); + +/** * Parses command line arguments and call vsm_destroy_netdev * * @see vsm_destroy_netdev diff --git a/cli/main.cpp b/cli/main.cpp index c915415..2431313 100644 --- a/cli/main.cpp +++ b/cli/main.cpp @@ -173,6 +173,15 @@ std::map commands = { } }, { + "lookup_netdev_by_name", { + lookup_netdev_by_name, + "lookup_netdev_by_name zone_id devId", + "Get netdev flags", + {{"zone_id", "id zone name"}, + {"devId", "network device id"}} + } + }, + { "destroy_netdev", { destroy_netdev, "destroy_netdev zone_id devId", diff --git a/client/vasum-client-impl.cpp b/client/vasum-client-impl.cpp index fb1b2ec..1de4de0 100644 --- a/client/vasum-client-impl.cpp +++ b/client/vasum-client-impl.cpp @@ -40,6 +40,10 @@ #include #include #include +#include + +#include +#include using namespace std; using namespace dbus; @@ -202,7 +206,6 @@ GVariant* createTupleArray(const vector>& dict) return g_variant_builder_end(&builder); } - VsmStatus toStatus(const exception& ex) { if (typeid(DbusCustomException) == typeid(ex)) { @@ -232,6 +235,29 @@ bool readFirstLineOfFile(const string& path, string& ret) } //namespace +VsmStatus Client::getNetdevAttrs(const string& zone, + const string& netdev, + NetdevAttrs& attrs) noexcept +{ + GVariant* out = NULL; + GVariant* args_in = g_variant_new("(ss)", zone.c_str(), netdev.c_str()); + VsmStatus ret = callMethod(HOST_INTERFACE, + api::host::METHOD_GET_NETDEV_ATTRS, + args_in, + "(a(ss))", + &out); + if (ret != VSMCLIENT_SUCCESS) { + return ret; + } + GVariant* unpacked; + g_variant_get(out, "(*)", &unpacked); + attrs = toDict(unpacked); + g_variant_unref(unpacked); + g_variant_unref(out); + mStatus = Status(); + return vsm_get_status(); +} + VsmStatus Client::vsm_start_glib_loop() noexcept { try { @@ -608,36 +634,37 @@ VsmStatus Client::vsm_netdev_get_ipv4_addr(const char* zone, const char* netdevId, struct in_addr* addr) noexcept { + using namespace boost::algorithm; + assert(zone); assert(netdevId); assert(addr); - GVariant* out = NULL; - GVariant* args_in = g_variant_new("(ss)", zone, netdevId); - VsmStatus ret = callMethod(HOST_INTERFACE, - api::host::METHOD_GET_NETDEV_ATTRS, - args_in, - "(a(ss))", - &out); + NetdevAttrs attrs; + VsmStatus ret = getNetdevAttrs(zone, netdevId, attrs); if (ret != VSMCLIENT_SUCCESS) { return ret; } - GVariant* unpacked; - g_variant_get(out, "(*)", &unpacked); - vector> attrs = toDict(unpacked); - g_variant_unref(unpacked); - g_variant_unref(out); auto it = find_if(attrs.begin(), attrs.end(), [](const tuple& entry) { return get<0>(entry) == "ipv4"; }); if (it != attrs.end()) { - if (inet_pton(AF_INET, get<1>(*it).c_str(), addr) != 1) { - mStatus = Status(VSMCLIENT_CUSTOM_ERROR, "Invalid response data"); - return vsm_get_status(); - } - mStatus = Status(); - return vsm_get_status(); + vector addrAttrs; + for(auto addrAttr : split(addrAttrs, get<1>(*it), is_any_of(","))) { + size_t pos = addrAttr.find(":"); + if (addrAttr.substr(0, pos) == "ip") { + if (pos != string::npos && pos < addrAttr.length() && + inet_pton(AF_INET, addrAttr.substr(pos + 1).c_str(), addr) == 1) { + //XXX: return only one address + mStatus = Status(); + return vsm_get_status(); + } else { + mStatus = Status(VSMCLIENT_CUSTOM_ERROR, "Invalid response data"); + return vsm_get_status(); + } + } + } } mStatus = Status(VSMCLIENT_CUSTOM_ERROR, "Address not found"); return vsm_get_status(); @@ -647,37 +674,37 @@ VsmStatus Client::vsm_netdev_get_ipv6_addr(const char* zone, const char* netdevId, struct in6_addr* addr) noexcept { + using namespace boost::algorithm; + assert(zone); assert(netdevId); assert(addr); - GVariant* out = NULL; - GVariant* args_in = g_variant_new("(ss)", zone, netdevId); - VsmStatus ret = callMethod(HOST_INTERFACE, - api::host::METHOD_GET_NETDEV_ATTRS, - args_in, - "(a(ss))", - &out); + NetdevAttrs attrs; + VsmStatus ret = getNetdevAttrs(zone, netdevId, attrs); if (ret != VSMCLIENT_SUCCESS) { return ret; } - GVariant* unpacked; - g_variant_get(out, "(*)", &unpacked); - vector> attrs = toDict(unpacked); - g_variant_unref(unpacked); - g_variant_unref(out); - //XXX: return only one address auto it = find_if(attrs.begin(), attrs.end(), [](const tuple& entry) { return get<0>(entry) == "ipv6"; }); if (it != attrs.end()) { - if (inet_pton(AF_INET6, get<1>(*it).c_str(), addr) != 1) { - mStatus = Status(VSMCLIENT_CUSTOM_ERROR, "Invalid response data"); - return vsm_get_status(); - } - mStatus = Status(); - return vsm_get_status(); + vector addrAttrs; + for(auto addrAttr : split(addrAttrs, get<1>(*it), is_any_of(","))) { + size_t pos = addrAttr.find(":"); + if (addrAttr.substr(0, pos) == "ip") { + if (pos != string::npos && pos < addrAttr.length() && + inet_pton(AF_INET6, addrAttr.substr(pos + 1).c_str(), addr) == 1) { + //XXX: return only one address + mStatus = Status(); + return vsm_get_status(); + } else { + mStatus = Status(VSMCLIENT_CUSTOM_ERROR, "Invalid response data"); + return vsm_get_status(); + } + } + } } mStatus = Status(VSMCLIENT_CUSTOM_ERROR, "Address not found"); return vsm_get_status(); @@ -689,8 +716,9 @@ VsmStatus Client::vsm_netdev_set_ipv4_addr(const char* zone, int mask) noexcept { try { - GVariant* dict = createTupleArray({make_tuple("ipv4", toString(addr)), - make_tuple("mask", to_string(mask))}); + GVariant* dict = createTupleArray({make_tuple("ipv4", + "ip:" + toString(addr) + "," + "prefixlen:" + to_string(mask))}); GVariant* args_in = g_variant_new("(ss@a(ss))", zone, netdevId, dict); return callMethod(HOST_INTERFACE, api::host::METHOD_SET_NETDEV_ATTRS, args_in); } catch (exception& ex) { @@ -705,8 +733,9 @@ VsmStatus Client::vsm_netdev_set_ipv6_addr(const char* zone, int mask) noexcept { try { - GVariant* dict = createTupleArray({make_tuple("ipv6", toString(addr)), - make_tuple("mask", to_string(mask))}); + GVariant* dict = createTupleArray({make_tuple("ipv6", + "ip:" + toString(addr) + "," + "prefixlen:" + to_string(mask))}); GVariant* args_in = g_variant_new("(ss@a(ss))", zone, netdevId, dict); return callMethod(HOST_INTERFACE, api::host::METHOD_SET_NETDEV_ATTRS, args_in); } catch (exception& ex) { @@ -718,7 +747,8 @@ VsmStatus Client::vsm_netdev_set_ipv6_addr(const char* zone, VsmStatus Client::vsm_netdev_up(const char* zone, const char* netdevId) noexcept { try { - GVariant* dict = createTupleArray({make_tuple("up", "true")}); + GVariant* dict = createTupleArray({make_tuple("flags", to_string(IFF_UP)), + make_tuple("change", to_string(IFF_UP))}); GVariant* args_in = g_variant_new("(ss@a(ss))", zone, netdevId, dict); return callMethod(HOST_INTERFACE, api::host::METHOD_SET_NETDEV_ATTRS, args_in); } catch (exception& ex) { @@ -730,7 +760,8 @@ VsmStatus Client::vsm_netdev_up(const char* zone, const char* netdevId) noexcept VsmStatus Client::vsm_netdev_down(const char* zone, const char* netdevId) noexcept { try { - GVariant* dict = createTupleArray({make_tuple("up", "false")}); + GVariant* dict = createTupleArray({make_tuple("flags", to_string(~IFF_UP)), + make_tuple("change", to_string(IFF_UP))}); GVariant* args_in = g_variant_new("(ss@a(ss))", zone, netdevId, dict); return callMethod(HOST_INTERFACE, api::host::METHOD_SET_NETDEV_ATTRS, args_in); } catch (exception& ex) { @@ -762,9 +793,44 @@ VsmStatus Client::vsm_create_netdev_phys(const char* zone, const char* devId) no return callMethod(HOST_INTERFACE, api::host::METHOD_CREATE_NETDEV_PHYS, args_in); } -VsmStatus Client::vsm_lookup_netdev_by_name(const char*, const char*, VsmNetdev*) noexcept +VsmStatus Client::vsm_lookup_netdev_by_name(const char* zone, + const char* netdevId, + VsmNetdev* netdev) noexcept { - mStatus = Status(VSMCLIENT_OTHER_ERROR, "Not implemented"); + using namespace boost::algorithm; + + assert(zone); + assert(netdevId); + assert(netdev); + + NetdevAttrs attrs; + VsmStatus ret = getNetdevAttrs(zone, netdevId, attrs); + if (ret != VSMCLIENT_SUCCESS) { + return ret; + } + + auto it = find_if(attrs.begin(), attrs.end(), [](const tuple& entry) { + return get<0>(entry) == "type"; + }); + + VsmNetdevType type; + if (it == attrs.end()) { + mStatus = Status(VSMCLIENT_OTHER_ERROR, "Can't fetch netdev type"); + return vsm_get_status(); + } + + switch (stoi(get<1>(*it))) { + case 1<<0 /*IFF_802_1Q_VLAN*/: type = VSMNETDEV_VETH; break; + case 1<<21 /*IFF_MACVLAN*/: type = VSMNETDEV_MACVLAN; break; + default: + mStatus = Status(VSMCLIENT_CUSTOM_ERROR, "Unknown netdev type: " + get<1>(*it)); + return vsm_get_status(); + } + + *netdev = reinterpret_cast(malloc(sizeof(**netdev))); + (*netdev)->name = strdup(zone); + (*netdev)->type = type; + mStatus = Status(); return vsm_get_status(); } diff --git a/client/vasum-client-impl.hpp b/client/vasum-client-impl.hpp index 9399839..1493a00 100644 --- a/client/vasum-client-impl.hpp +++ b/client/vasum-client-impl.hpp @@ -29,6 +29,8 @@ #include "vasum-client.h" #include #include +#include +#include #include /** @@ -53,6 +55,7 @@ struct DbusInterfaceInfo { */ class Client { private: + typedef std::vector> NetdevAttrs; typedef std::function SignalCallback; struct Status { Status(); @@ -74,6 +77,9 @@ private: SignalCallback signalCallback, VsmSubscriptionId* subscriptionId); VsmStatus signalUnsubscribe(VsmSubscriptionId id); + VsmStatus getNetdevAttrs(const std::string& zone, + const std::string& netdev, + NetdevAttrs& attrs) noexcept; public: Client() noexcept; diff --git a/client/vasum-client.h b/client/vasum-client.h index 0bd40ad..18af990 100644 --- a/client/vasum-client.h +++ b/client/vasum-client.h @@ -160,9 +160,9 @@ typedef VsmZoneStructure* VsmZone; * Netowrk device type */ typedef enum { - VETH, - PHYS, - MACVLAN + VSMNETDEV_VETH, + VSMNETDEV_PHYS, + VSMNETDEV_MACVLAN } VsmNetdevType; /** diff --git a/server/netdev.cpp b/server/netdev.cpp index e17ecda..da58641 100644 --- a/server/netdev.cpp +++ b/server/netdev.cpp @@ -36,17 +36,22 @@ #include #include #include +#include +#include + +#include +#include #include #include #include +#include #include #include #include #include #include #include -#include #include //IFLA_BRIDGE_FLAGS and BRIDGE_FLAGS_MASTER @@ -99,6 +104,22 @@ uint32_t getInterfaceIndex(const string& name) { return index; } +uint32_t getInterfaceIndex(const string& name, pid_t nsPid) { + NetlinkMessage nlm(RTM_GETLINK, NLM_F_REQUEST | NLM_F_ACK); + ifinfomsg infoPeer = utils::make_clean(); + infoPeer.ifi_family = AF_UNSPEC; + infoPeer.ifi_change = 0xFFFFFFFF; + nlm.put(infoPeer) + .put(IFLA_IFNAME, name); + NetlinkResponse response = send(nlm, nsPid); + if (!response.hasMessage()) { + throw VasumException("Can't get interface index"); + } + + response.fetch(infoPeer); + return infoPeer.ifi_index; +} + void validateNetdevName(const string& name) { if (name.size() <= 1 || name.size() >= IFNAMSIZ) { @@ -209,6 +230,107 @@ void createMacvlan(const string& master, const string& slave, const macvlan_mode send(nlm); } +std::vector getIpAddresses(const pid_t nsPid, int family, uint32_t index) +{ + NetlinkMessage nlm(RTM_GETADDR, NLM_F_REQUEST | NLM_F_ACK | NLM_F_DUMP); + ifaddrmsg infoAddr = utils::make_clean(); + infoAddr.ifa_family = family; + nlm.put(infoAddr); + NetlinkResponse response = send(nlm, nsPid); + if (!response.hasMessage()) { + //There is no interfaces with addresses + return std::vector(); + } + + std::vector addresses; + while (response.hasMessage()) { + ifaddrmsg addrmsg; + response.fetch(addrmsg); + if (addrmsg.ifa_index == index) { + Attrs attrs; + attrs.push_back(make_tuple("prefixlen", std::to_string(addrmsg.ifa_prefixlen))); + attrs.push_back(make_tuple("flags", std::to_string(addrmsg.ifa_flags))); + attrs.push_back(make_tuple("scope", std::to_string(addrmsg.ifa_scope))); + attrs.push_back(make_tuple("family", std::to_string(addrmsg.ifa_family))); + while (response.hasAttribute()) { + assert(INET6_ADDRSTRLEN >= INET_ADDRSTRLEN); + char buf[INET6_ADDRSTRLEN]; + in6_addr addr6; + in_addr addr4; + const void* addr = NULL; + int attrType = response.getAttributeType(); + switch (attrType) { + case IFA_ADDRESS: + if (family == AF_INET6) { + response.fetch(IFA_ADDRESS, addr6); + addr = &addr6; + } else { + assert(family == AF_INET); + response.fetch(IFA_ADDRESS, addr4); + addr = &addr4; + } + addr = inet_ntop(family, addr, buf, sizeof(buf)); + if (addr == NULL) { + LOGE("Can't convert ip address: " << getSystemErrorMessage()); + throw VasumException("Can't get ip address"); + } + attrs.push_back(make_tuple("ip", buf)); + break; + default: + response.skipAttribute(); + break; + } + } + addresses.push_back(std::move(attrs)); + } + response.fetchNextMessage(); + } + return addresses; +} + +void setIpAddresses(const pid_t nsPid, + const uint32_t index, + const Attrs& attrs, + int family) +{ + NetlinkMessage nlm(RTM_NEWADDR, NLM_F_CREATE | NLM_F_REQUEST | NLM_F_ACK); + ifaddrmsg infoAddr = utils::make_clean(); + infoAddr.ifa_family = family; + infoAddr.ifa_index = index; + for (const auto& attr : attrs) { + if (get<0>(attr) == "prefixlen") { + infoAddr.ifa_prefixlen = stoul(get<1>(attr)); + } + if (get<0>(attr) == "flags") { + infoAddr.ifa_flags = stoul(get<1>(attr)); + } + if (get<0>(attr) == "scope") { + infoAddr.ifa_scope = stoul(get<1>(attr)); + } + } + nlm.put(infoAddr); + for (const auto& attr : attrs) { + if (get<0>(attr) == "ip") { + if (family == AF_INET6) { + in6_addr addr6; + if (inet_pton(AF_INET6, get<1>(attr).c_str(), &addr6) != 1) { + throw VasumException("Can't set ipv4 address"); + }; + nlm.put(IFA_ADDRESS, addr6); + nlm.put(IFA_LOCAL, addr6); + } else { + assert(family == AF_INET); + in_addr addr4; + if (inet_pton(AF_INET, get<1>(attr).c_str(), &addr4) != 1) { + throw VasumException("Can't set ipv6 address"); + }; + nlm.put(IFA_LOCAL, addr4); + } + } + } + send(nlm, nsPid); +} + } // namespace void createVeth(const pid_t& nsPid, const string& nsDev, const string& hostDev) @@ -310,6 +432,138 @@ void createBridge(const string& netdev) send(nlm); } +Attrs getAttrs(const pid_t nsPid, const std::string& netdev) +{ + auto joinAddresses = [](const Attrs& attrs) -> std::string { + bool first = true; + stringstream ss; + for (const auto& attr : attrs) { + ss << (first ? "" : ",") << get<0>(attr) << ":" << get<1>(attr); + first = false; + } + return ss.str(); + }; + + LOGT("Getting network device informations: " << netdev); + validateNetdevName(netdev); + + NetlinkMessage nlm(RTM_GETLINK, NLM_F_REQUEST | NLM_F_ACK); + ifinfomsg infoPeer = utils::make_clean(); + infoPeer.ifi_family = AF_UNSPEC; + infoPeer.ifi_change = 0xFFFFFFFF; + nlm.put(infoPeer) + .put(IFLA_IFNAME, netdev); + NetlinkResponse response = send(nlm, nsPid); + if (!response.hasMessage()) { + throw VasumException("Can't get interface information"); + } + response.fetch(infoPeer); + + Attrs attrs; + while (response.hasAttribute()) { + uint32_t mtu, link; + int attrType = response.getAttributeType(); + switch (attrType) { + case IFLA_MTU: + response.fetch(IFLA_MTU, mtu); + attrs.push_back(make_tuple("mtu", std::to_string(mtu))); + break; + case IFLA_LINK: + response.fetch(IFLA_LINK, link); + attrs.push_back(make_tuple("link", std::to_string(link))); + break; + default: + response.skipAttribute(); + break; + } + } + attrs.push_back(make_tuple("flags", std::to_string(infoPeer.ifi_flags))); + attrs.push_back(make_tuple("type", std::to_string(infoPeer.ifi_type))); + for (const auto& address : getIpAddresses(nsPid, AF_INET, infoPeer.ifi_index)) { + attrs.push_back(make_tuple("ipv4", joinAddresses(address))); + } + for (const auto& address : getIpAddresses(nsPid, AF_INET6, infoPeer.ifi_index)) { + attrs.push_back(make_tuple("ipv6", joinAddresses(address))); + } + + return attrs; +} + +void setAttrs(const pid_t nsPid, const std::string& netdev, const Attrs& attrs) +{ + const set supportedAttrs{"flags", "change", "type", "mtu", "link", "ipv4", "ipv6"}; + + LOGT("Setting network device informations: " << netdev); + validateNetdevName(netdev); + for (const auto& attr : attrs) { + if (supportedAttrs.find(get<0>(attr)) == supportedAttrs.end()) { + throw VasumException("Unsupported attribute: " + get<0>(attr)); + } + } + + NetlinkMessage nlm(RTM_NEWLINK, NLM_F_REQUEST | NLM_F_CREATE | NLM_F_ACK); + ifinfomsg infoPeer = utils::make_clean(); + infoPeer.ifi_family = AF_UNSPEC; + infoPeer.ifi_index = getInterfaceIndex(netdev, nsPid); + infoPeer.ifi_change = 0xFFFFFFFF; + for (const auto& attr : attrs) { + if (get<0>(attr) == "flags") { + infoPeer.ifi_flags = stoul(get<1>(attr)); + } + if (get<0>(attr) == "change") { + infoPeer.ifi_change = stoul(get<1>(attr)); + } + if (get<0>(attr) == "type") { + infoPeer.ifi_type = stoul(get<1>(attr)); + } + } + nlm.put(infoPeer); + for (const auto& attr : attrs) { + if (get<0>(attr) == "mtu") { + nlm.put(IFLA_MTU, stoul(get<1>(attr))); + } + if (get<0>(attr) == "link") { + nlm.put(IFLA_LINK, stoul(get<1>(attr))); + } + } + + NetlinkResponse response = send(nlm, nsPid); + if (!response.hasMessage()) { + throw VasumException("Can't set interface information"); + } + + //TODO: Multiple addresses should be set at once (add support NLM_F_MULTI to NetlinkMessage). + vector ipv4; + vector ipv6; + for (const auto& attr : attrs) { + if (get<0>(attr) == "ipv4") { + ipv4.push_back(get<1>(attr)); + } + if (get<0>(attr) == "ipv6") { + ipv6.push_back(get<1>(attr)); + } + } + + auto setIp = [nsPid](const vector& ips, uint32_t index, int family) -> void { + using namespace boost::algorithm; + for (const auto& ip : ips) { + Attrs attrs; + vector params; + for (const auto& addrAttr : split(params, ip, is_any_of(","))) { + size_t pos = addrAttr.find(":"); + if (pos == string::npos || pos == addrAttr.length()) { + LOGE("Wrong input data format: ill formed address attribute: " << addrAttr); + VasumException("Wrong input data format: ill formed address attribute"); + } + attrs.push_back(make_tuple(addrAttr.substr(0, pos), addrAttr.substr(pos + 1))); + } + setIpAddresses(nsPid, index, attrs, family); + } + }; + + setIp(ipv4, infoPeer.ifi_index, AF_INET); + setIp(ipv6, infoPeer.ifi_index, AF_INET6); +} } //namespace netdev } //namespace vasum diff --git a/server/netdev.hpp b/server/netdev.hpp index 0e9bfde..5e5821d 100644 --- a/server/netdev.hpp +++ b/server/netdev.hpp @@ -27,12 +27,15 @@ #include #include +#include #include #include namespace vasum { namespace netdev { +typedef std::vector> Attrs; + void createVeth(const pid_t& nsPid, const std::string& nsDev, const std::string& hostDev); void createMacvlan(const pid_t& nsPid, const std::string& nsDev, @@ -51,6 +54,9 @@ void destroyNetdev(const std::string& netdev, const pid_t pid = 0); */ void createBridge(const std::string& netdev); +Attrs getAttrs(const pid_t nsPid, const std::string& netdev); +void setAttrs(const pid_t nsPid, const std::string& netdev, const Attrs& attrs); + } //namespace netdev } //namespace vasum diff --git a/server/zone-admin.cpp b/server/zone-admin.cpp index 29577f8..b584279 100644 --- a/server/zone-admin.cpp +++ b/server/zone-admin.cpp @@ -307,14 +307,14 @@ void ZoneAdmin::destroyNetdev(const std::string& devId) netdev::destroyNetdev(devId, mZone.getInitPid()); } -void ZoneAdmin::setNetdevAttrs(const std::string& /* netdev */, const NetdevAttrs& /* attrs */) +void ZoneAdmin::setNetdevAttrs(const std::string& netdev, const NetdevAttrs& attrs) { - throw ZoneOperationException("Not implemented"); + netdev::setAttrs(mZone.getInitPid(), netdev, attrs); } -ZoneAdmin::NetdevAttrs ZoneAdmin::getNetdevAttrs(const std::string& /* netdev */) +ZoneAdmin::NetdevAttrs ZoneAdmin::getNetdevAttrs(const std::string& netdev) { - throw ZoneOperationException("Not implemented"); + return netdev::getAttrs(mZone.getInitPid(), netdev); } std::vector ZoneAdmin::getNetdevList() diff --git a/server/zone-admin.hpp b/server/zone-admin.hpp index c6d26f0..db2b0f2 100644 --- a/server/zone-admin.hpp +++ b/server/zone-admin.hpp @@ -28,7 +28,7 @@ #include "zone-config.hpp" #include "lxc/zone.hpp" - +#include "netdev.hpp" namespace vasum { @@ -41,7 +41,7 @@ enum class SchedulerLevel { class ZoneAdmin { public: - typedef std::vector> NetdevAttrs; + typedef netdev::Attrs NetdevAttrs; /** * ZoneAdmin constructor diff --git a/tests/unit_tests/server/ut-zone.cpp b/tests/unit_tests/server/ut-zone.cpp index 91d0540..234dabb 100644 --- a/tests/unit_tests/server/ut-zone.cpp +++ b/tests/unit_tests/server/ut-zone.cpp @@ -40,8 +40,10 @@ #include #include #include +#include #include #include +#include using namespace vasum; using namespace vasum::netdev; @@ -169,8 +171,6 @@ BOOST_AUTO_TEST_CASE(ListNetdevTest) NetdevList hostNetdevs = netdev::listNetdev(0); // Check if we get interfaces from zone net namespace BOOST_CHECK(hostNetdevs != netdevs); - - c->stop(false); } BOOST_AUTO_TEST_CASE(CreateNetdevVethTest) @@ -206,7 +206,147 @@ BOOST_AUTO_TEST_CASE(CreateNetdevMacvlanTest) c->createNetdevVeth(ZONE_NETDEV, BRIDGE_NAME); NetdevList netdevs = c->getNetdevList(); BOOST_CHECK(find(netdevs.begin(), netdevs.end(), ZONE_NETDEV) != netdevs.end()); - c->stop(false); +} + +BOOST_AUTO_TEST_CASE(GetNetdevAttrsTest) +{ + setupBridge(BRIDGE_NAME); + auto c = create(TEST_CONFIG_PATH); + c->start(); + ensureStarted(); + c->createNetdevVeth(ZONE_NETDEV, BRIDGE_NAME); + ZoneAdmin::NetdevAttrs attrs = c->getNetdevAttrs(ZONE_NETDEV); + bool gotMtu = false; + bool gotFlags = false; + bool gotType = false; + for (auto& attr : attrs) { + if (std::get<0>(attr) == "mtu") { + BOOST_CHECK(!gotMtu); + gotMtu = true; + } else if (std::get<0>(attr) == "flags") { + BOOST_CHECK(!gotFlags); + BOOST_CHECK(IFF_BROADCAST & stol(std::get<1>(attr))); + gotFlags = true; + } else if (std::get<0>(attr) == "type") { + BOOST_CHECK(!gotType); + BOOST_CHECK_EQUAL(1 /*IFF_802_1Q_VLAN */, stol(std::get<1>(attr))); + gotType = true; + } else { + BOOST_CHECK_MESSAGE(false, "Got unexpected option " + std::get<0>(attr)); + } + } + BOOST_CHECK(gotMtu); + BOOST_CHECK(gotFlags); + BOOST_CHECK(gotType); +} + +BOOST_AUTO_TEST_CASE(SetNetdevAttrsTest) +{ + setupBridge(BRIDGE_NAME); + auto c = create(TEST_CONFIG_PATH); + c->start(); + ensureStarted(); + c->createNetdevVeth(ZONE_NETDEV, BRIDGE_NAME); + ZoneAdmin::NetdevAttrs attrsIn; + attrsIn.push_back(std::make_tuple("mtu", "500")); + c->setNetdevAttrs(ZONE_NETDEV, attrsIn); + + bool gotMtu = false; + ZoneAdmin::NetdevAttrs attrsOut = c->getNetdevAttrs(ZONE_NETDEV); + for (auto& attr : attrsOut) { + if (std::get<0>(attr) == "mtu") { + BOOST_CHECK(!gotMtu); + BOOST_CHECK_EQUAL(std::get<1>(attr), "500"); + gotMtu = true; + } + } + BOOST_CHECK(gotMtu); + + attrsIn.clear(); + attrsIn.push_back(std::make_tuple("does_not_exists", "500")); + BOOST_REQUIRE_EXCEPTION(c->setNetdevAttrs(ZONE_NETDEV, attrsIn), + VasumException, + WhatEquals("Unsupported attribute: does_not_exists")); +} + +BOOST_AUTO_TEST_CASE(SetNetdevIpv4Test) +{ + setupBridge(BRIDGE_NAME); + auto c = create(TEST_CONFIG_PATH); + c->start(); + ensureStarted(); + c->createNetdevVeth(ZONE_NETDEV, BRIDGE_NAME); + ZoneAdmin::NetdevAttrs attrsIn; + attrsIn.push_back(std::make_tuple("ipv4", "ip:192.168.4.1,prefixlen:24")); + c->setNetdevAttrs(ZONE_NETDEV, attrsIn); + + ZoneAdmin::NetdevAttrs attrsOut = c->getNetdevAttrs(ZONE_NETDEV); + int gotIp = 0; + for (auto& attr : attrsOut) { + if (std::get<0>(attr) == "ipv4") { + BOOST_CHECK(std::get<1>(attr).find("ip:192.168.4.1") != std::string::npos); + BOOST_CHECK(std::get<1>(attr).find("prefixlen:24") != std::string::npos); + gotIp++; + } + } + BOOST_CHECK_EQUAL(gotIp, 1); + + attrsIn.clear(); + attrsIn.push_back(std::make_tuple("ipv4", "ip:192.168.4.2,prefixlen:24")); + attrsIn.push_back(std::make_tuple("ipv4", "ip:192.168.4.3,prefixlen:24")); + c->setNetdevAttrs(ZONE_NETDEV, attrsIn); + attrsOut = c->getNetdevAttrs(ZONE_NETDEV); + gotIp = 0; + for (auto& attr : attrsOut) { + if (std::get<0>(attr) == "ipv4") { + BOOST_CHECK(std::get<1>(attr).find("ip:192.168.4.1") != std::string::npos || + std::get<1>(attr).find("ip:192.168.4.2") != std::string::npos || + std::get<1>(attr).find("ip:192.168.4.3") != std::string::npos); + BOOST_CHECK(std::get<1>(attr).find("prefixlen:24") != std::string::npos); + gotIp++; + } + } + BOOST_CHECK_EQUAL(gotIp, 3); +} + +BOOST_AUTO_TEST_CASE(SetNetdevIpv6Test) +{ + setupBridge(BRIDGE_NAME); + auto c = create(TEST_CONFIG_PATH); + c->start(); + ensureStarted(); + c->createNetdevVeth(ZONE_NETDEV, BRIDGE_NAME); + ZoneAdmin::NetdevAttrs attrsIn; + attrsIn.push_back(std::make_tuple("ipv6", "ip:2001:db8::1,prefixlen:64")); + c->setNetdevAttrs(ZONE_NETDEV, attrsIn); + + ZoneAdmin::NetdevAttrs attrsOut = c->getNetdevAttrs(ZONE_NETDEV); + int gotIp = 0; + for (auto& attr : attrsOut) { + if (std::get<0>(attr) == "ipv6") { + BOOST_CHECK(std::get<1>(attr).find("ip:2001:db8::1") != std::string::npos); + BOOST_CHECK(std::get<1>(attr).find("prefixlen:64") != std::string::npos); + gotIp++; + } + } + BOOST_CHECK_EQUAL(gotIp, 1); + + attrsIn.clear(); + attrsIn.push_back(std::make_tuple("ipv6", "ip:2001:db8::2,prefixlen:64")); + attrsIn.push_back(std::make_tuple("ipv6", "ip:2001:db8::3,prefixlen:64")); + c->setNetdevAttrs(ZONE_NETDEV, attrsIn); + attrsOut = c->getNetdevAttrs(ZONE_NETDEV); + gotIp = 0; + for (auto& attr : attrsOut) { + if (std::get<0>(attr) == "ipv6") { + BOOST_CHECK(std::get<1>(attr).find("ip:2001:db8::1") != std::string::npos || + std::get<1>(attr).find("ip:2001:db8::2") != std::string::npos || + std::get<1>(attr).find("ip:2001:db8::3") != std::string::npos); + BOOST_CHECK(std::get<1>(attr).find("prefixlen:64") != std::string::npos); + gotIp++; + } + } + BOOST_CHECK_EQUAL(gotIp, 3); } BOOST_AUTO_TEST_SUITE_END() -- 2.7.4 From 9a6ea1bd77132efc3490e427fd257deaac230f10 Mon Sep 17 00:00:00 2001 From: Lukasz Kostyra Date: Wed, 25 Mar 2015 11:57:30 +0100 Subject: [PATCH 12/16] Cleanup test case names [Feature] Renamed test case names [Cause] Inconsistent test case names [Solution] Rename tests, keep the naming consistent [Verification] Build, install, run tests Change-Id: I76da5f2bedcbe361ebcd5d4a612129a867599a16 --- tests/unit_tests/client/ut-client-utils.cpp | 2 +- tests/unit_tests/client/ut-client.cpp | 28 ++++++++-------- tests/unit_tests/config/ut-configuration.cpp | 20 +++++------ tests/unit_tests/config/ut-kvstore.cpp | 18 +++++----- tests/unit_tests/dbus/ut-connection.cpp | 40 +++++++++++----------- tests/unit_tests/ipc/ut-ipc.cpp | 2 +- tests/unit_tests/log/ut-logger.cpp | 16 ++++----- tests/unit_tests/lxc/ut-zone.cpp | 16 ++++----- tests/unit_tests/server/ut-input-monitor.cpp | 14 ++++---- tests/unit_tests/server/ut-server.cpp | 10 +++--- tests/unit_tests/server/ut-zone-admin.cpp | 16 ++++----- tests/unit_tests/server/ut-zone-connection.cpp | 8 ++--- tests/unit_tests/server/ut-zone-provision.cpp | 20 +++++------ tests/unit_tests/server/ut-zone.cpp | 16 ++++----- tests/unit_tests/server/ut-zones-manager.cpp | 44 ++++++++++++------------- tests/unit_tests/utils/ut-callback-guard.cpp | 6 ++-- tests/unit_tests/utils/ut-counting-map.cpp | 2 +- tests/unit_tests/utils/ut-fs.cpp | 12 +++---- tests/unit_tests/utils/ut-glib-loop.cpp | 2 +- tests/unit_tests/utils/ut-paths.cpp | 4 +-- tests/unit_tests/utils/ut-same-thread-guard.cpp | 4 +-- tests/unit_tests/utils/ut-value-latch.cpp | 12 +++---- tests/unit_tests/utils/ut-worker.cpp | 14 ++++---- 23 files changed, 163 insertions(+), 163 deletions(-) diff --git a/tests/unit_tests/client/ut-client-utils.cpp b/tests/unit_tests/client/ut-client-utils.cpp index 140238a..459a1b1 100644 --- a/tests/unit_tests/client/ut-client-utils.cpp +++ b/tests/unit_tests/client/ut-client-utils.cpp @@ -30,7 +30,7 @@ BOOST_AUTO_TEST_SUITE(ClientUtils) -BOOST_AUTO_TEST_CASE(ParseZoneIdFromCpuSetTest) +BOOST_AUTO_TEST_CASE(ParseZoneIdFromCpuSet) { auto testBad = [](const std::string& input) { std::string ret; diff --git a/tests/unit_tests/client/ut-client.cpp b/tests/unit_tests/client/ut-client.cpp index ce31795..197da5e 100644 --- a/tests/unit_tests/client/ut-client.cpp +++ b/tests/unit_tests/client/ut-client.cpp @@ -151,7 +151,7 @@ std::ostream& operator<<(std::ostream& out, VsmStatus status) BOOST_FIXTURE_TEST_SUITE(ClientSuite, Fixture) -BOOST_AUTO_TEST_CASE(NotRunningServerTest) +BOOST_AUTO_TEST_CASE(NotRunningServer) { cm.shutdownAll(); @@ -162,7 +162,7 @@ BOOST_AUTO_TEST_CASE(NotRunningServerTest) vsm_client_free(client); } -BOOST_AUTO_TEST_CASE(GetZoneDbusesTest) +BOOST_AUTO_TEST_CASE(GetZoneDbuses) { VsmClient client = vsm_client_create(); VsmStatus status = vsm_connect(client); @@ -185,7 +185,7 @@ BOOST_AUTO_TEST_CASE(GetZoneDbusesTest) vsm_client_free(client); } -BOOST_AUTO_TEST_CASE(GetZoneIdsTest) +BOOST_AUTO_TEST_CASE(GetZoneIds) { VsmClient client = vsm_client_create(); VsmStatus status = vsm_connect(client); @@ -206,7 +206,7 @@ BOOST_AUTO_TEST_CASE(GetZoneIdsTest) vsm_client_free(client); } -BOOST_AUTO_TEST_CASE(GetActiveZoneIdTest) +BOOST_AUTO_TEST_CASE(GetActiveZoneId) { VsmClient client = vsm_client_create(); VsmStatus status = vsm_connect(client); @@ -221,7 +221,7 @@ BOOST_AUTO_TEST_CASE(GetActiveZoneIdTest) vsm_client_free(client); } -BOOST_AUTO_TEST_CASE(SetActiveZoneTest) +BOOST_AUTO_TEST_CASE(SetActiveZone) { const std::string newActiveZoneId = "zone2"; @@ -236,7 +236,7 @@ BOOST_AUTO_TEST_CASE(SetActiveZoneTest) vsm_client_free(client); } -BOOST_AUTO_TEST_CASE(CreateZoneTest) +BOOST_AUTO_TEST_CASE(CreateZone) { const std::string newActiveZoneId = ""; @@ -248,7 +248,7 @@ BOOST_AUTO_TEST_CASE(CreateZoneTest) vsm_client_free(client); } -BOOST_AUTO_TEST_CASE(StartShutdownZoneTest) +BOOST_AUTO_TEST_CASE(StartShutdownZone) { const std::string newActiveZoneId = "zone1"; @@ -262,7 +262,7 @@ BOOST_AUTO_TEST_CASE(StartShutdownZoneTest) vsm_client_free(client); } -BOOST_AUTO_TEST_CASE(LockUnlockZoneTest) +BOOST_AUTO_TEST_CASE(LockUnlockZone) { const std::string newActiveZoneId = "zone2"; @@ -276,7 +276,7 @@ BOOST_AUTO_TEST_CASE(LockUnlockZoneTest) vsm_client_free(client); } -BOOST_AUTO_TEST_CASE(FileMoveRequestTest) +BOOST_AUTO_TEST_CASE(FileMoveRequest) { const std::string path = "/tmp/fake_path"; const std::string secondZone = "fake_zone"; @@ -291,7 +291,7 @@ BOOST_AUTO_TEST_CASE(FileMoveRequestTest) vsm_client_free(client); } -BOOST_AUTO_TEST_CASE(NotificationTest) +BOOST_AUTO_TEST_CASE(Notification) { const std::string MSG_CONTENT = "msg"; const std::string MSG_APP = "app"; @@ -346,7 +346,7 @@ BOOST_AUTO_TEST_CASE(NotificationTest) } } -BOOST_AUTO_TEST_CASE(GetZoneIdByPidTest1) +BOOST_AUTO_TEST_CASE(GetZoneIdByPidTestSingle) { VsmClient client = vsm_client_create(); VsmString zone; @@ -359,7 +359,7 @@ BOOST_AUTO_TEST_CASE(GetZoneIdByPidTest1) vsm_client_free(client); } -BOOST_AUTO_TEST_CASE(GetZoneIdByPidTest2) +BOOST_AUTO_TEST_CASE(GetZoneIdByPidTestMultiple) { std::set ids; @@ -383,7 +383,7 @@ BOOST_AUTO_TEST_CASE(GetZoneIdByPidTest2) } } -BOOST_AUTO_TEST_CASE(GrantRevokeTest) +BOOST_AUTO_TEST_CASE(GrantRevoke) { const std::string zoneId = "zone2"; const std::string dev = "tty3"; @@ -405,7 +405,7 @@ BOOST_AUTO_TEST_CASE(GrantRevokeTest) vsm_client_free(client); } -BOOST_AUTO_TEST_CASE(ProvisionTest) +BOOST_AUTO_TEST_CASE(Provision) { VsmClient client = vsm_client_create(); BOOST_REQUIRE_EQUAL(VSMCLIENT_SUCCESS, vsm_connect(client)); diff --git a/tests/unit_tests/config/ut-configuration.cpp b/tests/unit_tests/config/ut-configuration.cpp index 8049975..a9a5332 100644 --- a/tests/unit_tests/config/ut-configuration.cpp +++ b/tests/unit_tests/config/ut-configuration.cpp @@ -52,7 +52,7 @@ struct Fixture { BOOST_FIXTURE_TEST_SUITE(ConfigurationSuite, Fixture) -BOOST_AUTO_TEST_CASE(FromJsonStringTest) +BOOST_AUTO_TEST_CASE(FromJsonString) { TestConfig testConfig; @@ -117,7 +117,7 @@ BOOST_AUTO_TEST_CASE(FromJsonStringTest) } -BOOST_AUTO_TEST_CASE(ToJsonStringTest) +BOOST_AUTO_TEST_CASE(ToJsonString) { TestConfig testConfig; BOOST_REQUIRE_NO_THROW(loadFromJsonString(jsonTestString, testConfig)); @@ -153,7 +153,7 @@ struct UnionConfig { } // namespace loadErrorsTest -BOOST_AUTO_TEST_CASE(JsonLoadErrorsTest) +BOOST_AUTO_TEST_CASE(JsonLoadErrors) { using namespace loadErrorsTest; @@ -256,7 +256,7 @@ struct NotFunction { } // namespace hasVisitableTest -BOOST_AUTO_TEST_CASE(HasVisibleInternalHelperTest) +BOOST_AUTO_TEST_CASE(HasVisibleInternalHelper) { using namespace hasVisitableTest; @@ -273,7 +273,7 @@ BOOST_AUTO_TEST_CASE(HasVisibleInternalHelperTest) BOOST_CHECK(isVisitable()); } -BOOST_AUTO_TEST_CASE(FromToKVStoreTest) +BOOST_AUTO_TEST_CASE(FromToKVStore) { TestConfig config; loadFromJsonString(jsonTestString, config); @@ -286,7 +286,7 @@ BOOST_AUTO_TEST_CASE(FromToKVStoreTest) BOOST_CHECK_EQUAL(out, jsonTestString); } -BOOST_AUTO_TEST_CASE(FromToFDTest) +BOOST_AUTO_TEST_CASE(FromToFD) { TestConfig config; loadFromJsonString(jsonTestString, config); @@ -307,7 +307,7 @@ BOOST_AUTO_TEST_CASE(FromToFDTest) BOOST_CHECK(::close(fd) >= 0); } -BOOST_AUTO_TEST_CASE(FromKVWithDefaultsTest) +BOOST_AUTO_TEST_CASE(FromKVWithDefaults) { TestConfig config; loadFromJsonString(jsonTestString, config); @@ -328,7 +328,7 @@ BOOST_AUTO_TEST_CASE(FromKVWithDefaultsTest) BOOST_CHECK_EQUAL(out2, jsonTestString); } -BOOST_AUTO_TEST_CASE(PartialConfigTest) +BOOST_AUTO_TEST_CASE(PartialConfig) { // check if partial config is fully supported TestConfig config; @@ -379,7 +379,7 @@ BOOST_AUTO_TEST_CASE(PartialConfigTest) } } -BOOST_AUTO_TEST_CASE(ConfigUnionTest) +BOOST_AUTO_TEST_CASE(ConfigUnion) { TestConfig testConfig; BOOST_REQUIRE_NO_THROW(loadFromJsonString(jsonTestString, testConfig)); @@ -426,7 +426,7 @@ BOOST_AUTO_TEST_CASE(ConfigUnionTest) } -BOOST_AUTO_TEST_CASE(GVariantVisitorTest) +BOOST_AUTO_TEST_CASE(GVariantVisitor) { TestConfig testConfig; BOOST_REQUIRE_NO_THROW(loadFromJsonString(jsonTestString, testConfig)); diff --git a/tests/unit_tests/config/ut-kvstore.cpp b/tests/unit_tests/config/ut-kvstore.cpp index 1129bdf..239f568 100644 --- a/tests/unit_tests/config/ut-kvstore.cpp +++ b/tests/unit_tests/config/ut-kvstore.cpp @@ -98,7 +98,7 @@ BOOST_FIXTURE_TEST_SUITE(KVStoreSuite, Fixture) const std::string KEY = "KEY"; -BOOST_AUTO_TEST_CASE(SimpleConstructorDestructorTest) +BOOST_AUTO_TEST_CASE(SimpleConstructorDestructor) { std::unique_ptr conPtr; BOOST_REQUIRE_NO_THROW(conPtr.reset(new KVStore(dbPath))); @@ -109,7 +109,7 @@ BOOST_AUTO_TEST_CASE(SimpleConstructorDestructorTest) BOOST_CHECK(fs::exists(dbPath)); } -BOOST_AUTO_TEST_CASE(EscapedCharactersTest) +BOOST_AUTO_TEST_CASE(EscapedCharacters) { // '*' ?' '[' ']' are escaped // They shouldn't influence the internal implementation @@ -162,7 +162,7 @@ void testSingleValue(Fixture& f, const A& a, const B& b) } // namespace -BOOST_AUTO_TEST_CASE(SingleValueTest) +BOOST_AUTO_TEST_CASE(SingleValue) { testSingleValue(*this, "A", "B"); testSingleValue(*this, 1, 2); @@ -202,7 +202,7 @@ void testVectorOfValues(Fixture& f, } } // namespace -BOOST_AUTO_TEST_CASE(VectorOfValuesTest) +BOOST_AUTO_TEST_CASE(VectorOfValues) { testVectorOfValues(*this, {"A", "B"}, {"A", "C"}, {"A", "B", "C"}); testVectorOfValues(*this, {1, 2}, {1, 3}, {1, 2, 3}); @@ -211,7 +211,7 @@ BOOST_AUTO_TEST_CASE(VectorOfValuesTest) testVectorOfValues(*this, {1, 2}, {1, 3}, {1, 2, 3}); } -BOOST_AUTO_TEST_CASE(ClearTest) +BOOST_AUTO_TEST_CASE(Clear) { BOOST_CHECK_NO_THROW(c.clear()); std::vector vec = {"A", "B"}; @@ -224,7 +224,7 @@ BOOST_AUTO_TEST_CASE(ClearTest) BOOST_CHECK_THROW(c.get(KEY), ConfigException); } -BOOST_AUTO_TEST_CASE(TransactionTest) +BOOST_AUTO_TEST_CASE(Transaction) { { KVStore::Transaction trans(c); @@ -248,7 +248,7 @@ BOOST_AUTO_TEST_CASE(TransactionTest) } } -BOOST_AUTO_TEST_CASE(TransactionStackedTest) +BOOST_AUTO_TEST_CASE(TransactionStacked) { { KVStore::Transaction transOuter(c); @@ -285,7 +285,7 @@ BOOST_AUTO_TEST_CASE(TransactionStackedTest) } } -BOOST_AUTO_TEST_CASE(TransactionThreadsTest) +BOOST_AUTO_TEST_CASE(TransactionThreads) { Latch trans1Started, trans1Release, trans2Released; std::thread thread1([&] { @@ -306,7 +306,7 @@ BOOST_AUTO_TEST_CASE(TransactionThreadsTest) thread2.join(); } -BOOST_AUTO_TEST_CASE(KeyTest) +BOOST_AUTO_TEST_CASE(Key) { BOOST_CHECK_EQUAL(key(), ""); BOOST_CHECK_EQUAL(key<>(), ""); diff --git a/tests/unit_tests/dbus/ut-connection.cpp b/tests/unit_tests/dbus/ut-connection.cpp index e52778e..84ea626 100644 --- a/tests/unit_tests/dbus/ut-connection.cpp +++ b/tests/unit_tests/dbus/ut-connection.cpp @@ -96,24 +96,24 @@ std::string getInterfaceFromIntrospectionXML(const std::string& xml, const std:: } // namespace -BOOST_AUTO_TEST_CASE(DbusDaemonTest) +BOOST_AUTO_TEST_CASE(DbusDaemon) { ScopedDbusDaemon daemon; } -BOOST_AUTO_TEST_CASE(NoDbusTest) +BOOST_AUTO_TEST_CASE(NoDbus) { ScopedGlibLoop loop; BOOST_CHECK_THROW(DbusConnection::create(DBUS_ADDRESS), DbusIOException); } -BOOST_AUTO_TEST_CASE(ConnectionTest) +BOOST_AUTO_TEST_CASE(Connection) { ScopedGlibLoop loop; DbusConnection::Pointer connSystem = DbusConnection::createSystem(); } -BOOST_AUTO_TEST_CASE(SimpleTest) +BOOST_AUTO_TEST_CASE(Simple) { ScopedDbusDaemon daemon; ScopedGlibLoop loop; @@ -129,7 +129,7 @@ BOOST_AUTO_TEST_CASE(SimpleTest) BOOST_CHECK(nameLost.empty()); } -BOOST_AUTO_TEST_CASE(ConnectionLostTest) +BOOST_AUTO_TEST_CASE(ConnectionLost) { ScopedDbusDaemon daemon; ScopedGlibLoop loop; @@ -147,7 +147,7 @@ BOOST_AUTO_TEST_CASE(ConnectionLostTest) BOOST_CHECK(nameLost.wait(EVENT_TIMEOUT)); } -BOOST_AUTO_TEST_CASE(NameOwnerTest) +BOOST_AUTO_TEST_CASE(NameOwner) { ScopedDbusDaemon daemon; ScopedGlibLoop loop; @@ -177,7 +177,7 @@ BOOST_AUTO_TEST_CASE(NameOwnerTest) //BOOST_CHECK(nameAcquired2.wait(EVENT_TIMEOUT)); } -BOOST_AUTO_TEST_CASE(GenericSignalTest) +BOOST_AUTO_TEST_CASE(GenericSignal) { ScopedDbusDaemon daemon; ScopedGlibLoop loop; @@ -208,7 +208,7 @@ BOOST_AUTO_TEST_CASE(GenericSignalTest) BOOST_CHECK(signalEmitted.wait(EVENT_TIMEOUT)); } -BOOST_AUTO_TEST_CASE(FilteredSignalTest) +BOOST_AUTO_TEST_CASE(FilteredSignal) { ScopedDbusDaemon daemon; ScopedGlibLoop loop; @@ -259,7 +259,7 @@ BOOST_AUTO_TEST_CASE(FilteredSignalTest) BOOST_CHECK(wrongSignalEmitted.empty()); } -BOOST_AUTO_TEST_CASE(RegisterObjectTest) +BOOST_AUTO_TEST_CASE(RegisterObject) { ScopedDbusDaemon daemon; ScopedGlibLoop loop; @@ -274,7 +274,7 @@ BOOST_AUTO_TEST_CASE(RegisterObjectTest) BOOST_CHECK_NO_THROW(conn->registerObject(TESTAPI_OBJECT_PATH, TESTAPI_DEFINITION, callback)); } -BOOST_AUTO_TEST_CASE(IntrospectSystemTest) +BOOST_AUTO_TEST_CASE(IntrospectSystem) { ScopedGlibLoop loop; DbusConnection::Pointer conn = DbusConnection::createSystem(); @@ -283,7 +283,7 @@ BOOST_AUTO_TEST_CASE(IntrospectSystemTest) BOOST_CHECK(!iface.empty()); } -BOOST_AUTO_TEST_CASE(IntrospectTest) +BOOST_AUTO_TEST_CASE(Introspect) { ScopedDbusDaemon daemon; ScopedGlibLoop loop; @@ -309,7 +309,7 @@ BOOST_AUTO_TEST_CASE(IntrospectTest) BOOST_CHECK(std::string::npos != iface.find(TESTAPI_SIGNAL_NOTIFY)); } -BOOST_AUTO_TEST_CASE(MethodCallTest) +BOOST_AUTO_TEST_CASE(MethodCall) { ScopedDbusDaemon daemon; ScopedGlibLoop loop; @@ -372,7 +372,7 @@ BOOST_AUTO_TEST_CASE(MethodCallTest) DbusCustomException); } -BOOST_AUTO_TEST_CASE(MethodAsyncCallTest) +BOOST_AUTO_TEST_CASE(MethodAsyncCall) { ScopedDbusDaemon daemon; ScopedGlibLoop loop; @@ -457,7 +457,7 @@ BOOST_AUTO_TEST_CASE(MethodAsyncCallTest) BOOST_REQUIRE(callDone.wait(EVENT_TIMEOUT)); } -BOOST_AUTO_TEST_CASE(MethodAsyncCallAsyncHandlerTest) +BOOST_AUTO_TEST_CASE(MethodAsyncCallAsyncHandler) { ScopedDbusDaemon daemon; ScopedGlibLoop loop; @@ -513,7 +513,7 @@ BOOST_AUTO_TEST_CASE(MethodAsyncCallAsyncHandlerTest) BOOST_REQUIRE(callDone.wait(EVENT_TIMEOUT)); } -BOOST_AUTO_TEST_CASE(MethodCallExceptionTest) +BOOST_AUTO_TEST_CASE(MethodCallException) { ScopedDbusDaemon daemon; ScopedGlibLoop loop; @@ -559,7 +559,7 @@ BOOST_AUTO_TEST_CASE(MethodCallExceptionTest) DbusOperationException); } -BOOST_AUTO_TEST_CASE(DbusApiTest) +BOOST_AUTO_TEST_CASE(DbusApi) { ScopedDbusDaemon daemon; ScopedGlibLoop loop; @@ -575,7 +575,7 @@ BOOST_AUTO_TEST_CASE(DbusApiTest) WhatEquals("Argument: 666")); } -BOOST_AUTO_TEST_CASE(DbusApiNotifyTest) +BOOST_AUTO_TEST_CASE(DbusApiNotify) { ScopedDbusDaemon daemon; ScopedGlibLoop loop; @@ -594,7 +594,7 @@ BOOST_AUTO_TEST_CASE(DbusApiNotifyTest) BOOST_CHECK(notified.wait(EVENT_TIMEOUT)); } -BOOST_AUTO_TEST_CASE(DbusApiNameAcquiredTest) +BOOST_AUTO_TEST_CASE(DbusApiNameAcquired) { ScopedDbusDaemon daemon; ScopedGlibLoop loop; @@ -606,7 +606,7 @@ BOOST_AUTO_TEST_CASE(DbusApiNameAcquiredTest) BOOST_CHECK_NO_THROW(client.noop()); } -BOOST_AUTO_TEST_CASE(DbusApiConnectionLost1Test) +BOOST_AUTO_TEST_CASE(DbusApiConnectionLost) { ScopedDbusDaemon daemon; ScopedGlibLoop loop; @@ -622,7 +622,7 @@ BOOST_AUTO_TEST_CASE(DbusApiConnectionLost1Test) BOOST_CHECK_THROW(client.noop(), DbusIOException); } -BOOST_AUTO_TEST_CASE(DbusApiConnectionLost2Test) +BOOST_AUTO_TEST_CASE(DbusApiConnectionLostDelayedCallbackSet) { ScopedDbusDaemon daemon; ScopedGlibLoop loop; diff --git a/tests/unit_tests/ipc/ut-ipc.cpp b/tests/unit_tests/ipc/ut-ipc.cpp index 8f47a65..6f2765b 100644 --- a/tests/unit_tests/ipc/ut-ipc.cpp +++ b/tests/unit_tests/ipc/ut-ipc.cpp @@ -702,7 +702,7 @@ MULTI_FIXTURE_TEST_CASE(MixOperations, F, ThreadedFixture, GlibFixture) BOOST_CHECK(l.wait(TIMEOUT)); } -// MULTI_FIXTURE_TEST_CASE(ConnectionLimitTest, F, ThreadedFixture, GlibFixture) +// MULTI_FIXTURE_TEST_CASE(ConnectionLimit, F, ThreadedFixture, GlibFixture) // { // unsigned oldLimit = ipc::getMaxFDNumber(); // ipc::setMaxFDNumber(50); diff --git a/tests/unit_tests/log/ut-logger.cpp b/tests/unit_tests/log/ut-logger.cpp index ef3634e..36f52e3 100644 --- a/tests/unit_tests/log/ut-logger.cpp +++ b/tests/unit_tests/log/ut-logger.cpp @@ -97,7 +97,7 @@ void exampleTestLogs(void) } // namespace -BOOST_AUTO_TEST_CASE(LogLevelSetandGet) +BOOST_AUTO_TEST_CASE(LogLevelSetAndGet) { Logger::setLogLevel(LogLevel::TRACE); BOOST_CHECK(LogLevel::TRACE == Logger::getLogLevel()); @@ -115,7 +115,7 @@ BOOST_AUTO_TEST_CASE(LogLevelSetandGet) BOOST_CHECK(LogLevel::ERROR == Logger::getLogLevel()); } -BOOST_AUTO_TEST_CASE(StringLogLevelSetandGet) +BOOST_AUTO_TEST_CASE(StringLogLevelSetAndGet) { Logger::setLogLevel("TRACE"); BOOST_CHECK(LogLevel::TRACE == Logger::getLogLevel()); @@ -140,7 +140,7 @@ BOOST_AUTO_TEST_CASE(StringLogLevelSetandGet) WhatEquals("Invalid LogLevel to parse")); //TODO change message } -BOOST_AUTO_TEST_CASE(TestLogsError) +BOOST_AUTO_TEST_CASE(LogsLevelError) { TestLog tf(LogLevel::ERROR); exampleTestLogs(); @@ -152,7 +152,7 @@ BOOST_AUTO_TEST_CASE(TestLogsError) BOOST_CHECK(tf.logContains("[TRACE]") == false); } -BOOST_AUTO_TEST_CASE(TestLogsWarn) +BOOST_AUTO_TEST_CASE(LogsLevelWarn) { TestLog tf(LogLevel::WARN); exampleTestLogs(); @@ -164,7 +164,7 @@ BOOST_AUTO_TEST_CASE(TestLogsWarn) BOOST_CHECK(tf.logContains("[TRACE]") == false); } -BOOST_AUTO_TEST_CASE(TestLogsInfo) +BOOST_AUTO_TEST_CASE(LogsLevelInfo) { TestLog tf(LogLevel::INFO); exampleTestLogs(); @@ -176,7 +176,7 @@ BOOST_AUTO_TEST_CASE(TestLogsInfo) BOOST_CHECK(tf.logContains("[TRACE]") == false); } -BOOST_AUTO_TEST_CASE(TestLogsDebug) +BOOST_AUTO_TEST_CASE(LogsLevelDebug) { TestLog tf(LogLevel::DEBUG); exampleTestLogs(); @@ -188,7 +188,7 @@ BOOST_AUTO_TEST_CASE(TestLogsDebug) BOOST_CHECK(tf.logContains("[TRACE]") == false); } -BOOST_AUTO_TEST_CASE(TestLogsTrace) +BOOST_AUTO_TEST_CASE(LogsLevelTrace) { TestLog tf(LogLevel::TRACE); exampleTestLogs(); @@ -200,7 +200,7 @@ BOOST_AUTO_TEST_CASE(TestLogsTrace) BOOST_CHECK(tf.logContains("[TRACE]") == true); } -BOOST_AUTO_TEST_CASE(TestLoggerScope) +BOOST_AUTO_TEST_CASE(LoggerScope) { LOGS("Main function scope"); diff --git a/tests/unit_tests/lxc/ut-zone.cpp b/tests/unit_tests/lxc/ut-zone.cpp index 3b375bd..194a2a6 100644 --- a/tests/unit_tests/lxc/ut-zone.cpp +++ b/tests/unit_tests/lxc/ut-zone.cpp @@ -80,12 +80,12 @@ struct Fixture { BOOST_FIXTURE_TEST_SUITE(LxcZoneSuite, Fixture) -BOOST_AUTO_TEST_CASE(ConstructorDestructorTest) +BOOST_AUTO_TEST_CASE(ConstructorDestructor) { LxcZone lxc(LXC_PATH, ZONE_NAME); } -BOOST_AUTO_TEST_CASE(CreateDestroyTest) +BOOST_AUTO_TEST_CASE(CreateDestroy) { LxcZone lxc(LXC_PATH, ZONE_NAME); BOOST_CHECK(!lxc.isDefined()); @@ -101,7 +101,7 @@ BOOST_AUTO_TEST_CASE(CreateDestroyTest) BOOST_CHECK(!lxc.isDefined()); } -BOOST_AUTO_TEST_CASE(StartShutdownTest) +BOOST_AUTO_TEST_CASE(StartShutdown) { { LxcZone lxc(LXC_PATH, ZONE_NAME); @@ -124,7 +124,7 @@ BOOST_AUTO_TEST_CASE(StartShutdownTest) BOOST_CHECK(lxc.destroy()); } -BOOST_AUTO_TEST_CASE(StartStopTest) +BOOST_AUTO_TEST_CASE(StartStop) { { LxcZone lxc(LXC_PATH, ZONE_NAME); @@ -149,7 +149,7 @@ BOOST_AUTO_TEST_CASE(StartStopTest) BOOST_CHECK(lxc.destroy()); } -BOOST_AUTO_TEST_CASE(StartHasStoppedTest) +BOOST_AUTO_TEST_CASE(StartHasStopped) { { LxcZone lxc(LXC_PATH, ZONE_NAME); @@ -170,7 +170,7 @@ BOOST_AUTO_TEST_CASE(StartHasStoppedTest) BOOST_CHECK(lxc.destroy()); } -BOOST_AUTO_TEST_CASE(FreezeUnfreezeTest) +BOOST_AUTO_TEST_CASE(FreezeUnfreeze) { LxcZone lxc(LXC_PATH, ZONE_NAME); BOOST_CHECK(lxc.create(TEMPLATE, TEMPLATE_ARGS)); @@ -193,7 +193,7 @@ BOOST_AUTO_TEST_CASE(FreezeUnfreezeTest) BOOST_CHECK(lxc.destroy()); } -BOOST_AUTO_TEST_CASE(FreezeStopTest) +BOOST_AUTO_TEST_CASE(FreezeStop) { LxcZone lxc(LXC_PATH, ZONE_NAME); BOOST_CHECK(lxc.create(TEMPLATE, TEMPLATE_ARGS)); @@ -216,7 +216,7 @@ BOOST_AUTO_TEST_CASE(FreezeStopTest) BOOST_CHECK(lxc.destroy()); } -BOOST_AUTO_TEST_CASE(RepeatTest) +BOOST_AUTO_TEST_CASE(Repeat) { LxcZone lxc(LXC_PATH, ZONE_NAME); BOOST_CHECK(lxc.create(TEMPLATE, TEMPLATE_ARGS)); diff --git a/tests/unit_tests/server/ut-input-monitor.cpp b/tests/unit_tests/server/ut-input-monitor.cpp index 3560b40..454a307 100644 --- a/tests/unit_tests/server/ut-input-monitor.cpp +++ b/tests/unit_tests/server/ut-input-monitor.cpp @@ -89,12 +89,12 @@ struct Fixture { BOOST_FIXTURE_TEST_SUITE(InputMonitorSuite, Fixture) -BOOST_AUTO_TEST_CASE(Config_OK) +BOOST_AUTO_TEST_CASE(ConfigOK) { InputMonitor inputMonitor(inputConfig, InputMonitor::NotifyCallback()); } -BOOST_AUTO_TEST_CASE(Config_timeWindowMsTooHigh) +BOOST_AUTO_TEST_CASE(ConfigTimeWindowMsTooHigh) { inputConfig.timeWindowMs = 50000; @@ -103,7 +103,7 @@ BOOST_AUTO_TEST_CASE(Config_timeWindowMsTooHigh) WhatEquals("Time window exceeds maximum")); } -BOOST_AUTO_TEST_CASE(Config_deviceFilePathNotExisting) +BOOST_AUTO_TEST_CASE(ConfigDeviceFilePathNotExisting) { inputConfig.device = TEST_INPUT_DEVICE + "notExisting"; @@ -148,12 +148,12 @@ void sendNEvents(Fixture& f, unsigned int noOfEventsToSend) } // namespace -BOOST_AUTO_TEST_CASE(Event_oneAtATime) +BOOST_AUTO_TEST_CASE(EventOneAtATime) { sendNEvents(*this, 1); } -BOOST_AUTO_TEST_CASE(Event_tenAtATime) +BOOST_AUTO_TEST_CASE(EventTenAtATime) { sendNEvents(*this, 10); } @@ -199,12 +199,12 @@ void sendNEventsWithPauses(Fixture& f, unsigned int noOfEventsToSend) } // namespace -BOOST_AUTO_TEST_CASE(Event_oneAtATimeWithPauses) +BOOST_AUTO_TEST_CASE(EventOneAtATimeWithPauses) { sendNEventsWithPauses(*this, 1); } -BOOST_AUTO_TEST_CASE(Event_tenAtATimeWithPauses) +BOOST_AUTO_TEST_CASE(EventTenAtATimeWithPauses) { sendNEventsWithPauses(*this, 10); } diff --git a/tests/unit_tests/server/ut-server.cpp b/tests/unit_tests/server/ut-server.cpp index eccea8a..8466f19 100644 --- a/tests/unit_tests/server/ut-server.cpp +++ b/tests/unit_tests/server/ut-server.cpp @@ -73,34 +73,34 @@ BOOST_FIXTURE_TEST_SUITE(ServerSuite, Fixture) using namespace vasum; using namespace config; -BOOST_AUTO_TEST_CASE(ConstructorDestructorTest) +BOOST_AUTO_TEST_CASE(ConstructorDestructor) { std::unique_ptr s; s.reset(new Server(TEST_CONFIG_PATH)); s.reset(); } -BOOST_AUTO_TEST_CASE(MissingConfigTest) +BOOST_AUTO_TEST_CASE(MissingConfig) { BOOST_REQUIRE_EXCEPTION(Server(MISSING_CONFIG_PATH).run(AS_ROOT), ConfigException, WhatEquals("Could not load " + MISSING_CONFIG_PATH)); } -BOOST_AUTO_TEST_CASE(TerminateTest) +BOOST_AUTO_TEST_CASE(Terminate) { Server s(TEST_CONFIG_PATH); s.terminate(); } -BOOST_AUTO_TEST_CASE(TerminateRunTest) +BOOST_AUTO_TEST_CASE(TerminateRun) { Server s(TEST_CONFIG_PATH); s.terminate(); s.run(AS_ROOT); } -BOOST_AUTO_TEST_CASE(RunTerminateTest) +BOOST_AUTO_TEST_CASE(RunTerminate) { Server s(TEST_CONFIG_PATH); std::future runFuture = std::async(std::launch::async, [&] {s.run(AS_ROOT);}); diff --git a/tests/unit_tests/server/ut-zone-admin.cpp b/tests/unit_tests/server/ut-zone-admin.cpp index c711169..3aa38d1 100644 --- a/tests/unit_tests/server/ut-zone-admin.cpp +++ b/tests/unit_tests/server/ut-zone-admin.cpp @@ -79,20 +79,20 @@ struct Fixture { BOOST_FIXTURE_TEST_SUITE(ZoneAdminSuite, Fixture) -BOOST_AUTO_TEST_CASE(ConstructorDestructorTest) +BOOST_AUTO_TEST_CASE(ConstructorDestructor) { auto admin = create(TEST_CONFIG_PATH); admin.reset(); } -BOOST_AUTO_TEST_CASE(MissingConfigTest) +BOOST_AUTO_TEST_CASE(MissingConfig) { BOOST_REQUIRE_EXCEPTION(create(MISSING_CONFIG_PATH), ZoneOperationException, WhatEquals("Could not create zone")); } -BOOST_AUTO_TEST_CASE(StartTest) +BOOST_AUTO_TEST_CASE(Start) { auto admin = create(TEST_CONFIG_PATH); @@ -102,7 +102,7 @@ BOOST_AUTO_TEST_CASE(StartTest) BOOST_CHECK(admin->isRunning()); } -BOOST_AUTO_TEST_CASE(StartBuggyTest) +BOOST_AUTO_TEST_CASE(StartBuggy) { auto admin = create(BUGGY_CONFIG_PATH); BOOST_REQUIRE_EXCEPTION(admin->start(), @@ -110,7 +110,7 @@ BOOST_AUTO_TEST_CASE(StartBuggyTest) WhatEquals("Could not start zone")); } -BOOST_AUTO_TEST_CASE(StopShutdownTest) +BOOST_AUTO_TEST_CASE(StopShutdown) { auto admin = create(TEST_CONFIG_PATH); @@ -124,7 +124,7 @@ BOOST_AUTO_TEST_CASE(StopShutdownTest) } // This test needs to wait for a shutdown timer in stop() method. This takes 10s+. -BOOST_AUTO_TEST_CASE(StopDestroyTest) +BOOST_AUTO_TEST_CASE(StopDestroy) { auto admin = create(TEST_NO_SHUTDOWN_CONFIG_PATH); @@ -137,7 +137,7 @@ BOOST_AUTO_TEST_CASE(StopDestroyTest) BOOST_CHECK(admin->isStopped()); } -BOOST_AUTO_TEST_CASE(SuspendResumeTest) +BOOST_AUTO_TEST_CASE(SuspendResume) { auto admin = create(TEST_NO_SHUTDOWN_CONFIG_PATH); @@ -156,7 +156,7 @@ BOOST_AUTO_TEST_CASE(SuspendResumeTest) BOOST_CHECK(admin->isRunning()); } -BOOST_AUTO_TEST_CASE(SchedulerLevelTest) +BOOST_AUTO_TEST_CASE(ForegroundBackgroundSchedulerLevel) { auto admin = create(TEST_CONFIG_PATH); diff --git a/tests/unit_tests/server/ut-zone-connection.cpp b/tests/unit_tests/server/ut-zone-connection.cpp index 2a72b87..5f2c63b 100644 --- a/tests/unit_tests/server/ut-zone-connection.cpp +++ b/tests/unit_tests/server/ut-zone-connection.cpp @@ -133,12 +133,12 @@ private: BOOST_FIXTURE_TEST_SUITE(ZoneConnectionSuite, Fixture) -BOOST_AUTO_TEST_CASE(ConstructorDestructorConnectTest) +BOOST_AUTO_TEST_CASE(ConstructorDestructorConnect) { ZoneConnection(acquireAddress(), nullptr); } -BOOST_AUTO_TEST_CASE(NotifyActiveZoneApiTest) +BOOST_AUTO_TEST_CASE(NotifyActiveZoneApi) { Latch notifyCalled; ZoneConnection connection(acquireAddress(), nullptr); @@ -161,7 +161,7 @@ BOOST_AUTO_TEST_CASE(NotifyActiveZoneApiTest) BOOST_CHECK(notifyCalled.wait(EVENT_TIMEOUT)); } -BOOST_AUTO_TEST_CASE(SignalNotificationApiTest) +BOOST_AUTO_TEST_CASE(SignalNotificationApi) { Latch signalEmitted; ZoneConnection connection(acquireAddress(), nullptr); @@ -196,7 +196,7 @@ BOOST_AUTO_TEST_CASE(SignalNotificationApiTest) BOOST_CHECK(signalEmitted.wait(EVENT_TIMEOUT)); } -BOOST_AUTO_TEST_CASE(SignalDisplayOffApiTest) +BOOST_AUTO_TEST_CASE(SignalDisplayOffApi) { Latch displayOffCalled; ZoneConnection connection(acquireAddress(), nullptr); diff --git a/tests/unit_tests/server/ut-zone-provision.cpp b/tests/unit_tests/server/ut-zone-provision.cpp index 4109cb2..a79a260 100644 --- a/tests/unit_tests/server/ut-zone-provision.cpp +++ b/tests/unit_tests/server/ut-zone-provision.cpp @@ -94,7 +94,7 @@ struct Fixture { BOOST_FIXTURE_TEST_SUITE(ZoneProvisionSuite, Fixture) -BOOST_AUTO_TEST_CASE(DestructorTest) +BOOST_AUTO_TEST_CASE(Destructor) { const fs::path mountTarget = fs::path("/opt/usr/data/ut-from-host-provision"); const fs::path mountSource = fs::path("/tmp/ut-provision"); @@ -122,7 +122,7 @@ BOOST_AUTO_TEST_CASE(DestructorTest) BOOST_CHECK(!fs::exists(mountSource)); } -BOOST_AUTO_TEST_CASE(FileTest) +BOOST_AUTO_TEST_CASE(File) { //TODO: Test Fifo const fs::path regularFile = fs::path("/opt/usr/data/ut-regular-file"); @@ -165,7 +165,7 @@ BOOST_AUTO_TEST_CASE(FileTest) zoneProvision.stop(); } -BOOST_AUTO_TEST_CASE(MountTest) +BOOST_AUTO_TEST_CASE(Mount) { //TODO: Test Fifo const fs::path mountTarget = fs::path("/opt/usr/data/ut-from-host-provision"); @@ -205,7 +205,7 @@ BOOST_AUTO_TEST_CASE(MountTest) zoneProvision.stop(); } -BOOST_AUTO_TEST_CASE(LinkTest) +BOOST_AUTO_TEST_CASE(Link) { const fs::path linkFile = fs::path("/ut-from-host-file.txt"); @@ -234,7 +234,7 @@ BOOST_AUTO_TEST_CASE(LinkTest) } } -BOOST_AUTO_TEST_CASE(DeclareFileTest) +BOOST_AUTO_TEST_CASE(DeclareFile) { ZoneProvision zoneProvision = create({}); zoneProvision.declareFile(1, "path", 0747, 0777); @@ -252,7 +252,7 @@ BOOST_AUTO_TEST_CASE(DeclareFileTest) BOOST_CHECK_EQUAL(provision.mode, 0777); } -BOOST_AUTO_TEST_CASE(DeclareMountTest) +BOOST_AUTO_TEST_CASE(DeclareMount) { ZoneProvision zoneProvision = create({}); zoneProvision.declareMount("/fake/path1", "/fake/path2", "tmpfs", 077, "fake"); @@ -274,7 +274,7 @@ BOOST_AUTO_TEST_CASE(DeclareMountTest) BOOST_CHECK_EQUAL(provision.data, "fake"); } -BOOST_AUTO_TEST_CASE(DeclareLinkTest) +BOOST_AUTO_TEST_CASE(DeclareLink) { ZoneProvision zoneProvision = create({}); zoneProvision.declareLink("/fake/path1", "/fake/path2"); @@ -290,7 +290,7 @@ BOOST_AUTO_TEST_CASE(DeclareLinkTest) BOOST_CHECK_EQUAL(provision.target, "/fake/path2"); } -BOOST_AUTO_TEST_CASE(ProvisionedAlreadyTest) +BOOST_AUTO_TEST_CASE(ProvisionedAlready) { const fs::path dir = fs::path("/opt/usr/data/ut-from-host"); const fs::path linkFile = fs::path("/ut-from-host-file.txt"); @@ -341,7 +341,7 @@ BOOST_AUTO_TEST_CASE(ProvisionedAlreadyTest) zoneProvision.stop(); } -BOOST_AUTO_TEST_CASE(ListTest) +BOOST_AUTO_TEST_CASE(List) { std::vector expected; ZoneProvision zoneProvision = create({}); @@ -369,7 +369,7 @@ BOOST_AUTO_TEST_CASE(ListTest) } } -BOOST_AUTO_TEST_CASE(RemoveTest) +BOOST_AUTO_TEST_CASE(Remove) { std::vector expected; ZoneProvision zoneProvision = create({}); diff --git a/tests/unit_tests/server/ut-zone.cpp b/tests/unit_tests/server/ut-zone.cpp index 234dabb..722f32c 100644 --- a/tests/unit_tests/server/ut-zone.cpp +++ b/tests/unit_tests/server/ut-zone.cpp @@ -117,27 +117,27 @@ struct Fixture { BOOST_FIXTURE_TEST_SUITE(ZoneSuite, Fixture) -BOOST_AUTO_TEST_CASE(ConstructorDestructorTest) +BOOST_AUTO_TEST_CASE(ConstructorDestructor) { auto c = create(TEST_CONFIG_PATH); c.reset(); } -BOOST_AUTO_TEST_CASE(BuggyConfigTest) +BOOST_AUTO_TEST_CASE(BuggyConfig) { BOOST_REQUIRE_EXCEPTION(create(BUGGY_CONFIG_PATH), ZoneOperationException, WhatEquals("Could not create zone")); } -BOOST_AUTO_TEST_CASE(MissingConfigTest) +BOOST_AUTO_TEST_CASE(MissingConfig) { BOOST_REQUIRE_EXCEPTION(create(MISSING_CONFIG_PATH), ConfigException, WhatEquals("Could not load " + MISSING_CONFIG_PATH)); } -BOOST_AUTO_TEST_CASE(StartStopTest) +BOOST_AUTO_TEST_CASE(StartStop) { auto c = create(TEST_CONFIG_PATH); c->start(); @@ -145,7 +145,7 @@ BOOST_AUTO_TEST_CASE(StartStopTest) c->stop(true); } -BOOST_AUTO_TEST_CASE(DbusConnectionTest) +BOOST_AUTO_TEST_CASE(DbusConnection) { mRunGuard.create("/tmp/ut-run"); // the same path as in lxc template @@ -157,7 +157,7 @@ BOOST_AUTO_TEST_CASE(DbusConnectionTest) // TODO: DbusReconnectionTest -BOOST_AUTO_TEST_CASE(ListNetdevTest) +BOOST_AUTO_TEST_CASE(ListNetdev) { typedef std::vector NetdevList; @@ -173,7 +173,7 @@ BOOST_AUTO_TEST_CASE(ListNetdevTest) BOOST_CHECK(hostNetdevs != netdevs); } -BOOST_AUTO_TEST_CASE(CreateNetdevVethTest) +BOOST_AUTO_TEST_CASE(CreateNetdevVeth) { typedef std::vector NetdevList; @@ -195,7 +195,7 @@ BOOST_AUTO_TEST_CASE(CreateNetdevVethTest) hostNetdevsThrow.begin(), hostNetdevsThrow.end()); } -BOOST_AUTO_TEST_CASE(CreateNetdevMacvlanTest) +BOOST_AUTO_TEST_CASE(CreateNetdevMacvlan) { typedef std::vector NetdevList; diff --git a/tests/unit_tests/server/ut-zones-manager.cpp b/tests/unit_tests/server/ut-zones-manager.cpp index ea858e2..b140e6f 100644 --- a/tests/unit_tests/server/ut-zones-manager.cpp +++ b/tests/unit_tests/server/ut-zones-manager.cpp @@ -481,28 +481,28 @@ struct Fixture { BOOST_FIXTURE_TEST_SUITE(ZonesManagerSuite, Fixture) -BOOST_AUTO_TEST_CASE(ConstructorDestructorTest) +BOOST_AUTO_TEST_CASE(ConstructorDestructor) { std::unique_ptr cm; cm.reset(new ZonesManager(TEST_CONFIG_PATH)); cm.reset(); } -BOOST_AUTO_TEST_CASE(MissingConfigTest) +BOOST_AUTO_TEST_CASE(MissingConfig) { BOOST_REQUIRE_EXCEPTION(ZonesManager{MISSING_CONFIG_PATH}, ConfigException, WhatEquals("Could not load " + MISSING_CONFIG_PATH)); } -BOOST_AUTO_TEST_CASE(CreateTest) +BOOST_AUTO_TEST_CASE(Create) { ZonesManager cm(TEST_CONFIG_PATH); cm.createZone("zone1", SIMPLE_TEMPLATE); cm.createZone("zone2", SIMPLE_TEMPLATE); } -BOOST_AUTO_TEST_CASE(StartStopTest) +BOOST_AUTO_TEST_CASE(StartStop) { ZonesManager cm(TEST_CONFIG_PATH); cm.createZone("zone1", SIMPLE_TEMPLATE); @@ -514,7 +514,7 @@ BOOST_AUTO_TEST_CASE(StartStopTest) BOOST_CHECK_EQUAL(cm.getRunningForegroundZoneId(), ""); } -BOOST_AUTO_TEST_CASE(DetachOnExitTest) +BOOST_AUTO_TEST_CASE(DetachOnExit) { { ZonesManager cm(TEST_CONFIG_PATH); @@ -531,7 +531,7 @@ BOOST_AUTO_TEST_CASE(DetachOnExitTest) } } -BOOST_AUTO_TEST_CASE(FocusTest) +BOOST_AUTO_TEST_CASE(Focus) { ZonesManager cm(TEST_CONFIG_PATH); cm.createZone("zone1", SIMPLE_TEMPLATE); @@ -548,7 +548,7 @@ BOOST_AUTO_TEST_CASE(FocusTest) BOOST_CHECK(cm.getRunningForegroundZoneId() == "zone3"); } -BOOST_AUTO_TEST_CASE(NotifyActiveZoneTest) +BOOST_AUTO_TEST_CASE(NotifyActiveZone) { ZonesManager cm(TEST_CONFIG_PATH); cm.createZone("zone1", DBUS_TEMPLATE); @@ -618,7 +618,7 @@ BOOST_AUTO_TEST_CASE(NotifyActiveZoneTest) dbuses.clear(); } -BOOST_AUTO_TEST_CASE(DisplayOffTest) +BOOST_AUTO_TEST_CASE(DisplayOff) { ZonesManager cm(TEST_CONFIG_PATH); cm.createZone("zone1", DBUS_TEMPLATE); @@ -655,7 +655,7 @@ BOOST_AUTO_TEST_CASE(DisplayOffTest) } } -BOOST_AUTO_TEST_CASE(MoveFileTest) +BOOST_AUTO_TEST_CASE(MoveFile) { ZonesManager cm(TEST_CONFIG_PATH); cm.createZone("zone1", DBUS_TEMPLATE); @@ -757,7 +757,7 @@ BOOST_AUTO_TEST_CASE(MoveFileTest) fs::remove_all(ZONE2PATH, ec); } -BOOST_AUTO_TEST_CASE(AllowSwitchToDefaultTest) +BOOST_AUTO_TEST_CASE(AllowSwitchToDefault) { ZonesManager cm(TEST_CONFIG_PATH); cm.createZone("zone1", DBUS_TEMPLATE); @@ -806,7 +806,7 @@ BOOST_AUTO_TEST_CASE(AllowSwitchToDefaultTest) } } -BOOST_AUTO_TEST_CASE(ProxyCallTest) +BOOST_AUTO_TEST_CASE(ProxyCall) { ZonesManager cm(TEST_CONFIG_PATH); cm.createZone("zone1", DBUS_TEMPLATE); @@ -895,7 +895,7 @@ namespace { "unix:path=/tmp/ut-run/zone3/dbus/system_bus_socket"}}; } // namespace -BOOST_AUTO_TEST_CASE(GetZoneDbusesTest) +BOOST_AUTO_TEST_CASE(GetZoneDbuses) { DbusAccessory host(DbusAccessory::HOST_ID); ZonesManager cm(TEST_CONFIG_PATH); @@ -910,7 +910,7 @@ BOOST_AUTO_TEST_CASE(GetZoneDbusesTest) BOOST_CHECK(EXPECTED_DBUSES_NONE == host.callMethodGetZoneDbuses()); } -BOOST_AUTO_TEST_CASE(GetZoneDbusesNoDbusTest) +BOOST_AUTO_TEST_CASE(GetZoneDbusesNoDbus) { DbusAccessory host(DbusAccessory::HOST_ID); ZonesManager cm(TEST_CONFIG_PATH); @@ -925,7 +925,7 @@ BOOST_AUTO_TEST_CASE(GetZoneDbusesNoDbusTest) BOOST_CHECK(EXPECTED_DBUSES_NONE == host.callMethodGetZoneDbuses()); } -BOOST_AUTO_TEST_CASE(ZoneDbusesSignalsTest) +BOOST_AUTO_TEST_CASE(ZoneDbusesSignals) { Latch signalLatch; DbusAccessory::Dbuses collectedDbuses; @@ -975,7 +975,7 @@ BOOST_AUTO_TEST_CASE(ZoneDbusesSignalsTest) } -BOOST_AUTO_TEST_CASE(GetZoneIdsTest) +BOOST_AUTO_TEST_CASE(GetZoneIds) { ZonesManager cm(TEST_CONFIG_PATH); cm.createZone("zone1", SIMPLE_TEMPLATE); @@ -992,7 +992,7 @@ BOOST_AUTO_TEST_CASE(GetZoneIdsTest) BOOST_CHECK(returnedIds == zoneIds);// order should be preserved } -BOOST_AUTO_TEST_CASE(GetActiveZoneIdTest) +BOOST_AUTO_TEST_CASE(GetActiveZoneId) { ZonesManager cm(TEST_CONFIG_PATH); cm.createZone("zone1", SIMPLE_TEMPLATE); @@ -1015,7 +1015,7 @@ BOOST_AUTO_TEST_CASE(GetActiveZoneIdTest) BOOST_CHECK(dbus.callMethodGetActiveZoneId() == ""); } -BOOST_AUTO_TEST_CASE(SetActiveZoneTest) +BOOST_AUTO_TEST_CASE(SetActiveZone) { ZonesManager cm(TEST_CONFIG_PATH); cm.createZone("zone1", SIMPLE_TEMPLATE); @@ -1044,7 +1044,7 @@ BOOST_AUTO_TEST_CASE(SetActiveZoneTest) WhatEquals("Could not activate stopped or paused zone")); } -BOOST_AUTO_TEST_CASE(CreateDestroyZoneTest) +BOOST_AUTO_TEST_CASE(CreateDestroyZone) { const std::string zone1 = "test1"; const std::string zone2 = "test2"; @@ -1096,7 +1096,7 @@ BOOST_AUTO_TEST_CASE(CreateDestroyZoneTest) BOOST_CHECK_EQUAL(cm.getRunningForegroundZoneId(), ""); } -BOOST_AUTO_TEST_CASE(CreateDestroyZonePersistenceTest) +BOOST_AUTO_TEST_CASE(CreateDestroyZonePersistence) { const std::string zone = "test1"; @@ -1140,7 +1140,7 @@ BOOST_AUTO_TEST_CASE(CreateDestroyZonePersistenceTest) BOOST_CHECK(getZoneIds().empty()); } -BOOST_AUTO_TEST_CASE(ZoneStatePersistenceTest) +BOOST_AUTO_TEST_CASE(ZoneStatePersistence) { const std::string zone1 = "zone1"; const std::string zone2 = "zone2"; @@ -1211,7 +1211,7 @@ BOOST_AUTO_TEST_CASE(ZoneStatePersistenceTest) } } -BOOST_AUTO_TEST_CASE(StartShutdownZoneTest) +BOOST_AUTO_TEST_CASE(StartShutdownZone) { const std::string zone1 = "zone1"; const std::string zone2 = "zone2"; @@ -1251,7 +1251,7 @@ BOOST_AUTO_TEST_CASE(StartShutdownZoneTest) BOOST_CHECK_EQUAL(cm.getRunningForegroundZoneId(), ""); } -BOOST_AUTO_TEST_CASE(LockUnlockZoneTest) +BOOST_AUTO_TEST_CASE(LockUnlockZone) { ZonesManager cm(TEST_CONFIG_PATH); cm.createZone("zone1", DBUS_TEMPLATE); diff --git a/tests/unit_tests/utils/ut-callback-guard.cpp b/tests/unit_tests/utils/ut-callback-guard.cpp index 89787d5..524c7d5 100644 --- a/tests/unit_tests/utils/ut-callback-guard.cpp +++ b/tests/unit_tests/utils/ut-callback-guard.cpp @@ -39,14 +39,14 @@ using namespace vasum::utils; const int unsigned TIMEOUT = 1000; -BOOST_AUTO_TEST_CASE(EmptyTest) +BOOST_AUTO_TEST_CASE(Empty) { CallbackGuard guard; BOOST_CHECK_EQUAL(0, guard.getTrackersCount()); BOOST_CHECK(guard.waitForTrackers(TIMEOUT)); } -BOOST_AUTO_TEST_CASE(SimpleTest) +BOOST_AUTO_TEST_CASE(Simple) { CallbackGuard guard; guard.spawn(); @@ -66,7 +66,7 @@ BOOST_AUTO_TEST_CASE(SimpleTest) BOOST_CHECK(guard.waitForTrackers(TIMEOUT)); } -BOOST_AUTO_TEST_CASE(ThreadTest) +BOOST_AUTO_TEST_CASE(Thread) { Latch trackerCreated; Latch trackerCanBeDestroyed; diff --git a/tests/unit_tests/utils/ut-counting-map.cpp b/tests/unit_tests/utils/ut-counting-map.cpp index 702470f..04832db 100644 --- a/tests/unit_tests/utils/ut-counting-map.cpp +++ b/tests/unit_tests/utils/ut-counting-map.cpp @@ -32,7 +32,7 @@ BOOST_AUTO_TEST_SUITE(CountingMapSuite) using namespace vasum::utils; -BOOST_AUTO_TEST_CASE(CountingTest) +BOOST_AUTO_TEST_CASE(Counting) { CountingMap map; diff --git a/tests/unit_tests/utils/ut-fs.cpp b/tests/unit_tests/utils/ut-fs.cpp index b2defba..cbbe14b 100644 --- a/tests/unit_tests/utils/ut-fs.cpp +++ b/tests/unit_tests/utils/ut-fs.cpp @@ -72,7 +72,7 @@ struct Fixture { BOOST_FIXTURE_TEST_SUITE(UtilsFSSuite, Fixture) -BOOST_AUTO_TEST_CASE(ReadFileContentTest) +BOOST_AUTO_TEST_CASE(ReadFileContent) { BOOST_CHECK_EQUAL(REFERENCE_FILE_CONTENT, readFileContent(REFERENCE_FILE_PATH)); BOOST_CHECK_EXCEPTION(readFileContent(BUGGY_FILE_PATH), @@ -80,20 +80,20 @@ BOOST_AUTO_TEST_CASE(ReadFileContentTest) WhatEquals("Read failed")); } -BOOST_AUTO_TEST_CASE(SaveFileContentTest) +BOOST_AUTO_TEST_CASE(SaveFileContent) { BOOST_REQUIRE(saveFileContent(FILE_PATH, REFERENCE_FILE_CONTENT)); BOOST_CHECK_EQUAL(REFERENCE_FILE_CONTENT, readFileContent(FILE_PATH)); } -BOOST_AUTO_TEST_CASE(RemoveFileTest) +BOOST_AUTO_TEST_CASE(RemoveFile) { BOOST_REQUIRE(saveFileContent(FILE_PATH, REFERENCE_FILE_CONTENT)); BOOST_REQUIRE(removeFile(FILE_PATH)); BOOST_REQUIRE(!boost::filesystem::exists(FILE_PATH)); } -BOOST_AUTO_TEST_CASE(MountPointTest) +BOOST_AUTO_TEST_CASE(MountPoint) { bool result; namespace fs = boost::filesystem; @@ -115,7 +115,7 @@ BOOST_AUTO_TEST_CASE(MountPointTest) BOOST_REQUIRE(fs::remove(MOUNT_POINT_1, ec)); } -BOOST_AUTO_TEST_CASE(MoveFileTest) +BOOST_AUTO_TEST_CASE(MoveFile) { namespace fs = boost::filesystem; boost::system::error_code ec; @@ -150,7 +150,7 @@ BOOST_AUTO_TEST_CASE(MoveFileTest) BOOST_REQUIRE(fs::remove(MOUNT_POINT_2, ec)); } -BOOST_AUTO_TEST_CASE(CopyDirContentsTest) +BOOST_AUTO_TEST_CASE(CopyDirContents) { namespace fs = boost::filesystem; std::string src, src_inner, src_inner2, dst, dst_inner, dst_inner2; diff --git a/tests/unit_tests/utils/ut-glib-loop.cpp b/tests/unit_tests/utils/ut-glib-loop.cpp index 7c5e318..467fbfb 100644 --- a/tests/unit_tests/utils/ut-glib-loop.cpp +++ b/tests/unit_tests/utils/ut-glib-loop.cpp @@ -49,7 +49,7 @@ BOOST_AUTO_TEST_CASE(GlibLoopTest) ScopedGlibLoop loop; } -BOOST_AUTO_TEST_CASE(GlibTimerEventTest) +BOOST_AUTO_TEST_CASE(GlibTimerEvent) { ScopedGlibLoop loop; std::atomic_uint counter(0); diff --git a/tests/unit_tests/utils/ut-paths.cpp b/tests/unit_tests/utils/ut-paths.cpp index bb2b11f..e14da13 100644 --- a/tests/unit_tests/utils/ut-paths.cpp +++ b/tests/unit_tests/utils/ut-paths.cpp @@ -34,7 +34,7 @@ BOOST_AUTO_TEST_SUITE(UtilsPathsSuite) using namespace vasum::utils; -BOOST_AUTO_TEST_CASE(CreateFilePathTest) +BOOST_AUTO_TEST_CASE(CreateFilePath) { BOOST_CHECK_EQUAL("", createFilePath()); @@ -60,7 +60,7 @@ BOOST_AUTO_TEST_CASE(CreateFilePathTest) BOOST_CHECK_EQUAL("a/b/.txt", createFilePath("a", "/b/", "/.txt")); } -BOOST_AUTO_TEST_CASE(DirNameTest) +BOOST_AUTO_TEST_CASE(DirName) { BOOST_CHECK_EQUAL(".", dirName("")); BOOST_CHECK_EQUAL(".", dirName(".")); diff --git a/tests/unit_tests/utils/ut-same-thread-guard.cpp b/tests/unit_tests/utils/ut-same-thread-guard.cpp index 7dbba57..463c07d 100644 --- a/tests/unit_tests/utils/ut-same-thread-guard.cpp +++ b/tests/unit_tests/utils/ut-same-thread-guard.cpp @@ -35,7 +35,7 @@ BOOST_AUTO_TEST_SUITE(SameThreadGuardSuite) using namespace vasum::utils; -BOOST_AUTO_TEST_CASE(SimpleTest) +BOOST_AUTO_TEST_CASE(Simple) { SameThreadGuard guard; BOOST_CHECK(guard.check()); @@ -45,7 +45,7 @@ BOOST_AUTO_TEST_CASE(SimpleTest) BOOST_CHECK(guard.check()); } -BOOST_AUTO_TEST_CASE(ThreadTest) +BOOST_AUTO_TEST_CASE(Thread) { SameThreadGuard guard; diff --git a/tests/unit_tests/utils/ut-value-latch.cpp b/tests/unit_tests/utils/ut-value-latch.cpp index 711c8e6..2b09967 100644 --- a/tests/unit_tests/utils/ut-value-latch.cpp +++ b/tests/unit_tests/utils/ut-value-latch.cpp @@ -58,7 +58,7 @@ namespace }; } // namespace -BOOST_AUTO_TEST_CASE(SimpleTypeTest) +BOOST_AUTO_TEST_CASE(SimpleValue) { ValueLatch testLatch; @@ -71,7 +71,7 @@ BOOST_AUTO_TEST_CASE(SimpleTypeTest) BOOST_REQUIRE_EQUAL(testLatch.get(TIMEOUT), 3); } -BOOST_AUTO_TEST_CASE(ComplexTypeTest) +BOOST_AUTO_TEST_CASE(ComplexValue) { ValueLatch testLatch; @@ -86,7 +86,7 @@ BOOST_AUTO_TEST_CASE(ComplexTypeTest) BOOST_REQUIRE_EQUAL(test.str, TEST_STRING); } -BOOST_AUTO_TEST_CASE(ComplexMovableTypeTest) +BOOST_AUTO_TEST_CASE(ComplexMovableValue) { ValueLatch testLatch; @@ -101,7 +101,7 @@ BOOST_AUTO_TEST_CASE(ComplexMovableTypeTest) BOOST_REQUIRE_EQUAL(test.value.str, TEST_STRING); } -BOOST_AUTO_TEST_CASE(TimeoutTest) +BOOST_AUTO_TEST_CASE(Timeout) { ValueLatch testLatch; @@ -110,7 +110,7 @@ BOOST_AUTO_TEST_CASE(TimeoutTest) WhatEquals("Timeout occured")); } -BOOST_AUTO_TEST_CASE(MultipleSetTest) +BOOST_AUTO_TEST_CASE(MultipleSet) { ValueLatch testLatch; @@ -120,7 +120,7 @@ BOOST_AUTO_TEST_CASE(MultipleSetTest) WhatEquals("Cannot set value multiple times")); } -BOOST_AUTO_TEST_CASE(MultipleGetTest) +BOOST_AUTO_TEST_CASE(MultipleGet) { ValueLatch testLatch; diff --git a/tests/unit_tests/utils/ut-worker.cpp b/tests/unit_tests/utils/ut-worker.cpp index 91fa6b8..da2a96d 100644 --- a/tests/unit_tests/utils/ut-worker.cpp +++ b/tests/unit_tests/utils/ut-worker.cpp @@ -39,12 +39,12 @@ using namespace vasum::utils; const int unsigned TIMEOUT = 1000; -BOOST_AUTO_TEST_CASE(NoTasksTest) +BOOST_AUTO_TEST_CASE(NoTasks) { Worker::Pointer worker = Worker::create(); } -BOOST_AUTO_TEST_CASE(NoTasks2Test) +BOOST_AUTO_TEST_CASE(NoTasksWithSubWorkers) { Worker::Pointer worker = Worker::create(); Worker::Pointer sub1 = worker->createSubWorker(); @@ -55,7 +55,7 @@ BOOST_AUTO_TEST_CASE(NoTasks2Test) worker.reset(); } -BOOST_AUTO_TEST_CASE(SimpleTest) +BOOST_AUTO_TEST_CASE(Simple) { Latch done; @@ -67,7 +67,7 @@ BOOST_AUTO_TEST_CASE(SimpleTest) BOOST_CHECK(done.wait(TIMEOUT)); } -BOOST_AUTO_TEST_CASE(QueueTest) +BOOST_AUTO_TEST_CASE(Queue) { std::mutex mutex; std::string result; @@ -88,7 +88,7 @@ BOOST_AUTO_TEST_CASE(QueueTest) BOOST_CHECK_EQUAL("0123456789", result); } -BOOST_AUTO_TEST_CASE(ThreadResumeTest) +BOOST_AUTO_TEST_CASE(ThreadResume) { Latch done; @@ -112,7 +112,7 @@ BOOST_AUTO_TEST_CASE(ThreadResumeTest) BOOST_CHECK(done.wait(TIMEOUT)); } -BOOST_AUTO_TEST_CASE(SubWorkerTest) +BOOST_AUTO_TEST_CASE(SubWorker) { std::mutex mutex; std::string result; @@ -154,7 +154,7 @@ BOOST_AUTO_TEST_CASE(SubWorkerTest) } } -BOOST_AUTO_TEST_CASE(NoCopyTest) +BOOST_AUTO_TEST_CASE(NoCopy) { typedef std::atomic_int Counter; -- 2.7.4 From b1762a1880ad20cc09a100e4c3c77aca54bfa290 Mon Sep 17 00:00:00 2001 From: Mateusz Malicki Date: Wed, 25 Mar 2015 14:46:14 +0100 Subject: [PATCH 13/16] FIX: compile on x86_64, operator << instead + in log message. [Bug/Feature] Doesn't compile on x86_84 (conversion warning), operator << instead + in log message [Cause] N/A [Solution] N/A [Verification] compile on x86_64 (f.e. tizenorg_common_x86_64_x11) Change-Id: I51e51297eec860c65a19810ea1d4feead7c1d3a8 --- common/netlink/netlink-message.cpp | 2 +- common/netlink/netlink-message.hpp | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/common/netlink/netlink-message.cpp b/common/netlink/netlink-message.cpp index ac42c58..c64199a 100644 --- a/common/netlink/netlink-message.cpp +++ b/common/netlink/netlink-message.cpp @@ -232,7 +232,7 @@ const char* NetlinkResponse::get(int ifla, int len) const throw VasumException("Wrong attribute type"); } if (len >= 0 && rta->rta_len != RTA_LENGTH(len)) { - LOGE("Wrong attribute length, expected: " << rta->rta_len + ", got " << len); + LOGE("Wrong attribute length, expected: " << rta->rta_len << ", got " << len); throw VasumException("Wrong attribute length"); } return reinterpret_cast(RTA_DATA(get(rta->rta_len))); diff --git a/common/netlink/netlink-message.hpp b/common/netlink/netlink-message.hpp index 6b84de4..971e6ad 100644 --- a/common/netlink/netlink-message.hpp +++ b/common/netlink/netlink-message.hpp @@ -149,7 +149,7 @@ public: /** * Fetch attribute */ - NetlinkResponse& fetch(int ifla, std::string& value, int maxSize = std::string::npos); + NetlinkResponse& fetch(int ifla, std::string& value, int maxSize = -1); template NetlinkResponse& fetch(int ifla, T& value); ///@} -- 2.7.4 From ab211e3f6c34d20da3f1ff544cf6478490246869 Mon Sep 17 00:00:00 2001 From: Jan Olszak Date: Mon, 16 Mar 2015 13:28:04 +0100 Subject: [PATCH 14/16] Using libConfig structures for input in server [Feature] Deserialization with libConfig Uint test of libConfig [Cause] N/A [Solution] N/A [Verification] Build, run tests, run tests with valgrind Change-Id: I9c9dfd32bd31ddbde60f35c9317027f41c3faaa3 Signed-off-by: Piotr Bartosiewicz Signed-off-by: Jan Olszak --- common/api/messages.hpp | 412 +++++++------------------ server/host-connection.cpp | 196 +++++------- server/host-connection.hpp | 71 ++--- server/zones-manager.cpp | 255 +++++++-------- server/zones-manager.hpp | 83 ++--- tests/unit_tests/config/testconfig-example.hpp | 8 + tests/unit_tests/config/ut-configuration.cpp | 2 + 7 files changed, 373 insertions(+), 654 deletions(-) diff --git a/common/api/messages.hpp b/common/api/messages.hpp index 6c6d4da..a567975 100644 --- a/common/api/messages.hpp +++ b/common/api/messages.hpp @@ -78,13 +78,19 @@ struct VectorOfStringPairs { typedef api::String ZoneId; typedef api::String Declaration; typedef api::String FileMoveRequestStatus; +typedef api::StringPair GetNetDevAttrsIn; +typedef api::StringPair CreateNetDevPhysIn; +typedef api::StringPair RemoveDeclarationIn; +typedef api::StringPair CreateZoneIn; +typedef api::StringPair RevokeDeviceIn; +typedef api::StringPair DestroyNetDevIn; typedef api::VectorOfStrings ZoneIds; typedef api::VectorOfStrings Declarations; typedef api::VectorOfStrings NetDevList; typedef api::VectorOfStringPairs Dbuses; -typedef api::VectorOfStringPairs NetDevAttrs; +typedef api::VectorOfStringPairs GetNetDevAttrs; -struct ZoneInfo { +struct ZoneInfoOut { std::string id; int vt; std::string state; @@ -99,304 +105,110 @@ struct ZoneInfo { ) }; -// struct MethodSetActiveZoneConfig { -// std::string id; - -// CONFIG_REGISTER -// ( -// id -// ) -// }; - -// struct MethodGetZoneDbusesConfig { -// CONFIG_REGISTER_EMPTY -// }; - -// struct MethodGetZoneIdListConfig { -// CONFIG_REGISTER_EMPTY -// }; - - -// struct MethodGetActiveZoneIdConfig { -// CONFIG_REGISTER_EMPTY -// }; - - -// struct MethodGetZoneInfoConfig { -// std::string id; - -// CONFIG_REGISTER -// ( -// id -// ) -// }; - -// struct MethodSetNetDevAttrsConfig { -// std::string zone; -// std::string netdev; - -// struct Store { -// std::string key; -// std::string value; - -// CONFIG_REGISTER -// ( -// key, -// value -// ) -// }; - -// std::vector attrs; - -// CONFIG_REGISTER -// ( -// zone, -// netdev, -// attrs -// ) -// }; - -// struct MethodGetNetDevAttrsConfig { -// std::string zone; -// std::string netdev; - -// CONFIG_REGISTER -// ( -// zone, -// netdev -// ) -// }; - -// struct MethodGetNetDevListConfig { -// std::string zone; - -// CONFIG_REGISTER -// ( -// zone -// ) -// }; - -// struct MethodCreateNetDevVethConfig { -// std::string id; -// std::string zoneDev; -// std::string hostDev; - -// CONFIG_REGISTER -// ( -// id, -// zoneDev, -// hostDev -// ) -// }; - -// struct MethodCreateNetDevMacvlanConfig { -// std::string id; -// std::string zoneDev; -// std::string hostDev; - -// CONFIG_REGISTER -// ( -// id, -// zoneDev, -// hostDev -// ) -// }; - -// struct MethodCreateNetDevPhysConfig { -// std::string id; -// std::string devId; - -// CONFIG_REGISTER -// ( -// id, -// devId -// ) -// }; - -// struct MethodGetDeclareFileConfig { -// std::string zone; -// int32_t type; -// std::string path; -// int32_t flags; -// int32_t mode; - -// CONFIG_REGISTER -// ( -// zone, -// type, -// path, -// flags, -// mode -// ) -// }; - -// struct MethodGetDeclareMountConfig { -// std::string source; -// std::string zone; -// std::string target; -// uint64_t flags; -// std::string data; - -// CONFIG_REGISTER -// ( -// source, -// zone, -// target, -// flags, -// data -// ) -// }; - -// struct MethodGetDeclareLinkConfig { -// std::string source; -// std::string zone; -// std::string target; - -// CONFIG_REGISTER -// ( -// source, -// zone, -// target -// ) -// }; - -// struct MethodGetDeclarationConfig { -// std::string zone; -// std::string declarationId; - -// CONFIG_REGISTER -// ( -// zone, -// declarationId -// ) -// }; - -// struct MethodRemoveDeclarationConfig { -// std::string id; -// std::string declarationId; - -// CONFIG_REGISTER -// ( -// id, -// declarationId -// ) -// }; - -// struct MethodCreateZoneConfig { -// std::string id; -// std::string templateName; - -// CONFIG_REGISTER -// ( -// id, -// templateName -// ) -// }; - -// struct MethodDestroyZoneConfig { -// std::string id; - -// CONFIG_REGISTER -// ( -// id -// ) -// }; - - -// struct MethodShutdownZoneConfig { -// std::string id; - -// CONFIG_REGISTER -// ( -// id -// ) -// }; - -// struct MethodStartZoneConfig { -// std::string id; - -// CONFIG_REGISTER -// ( -// id -// ) -// }; - -// struct MethodLockZoneConfig { -// std::string id; - -// CONFIG_REGISTER -// ( -// id -// ) -// }; - -// struct MethodUnlockZoneConfig { -// std::string id; - -// CONFIG_REGISTER -// ( -// id -// ) -// }; - -// struct MethodGrantDeviceConfig { -// std::string id; -// std::string device; -// uint32_t flags; - -// CONFIG_REGISTER -// ( -// id, -// device, -// flags -// ) -// }; - -// struct MethodRevokeDeviceConfig { -// std::string id; -// std::string device; - -// CONFIG_REGISTER -// ( -// id, -// device -// ) -// }; - -// TODO: Agregate configs if it makes sense. For example: MethodLockZoneConfig and MethodUnlockZoneConfig - - -// Zone: -// struct MethodNotifyActiveZoneConfig { -// std::string application; -// std::string message; - -// CONFIG_REGISTER -// ( -// application, -// message -// ) -// }; - -// struct MethodFileMoveRequest { -// std::string destination; -// std::string path; - -// CONFIG_REGISTER -// ( -// destination, -// path -// ) -// }; - -// struct MethodFileMoveRequestResult { -// std::string result; - -// CONFIG_REGISTER -// ( -// result -// ) -// }; +struct SetNetDevAttrsIn { + std::string id; // Zone's id + std::string netDev; + std::vector attrs; + + CONFIG_REGISTER + ( + id, + netDev, + attrs + ) +}; + +struct CreateNetDevVethIn { + std::string id; + std::string zoneDev; + std::string hostDev; + + CONFIG_REGISTER + ( + id, + zoneDev, + hostDev + ) +}; + +struct CreateNetDevMacvlanIn { + std::string id; + std::string zoneDev; + std::string hostDev; + uint32_t mode; + + CONFIG_REGISTER + ( + id, + zoneDev, + hostDev, + mode + ) +}; + +struct DeclareFileIn { + std::string zone; + int32_t type; + std::string path; + int32_t flags; + int32_t mode; + + CONFIG_REGISTER + ( + zone, + type, + path, + flags, + mode + ) +}; + +struct DeclareMountIn { + std::string source; + std::string zone; + std::string target; + std::string type; + uint64_t flags; + std::string data; + + CONFIG_REGISTER + ( + source, + zone, + target, + type, + flags, + data + ) +}; + +struct DeclareLinkIn +{ + std::string source; + std::string zone; + std::string target; + + CONFIG_REGISTER + ( + source, + zone, + target + ) +}; + +struct GrantDeviceIn +{ + std::string id; + std::string device; + uint32_t flags; + + CONFIG_REGISTER + ( + id, + device, + flags + ) +}; } // namespace api } // namespace vasum diff --git a/server/host-connection.cpp b/server/host-connection.cpp index d0b612a..993b63d 100644 --- a/server/host-connection.cpp +++ b/server/host-connection.cpp @@ -31,7 +31,7 @@ #include "api/messages.hpp" #include "logger/logger.hpp" - +#include "config/manager.hpp" namespace vasum { @@ -81,9 +81,9 @@ bool HostConnection::waitForName(const unsigned int timeoutMs) std::unique_lock lock(mNameMutex); mNameCondition.wait_for(lock, std::chrono::milliseconds(timeoutMs), - [this] { - return mNameAcquired || mNameLost; - }); + [this] { + return mNameAcquired || mNameLost; + }); return mNameAcquired; } @@ -249,12 +249,12 @@ void HostConnection::onMessageCall(const std::string& objectPath, } if (methodName == api::host::METHOD_SET_ACTIVE_ZONE) { - const gchar* id = NULL; - g_variant_get(parameters, "(&s)", &id); + api::ZoneId zoneId; + config::loadFromGVariant(parameters, zoneId); if (mSetActiveZoneCallback) { auto rb = std::make_shared>(result); - mSetActiveZoneCallback(id, rb); + mSetActiveZoneCallback(zoneId, rb); } return; } @@ -313,261 +313,227 @@ void HostConnection::onMessageCall(const std::string& objectPath, } if (methodName == api::host::METHOD_GET_ZONE_INFO) { - const gchar* id = NULL; - g_variant_get(parameters, "(&s)", &id); + api::ZoneId zoneId; + config::loadFromGVariant(parameters, zoneId); if (mGetZoneInfoCallback) { - auto rb = std::make_shared>(result); - mGetZoneInfoCallback(id, rb); + auto rb = std::make_shared>(result); + mGetZoneInfoCallback(zoneId, rb); } return; } if (methodName == api::host::METHOD_SET_NETDEV_ATTRS) { - const gchar* zone = NULL; - const gchar* netdev = NULL; - GVariantIter* iter; - g_variant_get(parameters, "(&s&sa(ss))", &zone, &netdev, &iter); - gchar* key = NULL; - gchar* value = NULL; - std::vector> attrs; - while (g_variant_iter_loop(iter, "(&s&s)", &key, &value)) { - attrs.push_back(std::make_tuple(key, value)); - } - g_variant_iter_free(iter); + api::SetNetDevAttrsIn data; + config::loadFromGVariant(parameters, data); + if (mSetNetdevAttrsCallback) { auto rb = std::make_shared>(result); - mSetNetdevAttrsCallback(zone, netdev, attrs, rb); + mSetNetdevAttrsCallback(data, rb); } return; } if (methodName == api::host::METHOD_GET_NETDEV_ATTRS) { - const gchar* zone = NULL; - const gchar* netdev = NULL; - g_variant_get(parameters, "(&s&s)", &zone, &netdev); + api::GetNetDevAttrsIn data; + config::loadFromGVariant(parameters, data); + if (mGetNetdevAttrsCallback) { - auto rb = std::make_shared>(result); - mGetNetdevAttrsCallback(zone, netdev, rb); + auto rb = std::make_shared>(result); + mGetNetdevAttrsCallback(data, rb); } return; } if (methodName == api::host::METHOD_GET_NETDEV_LIST) { - const gchar* zone = NULL; - g_variant_get(parameters, "(&s)", &zone); + api::ZoneId data; + config::loadFromGVariant(parameters, data); + if (mGetNetdevListCallback) { - auto rb = std::make_shared>(result); - mGetNetdevListCallback(zone, rb); + auto rb = std::make_shared>(result); + mGetNetdevListCallback(data, rb); } return; } - if (methodName == api::host::METHOD_CREATE_NETDEV_VETH) { - const gchar* id = NULL; - const gchar* zoneDev = NULL; - const gchar* hostDev = NULL; - g_variant_get(parameters, "(&s&s&s)", &id, &zoneDev, &hostDev); + api::CreateNetDevVethIn data; + config::loadFromGVariant(parameters, data); + if (mCreateNetdevVethCallback) { auto rb = std::make_shared>(result); - mCreateNetdevVethCallback(id, zoneDev, hostDev, rb); + mCreateNetdevVethCallback(data, rb); } return; } if (methodName == api::host::METHOD_CREATE_NETDEV_MACVLAN) { - const gchar* id = NULL; - const gchar* zoneDev = NULL; - const gchar* hostDev = NULL; - guint32 mode; - g_variant_get(parameters, "(&s&s&su)", &id, &zoneDev, &hostDev, &mode); + api::CreateNetDevMacvlanIn data; + config::loadFromGVariant(parameters, data); + if (mCreateNetdevMacvlanCallback) { auto rb = std::make_shared>(result); - mCreateNetdevMacvlanCallback(id, zoneDev, hostDev, mode, rb); + mCreateNetdevMacvlanCallback(data, rb); } } if (methodName == api::host::METHOD_CREATE_NETDEV_PHYS) { - const gchar* id = NULL; - const gchar* devId = NULL; - g_variant_get(parameters, "(&s&s)", &id, &devId); + api::CreateNetDevPhysIn data; + config::loadFromGVariant(parameters, data); + if (mCreateNetdevPhysCallback) { auto rb = std::make_shared>(result); - mCreateNetdevPhysCallback(id, devId, rb); + mCreateNetdevPhysCallback(data, rb); } } if (methodName == api::host::METHOD_DESTROY_NETDEV) { - const gchar* id = NULL; - const gchar* devId = NULL; - g_variant_get(parameters, "(&s&s)", &id, &devId); + api::DestroyNetDevIn data; + config::loadFromGVariant(parameters, data); + if (mDestroyNetdevCallback) { auto rb = std::make_shared>(result); - mDestroyNetdevCallback(id, devId, rb); + mDestroyNetdevCallback(data, rb); } } if (methodName == api::host::METHOD_DECLARE_FILE) { - const gchar* zone; - int32_t type; - const gchar* path; - int32_t flags; - int32_t mode; - g_variant_get(parameters, "(&si&sii)", &zone, &type, &path, &flags, &mode); + api::DeclareFileIn data; + config::loadFromGVariant(parameters, data); if (mDeclareFileCallback) { auto rb = std::make_shared>(result); - mDeclareFileCallback(zone, type, path, flags, mode, rb); + mDeclareFileCallback(data, rb); } return; } if (methodName == api::host::METHOD_DECLARE_MOUNT) { - const gchar* source; - const gchar* zone; - const gchar* target; - const gchar* type; - uint64_t flags; - const gchar* data; - g_variant_get(parameters, - "(&s&s&s&st&s)", - &source, - &zone, - &target, - &type, - &flags, - &data); + api::DeclareMountIn data; + config::loadFromGVariant(parameters, data); if (mDeclareMountCallback) { auto rb = std::make_shared>(result); - mDeclareMountCallback(source, zone, target, type, flags, data, rb); + mDeclareMountCallback(data, rb); } return; } if (methodName == api::host::METHOD_DECLARE_LINK) { - const gchar* source; - const gchar* zone; - const gchar* target; - g_variant_get(parameters, "(&s&s&s)", &source, &zone, &target); + api::DeclareLinkIn data; + config::loadFromGVariant(parameters, data); if (mDeclareLinkCallback) { auto rb = std::make_shared>(result); - mDeclareLinkCallback(source, zone, target, rb); + mDeclareLinkCallback(data, rb); } return; } if (methodName == api::host::METHOD_GET_DECLARATIONS) { - const gchar* zone; - g_variant_get(parameters, "(&s)", &zone); + api::ZoneId data; + config::loadFromGVariant(parameters, data); if (mGetDeclarationsCallback) { auto rb = std::make_shared>(result); - mGetDeclarationsCallback(zone, rb); + mGetDeclarationsCallback(data, rb); } return; } if (methodName == api::host::METHOD_REMOVE_DECLARATION) { - const gchar* zone; - const gchar* declarationId; - g_variant_get(parameters, "(&s&s)", &zone, &declarationId); + api::RemoveDeclarationIn data; + config::loadFromGVariant(parameters, data); if (mRemoveDeclarationCallback) { auto rb = std::make_shared>(result); - mRemoveDeclarationCallback(zone, declarationId, rb); + mRemoveDeclarationCallback(data, rb); } return; } if (methodName == api::host::METHOD_CREATE_ZONE) { - const gchar* id = NULL; - const gchar* templateName = NULL; - g_variant_get(parameters, "(&s&s)", &id, &templateName); + api::CreateZoneIn data; + config::loadFromGVariant(parameters, data); if (mCreateZoneCallback) { auto rb = std::make_shared>(result); - mCreateZoneCallback(id, templateName, rb); + mCreateZoneCallback(data, rb); } return; } if (methodName == api::host::METHOD_DESTROY_ZONE) { - const gchar* id = NULL; - g_variant_get(parameters, "(&s)", &id); + api::ZoneId data; + config::loadFromGVariant(parameters, data); if (mDestroyZoneCallback) { auto rb = std::make_shared>(result); - mDestroyZoneCallback(id, rb); + mDestroyZoneCallback(data, rb); } return; } if (methodName == api::host::METHOD_SHUTDOWN_ZONE) { - const gchar* id = NULL; - g_variant_get(parameters, "(&s)", &id); + api::ZoneId data; + config::loadFromGVariant(parameters, data); if (mShutdownZoneCallback) { auto rb = std::make_shared>(result); - mShutdownZoneCallback(id, rb); + mShutdownZoneCallback(data, rb); } } if (methodName == api::host::METHOD_START_ZONE) { - const gchar* id = NULL; - g_variant_get(parameters, "(&s)", &id); + api::ZoneId data; + config::loadFromGVariant(parameters, data); if (mStartZoneCallback) { auto rb = std::make_shared>(result); - mStartZoneCallback(id, rb); + mStartZoneCallback(data, rb); } } if (methodName == api::host::METHOD_LOCK_ZONE) { - const gchar* id = NULL; - g_variant_get(parameters, "(&s)", &id); + api::ZoneId data; + config::loadFromGVariant(parameters, data); if (mLockZoneCallback) { auto rb = std::make_shared>(result); - mLockZoneCallback(id, rb); + mLockZoneCallback(data, rb); } return; } if (methodName == api::host::METHOD_UNLOCK_ZONE) { - const gchar* id = NULL; - g_variant_get(parameters, "(&s)", &id); + api::ZoneId data; + config::loadFromGVariant(parameters, data); if (mUnlockZoneCallback) { auto rb = std::make_shared>(result); - mUnlockZoneCallback(id, rb); + mUnlockZoneCallback(data, rb); } return; } if (methodName == api::host::METHOD_GRANT_DEVICE) { - const gchar* id = NULL; - const gchar* device = NULL; - uint32_t flags; - g_variant_get(parameters, "(&s&su)", &id, &device, &flags); + api::GrantDeviceIn data; + config::loadFromGVariant(parameters, data); if (mGrantDeviceCallback) { auto rb = std::make_shared>(result); - mGrantDeviceCallback(id, device, flags, rb); + mGrantDeviceCallback(data, rb); } return; } if (methodName == api::host::METHOD_REVOKE_DEVICE) { - const gchar* id = NULL; - const gchar* device = NULL; - g_variant_get(parameters, "(&s&s)", &id, &device); + api::RevokeDeviceIn data; + config::loadFromGVariant(parameters, data); if (mRevokeDeviceCallback) { auto rb = std::make_shared>(result); - mRevokeDeviceCallback(id, device, rb); + mRevokeDeviceCallback(data, rb); } return; } @@ -590,7 +556,7 @@ void HostConnection::proxyCallAsync(const std::string& busName, } void HostConnection::signalZoneDbusState(const std::string& zoneId, - const std::string& dbusAddress) + const std::string& dbusAddress) { GVariant* parameters = g_variant_new("(ss)", zoneId.c_str(), dbusAddress.c_str()); mDbusConnection->emitSignal(api::host::OBJECT_PATH, diff --git a/server/host-connection.hpp b/server/host-connection.hpp index 0ef9585..4cb1c8e 100644 --- a/server/host-connection.hpp +++ b/server/host-connection.hpp @@ -28,6 +28,7 @@ #include "dbus/connection.hpp" #include "api/method-result-builder.hpp" +#include "api/messages.hpp" #include #include @@ -60,96 +61,70 @@ public: )> GetZoneIdsCallback; typedef std::function GetActiveZoneIdCallback; - typedef std::function GetZoneInfoCallback; - typedef std::function>& attrs, + typedef std::function SetNetdevAttrsCallback; - typedef std::function GetNetdevAttrsCallback; - typedef std::function GetNetdevListCallback; - typedef std::function CreateNetdevVethCallback; - typedef std::function CreateNetdevMacvlanCallback; - typedef std::function CreateNetdevPhysCallback; - typedef std::function DestroyNetdevCallback; - typedef std::function DeclareFileCallback; - typedef std::function DeclareMountCallback; - typedef std::function DeclareLinkCallback; - typedef std::function GetDeclarationsCallback; - typedef std::function RemoveDeclarationCallback; - typedef std::function SetActiveZoneCallback; - typedef std::function CreateZoneCallback; - typedef std::function DestroyZoneCallback; - typedef std::function ShutdownZoneCallback; - typedef std::function StartZoneCallback; - typedef std::function LockZoneCallback; - typedef std::function UnlockZoneCallback; - typedef std::function GrantDeviceCallback; - typedef std::function RevokeDeviceCallback; diff --git a/server/zones-manager.cpp b/server/zones-manager.cpp index 4266820..67e2b88 100644 --- a/server/zones-manager.cpp +++ b/server/zones-manager.cpp @@ -143,46 +143,46 @@ ZonesManager::ZonesManager(const std::string& configPath) this, _1, _2)); mHostConnection.setSetNetdevAttrsCallback(bind(&ZonesManager::handleSetNetdevAttrsCall, - this, _1, _2, _3, _4)); + this, _1, _2)); mHostConnection.setGetNetdevAttrsCallback(bind(&ZonesManager::handleGetNetdevAttrsCall, - this, _1, _2, _3)); + this, _1, _2)); mHostConnection.setGetNetdevListCallback(bind(&ZonesManager::handleGetNetdevListCall, this, _1, _2)); mHostConnection.setCreateNetdevVethCallback(bind(&ZonesManager::handleCreateNetdevVethCall, - this, _1, _2, _3, _4)); + this, _1, _2)); mHostConnection.setCreateNetdevMacvlanCallback(bind(&ZonesManager::handleCreateNetdevMacvlanCall, - this, _1, _2, _3, _4, _5)); + this, _1, _2)); mHostConnection.setCreateNetdevPhysCallback(bind(&ZonesManager::handleCreateNetdevPhysCall, - this, _1, _2, _3)); + this, _1, _2)); mHostConnection.setDestroyNetdevCallback(bind(&ZonesManager::handleDestroyNetdevCall, - this, _1, _2, _3)); + this, _1, _2)); mHostConnection.setDeclareFileCallback(bind(&ZonesManager::handleDeclareFileCall, - this, _1, _2, _3, _4, _5, _6)); + this, _1, _2)); mHostConnection.setDeclareMountCallback(bind(&ZonesManager::handleDeclareMountCall, - this, _1, _2, _3, _4, _5, _6, _7)); + this, _1, _2)); mHostConnection.setDeclareLinkCallback(bind(&ZonesManager::handleDeclareLinkCall, - this, _1, _2, _3, _4)); + this, _1, _2)); mHostConnection.setGetDeclarationsCallback(bind(&ZonesManager::handleGetDeclarationsCall, this, _1, _2)); mHostConnection.setRemoveDeclarationCallback(bind(&ZonesManager::handleRemoveDeclarationCall, - this, _1, _2, _3)); + this, _1, _2)); mHostConnection.setSetActiveZoneCallback(bind(&ZonesManager::handleSetActiveZoneCall, this, _1, _2)); mHostConnection.setCreateZoneCallback(bind(&ZonesManager::handleCreateZoneCall, - this, _1, _2, _3)); + this, _1, _2)); mHostConnection.setDestroyZoneCallback(bind(&ZonesManager::handleDestroyZoneCall, this, _1, _2)); @@ -200,10 +200,10 @@ ZonesManager::ZonesManager(const std::string& configPath) this, _1, _2)); mHostConnection.setGrantDeviceCallback(bind(&ZonesManager::handleGrantDeviceCall, - this, _1, _2, _3, _4)); + this, _1, _2)); mHostConnection.setRevokeDeviceCallback(bind(&ZonesManager::handleRevokeDeviceCall, - this, _1, _2, _3)); + this, _1, _2)); for (const auto& zoneId : mDynamicConfig.zoneIds) { insertZone(zoneId, getTemplatePathForExistingZone(zoneId)); @@ -778,22 +778,22 @@ void ZonesManager::handleGetActiveZoneIdCall(api::MethodResultBuilder::Pointer r result->set(zoneId); } -void ZonesManager::handleGetZoneInfoCall(const std::string& id, +void ZonesManager::handleGetZoneInfoCall(const api::ZoneId& zoneId, api::MethodResultBuilder::Pointer result) { LOGI("GetZoneInfo call"); Lock lock(mMutex); - auto iter = findZone(id); + auto iter = findZone(zoneId.value); if (iter == mZones.end()) { - LOGE("No zone with id=" << id); + LOGE("No zone with id=" << zoneId.value); result->setError(api::ERROR_INVALID_ID, "No such zone id"); return; } Zone& zone = get(iter); - auto zoneInfo = std::make_shared(); + auto zoneInfo = std::make_shared(); if (zone.isRunning()) { zoneInfo->state = "RUNNING"; @@ -802,7 +802,7 @@ void ZonesManager::handleGetZoneInfoCall(const std::string& id, } else if (zone.isPaused()) { zoneInfo->state = "FROZEN"; } else { - LOGE("Unrecognized state of zone id=" << id); + LOGE("Unrecognized state of zone id=" << zoneId.value); result->setError(api::ERROR_INTERNAL, "Unrecognized state of zone"); return; } @@ -810,18 +810,23 @@ void ZonesManager::handleGetZoneInfoCall(const std::string& id, result->set(zoneInfo); } -void ZonesManager::handleSetNetdevAttrsCall(const std::string& zone, - const std::string& netdev, - const std::vector>& attrs, +void ZonesManager::handleSetNetdevAttrsCall(const api::SetNetDevAttrsIn& data, api::MethodResultBuilder::Pointer result) { LOGI("SetNetdevAttrs call"); try { Lock lock(mMutex); - getZone(zone).setNetdevAttrs(netdev, attrs); + + // TODO: Use vector instead of tuples + std::vector> attrsAsTuples; + for(const auto& entry: data.attrs){ + attrsAsTuples.push_back(std::make_tuple(entry.first, entry.second)); + } + + getZone(data.id).setNetdevAttrs(data.netDev, attrsAsTuples); result->setVoid(); } catch (const InvalidZoneIdException&) { - LOGE("No zone with id=" << zone); + LOGE("No zone with id=" << data.id); result->setError(api::ERROR_INVALID_ID, "No such zone id"); } catch (const VasumException& ex) { LOGE("Can't set attributes: " << ex.what()); @@ -829,22 +834,21 @@ void ZonesManager::handleSetNetdevAttrsCall(const std::string& zone, } } -void ZonesManager::handleGetNetdevAttrsCall(const std::string& zone, - const std::string& netdev, +void ZonesManager::handleGetNetdevAttrsCall(const api::GetNetDevAttrsIn& data, api::MethodResultBuilder::Pointer result) { LOGI("GetNetdevAttrs call"); try { Lock lock(mMutex); - auto netDevAttrs = std::make_shared(); - const auto attrs = getZone(zone).getNetdevAttrs(netdev); + auto netDevAttrs = std::make_shared(); + const auto attrs = getZone(data.first).getNetdevAttrs(data.second); for (size_t i = 0; i < attrs.size(); ++i) { netDevAttrs->values.push_back({std::get<0>(attrs[i]), std::get<1>(attrs[i])}); } result->set(netDevAttrs); } catch (const InvalidZoneIdException&) { - LOGE("No zone with id=" << zone); + LOGE("No zone with id=" << data.first); result->setError(api::ERROR_INVALID_ID, "No such zone id"); } catch (const VasumException& ex) { LOGE("Can't set attributes: " << ex.what()); @@ -852,17 +856,17 @@ void ZonesManager::handleGetNetdevAttrsCall(const std::string& zone, } } -void ZonesManager::handleGetNetdevListCall(const std::string& zone, +void ZonesManager::handleGetNetdevListCall(const api::ZoneId& zoneId, api::MethodResultBuilder::Pointer result) { LOGI("GetNetdevList call"); try { Lock lock(mMutex); auto netDevList = std::make_shared(); - netDevList->values = getZone(zone).getNetdevList(); + netDevList->values = getZone(zoneId.value).getNetdevList(); result->set(netDevList); } catch (const InvalidZoneIdException&) { - LOGE("No zone with id=" << zone); + LOGE("No zone with id=" << zoneId.value); result->setError(api::ERROR_INVALID_ID, "No such zone id"); } catch (const VasumException& ex) { LOGE("Can't set attributes: " << ex.what()); @@ -870,19 +874,17 @@ void ZonesManager::handleGetNetdevListCall(const std::string& zone, } } -void ZonesManager::handleCreateNetdevVethCall(const std::string& zone, - const std::string& zoneDev, - const std::string& hostDev, +void ZonesManager::handleCreateNetdevVethCall(const api::CreateNetDevVethIn& data, api::MethodResultBuilder::Pointer result) { LOGI("CreateNetdevVeth call"); try { Lock lock(mMutex); - getZone(zone).createNetdevVeth(zoneDev, hostDev); + getZone(data.id).createNetdevVeth(data.zoneDev, data.hostDev); result->setVoid(); } catch (const InvalidZoneIdException&) { - LOGE("No zone with id=" << zone); + LOGE("No zone with id=" << data.id); result->setError(api::ERROR_INVALID_ID, "No such zone id"); } catch (const VasumException& ex) { LOGE("Can't create veth: " << ex.what()); @@ -890,20 +892,16 @@ void ZonesManager::handleCreateNetdevVethCall(const std::string& zone, } } -void ZonesManager::handleCreateNetdevMacvlanCall(const std::string& zone, - const std::string& zoneDev, - const std::string& hostDev, - const uint32_t& mode, +void ZonesManager::handleCreateNetdevMacvlanCall(const api::CreateNetDevMacvlanIn& data, api::MethodResultBuilder::Pointer result) { LOGI("CreateNetdevMacvlan call"); try { Lock lock(mMutex); - - getZone(zone).createNetdevMacvlan(zoneDev, hostDev, mode); + getZone(data.id).createNetdevMacvlan(data.zoneDev, data.hostDev, data.mode); result->setVoid(); } catch (const InvalidZoneIdException&) { - LOGE("No zone with id=" << zone); + LOGE("No zone with id=" << data.id); result->setError(api::ERROR_INVALID_ID, "No such zone id"); } catch (const VasumException& ex) { LOGE("Can't create macvlan: " << ex.what()); @@ -911,18 +909,17 @@ void ZonesManager::handleCreateNetdevMacvlanCall(const std::string& zone, } } -void ZonesManager::handleCreateNetdevPhysCall(const std::string& zone, - const std::string& devId, +void ZonesManager::handleCreateNetdevPhysCall(const api::CreateNetDevPhysIn& data, api::MethodResultBuilder::Pointer result) { LOGI("CreateNetdevPhys call"); try { Lock lock(mMutex); - getZone(zone).moveNetdev(devId); + getZone(data.first).moveNetdev(data.second); result->setVoid(); } catch (const InvalidZoneIdException&) { - LOGE("No zone with id=" << zone); + LOGE("No zone with id=" << data.first); result->setError(api::ERROR_INVALID_ID, "No such zone id"); } catch (const VasumException& ex) { LOGE("Can't create netdev: " << ex.what()); @@ -930,18 +927,17 @@ void ZonesManager::handleCreateNetdevPhysCall(const std::string& zone, } } -void ZonesManager::handleDestroyNetdevCall(const std::string& zone, - const std::string& devId, +void ZonesManager::handleDestroyNetdevCall(const api::DestroyNetDevIn& data, api::MethodResultBuilder::Pointer result) { LOGI("DestroyNetdev call"); try { Lock lock(mMutex); - getZone(zone).destroyNetdev(devId); + getZone(data.first).destroyNetdev(data.second); result->setVoid(); } catch (const InvalidZoneIdException&) { - LOGE("No zone with id=" << zone); + LOGE("No zone with id=" << data.first); result->setError(api::ERROR_INVALID_ID, "No such zone id"); } catch (const VasumException& ex) { LOGE("Can't create netdev: " << ex.what()); @@ -949,11 +945,7 @@ void ZonesManager::handleDestroyNetdevCall(const std::string& zone, } } -void ZonesManager::handleDeclareFileCall(const std::string& zone, - const int32_t& type, - const std::string& path, - const int32_t& flags, - const int32_t& mode, +void ZonesManager::handleDeclareFileCall(const api::DeclareFileIn& data, api::MethodResultBuilder::Pointer result) { LOGI("DeclareFile call"); @@ -961,10 +953,10 @@ void ZonesManager::handleDeclareFileCall(const std::string& zone, try { Lock lock(mMutex); auto declaration = std::make_shared(); - declaration->value = getZone(zone).declareFile(type, path, flags, mode); + declaration->value = getZone(data.zone).declareFile(data.type, data.path, data.flags, data.mode); result->set(declaration); } catch (const InvalidZoneIdException&) { - LOGE("No zone with id=" << zone); + LOGE("No zone with id=" << data.zone); result->setError(api::ERROR_INVALID_ID, "No such zone id"); } catch (const config::ConfigException& ex) { LOGE("Can't declare file: " << ex.what()); @@ -972,12 +964,7 @@ void ZonesManager::handleDeclareFileCall(const std::string& zone, } } -void ZonesManager::handleDeclareMountCall(const std::string& source, - const std::string& zone, - const std::string& target, - const std::string& type, - const uint64_t& flags, - const std::string& data, +void ZonesManager::handleDeclareMountCall(const api::DeclareMountIn& data, api::MethodResultBuilder::Pointer result) { LOGI("DeclareMount call"); @@ -985,10 +972,10 @@ void ZonesManager::handleDeclareMountCall(const std::string& source, try { Lock lock(mMutex); auto declaration = std::make_shared(); - declaration->value = getZone(zone).declareMount(source, target, type, flags, data); + declaration->value = getZone(data.zone).declareMount(data.source, data.target, data.type, data.flags, data.data); result->set(declaration); } catch (const InvalidZoneIdException&) { - LOGE("No zone with id=" << zone); + LOGE("No zone with id=" << data.zone); result->setError(api::ERROR_INVALID_ID, "No such zone id"); } catch (const config::ConfigException& ex) { LOGE("Can't declare mount: " << ex.what()); @@ -996,19 +983,17 @@ void ZonesManager::handleDeclareMountCall(const std::string& source, } } -void ZonesManager::handleDeclareLinkCall(const std::string& source, - const std::string& zone, - const std::string& target, +void ZonesManager::handleDeclareLinkCall(const api::DeclareLinkIn& data, api::MethodResultBuilder::Pointer result) { LOGI("DeclareLink call"); try { Lock lock(mMutex); auto declaration = std::make_shared(); - declaration->value = getZone(zone).declareLink(source, target); + declaration->value = getZone(data.zone).declareLink(data.source, data.target); result->set(declaration); } catch (const InvalidZoneIdException&) { - LOGE("No zone with id=" << zone); + LOGE("No zone with id=" << data.zone); result->setError(api::ERROR_INVALID_ID, "No such zone id"); } catch (const config::ConfigException& ex) { LOGE("Can't declare link: " << ex.what()); @@ -1016,17 +1001,17 @@ void ZonesManager::handleDeclareLinkCall(const std::string& source, } } -void ZonesManager::handleGetDeclarationsCall(const std::string& zone, +void ZonesManager::handleGetDeclarationsCall(const api::ZoneId& zoneId, api::MethodResultBuilder::Pointer result) { - LOGI("GetDeclarations call Id=" << zone); + LOGI("GetDeclarations call Id=" << zoneId.value); try { Lock lock(mMutex); auto declarations = std::make_shared(); - declarations->values = getZone(zone).getDeclarations(); + declarations->values = getZone(zoneId.value).getDeclarations(); result->set(declarations); } catch (const InvalidZoneIdException&) { - LOGE("No zone with id=" << zone); + LOGE("No zone with id=" << zoneId.value); result->setError(api::ERROR_INVALID_ID, "No such zone id"); } catch (const VasumException& ex) { LOGE(ex.what()); @@ -1034,19 +1019,16 @@ void ZonesManager::handleGetDeclarationsCall(const std::string& zone, } } -void ZonesManager::handleRemoveDeclarationCall(const std::string& zone, - const std::string& declarationId, +void ZonesManager::handleRemoveDeclarationCall(const api::RemoveDeclarationIn& data, api::MethodResultBuilder::Pointer result) { - LOGI("RemoveDeclaration call Id=" << zone); + LOGI("RemoveDeclaration call Id=" << data.first); try { Lock lock(mMutex); - - getZone(zone).removeDeclaration(declarationId); - + getZone(data.first).removeDeclaration(data.second); result->setVoid(); } catch (const InvalidZoneIdException&) { - LOGE("No zone with id=" << zone); + LOGE("No zone with id=" << data.first); result->setError(api::ERROR_INVALID_ID, "No such zone id"); } catch (const VasumException& ex) { LOGE(ex.what()); @@ -1054,16 +1036,16 @@ void ZonesManager::handleRemoveDeclarationCall(const std::string& zone, } } -void ZonesManager::handleSetActiveZoneCall(const std::string& id, +void ZonesManager::handleSetActiveZoneCall(const api::ZoneId& zoneId, api::MethodResultBuilder::Pointer result) { - LOGI("SetActiveZone call; Id=" << id ); + LOGI("SetActiveZone call; Id=" << zoneId.value ); Lock lock(mMutex); - auto iter = findZone(id); + auto iter = findZone(zoneId.value); if (iter == mZones.end()) { - LOGE("No zone with id=" << id ); + LOGE("No zone with id=" << zoneId.value); result->setError(api::ERROR_INVALID_ID, "No such zone id"); return; } @@ -1208,12 +1190,11 @@ void ZonesManager::createZone(const std::string& id, updateDefaultId(); } -void ZonesManager::handleCreateZoneCall(const std::string& id, - const std::string& templateName, +void ZonesManager::handleCreateZoneCall(const api::CreateZoneIn& data, api::MethodResultBuilder::Pointer result) { try { - createZone(id, templateName); + createZone(data.first, data.second); result->setVoid(); } catch (const InvalidZoneIdException& e) { result->setError(api::ERROR_INVALID_ID, "Existing or invalid zone id"); @@ -1222,16 +1203,15 @@ void ZonesManager::handleCreateZoneCall(const std::string& id, } } -void ZonesManager::handleDestroyZoneCall(const std::string& id, +void ZonesManager::handleDestroyZoneCall(const api::ZoneId& zoneId, api::MethodResultBuilder::Pointer result) { - auto destroyer = [id, result, this] { + auto destroyer = [zoneId, result, this] { try { - LOGI("Destroying zone " << id); - - destroyZone(id); + LOGI("Destroying zone " << zoneId.value); + destroyZone(zoneId.value); } catch (const InvalidZoneIdException&) { - LOGE("Failed to destroy zone - no such zone id: " << id); + LOGE("Failed to destroy zone - no such zone id: " << zoneId.value); result->setError(api::ERROR_INVALID_ID, "No such zone id"); } catch (const VasumException& e) { LOGE("Error during zone destruction: " << e.what()); @@ -1244,19 +1224,19 @@ void ZonesManager::handleDestroyZoneCall(const std::string& id, mWorker->addTask(destroyer); } -void ZonesManager::handleShutdownZoneCall(const std::string& id, +void ZonesManager::handleShutdownZoneCall(const api::ZoneId& zoneId, api::MethodResultBuilder::Pointer result) { - LOGI("ShutdownZone call; Id=" << id ); + LOGI("ShutdownZone call; Id=" << zoneId.value); - auto shutdown = [id, result, this] { + auto shutdown = [zoneId, result, this] { try { - LOGT("Shutdown zone " << id); + LOGT("Shutdown zone " << zoneId.value); Lock lock(mMutex); - auto iter = findZone(id); + auto iter = findZone(zoneId.value); if (iter == mZones.end()) { - LOGE("Failed to shutdown zone - no such zone id: " << id); + LOGE("Failed to shutdown zone - no such zone id: " << zoneId.value); result->setError(api::ERROR_INVALID_ID, "No such zone id"); return; } @@ -1273,19 +1253,19 @@ void ZonesManager::handleShutdownZoneCall(const std::string& id, mWorker->addTask(shutdown); } -void ZonesManager::handleStartZoneCall(const std::string& id, +void ZonesManager::handleStartZoneCall(const api::ZoneId& zoneId, api::MethodResultBuilder::Pointer result) { - LOGI("StartZone call; Id=" << id ); + LOGI("StartZone call; Id=" << zoneId.value); - auto startAsync = [this, id, result]() { + auto startAsync = [this, zoneId, result]() { try { - LOGT("Start zone " << id ); + LOGT("Start zone " << zoneId.value); Lock lock(mMutex); - auto iter = findZone(id); + auto iter = findZone(zoneId.value); if (iter == mZones.end()) { - LOGE("Failed to start zone - no such zone id: " << id); + LOGE("Failed to start zone - no such zone id: " << zoneId.value); result->setError(api::ERROR_INVALID_ID, "No such zone id"); return; } @@ -1293,30 +1273,30 @@ void ZonesManager::handleStartZoneCall(const std::string& id, focusInternal(iter); result->setVoid(); } catch (const std::exception& e) { - LOGE(id << ": failed to start: " << e.what()); + LOGE(zoneId.value << ": failed to start: " << e.what()); result->setError(api::ERROR_INTERNAL, "Failed to start zone"); } }; mWorker->addTask(startAsync); } -void ZonesManager::handleLockZoneCall(const std::string& id, +void ZonesManager::handleLockZoneCall(const api::ZoneId& zoneId, api::MethodResultBuilder::Pointer result) { - LOGI("LockZone call; Id=" << id ); + LOGI("LockZone call; Id=" << zoneId.value ); Lock lock(mMutex); - auto iter = findZone(id); + auto iter = findZone(zoneId.value); if (iter == mZones.end()) { - LOGE("Failed to lock zone - no such zone id: " << id); + LOGE("Failed to lock zone - no such zone id: " << zoneId.value); result->setError(api::ERROR_INVALID_ID, "No such zone id"); return; } Zone& zone = get(iter); if (!zone.isRunning()) { - LOGE("Zone id=" << id << " is not running."); + LOGE("Zone id=" << zoneId.value << " is not running."); result->setError(api::ERROR_INVALID_STATE, "Zone is not running"); return; } @@ -1335,23 +1315,23 @@ void ZonesManager::handleLockZoneCall(const std::string& id, result->setVoid(); } -void ZonesManager::handleUnlockZoneCall(const std::string& id, +void ZonesManager::handleUnlockZoneCall(const api::ZoneId& zoneId, api::MethodResultBuilder::Pointer result) { - LOGI("UnlockZone call; Id=" << id ); + LOGI("UnlockZone call; Id=" << zoneId.value ); Lock lock(mMutex); - auto iter = findZone(id); + auto iter = findZone(zoneId.value); if (iter == mZones.end()) { - LOGE("Failed to unlock zone - no such zone id: " << id); + LOGE("Failed to unlock zone - no such zone id: " << zoneId.value); result->setError(api::ERROR_INVALID_ID, "No such zone id"); return; } Zone& zone = get(iter); if (!zone.isPaused()) { - LOGE("Zone id=" << id << " is not paused."); + LOGE("Zone id=" << zoneId.value << " is not paused."); result->setError(api::ERROR_INVALID_STATE, "Zone is not paused"); return; } @@ -1368,40 +1348,38 @@ void ZonesManager::handleUnlockZoneCall(const std::string& id, result->setVoid(); } -void ZonesManager::handleGrantDeviceCall(const std::string& id, - const std::string& device, - uint32_t flags, +void ZonesManager::handleGrantDeviceCall(const api::GrantDeviceIn& data, api::MethodResultBuilder::Pointer result) { - LOGI("GrantDevice call; id=" << id << "; dev=" << device); + LOGI("GrantDevice call; id=" << data.id << "; dev=" << data.device); Lock lock(mMutex); - auto iter = findZone(id); + auto iter = findZone(data.id); if (iter == mZones.end()) { - LOGE("Failed to grant device - no such zone id: " << id); + LOGE("Failed to grant device - no such zone id: " << data.id); result->setError(api::ERROR_INVALID_ID, "No such zone id"); return; } Zone& zone = get(iter); if (!zone.isRunning() && !zone.isPaused()) { - LOGE("Zone id=" << id << " is not running"); + LOGE("Zone id=" << data.id << " is not running"); result->setError(api::ERROR_INVALID_STATE, "Zone is not running"); return; } - std::string devicePath = "/dev/" + device; + std::string devicePath = "/dev/" + data.device; if (!lxc::isDevice(devicePath)) { - LOGE("Failed to grant device - cannot acces device: " << device); + LOGE("Failed to grant device - cannot acces device: " << data.device); result->setError(api::ERROR_FORBIDDEN, "Cannot access device"); return; } // assume device node is created inside zone - if (!lxc::setDeviceAccess(id, devicePath, true, flags)) { - LOGE("Failed to grant device: " << device << " for zone: " << id); + if (!lxc::setDeviceAccess(data.id, devicePath, true, data.flags)) { + LOGE("Failed to grant device: " << data.device << " for zone: " << data.id); result->setError(api::ERROR_INTERNAL, "Cannot grant device"); return; } @@ -1409,37 +1387,36 @@ void ZonesManager::handleGrantDeviceCall(const std::string& id, result->setVoid(); } -void ZonesManager::handleRevokeDeviceCall(const std::string& id, - const std::string& device, +void ZonesManager::handleRevokeDeviceCall(const api::RevokeDeviceIn& data, api::MethodResultBuilder::Pointer result) { - LOGI("RevokeDevice call; id=" << id << "; dev=" << device); + LOGI("RevokeDevice call; id=" << data.first << "; dev=" << data.second); Lock lock(mMutex); - auto iter = findZone(id); + auto iter = findZone(data.first); if (iter == mZones.end()) { - LOGE("Failed to revoke device - no such zone id: " << id); + LOGE("Failed to revoke device - no such zone id: " << data.first); result->setError(api::ERROR_INVALID_ID, "No such zone id"); return; } Zone& zone = get(iter); if (!zone.isRunning() && !zone.isPaused()) { - LOGE("Zone id=" << id << " is not running"); + LOGE("Zone id=" << data.first << " is not running"); result->setError(api::ERROR_INVALID_STATE, "Zone is not running"); return; } - std::string devicePath = "/dev/" + device; + std::string devicePath = "/dev/" + data.second; if (!lxc::isDevice(devicePath)) { - LOGE("Failed to revoke device - cannot acces device: " << device); + LOGE("Failed to revoke device - cannot acces device: " << data.second); result->setError(api::ERROR_FORBIDDEN, "Cannot access device"); return; } - if (!lxc::setDeviceAccess(id, devicePath, false, 0)) { - LOGE("Failed to revoke device: " << device << " for zone: " << id); + if (!lxc::setDeviceAccess(data.first, devicePath, false, 0)) { + LOGE("Failed to revoke device: " << data.second << " for zone: " << data.first); result->setError(api::ERROR_INTERNAL, "Cannot revoke device"); return; } diff --git a/server/zones-manager.hpp b/server/zones-manager.hpp index deb9b9d..ae89566 100644 --- a/server/zones-manager.hpp +++ b/server/zones-manager.hpp @@ -146,15 +146,16 @@ private: int getVTForNewZone(); void insertZone(const std::string& zoneId, const std::string& templatePath); + // Zone's handlers--------------------------------------------------------- void handleNotifyActiveZoneCall(const std::string& caller, const std::string& appliaction, const std::string& message, api::MethodResultBuilder::Pointer result); void handleDisplayOffCall(const std::string& caller); void handleFileMoveCall(const std::string& srcZoneId, - const std::string& dstZoneId, - const std::string& path, - api::MethodResultBuilder::Pointer result); + const std::string& dstZoneId, + const std::string& path, + api::MethodResultBuilder::Pointer result); void handleProxyCall(const std::string& caller, const std::string& target, const std::string& targetBusName, @@ -164,77 +165,55 @@ private: GVariant* parameters, dbus::MethodResultBuilder::Pointer result); void handleGetZoneDbusesCall(api::MethodResultBuilder::Pointer result); - void handleDbusStateChanged(const std::string& zoneId, const std::string& dbusAddress); + + void handleDbusStateChanged(const std::string& zoneId, + const std::string& dbusAddress); + // Host's handlers -------------------------------------------------------- void handleGetZoneIdsCall(api::MethodResultBuilder::Pointer result); void handleGetActiveZoneIdCall(api::MethodResultBuilder::Pointer result); - void handleGetZoneInfoCall(const std::string& id, api::MethodResultBuilder::Pointer result); - void handleSetNetdevAttrsCall(const std::string& zone, - const std::string& netdev, - const std::vector>& attrs, + void handleGetZoneInfoCall(const api::ZoneId& data, + api::MethodResultBuilder::Pointer result); + void handleSetNetdevAttrsCall(const api::SetNetDevAttrsIn& data, api::MethodResultBuilder::Pointer result); - void handleGetNetdevAttrsCall(const std::string& zone, - const std::string& netdev, + void handleGetNetdevAttrsCall(const api::GetNetDevAttrsIn& data, api::MethodResultBuilder::Pointer result); - void handleGetNetdevListCall(const std::string& zone, + void handleGetNetdevListCall(const api::ZoneId& data, api::MethodResultBuilder::Pointer result); - void handleCreateNetdevVethCall(const std::string& zone, - const std::string& zoneDev, - const std::string& hostDev, + void handleCreateNetdevVethCall(const api::CreateNetDevVethIn& data, api::MethodResultBuilder::Pointer result); - void handleCreateNetdevMacvlanCall(const std::string& zone, - const std::string& zoneDev, - const std::string& hostDev, - const uint32_t& mode, + void handleCreateNetdevMacvlanCall(const api::CreateNetDevMacvlanIn& data, api::MethodResultBuilder::Pointer result); - void handleCreateNetdevPhysCall(const std::string& zone, - const std::string& devId, + void handleCreateNetdevPhysCall(const api::CreateNetDevPhysIn& data, api::MethodResultBuilder::Pointer result); - void handleDestroyNetdevCall(const std::string& zone, - const std::string& devId, + void handleDestroyNetdevCall(const api::DestroyNetDevIn& data, api::MethodResultBuilder::Pointer result); - void handleDeclareFileCall(const std::string& zone, - const int32_t& type, - const std::string& path, - const int32_t& flags, - const int32_t& mode, + void handleDeclareFileCall(const api::DeclareFileIn& data, api::MethodResultBuilder::Pointer result); - void handleDeclareMountCall(const std::string& source, - const std::string& zone, - const std::string& target, - const std::string& type, - const uint64_t& flags, - const std::string& data, + void handleDeclareMountCall(const api::DeclareMountIn& data, api::MethodResultBuilder::Pointer result); - void handleDeclareLinkCall(const std::string& source, - const std::string& zone, - const std::string& target, + void handleDeclareLinkCall(const api::DeclareLinkIn& data, api::MethodResultBuilder::Pointer result); - void handleGetDeclarationsCall(const std::string& zone, + void handleGetDeclarationsCall(const api::ZoneId& data, api::MethodResultBuilder::Pointer result); - void handleRemoveDeclarationCall(const std::string& zone, - const std::string& declarationId, + void handleRemoveDeclarationCall(const api::RemoveDeclarationIn& data, api::MethodResultBuilder::Pointer result); - void handleSetActiveZoneCall(const std::string& id, + void handleSetActiveZoneCall(const api::ZoneId& data, api::MethodResultBuilder::Pointer result); - void handleCreateZoneCall(const std::string& id, - const std::string& templateName, + void handleCreateZoneCall(const api::CreateZoneIn& data, api::MethodResultBuilder::Pointer result); - void handleDestroyZoneCall(const std::string& id, + void handleDestroyZoneCall(const api::ZoneId& data, api::MethodResultBuilder::Pointer result); - void handleShutdownZoneCall(const std::string& id, + void handleShutdownZoneCall(const api::ZoneId& data, api::MethodResultBuilder::Pointer result); - void handleStartZoneCall(const std::string& id, + void handleStartZoneCall(const api::ZoneId& data, api::MethodResultBuilder::Pointer result); - void handleLockZoneCall(const std::string& id, + void handleLockZoneCall(const api::ZoneId& data, api::MethodResultBuilder::Pointer result); - void handleUnlockZoneCall(const std::string& id, + void handleUnlockZoneCall(const api::ZoneId& data, api::MethodResultBuilder::Pointer result); - void handleGrantDeviceCall(const std::string& id, - const std::string& device, - uint32_t flags, + void handleGrantDeviceCall(const api::GrantDeviceIn& data, api::MethodResultBuilder::Pointer result); - void handleRevokeDeviceCall(const std::string& id, - const std::string& device, + void handleRevokeDeviceCall(const api::RevokeDeviceIn& data, api::MethodResultBuilder::Pointer result); }; diff --git a/tests/unit_tests/config/testconfig-example.hpp b/tests/unit_tests/config/testconfig-example.hpp index 6c14719..ff5c2ef 100644 --- a/tests/unit_tests/config/testconfig-example.hpp +++ b/tests/unit_tests/config/testconfig-example.hpp @@ -84,6 +84,8 @@ struct TestConfig { int intVal; std::int64_t int64Val; + std::uint32_t uint32Val; + std::uint64_t uint64Val; std::string stringVal; double doubleVal; bool boolVal; @@ -104,6 +106,8 @@ struct TestConfig { ( intVal, int64Val, + uint32Val, + uint64Val, stringVal, doubleVal, boolVal, @@ -142,6 +146,8 @@ struct PartialTestConfig { const std::string jsonTestString = "{ \"intVal\": 12345, " "\"int64Val\": -1234567890123456789, " + "\"uint32Val\": 123456, " + "\"uint64Val\": 1234567890123456789, " "\"stringVal\": \"blah\", " "\"doubleVal\": -1.234000, " "\"boolVal\": true, " @@ -163,6 +169,8 @@ const std::string jsonTestString = const std::string jsonEmptyTestString = "{ \"intVal\": 0, " "\"int64Val\": 0, " + "\"uint32Val\": 0, " + "\"uint64Val\": 0, " "\"stringVal\": \"\", " "\"boolVal\": false, " "\"emptyIntVector\": [ ], " diff --git a/tests/unit_tests/config/ut-configuration.cpp b/tests/unit_tests/config/ut-configuration.cpp index a9a5332..1334966 100644 --- a/tests/unit_tests/config/ut-configuration.cpp +++ b/tests/unit_tests/config/ut-configuration.cpp @@ -60,6 +60,8 @@ BOOST_AUTO_TEST_CASE(FromJsonString) BOOST_CHECK_EQUAL(12345, testConfig.intVal); BOOST_CHECK_EQUAL(-1234567890123456789ll, testConfig.int64Val); + BOOST_CHECK_EQUAL(123456, testConfig.uint32Val); + BOOST_CHECK_EQUAL(1234567890123456789ll, testConfig.uint64Val); BOOST_CHECK_EQUAL("blah", testConfig.stringVal); BOOST_CHECK_CLOSE(-1.234, testConfig.doubleVal, TOLERANCE); BOOST_CHECK_EQUAL(true, testConfig.boolVal); -- 2.7.4 From 70a84ae9b6a4d2f7288cfce840b5b536fa917e2c Mon Sep 17 00:00:00 2001 From: Mateusz Malicki Date: Tue, 17 Mar 2015 15:55:16 +0100 Subject: [PATCH 15/16] Possibility to remove ipv4/ipv6 addresses from interface [Feature] Possibility to remove ipv4/ipv6 addresses from interface [Cause] N/A [Solution] Implemented: vsm_netdev_del_ipv4_addr, vsm_netdev_del_ipv6_addr [Verification] Build, run test Change-Id: If1e43c73f443e5480e5f1794a1d1f29fa78c3dd3 --- client/vasum-client-impl.cpp | 38 +++++++++++++++++++++ client/vasum-client-impl.hpp | 16 +++++++++ client/vasum-client.cpp | 18 ++++++++++ client/vasum-client.h | 38 +++++++++++++++++++-- common/api/messages.hpp | 13 ++++++++ server/host-connection.cpp | 14 ++++++++ server/host-connection.hpp | 9 +++++ server/host-dbus-definitions.hpp | 66 ++++++++++++++++++++----------------- server/netdev.cpp | 56 +++++++++++++++++++++++++++++++ server/netdev.hpp | 5 +++ server/zone-admin.cpp | 5 +++ server/zone-admin.hpp | 5 +++ server/zone.cpp | 6 ++++ server/zone.hpp | 5 +++ server/zones-manager.cpp | 20 +++++++++++ server/zones-manager.hpp | 2 ++ tests/unit_tests/server/ut-zone.cpp | 47 +++++++++++++++++++++++--- 17 files changed, 325 insertions(+), 38 deletions(-) diff --git a/client/vasum-client-impl.cpp b/client/vasum-client-impl.cpp index 1de4de0..0c5482a 100644 --- a/client/vasum-client-impl.cpp +++ b/client/vasum-client-impl.cpp @@ -744,6 +744,44 @@ VsmStatus Client::vsm_netdev_set_ipv6_addr(const char* zone, } } +VsmStatus Client::vsm_netdev_del_ipv4_addr(const char* zone, + const char* netdevId, + struct in_addr* addr, + int prefix) noexcept +{ + std::string ip; + try { + //CIDR notation + ip = toString(addr) + "/" + to_string(prefix); + } catch(const std::exception& ex) { + mStatus = Status(VSMCLIENT_INVALID_ARGUMENT, ex.what()); + return vsm_get_status(); + } + + GVariant* args_in = g_variant_new("(sss)", zone, netdevId, ip.c_str()); + return callMethod(HOST_INTERFACE, api::host::METHOD_DELETE_NETDEV_IP_ADDRESS, args_in); +} + +VsmStatus Client::vsm_netdev_del_ipv6_addr(const char* zone, + const char* netdevId, + struct in6_addr* addr, + int prefix) noexcept +{ + + std::string ip; + try { + //CIDR notation + ip = toString(addr) + "/" + to_string(prefix); + } catch(const std::exception& ex) { + mStatus = Status(VSMCLIENT_INVALID_ARGUMENT, ex.what()); + return vsm_get_status(); + } + + GVariant* args_in = g_variant_new("(sss)", zone, netdevId, ip.c_str()); + return callMethod(HOST_INTERFACE, api::host::METHOD_DELETE_NETDEV_IP_ADDRESS, args_in); +} + + VsmStatus Client::vsm_netdev_up(const char* zone, const char* netdevId) noexcept { try { diff --git a/client/vasum-client-impl.hpp b/client/vasum-client-impl.hpp index 1493a00..4e01966 100644 --- a/client/vasum-client-impl.hpp +++ b/client/vasum-client-impl.hpp @@ -235,6 +235,22 @@ public: int prefix) noexcept; /** + * @see ::vsm_netdev_del_ipv4_addr + */ + VsmStatus vsm_netdev_del_ipv4_addr(const char* zone, + const char* netdevId, + struct in_addr* addr, + int prefix) noexcept; + + /** + * @see ::vsm_netdev_del_ipv6_addr + */ + VsmStatus vsm_netdev_del_ipv6_addr(const char* zone, + const char* netdevId, + struct in6_addr* addr, + int prefix) noexcept; + + /** * @see ::vsm_netdev_up */ VsmStatus vsm_netdev_up(const char* zone, const char* netdevId) noexcept; diff --git a/client/vasum-client.cpp b/client/vasum-client.cpp index 9c0ca60..c12e8c6 100644 --- a/client/vasum-client.cpp +++ b/client/vasum-client.cpp @@ -250,6 +250,24 @@ API VsmStatus vsm_netdev_set_ipv6_addr(VsmClient client, return getClient(client).vsm_netdev_set_ipv6_addr(zone, netdevId, addr, prefix); } +API VsmStatus vsm_netdev_del_ipv4_addr(VsmClient client, + const char* zone, + const char* netdevId, + struct in_addr* addr, + int prefix) +{ + return getClient(client).vsm_netdev_del_ipv4_addr(zone, netdevId, addr, prefix); +} + +API VsmStatus vsm_netdev_del_ipv6_addr(VsmClient client, + const char* zone, + const char* netdevId, + struct in6_addr* addr, + int prefix) +{ + return getClient(client).vsm_netdev_del_ipv6_addr(zone, netdevId, addr, prefix); +} + API VsmStatus vsm_netdev_up(VsmClient client, const char* zone, const char* netdevId) diff --git a/client/vasum-client.h b/client/vasum-client.h index 18af990..c252b32 100644 --- a/client/vasum-client.h +++ b/client/vasum-client.h @@ -552,6 +552,38 @@ VsmStatus vsm_netdev_set_ipv6_addr(VsmClient client, int prefix); /** + * Remove ipv4 address from netdev + * + * @param[in] client vasum-server's client + * @param[in] zone zone name + * @param[in] netdevId network device id + * @param[in] addr ipv4 address + * @param[in] prefix bit-length of the network prefix + * @return status of this function call + */ +VsmStatus vsm_netdev_del_ipv4_addr(VsmClient client, + const char* zone, + const char* netdevId, + struct in_addr* addr, + int prefix); + +/** + * Remove ipv6 address from netdev + * + * @param[in] client vasum-server's client + * @param[in] zone zone name + * @param[in] netdevId network device id + * @param[in] addr ipv6 address + * @param[in] prefix bit-length of the network prefix + * @return status of this function call + */ +VsmStatus vsm_netdev_del_ipv6_addr(VsmClient client, + const char* zone, + const char* netdevId, + struct in6_addr* addr, + int prefix); + +/** * Turn up a network device in the zone * * @param[in] client vasum-server's client @@ -750,9 +782,9 @@ VsmStatus vsm_remove_declaration(VsmClient client, * @param data custom user's data pointer passed to vsm_add_notification_callback() */ typedef void (*VsmNotificationCallback)(const char* zone, - const char* application, - const char* message, - void* data); + const char* application, + const char* message, + void* data); /** * Send message to active zone. * diff --git a/common/api/messages.hpp b/common/api/messages.hpp index a567975..de193bd 100644 --- a/common/api/messages.hpp +++ b/common/api/messages.hpp @@ -146,6 +146,19 @@ struct CreateNetDevMacvlanIn { ) }; +struct DeleteNetdevIpAddressIn { + std::string zone; + std::string netdev; + std::string ip; + + CONFIG_REGISTER + ( + zone, + netdev, + ip + ) +}; + struct DeclareFileIn { std::string zone; int32_t type; diff --git a/server/host-connection.cpp b/server/host-connection.cpp index 993b63d..f3cbfa0 100644 --- a/server/host-connection.cpp +++ b/server/host-connection.cpp @@ -167,6 +167,11 @@ void HostConnection::setDestroyNetdevCallback(const DestroyNetdevCallback& callb mDestroyNetdevCallback = callback; } +void HostConnection::setDeleleNetdevIpAddressCallback(const DeleteNetdevIpAddressCallback& callback) +{ + mDeleteNetdevIpAddressCallback = callback; +} + void HostConnection::setDeclareFileCallback(const DeclareFileCallback& callback) { mDeclareFileCallback = callback; @@ -397,6 +402,15 @@ void HostConnection::onMessageCall(const std::string& objectPath, } } + if (methodName == api::host::METHOD_DELETE_NETDEV_IP_ADDRESS) { + api::DeleteNetdevIpAddressIn data; + config::loadFromGVariant(parameters, data); + if (mDeleteNetdevIpAddressCallback) { + auto rb = std::make_shared>(result); + mDeleteNetdevIpAddressCallback(data, rb); + } + } + if (methodName == api::host::METHOD_DECLARE_FILE) { api::DeclareFileIn data; config::loadFromGVariant(parameters, data); diff --git a/server/host-connection.hpp b/server/host-connection.hpp index 4cb1c8e..4ad07c8 100644 --- a/server/host-connection.hpp +++ b/server/host-connection.hpp @@ -82,6 +82,9 @@ public: typedef std::function CreateNetdevPhysCallback; + typedef std::function DeleteNetdevIpAddressCallback; typedef std::function DestroyNetdevCallback; @@ -194,6 +197,11 @@ public: void setDestroyNetdevCallback(const DestroyNetdevCallback& callback); /** + * Register a callback called to remove ip address from netdev + */ + void setDeleleNetdevIpAddressCallback(const DeleteNetdevIpAddressCallback& callback); + + /** * Register a callback called to declare file */ void setDeclareFileCallback(const DeclareFileCallback& callback); @@ -291,6 +299,7 @@ private: CreateNetdevMacvlanCallback mCreateNetdevMacvlanCallback; CreateNetdevPhysCallback mCreateNetdevPhysCallback; DestroyNetdevCallback mDestroyNetdevCallback; + DeleteNetdevIpAddressCallback mDeleteNetdevIpAddressCallback; DeclareFileCallback mDeclareFileCallback; DeclareMountCallback mDeclareMountCallback; DeclareLinkCallback mDeclareLinkCallback; diff --git a/server/host-dbus-definitions.hpp b/server/host-dbus-definitions.hpp index 2ac5745..1e6fecc 100644 --- a/server/host-dbus-definitions.hpp +++ b/server/host-dbus-definitions.hpp @@ -32,39 +32,40 @@ namespace vasum { namespace api { namespace host { -const std::string BUS_NAME = "org.tizen.vasum.host"; -const std::string OBJECT_PATH = "/org/tizen/vasum/host"; -const std::string INTERFACE = "org.tizen.vasum.host.manager"; +const std::string BUS_NAME = "org.tizen.vasum.host"; +const std::string OBJECT_PATH = "/org/tizen/vasum/host"; +const std::string INTERFACE = "org.tizen.vasum.host.manager"; -const std::string ERROR_ZONE_NOT_RUNNING = "org.tizen.vasum.host.Error.ZonesNotRunning"; +const std::string ERROR_ZONE_NOT_RUNNING = "org.tizen.vasum.host.Error.ZonesNotRunning"; -const std::string METHOD_GET_ZONE_DBUSES = "GetZoneDbuses"; -const std::string METHOD_GET_ZONE_ID_LIST = "GetZoneIds"; -const std::string METHOD_GET_ACTIVE_ZONE_ID = "GetActiveZoneId"; -const std::string METHOD_GET_ZONE_INFO = "GetZoneInfo"; -const std::string METHOD_SET_NETDEV_ATTRS = "SetNetdevAttrs"; -const std::string METHOD_GET_NETDEV_ATTRS = "GetNetdevAttrs"; -const std::string METHOD_GET_NETDEV_LIST = "GetNetdevList"; -const std::string METHOD_CREATE_NETDEV_VETH = "CreateNetdevVeth"; -const std::string METHOD_CREATE_NETDEV_MACVLAN = "CreateNetdevMacvlan"; -const std::string METHOD_CREATE_NETDEV_PHYS = "CreateNetdevPhys"; -const std::string METHOD_DESTROY_NETDEV = "DestroyNetdev"; -const std::string METHOD_DECLARE_FILE = "DeclareFile"; -const std::string METHOD_DECLARE_MOUNT = "DeclareMount"; -const std::string METHOD_DECLARE_LINK = "DeclareLink"; -const std::string METHOD_GET_DECLARATIONS = "GetDeclarations"; -const std::string METHOD_REMOVE_DECLARATION = "RemoveDeclaration"; -const std::string METHOD_SET_ACTIVE_ZONE = "SetActiveZone"; -const std::string METHOD_CREATE_ZONE = "CreateZone"; -const std::string METHOD_DESTROY_ZONE = "DestroyZone"; -const std::string METHOD_SHUTDOWN_ZONE = "ShutdownZone"; -const std::string METHOD_START_ZONE = "StartZone"; -const std::string METHOD_LOCK_ZONE = "LockZone"; -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_GET_ZONE_DBUSES = "GetZoneDbuses"; +const std::string METHOD_GET_ZONE_ID_LIST = "GetZoneIds"; +const std::string METHOD_GET_ACTIVE_ZONE_ID = "GetActiveZoneId"; +const std::string METHOD_GET_ZONE_INFO = "GetZoneInfo"; +const std::string METHOD_SET_NETDEV_ATTRS = "SetNetdevAttrs"; +const std::string METHOD_GET_NETDEV_ATTRS = "GetNetdevAttrs"; +const std::string METHOD_GET_NETDEV_LIST = "GetNetdevList"; +const std::string METHOD_CREATE_NETDEV_VETH = "CreateNetdevVeth"; +const std::string METHOD_CREATE_NETDEV_MACVLAN = "CreateNetdevMacvlan"; +const std::string METHOD_CREATE_NETDEV_PHYS = "CreateNetdevPhys"; +const std::string METHOD_DESTROY_NETDEV = "DestroyNetdev"; +const std::string METHOD_DELETE_NETDEV_IP_ADDRESS = "DeleteNetdevIpAddress"; +const std::string METHOD_DECLARE_FILE = "DeclareFile"; +const std::string METHOD_DECLARE_MOUNT = "DeclareMount"; +const std::string METHOD_DECLARE_LINK = "DeclareLink"; +const std::string METHOD_GET_DECLARATIONS = "GetDeclarations"; +const std::string METHOD_REMOVE_DECLARATION = "RemoveDeclaration"; +const std::string METHOD_SET_ACTIVE_ZONE = "SetActiveZone"; +const std::string METHOD_CREATE_ZONE = "CreateZone"; +const std::string METHOD_DESTROY_ZONE = "DestroyZone"; +const std::string METHOD_SHUTDOWN_ZONE = "ShutdownZone"; +const std::string METHOD_START_ZONE = "StartZone"; +const std::string METHOD_LOCK_ZONE = "LockZone"; +const std::string METHOD_UNLOCK_ZONE = "UnlockZone"; +const std::string METHOD_GRANT_DEVICE = "GrantDevice"; +const std::string METHOD_REVOKE_DEVICE = "RevokeDevice"; -const std::string SIGNAL_ZONE_DBUS_STATE = "ZoneDbusState"; +const std::string SIGNAL_ZONE_DBUS_STATE = "ZoneDbusState"; const std::string DEFINITION = @@ -125,6 +126,11 @@ const std::string DEFINITION = " " " " " " + " " + " " + " " + " " + " " " " " " " " diff --git a/server/netdev.cpp b/server/netdev.cpp index da58641..38ccb88 100644 --- a/server/netdev.cpp +++ b/server/netdev.cpp @@ -120,6 +120,11 @@ uint32_t getInterfaceIndex(const string& name, pid_t nsPid) { return infoPeer.ifi_index; } +int getIpFamily(const std::string& ip) +{ + return ip.find(':') == std::string::npos ? AF_INET : AF_INET6; +} + void validateNetdevName(const string& name) { if (name.size() <= 1 || name.size() >= IFNAMSIZ) { @@ -331,6 +336,36 @@ void setIpAddresses(const pid_t nsPid, send(nlm, nsPid); } +void deleteIpAddress(const pid_t nsPid, + const uint32_t index, + const std::string& ip, + int prefixlen, + int family) +{ + NetlinkMessage nlm(RTM_DELADDR, NLM_F_REQUEST | NLM_F_ACK); + ifaddrmsg infoAddr = utils::make_clean(); + infoAddr.ifa_family = family; + infoAddr.ifa_index = index; + infoAddr.ifa_prefixlen = prefixlen; + nlm.put(infoAddr); + if (family == AF_INET6) { + in6_addr addr6; + if (inet_pton(AF_INET6, ip.c_str(), &addr6) != 1) { + throw VasumException("Can't delete ipv6 address"); + }; + nlm.put(IFA_ADDRESS, addr6); + nlm.put(IFA_LOCAL, addr6); + } else { + assert(family == AF_INET); + in_addr addr4; + if (inet_pton(AF_INET, ip.c_str(), &addr4) != 1) { + throw VasumException("Can't delete ipv4 address"); + }; + nlm.put(IFA_LOCAL, addr4); + } + send(nlm, nsPid); +} + } // namespace void createVeth(const pid_t& nsPid, const string& nsDev, const string& hostDev) @@ -565,6 +600,27 @@ void setAttrs(const pid_t nsPid, const std::string& netdev, const Attrs& attrs) setIp(ipv6, infoPeer.ifi_index, AF_INET6); } +void deleteIpAddress(const pid_t nsPid, + const std::string& netdev, + const std::string& ip) +{ + uint32_t index = getInterfaceIndex(netdev, nsPid); + size_t slash = ip.find('/'); + if (slash == string::npos) { + LOGE("Wrong address format: it is not CIDR notation: can't find '/'"); + throw VasumException("Wrong address format"); + } + int prefixlen = 0; + try { + prefixlen = stoi(ip.substr(slash + 1)); + } catch (const std::exception& ex) { + LOGE("Wrong address format: invalid prefixlen"); + throw VasumException("Wrong address format: invalid prefixlen"); + } + deleteIpAddress(nsPid, index, ip.substr(0, slash), prefixlen, getIpFamily(ip)); +} + + } //namespace netdev } //namespace vasum diff --git a/server/netdev.hpp b/server/netdev.hpp index 5e5821d..b3c574d 100644 --- a/server/netdev.hpp +++ b/server/netdev.hpp @@ -57,6 +57,11 @@ void createBridge(const std::string& netdev); Attrs getAttrs(const pid_t nsPid, const std::string& netdev); void setAttrs(const pid_t nsPid, const std::string& netdev, const Attrs& attrs); +/** + * Remove ipv4/ipv6 address from interface + */ +void deleteIpAddress(const pid_t nsPid, const std::string& netdev, const std::string& ip); + } //namespace netdev } //namespace vasum diff --git a/server/zone-admin.cpp b/server/zone-admin.cpp index b584279..3098f29 100644 --- a/server/zone-admin.cpp +++ b/server/zone-admin.cpp @@ -322,4 +322,9 @@ std::vector ZoneAdmin::getNetdevList() return netdev::listNetdev(mZone.getInitPid()); } +void ZoneAdmin::deleteNetdevIpAddress(const std::string& netdev, const std::string& ip) +{ + netdev::deleteIpAddress(mZone.getInitPid(), netdev, ip); +} + } // namespace vasum diff --git a/server/zone-admin.hpp b/server/zone-admin.hpp index db2b0f2..d1b179d 100644 --- a/server/zone-admin.hpp +++ b/server/zone-admin.hpp @@ -169,6 +169,11 @@ public: */ std::vector getNetdevList(); + /** + * Remove ipv4/ipv6 address from network device + */ + void deleteNetdevIpAddress(const std::string& netdev, const std::string& ip); + private: const ZoneConfig& mConfig; const ZoneDynamicConfig& mDynamicConfig; diff --git a/server/zone.cpp b/server/zone.cpp index b0c3c28..e26da52 100644 --- a/server/zone.cpp +++ b/server/zone.cpp @@ -513,4 +513,10 @@ std::vector Zone::getNetdevList() return mAdmin->getNetdevList(); } +void Zone::deleteNetdevIpAddress(const std::string& netdev, const std::string& ip) +{ + Lock lock(mReconnectMutex); + mAdmin->deleteNetdevIpAddress(netdev, ip); +} + } // namespace vasum diff --git a/server/zone.hpp b/server/zone.hpp index b981e9a..687077f 100644 --- a/server/zone.hpp +++ b/server/zone.hpp @@ -311,6 +311,11 @@ public: */ std::vector getNetdevList(); + /** + * Remove ipv4/ipv6 address from network device + */ + void deleteNetdevIpAddress(const std::string& netdev, const std::string& ip); + private: utils::Worker::Pointer mWorker; ZoneConfig mConfig; diff --git a/server/zones-manager.cpp b/server/zones-manager.cpp index 67e2b88..4f34a76 100644 --- a/server/zones-manager.cpp +++ b/server/zones-manager.cpp @@ -163,6 +163,9 @@ ZonesManager::ZonesManager(const std::string& configPath) mHostConnection.setDestroyNetdevCallback(bind(&ZonesManager::handleDestroyNetdevCall, this, _1, _2)); + mHostConnection.setDeleleNetdevIpAddressCallback(bind(&ZonesManager::handleDeleteNetdevIpAddressCall, + this, _1, _2)); + mHostConnection.setDeclareFileCallback(bind(&ZonesManager::handleDeclareFileCall, this, _1, _2)); @@ -945,6 +948,23 @@ void ZonesManager::handleDestroyNetdevCall(const api::DestroyNetDevIn& data, } } +void ZonesManager::handleDeleteNetdevIpAddressCall(const api::DeleteNetdevIpAddressIn& data, + api::MethodResultBuilder::Pointer result) +{ + LOGI("DelNetdevIpAddress call"); + try { + Lock lock(mMutex); + getZone(data.zone).deleteNetdevIpAddress(data.netdev, data.ip); + result->setVoid(); + } catch (const InvalidZoneIdException&) { + LOGE("No zone with id=" << data.zone); + result->setError(api::ERROR_INVALID_ID, "No such zone id"); + } catch (const VasumException& ex) { + LOGE("Can't delete address: " << ex.what()); + result->setError(api::ERROR_INTERNAL, ex.what()); + } +} + void ZonesManager::handleDeclareFileCall(const api::DeclareFileIn& data, api::MethodResultBuilder::Pointer result) { diff --git a/server/zones-manager.hpp b/server/zones-manager.hpp index ae89566..f789595 100644 --- a/server/zones-manager.hpp +++ b/server/zones-manager.hpp @@ -187,6 +187,8 @@ private: api::MethodResultBuilder::Pointer result); void handleDestroyNetdevCall(const api::DestroyNetDevIn& data, api::MethodResultBuilder::Pointer result); + void handleDeleteNetdevIpAddressCall(const api::DeleteNetdevIpAddressIn& data, + api::MethodResultBuilder::Pointer result); void handleDeclareFileCall(const api::DeclareFileIn& data, api::MethodResultBuilder::Pointer result); void handleDeclareMountCall(const api::DeclareMountIn& data, diff --git a/tests/unit_tests/server/ut-zone.cpp b/tests/unit_tests/server/ut-zone.cpp index 722f32c..dc66753 100644 --- a/tests/unit_tests/server/ut-zone.cpp +++ b/tests/unit_tests/server/ut-zone.cpp @@ -155,7 +155,7 @@ BOOST_AUTO_TEST_CASE(DbusConnection) c->stop(true); } -// TODO: DbusReconnectionTest +// TODO: DbusReconnection BOOST_AUTO_TEST_CASE(ListNetdev) { @@ -208,7 +208,7 @@ BOOST_AUTO_TEST_CASE(CreateNetdevMacvlan) BOOST_CHECK(find(netdevs.begin(), netdevs.end(), ZONE_NETDEV) != netdevs.end()); } -BOOST_AUTO_TEST_CASE(GetNetdevAttrsTest) +BOOST_AUTO_TEST_CASE(GetNetdevAttrs) { setupBridge(BRIDGE_NAME); auto c = create(TEST_CONFIG_PATH); @@ -240,7 +240,7 @@ BOOST_AUTO_TEST_CASE(GetNetdevAttrsTest) BOOST_CHECK(gotType); } -BOOST_AUTO_TEST_CASE(SetNetdevAttrsTest) +BOOST_AUTO_TEST_CASE(SetNetdevAttrs) { setupBridge(BRIDGE_NAME); auto c = create(TEST_CONFIG_PATH); @@ -269,7 +269,7 @@ BOOST_AUTO_TEST_CASE(SetNetdevAttrsTest) WhatEquals("Unsupported attribute: does_not_exists")); } -BOOST_AUTO_TEST_CASE(SetNetdevIpv4Test) +BOOST_AUTO_TEST_CASE(SetNetdevIpv4) { setupBridge(BRIDGE_NAME); auto c = create(TEST_CONFIG_PATH); @@ -309,7 +309,7 @@ BOOST_AUTO_TEST_CASE(SetNetdevIpv4Test) BOOST_CHECK_EQUAL(gotIp, 3); } -BOOST_AUTO_TEST_CASE(SetNetdevIpv6Test) +BOOST_AUTO_TEST_CASE(SetNetdevIpv6) { setupBridge(BRIDGE_NAME); auto c = create(TEST_CONFIG_PATH); @@ -349,4 +349,41 @@ BOOST_AUTO_TEST_CASE(SetNetdevIpv6Test) BOOST_CHECK_EQUAL(gotIp, 3); } +BOOST_AUTO_TEST_CASE(DelNetdevIpAddress) +{ + auto contain = [](const ZoneAdmin::NetdevAttrs& container, const std::string& key) { + return container.end() != find_if(container.begin(), + container.end(), + [&](const ZoneAdmin::NetdevAttrs::value_type& value) { + return std::get<0>(value) == key; + }); + }; + + setupBridge(BRIDGE_NAME); + auto c = create(TEST_CONFIG_PATH); + c->start(); + ensureStarted(); + c->createNetdevVeth(ZONE_NETDEV, BRIDGE_NAME); + ZoneAdmin::NetdevAttrs attrs; + attrs.push_back(std::make_tuple("ipv6", "ip:2001:db8::1,prefixlen:64")); + attrs.push_back(std::make_tuple("ipv4", "ip:192.168.4.1,prefixlen:24")); + c->setNetdevAttrs(ZONE_NETDEV, attrs); + attrs = c->getNetdevAttrs(ZONE_NETDEV); + BOOST_REQUIRE(contain(attrs, "ipv4")); + BOOST_REQUIRE(contain(attrs, "ipv6")); + + c->deleteNetdevIpAddress(ZONE_NETDEV, "192.168.4.1/24"); + attrs = c->getNetdevAttrs(ZONE_NETDEV); + BOOST_CHECK(!contain(attrs, "ipv4")); + BOOST_CHECK(contain(attrs, "ipv6")); + + c->deleteNetdevIpAddress(ZONE_NETDEV, "2001:db8::1/64"); + attrs = c->getNetdevAttrs(ZONE_NETDEV); + BOOST_REQUIRE(!contain(attrs, "ipv4")); + BOOST_REQUIRE(!contain(attrs, "ipv6")); + + BOOST_CHECK_THROW(c->deleteNetdevIpAddress(ZONE_NETDEV, "192.168.4.1/24"), VasumException); + BOOST_CHECK_THROW(c->deleteNetdevIpAddress(ZONE_NETDEV, "2001:db8::1/64"), VasumException); +} + BOOST_AUTO_TEST_SUITE_END() -- 2.7.4 From 04fbbc8a8324a2025d268d83036fbd39092f0438 Mon Sep 17 00:00:00 2001 From: Mateusz Malicki Date: Wed, 25 Mar 2015 16:22:29 +0100 Subject: [PATCH 16/16] Added netdev_down to cli and made some code cleanup (cli/client) [Bug/Feature] Added netdev_down to cli and made some code cleanup (cli/client) [Cause] N/A [Solution] N/A [Verification] Create netdev, turn it up and turn it down Change-Id: I698de7ccd181d0d8adbb892facddb5d552d6aee4 --- cli/main.cpp | 31 ++++++++++++++++++++----------- client/vasum-client-impl.cpp | 8 ++++---- 2 files changed, 24 insertions(+), 15 deletions(-) diff --git a/cli/main.cpp b/cli/main.cpp index 2431313..6c10945 100644 --- a/cli/main.cpp +++ b/cli/main.cpp @@ -145,40 +145,40 @@ std::map commands = { { "create_netdev_veth", { create_netdev_veth, - "create_netdev_veth zone_id zoneDev hostDev", + "create_netdev_veth zone_id zone_netdev_id host_netdev_id", "Create netdev in zone", {{"zone_id", "id zone name"}, - {"zoneDev", "network device id"}, - {"hostDev", "host bridge id"}} + {"zone_netdev_id", "network device id"}, + {"host_netdev_id", "host bridge id"}} } }, { "create_netdev_macvlan", { create_netdev_macvlan, - "create_netdev_macvlan zone_id zoneDev hostDev mode", + "create_netdev_macvlan zone_id zone_netdev_id host_netdev_id mode", "Create netdev in zone", {{"zone_id", "id zone name"}, - {"zoneDev", "network device id"}, - {"hostDev", "host bridge id"}, + {"zone_netdev_id", "network device id"}, + {"host_netdev_id", "host bridge id"}, {"mode", "macvlan mode (private, vepa, bridge, passthru)"}} } }, { "create_netdev_phys", { create_netdev_phys, - "create_netdev_phys zone_id devId", + "create_netdev_phys zone_id netdev_id", "Create/move netdev to zone", {{"zone_id", "id zone name"}, - {"devId", "network device id"}} + {"netdev_id", "network device name"}} } }, { "lookup_netdev_by_name", { lookup_netdev_by_name, - "lookup_netdev_by_name zone_id devId", + "lookup_netdev_by_name zone_id netdev_id", "Get netdev flags", {{"zone_id", "id zone name"}, - {"devId", "network device id"}} + {"netdev_id", "network device name"}} } }, { @@ -187,7 +187,7 @@ std::map commands = { "destroy_netdev zone_id devId", "Destroy netdev in zone", {{"zone_id", "id zone name"}, - {"devId", "network device id"}} + {"netdev_id", "network device name"}} } }, { @@ -248,6 +248,15 @@ std::map commands = { } }, { + "netdev_down", { + netdev_down, + "netdev_down zone_id netdev_id", + "Turn down a network device in the zone", + {{"zone_id", "id zone name"}, + {"netdev_id", "network device id"}} + } + }, + { "zone_get_netdevs", { zone_get_netdevs, "zone_get_netdevs zone_id", diff --git a/client/vasum-client-impl.cpp b/client/vasum-client-impl.cpp index 0c5482a..f4d8580 100644 --- a/client/vasum-client-impl.cpp +++ b/client/vasum-client-impl.cpp @@ -713,12 +713,12 @@ VsmStatus Client::vsm_netdev_get_ipv6_addr(const char* zone, VsmStatus Client::vsm_netdev_set_ipv4_addr(const char* zone, const char* netdevId, struct in_addr* addr, - int mask) noexcept + int prefix) noexcept { try { GVariant* dict = createTupleArray({make_tuple("ipv4", "ip:" + toString(addr) + "," - "prefixlen:" + to_string(mask))}); + "prefixlen:" + to_string(prefix))}); GVariant* args_in = g_variant_new("(ss@a(ss))", zone, netdevId, dict); return callMethod(HOST_INTERFACE, api::host::METHOD_SET_NETDEV_ATTRS, args_in); } catch (exception& ex) { @@ -730,12 +730,12 @@ VsmStatus Client::vsm_netdev_set_ipv4_addr(const char* zone, VsmStatus Client::vsm_netdev_set_ipv6_addr(const char* zone, const char* netdevId, struct in6_addr* addr, - int mask) noexcept + int prefix) noexcept { try { GVariant* dict = createTupleArray({make_tuple("ipv6", "ip:" + toString(addr) + "," - "prefixlen:" + to_string(mask))}); + "prefixlen:" + to_string(prefix))}); GVariant* args_in = g_variant_new("(ss@a(ss))", zone, netdevId, dict); return callMethod(HOST_INTERFACE, api::host::METHOD_SET_NETDEV_ATTRS, args_in); } catch (exception& ex) { -- 2.7.4