From 9c895ec3e042205df243e175a06967a975d8f645 Mon Sep 17 00:00:00 2001
From: Pawel Kubik
Date: Mon, 7 Sep 2015 11:17:45 +0200
Subject: [PATCH 01/16] cppcheck fixes
[Feature] Small code fixes based on cppcheck
[Cause] Minimizing possible runtime errors
[Solution] Fix the code using cppcheck suggestions, suppress
false-positives
[Verification] Compile, run cppcheck
Change-Id: I94fab8e50879f78f3ccb503fd18606e9cbfabfb5
---
cli/cli-exception.hpp | 4 +--
client/exception.hpp | 10 +++---
client/vasum-client-impl.cpp | 1 -
common/api/ipc-method-result-builder.hpp | 2 +-
common/base-exception.hpp | 2 +-
common/lxc/exception.hpp | 4 +--
common/utils/exception.hpp | 4 +--
libs/dbus/exception.hpp | 10 +++---
libs/ipc/exception.hpp | 16 +++++-----
libs/ipc/internals/finish-request.hpp | 2 +-
libs/ipc/internals/method-request.hpp | 6 ++--
libs/ipc/internals/processor.cpp | 26 ++++++++--------
libs/ipc/internals/processor.hpp | 46 ++++++++++++++--------------
libs/ipc/internals/remove-peer-request.hpp | 2 +-
libs/ipc/internals/result-builder.hpp | 10 ++----
libs/ipc/internals/send-result-request.hpp | 4 +--
libs/ipc/internals/signal-request.hpp | 6 ++--
libs/ipc/method-result.cpp | 6 ++--
libs/ipc/method-result.hpp | 6 ++--
libs/ipc/service.hpp | 8 ++---
libs/lxcpp/exception.hpp | 22 ++++++-------
server/exception.hpp | 14 ++++-----
server/zones-manager.cpp | 4 +--
tests/cppcheck/cppcheck.sh | 4 ++-
tests/cppcheck/cppcheck.suppress | 23 ++++++++++++--
tests/unit_tests/ipc/ut-ipc.cpp | 2 +-
tests/unit_tests/server/ut-zones-manager.cpp | 11 +++----
tests/unit_tests/utils/ut-worker.cpp | 2 +-
zone-daemon/exception.hpp | 2 +-
29 files changed, 135 insertions(+), 124 deletions(-)
diff --git a/cli/cli-exception.hpp b/cli/cli-exception.hpp
index 982f52d..f0d5e0f 100644
--- a/cli/cli-exception.hpp
+++ b/cli/cli-exception.hpp
@@ -38,12 +38,12 @@ namespace cli {
*/
struct CliException: public VasumException {
- CliException(const std::string& error) : VasumException(error) {}
+ explicit CliException(const std::string& error) : VasumException(error) {}
};
struct IOException: public CliException {
- IOException(const std::string& error) : CliException(error) {}
+ explicit IOException(const std::string& error) : CliException(error) {}
};
} // namespace cli
diff --git a/client/exception.hpp b/client/exception.hpp
index d4be66b..98ebf81 100644
--- a/client/exception.hpp
+++ b/client/exception.hpp
@@ -37,27 +37,27 @@ namespace vasum {
*/
struct ClientException: public VasumException {
- ClientException(const std::string& error) : VasumException(error) {}
+ explicit ClientException(const std::string& error) : VasumException(error) {}
};
struct IOException: public ClientException {
- IOException(const std::string& error) : ClientException(error) {}
+ explicit IOException(const std::string& error) : ClientException(error) {}
};
struct OperationFailedException: public ClientException {
- OperationFailedException(const std::string& error) : ClientException(error) {}
+ explicit OperationFailedException(const std::string& error) : ClientException(error) {}
};
struct InvalidArgumentException: public ClientException {
- InvalidArgumentException(const std::string& error) : ClientException(error) {}
+ explicit InvalidArgumentException(const std::string& error) : ClientException(error) {}
};
struct InvalidResponseException: public ClientException {
- InvalidResponseException(const std::string& error) : ClientException(error) {}
+ explicit InvalidResponseException(const std::string& error) : ClientException(error) {}
};
}
diff --git a/client/vasum-client-impl.cpp b/client/vasum-client-impl.cpp
index e3aca1d..41cc919 100644
--- a/client/vasum-client-impl.cpp
+++ b/client/vasum-client-impl.cpp
@@ -899,4 +899,3 @@ VsmStatus Client::vsm_clean_up_zones_root() noexcept
std::make_shared());
});
}
-
diff --git a/common/api/ipc-method-result-builder.hpp b/common/api/ipc-method-result-builder.hpp
index e9554d0..cad5d8a 100644
--- a/common/api/ipc-method-result-builder.hpp
+++ b/common/api/ipc-method-result-builder.hpp
@@ -40,7 +40,7 @@ const std::string IPC_CONNECTION_PREFIX = "ipc://";
class IPCMethodResultBuilder: public MethodResultBuilder {
public:
- IPCMethodResultBuilder(const ipc::MethodResult::Pointer& methodResult);
+ explicit IPCMethodResultBuilder(const ipc::MethodResult::Pointer& methodResult);
~IPCMethodResultBuilder() {}
private:
diff --git a/common/base-exception.hpp b/common/base-exception.hpp
index 645fa41..05e1fd6 100644
--- a/common/base-exception.hpp
+++ b/common/base-exception.hpp
@@ -38,7 +38,7 @@ namespace vasum {
*/
struct VasumException: public std::runtime_error {
- VasumException(const std::string& error) : std::runtime_error(error) {}
+ explicit VasumException(const std::string& error) : std::runtime_error(error) {}
};
} // namespace vasum
diff --git a/common/lxc/exception.hpp b/common/lxc/exception.hpp
index 379fe43..40c7d5f 100644
--- a/common/lxc/exception.hpp
+++ b/common/lxc/exception.hpp
@@ -37,12 +37,12 @@ namespace vasum {
*/
struct LxcException: public VasumException {
- LxcException(const std::string& error) : VasumException(error) {}
+ explicit LxcException(const std::string& error) : VasumException(error) {}
};
struct KeyNotFoundException: public LxcException {
- KeyNotFoundException(const std::string& error) : LxcException(error) {}
+ explicit KeyNotFoundException(const std::string& error) : LxcException(error) {}
};
} // namespace vasum
diff --git a/common/utils/exception.hpp b/common/utils/exception.hpp
index fda0554..232b090 100644
--- a/common/utils/exception.hpp
+++ b/common/utils/exception.hpp
@@ -36,12 +36,12 @@ namespace utils {
*/
struct UtilsException: public std::runtime_error {
- UtilsException(const std::string& error) : std::runtime_error(error) {}
+ explicit UtilsException(const std::string& error) : std::runtime_error(error) {}
};
struct ProvisionExistsException: public UtilsException {
- ProvisionExistsException(const std::string& error) : UtilsException(error) {}
+ explicit ProvisionExistsException(const std::string& error) : UtilsException(error) {}
};
/**
diff --git a/libs/dbus/exception.hpp b/libs/dbus/exception.hpp
index a09bdbc..b38877c 100644
--- a/libs/dbus/exception.hpp
+++ b/libs/dbus/exception.hpp
@@ -34,7 +34,7 @@ namespace dbus {
*/
struct DbusException: public std::runtime_error {
- DbusException(const std::string& error = "") : std::runtime_error(error) {}
+ explicit DbusException(const std::string& error = "") : std::runtime_error(error) {}
};
/**
@@ -42,7 +42,7 @@ struct DbusException: public std::runtime_error {
*/
struct DbusIOException: public DbusException {
- DbusIOException(const std::string& error = "") : DbusException(error) {}
+ explicit DbusIOException(const std::string& error = "") : DbusException(error) {}
};
/**
@@ -50,7 +50,7 @@ struct DbusIOException: public DbusException {
*/
struct DbusOperationException: public DbusException {
- DbusOperationException(const std::string& error = "") : DbusException(error) {}
+ explicit DbusOperationException(const std::string& error = "") : DbusException(error) {}
};
/**
@@ -58,7 +58,7 @@ struct DbusOperationException: public DbusException {
*/
struct DbusCustomException: public DbusException {
- DbusCustomException(const std::string& error = "") : DbusException(error) {}
+ explicit DbusCustomException(const std::string& error = "") : DbusException(error) {}
};
/**
@@ -66,7 +66,7 @@ struct DbusCustomException: public DbusException {
*/
struct DbusInvalidArgumentException: public DbusException {
- DbusInvalidArgumentException(const std::string& error = "") : DbusException(error) {}
+ explicit DbusInvalidArgumentException(const std::string& error = "") : DbusException(error) {}
};
} // namespace dbus
diff --git a/libs/ipc/exception.hpp b/libs/ipc/exception.hpp
index 140619c..3fe7a5b 100644
--- a/libs/ipc/exception.hpp
+++ b/libs/ipc/exception.hpp
@@ -36,7 +36,7 @@ namespace ipc {
* @defgroup IPCException IPCException
*/
struct IPCException: public std::runtime_error {
- IPCException(const std::string& message)
+ explicit IPCException(const std::string& message)
: std::runtime_error(message) {}
};
@@ -45,7 +45,7 @@ struct IPCException: public std::runtime_error {
* @ingroup IPCException
*/
struct IPCParsingException: public IPCException {
- IPCParsingException(const std::string& message = "Exception during reading/parsing data from the socket")
+ explicit IPCParsingException(const std::string& message = "Exception during reading/parsing data from the socket")
: IPCException(message) {}
};
@@ -54,7 +54,7 @@ struct IPCParsingException: public IPCException {
* @ingroup IPCException
*/
struct IPCSerializationException: public IPCException {
- IPCSerializationException(const std::string& message = "Exception during writing/serializing data to the socket")
+ explicit IPCSerializationException(const std::string& message = "Exception during writing/serializing data to the socket")
: IPCException(message) {}
};
@@ -63,7 +63,7 @@ struct IPCSerializationException: public IPCException {
* @ingroup IPCException
*/
struct IPCPeerDisconnectedException: public IPCException {
- IPCPeerDisconnectedException(const std::string& message = "No such peer. Might got disconnected.")
+ explicit IPCPeerDisconnectedException(const std::string& message = "No such peer. Might got disconnected.")
: IPCException(message) {}
};
@@ -72,7 +72,7 @@ struct IPCPeerDisconnectedException: public IPCException {
* @ingroup IPCException
*/
struct IPCNaughtyPeerException: public IPCException {
- IPCNaughtyPeerException(const std::string& message = "Peer performed a forbidden action.")
+ explicit IPCNaughtyPeerException(const std::string& message = "Peer performed a forbidden action.")
: IPCException(message) {}
};
@@ -81,7 +81,7 @@ struct IPCNaughtyPeerException: public IPCException {
* @ingroup IPCException
*/
struct IPCRemovedPeerException: public IPCException {
- IPCRemovedPeerException(const std::string& message = "Removing peer")
+ explicit IPCRemovedPeerException(const std::string& message = "Removing peer")
: IPCException(message) {}
};
@@ -90,7 +90,7 @@ struct IPCRemovedPeerException: public IPCException {
* @ingroup IPCException
*/
struct IPCClosingException: public IPCException {
- IPCClosingException(const std::string& message = "Closing IPC")
+ explicit IPCClosingException(const std::string& message = "Closing IPC")
: IPCException(message) {}
};
@@ -99,7 +99,7 @@ struct IPCClosingException: public IPCException {
* @ingroup IPCException
*/
struct IPCTimeoutException: public IPCException {
- IPCTimeoutException(const std::string& message)
+ explicit IPCTimeoutException(const std::string& message)
: IPCException(message) {}
};
diff --git a/libs/ipc/internals/finish-request.hpp b/libs/ipc/internals/finish-request.hpp
index 5a948bd..934c135 100644
--- a/libs/ipc/internals/finish-request.hpp
+++ b/libs/ipc/internals/finish-request.hpp
@@ -43,4 +43,4 @@ public:
} // namespace ipc
-#endif // COMMON_IPC_INTERNALS_FINISH_REQUEST_HPP
\ No newline at end of file
+#endif // COMMON_IPC_INTERNALS_FINISH_REQUEST_HPP
diff --git a/libs/ipc/internals/method-request.hpp b/libs/ipc/internals/method-request.hpp
index 663cbde..53d9d44 100644
--- a/libs/ipc/internals/method-request.hpp
+++ b/libs/ipc/internals/method-request.hpp
@@ -41,7 +41,7 @@ public:
template
static std::shared_ptr create(const MethodID methodID,
- const PeerID peerID,
+ const PeerID& peerID,
const std::shared_ptr& data,
const typename ResultHandler::type& process);
@@ -54,7 +54,7 @@ public:
ResultBuilderHandler process;
private:
- MethodRequest(const MethodID methodID, const PeerID peerID)
+ MethodRequest(const MethodID methodID, const PeerID& peerID)
: methodID(methodID),
peerID(peerID),
messageID(getNextMessageID())
@@ -64,7 +64,7 @@ private:
template
std::shared_ptr MethodRequest::create(const MethodID methodID,
- const PeerID peerID,
+ const PeerID& peerID,
const std::shared_ptr& data,
const typename ResultHandler::type& process)
{
diff --git a/libs/ipc/internals/processor.cpp b/libs/ipc/internals/processor.cpp
index fdbcbe8..164d735 100644
--- a/libs/ipc/internals/processor.cpp
+++ b/libs/ipc/internals/processor.cpp
@@ -92,7 +92,7 @@ Processor::Peers::iterator Processor::getPeerInfoIterator(const FileDescriptor f
});
}
-Processor::Peers::iterator Processor::getPeerInfoIterator(const PeerID peerID)
+Processor::Peers::iterator Processor::getPeerInfoIterator(const PeerID & peerID)
{
return std::find_if(mPeerInfo.begin(), mPeerInfo.end(), [peerID](const PeerInfo & peerInfo) {
return peerID == peerInfo.peerID;
@@ -162,16 +162,16 @@ FileDescriptor Processor::getEventFD()
}
void Processor::sendResult(const MethodID methodID,
- const PeerID peerID,
- const MessageID messageID,
+ const PeerID& peerID,
+ const MessageID& messageID,
const std::shared_ptr& data)
{
auto requestPtr = std::make_shared(methodID, peerID, messageID, data);
mRequestQueue.pushFront(Event::SEND_RESULT, requestPtr);
}
-void Processor::sendError(const PeerID peerID,
- const MessageID messageID,
+void Processor::sendError(const PeerID& peerID,
+ const MessageID& messageID,
const int errorCode,
const std::string& message)
{
@@ -180,8 +180,8 @@ void Processor::sendError(const PeerID peerID,
}
void Processor::sendVoid(const MethodID methodID,
- const PeerID peerID,
- const MessageID messageID)
+ const PeerID& peerID,
+ const MessageID& messageID)
{
auto data = std::make_shared();
auto requestPtr = std::make_shared(methodID, peerID, messageID, data);
@@ -208,7 +208,7 @@ PeerID Processor::addPeer(const std::shared_ptr& socketPtr)
return requestPtr->peerID;
}
-void Processor::removePeerSyncInternal(const PeerID peerID, Lock& lock)
+void Processor::removePeerSyncInternal(const PeerID& peerID, Lock& lock)
{
LOGS(mLogPrefix + "Processor removePeer peerID: " << peerID);
@@ -329,7 +329,7 @@ bool Processor::handleInput(const FileDescriptor fd)
}
}
-void Processor::onNewSignals(const PeerID peerID, std::shared_ptr& data)
+void Processor::onNewSignals(const PeerID& peerID, std::shared_ptr& data)
{
LOGS(mLogPrefix + "Processor onNewSignals peerID: " << peerID);
@@ -338,7 +338,7 @@ void Processor::onNewSignals(const PeerID peerID, std::shared_ptr& data)
+void Processor::onErrorSignal(const PeerID&, std::shared_ptr& data)
{
LOGS(mLogPrefix + "Processor onErrorSignal messageID: " << data->messageID);
@@ -351,7 +351,7 @@ void Processor::onErrorSignal(const PeerID, std::shared_ptr signalCallbacks)
{
LOGS(mLogPrefix + "Processor onRemoteSignal; methodID: " << methodID << " messageID: " << messageID);
@@ -422,7 +422,7 @@ bool Processor::onRemoteSignal(Peers::iterator& peerIt,
bool Processor::onRemoteMethod(Peers::iterator& peerIt,
const MethodID methodID,
- const MessageID messageID,
+ const MessageID& messageID,
std::shared_ptr methodCallbacks)
{
LOGS(mLogPrefix + "Processor onRemoteMethod; methodID: " << methodID << " messageID: " << messageID);
diff --git a/libs/ipc/internals/processor.hpp b/libs/ipc/internals/processor.hpp
index e383a57..91edfc1 100644
--- a/libs/ipc/internals/processor.hpp
+++ b/libs/ipc/internals/processor.hpp
@@ -217,8 +217,8 @@ public:
* @param data data to send
*/
void sendResult(const MethodID methodID,
- const PeerID peerID,
- const MessageID messageID,
+ const PeerID& peerID,
+ const MessageID& messageID,
const std::shared_ptr& data);
/**
@@ -229,8 +229,8 @@ public:
* @param errorCode code of the error
* @param message description of the error
*/
- void sendError(const PeerID peerID,
- const MessageID messageID,
+ void sendError(const PeerID& peerID,
+ const MessageID& messageID,
const int errorCode,
const std::string& message);
@@ -242,8 +242,8 @@ public:
* @param messageID id of the message to which it replies
*/
void sendVoid(const MethodID methodID,
- const PeerID peerID,
- const MessageID messageID);
+ const PeerID& peerID,
+ const MessageID& messageID);
/**
* Removes the callback associated with specific method id.
@@ -267,7 +267,7 @@ public:
*/
template
std::shared_ptr callSync(const MethodID methodID,
- const PeerID peerID,
+ const PeerID& peerID,
const std::shared_ptr& data,
unsigned int timeoutMS = 5000);
@@ -283,7 +283,7 @@ public:
*/
template
MessageID callAsync(const MethodID methodID,
- const PeerID peerID,
+ const PeerID& peerID,
const std::shared_ptr& data,
const typename ResultHandler::type& process);
@@ -352,7 +352,7 @@ private:
struct RegisterSignalsProtocolMessage {
RegisterSignalsProtocolMessage() = default;
- RegisterSignalsProtocolMessage(const std::vector& ids)
+ explicit RegisterSignalsProtocolMessage(const std::vector& ids)
: ids(ids) {}
std::vector ids;
@@ -365,7 +365,7 @@ private:
struct ErrorProtocolMessage {
ErrorProtocolMessage() = default;
- ErrorProtocolMessage(const MessageID messageID, const int code, const std::string& message)
+ ErrorProtocolMessage(const MessageID& messageID, const int code, const std::string& message)
: messageID(messageID), code(code), message(message) {}
MessageID messageID;
@@ -461,7 +461,7 @@ private:
template
MessageID callAsyncInternal(const MethodID methodID,
- const PeerID peerID,
+ const PeerID& peerID,
const std::shared_ptr& data,
const typename ResultHandler::type& process);
@@ -475,7 +475,7 @@ private:
template
void signalInternal(const MethodID methodID,
- const PeerID peerID,
+ const PeerID& peerID,
const std::shared_ptr& data);
// Request handlers
@@ -487,28 +487,28 @@ private:
bool onFinishRequest(FinishRequest& request);
bool onReturnValue(Peers::iterator& peerIt,
- const MessageID messageID);
+ const MessageID& messageID);
bool onRemoteMethod(Peers::iterator& peerIt,
const MethodID methodID,
- const MessageID messageID,
+ const MessageID& messageID,
std::shared_ptr methodCallbacks);
bool onRemoteSignal(Peers::iterator& peerIt,
const MethodID methodID,
- const MessageID messageID,
+ const MessageID& messageID,
std::shared_ptr signalCallbacks);
void removePeerInternal(Peers::iterator peerIt,
const std::exception_ptr& exceptionPtr);
- void removePeerSyncInternal(const PeerID peerID, Lock& lock);
+ void removePeerSyncInternal(const PeerID& peerID, Lock& lock);
- void onNewSignals(const PeerID peerID,
+ void onNewSignals(const PeerID& peerID,
std::shared_ptr& data);
- void onErrorSignal(const PeerID peerID,
+ void onErrorSignal(const PeerID& peerID,
std::shared_ptr& data);
Peers::iterator getPeerInfoIterator(const FileDescriptor fd);
- Peers::iterator getPeerInfoIterator(const PeerID peerID);
+ Peers::iterator getPeerInfoIterator(const PeerID& peerID);
};
@@ -616,7 +616,7 @@ void Processor::setSignalHandler(const MethodID methodID,
template
MessageID Processor::callAsync(const MethodID methodID,
- const PeerID peerID,
+ const PeerID& peerID,
const std::shared_ptr& data,
const typename ResultHandler::type& process)
{
@@ -626,7 +626,7 @@ MessageID Processor::callAsync(const MethodID methodID,
template
MessageID Processor::callAsyncInternal(const MethodID methodID,
- const PeerID peerID,
+ const PeerID& peerID,
const std::shared_ptr& data,
const typename ResultHandler::type& process)
{
@@ -638,7 +638,7 @@ MessageID Processor::callAsyncInternal(const MethodID methodID,
template
std::shared_ptr Processor::callSync(const MethodID methodID,
- const PeerID peerID,
+ const PeerID& peerID,
const std::shared_ptr& data,
unsigned int timeoutMS)
{
@@ -692,7 +692,7 @@ std::shared_ptr Processor::callSync(const MethodID methodID,
template
void Processor::signalInternal(const MethodID methodID,
- const PeerID peerID,
+ const PeerID& peerID,
const std::shared_ptr& data)
{
auto requestPtr = SignalRequest::create(methodID, peerID, data);
diff --git a/libs/ipc/internals/remove-peer-request.hpp b/libs/ipc/internals/remove-peer-request.hpp
index c9f7ec7..e124227 100644
--- a/libs/ipc/internals/remove-peer-request.hpp
+++ b/libs/ipc/internals/remove-peer-request.hpp
@@ -37,7 +37,7 @@ public:
RemovePeerRequest(const RemovePeerRequest&) = delete;
RemovePeerRequest& operator=(const RemovePeerRequest&) = delete;
- RemovePeerRequest(const PeerID peerID,
+ RemovePeerRequest(const PeerID& peerID,
const std::shared_ptr& conditionPtr)
: peerID(peerID),
conditionPtr(conditionPtr)
diff --git a/libs/ipc/internals/result-builder.hpp b/libs/ipc/internals/result-builder.hpp
index 97134e3..b9c9471 100644
--- a/libs/ipc/internals/result-builder.hpp
+++ b/libs/ipc/internals/result-builder.hpp
@@ -39,12 +39,12 @@ public:
mExceptionPtr(nullptr)
{}
- ResultBuilder(const std::exception_ptr& exceptionPtr)
+ explicit ResultBuilder(const std::exception_ptr& exceptionPtr)
: mData(nullptr),
mExceptionPtr(exceptionPtr)
{}
- ResultBuilder(const std::shared_ptr& data)
+ explicit ResultBuilder(const std::shared_ptr& data)
: mData(data),
mExceptionPtr(nullptr)
@@ -68,9 +68,3 @@ typedef std::function ResultBuilderHandler;
} // namespace ipc
#endif // COMMON_IPC_RESULT_BUILDER_HPP
-
-
-
-
-
-
diff --git a/libs/ipc/internals/send-result-request.hpp b/libs/ipc/internals/send-result-request.hpp
index a6ed2b4..de512c0 100644
--- a/libs/ipc/internals/send-result-request.hpp
+++ b/libs/ipc/internals/send-result-request.hpp
@@ -36,8 +36,8 @@ public:
SendResultRequest& operator=(const SendResultRequest&) = delete;
SendResultRequest(const MethodID methodID,
- const PeerID peerID,
- const MessageID messageID,
+ const PeerID& peerID,
+ const MessageID& messageID,
const std::shared_ptr& data)
: methodID(methodID),
peerID(peerID),
diff --git a/libs/ipc/internals/signal-request.hpp b/libs/ipc/internals/signal-request.hpp
index 904d3f3..aa597c0 100644
--- a/libs/ipc/internals/signal-request.hpp
+++ b/libs/ipc/internals/signal-request.hpp
@@ -38,7 +38,7 @@ public:
template
static std::shared_ptr create(const MethodID methodID,
- const PeerID peerID,
+ const PeerID& peerID,
const std::shared_ptr& data);
MethodID methodID;
@@ -48,7 +48,7 @@ public:
SerializeCallback serialize;
private:
- SignalRequest(const MethodID methodID, const PeerID peerID)
+ SignalRequest(const MethodID methodID, const PeerID& peerID)
: methodID(methodID),
peerID(peerID),
messageID(getNextMessageID())
@@ -58,7 +58,7 @@ private:
template
std::shared_ptr SignalRequest::create(const MethodID methodID,
- const PeerID peerID,
+ const PeerID& peerID,
const std::shared_ptr& data)
{
std::shared_ptr request(new SignalRequest(methodID, peerID));
diff --git a/libs/ipc/method-result.cpp b/libs/ipc/method-result.cpp
index 97eb450..f110689 100644
--- a/libs/ipc/method-result.cpp
+++ b/libs/ipc/method-result.cpp
@@ -31,8 +31,8 @@ namespace ipc {
MethodResult::MethodResult(Processor& processor,
const MethodID methodID,
- const MessageID messageID,
- const PeerID peerID)
+ const MessageID& messageID,
+ const PeerID& peerID)
: mProcessor(processor),
mMethodID(methodID),
mPeerID(peerID),
@@ -54,7 +54,7 @@ void MethodResult::setError(const int code, const std::string& message)
mProcessor.sendError(mPeerID, mMessageID, code, message);
}
-PeerID MethodResult::getPeerID()
+PeerID MethodResult::getPeerID() const
{
return mPeerID;
}
diff --git a/libs/ipc/method-result.hpp b/libs/ipc/method-result.hpp
index c1729f7..c6fce37 100644
--- a/libs/ipc/method-result.hpp
+++ b/libs/ipc/method-result.hpp
@@ -43,8 +43,8 @@ public:
MethodResult(Processor& processor,
const MethodID methodID,
- const MessageID messageID,
- const PeerID peerID);
+ const MessageID& messageID,
+ const PeerID& peerID);
template
@@ -55,7 +55,7 @@ public:
void setVoid();
void setError(const int code, const std::string& message);
- PeerID getPeerID();
+ PeerID getPeerID() const;
private:
Processor& mProcessor;
diff --git a/libs/ipc/service.hpp b/libs/ipc/service.hpp
index a5f7c86..6d953dd 100644
--- a/libs/ipc/service.hpp
+++ b/libs/ipc/service.hpp
@@ -191,7 +191,7 @@ public:
*/
template
std::shared_ptr callSync(const MethodID methodID,
- const PeerID peerID,
+ const PeerID& peerID,
const std::shared_ptr& data,
unsigned int timeoutMS = 5000);
@@ -208,7 +208,7 @@ public:
*/
template
void callAsync(const MethodID methodID,
- const PeerID peerID,
+ const PeerID& peerID,
const std::shared_ptr& data,
const typename ResultHandler::type& resultCallback);
@@ -251,7 +251,7 @@ void Service::setSignalHandler(const MethodID methodID,
template
std::shared_ptr Service::callSync(const MethodID methodID,
- const PeerID peerID,
+ const PeerID& peerID,
const std::shared_ptr& data,
unsigned int timeoutMS)
{
@@ -263,7 +263,7 @@ std::shared_ptr Service::callSync(const MethodID methodID,
template
void Service::callAsync(const MethodID methodID,
- const PeerID peerID,
+ const PeerID& peerID,
const std::shared_ptr& data,
const typename ResultHandler::type& resultCallback)
{
diff --git a/libs/lxcpp/exception.hpp b/libs/lxcpp/exception.hpp
index af81779..7764282 100644
--- a/libs/lxcpp/exception.hpp
+++ b/libs/lxcpp/exception.hpp
@@ -32,57 +32,57 @@ namespace lxcpp {
* Base class for exceptions in lxcpp
*/
struct Exception: public std::runtime_error {
- Exception(const std::string& message)
+ explicit Exception(const std::string& message)
: std::runtime_error(message) {}
};
struct NotImplementedException: public Exception {
- NotImplementedException(const std::string& message = "Functionality not yet implemented")
+ explicit NotImplementedException(const std::string& message = "Functionality not yet implemented")
: Exception(message) {}
};
struct ProcessSetupException: public Exception {
- ProcessSetupException(const std::string& message = "Error while setting up a process")
+ explicit ProcessSetupException(const std::string& message = "Error while setting up a process")
: Exception(message) {}
};
struct FileSystemSetupException: public Exception {
- FileSystemSetupException(const std::string& message = "Error during a file system operation")
+ explicit FileSystemSetupException(const std::string& message = "Error during a file system operation")
: Exception(message) {}
};
struct EnvironmentSetupException: public Exception {
- EnvironmentSetupException(const std::string& message = "Error during handling environment variables")
+ explicit EnvironmentSetupException(const std::string& message = "Error during handling environment variables")
: Exception(message) {}
};
struct CredentialSetupException: public Exception {
- CredentialSetupException(const std::string& message = "Error during handling environment variables")
+ explicit CredentialSetupException(const std::string& message = "Error during handling environment variables")
: Exception(message) {}
};
struct CapabilitySetupException: public Exception {
- CapabilitySetupException(const std::string& message = "Error during a capability operation")
+ explicit CapabilitySetupException(const std::string& message = "Error during a capability operation")
: Exception(message) {}
};
struct BadArgument: public Exception {
- BadArgument(const std::string& message = "Bad argument passed")
+ explicit BadArgument(const std::string& message = "Bad argument passed")
: Exception(message) {}
};
struct NoSuchValue: public Exception {
- NoSuchValue(const std::string& message = "Value not found")
+ explicit NoSuchValue(const std::string& message = "Value not found")
: Exception(message) {}
};
struct NetworkException : public Exception {
- NetworkException (const std::string& message = "Error during setting up a network")
+ explicit NetworkException (const std::string& message = "Error during setting up a network")
: Exception(message) {}
};
struct ConfigureException: public Exception {
- ConfigureException(const std::string& message = "Error while configuring a container")
+ explicit ConfigureException(const std::string& message = "Error while configuring a container")
: Exception(message) {}
};
diff --git a/server/exception.hpp b/server/exception.hpp
index e1b3be4..e72df76 100644
--- a/server/exception.hpp
+++ b/server/exception.hpp
@@ -37,7 +37,7 @@ namespace vasum {
*/
struct ServerException: public VasumException {
- ServerException(const std::string& error) : VasumException(error) {}
+ explicit ServerException(const std::string& error) : VasumException(error) {}
};
/**
@@ -46,7 +46,7 @@ struct ServerException: public VasumException {
*/
struct ZoneOperationException: public ServerException {
- ZoneOperationException(const std::string& error) : ServerException(error) {}
+ explicit ZoneOperationException(const std::string& error) : ServerException(error) {}
};
/**
@@ -54,7 +54,7 @@ struct ZoneOperationException: public ServerException {
*/
struct InvalidZoneIdException : public ServerException {
- InvalidZoneIdException(const std::string& error) : ServerException(error) {}
+ explicit InvalidZoneIdException(const std::string& error) : ServerException(error) {}
};
/**
@@ -62,7 +62,7 @@ struct InvalidZoneIdException : public ServerException {
*/
struct ZoneConnectionException: public ServerException {
- ZoneConnectionException(const std::string& error) : ServerException(error) {}
+ explicit ZoneConnectionException(const std::string& error) : ServerException(error) {}
};
/**
@@ -70,7 +70,7 @@ struct ZoneConnectionException: public ServerException {
*/
struct HostConnectionException: public ServerException {
- HostConnectionException(const std::string& error) : ServerException(error) {}
+ explicit HostConnectionException(const std::string& error) : ServerException(error) {}
};
/**
@@ -79,12 +79,12 @@ struct HostConnectionException: public ServerException {
*/
struct InputMonitorException: public ServerException {
- InputMonitorException(const std::string& error) : ServerException(error) {}
+ explicit InputMonitorException(const std::string& error) : ServerException(error) {}
};
struct TimeoutException: public InputMonitorException {
- TimeoutException(const std::string& error) : InputMonitorException (error) {}
+ explicit TimeoutException(const std::string& error) : InputMonitorException (error) {}
};
}
diff --git a/server/zones-manager.cpp b/server/zones-manager.cpp
index 55e63f5..baf3ed1 100644
--- a/server/zones-manager.cpp
+++ b/server/zones-manager.cpp
@@ -1266,7 +1266,7 @@ void ZonesManager::createZone(const std::string& id,
} catch (std::runtime_error& e) {
LOGE("Generate config failed: " << e.what());
utils::launchAsRoot(std::bind(removeAllWrapper, zonePathStr));
- throw e;
+ throw;
}
LOGT("Creating new zone");
@@ -1275,7 +1275,7 @@ void ZonesManager::createZone(const std::string& id,
} catch (std::runtime_error& e) {
LOGE("Creating new zone failed: " << e.what());
utils::launchAsRoot(std::bind(removeAllWrapper, zonePathStr));
- throw e;
+ throw;
}
mDynamicConfig.zoneIds.push_back(id);
diff --git a/tests/cppcheck/cppcheck.sh b/tests/cppcheck/cppcheck.sh
index b8bb637..bbe96b5 100755
--- a/tests/cppcheck/cppcheck.sh
+++ b/tests/cppcheck/cppcheck.sh
@@ -11,5 +11,7 @@ OPT+=" -I common"
OPT+=" -I libs"
OPT+=" -I client"
OPT+=" -I server"
+OPT+=" -I tests/unit_tests"
+OPT+=" -I tests/unit_tests/socket_test_service"
OPT+=" -U__NR_capset"
-cppcheck ${OPT} --template=gcc ./ 1>/dev/null
+cppcheck ${OPT} --template=gcc $@ ./ 1>/dev/null
diff --git a/tests/cppcheck/cppcheck.suppress b/tests/cppcheck/cppcheck.suppress
index d3b098f..8d7380b 100644
--- a/tests/cppcheck/cppcheck.suppress
+++ b/tests/cppcheck/cppcheck.suppress
@@ -1,7 +1,26 @@
// public API functions (or write tests to use them all)
unusedFunction:wrapper/wrapper-compatibility.cpp
unusedFunction:wrapper/wrapper.cpp
+unusedFunction:libs/config/kvstore.cpp
+unusedFunction:libs/ipc/internals/processor.cpp
+unusedFunction:server/zones-manager.cpp
+unusedFunction:libs/lxcpp/container-impl.cpp
+unusedFunction:libs/lxcpp/filesystem.cpp
+unusedFunction:libs/lxcpp/network.cpp
+unusedFunction:libs/lxcpp/network-config.cpp
+unusedFunction:client/vasum-client.cpp
+unusedFunction:common/netlink/netlink-message.cpp
+unusedFunction:common/utils/fd-utils.cpp
+unusedFunction:server/zone.cpp
-// lambda not recognized to catch exception (v1.68)
-exceptThrowInNoexecptFunction:client/vasum-client-impl.cpp
+// lambda not recognized to catch exception (v1.69)
+throwInNoexceptFunction:client/vasum-client-impl.cpp
+// complains that all constructors with 1 argument should be explicit
+noExplicitConstructor
+
+// required for C abstraction
+unusedStructMember:common/utils/initctl.cpp
+
+// functions called by external utilities
+unusedFunction:tests/unit_tests/ut.cpp
diff --git a/tests/unit_tests/ipc/ut-ipc.cpp b/tests/unit_tests/ipc/ut-ipc.cpp
index 853faa2..5ba540e 100644
--- a/tests/unit_tests/ipc/ut-ipc.cpp
+++ b/tests/unit_tests/ipc/ut-ipc.cpp
@@ -237,7 +237,7 @@ void testEcho(Client& c, const MethodID methodID)
BOOST_CHECK_EQUAL(recvData->intVal, sentData->intVal);
}
-void testEcho(Service& s, const MethodID methodID, const PeerID peerID)
+void testEcho(Service& s, const MethodID methodID, const PeerID& peerID)
{
std::shared_ptr sentData(new SendData(56));
std::shared_ptr recvData = s.callSync(methodID, peerID, sentData, TIMEOUT);
diff --git a/tests/unit_tests/server/ut-zones-manager.cpp b/tests/unit_tests/server/ut-zones-manager.cpp
index 819da53..6d6a71d 100644
--- a/tests/unit_tests/server/ut-zones-manager.cpp
+++ b/tests/unit_tests/server/ut-zones-manager.cpp
@@ -163,7 +163,7 @@ public:
void signalSubscribe(const DbusConnection::SignalCallback& callback)
{
- mClient->signalSubscribe(callback, isHost() ? api::dbus::BUS_NAME : api::dbus::BUS_NAME);
+ mClient->signalSubscribe(callback, api::dbus::BUS_NAME);
}
void callSwitchToDefault()
@@ -225,12 +225,9 @@ public:
interface.c_str(),
method.c_str(),
parameters);
- GVariantPtr result = mClient->callMethod(isHost() ? api::dbus::BUS_NAME :
- api::dbus::BUS_NAME,
- isHost() ? api::dbus::OBJECT_PATH :
- api::dbus::OBJECT_PATH,
- isHost() ? api::dbus::INTERFACE :
- api::dbus::INTERFACE,
+ GVariantPtr result = mClient->callMethod(api::dbus::BUS_NAME,
+ api::dbus::OBJECT_PATH,
+ api::dbus::INTERFACE,
api::dbus::METHOD_PROXY_CALL,
packedParameters,
"(v)");
diff --git a/tests/unit_tests/utils/ut-worker.cpp b/tests/unit_tests/utils/ut-worker.cpp
index 52c14fd..b05aef0 100644
--- a/tests/unit_tests/utils/ut-worker.cpp
+++ b/tests/unit_tests/utils/ut-worker.cpp
@@ -166,7 +166,7 @@ BOOST_AUTO_TEST_CASE(NoCopy)
Task(Task&& r) : count(r.count) {}
Task& operator=(const Task&) = delete;
Task& operator=(Task&&) = delete;
- void operator() () {}
+ void operator() () const {}
};
diff --git a/zone-daemon/exception.hpp b/zone-daemon/exception.hpp
index 5fcf54d..9889e62 100644
--- a/zone-daemon/exception.hpp
+++ b/zone-daemon/exception.hpp
@@ -37,7 +37,7 @@ namespace zone_daemon {
*/
struct ZoneDaemonException: public VasumException {
- ZoneDaemonException(const std::string& error) : VasumException(error) {}
+ explicit ZoneDaemonException(const std::string& error) : VasumException(error) {}
};
--
2.7.4
From ded590f480be25eb3b8c593187606f9859c942ee Mon Sep 17 00:00:00 2001
From: Pawel Kubik
Date: Wed, 9 Sep 2015 17:27:08 +0200
Subject: [PATCH 02/16] Static common library
[Feature] Static common library
[Cause] Need for cleaner dependency management
[Solution] Rules for building static common library, linking it
with other binaries instead of manually adding sources
[Verification] Build, install, run tests and main executables
Change-Id: I6eccf5a706b88ca4576e5bfc31b73ebe87177ff5
---
CMakeLists.txt | 2 +-
cli/CMakeLists.txt | 10 ++++------
client/CMakeLists.txt | 9 ++++-----
common/CMakeLists.txt | 29 +++++++++++++++++++++++++++++
libs/dbus/CMakeLists.txt | 15 +++++----------
libs/ipc/CMakeLists.txt | 14 +++++---------
libs/logger/CMakeLists.txt | 15 ++++++---------
libs/lxcpp/CMakeLists.txt | 23 ++++++-----------------
server/CMakeLists.txt | 8 ++++----
tests/unit_tests/CMakeLists.txt | 21 ++++++++++++---------
wrapper/CMakeLists.txt | 12 ++++--------
zone-daemon/CMakeLists.txt | 7 +++----
12 files changed, 83 insertions(+), 82 deletions(-)
create mode 100644 common/CMakeLists.txt
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 9823735..5b98eee 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -188,6 +188,7 @@ SET(VSM_CONFIG_INSTALL_DIR ${SYSCONF_INSTALL_DIR}/vasum)
SET(VSM_SERVER_IPC_SOCKET_PATH ${RUN_DIR}/vasum.socket)
SET(VSM_UNIT_TESTS_IPC_SOCKET_PATH ${RUN_DIR}/vasum-ipc-unit-tests.socket)
+ADD_SUBDIRECTORY(${COMMON_FOLDER})
ADD_SUBDIRECTORY(${LOGGER_FOLDER})
ADD_SUBDIRECTORY(${LXCPP_FOLDER})
IF(NOT WITHOUT_DBUS)
@@ -204,4 +205,3 @@ ENDIF(NOT WITHOUT_DBUS)
ADD_SUBDIRECTORY(${TESTS_FOLDER})
ADD_SUBDIRECTORY(${CLI_FOLDER})
ADD_SUBDIRECTORY(${WRAPPER_FOLDER})
-
diff --git a/cli/CMakeLists.txt b/cli/CMakeLists.txt
index 0f4fbfe..478cc25 100644
--- a/cli/CMakeLists.txt
+++ b/cli/CMakeLists.txt
@@ -19,14 +19,14 @@
MESSAGE(STATUS "")
MESSAGE(STATUS "Generating makefile for the command line interface...")
-FILE(GLOB cli_SRCS *.cpp *.hpp
- ${COMMON_FOLDER}/utils/c-array.cpp
- ${COMMON_FOLDER}/utils/c-array.hpp)
+FILE(GLOB cli_SRCS *.cpp *.hpp)
## Setup target ################################################################
SET(CLI_CODENAME "vsm")
ADD_EXECUTABLE(${CLI_CODENAME} ${cli_SRCS})
+ADD_DEPENDENCIES(${CLI_CODENAME} Common ${PROJECT_NAME}-client Ipc)
+
## Readline detection ##########################################################
FIND_PATH(READLINE_INCLUDE_DIR readline/readline.h
@@ -46,11 +46,9 @@ INCLUDE_DIRECTORIES(${READLINE_INCLUDE_DIRS})
TARGET_LINK_LIBRARIES(${CLI_CODENAME} ${READLINE_LIBRARIES})
## Link libraries ##############################################################
-PKG_CHECK_MODULES(LIB_DEPS REQUIRED vasum)
-
INCLUDE_DIRECTORIES(${CLIENT_FOLDER})
INCLUDE_DIRECTORIES(${COMMON_FOLDER})
-TARGET_LINK_LIBRARIES(${CLI_CODENAME} ${PROJECT_NAME}-client ${LIB_DEPS_LIBRARIES} Ipc)
+TARGET_LINK_LIBRARIES(${CLI_CODENAME} Common ${PROJECT_NAME}-client ${LIB_DEPS_LIBRARIES} Ipc)
CONFIGURE_FILE(support/vsm-completion.sh.in
${CMAKE_BINARY_DIR}/vsm-completion.sh
diff --git a/client/CMakeLists.txt b/client/CMakeLists.txt
index f0d1828..e4e9ca5 100644
--- a/client/CMakeLists.txt
+++ b/client/CMakeLists.txt
@@ -22,9 +22,6 @@ MESSAGE(STATUS "")
MESSAGE(STATUS "Generating makefile for the Client...")
FILE(GLOB project_SRCS *.cpp *.hpp *.h)
-FILE(GLOB common_SRCS ${COMMON_FOLDER}/utils/*.hpp ${COMMON_FOLDER}/utils/*.cpp
- ${COMMON_FOLDER}/*.hpp ${COMMON_FOLDER}/*.cpp)
-
SET(_LIB_VERSION_ "${VERSION}")
SET(_LIB_SOVERSION_ "0")
SET(PC_FILE "${PROJECT_NAME}.pc")
@@ -36,12 +33,14 @@ SET(PC_FILE "${PROJECT_NAME}.pc")
ADD_DEFINITIONS(-fvisibility=hidden)
## Setup target ################################################################
-ADD_LIBRARY(${PROJECT_NAME} SHARED ${project_SRCS} ${common_SRCS})
+ADD_LIBRARY(${PROJECT_NAME} SHARED ${project_SRCS})
SET_TARGET_PROPERTIES(${PROJECT_NAME} PROPERTIES
SOVERSION ${_LIB_SOVERSION_}
VERSION ${_LIB_VERSION_}
COMPILE_DEFINITIONS HOST_IPC_SOCKET="${VSM_SERVER_IPC_SOCKET_PATH}")
+ADD_DEPENDENCIES(${PROJECT_NAME} Common Config Ipc)
+
## Link libraries ##############################################################
FIND_PACKAGE(Boost COMPONENTS system filesystem)
PKG_CHECK_MODULES(LIB_DEPS REQUIRED gio-2.0)
@@ -51,7 +50,7 @@ INCLUDE_DIRECTORIES(${LIBS_FOLDER})
INCLUDE_DIRECTORIES(${IPC_FOLDER})
INCLUDE_DIRECTORIES(${SERVER_FOLDER})
-TARGET_LINK_LIBRARIES(${PROJECT_NAME} ${LIB_DEPS_LIBRARIES} ${Boost_LIBRARIES} Config Ipc)
+TARGET_LINK_LIBRARIES(${PROJECT_NAME} Common ${LIB_DEPS_LIBRARIES} ${Boost_LIBRARIES} Config Ipc)
IF(NOT WITHOUT_DBUS)
TARGET_LINK_LIBRARIES(${PROJECT_NAME} SimpleDbus)
ENDIF(NOT WITHOUT_DBUS)
diff --git a/common/CMakeLists.txt b/common/CMakeLists.txt
new file mode 100644
index 0000000..8534a46
--- /dev/null
+++ b/common/CMakeLists.txt
@@ -0,0 +1,29 @@
+# Copyright (c) 2015 Samsung Electronics Co., Ltd All Rights Reserved
+#
+# 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 CMakeLists.txt
+# @author Pawel Kubik (p.kubik@samsung.com)
+#
+
+MESSAGE(STATUS "")
+MESSAGE(STATUS "Generating makefile for the libCommon...")
+FILE(GLOB_RECURSE SRCS *.cpp *.hpp)
+
+## Setup target ################################################################
+ADD_LIBRARY(Common STATIC ${SRCS})
+
+PKG_CHECK_MODULES(COMMON_DEPS REQUIRED glib-2.0)
+
+INCLUDE_DIRECTORIES(SYSTEM ${COMMON_FOLDER} ${LIBS_FOLDER} ${COMMON_DEPS_INCLUDE_DIRS})
diff --git a/libs/dbus/CMakeLists.txt b/libs/dbus/CMakeLists.txt
index 840b3b4..6045c04 100644
--- a/libs/dbus/CMakeLists.txt
+++ b/libs/dbus/CMakeLists.txt
@@ -22,14 +22,7 @@ PROJECT(SimpleDbus)
MESSAGE(STATUS "")
MESSAGE(STATUS "Generating makefile for the libSimpleDbus...")
FILE(GLOB HEADERS *.hpp)
-FILE(GLOB HEADERS_UTILS ${COMMON_FOLDER}/utils/callback-guard.hpp
- ${COMMON_FOLDER}/utils/scoped-gerror.hpp
- ${COMMON_FOLDER}/utils/glib-utils.hpp
- ${COMMON_FOLDER}/utils/callback-wrapper.hpp)
-FILE(GLOB SRCS_UTILS ${COMMON_FOLDER}/utils/callback-guard.cpp
- ${COMMON_FOLDER}/utils/scoped-gerror.cpp
- ${COMMON_FOLDER}/utils/glib-utils.cpp
- ${COMMON_FOLDER}/utils/callback-wrapper.cpp)
+FILE(GLOB HEADERS_UTILS ${COMMON_FOLDER}/utils/callback-guard.hpp)
FILE(GLOB SRCS *.cpp *.hpp)
SET(_LIB_VERSION_ "${VERSION}")
@@ -37,18 +30,20 @@ SET(_LIB_SOVERSION_ "0")
SET(PC_FILE "lib${PROJECT_NAME}.pc")
## Setup target ################################################################
-ADD_LIBRARY(${PROJECT_NAME} SHARED ${SRCS} ${SRCS_UTILS})
+ADD_LIBRARY(${PROJECT_NAME} SHARED ${SRCS})
SET_TARGET_PROPERTIES(${PROJECT_NAME} PROPERTIES
SOVERSION ${_LIB_SOVERSION_}
VERSION ${_LIB_VERSION_}
)
+ADD_DEPENDENCIES(${PROJECT_NAME} Common)
+
## Link libraries ##############################################################
PKG_CHECK_MODULES(DBUS_DEPS REQUIRED glib-2.0 gio-2.0)
INCLUDE_DIRECTORIES(${COMMON_FOLDER})
INCLUDE_DIRECTORIES(${LIBS_FOLDER})
INCLUDE_DIRECTORIES(SYSTEM ${DBUS_DEPS_INCLUDE_DIRS})
-TARGET_LINK_LIBRARIES(${PROJECT_NAME} ${pkgs_LDFLAGS} ${DBUS_DEPS_LIBRARIES} Logger)
+TARGET_LINK_LIBRARIES(${PROJECT_NAME} Common ${pkgs_LDFLAGS} ${DBUS_DEPS_LIBRARIES} Logger)
## Generate the pc file ########################################################
CONFIGURE_FILE(${PC_FILE}.in ${CMAKE_CURRENT_BINARY_DIR}/${PC_FILE} @ONLY)
diff --git a/libs/ipc/CMakeLists.txt b/libs/ipc/CMakeLists.txt
index 854e0de..9e1e6f9 100644
--- a/libs/ipc/CMakeLists.txt
+++ b/libs/ipc/CMakeLists.txt
@@ -25,29 +25,25 @@ MESSAGE(STATUS "Generating makefile for the libIpc...")
FILE(GLOB HEADERS *.hpp)
FILE(GLOB HEADERS_INTERNALS internals/*.hpp)
FILE(GLOB HEADERS_EPOLL epoll/*.hpp)
-FILE(GLOB HEADERS_UTILS ${COMMON_FOLDER}/utils/fd-utils.hpp
- ${COMMON_FOLDER}/utils/eventfd.hpp
- ${COMMON_FOLDER}/utils/exception.hpp
+FILE(GLOB HEADERS_UTILS ${COMMON_FOLDER}/utils/eventfd.hpp
${COMMON_FOLDER}/utils/callback-guard.hpp)
FILE(GLOB SRCS *.cpp)
FILE(GLOB SRCS_INTERNALS internals/*.cpp)
FILE(GLOB SRCS_EPOLL epoll/*.cpp)
-FILE(GLOB SRCS_UTILS ${COMMON_FOLDER}/utils/fd-utils.cpp
- ${COMMON_FOLDER}/utils/eventfd.cpp
- ${COMMON_FOLDER}/utils/exception.cpp
- ${COMMON_FOLDER}/utils/callback-guard.cpp)
SET(_LIB_VERSION_ "${VERSION}")
SET(_LIB_SOVERSION_ "0")
SET(PC_FILE "lib${PROJECT_NAME}.pc")
## Setup target ################################################################
-ADD_LIBRARY(${PROJECT_NAME} SHARED ${SRCS} ${SRCS_INTERNALS} ${SRCS_UTILS} ${SRCS_EPOLL})
+ADD_LIBRARY(${PROJECT_NAME} SHARED ${SRCS} ${SRCS_INTERNALS} ${SRCS_EPOLL})
SET_TARGET_PROPERTIES(${PROJECT_NAME} PROPERTIES
SOVERSION ${_LIB_SOVERSION_}
VERSION ${_LIB_VERSION_}
)
+ADD_DEPENDENCIES(${PROJECT_NAME} Common)
+
## Link libraries ##############################################################
IF(NOT WITHOUT_SYSTEMD)
PKG_CHECK_MODULES(IPC_DEPS REQUIRED libsystemd-daemon uuid)
@@ -56,7 +52,7 @@ ENDIF(NOT WITHOUT_SYSTEMD)
INCLUDE_DIRECTORIES(${LIBS_FOLDER})
INCLUDE_DIRECTORIES(${COMMON_FOLDER})
INCLUDE_DIRECTORIES(SYSTEM ${DBUS_DEPS_INCLUDE_DIRS} ${IPC_DEPS_INCLUDE_DIRS} ${CONFIG_DEPS_INCLUDE_DIRS} ${JSON_C_INCLUDE_DIRS})
-TARGET_LINK_LIBRARIES(${PROJECT_NAME} ${pkgs_LDFLAGS} ${IPC_DEPS_LIBRARIES} Logger Config)
+TARGET_LINK_LIBRARIES(${PROJECT_NAME} Common ${pkgs_LDFLAGS} ${IPC_DEPS_LIBRARIES} Logger Config)
## Generate the pc file ########################################################
CONFIGURE_FILE(${PC_FILE}.in ${CMAKE_CURRENT_BINARY_DIR}/${PC_FILE} @ONLY)
diff --git a/libs/logger/CMakeLists.txt b/libs/logger/CMakeLists.txt
index 6a65b34..b44a876 100644
--- a/libs/logger/CMakeLists.txt
+++ b/libs/logger/CMakeLists.txt
@@ -21,22 +21,22 @@ PROJECT(Logger)
MESSAGE(STATUS "")
MESSAGE(STATUS "Generating makefile for the libLogger...")
-FILE(GLOB HEADERS *.hpp)
-FILE(GLOB SRCS *.cpp *.hpp)
-FILE(GLOB HEADERS_UTILS ${COMMON_FOLDER}/utils/ccolor.hpp)
-FILE(GLOB SRCS_UTILS ${COMMON_FOLDER}/utils/ccolor.cpp)
+FILE(GLOB HEADERS *.hpp)
+FILE(GLOB SRCS *.cpp *.hpp)
SET(_LIB_VERSION_ "${VERSION}")
SET(_LIB_SOVERSION_ "0")
SET(PC_FILE "lib${PROJECT_NAME}.pc")
## Setup target ################################################################
-ADD_LIBRARY(${PROJECT_NAME} SHARED ${SRCS} ${SRCS_UTILS})
+ADD_LIBRARY(${PROJECT_NAME} SHARED ${SRCS})
SET_TARGET_PROPERTIES(${PROJECT_NAME} PROPERTIES
SOVERSION ${_LIB_SOVERSION_}
VERSION ${_LIB_VERSION_}
)
+ADD_DEPENDENCIES(${PROJECT_NAME} Common)
+
## Link libraries ##############################################################
IF(NOT WITHOUT_SYSTEMD)
PKG_CHECK_MODULES(LOGGER_DEPS REQUIRED libsystemd-journal)
@@ -44,7 +44,7 @@ ENDIF(NOT WITHOUT_SYSTEMD)
INCLUDE_DIRECTORIES(${LIBS_FOLDER} ${COMMON_FOLDER})
INCLUDE_DIRECTORIES(SYSTEM ${LOGGER_DEPS_INCLUDE_DIRS})
-TARGET_LINK_LIBRARIES(${PROJECT_NAME} ${pkgs_LDFLAGS} ${LOGGER_DEPS_LIBRARIES})
+TARGET_LINK_LIBRARIES(${PROJECT_NAME} Common ${pkgs_LDFLAGS} ${LOGGER_DEPS_LIBRARIES})
## Generate the pc file ########################################################
CONFIGURE_FILE(${PC_FILE}.in ${CMAKE_CURRENT_BINARY_DIR}/${PC_FILE} @ONLY)
@@ -59,6 +59,3 @@ INSTALL(TARGETS ${PROJECT_NAME}
INSTALL(FILES ${HEADERS}
DESTINATION ${INCLUDE_INSTALL_DIR}/vasum-tools/logger)
-
-INSTALL(FILES ${HEADERS_UTILS}
- DESTINATION ${INCLUDE_INSTALL_DIR}/vasum-tools/logger/utils)
diff --git a/libs/lxcpp/CMakeLists.txt b/libs/lxcpp/CMakeLists.txt
index c76de74..203ddd3 100644
--- a/libs/lxcpp/CMakeLists.txt
+++ b/libs/lxcpp/CMakeLists.txt
@@ -21,22 +21,11 @@ PROJECT(lxcpp)
MESSAGE(STATUS "")
MESSAGE(STATUS "Generating makefile for the liblxcpp...")
-FILE(GLOB HEADERS *.hpp)
-FILE(GLOB HEADERS_UTILS ${COMMON_FOLDER}/utils/fd-utils.hpp
- ${COMMON_FOLDER}/utils/exception.hpp
- ${COMMON_FOLDER}/utils/channel.hpp
- ${COMMON_FOLDER}/utils/environment.hpp
- ${COMMON_FOLDER}/utils/execute.hpp)
-FILE(GLOB HEADERS_NETLINK ${COMMON_FOLDER}/netlink/*.hpp)
+FILE(GLOB HEADERS *.hpp)
+FILE(GLOB HEADERS_UTILS ${COMMON_FOLDER}/utils/channel.hpp)
FILE(GLOB HEADERS_COMMANDS commands/*.hpp)
FILE(GLOB SRCS *.cpp *.hpp)
-FILE(GLOB SRCS_UTILS ${COMMON_FOLDER}/utils/fd-utils.cpp
- ${COMMON_FOLDER}/utils/exception.cpp
- ${COMMON_FOLDER}/utils/channel.cpp
- ${COMMON_FOLDER}/utils/environment.cpp
- ${COMMON_FOLDER}/utils/execute.cpp)
-FILE(GLOB SRCS_NETLINK ${COMMON_FOLDER}/netlink/*.cpp)
FILE(GLOB SRCS_COMMANDS commands/*.cpp)
SET(_LIB_VERSION_ "${VERSION}")
@@ -44,17 +33,19 @@ SET(_LIB_SOVERSION_ "0")
SET(PC_FILE "lib${PROJECT_NAME}.pc")
## Setup target ################################################################
-ADD_LIBRARY(${PROJECT_NAME} SHARED ${SRCS} ${SRCS_UTILS} ${SRCS_NETLINK} ${SRCS_COMMANDS})
+ADD_LIBRARY(${PROJECT_NAME} SHARED ${SRCS} ${SRCS_COMMANDS})
SET_TARGET_PROPERTIES(${PROJECT_NAME} PROPERTIES
SOVERSION ${_LIB_SOVERSION_}
VERSION ${_LIB_VERSION_}
)
+ADD_DEPENDENCIES(${PROJECT_NAME} Common Logger)
+
## Link libraries ##############################################################
FIND_PACKAGE(Boost COMPONENTS system filesystem)
INCLUDE_DIRECTORIES(${LIBS_FOLDER} ${COMMON_FOLDER})
INCLUDE_DIRECTORIES(SYSTEM ${Boost_INCLUDE_DIRS})
-TARGET_LINK_LIBRARIES(${PROJECT_NAME} ${pkgs_LDFLAGS} ${Boost_LIBRARIES} Logger)
+TARGET_LINK_LIBRARIES(${PROJECT_NAME} Common ${pkgs_LDFLAGS} ${Boost_LIBRARIES} Logger)
## Generate the pc file ########################################################
CONFIGURE_FILE(${PC_FILE}.in ${CMAKE_CURRENT_BINARY_DIR}/${PC_FILE} @ONLY)
@@ -71,7 +62,5 @@ INSTALL(FILES ${HEADERS}
DESTINATION ${INCLUDE_INSTALL_DIR}/lxcpp)
INSTALL(FILES ${HEADERS_UTILS}
DESTINATION ${INCLUDE_INSTALL_DIR}/lxcpp/utils)
-INSTALL(FILES ${HEADERS_NETLINK}
- DESTINATION ${INCLUDE_INSTALL_DIR}/lxcpp/netlink)
INSTALL(FILES ${HEADERS_COMMANDS}
DESTINATION ${INCLUDE_INSTALL_DIR}/lxcpp/commands)
diff --git a/server/CMakeLists.txt b/server/CMakeLists.txt
index 58c50f6..86b4f79 100644
--- a/server/CMakeLists.txt
+++ b/server/CMakeLists.txt
@@ -19,14 +19,14 @@
MESSAGE(STATUS "")
MESSAGE(STATUS "Generating makefile for the Server...")
-FILE(GLOB project_SRCS *.cpp *.hpp)
-FILE(GLOB_RECURSE common_SRCS ${COMMON_FOLDER}/*.cpp ${COMMON_FOLDER}/*.hpp)
+FILE(GLOB project_SRCS *.cpp *.hpp)
## Setup target ################################################################
SET(SERVER_CODENAME "${PROJECT_NAME}-server")
-ADD_EXECUTABLE(${SERVER_CODENAME} ${project_SRCS} ${common_SRCS})
+ADD_EXECUTABLE(${SERVER_CODENAME} ${project_SRCS})
+ADD_DEPENDENCIES(${SERVER_CODENAME} Common Logger Config Ipc)
## Link libraries ##############################################################
FIND_PACKAGE(Boost COMPONENTS program_options system filesystem regex)
@@ -43,7 +43,7 @@ SET_TARGET_PROPERTIES(${SERVER_CODENAME} PROPERTIES
LINK_FLAGS "-pthread"
)
-TARGET_LINK_LIBRARIES(${SERVER_CODENAME} ${SERVER_DEPS_LIBRARIES} ${Boost_LIBRARIES} Logger Config Ipc)
+TARGET_LINK_LIBRARIES(${SERVER_CODENAME} Common ${SERVER_DEPS_LIBRARIES} ${Boost_LIBRARIES} Logger Config Ipc)
IF(NOT WITHOUT_DBUS)
TARGET_LINK_LIBRARIES(${SERVER_CODENAME} SimpleDbus)
ENDIF(NOT WITHOUT_DBUS)
diff --git a/tests/unit_tests/CMakeLists.txt b/tests/unit_tests/CMakeLists.txt
index b532336..1c05576 100644
--- a/tests/unit_tests/CMakeLists.txt
+++ b/tests/unit_tests/CMakeLists.txt
@@ -20,7 +20,6 @@
MESSAGE(STATUS "")
MESSAGE(STATUS "Generating makefile for the Unit Tests...")
FILE(GLOB_RECURSE project_SRCS *.cpp *.hpp)
-FILE(GLOB_RECURSE common_SRCS ${COMMON_FOLDER}/*.cpp ${COMMON_FOLDER}/*.hpp)
FILE(GLOB server_SRCS ${SERVER_FOLDER}/*.cpp ${SERVER_FOLDER}/*.hpp)
FILE(GLOB client_SRCS ${CLIENT_FOLDER}/*.cpp ${CLIENT_FOLDER}/*.h)
FILE(GLOB socket_test_SRCS ${SOCKET_TEST_FOLDER}/*.cpp ${SOCKET_TEST_FOLDER}/*.hpp)
@@ -35,20 +34,25 @@ LIST(REMOVE_ITEM project_SRCS ${socket_test_SRCS} ${lxcpp_test_SRCS})
## Setup target ################################################################
SET(UT_SERVER_CODENAME "${PROJECT_NAME}-server-unit-tests")
-ADD_EXECUTABLE(${UT_SERVER_CODENAME} ${project_SRCS} ${common_SRCS} ${server_SRCS} ${client_SRCS})
+ADD_EXECUTABLE(${UT_SERVER_CODENAME} ${project_SRCS} ${server_SRCS} ${client_SRCS})
+ADD_DEPENDENCIES(${UT_SERVER_CODENAME} ${PROJECT_NAME}-server)
## A fake target to test vasum-client C API
-ADD_EXECUTABLE("vasum-client-c-api-compile-test" client/client-c-api-compile-test.c)
+SET(CLIENT_C_API_COMPILE_TEST "vasum-client-c-api-compile-test")
+ADD_EXECUTABLE(${CLIENT_C_API_COMPILE_TEST} client/client-c-api-compile-test.c)
+ADD_DEPENDENCIES(${CLIENT_C_API_COMPILE_TEST} ${PROJECT_NAME}-client)
## A fake target to test lxcpp API
-ADD_EXECUTABLE("lxcpp-api-compile-test" lxcpp/lxcpp-api-compile-test.cpp)
-TARGET_LINK_LIBRARIES("lxcpp-api-compile-test" lxcpp)
+SET(LXCPP_API_COMPILE_TEST "lxcpp-api-compile-test")
+ADD_EXECUTABLE(${LXCPP_API_COMPILE_TEST} lxcpp/lxcpp-api-compile-test.cpp)
+ADD_DEPENDENCIES(${LXCPP_API_COMPILE_TEST} lxcpp)
+TARGET_LINK_LIBRARIES(${LXCPP_API_COMPILE_TEST} lxcpp)
IF(NOT WITHOUT_SYSTEMD)
SET(SOCKET_TEST_CODENAME "${PROJECT_NAME}-socket-test")
## A stub mini-service to test socket functionality
-ADD_EXECUTABLE(${SOCKET_TEST_CODENAME} ${socket_test_SRCS} ${common_SRCS} ${client_SRCS})
+ADD_EXECUTABLE(${SOCKET_TEST_CODENAME} ${socket_test_SRCS} ${client_SRCS})
ENDIF(NOT WITHOUT_SYSTEMD)
## Link libraries ##############################################################
@@ -65,7 +69,7 @@ SET_TARGET_PROPERTIES(${UT_SERVER_CODENAME} PROPERTIES
LINK_FLAGS "-pthread"
)
-TARGET_LINK_LIBRARIES(${UT_SERVER_CODENAME} ${UT_SERVER_DEPS_LIBRARIES} ${Boost_LIBRARIES}
+TARGET_LINK_LIBRARIES(${UT_SERVER_CODENAME} Common ${UT_SERVER_DEPS_LIBRARIES} ${Boost_LIBRARIES}
Logger Config Ipc lxcpp)
IF(NOT WITHOUT_DBUS)
TARGET_LINK_LIBRARIES(${UT_SERVER_CODENAME} SimpleDbus)
@@ -78,7 +82,7 @@ SET_TARGET_PROPERTIES(${SOCKET_TEST_CODENAME} PROPERTIES
LINK_FLAGS "-pthread"
)
-TARGET_LINK_LIBRARIES(${SOCKET_TEST_CODENAME} ${UT_SERVER_DEPS_LIBRARIES} ${Boost_LIBRARIES}
+TARGET_LINK_LIBRARIES(${SOCKET_TEST_CODENAME} Common ${UT_SERVER_DEPS_LIBRARIES} ${Boost_LIBRARIES}
Logger Config Ipc)
IF(NOT WITHOUT_DBUS)
TARGET_LINK_LIBRARIES(${SOCKET_TEST_CODENAME} SimpleDbus)
@@ -100,4 +104,3 @@ INSTALL(TARGETS ${UT_SERVER_CODENAME} DESTINATION bin)
IF(NOT WITHOUT_SYSTEMD)
INSTALL(TARGETS ${SOCKET_TEST_CODENAME} DESTINATION bin)
ENDIF(NOT WITHOUT_SYSTEMD)
-
diff --git a/wrapper/CMakeLists.txt b/wrapper/CMakeLists.txt
index 3346df8..7e70765 100644
--- a/wrapper/CMakeLists.txt
+++ b/wrapper/CMakeLists.txt
@@ -27,12 +27,6 @@ FILE(GLOB wrapper_SRCS *.cpp *.hpp *.h
${CLIENT_FOLDER}/host-ipc-connection.hpp ${CLIENT_FOLDER}/host-ipc-connection.cpp
${CLIENT_FOLDER}/utils.hpp ${CLIENT_FOLDER}/utils.cpp)
-FILE(GLOB common_SRCS ${COMMON_FOLDER}/epoll/*.hpp ${COMMON_FOLDER}/epoll/*.cpp
- ${COMMON_FOLDER}/ipc/*.hpp ${COMMON_FOLDER}/ipc/*.cpp
- ${COMMON_FOLDER}/ipc/internals/*.hpp ${COMMON_FOLDER}/ipc/internals/*.cpp
- ${COMMON_FOLDER}/utils/*.hpp ${COMMON_FOLDER}/utils/*.cpp
- ${COMMON_FOLDER}/*.hpp ${COMMON_FOLDER}/*.cpp)
-
SET(_LIB_VERSION_ "${VERSION}")
SET(_LIB_SOVERSION_ "0")
SET(PC_FILE "${PROJECT_NAME}.pc")
@@ -44,12 +38,14 @@ SET(PC_FILE "${PROJECT_NAME}.pc")
ADD_DEFINITIONS(-fvisibility=hidden)
ADD_DEFINITIONS(-D__STDC_FORMAT_MACROS)
-ADD_LIBRARY(${PROJECT_NAME} SHARED ${wrapper_SRCS} ${common_SRCS})
+ADD_LIBRARY(${PROJECT_NAME} SHARED ${wrapper_SRCS})
SET_TARGET_PROPERTIES(${PROJECT_NAME} PROPERTIES
SOVERSION ${_LIB_SOVERSION_}
VERSION ${_LIB_VERSION_}
COMPILE_DEFINITIONS HOST_IPC_SOCKET="${VSM_SERVER_IPC_SOCKET_PATH}")
+ADD_DEPENDENCIES(${PROJECT_NAME} Common Config Ipc)
+
## Link libraries ##############################################################
FIND_PACKAGE(Boost COMPONENTS system filesystem)
PKG_CHECK_MODULES(LIB_DEPS REQUIRED gio-2.0)
@@ -59,7 +55,7 @@ INCLUDE_DIRECTORIES(${LIBS_FOLDER})
INCLUDE_DIRECTORIES(${SERVER_FOLDER})
INCLUDE_DIRECTORIES(${CLIENT_FOLDER})
-TARGET_LINK_LIBRARIES(${PROJECT_NAME} ${LIB_DEPS_LIBRARIES} ${Boost_LIBRARIES} Config Ipc)
+TARGET_LINK_LIBRARIES(${PROJECT_NAME} Common ${LIB_DEPS_LIBRARIES} ${Boost_LIBRARIES} Config Ipc)
IF(NOT WITHOUT_DBUS)
TARGET_LINK_LIBRARIES(${PROJECT_NAME} SimpleDbus)
ENDIF(NOT WITHOUT_DBUS)
diff --git a/zone-daemon/CMakeLists.txt b/zone-daemon/CMakeLists.txt
index 7171eee..0437a4f 100644
--- a/zone-daemon/CMakeLists.txt
+++ b/zone-daemon/CMakeLists.txt
@@ -20,13 +20,12 @@
MESSAGE(STATUS "")
MESSAGE(STATUS "Generating makefile for the Zone Daemon...")
FILE(GLOB project_SRCS *.cpp *.hpp)
-FILE(GLOB common_SRCS ${COMMON_FOLDER}/utils/*.cpp ${COMMON_FOLDER}/utils/*.hpp
- ${COMMON_FOLDER}/*.cpp)
## Setup target ################################################################
SET(ZONE_DAEMON_CODENAME "${PROJECT_NAME}-zone-daemon")
-ADD_EXECUTABLE(${ZONE_DAEMON_CODENAME} ${project_SRCS} ${common_SRCS})
+ADD_EXECUTABLE(${ZONE_DAEMON_CODENAME} ${project_SRCS})
+ADD_DEPENDENCIES(${ZONE_DAEMON_CODENAME} Common Logger SimpleDbus Ipc)
## Link libraries ##############################################################
FIND_PACKAGE (Boost COMPONENTS program_options system filesystem)
@@ -42,7 +41,7 @@ SET_TARGET_PROPERTIES(${ZONE_DAEMON_CODENAME} PROPERTIES
LINK_FLAGS "-pthread"
)
-TARGET_LINK_LIBRARIES(${ZONE_DAEMON_CODENAME} ${ZONE_DAEMON_DEPS_LIBRARIES}
+TARGET_LINK_LIBRARIES(${ZONE_DAEMON_CODENAME} Common ${ZONE_DAEMON_DEPS_LIBRARIES}
${Boost_LIBRARIES} Logger SimpleDbus Ipc)
--
2.7.4
From 54a315716b6773507cc0bffa236f10f11c5d2400 Mon Sep 17 00:00:00 2001
From: Pawel Kubik
Date: Mon, 14 Sep 2015 12:20:36 +0200
Subject: [PATCH 03/16] CLI bash completion fix
[Feature] CLI bash completion fix
[Cause] Bash completion broken after commit 4a9c93f
[Solution] Bash completion script template fix
[Verification] Build, install, check CLI completion
Change-Id: Iff043a983d042e4181b33b0f6c4e415befcc22ed
---
cli/support/vsm-completion.sh.in | 9 +++++++--
1 file changed, 7 insertions(+), 2 deletions(-)
diff --git a/cli/support/vsm-completion.sh.in b/cli/support/vsm-completion.sh.in
index 74a02a5..704e162 100755
--- a/cli/support/vsm-completion.sh.in
+++ b/cli/support/vsm-completion.sh.in
@@ -2,8 +2,13 @@
[ -z "$BASH_VERSION" ] && return
__@PROJECT_NAME@_cli() {
- words=`@CLI_CODENAME@ --bash-completion ${COMP_WORDS[COMP_CWORD]}`
- COMPREPLY=($(compgen -W "$words" -- ${COMP_WORDS[COMP_CWORD]}))
+ if [ "${COMP_WORDS[COMP_CWORD]}" = "" ]; then
+ comp="''"
+ else
+ comp=
+ fi
+ words=`@CLI_CODENAME@ --bash-completion $(echo "${COMP_WORDS[@]:1}" | sed 's/ = /=/g') $comp`
+ COMPREPLY=($(compgen -W "$words" -- "${COMP_WORDS[COMP_CWORD]}"))
}
complete -F __@PROJECT_NAME@_cli vsm
--
2.7.4
From 3166537b1ec126be9343551b0d7801a89c08e637 Mon Sep 17 00:00:00 2001
From: Jan Olszak
Date: Wed, 16 Sep 2015 11:22:22 +0200
Subject: [PATCH 04/16] lxcpp: Setting up the control terminal
[Feature] Setting up the control terminal in Attach
[Cause] N/A
[Solution] N/A
[Verification] Build, install, run tests
Change-Id: I6b1dced4f9a16c04e82b122679f86b90be29d3d1
---
libs/lxcpp/commands/attach.cpp | 51 +++++++++++++++++++++++++++++++++++++++++-
libs/lxcpp/commands/attach.hpp | 3 +++
libs/lxcpp/container-impl.cpp | 1 +
libs/lxcpp/credentials.hpp | 2 --
4 files changed, 54 insertions(+), 3 deletions(-)
diff --git a/libs/lxcpp/commands/attach.cpp b/libs/lxcpp/commands/attach.cpp
index 0ff856e..01a811b 100644
--- a/libs/lxcpp/commands/attach.cpp
+++ b/libs/lxcpp/commands/attach.cpp
@@ -31,9 +31,13 @@
#include "lxcpp/credentials.hpp"
#include "utils/exception.hpp"
+#include "utils/fd-utils.hpp"
+#include "logger/logger.hpp"
#include
#include
+#include
+#include
#include
@@ -67,6 +71,35 @@ void setupMountPoints()
*/
}
+bool setupControlTTY(const int ttyFD)
+{
+ if (!::isatty(ttyFD)) {
+ return false;
+ }
+
+ if (::setsid() < 0) {
+ return false;
+ }
+
+ if (::ioctl(ttyFD, TIOCSCTTY, NULL) < 0) {
+ return false;
+ }
+
+ if (::dup2(ttyFD, STDIN_FILENO) < 0) {
+ return false;
+ }
+
+ if (::dup2(ttyFD, STDOUT_FILENO) < 0) {
+ return false;
+ }
+
+ if (::dup2(ttyFD, STDERR_FILENO) < 0) {
+ return false;
+ }
+
+ return true;
+}
+
int execFunction(void* call)
{
try {
@@ -83,6 +116,7 @@ Attach::Attach(lxcpp::ContainerImpl& container,
Container::AttachCall& userCall,
const uid_t uid,
const gid_t gid,
+ const std::string& ttyPath,
const std::vector& supplementaryGids,
const int capsToKeep,
const std::string& workDirInContainer,
@@ -98,10 +132,18 @@ Attach::Attach(lxcpp::ContainerImpl& container,
mEnvToKeep(envToKeep),
mEnvToSet(envToSet)
{
+ mTTYFD = ::open(ttyPath.c_str(), O_RDWR | O_NOCTTY);
+ if (mTTYFD < 0) {
+ const std::string msg = "open() failed: " +
+ utils::getSystemErrorMessage();
+ LOGE(msg);
+ throw BadArgument(msg);
+ }
}
Attach::~Attach()
{
+ utils::close(mTTYFD);
}
void Attach::execute()
@@ -113,6 +155,7 @@ void Attach::execute()
mUserCall,
mUid,
mGid,
+ mTTYFD,
mSupplementaryGids,
mCapsToKeep,
mEnvToKeep,
@@ -127,13 +170,14 @@ void Attach::execute()
intermChannel.setRight();
interm(intermChannel, call);
intermChannel.shutdown();
- ::_exit(0);
+ ::_exit(EXIT_SUCCESS);
}
}
int Attach::child(const Container::AttachCall& call,
const uid_t uid,
const gid_t gid,
+ const int ttyFD,
const std::vector& supplementaryGids,
const int capsToKeep,
const std::vector& envToKeep,
@@ -155,6 +199,11 @@ int Attach::child(const Container::AttachCall& call,
lxcpp::setuid(uid);
+ // Set control TTY
+ if(!setupControlTTY(ttyFD)) {
+ ::_exit(EXIT_FAILURE);
+ }
+
// Run user's code
return call();
}
diff --git a/libs/lxcpp/commands/attach.hpp b/libs/lxcpp/commands/attach.hpp
index 36c57ba..2c1f365 100644
--- a/libs/lxcpp/commands/attach.hpp
+++ b/libs/lxcpp/commands/attach.hpp
@@ -58,6 +58,7 @@ public:
Container::AttachCall& userCall,
const uid_t uid,
const gid_t gid,
+ const std::string& ttyPath,
const std::vector& supplementaryGids,
const int capsToKeep,
const std::string& workDirInContainer,
@@ -72,6 +73,7 @@ private:
const Container::AttachCall& mUserCall;
const uid_t mUid;
const gid_t mGid;
+ int mTTYFD;
const std::vector& mSupplementaryGids;
const int mCapsToKeep;
const std::string& mWorkDirInContainer;
@@ -82,6 +84,7 @@ private:
static int child(const Container::AttachCall& call,
const uid_t uid,
const gid_t gid,
+ const int ttyFD,
const std::vector& supplementaryGids,
const int capsToKeep,
const std::vector& envToKeep,
diff --git a/libs/lxcpp/container-impl.cpp b/libs/lxcpp/container-impl.cpp
index 73e5254..8249009 100644
--- a/libs/lxcpp/container-impl.cpp
+++ b/libs/lxcpp/container-impl.cpp
@@ -152,6 +152,7 @@ void ContainerImpl::attach(Container::AttachCall& call,
call,
/*uid in container*/ 0,
/*gid in container*/ 0,
+ "/dev/tty",
/*supplementary gids in container*/ {},
/*capsToKeep*/ 0,
cwdInContainer,
diff --git a/libs/lxcpp/credentials.hpp b/libs/lxcpp/credentials.hpp
index df00ce5..ab1a490 100644
--- a/libs/lxcpp/credentials.hpp
+++ b/libs/lxcpp/credentials.hpp
@@ -36,8 +36,6 @@ void setgid(const gid_t gid);
void setuid(const uid_t uid);
-
-
} // namespace lxcpp
#endif // LXCPP_CREDENTIALS_HPP
\ No newline at end of file
--
2.7.4
From 61e31300c53fb090f48930f4d4462e6bc9218be1 Mon Sep 17 00:00:00 2001
From: Lukasz Pawelczyk
Date: Wed, 29 Jul 2015 13:27:25 +0200
Subject: [PATCH 05/16] lxcpp: Initial implementation of the start API call
[Feature] Initial implementation of the start API call.
[Verification] Build, install, run tests
Significant changes related to the start API call:
- Start command that daemonizes and execs guard binary
- Guard process implementation that execs the container's init
Additional changes in this commit supporting the Start API call:
- API extension to Channel class, support close on exec and be able
to survive (as a FD) exec() call
- set close on exec in persistent file logger
- new logger helper to setup the logger
- add pid to the log format
Change-Id: I2d9648e2a861add2aa1bd1d66587bff2a109cc9c
---
CMakeLists.txt | 8 +-
common/utils/channel.cpp | 55 ++++++++++++-
common/utils/channel.hpp | 27 ++++++-
libs/logger/backend-persistent-file.hpp | 9 ++-
libs/logger/formatter.cpp | 5 +-
libs/logger/level.hpp | 2 +-
libs/logger/logger.cpp | 38 +++++++++
libs/logger/logger.hpp | 28 ++++++-
libs/lxcpp/CMakeLists.txt | 10 ++-
libs/lxcpp/commands/attach.cpp | 2 +
libs/lxcpp/commands/start.cpp | 135 ++++++++++++++++++++++++++++++++
libs/lxcpp/commands/start.hpp | 66 ++++++++++++++++
libs/lxcpp/container-config.hpp | 111 ++++++++++++++++++++++++++
libs/lxcpp/container-impl.cpp | 12 ++-
libs/lxcpp/container-impl.hpp | 28 ++-----
libs/lxcpp/container.hpp | 5 ++
libs/lxcpp/exception.hpp | 5 ++
libs/lxcpp/guard/CMakeLists.txt | 37 +++++++++
libs/lxcpp/guard/guard.cpp | 100 +++++++++++++++++++++++
libs/lxcpp/guard/guard.hpp | 39 +++++++++
libs/lxcpp/guard/main.cpp | 49 ++++++++++++
libs/lxcpp/logger-config.cpp | 48 ++++++++++++
libs/lxcpp/logger-config.hpp | 65 +++++++++++++++
libs/lxcpp/utils.cpp | 122 +++++++++++++++++++++++++++++
libs/lxcpp/utils.hpp | 54 +++++++++++++
packaging/vasum.spec | 1 +
26 files changed, 1022 insertions(+), 39 deletions(-)
create mode 100644 libs/lxcpp/commands/start.cpp
create mode 100644 libs/lxcpp/commands/start.hpp
create mode 100644 libs/lxcpp/container-config.hpp
create mode 100644 libs/lxcpp/guard/CMakeLists.txt
create mode 100644 libs/lxcpp/guard/guard.cpp
create mode 100644 libs/lxcpp/guard/guard.hpp
create mode 100644 libs/lxcpp/guard/main.cpp
create mode 100644 libs/lxcpp/logger-config.cpp
create mode 100644 libs/lxcpp/logger-config.hpp
create mode 100644 libs/lxcpp/utils.cpp
create mode 100644 libs/lxcpp/utils.hpp
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 5b98eee..0409167 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -143,10 +143,10 @@ ENDIF(NOT DEFINED PYTHON_SITELIB)
SET(COMMON_FOLDER ${PROJECT_SOURCE_DIR}/common)
SET(LIBS_FOLDER ${PROJECT_SOURCE_DIR}/libs)
SET(LOGGER_FOLDER ${PROJECT_SOURCE_DIR}/libs/logger)
-SET(LXCPP_FOLDER ${PROJECT_SOURCE_DIR}/libs/lxcpp)
SET(DBUS_FOLDER ${PROJECT_SOURCE_DIR}/libs/dbus)
SET(CONFIG_FOLDER ${PROJECT_SOURCE_DIR}/libs/config)
SET(IPC_FOLDER ${PROJECT_SOURCE_DIR}/libs/ipc)
+SET(LXCPP_FOLDER ${PROJECT_SOURCE_DIR}/libs/lxcpp)
SET(CLIENT_FOLDER ${PROJECT_SOURCE_DIR}/client)
SET(SERVER_FOLDER ${PROJECT_SOURCE_DIR}/server)
SET(ZONE_SUPPORT_FOLDER ${PROJECT_SOURCE_DIR}/zone-support)
@@ -180,6 +180,10 @@ IF(NOT DEFINED DATA_DIR)
SET(DATA_DIR "${CMAKE_INSTALL_PREFIX}/share")
ENDIF(NOT DEFINED DATA_DIR)
+IF(NOT DEFINED LIBEXEC_DIR)
+ SET(LIBEXEC_DIR "${CMAKE_INSTALL_PREFIX}/libexec")
+ENDIF(NOT DEFINED LIBEXEC_DIR)
+
IF(NOT DEFINED RUN_DIR)
SET(RUN_DIR "/var/run")
ENDIF(NOT DEFINED RUN_DIR)
@@ -190,12 +194,12 @@ SET(VSM_UNIT_TESTS_IPC_SOCKET_PATH ${RUN_DIR}/vasum-ipc-unit-tests.socket)
ADD_SUBDIRECTORY(${COMMON_FOLDER})
ADD_SUBDIRECTORY(${LOGGER_FOLDER})
-ADD_SUBDIRECTORY(${LXCPP_FOLDER})
IF(NOT WITHOUT_DBUS)
ADD_SUBDIRECTORY(${DBUS_FOLDER})
ENDIF(NOT WITHOUT_DBUS)
ADD_SUBDIRECTORY(${CONFIG_FOLDER})
ADD_SUBDIRECTORY(${IPC_FOLDER})
+ADD_SUBDIRECTORY(${LXCPP_FOLDER})
ADD_SUBDIRECTORY(${CLIENT_FOLDER})
ADD_SUBDIRECTORY(${SERVER_FOLDER})
IF(NOT WITHOUT_DBUS)
diff --git a/common/utils/channel.cpp b/common/utils/channel.cpp
index fbb110d..3a0dd31 100644
--- a/common/utils/channel.cpp
+++ b/common/utils/channel.cpp
@@ -27,6 +27,8 @@
#include "logger/logger.hpp"
+#include
+#include
#include
namespace {
@@ -36,10 +38,15 @@ const int RIGHT = 1;
namespace utils {
-Channel::Channel()
+Channel::Channel(const bool closeOnExec)
: mSocketIndex(-1)
{
- if (::socketpair(AF_LOCAL, SOCK_STREAM | SOCK_CLOEXEC, 0, mSockets) < 0) {
+ int flags = SOCK_STREAM;
+ if (closeOnExec) {
+ flags |= SOCK_CLOEXEC;
+ };
+
+ if (::socketpair(AF_LOCAL, flags, 0, mSockets.data()) < 0) {
const std::string msg = "socketpair() failed: " +
utils::getSystemErrorMessage();
LOGE(msg);
@@ -47,23 +54,36 @@ Channel::Channel()
}
}
+Channel::Channel(const int fd)
+ : mSocketIndex(LEFT),
+ mSockets{{fd, -1}}
+{
+ assert(fd >= 0);
+}
+
Channel::~Channel()
{
closeSocket(LEFT);
closeSocket(RIGHT);
}
+/*
+ * This function has to be safe in regard to signal(7)
+ */
void Channel::setLeft()
{
mSocketIndex = LEFT;
- utils::close(mSockets[RIGHT]);
+ ::close(mSockets[RIGHT]);
mSockets[RIGHT] = -1;
}
+/*
+ * This function has to be safe in regard to signal(7)
+ */
void Channel::setRight()
{
mSocketIndex = RIGHT;
- utils::close(mSockets[LEFT]);
+ ::close(mSockets[LEFT]);
mSockets[LEFT] = -1;
}
@@ -73,6 +93,33 @@ void Channel::shutdown()
closeSocket(mSocketIndex);
}
+int Channel::getFD()
+{
+ assert(mSocketIndex != -1 && "Channel's end isn't set");
+ return mSockets[mSocketIndex];
+}
+
+int Channel::getLeftFD()
+{
+ return mSockets[LEFT];
+}
+
+int Channel::getRightFD()
+{
+ return mSockets[RIGHT];
+}
+
+void Channel::setCloseOnExec(const bool closeOnExec)
+{
+ const int fd = getFD();
+
+ if (closeOnExec) {
+ ::fcntl(fd, F_SETFD, ::fcntl(fd, F_GETFD) | FD_CLOEXEC);
+ } else {
+ ::fcntl(fd, F_SETFD, ::fcntl(fd, F_GETFD) & ~FD_CLOEXEC);
+ }
+}
+
void Channel::closeSocket(int socketIndex)
{
utils::shutdown(mSockets[socketIndex]);
diff --git a/common/utils/channel.hpp b/common/utils/channel.hpp
index f537121..3b60daa 100644
--- a/common/utils/channel.hpp
+++ b/common/utils/channel.hpp
@@ -26,6 +26,8 @@
#define COMMON_UTILS_CHANNEL_HPP
#include "utils/fd-utils.hpp"
+
+#include
#include
namespace utils {
@@ -35,7 +37,8 @@ namespace utils {
*/
class Channel {
public:
- Channel();
+ explicit Channel(const bool closeOnExec = true);
+ explicit Channel(const int fd);
~Channel();
Channel(const Channel&) = delete;
@@ -72,12 +75,32 @@ public:
template
Data read();
+ /**
+ * Get an active file descriptor
+ */
+ int getFD();
+
+ /**
+ * Gen the left file descriptor
+ */
+ int getLeftFD();
+
+ /**
+ * Gen the right file descriptor
+ */
+ int getRightFD();
+
+ /**
+ * Sets close on exec on an active fd to either true or false
+ */
+ void setCloseOnExec(const bool closeOnExec);
+
private:
void closeSocket(int socketIndex);
int mSocketIndex;
- int mSockets[2];
+ std::array mSockets;
};
template
diff --git a/libs/logger/backend-persistent-file.hpp b/libs/logger/backend-persistent-file.hpp
index 74d2def..5cbd714 100644
--- a/libs/logger/backend-persistent-file.hpp
+++ b/libs/logger/backend-persistent-file.hpp
@@ -27,7 +27,9 @@
#include "logger/backend.hpp"
+#include
#include
+#include
namespace logger {
@@ -35,7 +37,12 @@ class PersistentFileBackend : public LogBackend {
public:
PersistentFileBackend(const std::string& filePath) :
mfilePath(filePath),
- mOut(mfilePath, std::ios::app) {}
+ mOut(mfilePath, std::ios::app)
+ {
+ using filebufType = __gnu_cxx::stdio_filebuf;
+ const int fd = static_cast(mOut.rdbuf())->fd();
+ ::fcntl(fd, F_SETFD, ::fcntl(fd, F_GETFD) | FD_CLOEXEC);
+ }
void log(LogLevel logLevel,
const std::string& file,
diff --git a/libs/logger/formatter.cpp b/libs/logger/formatter.cpp
index 17bed53..06404f2 100644
--- a/libs/logger/formatter.cpp
+++ b/libs/logger/formatter.cpp
@@ -26,6 +26,7 @@
#include "logger/formatter.hpp"
#include "utils/ccolor.hpp"
+#include
#include
#include
#include
@@ -39,7 +40,7 @@ namespace {
const int TIME_COLUMN_LENGTH = 12;
const int SEVERITY_COLUMN_LENGTH = 8;
-const int THREAD_COLUMN_LENGTH = 3;
+const int PROCESS_COLUMN_LENGTH = 8;
const int FILE_COLUMN_LENGTH = 60;
std::atomic gNextThreadId(1);
@@ -122,7 +123,7 @@ std::string LogFormatter::getHeader(LogLevel logLevel,
std::ostringstream logLine;
logLine << getCurrentTime() << ' '
<< std::left << std::setw(SEVERITY_COLUMN_LENGTH) << '[' + toString(logLevel) + ']'
- << std::right << std::setw(THREAD_COLUMN_LENGTH) << getCurrentThread() << ": "
+ << std::right << std::setw(PROCESS_COLUMN_LENGTH) << ::getpid() << "/" << getCurrentThread() << ": "
<< std::left << std::setw(FILE_COLUMN_LENGTH)
<< file + ':' + std::to_string(line) + ' ' + func + ':';
return logLine.str();
diff --git a/libs/logger/level.hpp b/libs/logger/level.hpp
index fd33343..99dc235 100644
--- a/libs/logger/level.hpp
+++ b/libs/logger/level.hpp
@@ -33,7 +33,7 @@ namespace logger {
* @brief Available log levels
* @ingroup libLogger
*/
-enum class LogLevel {
+enum class LogLevel : int {
TRACE, ///< Most detailed log level
DEBUG, ///< Debug logs
INFO, ///< Information
diff --git a/libs/logger/logger.cpp b/libs/logger/logger.cpp
index ec0855b..fbb85d6 100644
--- a/libs/logger/logger.cpp
+++ b/libs/logger/logger.cpp
@@ -40,6 +40,44 @@ std::mutex gLogMutex;
} // namespace
+void setupLogger(const LogType type,
+ const LogLevel level,
+ const std::string &arg)
+{
+ if (type == LogType::LOG_FILE || type == LogType::LOG_PERSISTENT_FILE) {
+ if (arg.empty()) {
+ throw std::runtime_error("Path needs to be specified in the agument");
+ }
+ }
+
+ switch(type) {
+ case LogType::LOG_NULL:
+ Logger::setLogBackend(new NullLogger());
+ break;
+#ifdef HAVE_SYSTEMD
+ case LogType::LOG_JOURNALD:
+ Logger::setLogBackend(new SystemdJournalBackend());
+ break;
+#endif
+ case LogType::LOG_FILE:
+ Logger::setLogBackend(new FileBackend(arg));
+ break;
+ case LogType::LOG_PERSISTENT_FILE:
+ Logger::setLogBackend(new PersistentFileBackend(arg));
+ break;
+ case LogType::LOG_SYSLOG:
+ Logger::setLogBackend(new SyslogBackend());
+ break;
+ case LogType::LOG_STDERR:
+ Logger::setLogBackend(new StderrBackend());
+ break;
+ default:
+ throw std::runtime_error("Bad logger type passed");
+ }
+
+ Logger::setLogLevel(level);
+}
+
void Logger::logMessage(LogLevel logLevel,
const std::string& message,
const std::string& file,
diff --git a/libs/logger/logger.hpp b/libs/logger/logger.hpp
index 0a1ebe6..92baee1 100644
--- a/libs/logger/logger.hpp
+++ b/libs/logger/logger.hpp
@@ -61,9 +61,14 @@
#define COMMON_LOGGER_LOGGER_HPP
#include "logger/level.hpp"
+#include "logger/backend-null.hpp"
+#ifdef HAVE_SYSTEMD
+#include "logger/backend-journal.hpp"
+#endif
#include "logger/backend-file.hpp"
-#include "logger/backend-stderr.hpp"
#include "logger/backend-persistent-file.hpp"
+#include "logger/backend-syslog.hpp"
+#include "logger/backend-stderr.hpp"
#include
#include
@@ -74,6 +79,27 @@
namespace logger {
+enum class LogType : int {
+ LOG_NULL,
+ LOG_JOURNALD,
+ LOG_FILE,
+ LOG_PERSISTENT_FILE,
+ LOG_SYSLOG,
+ LOG_STDERR
+};
+
+/**
+ * A helper function to easily and completely setup a new logger
+ *
+ * @param type logger type to be set up
+ * @param level maximum log level that will be logged
+ * @param arg an argument used by some loggers, specific to them
+ * (e.g. file name for file loggers)
+ */
+void setupLogger(const LogType type,
+ const LogLevel level,
+ const std::string &arg = "");
+
class LogBackend;
class Logger {
diff --git a/libs/lxcpp/CMakeLists.txt b/libs/lxcpp/CMakeLists.txt
index 203ddd3..8f391e8 100644
--- a/libs/lxcpp/CMakeLists.txt
+++ b/libs/lxcpp/CMakeLists.txt
@@ -19,6 +19,9 @@
PROJECT(lxcpp)
+SET(GUARD_CODENAME "${PROJECT_NAME}-guard")
+ADD_SUBDIRECTORY(guard)
+
MESSAGE(STATUS "")
MESSAGE(STATUS "Generating makefile for the liblxcpp...")
FILE(GLOB HEADERS *.hpp)
@@ -37,15 +40,18 @@ ADD_LIBRARY(${PROJECT_NAME} SHARED ${SRCS} ${SRCS_COMMANDS})
SET_TARGET_PROPERTIES(${PROJECT_NAME} PROPERTIES
SOVERSION ${_LIB_SOVERSION_}
VERSION ${_LIB_VERSION_}
+ COMPILE_DEFINITIONS GUARD_PATH="${LIBEXEC_DIR}/${GUARD_CODENAME}"
)
ADD_DEPENDENCIES(${PROJECT_NAME} Common Logger)
## Link libraries ##############################################################
FIND_PACKAGE(Boost COMPONENTS system filesystem)
+PKG_CHECK_MODULES(LXCPP_DEPS REQUIRED glib-2.0)
+
INCLUDE_DIRECTORIES(${LIBS_FOLDER} ${COMMON_FOLDER})
-INCLUDE_DIRECTORIES(SYSTEM ${Boost_INCLUDE_DIRS})
-TARGET_LINK_LIBRARIES(${PROJECT_NAME} Common ${pkgs_LDFLAGS} ${Boost_LIBRARIES} Logger)
+INCLUDE_DIRECTORIES(SYSTEM ${Boost_INCLUDE_DIRS} ${LXCPP_DEPS_INCLUDE_DIRS} ${JSON_C_INCLUDE_DIRS})
+TARGET_LINK_LIBRARIES(${PROJECT_NAME} Common ${pkgs_LDFLAGS} ${Boost_LIBRARIES} Logger Config)
## Generate the pc file ########################################################
CONFIGURE_FILE(${PC_FILE}.in ${CMAKE_CURRENT_BINARY_DIR}/${PC_FILE} @ONLY)
diff --git a/libs/lxcpp/commands/attach.cpp b/libs/lxcpp/commands/attach.cpp
index 01a811b..419f651 100644
--- a/libs/lxcpp/commands/attach.cpp
+++ b/libs/lxcpp/commands/attach.cpp
@@ -167,6 +167,8 @@ void Attach::execute()
parent(intermChannel, interPid);
intermChannel.shutdown();
} else {
+ // TODO: only safe functions mentioned in signal(7) should be used below.
+ // This is not the case now, needs fixing.
intermChannel.setRight();
interm(intermChannel, call);
intermChannel.shutdown();
diff --git a/libs/lxcpp/commands/start.cpp b/libs/lxcpp/commands/start.cpp
new file mode 100644
index 0000000..f68654a
--- /dev/null
+++ b/libs/lxcpp/commands/start.cpp
@@ -0,0 +1,135 @@
+/*
+ * Copyright (C) 2015 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License version 2.1 as published by the Free Software Foundation.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+/**
+ * @file
+ * @author Lukasz Pawelczyk (l.pawelczyk@samsung.com)
+ * @brief Implementation of starting a container
+ */
+
+#include "lxcpp/commands/start.hpp"
+#include "lxcpp/exception.hpp"
+#include "lxcpp/process.hpp"
+#include "lxcpp/utils.hpp"
+
+#include "logger/logger.hpp"
+#include "config/manager.hpp"
+
+#include
+
+
+namespace lxcpp {
+
+
+Start::Start(ContainerConfig &config)
+ : mConfig(config),
+ mChannel(false),
+ mGuardPath(GUARD_PATH),
+ mChannelFD(std::to_string(mChannel.getRightFD()))
+{
+}
+
+Start::~Start()
+{
+}
+
+void Start::execute()
+{
+ LOGD("Forking daemonize and guard processes. Execing guard libexec binary.");
+ LOGD("Logging will cease now. It should be restored using some new facility in the guard process.");
+ const pid_t pid = lxcpp::fork();
+
+ if (pid > 0) {
+ mChannel.setLeft();
+ parent(pid);
+ } else {
+ // Below this point only safe functions mentioned in signal(7) are allowed.
+ mChannel.setRight();
+ daemonize();
+ ::_exit(EXIT_FAILURE);
+ }
+}
+
+void Start::parent(const pid_t pid)
+{
+ int status = lxcpp::waitpid(pid);
+ if (status != EXIT_SUCCESS) {
+ const std::string msg = "Problem with a daemonize process";
+ LOGE(msg);
+ throw ProcessSetupException(msg);
+ }
+
+ // Send the config to the guard process
+ config::saveToFD(mChannel.getFD(), mConfig);
+
+ // Read the pids from the guard process
+ mConfig.mGuardPid = mChannel.read();
+ mConfig.mInitPid = mChannel.read();
+
+ mChannel.shutdown();
+
+ if (mConfig.mGuardPid <= 0 || mConfig.mInitPid <= 0) {
+ const std::string msg = "Problem with receiving pids";
+ LOGE(msg);
+ throw ProcessSetupException(msg);
+ }
+
+ LOGD("Guard PID: " << mConfig.mGuardPid);
+ LOGD("Init PID: " << mConfig.mInitPid);
+}
+
+void Start::daemonize()
+{
+ // Double fork() with exit() to reattach the process under the host's init
+ pid_t pid = ::fork();
+ if (pid < 0) {
+ ::_exit(EXIT_FAILURE);
+ }
+
+ if (pid == 0) {
+ // Prepare a clean environment for a guard process:
+ // - chdir to / so it's independent on other directories
+ // - null std* fds so it's properly dettached from the terminal
+ // - set a new session so it cannot reacquire a terminal
+
+ if (::chdir("/") < 0) {
+ ::_exit(EXIT_FAILURE);
+ }
+ if (nullStdFDs() <0) {
+ ::_exit(EXIT_FAILURE);
+ }
+ if (::setsid() < 0) {
+ ::_exit(EXIT_FAILURE);
+ }
+
+ // Add name and path of the container to argv. They are not used, but will
+ // identify the container in the process list in case setProcTitle() fails
+ // and will guarantee we have enough argv memory to write the title we want.
+ const char *argv[] = {mGuardPath.c_str(),
+ mChannelFD.c_str(),
+ mConfig.mName.c_str(),
+ mConfig.mRootPath.c_str(),
+ NULL};
+ ::execve(argv[0], const_cast(argv), NULL);
+ ::_exit(EXIT_FAILURE);
+ }
+
+ ::_exit(EXIT_SUCCESS);
+}
+
+
+} // namespace lxcpp
diff --git a/libs/lxcpp/commands/start.hpp b/libs/lxcpp/commands/start.hpp
new file mode 100644
index 0000000..758b471
--- /dev/null
+++ b/libs/lxcpp/commands/start.hpp
@@ -0,0 +1,66 @@
+/*
+ * Copyright (C) 2015 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License version 2.1 as published by the Free Software Foundation.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+/**
+ * @file
+ * @author Lukasz Pawelczyk (l.pawelczyk@samsung.com)
+ * @brief Headers for starting a container
+ */
+
+#ifndef LXCPP_COMMANDS_START_HPP
+#define LXCPP_COMMANDS_START_HPP
+
+#include "lxcpp/commands/command.hpp"
+#include "lxcpp/container-config.hpp"
+#include "utils/channel.hpp"
+
+#include
+
+
+namespace lxcpp {
+
+
+class Start final: Command {
+public:
+ /**
+ * Starts the container
+ *
+ * In more details it prepares an environment for a guard process,
+ * starts it, and passes it the configuration through a file descriptor.
+ *
+ * @param config container's config
+ */
+ Start(ContainerConfig &config);
+ ~Start();
+
+ void execute();
+
+private:
+ ContainerConfig &mConfig;
+ utils::Channel mChannel;
+ std::string mGuardPath;
+ std::string mChannelFD;
+
+ void parent(const pid_t pid);
+ void daemonize();
+};
+
+
+} // namespace lxcpp
+
+
+#endif // LXCPP_COMMANDS_START_HPP
diff --git a/libs/lxcpp/container-config.hpp b/libs/lxcpp/container-config.hpp
new file mode 100644
index 0000000..9caad96
--- /dev/null
+++ b/libs/lxcpp/container-config.hpp
@@ -0,0 +1,111 @@
+/*
+ * Copyright (C) 2015 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License version 2.1 as published by the Free Software Foundation.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+/**
+ * @file
+ * @author Lukasz Pawelczyk (l.pawelczyk@samsung.com)
+ * @brief A definition of a ContainerConfig struct
+ */
+
+#ifndef LXCPP_CONTAINER_CONFIG_HPP
+#define LXCPP_CONTAINER_CONFIG_HPP
+
+#include "lxcpp/logger-config.hpp"
+
+#include
+#include
+
+#include
+#include
+#include
+
+
+namespace lxcpp {
+
+
+struct ContainerConfig {
+ /**
+ * Name of the container.
+ *
+ * Set: by constructor, cannot be changed afterwards.
+ * Get: getName()
+ */
+ std::string mName;
+
+ /**
+ * Path of the root directory of the container.
+ *
+ * Set: by contstructor, cannot be changed afterwards.
+ * Get: getRootPath()
+ */
+ std::string mRootPath;
+
+ /**
+ * Pid of the guard process.
+ *
+ * Set: automatically by the guard process itself.
+ * Get: getGuardPid()
+ */
+ pid_t mGuardPid;
+
+ /**
+ * Pid of the container's init process.
+ *
+ * Set: automatically by the guard process.
+ * Get: getInitPid()
+ */
+ pid_t mInitPid;
+
+ /**
+ * Argv of the container's init process to be executed.
+ * The path has to be relative to the RootPath.
+ *
+ * Set: setInit()
+ * Get: getInit()
+ */
+ std::vector mInit;
+
+ /**
+ * Logger to be configured inside the guard process. This logger
+ * reconfiguration is due to the fact that guard looses standard file
+ * descriptors and might loose access to other files by mount namespace
+ * usage. Hence an option to set some other logger that will work
+ * regardless. E.g. PersistentFile.
+ *
+ * Set: setLogger()
+ * Get: none
+ */
+ LoggerConfig mLogger;
+
+ ContainerConfig() : mGuardPid(-1), mInitPid(-1) {}
+
+ CONFIG_REGISTER
+ (
+ mName,
+ mRootPath,
+ mGuardPid,
+ mInitPid,
+ mInit,
+ mLogger
+ )
+};
+
+
+}
+
+
+#endif // LXCPP_CONTAINER_CONFIG_HPP
diff --git a/libs/lxcpp/container-impl.cpp b/libs/lxcpp/container-impl.cpp
index 8249009..cee6fa4 100644
--- a/libs/lxcpp/container-impl.cpp
+++ b/libs/lxcpp/container-impl.cpp
@@ -28,6 +28,7 @@
#include "lxcpp/namespace.hpp"
#include "lxcpp/capability.hpp"
#include "lxcpp/commands/attach.hpp"
+#include "lxcpp/commands/start.hpp"
#include "logger/logger.hpp"
#include "utils/exception.hpp"
@@ -120,9 +121,18 @@ pid_t ContainerImpl::getInitPid() const
return mConfig.mInitPid;
}
+void ContainerImpl::setLogger(const logger::LogType type,
+ const logger::LogLevel level,
+ const std::string &arg)
+{
+ mConfig.mLogger.set(type, level, arg);
+}
+
void ContainerImpl::start()
{
- throw NotImplementedException();
+ // TODO: check config consistency and completeness somehow
+ Start start(mConfig);
+ start.execute();
}
void ContainerImpl::stop()
diff --git a/libs/lxcpp/container-impl.hpp b/libs/lxcpp/container-impl.hpp
index 5435d49..1bf44b7 100644
--- a/libs/lxcpp/container-impl.hpp
+++ b/libs/lxcpp/container-impl.hpp
@@ -25,37 +25,15 @@
#define LXCPP_CONTAINER_IMPL_HPP
#include
-#include
-#include
#include
+#include "lxcpp/container-config.hpp"
#include "lxcpp/container.hpp"
#include "lxcpp/namespace.hpp"
#include "lxcpp/network.hpp"
-#include "utils/channel.hpp"
-
namespace lxcpp {
-struct ContainerConfig {
- std::string mName;
- std::string mRootPath;
- pid_t mGuardPid;
- pid_t mInitPid;
- std::vector mInit;
-
- ContainerConfig() : mGuardPid(-1), mInitPid(-1) {}
-
- CONFIG_REGISTER
- (
- mName,
- mRootPath,
- mGuardPid,
- mInitPid,
- mInit
- )
-};
-
class ContainerImpl : public virtual Container {
public:
@@ -73,6 +51,10 @@ public:
const std::vector& getInit();
void setInit(const std::vector &init);
+ void setLogger(const logger::LogType type,
+ const logger::LogLevel level,
+ const std::string &arg);
+
const std::vector& getNamespaces() const;
// Execution actions
diff --git a/libs/lxcpp/container.hpp b/libs/lxcpp/container.hpp
index 192f2df..88c3ff8 100644
--- a/libs/lxcpp/container.hpp
+++ b/libs/lxcpp/container.hpp
@@ -25,6 +25,7 @@
#define LXCPP_CONTAINER_HPP
#include "lxcpp/network-config.hpp"
+#include "lxcpp/logger-config.hpp"
#include
#include
@@ -60,6 +61,10 @@ public:
virtual const std::vector& getInit() = 0;
virtual void setInit(const std::vector &init) = 0;
+ virtual void setLogger(const logger::LogType type,
+ const logger::LogLevel level,
+ const std::string &arg) = 0;
+
// Execution actions
virtual void start() = 0;
virtual void stop() = 0;
diff --git a/libs/lxcpp/exception.hpp b/libs/lxcpp/exception.hpp
index 7764282..11a6a0e 100644
--- a/libs/lxcpp/exception.hpp
+++ b/libs/lxcpp/exception.hpp
@@ -66,6 +66,11 @@ struct CapabilitySetupException: public Exception {
: Exception(message) {}
};
+struct UtilityException: public Exception {
+ explicit UtilityException(const std::string& message = "Error during an utility operation")
+ : Exception(message) {}
+};
+
struct BadArgument: public Exception {
explicit BadArgument(const std::string& message = "Bad argument passed")
: Exception(message) {}
diff --git a/libs/lxcpp/guard/CMakeLists.txt b/libs/lxcpp/guard/CMakeLists.txt
new file mode 100644
index 0000000..6c69300
--- /dev/null
+++ b/libs/lxcpp/guard/CMakeLists.txt
@@ -0,0 +1,37 @@
+# Copyright (C) 2015 Samsung Electronics Co., Ltd All Rights Reserved
+#
+# This library is free software; you can redistribute it and/or
+# modify it under the terms of the GNU Lesser General Public
+# License version 2.1 as published by the Free Software Foundation.
+#
+# This library is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+# Lesser General Public License for more details.
+#
+# You should have received a copy of the GNU Lesser General Public
+# License along with this library; if not, write to the Free Software
+# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+#
+# @file CMakeLists.txt
+# @author Lukasz Pawelczyk (l.pawelczyk@samsung.com)
+#
+
+MESSAGE(STATUS "")
+MESSAGE(STATUS "Generating makefile for the Guard...")
+FILE(GLOB guard_SRCS *.cpp *.hpp)
+
+
+## Setup target ################################################################
+ADD_EXECUTABLE(${GUARD_CODENAME} ${guard_SRCS})
+
+
+## Link libraries ##############################################################
+PKG_CHECK_MODULES(GUARD_DEPS REQUIRED glib-2.0)
+INCLUDE_DIRECTORIES(${LIBS_FOLDER} ${COMMON_FOLDER})
+INCLUDE_DIRECTORIES(SYSTEM ${GUARD_DEPS_INCLUDE_DIRS} ${JSON_C_INCLUDE_DIRS})
+TARGET_LINK_LIBRARIES(${GUARD_CODENAME} lxcpp)
+
+
+## Install #####################################################################
+INSTALL(TARGETS ${GUARD_CODENAME} DESTINATION ${LIBEXEC_DIR})
diff --git a/libs/lxcpp/guard/guard.cpp b/libs/lxcpp/guard/guard.cpp
new file mode 100644
index 0000000..63c7263
--- /dev/null
+++ b/libs/lxcpp/guard/guard.cpp
@@ -0,0 +1,100 @@
+/*
+ * Copyright (C) 2015 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License version 2.1 as published by the Free Software Foundation.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+/**
+ * @file
+ * @author Lukasz Pawelczyk (l.pawelczyk@samsung.com)
+ * @brief LXCPP guard process implementation
+ */
+
+#include "lxcpp/utils.hpp"
+#include "lxcpp/guard/guard.hpp"
+#include "lxcpp/process.hpp"
+
+#include "config/manager.hpp"
+#include "logger/logger.hpp"
+
+#include
+#include
+
+
+namespace lxcpp {
+
+
+void startContainer(const ContainerConfig &cfg)
+{
+ std::vector argv;
+ argv.reserve(cfg.mInit.size() + 1);
+ for (auto const & it : cfg.mInit) {
+ argv.push_back(it.c_str());
+ }
+ argv.push_back(nullptr);
+
+ LOGD("Executing container's init: " << argv[0]);
+ ::execve(argv[0], const_cast(argv.data()), NULL);
+ ::_exit(EXIT_FAILURE);
+}
+
+int startGuard(int channelFD)
+{
+ ContainerConfig cfg;
+ utils::Channel channel(channelFD);
+ channel.setCloseOnExec(true);
+ config::loadFromFD(channel.getFD(), cfg);
+
+ logger::setupLogger(cfg.mLogger.getType(),
+ cfg.mLogger.getLevel(),
+ cfg.mLogger.getArg());
+
+ LOGD("Guard started, config & logging restored");
+
+ try {
+ LOGD("Setting the guard process title");
+ const std::string title = "[LXCPP] " + cfg.mName + " " + cfg.mRootPath;
+ setProcTitle(title);
+ } catch (std::exception &e) {
+ // Ignore, this is optional
+ LOGW("Failed to set the guard process title");
+ }
+
+ // TODO: container preparation part 1
+
+ // TODO: switch to clone
+ LOGD("Forking container's init process");
+ pid_t pid = lxcpp::fork();
+
+ if (pid == 0) {
+ // TODO: container preparation part 2
+
+ startContainer(cfg);
+ ::_exit(EXIT_FAILURE);
+ }
+
+ cfg.mGuardPid = ::getpid();
+ cfg.mInitPid = pid;
+
+ channel.write(cfg.mGuardPid);
+ channel.write(cfg.mInitPid);
+ channel.shutdown();
+
+ int status = lxcpp::waitpid(pid);
+ LOGD("Init exited with status: " << status);
+ return status;
+}
+
+
+} // namespace lxcpp
diff --git a/libs/lxcpp/guard/guard.hpp b/libs/lxcpp/guard/guard.hpp
new file mode 100644
index 0000000..78457ae
--- /dev/null
+++ b/libs/lxcpp/guard/guard.hpp
@@ -0,0 +1,39 @@
+/*
+ * Copyright (C) 2015 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License version 2.1 as published by the Free Software Foundation.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+/**
+ * @file
+ * @author Lukasz Pawelczyk (l.pawelczyk@samsung.com)
+ * @brief LXCPP guard process header
+ */
+
+#ifndef LXCPP_GUARD_GUARD_HPP
+#define LXCPP_GUARD_GUARD_HPP
+
+
+#include "lxcpp/container-config.hpp"
+#include "utils/channel.hpp"
+
+namespace lxcpp {
+
+
+int startGuard(int channelFD);
+
+
+} // namespace lxcpp
+
+#endif // LXCPP_GUARD_HPP
diff --git a/libs/lxcpp/guard/main.cpp b/libs/lxcpp/guard/main.cpp
new file mode 100644
index 0000000..c8db30b
--- /dev/null
+++ b/libs/lxcpp/guard/main.cpp
@@ -0,0 +1,49 @@
+/*
+ * Copyright (C) 2015 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License version 2.1 as published by the Free Software Foundation.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+/**
+ * @file
+ * @author Lukasz Pawelczyk (l.pawelczyk@samsung.com)
+ * @brief Main file for the Guard process (libexec)
+ */
+
+#include "lxcpp/guard/guard.hpp"
+
+#include "utils/fd-utils.hpp"
+
+#include
+#include
+
+int main(int argc, char *argv[])
+{
+ if (argc == 1) {
+ std::cout << "This file should not be executed by hand" << std::endl;
+ ::_exit(EXIT_FAILURE);
+ }
+
+ // NOTE: this might not be required now, but I leave it here not to forget.
+ // We need to investigate this with vasum and think about possibility of
+ // poorly written software that leaks file descriptors and might use LXCPP.
+#if 0
+ for(int fd = 3; fd < ::sysconf(_SC_OPEN_MAX); ++fd) {
+ utils::close(fd);
+ }
+#endif
+
+ int fd = std::stoi(argv[1]);
+ return lxcpp::startGuard(fd);
+}
diff --git a/libs/lxcpp/logger-config.cpp b/libs/lxcpp/logger-config.cpp
new file mode 100644
index 0000000..3aed302
--- /dev/null
+++ b/libs/lxcpp/logger-config.cpp
@@ -0,0 +1,48 @@
+/*
+ * Copyright (C) 2015 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License version 2.1 as published by the Free Software Foundation.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+/**
+ * @file
+ * @author Lukasz Pawelczyk (l.pawelczyk@samsumg.com)
+ * @brief Logger configuration
+ */
+
+#include "lxcpp/logger-config.hpp"
+#include "lxcpp/exception.hpp"
+
+namespace lxcpp {
+
+
+void LoggerConfig::set(const logger::LogType type,
+ const logger::LogLevel level,
+ const std::string &arg)
+{
+ if (type == logger::LogType::LOG_FILE || type == logger::LogType::LOG_PERSISTENT_FILE) {
+ if (arg.empty()) {
+ const std::string msg = "Path needs to be specified in the agument";
+ LOGE(msg);
+ throw BadArgument(msg);
+ }
+ }
+
+ mType = static_cast(type);
+ mLevel = static_cast(level);
+ mArg = arg;
+}
+
+
+} //namespace lxcpp
diff --git a/libs/lxcpp/logger-config.hpp b/libs/lxcpp/logger-config.hpp
new file mode 100644
index 0000000..8312623
--- /dev/null
+++ b/libs/lxcpp/logger-config.hpp
@@ -0,0 +1,65 @@
+/*
+ * Copyright (C) 2015 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License version 2.1 as published by the Free Software Foundation.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+/**
+ * @file
+ * @author Lukasz Pawelczyk (l.pawelczyk@samsumg.com)
+ * @brief Logger configuration
+ */
+
+#ifndef LXCPP_LOGGER_CONFIG_HPP
+#define LXCPP_LOGGER_CONFIG_HPP
+
+#include "config/config.hpp"
+#include "config/fields.hpp"
+#include "logger/logger.hpp"
+
+
+namespace lxcpp {
+
+
+/**
+ * Logger configuration
+ */
+struct LoggerConfig {
+private:
+ int mType;
+ int mLevel;
+ std::string mArg;
+
+public:
+ void set(const logger::LogType type,
+ const logger::LogLevel level,
+ const std::string &arg = "");
+
+ logger::LogType getType() const {return static_cast(mType);}
+ logger::LogLevel getLevel() const {return static_cast(mLevel);}
+ std::string getArg() const {return mArg;}
+
+ CONFIG_REGISTER
+ (
+ mType,
+ mLevel,
+ mArg
+ )
+};
+
+
+} //namespace lxcpp
+
+
+#endif // LXCPP_LOGGER_CONFIG_HPP
diff --git a/libs/lxcpp/utils.cpp b/libs/lxcpp/utils.cpp
new file mode 100644
index 0000000..41e76b5
--- /dev/null
+++ b/libs/lxcpp/utils.cpp
@@ -0,0 +1,122 @@
+/*
+ * Copyright (C) 2015 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License version 2.1 as published by the Free Software Foundation.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+/**
+ * @file
+ * @author Lukasz Pawelczyk (l.pawelczyk@samsung.com)
+ * @brief LXCPP utils implementation
+ */
+
+#include "lxcpp/exception.hpp"
+
+#include "logger/logger.hpp"
+#include "utils/fd-utils.hpp"
+#include "utils/exception.hpp"
+
+#ifndef _GNU_SOURCE
+#define _GNU_SOURCE
+#endif
+
+#include
+#include
+#include
+#include
+#include
+
+
+namespace lxcpp {
+
+
+/*
+ * This function has to be safe in regard to signal(7)
+ */
+int nullStdFDs()
+{
+ int ret = -1;
+
+ int fd = TEMP_FAILURE_RETRY(open("/dev/null", O_RDWR | O_CLOEXEC));
+ if (fd == -1) {
+ goto err;
+ }
+
+ if (-1 == TEMP_FAILURE_RETRY(::dup2(fd, STDIN_FILENO))) {
+ goto err_close;
+ }
+
+ if (-1 == TEMP_FAILURE_RETRY(::dup2(fd, STDOUT_FILENO))) {
+ goto err_close;
+ }
+
+ if (-1 == TEMP_FAILURE_RETRY(::dup2(fd, STDERR_FILENO))) {
+ goto err_close;
+ }
+
+ if (-1 == TEMP_FAILURE_RETRY(::close(fd))) {
+ goto err_close;
+ }
+
+ return 0;
+
+err_close:
+ TEMP_FAILURE_RETRY(::close(fd));
+err:
+ return ret;
+}
+
+void setProcTitle(const std::string &title)
+{
+ std::ifstream f("/proc/self/stat");
+ auto it = std::istream_iterator(f);
+
+ // Skip the first 47 fields, entries 48-49 are ARG_START and ARG_END.
+ std::advance(it, 47);
+ unsigned long argStart = std::stol(*it++);
+ unsigned long argEnd = std::stol(*it++);
+
+ f.close();
+
+ char *mem = reinterpret_cast(argStart);
+ ptrdiff_t oldLen = argEnd - argStart;
+
+ // Include the null byte here, because in the calculations below we want to have room for it.
+ size_t newLen = title.length() + 1;
+
+ // We shouldn't use more then we have available. Hopefully that should be enough.
+ if ((long)newLen > oldLen) {
+ newLen = oldLen;
+ } else {
+ argEnd = argStart + newLen;
+ }
+
+ // Sanity check
+ if (argEnd < newLen || argEnd < argStart) {
+ std::string msg = "setProcTitle() failed: " + utils::getSystemErrorMessage();
+ LOGE(msg);
+ throw UtilityException(msg);
+ }
+
+ // Let's try to set the memory range properly (this requires capabilities)
+ if (::prctl(PR_SET_MM, PR_SET_MM_ARG_END, argEnd, 0, 0) < 0) {
+ // If that failed let's fall back to the poor man's version, just zero the memory we already have.
+ ::bzero(mem, oldLen);
+ }
+
+ ::strcpy(mem, title.c_str());
+}
+
+
+} // namespace lxcpp
diff --git a/libs/lxcpp/utils.hpp b/libs/lxcpp/utils.hpp
new file mode 100644
index 0000000..2a59303
--- /dev/null
+++ b/libs/lxcpp/utils.hpp
@@ -0,0 +1,54 @@
+/*
+ * Copyright (C) 2015 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License version 2.1 as published by the Free Software Foundation.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+/**
+ * @file
+ * @author Lukasz Pawelczyk (l.pawelczyk@samsung.com)
+ * @brief LXCPP utils headers
+ */
+
+#ifndef LXCPP_UTILS_HPP
+#define LXCPP_UTILS_HPP
+
+#include
+
+
+namespace lxcpp {
+
+/**
+ * Nullifies all standard file descriptors (stdin, stdout, stderr)
+ * replacing them with file descriptor to /dev/null. Used to
+ * as a part of a process to detach a process from a control terminal.
+ *
+ * This function has to be safe in regard to signal(7)
+ *
+ * @returns an error code in case of failure.
+ */
+int nullStdFDs();
+
+/**
+ * Changes the tittle of a current process title (e.g. visible in ps tool).
+ *
+ * @param title A new tittle to be set
+ */
+void setProcTitle(const std::string &title);
+
+
+} // namespace lxcpp
+
+
+#endif // LXCPP_START_HPP
diff --git a/packaging/vasum.spec b/packaging/vasum.spec
index 2cd5dd8..7709ab4 100644
--- a/packaging/vasum.spec
+++ b/packaging/vasum.spec
@@ -487,6 +487,7 @@ The package provides liblxcpp library.
%files -n liblxcpp
%defattr(644,root,root,755)
%{_libdir}/liblxcpp.so.0
+%attr(755,root,root) %{_libexecdir}/lxcpp-guard
%attr(755,root,root) %{_libdir}/liblxcpp.so.%{version}
%package -n liblxcpp-devel
--
2.7.4
From a3495900d30400f536a89118984fca13df3187e1 Mon Sep 17 00:00:00 2001
From: Pawel Kubik
Date: Tue, 15 Sep 2015 15:40:41 +0200
Subject: [PATCH 06/16] Instructions for generating code coverage report
[Feature] Instructions in markdown
[Cause] Need for local coverage reports
[Solution] N/A
[Verification] Follow instructions in the file and check report
Change-Id: I69df0752268585c622b5006107ab91a59b840ea7
---
doc/coverage_report.md | 40 ++++++++++++++++++++++++++++++++++++++++
1 file changed, 40 insertions(+)
create mode 100644 doc/coverage_report.md
diff --git a/doc/coverage_report.md b/doc/coverage_report.md
new file mode 100644
index 0000000..cb9ef8e
--- /dev/null
+++ b/doc/coverage_report.md
@@ -0,0 +1,40 @@
+Generating Code Coverage Report
+===============================
+
+Requirements
+------------
+ - [**gcc**](gcc.gnu.org) - provides `gcov` which generates coverage summary
+ - [**gcovr**](gcovr.com) - recursively runs `gcov` and generates HTML report.
+ [*PyPI*](pypi.python.org/pypi/gcovr) should provide the newest version.
+ You can use `pip` command (available in most repositories):
+ ```bash
+ sudo pip install gcovr
+ ```
+
+Instructions
+------------
+
+All command should be run from within your build directory. **repodir** is a
+path to your repository root.
+
+1. Generate your build using CCOV profile
+```bash
+cmake -DCMAKE_BUILD_TYPE=CCOV repodir
+```
+
+2. Compile, install and run tests in order to generate coverage files (.gcda extension)
+```bash
+make
+sudo make install
+sudo vsm_all_tests.py
+```
+ **Make sure that no other Vasum binaries are being used after installation
+ except from those used by tests!**
+
+3. Generate HTML report
+```bash
+gcovr -e tests -s -v -r repodir --html -o coverage.html
+```
+
+4. Coverage report consists of single page **coverage.html**. Find it in your
+ build directory and open in a web browser.
--
2.7.4
From c6006f81f49ddd8c3fc1cf59f3b54ea522f12fcc Mon Sep 17 00:00:00 2001
From: Krzysztof Dynowski
Date: Thu, 27 Aug 2015 15:25:58 +0200
Subject: [PATCH 07/16] lxcpp: network implementation (part 1)
[Feature] Network implementation for lxcpp (list, details)
[Cause] N/A
[Solution] N/A
[Verification] Build, install, run tests
Change-Id: I2f43a2bb6d042b5aad9abf87951965e585fb4eb6
---
common/netlink/netlink-message.cpp | 22 +-
common/netlink/netlink-message.hpp | 8 +-
common/netlink/netlink.cpp | 2 +-
common/utils/text.cpp | 43 ++++
common/utils/text.hpp | 54 +++++
libs/lxcpp/commands/netcreate.cpp | 45 ++++
libs/lxcpp/commands/netcreate.hpp | 57 +++++
libs/lxcpp/container-config.hpp | 9 +
libs/lxcpp/container-impl.cpp | 40 +++-
libs/lxcpp/container-impl.hpp | 18 +-
libs/lxcpp/container.hpp | 20 +-
libs/lxcpp/network-config.cpp | 66 +++++-
libs/lxcpp/network-config.hpp | 55 ++++-
libs/lxcpp/network.cpp | 398 +++++++++++++++++++++++++++++++++-
libs/lxcpp/network.hpp | 78 ++++++-
server/netdev.cpp | 4 +-
tests/unit_tests/lxcpp/ut-network.cpp | 83 +++++++
17 files changed, 938 insertions(+), 64 deletions(-)
create mode 100644 common/utils/text.cpp
create mode 100644 common/utils/text.hpp
create mode 100644 libs/lxcpp/commands/netcreate.cpp
create mode 100644 libs/lxcpp/commands/netcreate.hpp
create mode 100644 tests/unit_tests/lxcpp/ut-network.cpp
diff --git a/common/netlink/netlink-message.cpp b/common/netlink/netlink-message.cpp
index cef7828..5bdda7b 100644
--- a/common/netlink/netlink-message.cpp
+++ b/common/netlink/netlink-message.cpp
@@ -191,7 +191,7 @@ void NetlinkResponse::skipAttribute()
NetlinkResponse& NetlinkResponse::openNested(int ifla)
{
const rtattr *rta = asAttr(get(RTA_LENGTH(0)));
- if (rta->rta_type == ifla) {
+ if (rta->rta_type != ifla) {
const std::string msg = "Wrong attribute type, expected: " + std::to_string(ifla) + ", got: " + std::to_string(rta->rta_type);
LOGE(msg);
throw VasumException(msg);
@@ -217,9 +217,13 @@ NetlinkResponse& NetlinkResponse::closeNested()
return *this;
}
-NetlinkResponse& NetlinkResponse::fetch(int ifla, std::string& value, int maxSize)
+NetlinkResponse& NetlinkResponse::fetch(int ifla, std::string& value, unsigned len)
{
- value = std::string(get(ifla, maxSize));
+ const rtattr *rta = asAttr(get(RTA_LENGTH(0)));
+ if (len > RTA_PAYLOAD(rta)) {
+ len = RTA_PAYLOAD(rta);
+ }
+ value = std::string(get(ifla, -1), len);
skipAttribute();
return *this;
}
@@ -228,12 +232,15 @@ 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) {
- const std::string msg = "Wrong attribute type, expected: " + std::to_string(ifla) + ", got: " + std::to_string(rta->rta_type);
+ const std::string msg = "Wrong attribute type, expected: " + std::to_string(ifla) +
+ ", got: " + std::to_string(rta->rta_type);
LOGE(msg);
throw VasumException(msg);
}
if (len >= 0 && rta->rta_len != RTA_LENGTH(len)) {
- const std::string msg = "Wrong attribute length, expected: " + std::to_string(rta->rta_len) + ", got: " + std::to_string(len);
+ const std::string msg = "Wrong attribute " + std::to_string(ifla) +
+ " length, expected: " + std::to_string(rta->rta_len) +
+ ", got: " + std::to_string(RTA_LENGTH(len));
LOGE(msg);
throw VasumException(msg);
}
@@ -270,6 +277,11 @@ int NetlinkResponse::getAttributeType() const
return asAttr(get(RTA_LENGTH(0)))->rta_type;
}
+int NetlinkResponse::getAttributeLength() const
+{
+ return RTA_PAYLOAD(asAttr(get(RTA_LENGTH(0))));
+}
+
NetlinkResponse& NetlinkResponse::seek(int len)
{
if (size() < mPosition + len) {
diff --git a/common/netlink/netlink-message.hpp b/common/netlink/netlink-message.hpp
index 3379009..73e6a4c 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
@@ -150,7 +151,7 @@ public:
/**
* Fetch attribute
*/
- NetlinkResponse& fetch(int ifla, std::string& value, int maxSize = -1);
+ NetlinkResponse& fetch(int ifla, std::string& value, unsigned maxLen = std::numeric_limits::max());
template
NetlinkResponse& fetch(int ifla, T& value);
///@}
@@ -161,6 +162,11 @@ public:
int getAttributeType() const;
/**
+ * Get attributie length
+ **/
+ int getAttributeLength() const;
+
+ /**
* Fetch data of type T
*/
template
diff --git a/common/netlink/netlink.cpp b/common/netlink/netlink.cpp
index 3408293..45d0697 100644
--- a/common/netlink/netlink.cpp
+++ b/common/netlink/netlink.cpp
@@ -100,7 +100,7 @@ void Netlink::open(int netNsPid)
auto fdFactory = []{ return socket(AF_NETLINK, SOCK_RAW, NETLINK_ROUTE); };
assert(mFd == -1);
- if (netNsPid == 0 || netNsPid == getpid()) {
+ if (netNsPid == 0 || netNsPid == 1 || netNsPid == ::getpid()) {
mFd = fdFactory();
if (mFd == -1) {
LOGE("Can't open socket: " << getSystemErrorMessage());
diff --git a/common/utils/text.cpp b/common/utils/text.cpp
new file mode 100644
index 0000000..5bdf335
--- /dev/null
+++ b/common/utils/text.cpp
@@ -0,0 +1,43 @@
+/*
+ * Copyright (C) 2015 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License version 2.1 as published by the Free Software Foundation.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+/**
+ * @file
+ * @author Krzysztof Dynowski (k.dynowski@samsumg.com)
+ * @brief Text related utility
+ */
+
+#include "utils/text.hpp"
+
+namespace utils {
+namespace {
+const char hexmap[] = {'0', '1', '2', '3', '4', '5', '6', '7',
+ '8', '9', 'A', 'B', 'C', 'D', 'E', 'F'};
+}
+
+std::string toHexString(const void *data, unsigned len)
+{
+ const unsigned char *d = static_cast(data);
+ std::string s(len * 2, ' ');
+ for (unsigned i = 0; i < len; ++i) {
+ s[2 * i] = hexmap[(d[i] >> 4) & 0x0F];
+ s[2 * i + 1] = hexmap[d[i] & 0x0F];
+ }
+ return s;
+}
+
+} // namespace utils
diff --git a/common/utils/text.hpp b/common/utils/text.hpp
new file mode 100644
index 0000000..435f421
--- /dev/null
+++ b/common/utils/text.hpp
@@ -0,0 +1,54 @@
+/*
+ * Copyright (C) 2015 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License version 2.1 as published by the Free Software Foundation.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+/**
+ * @file
+ * @author Krzysztof Dynowski (k.dynowski@samsumg.com)
+ * @brief Text related utils
+ */
+
+#ifndef COMMON_UTILS_TEXT_HPP
+#define COMMON_UTILS_TEXT_HPP
+
+#include
+
+namespace utils {
+
+/**
+ * Convert binary bytes array to hex string representation
+ */
+std::string toHexString(const void *data, unsigned len);
+
+inline bool beginsWith(std::string const &value, std::string const &part)
+{
+ if (part.size() > value.size()) {
+ return false;
+ }
+ return std::equal(part.begin(), part.end(), value.begin());
+}
+
+inline bool endsWith(std::string const &value, std::string const &part)
+{
+ if (part.size() > value.size()) {
+ return false;
+ }
+ return std::equal(part.rbegin(), part.rend(), value.rbegin());
+}
+
+} // namespace utils
+
+#endif // COMMON_UTILS_TEXT_HPP
diff --git a/libs/lxcpp/commands/netcreate.cpp b/libs/lxcpp/commands/netcreate.cpp
new file mode 100644
index 0000000..3c88d8e
--- /dev/null
+++ b/libs/lxcpp/commands/netcreate.cpp
@@ -0,0 +1,45 @@
+/*
+ * Copyright (C) 2015 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License version 2.1 as published by the Free Software Foundation.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+/**
+ * @file
+ * @author Krzysztof Dynowski (k.dynowski@samsumg.com)
+ * @brief Network configuration command
+ */
+
+#include "lxcpp/commands/netcreate.hpp"
+#include "lxcpp/network.hpp"
+
+namespace lxcpp {
+
+void NetCreateAll::execute()
+{
+ for (const auto& i : mInterfaceConfigs) {
+ NetworkInterface networkInerface(mContainerPid, i.getZoneIf());
+ networkInerface.create(i.getHostIf(), i.getType(), i.getMode());
+
+ Attrs attrs;
+ for (const auto& a : i.getAddrList()) {
+ Attr attr;
+ NetworkInterface::convertInetAddr2Attr(a, attr);
+ attrs.push_back(attr);
+ }
+ networkInerface.setAttrs(attrs);
+ }
+}
+
+} // namespace lxcpp
diff --git a/libs/lxcpp/commands/netcreate.hpp b/libs/lxcpp/commands/netcreate.hpp
new file mode 100644
index 0000000..5d6e512
--- /dev/null
+++ b/libs/lxcpp/commands/netcreate.hpp
@@ -0,0 +1,57 @@
+/*
+ * Copyright (C) 2015 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License version 2.1 as published by the Free Software Foundation.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+/**
+ * @file
+ * @author Krzysztof Dynowski (k.dynowski@samsumg.com)
+ * @brief Network configuration command
+ */
+
+#ifndef LXCPP_COMMAND_NETCREATE_HPP
+#define LXCPP_COMMAND_NETCREATE_HPP
+
+#include "lxcpp/commands/command.hpp"
+#include "lxcpp/network-config.hpp"
+
+#include
+
+namespace lxcpp {
+
+class NetCreateAll final: Command {
+public:
+ /**
+ * Runs call in the container's context
+ *
+ * Creates and configures network interfaces in the container
+ *
+ */
+ NetCreateAll(pid_t containerPid, const std::vector& iflist) :
+ mContainerPid(containerPid),
+ mInterfaceConfigs(iflist)
+ {
+ }
+
+ void execute();
+
+private:
+ const pid_t mContainerPid;
+ const std::vector& mInterfaceConfigs;
+};
+
+} // namespace lxcpp
+
+#endif // LXCPP_COMMAND_NETCREATE_HPP
diff --git a/libs/lxcpp/container-config.hpp b/libs/lxcpp/container-config.hpp
index 9caad96..54422bf 100644
--- a/libs/lxcpp/container-config.hpp
+++ b/libs/lxcpp/container-config.hpp
@@ -25,6 +25,7 @@
#define LXCPP_CONTAINER_CONFIG_HPP
#include "lxcpp/logger-config.hpp"
+#include "lxcpp/network-config.hpp"
#include
#include
@@ -71,6 +72,14 @@ struct ContainerConfig {
pid_t mInitPid;
/**
+ * Container network configration
+ *
+ * Set: by container network config methods
+ * Get: none
+ */
+ NetworkConfig mNetwork;
+
+ /**
* Argv of the container's init process to be executed.
* The path has to be relative to the RootPath.
*
diff --git a/libs/lxcpp/container-impl.cpp b/libs/lxcpp/container-impl.cpp
index cee6fa4..a524231 100644
--- a/libs/lxcpp/container-impl.cpp
+++ b/libs/lxcpp/container-impl.cpp
@@ -182,22 +182,48 @@ void ContainerImpl::addInterfaceConfig(const std::string& hostif,
InterfaceType type,
MacVLanMode mode)
{
- mInterfaceConfig.push_back(NetworkInterfaceConfig(hostif,zoneif,type,mode));
+ mConfig.mNetwork.addInterfaceConfig(hostif, zoneif, type, mode);
}
-void ContainerImpl::addAddrConfig(const std::string& /*ifname*/, const InetAddr& /*addr*/)
+void ContainerImpl::addInetConfig(const std::string& ifname, const InetAddr& addr)
{
- throw NotImplementedException();
+ mConfig.mNetwork.addInetConfig(ifname, addr);
}
-std::vector ContainerImpl::getInterfaces()
+std::vector ContainerImpl::getInterfaces() const
{
return NetworkInterface::getInterfaces(getInitPid());
}
-NetworkInterfaceInfo ContainerImpl::getInterfaceInfo(const std::string& /*ifname*/)
+NetworkInterfaceInfo ContainerImpl::getInterfaceInfo(const std::string& ifname) const
{
- throw NotImplementedException();
+ NetworkInterface ni(getInitPid(), ifname);
+ std::vector addrs;
+ std::string macaddr;
+ InetAddr addr;
+ int mtu = 0, flags = 0;
+ Attrs attrs = ni.getAttrs();
+ for (const Attr& a : attrs) {
+ switch (a.name) {
+ case AttrName::MAC:
+ macaddr = a.value;
+ break;
+ case AttrName::MTU:
+ mtu = std::stoul(a.value);
+ break;
+ case AttrName::IPV6:
+ case AttrName::IPV4:
+ NetworkInterface::convertAttr2InetAddr(a, addr);
+ addrs.push_back(addr);
+ break;
+ case AttrName::FLAGS:
+ flags = std::stoul(a.value);
+ break;
+ default: //ignore others
+ break;
+ }
+ }
+ return NetworkInterfaceInfo{ifname, ni.status(), macaddr, mtu, flags, addrs};
}
void ContainerImpl::createInterface(const std::string& hostif,
@@ -205,7 +231,7 @@ void ContainerImpl::createInterface(const std::string& hostif,
InterfaceType type,
MacVLanMode mode)
{
- NetworkInterface ni(*this, zoneif);
+ NetworkInterface ni(getInitPid(), zoneif);
ni.create(hostif, type, mode);
}
diff --git a/libs/lxcpp/container-impl.hpp b/libs/lxcpp/container-impl.hpp
index 1bf44b7..3379143 100644
--- a/libs/lxcpp/container-impl.hpp
+++ b/libs/lxcpp/container-impl.hpp
@@ -34,7 +34,6 @@
namespace lxcpp {
-
class ContainerImpl : public virtual Container {
public:
ContainerImpl(const std::string &name, const std::string &path);
@@ -69,15 +68,19 @@ public:
const std::string& cwdInContainer);
// Network interfaces setup/config
+ /**
+ * adds interface configration.
+ * throws NetworkException if zoneif name already on list
+ */
void addInterfaceConfig(const std::string& hostif,
- const std::string& zoneif,
- InterfaceType type,
- MacVLanMode mode);
- void addAddrConfig(const std::string& ifname, const InetAddr& addr);
+ const std::string& zoneif,
+ InterfaceType type,
+ MacVLanMode mode);
+ void addInetConfig(const std::string& ifname, const InetAddr& addr);
// Network interfaces (runtime)
- std::vector getInterfaces();
- NetworkInterfaceInfo getInterfaceInfo(const std::string& ifname);
+ std::vector getInterfaces() const;
+ NetworkInterfaceInfo getInterfaceInfo(const std::string& ifname) const;
void createInterface(const std::string& hostif,
const std::string& zoneif,
InterfaceType type,
@@ -93,7 +96,6 @@ private:
// TODO: convert to ContainerConfig struct
std::vector mNamespaces;
- std::vector mInterfaceConfig;
};
} // namespace lxcpp
diff --git a/libs/lxcpp/container.hpp b/libs/lxcpp/container.hpp
index 88c3ff8..3e126d2 100644
--- a/libs/lxcpp/container.hpp
+++ b/libs/lxcpp/container.hpp
@@ -34,14 +34,12 @@
namespace lxcpp {
-enum class NetStatus {
- DOWN,
- UP
-};
-
struct NetworkInterfaceInfo {
const std::string ifname;
const NetStatus status;
+ const std::string macaddr;
+ const int mtu;
+ const int flags;
const std::vector addrs;
};
@@ -78,14 +76,14 @@ public:
// Network interfaces setup/config
virtual void addInterfaceConfig(const std::string& hostif,
- const std::string& zoneif,
- InterfaceType type,
- MacVLanMode mode) = 0;
- virtual void addAddrConfig(const std::string& ifname, const InetAddr& addr) = 0;
+ const std::string& zoneif,
+ InterfaceType type,
+ MacVLanMode mode) = 0;
+ virtual void addInetConfig(const std::string& ifname, const InetAddr& addr) = 0;
// Network interfaces (runtime)
- virtual std::vector getInterfaces() = 0;
- virtual NetworkInterfaceInfo getInterfaceInfo(const std::string& ifname) = 0;
+ virtual std::vector getInterfaces() const = 0;
+ virtual NetworkInterfaceInfo getInterfaceInfo(const std::string& ifname) const = 0;
virtual void createInterface(const std::string& hostif,
const std::string& zoneif,
InterfaceType type,
diff --git a/libs/lxcpp/network-config.cpp b/libs/lxcpp/network-config.cpp
index 77e220a..17e1449 100644
--- a/libs/lxcpp/network-config.cpp
+++ b/libs/lxcpp/network-config.cpp
@@ -23,25 +23,81 @@
*/
#include "lxcpp/network-config.hpp"
+#include "lxcpp/network.hpp"
#include "lxcpp/exception.hpp"
+#include "logger/logger.hpp"
#include
+
namespace lxcpp {
-void NetworkInterfaceConfig::addNetAddr(const InetAddr& addr)
+const std::string& NetworkInterfaceConfig::getHostIf() const
+{
+ return mHostIf;
+}
+
+const std::string& NetworkInterfaceConfig::getZoneIf() const
+{
+ return mZoneIf;
+}
+
+const InterfaceType& NetworkInterfaceConfig::getType() const
+{
+ return mType;
+}
+
+const MacVLanMode& NetworkInterfaceConfig::getMode() const
+{
+ return mMode;
+}
+
+const std::vector& NetworkInterfaceConfig::getAddrList() const
+{
+ return mIpAddrList;
+}
+
+void NetworkInterfaceConfig::addInetAddr(const InetAddr& addr)
{
std::vector::iterator exists = std::find(mIpAddrList.begin(), mIpAddrList.end(), addr);
if (exists != mIpAddrList.end()) {
- std::string msg("Address alredy assigned");
+ std::string msg("Address already assigned");
throw NetworkException(msg);
}
mIpAddrList.push_back(addr);
}
-void NetworkInterfaceConfig::delNetAddr(const InetAddr& addr)
+void NetworkConfig::addInterfaceConfig(const std::string& hostif,
+ const std::string& zoneif,
+ InterfaceType type,
+ MacVLanMode mode)
{
- std::vector::iterator exists = std::find(mIpAddrList.begin(), mIpAddrList.end(), addr);
- mIpAddrList.erase(exists);
+ auto it = std::find_if(mInterfaces.begin(), mInterfaces.end(),
+ [&zoneif](const NetworkInterfaceConfig& entry) {
+ return entry.getZoneIf() == zoneif;
+ }
+ );
+ if (it != mInterfaces.end()) {
+ std::string msg = "Interface already exists";
+ LOGE(msg);
+ throw NetworkException(msg);
+ }
+ mInterfaces.push_back(NetworkInterfaceConfig(hostif,zoneif,type,mode));
+}
+
+void NetworkConfig::addInetConfig(const std::string& ifname, const InetAddr& addr)
+{
+ auto it = std::find_if(mInterfaces.begin(), mInterfaces.end(),
+ [&ifname](const NetworkInterfaceConfig& entry) {
+ return entry.getZoneIf() == ifname;
+ }
+ );
+
+ if (it == mInterfaces.end()) {
+ std::string msg = "No such interface";
+ LOGE(msg);
+ throw NetworkException(msg);
+ }
+ it->addInetAddr(addr);
}
} //namespace lxcpp
diff --git a/libs/lxcpp/network-config.hpp b/libs/lxcpp/network-config.hpp
index b4e2fe0..c94f45b 100644
--- a/libs/lxcpp/network-config.hpp
+++ b/libs/lxcpp/network-config.hpp
@@ -24,11 +24,15 @@
#ifndef LXCPP_NETWORK_CONFIG_HPP
#define LXCPP_NETWORK_CONFIG_HPP
+#include "config/config.hpp"
+#include "config/fields.hpp"
+
#include
#include
#include
#include
+#include
namespace lxcpp {
@@ -60,11 +64,18 @@ enum class InetAddrType {
IPV6
};
+enum class NetStatus {
+ DOWN,
+ UP
+};
+
+
/**
* Unified ip address
*/
struct InetAddr {
InetAddrType type;
+ uint32_t flags;
int prefix;
union {
struct in_addr ipv4;
@@ -99,22 +110,56 @@ public:
mType(type),
mMode(mode)
{
- // TODO: Remove temporary usage
- (void) mType;
- (void) mMode;
}
- void addNetAddr(const InetAddr&);
- void delNetAddr(const InetAddr&);
+ const std::string& getHostIf() const;
+
+ const std::string& getZoneIf() const;
+
+ const InterfaceType& getType() const;
+
+ const MacVLanMode& getMode() const;
+
+ const std::vector& getAddrList() const;
+
+ void addInetAddr(const InetAddr&);
private:
const std::string mHostIf;
const std::string mZoneIf;
const InterfaceType mType;
const MacVLanMode mMode;
+ //TODO mtu, macaddress, txqueue
+ /*
+ * above are interface parameters which can be read/modified:
+ * MTU (Maximum Transmit Unit) is maximum length of link level packet in TCP stream
+ * MAC address is also called hardware card address
+ * TXQueue is transmit queue length
+ *
+ * I think most usufull would be possibility to set MAC address, other have their
+ * well working defaults but can be tuned to make faster networking (especially localy)
+ */
std::vector mIpAddrList;
};
+/**
+ * Network interface configuration
+ */
+struct NetworkConfig {
+
+ //for convinience
+ void addInterfaceConfig(const std::string& hostif,
+ const std::string& zoneif,
+ InterfaceType type,
+ MacVLanMode mode);
+ void addInetConfig(const std::string& ifname, const InetAddr& addr);
+
+ std::vector mInterfaces;
+
+ //TODO tmporary to allow serialization of this object
+ CONFIG_REGISTER_EMPTY
+};
+
} //namespace lxcpp
#endif // LXCPP_NETWORK_CONFIG_HPP
diff --git a/libs/lxcpp/network.cpp b/libs/lxcpp/network.cpp
index ad01f6f..965f20c 100644
--- a/libs/lxcpp/network.cpp
+++ b/libs/lxcpp/network.cpp
@@ -23,16 +23,172 @@
#include "lxcpp/network.hpp"
+#include "lxcpp/container.hpp"
#include "lxcpp/exception.hpp"
#include "netlink/netlink-message.hpp"
#include "utils/make-clean.hpp"
+#include "utils/text.hpp"
+#include "logger/logger.hpp"
+
+#include
#include
+#include
+
+#define CHANGE_FLAGS_DEFAULT 0xffffffff
+/* from linux/if_addr.h:
+ * IFA_FLAGS is a u32 attribute that extends the u8 field ifa_flags.
+ * If present, the value from struct ifaddrmsg will be ignored.
+ *
+ * But this FLAG is available since some kernel version
+ * check if one of extended flags id defined
+ */
+#ifndef IFA_F_MANAGETEMPADDR
+#define IFA_FLAGS IFA_UNSPEC
+#endif
using namespace vasum::netlink;
namespace lxcpp {
+namespace {
+std::string toString(const in_addr& addr)
+{
+ char buf[INET_ADDRSTRLEN];
+ const char* ret = ::inet_ntop(AF_INET, &addr, buf, INET_ADDRSTRLEN);
+ if (ret == NULL) {
+ std::string msg = "Can't parse inet v4 addr";
+ LOGE(msg);
+ throw NetworkException(msg);
+ }
+ return ret;
+}
+
+std::string toString(const in6_addr& addr)
+{
+ char buf[INET6_ADDRSTRLEN];
+ const char* ret = ::inet_ntop(AF_INET6, &addr, buf, INET6_ADDRSTRLEN);
+ if (ret == NULL) {
+ std::string msg = "Can't parse inet v6 addr";
+ LOGE(msg);
+ throw NetworkException(msg);
+ }
+ return ret;
+}
+
+uint32_t getInterfaceIndex(const std::string& name)
+{
+ uint32_t index = ::if_nametoindex(name.c_str());
+ if (!index) {
+ std::string msg = "Can't find interface";
+ LOGE(msg);
+ throw NetworkException(msg);
+ }
+ return index;
+}
+
+uint32_t getInterfaceIndex(const std::string& name, pid_t pid)
+{
+ NetlinkMessage nlm(RTM_GETLINK, NLM_F_REQUEST | NLM_F_ACK);
+ ifinfomsg infoPeer = utils::make_clean();
+ infoPeer.ifi_family = AF_UNSPEC;
+ infoPeer.ifi_change = CHANGE_FLAGS_DEFAULT;
+ nlm.put(infoPeer)
+ .put(IFLA_IFNAME, name);
+
+ NetlinkResponse response = send(nlm, pid);
+ if (!response.hasMessage()) {
+ std::string msg = "Can't get interface index";
+ LOGE(msg);
+ throw NetworkException(msg);
+ }
+
+ response.fetch(infoPeer);
+ return infoPeer.ifi_index;
+}
+
+void getAddressAttrs(Attrs& attrs, int family, const std::string& ifname, pid_t pid)
+{
+ uint32_t index = getInterfaceIndex(ifname, pid);
+ NetlinkMessage nlm(RTM_GETADDR, NLM_F_REQUEST | NLM_F_ACK | NLM_F_DUMP);
+ ifaddrmsg infoAddr = utils::make_clean();
+ infoAddr.ifa_family = family; //test AF_PACKET to get all AF_INET* ?
+ nlm.put(infoAddr);
+
+ NetlinkResponse response = send(nlm, pid);
+ if (!response.hasMessage()) {
+ return ;
+ }
+
+ Attr attr;
+ while (response.hasMessage()) {
+ ifaddrmsg addrmsg;
+ response.fetch(addrmsg);
+ if (addrmsg.ifa_index == index) {
+ InetAddr a;
+ if (addrmsg.ifa_family == AF_INET6) {
+ a.type = InetAddrType::IPV6;
+ } else if (addrmsg.ifa_family == AF_INET) {
+ a.type = InetAddrType::IPV4;
+ } else {
+ std::string msg = "Unsupported inet family";
+ LOGE(msg);
+ throw NetworkException(msg);
+ }
+ a.flags = addrmsg.ifa_flags; // IF_F_SECONDARY = secondary(alias)
+ a.prefix = addrmsg.ifa_prefixlen;
+
+ bool hasLocal = false;
+ while (response.hasAttribute()) {
+
+ int attrType = response.getAttributeType();
+ switch (attrType) {
+
+ // on each case line, int number in comment is value of the enum
+ case IFA_ADDRESS: //1
+ if (hasLocal) {
+ response.skipAttribute();
+ break;
+ }
+ // fall thru
+ case IFA_LOCAL: //2
+ if (addrmsg.ifa_family == AF_INET6) {
+ response.fetch(attrType, a.addr.ipv6);
+ } else if (addrmsg.ifa_family == AF_INET) {
+ response.fetch(attrType, a.addr.ipv4);
+ } else {
+ LOGW("unsupported family " << addrmsg.ifa_family);
+ response.skipAttribute();
+ }
+ hasLocal=true;
+ break;
+
+ case IFA_FLAGS: //8 extended flags - overwrites addrmsg.ifa_flags
+ response.fetch(IFA_FLAGS, a.flags);
+ break;
+
+ case IFA_LABEL: //3 <- should be equal to ifname
+ case IFA_BROADCAST://4
+ case IFA_ANYCAST: //5
+ case IFA_CACHEINFO://6
+ case IFA_MULTICAST://7
+ default:
+ //std::string tmp;
+ //response.fetch(attrType, tmp);
+ //std::cout << "skip(IFA) " << attrType << ":" << tmp << std::endl;
+ response.skipAttribute();
+ break;
+ }
+ }
+ NetworkInterface::convertInetAddr2Attr(a, attr);
+ attrs.push_back(attr);
+ }
+ response.fetchNextMessage();
+ }
+}
+} // anonymous namespace
+
+
void NetworkInterface::create(const std::string& hostif,
InterfaceType type,
MacVLanMode mode)
@@ -70,9 +226,21 @@ void NetworkInterface::createMacVLan(const std::string& /*hostif*/, MacVLanMode
throw NotImplementedException();
}
-void NetworkInterface::move(const std::string& /*hostif*/)
+void NetworkInterface::move(const std::string& hostif)
{
- throw NotImplementedException();
+ uint32_t index = getInterfaceIndex(hostif);
+ NetlinkMessage nlm(RTM_NEWLINK, NLM_F_REQUEST | NLM_F_ACK);
+ ifinfomsg infopeer = utils::make_clean();
+ infopeer.ifi_family = AF_UNSPEC;
+ infopeer.ifi_index = index;
+ nlm.put(infopeer)
+ .put(IFLA_NET_NS_PID, mContainerPid);
+ send(nlm);
+
+ //rename to mIfname inside container
+ if (mIfname != hostif) {
+ renameFrom(hostif);
+ }
}
void NetworkInterface::destroy()
@@ -85,7 +253,7 @@ NetStatus NetworkInterface::status()
throw NotImplementedException();
/*
//TODO get container status, if stopped return CONFIGURED
- if (mContainer.getInitPid()<=0) return CONFIGURED;
+ if (mContainerPid<=0) return CONFIGURED;
// read netlink
return DOWN;*/
}
@@ -101,14 +269,152 @@ void NetworkInterface::down()
throw NotImplementedException();
}
-void NetworkInterface::setAttrs(const Attrs& /*attrs*/)
+void NetworkInterface::renameFrom(const std::string& oldif)
{
- throw NotImplementedException();
+ NetlinkMessage nlm(RTM_SETLINK, NLM_F_REQUEST | NLM_F_ACK);
+ ifinfomsg infoPeer = utils::make_clean();
+ infoPeer.ifi_family = AF_UNSPEC;
+ infoPeer.ifi_index = getInterfaceIndex(oldif, mContainerPid);
+ infoPeer.ifi_change = CHANGE_FLAGS_DEFAULT;
+
+ nlm.put(infoPeer)
+ .put(IFLA_IFNAME, mIfname);
+ send(nlm, mContainerPid);
}
-const Attrs NetworkInterface::getAttrs() const
+void NetworkInterface::addInetAddr(const InetAddr& addr)
{
- throw NotImplementedException();
+ NetlinkMessage nlm(RTM_NEWADDR, NLM_F_CREATE | NLM_F_REQUEST | NLM_F_ACK);
+ ifaddrmsg infoAddr = utils::make_clean();
+ infoAddr.ifa_index = getInterfaceIndex(mIfname, mContainerPid);
+ infoAddr.ifa_family = addr.type == InetAddrType::IPV4 ? AF_INET : AF_INET6;
+ infoAddr.ifa_prefixlen = addr.prefix;
+ infoAddr.ifa_flags = addr.flags;
+ nlm.put(infoAddr);
+
+ if (addr.type == InetAddrType::IPV6) {
+ nlm.put(IFA_ADDRESS, addr.addr.ipv6);
+ nlm.put(IFA_LOCAL, addr.addr.ipv6);
+ } else if (addr.type == InetAddrType::IPV4) {
+ nlm.put(IFA_ADDRESS, addr.addr.ipv4);
+ nlm.put(IFA_LOCAL, addr.addr.ipv4);
+ }
+
+ send(nlm, mContainerPid);
+}
+
+void NetworkInterface::setAttrs(const Attrs& attrs)
+{
+ //TODO check this: NetlinkMessage nlm(RTM_SETLINK, NLM_F_REQUEST | NLM_F_ACK);
+ NetlinkMessage nlm(RTM_NEWLINK, NLM_F_REQUEST | NLM_F_CREATE | NLM_F_ACK);
+ unsigned mtu=0, link=0, txq=0;
+ ifinfomsg infoPeer = utils::make_clean();
+ infoPeer.ifi_family = AF_UNSPEC;
+ infoPeer.ifi_index = getInterfaceIndex(mIfname, mContainerPid);
+ infoPeer.ifi_change = CHANGE_FLAGS_DEFAULT;
+
+ for (const auto& attr : attrs) {
+ if (attr.name == AttrName::FLAGS) {
+ infoPeer.ifi_flags = stoul(attr.value);
+ } else if (attr.name == AttrName::CHANGE) {
+ infoPeer.ifi_change = stoul(attr.value);
+ } else if (attr.name == AttrName::TYPE) {
+ infoPeer.ifi_type = stoul(attr.value);
+ } else if (attr.name == AttrName::MTU) {
+ mtu = stoul(attr.value);
+ } else if (attr.name == AttrName::LINK) {
+ link = stoul(attr.value);
+ } else if (attr.name == AttrName::TXQLEN) {
+ txq = stoul(attr.value);
+ }
+ }
+ nlm.put(infoPeer);
+ if (mtu) {
+ nlm.put(IFLA_MTU, mtu);
+ }
+ if (link) {
+ nlm.put(IFLA_LINK, link);
+ }
+ if (txq) {
+ nlm.put(IFLA_TXQLEN, txq);
+ }
+
+ NetlinkResponse response = send(nlm, mContainerPid);
+ if (!response.hasMessage()) {
+ throw NetworkException("Can't set interface information");
+ }
+
+ // configure inet addresses
+ InetAddr addr;
+ for (const Attr& a : attrs) {
+ if (convertAttr2InetAddr(a, addr)) {
+ addInetAddr(addr);
+ }
+ }
+}
+
+Attrs NetworkInterface::getAttrs() const
+{
+ NetlinkMessage nlm(RTM_GETLINK, NLM_F_REQUEST | NLM_F_ACK);
+ ifinfomsg infoPeer = utils::make_clean();
+ infoPeer.ifi_family = AF_UNSPEC;
+ infoPeer.ifi_change = CHANGE_FLAGS_DEFAULT;
+ nlm.put(infoPeer)
+ .put(IFLA_IFNAME, mIfname);
+
+ NetlinkResponse response = send(nlm, mContainerPid);
+ if (!response.hasMessage()) {
+ throw NetworkException("Can't get interface information");
+ }
+
+ Attrs attrs;
+ response.fetch(infoPeer);
+ attrs.push_back(Attr{AttrName::FLAGS, std::to_string(infoPeer.ifi_flags)});
+ attrs.push_back(Attr{AttrName::TYPE, std::to_string(infoPeer.ifi_type)});
+
+ while (response.hasAttribute()) {
+ /*
+ * While traditional MAC addresses are all 48 bits in length,
+ * a few types of networks require 64-bit addresses instead.
+ */
+ std::string mac;
+ uint32_t mtu, link, txq;
+ int attrType = response.getAttributeType();
+ switch (attrType) {
+ case IFLA_ADDRESS: //1
+ response.fetch(IFLA_ADDRESS, mac);
+ attrs.push_back(Attr{AttrName::MAC, utils::toHexString(mac.c_str(), mac.size())});
+ break;
+ case IFLA_MTU: //4
+ response.fetch(IFLA_MTU, mtu);
+ attrs.push_back(Attr{AttrName::MTU, std::to_string(mtu)});
+ break;
+ case IFLA_LINK://5
+ response.fetch(IFLA_LINK, link);
+ attrs.push_back(Attr{AttrName::LINK, std::to_string(link)});
+ break;
+ case IFLA_TXQLEN://13
+ response.fetch(IFLA_TXQLEN, txq);
+ attrs.push_back(Attr{AttrName::TXQLEN, std::to_string(txq)});
+ break;
+ case IFLA_BROADCAST://2 MAC broadcast
+ case IFLA_IFNAME: //3
+ case IFLA_QDISC: //6 queue discipline
+ case IFLA_STATS: //7 struct net_device_stats
+ case IFLA_COST: //8
+ case IFLA_PRIORITY: //9
+ case IFLA_MASTER: //10
+ case IFLA_WIRELESS: //11
+ case IFLA_PROTINFO: //12
+ case IFLA_MAP: //14
+ default:
+ response.skipAttribute();
+ break;
+ }
+ }
+ getAddressAttrs(attrs, AF_INET, mIfname, mContainerPid);
+ getAddressAttrs(attrs, AF_INET6, mIfname, mContainerPid);
+ return attrs;
}
std::vector NetworkInterface::getInterfaces(pid_t initpid)
@@ -124,11 +430,87 @@ std::vector NetworkInterface::getInterfaces(pid_t initpid)
while (response.hasMessage()) {
std::string ifName;
response.skip();
- response.fetch(IFLA_IFNAME, ifName);
+ // fetched value contains \0 terminator
+ int len = response.getAttributeLength();
+ response.fetch(IFLA_IFNAME, ifName, len - 1);
iflist.push_back(ifName);
response.fetchNextMessage();
}
return iflist;
}
+void NetworkInterface::convertInetAddr2Attr(const InetAddr& a, Attr& attr)
+{
+ std::string value;
+
+ if (a.type == InetAddrType::IPV6) {
+ value += "ip=" + toString(a.addr.ipv6);
+ } else if (a.type == InetAddrType::IPV4) {
+ value += "ip=" + toString(a.addr.ipv4);
+ } else {
+ throw NetworkException();
+ }
+
+ value += ",pfx=" + std::to_string(a.prefix);
+ value += ",flags=" + std::to_string(a.flags);
+
+ if (a.type == InetAddrType::IPV6) {
+ attr = Attr{AttrName::IPV6, value};
+ } else {
+ attr = Attr{AttrName::IPV4, value};
+ }
+}
+
+bool NetworkInterface::convertAttr2InetAddr(const Attr& attr, InetAddr& addr)
+{
+ std::string::size_type s = 0U;
+ std::string::size_type e = s;
+
+ if (attr.name != AttrName::IPV6 && attr.name != AttrName::IPV4) {
+ return false; //not inet attribute
+ }
+
+ addr.prefix = 0;
+ addr.flags = 0;
+
+ bool addrFound = false;
+ while (e != std::string::npos) {
+ e = attr.value.find(',', s);
+ std::string ss = attr.value.substr(s, e - s);
+ s = e + 1;
+
+ std::string name;
+ std::string value;
+ std::string::size_type p = ss.find('=');
+ if (p != std::string::npos) {
+ name = ss.substr(0, p);
+ value = ss.substr(p + 1);
+ } else {
+ name = ss;
+ //value remains empty
+ }
+
+ if (name == "ip") {
+ if (attr.name == AttrName::IPV6) {
+ addr.type = InetAddrType::IPV6;
+ if (inet_pton(AF_INET6, value.c_str(), &addr.addr.ipv6) != 1) {
+ throw NetworkException("Parse IPV6 address");
+ }
+ } else if (attr.name == AttrName::IPV4) {
+ addr.type = InetAddrType::IPV4;
+ if (inet_pton(AF_INET, value.c_str(), &addr.addr.ipv4) != 1) {
+ throw NetworkException("Parse IPV4 address");
+ }
+ }
+ addrFound = true;
+ } else if (name == "pfx") {
+ addr.prefix = stoul(value);
+ } else if (name == "flags") {
+ addr.flags = stoul(value);
+ }
+ }
+
+ return addrFound;
+}
+
} // namespace lxcpp
diff --git a/libs/lxcpp/network.hpp b/libs/lxcpp/network.hpp
index 8381611..cc0167e 100644
--- a/libs/lxcpp/network.hpp
+++ b/libs/lxcpp/network.hpp
@@ -24,31 +24,65 @@
#ifndef LXCPP_NETWORK_HPP
#define LXCPP_NETWORK_HPP
-#include "lxcpp/container.hpp"
+#include "lxcpp/network-config.hpp"
+
+#include
#include
+#include
namespace lxcpp {
+enum class AttrName {
+ MAC,
+ FLAGS,
+ CHANGE,
+ TYPE,
+ MTU,
+ LINK,
+ TXQLEN,
+ IPV4,
+ IPV6,
+};
+
+inline std::ostream& operator<<(std::ostream& os, const AttrName& a) {
+ switch (a) {
+ case AttrName::MAC: os << "mac"; break;
+ case AttrName::FLAGS: os << "flags"; break;
+ case AttrName::CHANGE: os << "change"; break;
+ case AttrName::TYPE: os << "type"; break;
+ case AttrName::MTU: os << "mtu"; break;
+ case AttrName::LINK: os << "link"; break;
+ case AttrName::TXQLEN: os << "txq"; break;
+ case AttrName::IPV4: os << "ipv4"; break;
+ case AttrName::IPV6: os << "ipv6"; break;
+ }
+ return os;
+}
+
struct Attr {
- std::string name;
+ AttrName name;
std::string value;
};
typedef std::vector Attrs;
-
-/// Network operations to be performed on given container and interface
-/// operates on netlink device
+/**
+ * Network operations to be performed on given container and interface
+ * operates on netlink device
+ */
class NetworkInterface {
public:
- NetworkInterface(Container& c, const std::string& ifname) :
- mContainer(c),
+ /**
+ * Create network interface object for the ifname in the container
+ */
+ NetworkInterface(pid_t pid, const std::string& ifname) :
+ mContainerPid(pid),
mIfname(ifname)
{
- // TODO: Remove temporary usage
- (void) mContainer;
}
+ const std::string& getName() const { return mIfname; }
+
//Network actions on Container
void create(const std::string& hostif, InterfaceType type, MacVLanMode mode=MacVLanMode::PRIVATE);
void destroy();
@@ -56,19 +90,39 @@ public:
NetStatus status();
void up();
void down();
+
+ /**
+ * Rename interface name
+ * Equivalent to: ip link set dev $oldif name $this.mIfname
+ */
+ void renameFrom(const std::string& oldif);
+
void setAttrs(const Attrs& attrs);
- const Attrs getAttrs() const;
+ Attrs getAttrs() const;
+
+ void setMACAddress(const std::string& macaddr);
+ void setMTU(int mtu);
+ void setTxLength(int txlen);
+ void addInetAddr(const InetAddr& addr);
+ void delInetAddr(const InetAddr& addr);
static std::vector getInterfaces(pid_t initpid);
+ static void convertInetAddr2Attr(const InetAddr& addr, Attr& attr);
+ static bool convertAttr2InetAddr(const Attr& attr, InetAddr& addr);
+
private:
void createVeth(const std::string& hostif);
void createBridge(const std::string& hostif);
void createMacVLan(const std::string& hostif, MacVLanMode mode);
+ /**
+ * Move interface to container
+ * Equivalent to: ip link set dev $hostif netns $mContainerPid
+ */
void move(const std::string& hostif);
- Container& mContainer; ///< Container to operate on
- const std::string mIfname; ///< network interface name inside zone
+ pid_t mContainerPid; ///< Container pid to operate on (0=kernel)
+ const std::string mIfname; ///< network interface name inside zone
};
} // namespace lxcpp
diff --git a/server/netdev.cpp b/server/netdev.cpp
index dc8642c..8387c84 100644
--- a/server/netdev.cpp
+++ b/server/netdev.cpp
@@ -428,7 +428,9 @@ std::vector listNetdev(const pid_t& nsPid)
while (response.hasMessage()) {
std::string ifName;
response.skip();
- response.fetch(IFLA_IFNAME, ifName);
+ // fetched value contains \0 terminator
+ int len = response.getAttributeLength();
+ response.fetch(IFLA_IFNAME, ifName, len - 1);
interfaces.push_back(ifName);
response.fetchNextMessage();
}
diff --git a/tests/unit_tests/lxcpp/ut-network.cpp b/tests/unit_tests/lxcpp/ut-network.cpp
new file mode 100644
index 0000000..373ec1b
--- /dev/null
+++ b/tests/unit_tests/lxcpp/ut-network.cpp
@@ -0,0 +1,83 @@
+/*
+ * Copyright (C) 2015 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License version 2.1 as published by the Free Software Foundation.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+/**
+ * @file
+ * @author Krzysztof Dynowski (k.dynowski@samsumg.com)
+ * @brief Unit tests of lxcpp network helpers
+ */
+
+#include "config.hpp"
+#include "config/manager.hpp"
+#include "lxcpp/network.hpp"
+#include "ut.hpp"
+
+#include
+#include
+
+namespace {
+
+struct Fixture {
+ Fixture() {}
+ ~Fixture() {}
+};
+
+} // namespace
+
+/*
+ * NOTE: network inerface unit tests are not finished yet
+ * tests are developed/added together with network interface code
+ * and container code development
+ */
+
+BOOST_FIXTURE_TEST_SUITE(LxcppNetworkSuite, Fixture)
+
+using namespace lxcpp;
+
+BOOST_AUTO_TEST_CASE(ListInterfaces)
+{
+ std::vector iflist;
+ BOOST_CHECK_NO_THROW(iflist = NetworkInterface::getInterfaces(0);)
+ for (const auto& i : iflist) {
+ std::cout << i << std::endl;
+ }
+}
+
+BOOST_AUTO_TEST_CASE(DetailedListInterfaces)
+{
+ std::vector iflist;
+ BOOST_CHECK_NO_THROW(iflist = NetworkInterface::getInterfaces(0);)
+ for (const auto& i : iflist) {
+ NetworkInterface ni(1,i);
+ std::cout << "Attrs of " << i << std::endl;
+ Attrs attrs;
+ BOOST_CHECK_NO_THROW(attrs = ni.getAttrs();)
+ for (const Attr& a : attrs) {
+ std::cout << a.name << "=" << a.value << "; ";
+ }
+ std::cout << std::endl;
+ }
+}
+BOOST_AUTO_TEST_CASE(NetworkConfigSerialization)
+{
+ NetworkConfig cfg;
+ std::string json;
+ BOOST_CHECK_NO_THROW(json = config::saveToJsonString(cfg);)
+ std::cout << json << std::endl;
+}
+
+BOOST_AUTO_TEST_SUITE_END()
--
2.7.4
From e1624f3797d5c9a50f5f4b8bfd0ce4970d0ed5f4 Mon Sep 17 00:00:00 2001
From: Pawel Kubik
Date: Fri, 18 Sep 2015 14:41:31 +0200
Subject: [PATCH 08/16] Fixed test scripts
[Feature] N/A
[Cause] Unit tests using fixtures can't be run separately,
because their names contains bash special characters.
[Solution] Put test names inside quotes.
[Verification] Install, launch single test case with fixture.
Change-Id: I61e426957e080b1a145bd901c155677775d571ba
---
tests/scripts/vsm_launch_test.py | 5 +++++
tests/scripts/vsm_test_parser.py | 2 +-
2 files changed, 6 insertions(+), 1 deletion(-)
diff --git a/tests/scripts/vsm_launch_test.py b/tests/scripts/vsm_launch_test.py
index 038ba30..dd5831f 100755
--- a/tests/scripts/vsm_launch_test.py
+++ b/tests/scripts/vsm_launch_test.py
@@ -5,6 +5,7 @@ from vsm_test_parser import Logger, Parser
import subprocess
import argparse
import os
+import re
_defLaunchArgs = ["--report_format=XML",
"--catch_system_errors=no",
@@ -38,6 +39,10 @@ def launchTest(cmd=[], externalToolCmd=[], parsing=True):
if externalToolCmd and not _checkIfBinExists(externalToolCmd[0]):
return
+ cmd[1:] = ["'{0}'".format(arg) if re.search("^\s*[^']*/.*<.*>\s*$", arg)
+ else arg
+ for arg in cmd[1:]]
+
log.info("Starting " + cmd[0] + " ...")
if parsing:
diff --git a/tests/scripts/vsm_test_parser.py b/tests/scripts/vsm_test_parser.py
index d0d4fa7..fc0eae6 100644
--- a/tests/scripts/vsm_test_parser.py
+++ b/tests/scripts/vsm_test_parser.py
@@ -80,7 +80,7 @@ class Logger(object):
commandPrefix = "vsm_launch_test.py " + bin + " -t "
self.infoTitle("Some tests failed. Use following command(s) to launch them explicitly:")
for test in self.__failedTests:
- self.error(self.__indentChar + commandPrefix + test)
+ self.error(self.__indentChar + commandPrefix + "'{0}'".format(test))
def terminatedBySignal(self, bin, signum):
self.error("\n=========== FAILED ===========\n")
--
2.7.4
From fe7acf72de44d39b5cb434fd9119364fc2ba44e2 Mon Sep 17 00:00:00 2001
From: Lukasz Pawelczyk
Date: Thu, 17 Sep 2015 18:18:04 +0200
Subject: [PATCH 09/16] lxcpp: Terminal preparation part 1 (host)
[Feature] Prepare pseudoterminals for the container
[Verification] Build, install, run tests
Changes in this commit:
- PrepHostTerminal command and surrounding function (openPty)
- Terminal(s)Config
- Changes to Start::daemonize() to do its job better
- fd-utils helpers for FD flags
- set CLOEXEC on FDs received through libConfig
Change-Id: I432447900c189bb50669267ff4422c36860b5481
---
common/utils/channel.cpp | 6 +-
common/utils/fd-utils.cpp | 32 ++++++
common/utils/fd-utils.hpp | 10 ++
libs/config/fdstore.cpp | 2 +-
libs/lxcpp/CMakeLists.txt | 2 +-
libs/lxcpp/commands/prep-host-terminal.cpp | 55 ++++++++++
libs/lxcpp/commands/prep-host-terminal.hpp | 57 +++++++++++
libs/lxcpp/commands/start.cpp | 60 ++++++-----
libs/lxcpp/container-config.hpp | 12 ++-
libs/lxcpp/container-impl.cpp | 16 +++
libs/lxcpp/container-impl.hpp | 2 +
libs/lxcpp/container.hpp | 2 +
libs/lxcpp/exception.hpp | 5 +
libs/lxcpp/guard/main.cpp | 9 +-
libs/lxcpp/terminal-config.hpp | 76 ++++++++++++++
libs/lxcpp/terminal.cpp | 155 +++++++++++++++++++++++++++++
libs/lxcpp/terminal.hpp | 59 +++++++++++
libs/lxcpp/utils.cpp | 44 +-------
libs/lxcpp/utils.hpp | 10 --
19 files changed, 526 insertions(+), 88 deletions(-)
create mode 100644 libs/lxcpp/commands/prep-host-terminal.cpp
create mode 100644 libs/lxcpp/commands/prep-host-terminal.hpp
create mode 100644 libs/lxcpp/terminal-config.hpp
create mode 100644 libs/lxcpp/terminal.cpp
create mode 100644 libs/lxcpp/terminal.hpp
diff --git a/common/utils/channel.cpp b/common/utils/channel.cpp
index 3a0dd31..52047ee 100644
--- a/common/utils/channel.cpp
+++ b/common/utils/channel.cpp
@@ -113,11 +113,7 @@ void Channel::setCloseOnExec(const bool closeOnExec)
{
const int fd = getFD();
- if (closeOnExec) {
- ::fcntl(fd, F_SETFD, ::fcntl(fd, F_GETFD) | FD_CLOEXEC);
- } else {
- ::fcntl(fd, F_SETFD, ::fcntl(fd, F_GETFD) & ~FD_CLOEXEC);
- }
+ utils::setCloseOnExec(fd, closeOnExec);
}
void Channel::closeSocket(int socketIndex)
diff --git a/common/utils/fd-utils.cpp b/common/utils/fd-utils.cpp
index 3b7b998..3e0db3e 100644
--- a/common/utils/fd-utils.cpp
+++ b/common/utils/fd-utils.cpp
@@ -93,6 +93,28 @@ void waitForEvent(int fd,
}
}
+void setFDFlag(const int fd, const int getOp, const int setOp, const int flag, const bool set)
+{
+ int ret = ::fcntl(fd, getOp);
+ if (ret == -1) {
+ std::string msg = "fcntl(): Failed to get FD flags: " + getSystemErrorMessage();
+ LOGE(msg);
+ throw UtilsException(msg);
+ }
+
+ if (set) {
+ ret = ::fcntl(fd, setOp, ret | flag);
+ } else {
+ ret = ::fcntl(fd, setOp, ret & ~flag);
+ }
+
+ if (ret == -1) {
+ std::string msg = "fcntl(): Failed to set FD flag: " + getSystemErrorMessage();
+ LOGE(msg);
+ throw UtilsException(msg);
+ }
+}
+
} // namespace
void close(int fd)
@@ -348,5 +370,15 @@ bool fdSend(int socket, int fd, const unsigned int timeoutMS)
return true;
}
+void setCloseOnExec(int fd, bool closeOnExec)
+{
+ setFDFlag(fd, F_GETFD, F_SETFD, FD_CLOEXEC, closeOnExec);
+}
+
+void setNonBlocking(int fd, bool nonBlocking)
+{
+ setFDFlag(fd, F_GETFL, F_SETFL, O_NONBLOCK, nonBlocking);
+}
+
} // namespace utils
diff --git a/common/utils/fd-utils.hpp b/common/utils/fd-utils.hpp
index 56e3f41..91bbff4 100644
--- a/common/utils/fd-utils.hpp
+++ b/common/utils/fd-utils.hpp
@@ -86,6 +86,16 @@ bool fdSend(int socket, int fd, const unsigned int timeoutMS = 5000);
*/
int fdRecv(int socket, const unsigned int timeoutMS = 5000);
+/**
+ * Set or remove CLOEXEC on a file descriptor
+ */
+void setCloseOnExec(int fd, bool closeOnExec);
+
+/**
+ * Set or remove NONBLOCK on a file descriptor
+ */
+void setNonBlocking(int fd, bool nonBlocking);
+
} // namespace utils
#endif // COMMON_UTILS_FD_HPP
diff --git a/libs/config/fdstore.cpp b/libs/config/fdstore.cpp
index cc0b903..44d2418 100644
--- a/libs/config/fdstore.cpp
+++ b/libs/config/fdstore.cpp
@@ -262,7 +262,7 @@ int FDStore::receiveFD(const unsigned int timeoutMS)
// Receive
for(;;) {
- ssize_t ret = ::recvmsg(mFD, &msgh, MSG_WAITALL);
+ ssize_t ret = ::recvmsg(mFD, &msgh, MSG_WAITALL | MSG_CMSG_CLOEXEC);
if (ret < 0) {
if (errno == EAGAIN || errno == EWOULDBLOCK || errno == EINTR) {
// Neglected errors, retry
diff --git a/libs/lxcpp/CMakeLists.txt b/libs/lxcpp/CMakeLists.txt
index 8f391e8..d5e205b 100644
--- a/libs/lxcpp/CMakeLists.txt
+++ b/libs/lxcpp/CMakeLists.txt
@@ -51,7 +51,7 @@ PKG_CHECK_MODULES(LXCPP_DEPS REQUIRED glib-2.0)
INCLUDE_DIRECTORIES(${LIBS_FOLDER} ${COMMON_FOLDER})
INCLUDE_DIRECTORIES(SYSTEM ${Boost_INCLUDE_DIRS} ${LXCPP_DEPS_INCLUDE_DIRS} ${JSON_C_INCLUDE_DIRS})
-TARGET_LINK_LIBRARIES(${PROJECT_NAME} Common ${pkgs_LDFLAGS} ${Boost_LIBRARIES} Logger Config)
+TARGET_LINK_LIBRARIES(${PROJECT_NAME} Common ${pkgs_LDFLAGS} ${Boost_LIBRARIES} Logger Config util)
## Generate the pc file ########################################################
CONFIGURE_FILE(${PC_FILE}.in ${CMAKE_CURRENT_BINARY_DIR}/${PC_FILE} @ONLY)
diff --git a/libs/lxcpp/commands/prep-host-terminal.cpp b/libs/lxcpp/commands/prep-host-terminal.cpp
new file mode 100644
index 0000000..f219ff9
--- /dev/null
+++ b/libs/lxcpp/commands/prep-host-terminal.cpp
@@ -0,0 +1,55 @@
+/*
+ * Copyright (C) 2015 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License version 2.1 as published by the Free Software Foundation.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+/**
+ * @file
+ * @author Lukasz Pawelczyk (l.pawelczyk@samsung.com)
+ * @brief Implementation of host terminal preparation
+ */
+
+#include "lxcpp/commands/prep-host-terminal.hpp"
+#include "lxcpp/terminal.hpp"
+
+#include "logger/logger.hpp"
+
+
+namespace lxcpp {
+
+
+PrepHostTerminal::PrepHostTerminal(TerminalsConfig &terminals)
+ : mTerminals(terminals)
+{
+}
+
+PrepHostTerminal::~PrepHostTerminal()
+{
+}
+
+void PrepHostTerminal::execute()
+{
+ LOGD("Creating " << mTerminals.count << " pseudoterminal(s) on the host side:");
+
+ for (int i = 0; i < mTerminals.count; ++i)
+ {
+ const auto pty = lxcpp::openPty(true);
+ LOGD(pty.second << " has been created");
+ mTerminals.PTYs.emplace_back(pty.first, pty.second);
+ }
+}
+
+
+} // namespace lxcpp
diff --git a/libs/lxcpp/commands/prep-host-terminal.hpp b/libs/lxcpp/commands/prep-host-terminal.hpp
new file mode 100644
index 0000000..f7153b2
--- /dev/null
+++ b/libs/lxcpp/commands/prep-host-terminal.hpp
@@ -0,0 +1,57 @@
+/*
+ * Copyright (C) 2015 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License version 2.1 as published by the Free Software Foundation.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+/**
+ * @file
+ * @author Lukasz Pawelczyk (l.pawelczyk@samsung.com)
+ * @brief Headers for host terminal preparation
+ */
+
+#ifndef LXCPP_COMMANDS_PREP_HOST_TERMINAL_HPP
+#define LXCPP_COMMANDS_PREP_HOST_TERMINAL_HPP
+
+#include "lxcpp/commands/command.hpp"
+#include "lxcpp/terminal-config.hpp"
+
+
+namespace lxcpp {
+
+
+class PrepHostTerminal final: Command {
+public:
+ /**
+ * Prepares the terminal on the host side.
+ *
+ * It creates a number of pseudoterminals and stores them
+ * to be passed to the guard and prepared for init process.
+ *
+ * @param config container's config
+ */
+ PrepHostTerminal(TerminalsConfig &config);
+ ~PrepHostTerminal();
+
+ void execute();
+
+private:
+ TerminalsConfig &mTerminals;
+};
+
+
+} // namespace lxcpp
+
+
+#endif // LXCPP_COMMANDS_PREP_HOST_TERMINAL_HPP
diff --git a/libs/lxcpp/commands/start.cpp b/libs/lxcpp/commands/start.cpp
index f68654a..32a3054 100644
--- a/libs/lxcpp/commands/start.cpp
+++ b/libs/lxcpp/commands/start.cpp
@@ -25,11 +25,14 @@
#include "lxcpp/exception.hpp"
#include "lxcpp/process.hpp"
#include "lxcpp/utils.hpp"
+#include "lxcpp/terminal.hpp"
#include "logger/logger.hpp"
#include "config/manager.hpp"
#include
+#include
+#include
namespace lxcpp {
@@ -94,41 +97,44 @@ void Start::parent(const pid_t pid)
void Start::daemonize()
{
+ // Prepare a clean daemonized environment for a guard process:
+
+ // Set a new session so the process looses its control terminal
+ if (::setsid() < 0) {
+ ::_exit(EXIT_FAILURE);
+ }
+
// Double fork() with exit() to reattach the process under the host's init
+ // and to make sure that the child (guard) is not a process group leader
+ // and cannot reacquire its control terminal
pid_t pid = ::fork();
- if (pid < 0) {
+ if (pid < 0) { // fork failed
+ ::_exit(EXIT_FAILURE);
+ }
+ if (pid > 0) { // exit in parent process
+ ::_exit(EXIT_SUCCESS);
+ }
+
+ // Chdir to / so it's independent on other directories
+ if (::chdir("/") < 0) {
::_exit(EXIT_FAILURE);
}
- if (pid == 0) {
- // Prepare a clean environment for a guard process:
- // - chdir to / so it's independent on other directories
- // - null std* fds so it's properly dettached from the terminal
- // - set a new session so it cannot reacquire a terminal
-
- if (::chdir("/") < 0) {
- ::_exit(EXIT_FAILURE);
- }
- if (nullStdFDs() <0) {
- ::_exit(EXIT_FAILURE);
- }
- if (::setsid() < 0) {
- ::_exit(EXIT_FAILURE);
- }
-
- // Add name and path of the container to argv. They are not used, but will
- // identify the container in the process list in case setProcTitle() fails
- // and will guarantee we have enough argv memory to write the title we want.
- const char *argv[] = {mGuardPath.c_str(),
- mChannelFD.c_str(),
- mConfig.mName.c_str(),
- mConfig.mRootPath.c_str(),
- NULL};
- ::execve(argv[0], const_cast(argv), NULL);
+ // Null std* fds so it's properly dettached from the terminal
+ if (nullStdFDs() < 0) {
::_exit(EXIT_FAILURE);
}
- ::_exit(EXIT_SUCCESS);
+ // Add name and path of the container to argv. They are not used, but will
+ // identify the container in the process list in case setProcTitle() fails
+ // and will guarantee we have enough argv memory to write the title we want.
+ const char *argv[] = {mGuardPath.c_str(),
+ mChannelFD.c_str(),
+ mConfig.mName.c_str(),
+ mConfig.mRootPath.c_str(),
+ NULL};
+ ::execve(argv[0], const_cast(argv), NULL);
+ ::_exit(EXIT_FAILURE);
}
diff --git a/libs/lxcpp/container-config.hpp b/libs/lxcpp/container-config.hpp
index 54422bf..c84b4ef 100644
--- a/libs/lxcpp/container-config.hpp
+++ b/libs/lxcpp/container-config.hpp
@@ -26,6 +26,7 @@
#include "lxcpp/logger-config.hpp"
#include "lxcpp/network-config.hpp"
+#include "lxcpp/terminal-config.hpp"
#include
#include
@@ -100,6 +101,14 @@ struct ContainerConfig {
*/
LoggerConfig mLogger;
+ /**
+ * Configuration for terminal(s), from API point of view, only their number.
+ *
+ * Set: setTerminalCount()
+ * Get: none
+ */
+ TerminalsConfig mTerminals;
+
ContainerConfig() : mGuardPid(-1), mInitPid(-1) {}
CONFIG_REGISTER
@@ -109,7 +118,8 @@ struct ContainerConfig {
mGuardPid,
mInitPid,
mInit,
- mLogger
+ mLogger,
+ mTerminals
)
};
diff --git a/libs/lxcpp/container-impl.cpp b/libs/lxcpp/container-impl.cpp
index a524231..715dad8 100644
--- a/libs/lxcpp/container-impl.cpp
+++ b/libs/lxcpp/container-impl.cpp
@@ -29,6 +29,7 @@
#include "lxcpp/capability.hpp"
#include "lxcpp/commands/attach.hpp"
#include "lxcpp/commands/start.hpp"
+#include "lxcpp/commands/prep-host-terminal.hpp"
#include "logger/logger.hpp"
#include "utils/exception.hpp"
@@ -128,9 +129,24 @@ void ContainerImpl::setLogger(const logger::LogType type,
mConfig.mLogger.set(type, level, arg);
}
+void ContainerImpl::setTerminalCount(const unsigned int count)
+{
+ if (count == 0) {
+ const std::string msg = "Container needs at least one terminal";
+ LOGE(msg);
+ throw ConfigureException(msg);
+ }
+
+ mConfig.mTerminals.count = count;
+}
+
void ContainerImpl::start()
{
// TODO: check config consistency and completeness somehow
+
+ PrepHostTerminal terminal(mConfig.mTerminals);
+ terminal.execute();
+
Start start(mConfig);
start.execute();
}
diff --git a/libs/lxcpp/container-impl.hpp b/libs/lxcpp/container-impl.hpp
index 3379143..97b9155 100644
--- a/libs/lxcpp/container-impl.hpp
+++ b/libs/lxcpp/container-impl.hpp
@@ -54,6 +54,8 @@ public:
const logger::LogLevel level,
const std::string &arg);
+ void setTerminalCount(const unsigned int count);
+
const std::vector& getNamespaces() const;
// Execution actions
diff --git a/libs/lxcpp/container.hpp b/libs/lxcpp/container.hpp
index 3e126d2..bf10a76 100644
--- a/libs/lxcpp/container.hpp
+++ b/libs/lxcpp/container.hpp
@@ -63,6 +63,8 @@ public:
const logger::LogLevel level,
const std::string &arg) = 0;
+ virtual void setTerminalCount(const unsigned int count) = 0;
+
// Execution actions
virtual void start() = 0;
virtual void stop() = 0;
diff --git a/libs/lxcpp/exception.hpp b/libs/lxcpp/exception.hpp
index 11a6a0e..387e2eb 100644
--- a/libs/lxcpp/exception.hpp
+++ b/libs/lxcpp/exception.hpp
@@ -71,6 +71,11 @@ struct UtilityException: public Exception {
: Exception(message) {}
};
+struct TerminalException: public Exception {
+ explicit TerminalException(const std::string& message = "Error during a terminal operation")
+ : Exception(message) {}
+};
+
struct BadArgument: public Exception {
explicit BadArgument(const std::string& message = "Bad argument passed")
: Exception(message) {}
diff --git a/libs/lxcpp/guard/main.cpp b/libs/lxcpp/guard/main.cpp
index c8db30b..1065ecb 100644
--- a/libs/lxcpp/guard/main.cpp
+++ b/libs/lxcpp/guard/main.cpp
@@ -35,15 +35,18 @@ int main(int argc, char *argv[])
::_exit(EXIT_FAILURE);
}
+ int channel = std::stoi(argv[1]);
+
// NOTE: this might not be required now, but I leave it here not to forget.
// We need to investigate this with vasum and think about possibility of
// poorly written software that leaks file descriptors and might use LXCPP.
#if 0
for(int fd = 3; fd < ::sysconf(_SC_OPEN_MAX); ++fd) {
- utils::close(fd);
+ if (fd != channel) {
+ utils::close(fd);
+ }
}
#endif
- int fd = std::stoi(argv[1]);
- return lxcpp::startGuard(fd);
+ return lxcpp::startGuard(channel);
}
diff --git a/libs/lxcpp/terminal-config.hpp b/libs/lxcpp/terminal-config.hpp
new file mode 100644
index 0000000..3d6675a
--- /dev/null
+++ b/libs/lxcpp/terminal-config.hpp
@@ -0,0 +1,76 @@
+/*
+ * Copyright (C) 2015 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License version 2.1 as published by the Free Software Foundation.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+/**
+ * @file
+ * @author Lukasz Pawelczyk (l.pawelczyk@samsumg.com)
+ * @brief Terminal configuration
+ */
+
+#ifndef LXCPP_TERMINAL_CONFIG_HPP
+#define LXCPP_TERMINAL_CONFIG_HPP
+
+#include "config/config.hpp"
+#include "config/fields.hpp"
+
+#include
+#include
+
+
+namespace lxcpp {
+
+
+struct TerminalConfig {
+ config::FileDescriptor masterFD;
+ std::string ptsName;
+
+ TerminalConfig()
+ : masterFD(-1)
+ {}
+
+ TerminalConfig(const int masterFD, const std::string &ptsName)
+ : masterFD(masterFD),
+ ptsName(ptsName)
+ {}
+
+ CONFIG_REGISTER
+ (
+ masterFD,
+ ptsName
+ )
+};
+
+struct TerminalsConfig {
+ int count;
+ std::vector PTYs;
+
+ TerminalsConfig(const int count = 1)
+ : count(count)
+ {}
+
+ CONFIG_REGISTER
+ (
+ count,
+ PTYs
+ )
+};
+
+
+} //namespace lxcpp
+
+
+#endif // LXCPP_TERMINAL_CONFIG_HPP
diff --git a/libs/lxcpp/terminal.cpp b/libs/lxcpp/terminal.cpp
new file mode 100644
index 0000000..ce77cd5
--- /dev/null
+++ b/libs/lxcpp/terminal.cpp
@@ -0,0 +1,155 @@
+/*
+ * Copyright (C) 2015 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License version 2.1 as published by the Free Software Foundation.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+/**
+ * @file
+ * @author Lukasz Pawelczyk (l.pawelczyk@samsung.com)
+ * @brief Terminal helpers implementation
+ */
+
+#include "lxcpp/exception.hpp"
+
+#include "logger/logger.hpp"
+#include "utils/exception.hpp"
+#include "utils/fd-utils.hpp"
+
+#include
+#include
+#include
+#include
+
+
+namespace lxcpp {
+
+
+namespace {
+
+void openpty(int *master, int *slave)
+{
+ // Do not use other parameters, they are not 100% safe
+ if (-1 == ::openpty(master, slave, NULL, NULL, NULL)) {
+ const std::string msg = "openpty() failed: " + utils::getSystemErrorMessage();
+ LOGE(msg);
+ throw TerminalException(msg);
+ }
+}
+
+void tcgetattr(const int fd, struct termios *termios_p)
+{
+ if (-1 == ::tcgetattr(fd, termios_p)) {
+ const std::string msg = "tcgetattr() failed: " + utils::getSystemErrorMessage();
+ LOGE(msg);
+ throw TerminalException(msg);
+ }
+}
+
+void tcsetattr(const int fd, const int optional_actions, const struct termios *termios_p)
+{
+ if (-1 == ::tcsetattr(fd, optional_actions, termios_p)) {
+ const std::string msg = "tcsetattr() failed: " + utils::getSystemErrorMessage();
+ LOGE(msg);
+ throw TerminalException(msg);
+ }
+}
+
+std::string ttyname_r(const int fd)
+{
+ char ptsName[PATH_MAX];
+ int rc = ::ttyname_r(fd, ptsName, PATH_MAX);
+
+ if (rc != 0) {
+ const std::string msg = "ttyname_r() failed: " + utils::getSystemErrorMessage(rc);
+ LOGE(msg);
+ throw TerminalException(msg);
+ }
+
+ return ptsName;
+}
+
+} // namespace
+
+
+/*
+ * This function has to be safe in regard to signal(7)
+ */
+int nullStdFDs()
+{
+ int ret = -1;
+
+ int fd = TEMP_FAILURE_RETRY(::open("/dev/null", O_RDWR | O_CLOEXEC));
+ if (fd == -1) {
+ goto err;
+ }
+
+ if (-1 == TEMP_FAILURE_RETRY(::dup2(fd, STDIN_FILENO))) {
+ goto err_close;
+ }
+
+ if (-1 == TEMP_FAILURE_RETRY(::dup2(fd, STDOUT_FILENO))) {
+ goto err_close;
+ }
+
+ if (-1 == TEMP_FAILURE_RETRY(::dup2(fd, STDERR_FILENO))) {
+ goto err_close;
+ }
+
+ if (-1 == TEMP_FAILURE_RETRY(::close(fd))) {
+ goto err;
+ }
+
+ return 0;
+
+err_close:
+ TEMP_FAILURE_RETRY(::close(fd));
+err:
+ return ret;
+}
+
+std::pair openPty(bool rawMode)
+{
+ int master, slave;
+ std::string ptsName;
+
+ try {
+ lxcpp::openpty(&master, &slave);
+
+ utils::setCloseOnExec(master, true);
+ utils::setNonBlocking(master, true);
+
+ if (rawMode) {
+ struct termios ttyAttr;
+
+ lxcpp::tcgetattr(slave, &ttyAttr);
+ ::cfmakeraw(&ttyAttr);
+ lxcpp::tcsetattr(slave, TCSADRAIN, &ttyAttr);
+ }
+
+ ptsName = lxcpp::ttyname_r(slave);
+
+ } catch(std::exception&) {
+ TEMP_FAILURE_RETRY(::close(master));
+ TEMP_FAILURE_RETRY(::close(slave));
+
+ throw;
+ }
+
+ utils::close(slave);
+ return std::pair(master, ptsName);
+}
+
+
+} // namespace lxcpp
diff --git a/libs/lxcpp/terminal.hpp b/libs/lxcpp/terminal.hpp
new file mode 100644
index 0000000..85ae6e2
--- /dev/null
+++ b/libs/lxcpp/terminal.hpp
@@ -0,0 +1,59 @@
+/*
+ * Copyright (C) 2015 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License version 2.1 as published by the Free Software Foundation.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+/**
+ * @file
+ * @author Lukasz Pawelczyk (l.pawelczyk@samsung.com)
+ * @brief Terminal helpers headers
+ */
+
+#ifndef LXCPP_TERMINAL_HPP
+#define LXCPP_TERMINAL_HPP
+
+
+namespace lxcpp {
+
+
+/**
+ * Nullifies all standard file descriptors (stdin, stdout, stderr)
+ * replacing them with file descriptor to /dev/null. Used to
+ * as a part of a process to detach a process from a control terminal.
+ *
+ * This function has to be safe in regard to signal(7)
+ *
+ * @returns an error code in case of failure.
+ */
+int nullStdFDs();
+
+/**
+ * This function creates a new pair of virtual character devices
+ * using a pseudtoreminal interface. It also configures as much as it
+ * can so the devices are immediately usable.
+ *
+ * @param rawMode Whether to set the terminal in the raw mode (termios(2))
+ *
+ * @returns file descriptor to the master device and the path/name of
+ * the pts slace device.
+ */
+std::pair openPty(bool rawMode);
+
+
+} // namespace lxcpp
+
+
+
+#endif // LXCPP_TERMINAL_HPP
diff --git a/libs/lxcpp/utils.cpp b/libs/lxcpp/utils.cpp
index 41e76b5..685d915 100644
--- a/libs/lxcpp/utils.cpp
+++ b/libs/lxcpp/utils.cpp
@@ -21,16 +21,16 @@
* @brief LXCPP utils implementation
*/
+#ifndef _GNU_SOURCE
+#define _GNU_SOURCE
+#endif
+
#include "lxcpp/exception.hpp"
#include "logger/logger.hpp"
#include "utils/fd-utils.hpp"
#include "utils/exception.hpp"
-#ifndef _GNU_SOURCE
-#define _GNU_SOURCE
-#endif
-
#include
#include
#include
@@ -41,42 +41,6 @@
namespace lxcpp {
-/*
- * This function has to be safe in regard to signal(7)
- */
-int nullStdFDs()
-{
- int ret = -1;
-
- int fd = TEMP_FAILURE_RETRY(open("/dev/null", O_RDWR | O_CLOEXEC));
- if (fd == -1) {
- goto err;
- }
-
- if (-1 == TEMP_FAILURE_RETRY(::dup2(fd, STDIN_FILENO))) {
- goto err_close;
- }
-
- if (-1 == TEMP_FAILURE_RETRY(::dup2(fd, STDOUT_FILENO))) {
- goto err_close;
- }
-
- if (-1 == TEMP_FAILURE_RETRY(::dup2(fd, STDERR_FILENO))) {
- goto err_close;
- }
-
- if (-1 == TEMP_FAILURE_RETRY(::close(fd))) {
- goto err_close;
- }
-
- return 0;
-
-err_close:
- TEMP_FAILURE_RETRY(::close(fd));
-err:
- return ret;
-}
-
void setProcTitle(const std::string &title)
{
std::ifstream f("/proc/self/stat");
diff --git a/libs/lxcpp/utils.hpp b/libs/lxcpp/utils.hpp
index 2a59303..e4c158b 100644
--- a/libs/lxcpp/utils.hpp
+++ b/libs/lxcpp/utils.hpp
@@ -29,16 +29,6 @@
namespace lxcpp {
-/**
- * Nullifies all standard file descriptors (stdin, stdout, stderr)
- * replacing them with file descriptor to /dev/null. Used to
- * as a part of a process to detach a process from a control terminal.
- *
- * This function has to be safe in regard to signal(7)
- *
- * @returns an error code in case of failure.
- */
-int nullStdFDs();
/**
* Changes the tittle of a current process title (e.g. visible in ps tool).
--
2.7.4
From 08a871f9e354e79e755402cd0a97dc6d4501ef47 Mon Sep 17 00:00:00 2001
From: Lukasz Pawelczyk
Date: Fri, 18 Sep 2015 16:26:58 +0200
Subject: [PATCH 10/16] lxcpp: Terminal preparation part 2 (guest)
[Feature] Make use of the created pseudoterminals in the container
[Verification] Build, install, run tests
Changes in this commit:
- PrepGuestTerminal command
- it's main function: setupIOControlTTY()
- some more utils/terminal wrappers for syscalls
- long overdue open(2) wrapper
Change-Id: I235baec044ed82d3376cba3f2e5b4d18f5b1dd71
---
common/utils/fd-utils.cpp | 59 +++++++++++++++++++++++++-
common/utils/fd-utils.hpp | 17 ++++++++
libs/lxcpp/commands/attach.cpp | 8 +---
libs/lxcpp/commands/prep-guest-terminal.cpp | 64 +++++++++++++++++++++++++++++
libs/lxcpp/commands/prep-guest-terminal.hpp | 58 ++++++++++++++++++++++++++
libs/lxcpp/commands/prep-host-terminal.cpp | 3 +-
libs/lxcpp/container-impl.cpp | 34 +++++++++++++++
libs/lxcpp/credentials.cpp | 12 ++++++
libs/lxcpp/credentials.hpp | 4 +-
libs/lxcpp/guard/guard.cpp | 4 ++
libs/lxcpp/guard/main.cpp | 6 +--
libs/lxcpp/process.cpp | 10 +----
libs/lxcpp/terminal.cpp | 32 +++++++++++++++
libs/lxcpp/terminal.hpp | 10 +++++
14 files changed, 299 insertions(+), 22 deletions(-)
create mode 100644 libs/lxcpp/commands/prep-guest-terminal.cpp
create mode 100644 libs/lxcpp/commands/prep-guest-terminal.hpp
diff --git a/common/utils/fd-utils.cpp b/common/utils/fd-utils.cpp
index 3e0db3e..9bd7d29 100644
--- a/common/utils/fd-utils.cpp
+++ b/common/utils/fd-utils.cpp
@@ -22,6 +22,10 @@
* @brief File descriptor utility functions
*/
+#ifndef _GNU_SOURCE
+#define _GNU_SOURCE
+#endif
+
#include "config.hpp"
#include "utils/fd-utils.hpp"
@@ -32,9 +36,11 @@
#include
#include
#include
+#include
#include
#include