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;