summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--plugins/Makefile.am1
-rwxr-xr-xplugins/discovery.py34
-rw-r--r--plugins/network_utils.py83
-rw-r--r--tests/Makefile.am1
-rw-r--r--tests/test_network_utils.py89
5 files changed, 191 insertions, 17 deletions
diff --git a/plugins/Makefile.am b/plugins/Makefile.am
index 3365ae3..7b604b0 100644
--- a/plugins/Makefile.am
+++ b/plugins/Makefile.am
@@ -14,6 +14,7 @@ dist_glusternagiosplugins_PYTHON = \
submit_external_command.py \
brick_status_event_handler.py \
server_utils.py \
+ network_utils.py \
$(NULL)
EXTRA_DIST = \
diff --git a/plugins/discovery.py b/plugins/discovery.py
index 46fee95..b17c81f 100755
--- a/plugins/discovery.py
+++ b/plugins/discovery.py
@@ -21,11 +21,13 @@ import datetime
import os
import shutil
import sys
+import socket
from glusternagios import utils
from glusternagios.glustercli import HostStatus
from config_generator import GlusterNagiosConfManager
import server_utils
+import network_utils
import submit_external_command
from constants import DEFAULT_AUTO_CONFIG_DIR
from constants import NAGIOS_CONFIG_FILE
@@ -432,23 +434,21 @@ def getNagiosAddress(clusterName):
nagiosAddress = autoConfigService['check_command'].split("!")[2]
return nagiosAddress
- (returncode, outputStr, err) = utils.execCmd([utils.hostnameCmdPath.cmd,
- '--fqdn'])
- if returncode == 0:
- default = outputStr[0]
- else:
- (returncode, outputStr, err) = utils.execCmd(
- [utils.hostnameCmdPath.cmd, '-I'])
- if returncode == 0:
- default = outputStr[0]
- if default:
- msg = "Enter Nagios server address [%s]: " % (default.strip())
- else:
- msg = "Enter Nagios server address : "
- ans = raw_input(msg)
- if not ans:
- ans = default
- return ans
+ return getHostAddress()
+
+
+def getHostAddress():
+ fqdn = socket.getfqdn()
+ while True:
+ msg = 'Enter Nagios server address [%s]: ' % fqdn
+ address = raw_input(msg)
+ if not address:
+ address = fqdn
+ validationMsg = network_utils.validateHostAddress(address)
+ if validationMsg:
+ print 'Host address is not valid: %s' % validationMsg
+ else:
+ return address
def getConfirmation(message, default):
diff --git a/plugins/network_utils.py b/plugins/network_utils.py
new file mode 100644
index 0000000..83fecc0
--- /dev/null
+++ b/plugins/network_utils.py
@@ -0,0 +1,83 @@
+#!/usr/bin/python
+# network_utils.py Network utility
+# Copyright (C) 2014 Red Hat Inc
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License
+# as published by the Free Software Foundation; either version 2
+# of the License, or (at your option) any later version.
+#
+# This program 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 General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
+#
+import re
+import socket
+import ethtool
+import logging
+
+
+IPADDR_RE = re.compile(r'\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}')
+DOMAIN_RE = re.compile(
+ flags=re.VERBOSE,
+ pattern=r"""
+ ^
+ [\w\.\-\_]+
+ \w+
+ $
+ """
+)
+
+
+def getNonLoopbackAddresses():
+ devices = ethtool.get_active_devices()
+ iplist = []
+
+ for device in devices:
+ try:
+ flags = ethtool.get_flags(device)
+ if flags and not (flags & ethtool.IFF_LOOPBACK):
+ iplist.append(ethtool.get_ipaddr(device))
+ except IOError as e:
+ logging.error("unable to get ipaddr/flags for %s: %s"
+ % (device, e))
+ return set(iplist)
+
+
+def validateFQDNresolvability(fqdn):
+ try:
+ resolvedAddresses = set(socket.gethostbyname_ex(fqdn)[2])
+ except socket.error:
+ return "%s did not resolve into an IP address" % fqdn
+
+ if not resolvedAddresses.issubset(getNonLoopbackAddresses()):
+ return "The following addreses: '%s' can't be mapped to non " \
+ "loopback devices on this host" % resolvedAddresses
+
+
+def validateHostAddress(address):
+ if not address:
+ return "Please specify host Address"
+
+ if IPADDR_RE.match(address):
+ if not address in getNonLoopbackAddresses():
+ return "Address '%s' can't be mapped to non loopback devices " \
+ "on this host" % address
+ else:
+ return
+
+ if len(address) > 1000:
+ return "FQDN has invalid length"
+
+ components = address.split('.', 1)
+ if len(components) < 2:
+ return "Host FQDN name '%s' has no domain suffix" % address
+ else:
+ if not DOMAIN_RE.match(components[1]):
+ return "Host FQDN name '%s' has invalid domain name" % address
+ return validateFQDNresolvability(address)
diff --git a/tests/Makefile.am b/tests/Makefile.am
index 8616007..f2bfc96 100644
--- a/tests/Makefile.am
+++ b/tests/Makefile.am
@@ -23,6 +23,7 @@ test_modules = \
test_notify_ovirt_engine_handler.py \
test_config_generator.py \
test_discovery.py \
+ test_network_utils.py
$(NULL)
dist_nagiosserveraddonstests_DATA = \
diff --git a/tests/test_network_utils.py b/tests/test_network_utils.py
new file mode 100644
index 0000000..f379e0c
--- /dev/null
+++ b/tests/test_network_utils.py
@@ -0,0 +1,89 @@
+#!/usr/bin/python
+# Copyright 2014 Red Hat, Inc.
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License
+# as published by the Free Software Foundation; either version 2
+# of the License, or (at your option) any later version.
+#
+# This program 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 General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
+#
+
+from plugins import network_utils
+from testrunner import PluginsTestCase as TestCaseBase
+
+
+class TestNetworkUtils(TestCaseBase):
+ def mockGetFlags(self, device):
+ if device == 'lo':
+ return 73
+ else:
+ return 4163
+
+ def mockGetDevices(self):
+ return ['lo', 'etho', 'eth1']
+
+ def mockGetIpAddr(self, device):
+ if device == 'lo':
+ return '127.0.0.1'
+ else:
+ return '10.70.42.1'
+
+ def mockGethostbyname_ex(self, host):
+ if host == 'test.host.com':
+ return host, [], ['10.70.42.1']
+ else:
+ return host, [], ['82.94.164.162']
+
+ def setUpMocks(self):
+ network_utils.ethtool.get_active_devices = self.mockGetDevices
+ network_utils.ethtool.get_flags = self.mockGetFlags
+ network_utils.ethtool.get_ipaddr = self.mockGetIpAddr
+ network_utils.socket.gethostbyname_ex = self.mockGethostbyname_ex
+
+ #Methods to test validateHostAddress(address)
+ def testValidateHostAddressWithEmptyAddress(self):
+ self.setUpMocks()
+ validationMsg = network_utils.validateHostAddress(None)
+ self.assertEqual('Please specify host Address', validationMsg)
+
+ def testValidateHostAddressWithLoopBackAddress(self):
+ self.setUpMocks()
+ validationMsg = network_utils.validateHostAddress("127.0.0.1")
+ self.assertEqual("Address '127.0.0.1' can't be mapped to non loopback "
+ "devices on this host", validationMsg)
+
+ def testValidateHostAddressWithValidAddress(self):
+ self.setUpMocks()
+ validationMsg = network_utils.validateHostAddress("10.70.42.1")
+ self.assertEqual(None, validationMsg)
+
+ def testValidateHostAddressWithInvalidFQDN(self):
+ self.setUpMocks()
+ validationMsg = network_utils.validateHostAddress("this-is-"
+ "invalid-fqdn")
+ self.assertEqual("Host FQDN name 'this-is-invalid-fqdn' has no domain "
+ "suffix", validationMsg)
+
+ validationMsg = network_utils.validateHostAddress("this.is."
+ "invalid.fqdn.")
+ self.assertEqual("Host FQDN name 'this.is.invalid.fqdn.' has invalid "
+ "domain name", validationMsg)
+
+ validationMsg = network_utils.validateHostAddress("test.host."
+ "com.notfound")
+ self.assertEqual("The following addreses: 'set(['82.94.164.162'])' "
+ "can't be mapped to non loopback devices on this "
+ "host", validationMsg)
+
+ def testValidateHostAddressWithValidFQDN(self):
+ self.setUpMocks()
+ validationMsg = network_utils.validateHostAddress("test.host.com")
+ self.assertEqual(None, validationMsg)