[Feature] Changes to the ContainerImpl class API for libConfig usage.
PersistentFileBackend for logger.
[Verification] Build, install, run tests.
Change-Id: I3e7290df2bf42df9e067fe6734b96dcf5f3aa20b
--- /dev/null
+/*
+ * 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
--- /dev/null
+/*
+ * 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
* 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());
*
#include "logger/level.hpp"
#include "logger/backend-file.hpp"
#include "logger/backend-stderr.hpp"
+#include "logger/backend-persistent-file.hpp"
#include <sstream>
#include <string>
#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();
}
return mNamespaces;
}
-
void ContainerImpl::addInterfaceConfig(const std::string& hostif,
const std::string& zoneif,
InterfaceType type,
#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,
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;
};
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,
};
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) {}
};
: Exception(message) {}
};
+struct ConfigureException: public Exception {
+ ConfigureException(const std::string& message = "Error while configuring a container")
+ : Exception(message) {}
+};
+
} // namespace lxcpp
#endif // LXCPP_EXCEPTION_HPP
namespace lxcpp {
-Container* createContainer()
+Container* createContainer(const std::string& name, const std::string& path)
{
- return new ContainerImpl();
+ return new ContainerImpl(name, path);
}
} // namespace lxcpp
namespace lxcpp {
-Container* createContainer();
+Container* createContainer(const std::string &name, const std::string &path);
} // namespace lxcpp
int main(int /*argc*/, const char * /*argv*/ [])
{
- Container* c = createContainer();
+ Container* c = createContainer("Name", "/");
+
delete c;
}
BOOST_AUTO_TEST_CASE(ConstructorDestructor)
{
- auto c = createContainer();
+ auto c = createContainer("FirstTestContainer", "/");
delete c;
}