diff options
Diffstat (limited to 'compass-tasks-base/actions/health_check/check_dhcp.py')
-rw-r--r-- | compass-tasks-base/actions/health_check/check_dhcp.py | 184 |
1 files changed, 184 insertions, 0 deletions
diff --git a/compass-tasks-base/actions/health_check/check_dhcp.py b/compass-tasks-base/actions/health_check/check_dhcp.py new file mode 100644 index 0000000..e3bae1e --- /dev/null +++ b/compass-tasks-base/actions/health_check/check_dhcp.py @@ -0,0 +1,184 @@ +# Copyright 2014 Huawei Technologies Co. Ltd +# +# 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. + +"""Health Check module for DHCP service.""" +import commands +import os +import re +import socket +import xmlrpclib + +from compass.actions.health_check import base + + +class DhcpCheck(base.BaseCheck): + """dhcp health check class.""" + + NAME = "DHCP Check" + + def run(self): + """do health check.""" + method_name = "self.check_" + self.os_installer['name'] + "_dhcp()" + return eval(method_name) + + def check_cobbler_dhcp(self): + """Checks if Cobbler has taken over DHCP service.""" + + try: + remote = xmlrpclib.Server( + self.os_installer['cobbler_url'], + allow_none=True) + credentials = self.os_installer['credentials'] + remote.login( + credentials['username'], credentials['password']) + except Exception: + self._set_status( + 0, + "[%s]Error: Cannot login to Cobbler with " + "the tokens provided in the config file" % self.NAME) + return (self.code, self.messages) + + cobbler_settings = remote.get_settings() + if cobbler_settings['manage_dhcp'] == 0: + self.messages.append( + "[%s]Info: DHCP service is " + "not managed by Compass" % self.NAME) + self.code = 0 + return (self.code, self.messages) + + self.check_cobbler_dhcp_template() + print "[Done]" + self.check_dhcp_service() + self.check_dhcp_netmask() + print "[Done]" + if self.code == 1: + self.messages.append( + "[%s]Info: DHCP health check has completed. " + "No problems found, all systems go." % self.NAME) + + return (self.code, self.messages) + + def check_cobbler_dhcp_template(self): + """Validates Cobbler's DHCP template file.""" + print "Checking DHCP template......", + if os.path.exists("/etc/cobbler/dhcp.template"): + var_map = { + "match_next_server": False, + "match_subnet": False, + "match_filename": False, + "match_range": False, + } + + ip_regex = re.compile(r'^\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}$') + + dhcp_template = open("/etc/cobbler/dhcp.template") + for line in dhcp_template.readlines(): + if line.find("next_server") != -1: + elmlist = line.split(" ") + for elm in elmlist: + if ";" in elm: + elm = elm[:-2] + + if "$next_server" in elm or ip_regex.match(elm): + var_map["match_next_server"] = True + + elif line.find("subnet") != -1 and line.find("{") != -1: + elmlist = line.split(" ") + for elm in elmlist: + if ip_regex.match(elm): + if elm[-1] == "0" and "255" not in elm: + var_map["match_subnet"] = True + elif elm[-1] != "0": + self.messages.append( + "[%s]Error: Subnet should be set " + "in the form of 192.168.0.0 in" + "/etc/cobbler/dhcp.template" % self.NAME) + + elif line.find("filename") != -1: + var_map["match_filename"] = True + elif line.find("range dynamic-bootp") != -1: + elmlist = line.split(" ") + ip_count = 0 + for elm in elmlist: + if ";" in elm and "\n" in elm: + elm = elm[:-2] + + if ip_regex.match(elm): + ip_count += 1 + + if ip_count != 2: + self.messages.append( + "[%s]Error: DHCP range should be set " + "between two IP addresses in " + "/etc/cobbler/dhcp.template" % self.NAME) + else: + var_map["match_range"] = True + + dhcp_template.close() + fails = [] + for var in var_map.keys(): + if var_map[var] is False: + fails.append(var) + + if len(fails) != 0: + self._set_status( + 0, + "[%s]Info: DHCP template file " + "failed components: %s" % ( + self.NAME, ' '.join(failed for failed in fails))) + + else: + self._set_status( + 0, + "[%s]Error: DHCP template file doesn't exist, " + "health check failed." % self.NAME) + + return True + + def check_dhcp_netmask(self): + with open('/etc/dhcp/dhcpd.conf') as conf_reader: + lines = conf_reader.readlines() + for line in lines: + if re.search('^subnet', line): + elm_list = line.split(' ') + break + subnet_ip = elm_list[1] + netmask = elm_list[-2] + subnet_ip_elm = subnet_ip.split('.') + netmask_elm = netmask.split('.') + for index, digit in enumerate(subnet_ip_elm): + if int(digit) & int(netmask_elm[index]) != int(digit): + self._set_status( + 0, + "[%s]Info: DHCP subnet IP and " + "netmask do not match" % self.NAME) + break + return True + + def check_dhcp_service(self): + """Checks if DHCP is running on port 67.""" + print "Checking DHCP service......", + if not commands.getoutput('pgrep dhcp'): + self._set_status( + 0, + "[%s]Error: dhcp service does not " + "seem to be running" % self.NAME) + + if socket.getservbyport(67) != 'bootps': + self._set_status( + 0, + "[%s]Error: bootps is not listening " + "on port 67" % self.NAME) + + return True |