Merge pull request #6511 from Icinga/feature/apilistener-dynamic-port

ApiListener: Add support for dynamic port handling
This commit is contained in:
Michael Friedrich 2018-08-09 12:09:23 +02:00 committed by GitHub
commit 3cc8bd2fcc
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
7 changed files with 104 additions and 28 deletions

View File

@ -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 <a id="upgrading-to-2-10-path-new-constants"></a>
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 <a id="upgrading-to-2-9"></a>
### Deprecation and Removal Notes <a id="upgrading-to-2-9-deprecation-removal-notes"></a>

View File

@ -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:

View File

@ -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<String, String>& 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<String, String> 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<String, String> Socket::GetClientAddressDetails()
{
boost::mutex::scoped_lock lock(m_SocketMutex);
@ -175,22 +185,32 @@ String Socket::GetClientAddress()
#endif /* _WIN32 */
}
String address;
std::pair<String, String> 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<String, String> Socket::GetPeerAddressDetails()
{
boost::mutex::scoped_lock lock(m_SocketMutex);
@ -215,14 +235,24 @@ String Socket::GetPeerAddress()
#endif /* _WIN32 */
}
String address;
std::pair<String, String> 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));
}

View File

@ -45,7 +45,9 @@ public:
void Close();
std::pair<String, String> GetClientAddressDetails();
String GetClientAddress();
std::pair<String, String> 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<String, String> GetDetailsFromSockaddr(sockaddr *address, socklen_t len);
static String GetHumanReadableAddress(const std::pair<String, String>& socketDetails);
};
class socket_error : virtual public std::exception, virtual public boost::exception { };

View File

@ -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<String, String> 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));
}
}
}

View File

@ -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);

View File

@ -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;