lxcpp: Changes to the ContainerImpl class API for libConfig usage 47/47547/6
authorLukasz Pawelczyk <l.pawelczyk@samsung.com>
Wed, 29 Jul 2015 11:27:25 +0000 (13:27 +0200)
committerDariusz Michaluk <d.michaluk@samsung.com>
Mon, 7 Sep 2015 12:26:13 +0000 (05:26 -0700)
[Feature]       Changes to the ContainerImpl class API for libConfig usage.
                PersistentFileBackend for logger.
[Verification]  Build, install, run tests.

Change-Id: I3e7290df2bf42df9e067fe6734b96dcf5f3aa20b

libs/logger/backend-persistent-file.cpp [new file with mode: 0644]
libs/logger/backend-persistent-file.hpp [new file with mode: 0644]
libs/logger/logger.hpp
libs/lxcpp/container-impl.cpp
libs/lxcpp/container-impl.hpp
libs/lxcpp/container.hpp
libs/lxcpp/exception.hpp
libs/lxcpp/lxcpp.cpp
libs/lxcpp/lxcpp.hpp
tests/unit_tests/lxcpp/lxcpp-api-compile-test.cpp
tests/unit_tests/lxcpp/ut-container.cpp

diff --git a/libs/logger/backend-persistent-file.cpp b/libs/logger/backend-persistent-file.cpp
new file mode 100644 (file)
index 0000000..8aa53cb
--- /dev/null
@@ -0,0 +1,46 @@
+/*
+ *  Copyright (c) 2015 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ *  Contact: Lukasz Pawelczyk (l.pawelczyk@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  Lukasz Pawelczyk (l.pawelczyk@samsung.com)
+ * @brief   Persistent file backend for logger
+ */
+
+#include "logger/config.hpp"
+#include "logger/formatter.hpp"
+#include "logger/backend-persistent-file.hpp"
+
+#include <fstream>
+
+namespace logger {
+
+void PersistentFileBackend::log(LogLevel logLevel,
+                                const std::string& file,
+                                const unsigned int& line,
+                                const std::string& func,
+                                const std::string& message)
+{
+    mOut << LogFormatter::getHeader(logLevel, file, line, func);
+    mOut << message;
+    mOut << std::endl;
+    mOut.flush();
+}
+
+
+} // namespace logger
diff --git a/libs/logger/backend-persistent-file.hpp b/libs/logger/backend-persistent-file.hpp
new file mode 100644 (file)
index 0000000..74d2def
--- /dev/null
@@ -0,0 +1,52 @@
+/*
+ *  Copyright (c) 2015 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ *  Contact: Lukasz Pawelczyk (l.pawelczyk@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  Lukasz Pawelczyk (l.pawelczyk@samsung.com)
+ * @brief   Persistent file backend for logger
+ */
+
+#ifndef COMMON_LOGGER_BACKEND_PERSISTENT_FILE_HPP
+#define COMMON_LOGGER_BACKEND_PERSISTENT_FILE_HPP
+
+#include "logger/backend.hpp"
+
+#include <fstream>
+
+namespace logger {
+
+class PersistentFileBackend : public LogBackend {
+public:
+    PersistentFileBackend(const std::string& filePath) :
+        mfilePath(filePath),
+        mOut(mfilePath, std::ios::app) {}
+
+    void log(LogLevel logLevel,
+             const std::string& file,
+             const unsigned int& line,
+             const std::string& func,
+             const std::string& message) override;
+private:
+    std::string mfilePath;
+    std::ofstream mOut;
+};
+
+} // namespace logger
+
+#endif // COMMON_LOGGER_BACKEND_PERSISTENT_FILE_HPP
index bedddb0..0a1ebe6 100644 (file)
@@ -36,6 +36,7 @@
  * Logger::setLogBackend(new NullLogger());
  * Logger::setLogBackend(new SystemdJournalBackend());
  * Logger::setLogBackend(new FileBackend("/tmp/logs.txt"));
+ * Logger::setLogBackend(new PersistentFileBackend("/tmp/logs.txt"));
  * Logger::setLogBackend(new SyslogBackend());
  * Logger::setLogBackend(new StderrBackend());
  *
@@ -62,6 +63,7 @@
 #include "logger/level.hpp"
 #include "logger/backend-file.hpp"
 #include "logger/backend-stderr.hpp"
+#include "logger/backend-persistent-file.hpp"
 
 #include <sstream>
 #include <string>
index 02e9f3a..73e5254 100644 (file)
 #include "lxcpp/capability.hpp"
 #include "lxcpp/commands/attach.hpp"
 
+#include "logger/logger.hpp"
 #include "utils/exception.hpp"
 
 #include <unistd.h>
 #include <sys/mount.h>
+#include <sys/wait.h>
+#include <mutex>
+#include <algorithm>
+
 
 namespace lxcpp {
 
-ContainerImpl::ContainerImpl()
+ContainerImpl::ContainerImpl(const std::string &name, const std::string &path)
 {
-}
+    if (name.empty()) {
+        const std::string msg = "Name cannot be empty";
+        LOGE(msg);
+        throw ConfigureException(msg);
+    }
 
-ContainerImpl::~ContainerImpl()
-{
+    if (path.empty()) {
+        const std::string msg = "Path cannot be empty";
+        LOGE(msg);
+        throw ConfigureException(msg);
+    }
+
+    if(::access(path.c_str(), X_OK) < 0) {
+        const std::string msg = "Path must point to a traversable directory";
+        LOGE(msg);
+        throw ConfigureException(msg);
+    }
+
+    mConfig.mName = name;
+    mConfig.mRootPath = path;
 }
 
-std::string ContainerImpl::getName()
+// TODO: the aim of this constructor is to create a new ContainerImpl based on an already
+// running container. It should talk to its guard and receive its current config.
+ContainerImpl::ContainerImpl(pid_t /*guardPid*/)
 {
     throw NotImplementedException();
 }
 
-void ContainerImpl::setName(const std::string& /* name */)
+ContainerImpl::~ContainerImpl()
 {
-    throw NotImplementedException();
 }
 
-void ContainerImpl::start()
+const std::string& ContainerImpl::getName() const
 {
-    throw NotImplementedException();
+    return mConfig.mName;
 }
 
-void ContainerImpl::stop()
+const std::string& ContainerImpl::getRootPath() const
 {
-    throw NotImplementedException();
+    return mConfig.mRootPath;
 }
 
-void ContainerImpl::freeze()
+const std::vector<std::string>& ContainerImpl::getInit()
 {
-    throw NotImplementedException();
+    return mConfig.mInit;
 }
 
-void ContainerImpl::unfreeze()
+void ContainerImpl::setInit(const std::vector<std::string> &init)
 {
-    throw NotImplementedException();
+    if (init.empty() || init[0].empty()) {
+        const std::string msg = "Init path cannot be empty";
+        LOGE(msg);
+        throw ConfigureException(msg);
+    }
+
+    std::string path = mConfig.mRootPath + "/" + init[0];
+
+    if (::access(path.c_str(), X_OK) < 0) {
+        const std::string msg = "Init path must point to an executable file";
+        LOGE(msg);
+        throw ConfigureException(msg);
+    }
+
+    mConfig.mInit = init;
 }
 
-void ContainerImpl::reboot()
+pid_t ContainerImpl::getGuardPid() const
 {
-    throw NotImplementedException();
+    return mConfig.mGuardPid;
 }
 
 pid_t ContainerImpl::getInitPid() const
 {
-    return mInitPid;
+    return mConfig.mInitPid;
 }
 
-void ContainerImpl::create()
+void ContainerImpl::start()
 {
     throw NotImplementedException();
 }
 
-void ContainerImpl::destroy()
+void ContainerImpl::stop()
 {
     throw NotImplementedException();
 }
 
-void ContainerImpl::setRootPath(const std::string& /* path */)
+void ContainerImpl::freeze()
 {
     throw NotImplementedException();
 }
 
-std::string ContainerImpl::getRootPath()
+void ContainerImpl::unfreeze()
+{
+    throw NotImplementedException();
+}
+
+void ContainerImpl::reboot()
 {
     throw NotImplementedException();
 }
@@ -125,7 +166,6 @@ const std::vector<Namespace>& ContainerImpl::getNamespaces() const
     return mNamespaces;
 }
 
-
 void ContainerImpl::addInterfaceConfig(const std::string& hostif,
                                        const std::string& zoneif,
                                        InterfaceType type,
index c862473..5435d49 100644 (file)
 #ifndef LXCPP_CONTAINER_IMPL_HPP
 #define LXCPP_CONTAINER_IMPL_HPP
 
+#include <sys/types.h>
+#include <config/config.hpp>
+#include <config/fields.hpp>
+#include <memory>
+
 #include "lxcpp/container.hpp"
 #include "lxcpp/namespace.hpp"
 #include "lxcpp/network.hpp"
 
 namespace lxcpp {
 
+struct ContainerConfig {
+    std::string mName;
+    std::string mRootPath;
+    pid_t mGuardPid;
+    pid_t mInitPid;
+    std::vector<std::string> mInit;
+
+    ContainerConfig() : mGuardPid(-1), mInitPid(-1) {}
+
+    CONFIG_REGISTER
+    (
+        mName,
+        mRootPath,
+        mGuardPid,
+        mInitPid,
+        mInit
+    )
+};
+
+
 class ContainerImpl : public virtual Container {
 public:
-    ContainerImpl();
+    ContainerImpl(const std::string &name, const std::string &path);
+    ContainerImpl(pid_t guardPid);
     ~ContainerImpl();
 
-    std::string getName();
-    void setName(const std::string& name);
+    // Configuration
+    const std::string& getName() const;
+    const std::string& getRootPath() const;
+
+    pid_t getGuardPid() const;
+    pid_t getInitPid() const;
 
-    //Execution actions
+    const std::vector<std::string>& getInit();
+    void setInit(const std::vector<std::string> &init);
+
+    const std::vector<Namespace>& getNamespaces() const;
+
+    // Execution actions
     void start();
     void stop();
     void freeze();
     void unfreeze();
     void reboot();
-    pid_t getInitPid() const;
-    const std::vector<Namespace>& getNamespaces() const;
-
-    //Filesystem actions
-    void create();
-    void destroy();
-    void setRootPath(const std::string& path);
-    std::string getRootPath();
 
     // Other
     void attach(Container::AttachCall& attachCall,
@@ -80,7 +107,9 @@ public:
     void delAddr(const std::string& ifname, const InetAddr& addr);
 
 private:
-    pid_t mInitPid;
+    ContainerConfig mConfig;
+
+    // TODO: convert to ContainerConfig struct
     std::vector<Namespace> mNamespaces;
     std::vector<NetworkInterfaceConfig> mInterfaceConfig;
 };
index 882aa87..192f2df 100644 (file)
@@ -50,22 +50,22 @@ public:
 
     virtual ~Container() {};
 
-    virtual std::string getName() = 0;
-    virtual void setName(const std::string& name) = 0;
+    // Configuration
+    virtual const std::string& getName() const = 0;
+    virtual const std::string& getRootPath() const = 0;
 
-    //Execution actions
+    virtual pid_t getGuardPid() const = 0;
+    virtual pid_t getInitPid() const = 0;
+
+    virtual const std::vector<std::string>& getInit() = 0;
+    virtual void setInit(const std::vector<std::string> &init) = 0;
+
+    // Execution actions
     virtual void start() = 0;
     virtual void stop() = 0;
     virtual void freeze() = 0;
     virtual void unfreeze() = 0;
     virtual void reboot() = 0;
-    virtual pid_t getInitPid() const = 0;
-
-    //Filesystem actions
-    virtual void create() = 0;
-    virtual void destroy() = 0;
-    virtual void setRootPath(const std::string& path) = 0;
-    virtual std::string getRootPath() = 0;
 
     // Other
     virtual void attach(AttachCall& attachCall,
index 037da41..af81779 100644 (file)
@@ -42,7 +42,7 @@ struct NotImplementedException: public Exception {
 };
 
 struct ProcessSetupException: public Exception {
-    ProcessSetupException(const std::string& message = "Error during setting up a process")
+    ProcessSetupException(const std::string& message = "Error while setting up a process")
         : Exception(message) {}
 };
 
@@ -81,6 +81,11 @@ struct NetworkException : public Exception {
         : Exception(message) {}
 };
 
+struct ConfigureException: public Exception {
+    ConfigureException(const std::string& message = "Error while configuring a container")
+        : Exception(message) {}
+};
+
 } // namespace lxcpp
 
 #endif // LXCPP_EXCEPTION_HPP
index 97c3866..35cd3d6 100644 (file)
@@ -25,9 +25,9 @@
 
 namespace lxcpp {
 
-Container* createContainer()
+Container* createContainer(const std::string& name, const std::string& path)
 {
-    return new ContainerImpl();
+    return new ContainerImpl(name, path);
 }
 
 } // namespace lxcpp
index 5eb3f57..c2b3029 100644 (file)
@@ -28,7 +28,7 @@
 
 namespace lxcpp {
 
-Container* createContainer();
+Container* createContainer(const std::string &name, const std::string &path);
 
 } // namespace lxcpp
 
index 2e72bfb..f6d48c2 100644 (file)
@@ -27,6 +27,7 @@ using namespace lxcpp;
 
 int main(int /*argc*/, const char * /*argv*/ [])
 {
-    Container* c = createContainer();
+    Container* c = createContainer("Name", "/");
+
     delete c;
 }
index 6177502..35672e0 100644 (file)
@@ -44,7 +44,7 @@ using namespace lxcpp;
 
 BOOST_AUTO_TEST_CASE(ConstructorDestructor)
 {
-    auto c = createContainer();
+    auto c = createContainer("FirstTestContainer", "/");
     delete c;
 }