diff --git a/doc/16-upgrading-icinga-2.md b/doc/16-upgrading-icinga-2.md index b44fbf51f..cce8cd916 100644 --- a/doc/16-upgrading-icinga-2.md +++ b/doc/16-upgrading-icinga-2.md @@ -37,6 +37,12 @@ has been removed and this setting has no effect. > > This is important if you rely on the sysconfig configuration in your own scripts. +### New Constants + +New [Icinga constants](17-language-reference.md#icinga-constants) have been added in this release. + +* `ApiBindHost` and `ApiBindPort` to allow overriding the default ApiListener values. This will be used for an Icinga addon only. + ## Upgrading to v2.9 ### Deprecation and Removal Notes diff --git a/doc/17-language-reference.md b/doc/17-language-reference.md index 1f50f610c..de94ba4e8 100644 --- a/doc/17-language-reference.md +++ b/doc/17-language-reference.md @@ -409,8 +409,10 @@ Vars |**Read-write.** Contains a dictionary with global custom at NodeName |**Read-write.** Contains the cluster node name. Set to the local hostname by default. RunAsUser |**Read-write.** Defines the user the Icinga 2 daemon is running as. Set in the Icinga 2 sysconfig. RunAsGroup |**Read-write.** Defines the group the Icinga 2 daemon is running as. Set in the Icinga 2 sysconfig. -MaxConcurrentChecks |**Read-write**. The number of max checks run simultaneously. Defaults to `512`. -Environment |**Read-write**. The name of the Icinga environment. Included in the SNI host name when making outbound connections. Defaults to `production`. +MaxConcurrentChecks |**Read-write.** The number of max checks run simultaneously. Defaults to `512`. +Environment |**Read-write.** The name of the Icinga environment. Included in the SNI host name when making outbound connections. Defaults to `production`. +ApiBindHost |**Read-write.** Overrides the default value for the ApiListener `bind_host` attribute. Not set by default. +ApiBindPort |**Read-write.** Overrides the default value for the ApiListener `bind_port` attribute. Not set by default. Application runtime details: diff --git a/lib/base/socket.cpp b/lib/base/socket.cpp index 97946f5ee..17d35778b 100644 --- a/lib/base/socket.cpp +++ b/lib/base/socket.cpp @@ -114,9 +114,21 @@ int Socket::GetError() const /** * Formats a sockaddr in a human-readable way. * - * @returns A String describing the sockaddr. + * @returns A pair of host and service. */ -String Socket::GetAddressFromSockaddr(sockaddr *address, socklen_t len) +String Socket::GetHumanReadableAddress(const std::pair& socketDetails) +{ + std::ostringstream s; + s << "[" << socketDetails.first << "]:" << socketDetails.second; + return s.str(); +} + +/** + * Returns host and service as pair. + * + * @returns A pair with host and service. + */ +std::pair Socket::GetDetailsFromSockaddr(sockaddr *address, socklen_t len) { char host[NI_MAXHOST]; char service[NI_MAXSERV]; @@ -140,17 +152,15 @@ String Socket::GetAddressFromSockaddr(sockaddr *address, socklen_t len) #endif /* _WIN32 */ } - std::ostringstream s; - s << "[" << host << "]:" << service; - return s.str(); + return std::make_pair(host, service); } /** - * Returns a String describing the local address of the socket. + * Returns a pair describing the local host and service of the socket. * - * @returns A String describing the local address. + * @returns A pair describing the local host and service. */ -String Socket::GetClientAddress() +std::pair Socket::GetClientAddressDetails() { boost::mutex::scoped_lock lock(m_SocketMutex); @@ -175,22 +185,32 @@ String Socket::GetClientAddress() #endif /* _WIN32 */ } - String address; + std::pair details; try { - address = GetAddressFromSockaddr((sockaddr *)&sin, len); + details = GetDetailsFromSockaddr((sockaddr *)&sin, len); } catch (const std::exception&) { /* already logged */ } - return address; + return details; } /** - * Returns a String describing the peer address of the socket. + * Returns a String describing the local address of the socket. * - * @returns A String describing the peer address. + * @returns A String describing the local address. */ -String Socket::GetPeerAddress() +String Socket::GetClientAddress() +{ + return GetHumanReadableAddress(GetClientAddressDetails()); +} + +/** + * Returns a pair describing the peer host and service of the socket. + * + * @returns A pair describing the peer host and service. + */ +std::pair Socket::GetPeerAddressDetails() { boost::mutex::scoped_lock lock(m_SocketMutex); @@ -215,14 +235,24 @@ String Socket::GetPeerAddress() #endif /* _WIN32 */ } - String address; + std::pair details; try { - address = GetAddressFromSockaddr((sockaddr *)&sin, len); + details = GetDetailsFromSockaddr((sockaddr *)&sin, len); } catch (const std::exception&) { /* already logged */ } - return address; + return details; +} + +/** + * Returns a String describing the peer address of the socket. + * + * @returns A String describing the peer address. + */ +String Socket::GetPeerAddress() +{ + return GetHumanReadableAddress(GetPeerAddressDetails()); } /** @@ -415,4 +445,3 @@ void Socket::SocketPair(SOCKET s[2]) << boost::errinfo_api_function("socketpair") << boost::errinfo_errno(errno)); } - diff --git a/lib/base/socket.hpp b/lib/base/socket.hpp index 89147c57d..7de915bbe 100644 --- a/lib/base/socket.hpp +++ b/lib/base/socket.hpp @@ -45,7 +45,9 @@ public: void Close(); + std::pair GetClientAddressDetails(); String GetClientAddress(); + std::pair GetPeerAddressDetails(); String GetPeerAddress(); size_t Read(void *buffer, size_t size); @@ -70,7 +72,8 @@ protected: private: SOCKET m_FD{INVALID_SOCKET}; /**< The socket descriptor. */ - static String GetAddressFromSockaddr(sockaddr *address, socklen_t len); + static std::pair GetDetailsFromSockaddr(sockaddr *address, socklen_t len); + static String GetHumanReadableAddress(const std::pair& socketDetails); }; class socket_error : virtual public std::exception, virtual public boost::exception { }; diff --git a/lib/remote/apilistener.cpp b/lib/remote/apilistener.cpp index c7ba834b4..bcfa29680 100644 --- a/lib/remote/apilistener.cpp +++ b/lib/remote/apilistener.cpp @@ -264,8 +264,12 @@ void ApiListener::Stop(bool runtimeDeleted) Log(LogInformation, "ApiListener") << "'" << GetName() << "' stopped."; - boost::mutex::scoped_lock lock(m_LogLock); - CloseLogFile(); + { + boost::mutex::scoped_lock lock(m_LogLock); + CloseLogFile(); + } + + RemoveStatusFile(); } ApiListener::Ptr ApiListener::GetInstance() @@ -318,9 +322,6 @@ bool ApiListener::AddListener(const String& node, const String& service) return false; } - Log(LogInformation, "ApiListener") - << "Adding new listener on port '" << service << "'"; - TcpSocket::Ptr server = new TcpSocket(); try { @@ -331,11 +332,16 @@ bool ApiListener::AddListener(const String& node, const String& service) return false; } + Log(LogInformation, "ApiListener") + << "Started new listener on '" << server->GetClientAddress() << "'"; + std::thread thread(std::bind(&ApiListener::ListenerThreadProc, this, server)); thread.detach(); m_Servers.insert(server); + UpdateStatusFile(server); + return true; } @@ -1469,3 +1475,28 @@ String ApiListener::GetFromZoneName(const Zone::Ptr& fromZone) return fromZoneName; } + +void ApiListener::UpdateStatusFile(TcpSocket::Ptr socket) +{ + String path = Application::GetConst("CacheDir") + "/api-state.json"; + std::pair details = socket->GetClientAddressDetails(); + + Utility::SaveJsonFile(path, 0644, new Dictionary({ + {"host", details.first}, + {"port", details.second} + })); +} + +void ApiListener::RemoveStatusFile() +{ + String path = Application::GetConst("CacheDir") + "/api-state.json"; + + if (Utility::PathExists(path)) { + if (unlink(path.CStr()) < 0 && errno != ENOENT) { + BOOST_THROW_EXCEPTION(posix_error() + << boost::errinfo_api_function("unlink") + << boost::errinfo_errno(errno) + << boost::errinfo_file_name(path)); + } + } +} diff --git a/lib/remote/apilistener.hpp b/lib/remote/apilistener.hpp index b3894992a..27d236eaa 100644 --- a/lib/remote/apilistener.hpp +++ b/lib/remote/apilistener.hpp @@ -163,6 +163,9 @@ private: static void CopyCertificateFile(const String& oldCertPath, const String& newCertPath); + void UpdateStatusFile(TcpSocket::Ptr socket); + void RemoveStatusFile(); + /* filesync */ static ConfigDirInformation LoadConfigDir(const String& dir); static Dictionary::Ptr MergeConfigUpdate(const ConfigDirInformation& config); diff --git a/lib/remote/apilistener.ti b/lib/remote/apilistener.ti index e04fa0185..04e483270 100644 --- a/lib/remote/apilistener.ti +++ b/lib/remote/apilistener.ti @@ -41,9 +41,11 @@ class ApiListener : ConfigObject default {{{ return "TLSv1"; }}} }; - [config] String bind_host; + [config] String bind_host { + default {{{ return Application::GetConst("ApiBindHost"); }}} + }; [config] String bind_port { - default {{{ return "5665"; }}} + default {{{ return Application::GetConst("ApiBindPort", "5665"); }}} }; [config] bool accept_config;