summaryrefslogtreecommitdiffstats
path: root/compass-tasks-base/actions/health_check
diff options
context:
space:
mode:
authorHarry Huang <huangxiangyu5@huawei.com>2017-11-17 14:53:44 +0800
committerHarry Huang <huangxiangyu5@huawei.com>2017-12-21 16:36:30 +0800
commit8646b8d62cf4ca7b6bccae537a0c9e72ba45eab3 (patch)
tree73a9a983e0dd1423e9df928a78a5023a09d5a7f9 /compass-tasks-base/actions/health_check
parent6234176ae292a75dcda5520324cb7857d6105988 (diff)
Merge compass-tasks-osa and compass-tasks-k8s
JIRA: COMPASS-568 rename compass-tasks to compass-tasks-base. add both osa and k8s support in compass-tasks Change-Id: I438f5b17e509d4cb751ced0ffe640ec70899882f Signed-off-by: Harry Huang <huangxiangyu5@huawei.com>
Diffstat (limited to 'compass-tasks-base/actions/health_check')
-rw-r--r--compass-tasks-base/actions/health_check/__init__.py13
-rw-r--r--compass-tasks-base/actions/health_check/base.py57
-rw-r--r--compass-tasks-base/actions/health_check/check.py96
-rw-r--r--compass-tasks-base/actions/health_check/check_apache.py89
-rw-r--r--compass-tasks-base/actions/health_check/check_celery.py115
-rw-r--r--compass-tasks-base/actions/health_check/check_dhcp.py184
-rw-r--r--compass-tasks-base/actions/health_check/check_dns.py139
-rw-r--r--compass-tasks-base/actions/health_check/check_hds.py97
-rw-r--r--compass-tasks-base/actions/health_check/check_misc.py219
-rw-r--r--compass-tasks-base/actions/health_check/check_os_installer.py151
-rw-r--r--compass-tasks-base/actions/health_check/check_package_installer.py68
-rw-r--r--compass-tasks-base/actions/health_check/check_squid.py128
-rw-r--r--compass-tasks-base/actions/health_check/check_tftp.py96
-rw-r--r--compass-tasks-base/actions/health_check/utils.py114
14 files changed, 1566 insertions, 0 deletions
diff --git a/compass-tasks-base/actions/health_check/__init__.py b/compass-tasks-base/actions/health_check/__init__.py
new file mode 100644
index 0000000..4ee55a4
--- /dev/null
+++ b/compass-tasks-base/actions/health_check/__init__.py
@@ -0,0 +1,13 @@
+# 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.
diff --git a/compass-tasks-base/actions/health_check/base.py b/compass-tasks-base/actions/health_check/base.py
new file mode 100644
index 0000000..22b6fae
--- /dev/null
+++ b/compass-tasks-base/actions/health_check/base.py
@@ -0,0 +1,57 @@
+# 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.
+
+"""Base class for Compass Health Check."""
+from compass.actions.health_check import utils as health_check_utils
+from compass.db.api import adapter as adapter_api
+from compass.utils import setting_wrapper as setting
+
+
+class BaseCheck(object):
+ """health check base class."""
+
+ def __init__(self):
+ self.config = setting
+ self.code = 1
+ self.messages = []
+ self.dist, self.version, self.release = health_check_utils.get_dist()
+ adapter_api.load_adapters_internal()
+ self.os_installer = self._get_os_installer()
+ self.package_installer = self._get_package_installer()
+
+ def _get_os_installer(self):
+ installer = adapter_api.OS_INSTALLERS.values()[0]
+ os_installer = {}
+ os_installer['name'] = health_check_utils.strip_name(
+ installer['name'])
+ os_installer.update(installer['settings'])
+ return os_installer
+
+ def _get_package_installer(self):
+ package_installer = {}
+ installer = adapter_api.PACKAGE_INSTALLERS.values()[0]
+ package_installer = {}
+ package_installer['name'] = health_check_utils.strip_name(
+ installer['name'])
+ package_installer.update(installer['settings'])
+ return package_installer
+
+ def _set_status(self, code, message):
+ """set status."""
+ self.code = code
+ self.messages.append(message)
+
+ def get_status(self):
+ """get status."""
+ return (self.code, self.messages)
diff --git a/compass-tasks-base/actions/health_check/check.py b/compass-tasks-base/actions/health_check/check.py
new file mode 100644
index 0000000..c1adbc6
--- /dev/null
+++ b/compass-tasks-base/actions/health_check/check.py
@@ -0,0 +1,96 @@
+# 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.
+
+"""Main Entry Point of Compass Health Check."""
+from compass.actions.health_check import base
+from compass.actions.health_check import check_apache
+from compass.actions.health_check import check_celery
+from compass.actions.health_check import check_dhcp
+from compass.actions.health_check import check_dns
+from compass.actions.health_check import check_hds
+from compass.actions.health_check import check_misc
+from compass.actions.health_check import check_os_installer
+from compass.actions.health_check import check_package_installer
+from compass.actions.health_check import check_squid
+from compass.actions.health_check import check_tftp
+
+
+class BootCheck(base.BaseCheck):
+ """health check for all components."""
+
+ def run(self):
+ """do health check."""
+ status = {}
+ status['apache'] = self._check_apache()
+ status['celery'] = self._check_celery()
+ status['dhcp'] = self._check_dhcp()
+ status['dns'] = self._check_dns()
+ status['hds'] = self._check_hds()
+ status['os_installer'] = self._check_os_installer()
+ status['package_installer'] = self._check_package_installer()
+ status['squid'] = self._check_squid()
+ status['tftp'] = self._check_tftp()
+ status['other'] = self._check_misc()
+
+ return status
+
+ def _check_apache(self):
+ """do apache health check."""
+ checker = check_apache.ApacheCheck()
+ return checker.run()
+
+ def _check_celery(self):
+ """do celery health check."""
+ checker = check_celery.CeleryCheck()
+ return checker.run()
+
+ def _check_dhcp(self):
+ """do dhcp health check."""
+ checker = check_dhcp.DhcpCheck()
+ return checker.run()
+
+ def _check_dns(self):
+ """do dns health check."""
+ checker = check_dns.DnsCheck()
+ return checker.run()
+
+ def _check_hds(self):
+ """do hds health check."""
+ checker = check_hds.HdsCheck()
+ return checker.run()
+
+ def _check_os_installer(self):
+ """do os installer health check."""
+ checker = check_os_installer.OsInstallerCheck()
+ return checker.run()
+
+ def _check_package_installer(self):
+ """do package installer health check."""
+ checker = check_package_installer.PackageInstallerCheck()
+ return checker.run()
+
+ def _check_squid(self):
+ """do squid health check."""
+ checker = check_squid.SquidCheck()
+ return checker.run()
+
+ def _check_tftp(self):
+ """do tftp health check."""
+ checker = check_tftp.TftpCheck()
+ return checker.run()
+
+ def _check_misc(self):
+ """do misc health check."""
+ checker = check_misc.MiscCheck()
+ return checker.run()
diff --git a/compass-tasks-base/actions/health_check/check_apache.py b/compass-tasks-base/actions/health_check/check_apache.py
new file mode 100644
index 0000000..294d6f9
--- /dev/null
+++ b/compass-tasks-base/actions/health_check/check_apache.py
@@ -0,0 +1,89 @@
+# 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 Apache service."""
+
+import socket
+import urllib2
+
+from compass.actions.health_check import base
+from compass.actions.health_check import utils as health_check_utils
+
+
+class ApacheCheck(base.BaseCheck):
+ """apache server health check class."""
+ NAME = "Apache Check"
+
+ def run(self):
+ """do the healthcheck."""
+ if self.dist in ("centos", "redhat", "fedora", "scientific linux"):
+ apache_service = 'httpd'
+ else:
+ apache_service = 'apache2'
+ self.check_apache_conf(apache_service)
+ print "[Done]"
+ self.check_apache_running(apache_service)
+ print "[Done]"
+ if self.code == 1:
+ self.messages.append(
+ "[%s]Info: Apache health check has completed. "
+ "No problems found, all systems go." % self.NAME)
+ return (self.code, self.messages)
+
+ def check_apache_conf(self, apache_service):
+ """Validates if Apache settings.
+
+ :param apache_service : service type of apache, os dependent.
+ e.g. httpd or apache2
+ :type apache_service : string
+
+ """
+ print "Checking Apache Config......",
+ conf_err_msg = health_check_utils.check_path(
+ self.NAME,
+ "/etc/%s/conf.d/ods-server.conf" % apache_service)
+ if not conf_err_msg == "":
+ self._set_status(0, conf_err_msg)
+
+ wsgi_err_msg = health_check_utils.check_path(
+ self.NAME,
+ '/var/www/compass/compass.wsgi')
+ if not wsgi_err_msg == "":
+ self._set_status(0, wsgi_err_msg)
+
+ return True
+
+ def check_apache_running(self, apache_service):
+ """Checks if Apache service is running on port 80."""
+
+ print "Checking Apache service......",
+ serv_err_msg = health_check_utils.check_service_running(self.NAME,
+ apache_service)
+ if not serv_err_msg == "":
+ self._set_status(0, serv_err_msg)
+ if 'http' != socket.getservbyport(80):
+ self._set_status(
+ 0,
+ "[%s]Error: Apache is not listening on port 80."
+ % self.NAME)
+ try:
+ html = urllib2.urlopen('http://localhost')
+ html.geturl()
+ except Exception:
+ self._set_status(
+ 0,
+ "[%s]Error: Apache is not listening on port 80."
+ % self.NAME)
+
+ return True
diff --git a/compass-tasks-base/actions/health_check/check_celery.py b/compass-tasks-base/actions/health_check/check_celery.py
new file mode 100644
index 0000000..2d8d27c
--- /dev/null
+++ b/compass-tasks-base/actions/health_check/check_celery.py
@@ -0,0 +1,115 @@
+# 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 Celery."""
+import commands
+import os
+
+from celery.task.control import inspect
+
+from compass.actions.health_check import base
+from compass.actions.health_check import utils as health_check_utils
+
+
+class CeleryCheck(base.BaseCheck):
+ """celery health check class."""
+ NAME = "Celery Check."
+
+ def run(self):
+ """do health check."""
+ self.check_compass_celery_setting()
+ print "[Done]"
+ self.check_celery_backend()
+ print "[Done]"
+ if self.code == 1:
+ self.messages.append("[%s]Info: Celery health check "
+ "has completed. No problems found, "
+ "all systems go." % self.NAME)
+ return (self.code, self.messages)
+
+ def check_compass_celery_setting(self):
+ """Validates Celery settings."""
+
+ print "Checking Celery setting......",
+ setting_map = {
+ 'logfile': 'CELERY_LOGFILE',
+ 'configdir': 'CELERYCONFIG_DIR',
+ 'configfile': 'CELERYCONFIG_FILE',
+ }
+ unset = []
+ res = health_check_utils.validate_setting('Celery',
+ self.config,
+ 'CELERY_LOGFILE')
+ if res is False:
+ unset.append(setting_map["logfile"])
+ self._set_status(0, res)
+
+ res = health_check_utils.validate_setting('Celery',
+ self.config,
+ 'CELERYCONFIG_DIR')
+ if res is False:
+ unset.append(setting_map["configdir"])
+ self._set_status(0, res)
+
+ res = health_check_utils.validate_setting('Celery',
+ self.config,
+ 'CELERYCONFIG_FILE')
+ if res is False:
+ unset.append(setting_map["configdir"])
+ self._set_status(0, res)
+
+ if len(unset) != 0:
+ self._set_status(0,
+ "[%s]Error: Unset celery settings: %s"
+ " in /etc/compass/setting"
+ % (self.NAME, ', '.join(item for item in unset)))
+ return True
+
+ def check_celery_backend(self):
+ """Checks if Celery backend is running and configured properly."""
+
+ print "Checking Celery Backend......",
+ if 'celery worker' not in commands.getoutput('ps -ef'):
+ self._set_status(0, "[%s]Error: celery is not running" % self.NAME)
+ return True
+
+ if not os.path.exists('/etc/compass/celeryconfig'):
+ self._set_status(
+ 0,
+ "[%s]Error: No celery config file found for Compass"
+ % self.NAME)
+ return True
+
+ try:
+ insp = inspect()
+ celery_stats = inspect.stats(insp)
+ if not celery_stats:
+ self._set_status(
+ 0,
+ "[%s]Error: No running Celery workers were found."
+ % self.NAME)
+ except IOError as error:
+ self._set_status(
+ 0,
+ "[%s]Error: Failed to connect to the backend: %s"
+ % (self.NAME, str(error)))
+ from errno import errorcode
+ if (
+ len(error.args) > 0 and
+ errorcode.get(error.args[0]) == 'ECONNREFUSED'
+ ):
+ self.messages.append(
+ "[%s]Error: RabbitMQ server isn't running"
+ % self.NAME)
+ return True
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
diff --git a/compass-tasks-base/actions/health_check/check_dns.py b/compass-tasks-base/actions/health_check/check_dns.py
new file mode 100644
index 0000000..843d7e2
--- /dev/null
+++ b/compass-tasks-base/actions/health_check/check_dns.py
@@ -0,0 +1,139 @@
+# 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 DNS service."""
+
+import commands
+import os
+import socket
+import xmlrpclib
+
+from compass.actions.health_check import base
+
+
+class DnsCheck(base.BaseCheck):
+ """dns health check class."""
+ NAME = "DNS Check"
+
+ def run(self):
+ """do health check."""
+ method_name = "self.check_" + self.os_installer['name'] + "_dns()"
+ return eval(method_name)
+
+ def check_cobbler_dns(self):
+ """Checks if Cobbler has taken over DNS 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_dns'] == 0:
+ self.messages.append('[DNS]Info: DNS is not managed by Compass')
+ return (0, self.messages)
+ self.check_cobbler_dns_template()
+ print "[Done]"
+ self.check_dns_service()
+ print "[Done]"
+ if self.code == 1:
+ self.messages.append(
+ "[%s]Info: DNS health check has complated. "
+ "No problems found, all systems go." % self.NAME)
+ return (self.code, self.messages)
+
+ def check_cobbler_dns_template(self):
+ """Validates Cobbler's DNS template file."""
+
+ print "Checking DNS template......",
+ if os.path.exists("/etc/cobbler/named.template"):
+ var_map = {
+ "match_port": False,
+ "match_allow_query": False,
+ }
+ named_template = open("/etc/cobbler/named.template")
+ host_ip = socket.gethostbyname(socket.gethostname())
+ missing_query = []
+ for line in named_template.readlines():
+ if "listen-on port 53" in line and host_ip in line:
+ var_map["match_port"] = True
+
+ if "allow-query" in line:
+ for subnet in ["127.0.0.0/8"]:
+ if subnet not in line:
+ missing_query.append(subnet)
+
+ named_template.close()
+
+ if var_map["match_port"] is False:
+ self.messages.append(
+ "[%s]Error: named service port "
+ "and/or IP is misconfigured in "
+ "/etc/cobbler/named.template" % self.NAME)
+
+ if len(missing_query) != 0:
+ self.messages.append(
+ "[%s]Error: Missing allow_query values in "
+ "/etc/cobbler/named.template:%s" % (
+ self.NAME,
+ ', '.join(subnet for subnet in missing_query)))
+ else:
+ var_map["match_allow_query"] = True
+
+ 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: DNS template failed components: "
+ "%s" % (
+ self.NAME,
+ ' '.join(failed for failed in fails)))
+
+ else:
+ self._set_status(
+ 0,
+ "[%s]Error: named template file doesn't exist, "
+ "health check failed." % self.NAME)
+
+ return True
+
+ def check_dns_service(self):
+ """Checks if DNS is running on port 53."""
+
+ print "Checking DNS service......",
+ if 'named' not in commands.getoutput('ps -ef'):
+ self._set_status(
+ 0,
+ "[%s]Error: named service does not seem to be "
+ "running" % self.NAME)
+
+ if socket.getservbyport(53) != 'domain':
+ self._set_status(
+ 0,
+ "[%s]Error: domain service is not listening on port "
+ "53" % self.NAME)
+
+ return None
diff --git a/compass-tasks-base/actions/health_check/check_hds.py b/compass-tasks-base/actions/health_check/check_hds.py
new file mode 100644
index 0000000..d176f1f
--- /dev/null
+++ b/compass-tasks-base/actions/health_check/check_hds.py
@@ -0,0 +1,97 @@
+# 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 Hardware Discovery."""
+import logging
+
+from compass.actions.health_check import base
+from compass.actions.health_check import utils as health_check_utils
+
+
+class HdsCheck(base.BaseCheck):
+ """hds health check class."""
+ NAME = "HDS Check"
+
+ def run(self):
+ """do health check."""
+ if self.dist in ("centos", "redhat", "fedora", "scientific linux"):
+ pkg_type = "yum"
+ else:
+ pkg_type = "apt"
+
+ try:
+ pkg_module = __import__(pkg_type)
+ except Exception:
+ self._set_status(
+ 0, "[%s]Error: No module named %s please install it first."
+ % (self.NAME, pkg_type)
+ )
+ return (self.code, self.messages)
+
+ logging.info('import %s: %s', pkg_type, pkg_module)
+ method_name = 'self.check_' + pkg_type + '_snmp(pkg_module)'
+ eval(method_name)
+ print "[Done]"
+ self.check_snmp_mibs()
+ print "[Done]"
+ if self.code == 1:
+ self.messages.append("[%s]Info: hds health check has complated. "
+ "No problems found, all systems go."
+ % self.NAME)
+
+ return (self.code, self.messages)
+
+ def check_yum_snmp(self, pkg_module):
+ """Check if SNMP yum dependencies are installed
+
+ :param pkg_module : python yum library
+ :type pkg_module : python module
+
+ """
+ print "Checking SNMP Packages......",
+ yum_base = pkg_module.YumBase()
+ uninstalled = []
+ for package in ['net-snmp-utils', 'net-snmp', 'net-snmp-python']:
+ if len(yum_base.rpmdb.searchNevra(name=package)) == 0:
+ self.messages.append("[%s]Error: %s package is required "
+ "for HDS" % (self.NAME, package))
+ uninstalled.append(package)
+
+ if len(uninstalled) != 0:
+ self._set_status(0, "[%s]Info: Uninstalled packages: %s"
+ % (self.NAME,
+ ', '.join(item for item in uninstalled)))
+
+ return True
+
+ def check_apt_snmp(self, pkg_module):
+ """do apt health check."""
+ return None
+
+ def check_snmp_mibs(self):
+ """Checks if SNMP MIB files are properly placed."""
+
+ print "Checking SNMP MIBs......",
+ conf_err_msg = health_check_utils.check_path(self.NAME,
+ '/etc/snmp/snmp.conf')
+ if not conf_err_msg == "":
+ self._set_status(0, conf_err_msg)
+
+ mibs_err_msg = health_check_utils.check_path(
+ self.NAME,
+ '/usr/local/share/snmp/mibs')
+ if not mibs_err_msg == "":
+ self._set_status(0, mibs_err_msg)
+
+ return True
diff --git a/compass-tasks-base/actions/health_check/check_misc.py b/compass-tasks-base/actions/health_check/check_misc.py
new file mode 100644
index 0000000..b8beb1b
--- /dev/null
+++ b/compass-tasks-base/actions/health_check/check_misc.py
@@ -0,0 +1,219 @@
+# 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.
+
+"""Miscellaneous Health Check for Compass."""
+import logging
+
+from compass.actions.health_check import base
+from compass.actions.health_check import utils as health_check_utils
+
+
+class MiscCheck(base.BaseCheck):
+ """health check for misc."""
+ NAME = "Miscellaneous Check"
+
+ MISC_MAPPING = {
+ "yum": "rsyslog ntp iproute openssh-clients python git wget "
+ "python-setuptools "
+ "amqp mod_wsgi httpd squid "
+ "dhcp bind rsync yum-utils xinetd tftp-server gcc "
+ "net-snmp-utils net-snmp".split(" "),
+ "pip": "netaddr flask flask_script flask_restful amqplib "
+ "flask_sqlalchemy paramiko mock celery six discover daemon "
+ "unittest2 chef".split(" "),
+ "disable": "iptables ip6tables".split(" "),
+ "enable": "httpd squid xinetd dhcpd named sshd rsyslog cobblerd "
+ "ntpd compass-celeryd compass-progress-updated".split(" "),
+ }
+
+ def run(self):
+ """do health check."""
+ self.check_linux_dependencies()
+ print "[Done]"
+ self.check_pip_dependencies()
+ print "[Done]"
+ self.check_ntp()
+ print "[Done]"
+ self.check_rsyslogd()
+ print "[Done]"
+ self.check_chkconfig()
+ print "[Done]"
+ self.check_selinux()
+ print "[Done]"
+
+ if self.code == 1:
+ self.messages.append(
+ "[%s]Info: Miscellaneous check has completed "
+ "No problems found, all systems go." % self.NAME)
+ return (self.code, self.messages)
+
+ def check_linux_dependencies(self):
+ """Checks if dependencies are installed."""
+ print "Checking Linux dependencies....",
+ if self.dist in ("centos", "redhat", "fedora", "scientific linux"):
+ pkg_type = "yum"
+ else:
+ pkg_type = "apt"
+
+ try:
+ pkg_module = __import__(pkg_type)
+ except Exception:
+ self._set_status(
+ 0,
+ "[%s]Error: No module named %s, "
+ "please install it first." % (self.NAME, pkg_type))
+ return True
+
+ logging.info('import %s: %s', pkg_type, pkg_module)
+ method_name = 'self.check_' + pkg_type + '_dependencies(pkg_module)'
+ eval(method_name)
+
+ def check_yum_dependencies(self, pkg_module):
+ """Checks if yum dependencies are installed.
+
+ :param pkg_module : python yum library
+ :type pkg_module : python module
+
+ """
+ print "Checking Yum dependencies......",
+ yum_base = pkg_module.YumBase()
+ uninstalled = []
+ for package in self.MISC_MAPPING["yum"]:
+ if len(yum_base.rpmdb.searchNevra(name=package)) == 0:
+ self._set_status(
+ 0,
+ "[%s]Error: %s package is required"
+ % (self.NAME, package))
+ uninstalled.append(package)
+
+ if len(uninstalled) != 0:
+ self._set_status(
+ 0,
+ "[%s]Info: Uninstalled yum packages: %s"
+ % (self.NAME, ', '.join(item for item in uninstalled)))
+
+ return True
+
+ def check_pip_dependencies(self):
+ """Checks if required pip packages are installed."""
+ print "Checking pip dependencies......",
+ uninstalled = []
+ for module in self.MISC_MAPPING['pip']:
+ try:
+ __import__(module)
+ except Exception:
+ self._set_status(
+ 0,
+ "[%s]Error: pip package %s is requred"
+ % (self.NAME, module))
+ uninstalled.append(module)
+
+ if len(uninstalled) != 0:
+ self._set_status(
+ 0,
+ "[%s]Info: Uninstalled pip packages: %s"
+ % (self.NAME, ', '.join(item for item in uninstalled)))
+
+ return True
+
+ def check_ntp(self):
+ """Validates ntp configuration and service."""
+
+ print "Checking NTP......",
+ conf_err_msg = health_check_utils.check_path(self.NAME,
+ '/etc/ntp.conf')
+ if not conf_err_msg == "":
+ self._set_status(0, conf_err_msg)
+
+ serv_err_msg = health_check_utils.check_service_running(self.NAME,
+ 'ntpd')
+ if not serv_err_msg == "":
+ self._set_status(0, serv_err_msg)
+
+ return True
+
+ def check_rsyslogd(self):
+ """Validates rsyslogd configuration and service."""
+
+ print "Checking rsyslog......",
+ conf_err_msg = health_check_utils.check_path(self.NAME,
+ '/etc/rsyslog.conf')
+ if not conf_err_msg == "":
+ self._set_status(0, conf_err_msg)
+
+ dir_err_msg = health_check_utils.check_path(self.NAME,
+ '/etc/rsyslog.d/')
+ if not dir_err_msg == "":
+ self._set_status(0, dir_err_msg)
+
+ serv_err_msg = health_check_utils.check_service_running(self.NAME,
+ 'rsyslogd')
+ if not serv_err_msg == "":
+ self._set_status(0, serv_err_msg)
+
+ return True
+
+ def check_chkconfig(self):
+ """Check if required services are enabled on the start up."""
+
+ print "Checking chkconfig......",
+ serv_to_disable = []
+ for serv in self.MISC_MAPPING["disable"]:
+ if health_check_utils.check_chkconfig(serv) is True:
+ self._set_status(
+ 0,
+ "[%s]Error: %s is not disabled"
+ % (self.NAME, serv))
+ serv_to_disable.append(serv)
+
+ if len(serv_to_disable) != 0:
+ self._set_status(
+ 0,
+ "[%s]Info: You need to disable these services "
+ "on system start-up: %s"
+ % (self.NAME,
+ ", ".join(item for item in serv_to_disable)))
+
+ serv_to_enable = []
+ for serv in self.MISC_MAPPING["enable"]:
+ if health_check_utils.check_chkconfig(serv) is False:
+ self._set_status(
+ 0, "[%s]Error: %s is disabled" % (self.NAME, serv))
+ serv_to_enable.append(serv)
+
+ if len(serv_to_enable) != 0:
+ self._set_status(0, "[%s]Info: You need to enable these "
+ "services on system start-up: %s"
+ % (self.NAME,
+ ", ".join(item for item in serv_to_enable)))
+
+ return True
+
+ def check_selinux(self):
+ """Check if SELinux is disabled."""
+ print "Checking Selinux......",
+ disabled = False
+ with open("/etc/selinux/config") as selinux:
+ for line in selinux:
+ if "SELINUX=disabled" in line:
+ disabled = True
+ break
+
+ if disabled is False:
+ self._set_status(
+ 0,
+ "[%s]Selinux is not disabled, "
+ "please disable it in /etc/selinux/config." % self.NAME)
+
+ return True
diff --git a/compass-tasks-base/actions/health_check/check_os_installer.py b/compass-tasks-base/actions/health_check/check_os_installer.py
new file mode 100644
index 0000000..6ef9818
--- /dev/null
+++ b/compass-tasks-base/actions/health_check/check_os_installer.py
@@ -0,0 +1,151 @@
+# 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.
+
+"""Compass Health Check module for OS Installer."""
+
+import os
+import xmlrpclib
+
+from compass.actions.health_check import base
+
+
+class OsInstallerCheck(base.BaseCheck):
+ """os installer health check."""
+ NAME = "OS Installer Check"
+
+ def run(self):
+ """do health check."""
+ method_name = 'self.' + self.os_installer['name'] + '_check()'
+ return eval(method_name)
+
+ def cobbler_check(self):
+ """Runs cobbler check from xmlrpc client."""
+ try:
+ remote = xmlrpclib.Server(
+ self.os_installer['cobbler_url'],
+ allow_none=True)
+ credentials = self.os_installer['credentials']
+ token = remote.login(
+ credentials['username'], credentials['password'])
+ except Exception:
+ self.code = 0
+ self.messages.append(
+ "[%s]Error: Cannot login to Cobbler with "
+ "the tokens provided in the config file"
+ % self.NAME)
+ self.messages.append(
+ "[%s]Error: Failed to connect to Cobbler "
+ "API, please check if /etc/cobbler/setting "
+ "is properly configured" % self.NAME)
+ return (self.code, self.messages)
+
+ check_result = remote.check(token)
+
+ for index, message in enumerate(check_result):
+ if "SELinux" in message:
+ check_result.pop(index)
+
+ if len(check_result) != 0:
+ self.code = 0
+ for error_msg in check_result:
+ self.messages.append("[%s]Error: " % self.NAME + error_msg)
+
+ if len(remote.get_distros()) == 0:
+ self._set_status(0,
+ "[%s]Error: No Cobbler distros found" % self.NAME)
+
+ if len(remote.get_profiles()) == 0:
+ self._set_status(0,
+ "[%s]Error: No Cobbler profiles found"
+ % self.NAME)
+
+ found_ppa = False
+ if len(remote.get_repos()) != 0:
+ for repo in remote.get_repos():
+ if 'ppa_repo' in repo['mirror']:
+ found_ppa = True
+ break
+
+ if found_ppa is False:
+ self._set_status(0,
+ "[%s]Error: No repository ppa_repo found"
+ % self.NAME)
+
+ path_map = {
+ 'match_kickstart': (
+ '/var/lib/cobbler/kickstarts/',
+ ['default.ks', 'default.seed']
+ ),
+ 'match_snippets': (
+ '/var/lib/cobbler/snippets/',
+ [
+ 'kickstart_done',
+ 'kickstart_start',
+ 'kickstart_pre_partition_disks',
+ 'kickstart_partition_disks',
+ 'kickstart_pre_anamon',
+ 'kickstart_post_anamon',
+ 'kickstart_pre_install_network_config',
+ 'kickstart_network_config',
+ 'kickstart_post_install_network_config',
+ 'kickstart_chef',
+ 'kickstart_ntp',
+ 'kickstart_yum_repo_config',
+ 'preseed_pre_partition_disks',
+ 'preseed_partition_disks',
+ 'preseed_pre_anamon',
+ 'preseed_post_anamon',
+ 'preseed_pre_install_network_config',
+ 'preseed_network_config',
+ 'preseed_post_install_network_config',
+ 'preseed_chef',
+ 'preseed_ntp',
+ 'preseed_apt_repo_config',
+ ]
+ ),
+ 'match_ks_mirror': (
+ '/var/www/cobbler/',
+ ['ks_mirror']
+ ),
+ 'match_repo_mirror': (
+ '/var/www/cobbler/',
+ ['repo_mirror']
+ ),
+ 'match_iso': (
+ '/var/lib/cobbler/',
+ ['iso']
+ ),
+ }
+ not_exists = []
+ for key in path_map.keys():
+ for path in path_map[key][1]:
+ if not os.path.exists(path_map[key][0] + path):
+ not_exists.append(path_map[key][0] + path)
+
+ if len(not_exists) != 0:
+ self._set_status(
+ 0,
+ "[%s]Error: These locations do not exist: "
+ "%s" % (
+ self.NAME,
+ ', '.join(item for item in not_exists)
+ )
+ )
+
+ if self.code == 1:
+ self.messages.append(
+ "[%s]Info: OS Installer health check has completed."
+ " No problems found, all systems go." % self.NAME)
+
+ return (self.code, self.messages)
diff --git a/compass-tasks-base/actions/health_check/check_package_installer.py b/compass-tasks-base/actions/health_check/check_package_installer.py
new file mode 100644
index 0000000..efcd8e8
--- /dev/null
+++ b/compass-tasks-base/actions/health_check/check_package_installer.py
@@ -0,0 +1,68 @@
+# 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 Package Installer."""
+import logging
+import os
+import requests
+
+from compass.actions.health_check import base
+from compass.actions.health_check import utils as health_check_utils
+
+
+class PackageInstallerCheck(base.BaseCheck):
+ """package installer health check class."""
+ NAME = "Package Installer Check"
+
+ def run(self):
+ """do health check."""
+ method_name = "self." + self.package_installer['name'] + "_check()"
+ return eval(method_name)
+
+ def chef_check(self):
+ """Checks chef setting, cookbooks and roles."""
+ self.check_chef_config_dir()
+ print "[Done]"
+ if self.code == 1:
+ self.messages.append(
+ "[%s]Info: Package installer health check "
+ "has completed. No problems found, all systems "
+ "go." % self.NAME)
+
+ return (self.code, self.messages)
+
+ def check_chef_config_dir(self):
+ """Validates chef configuration directories."""
+
+ print "Checking Chef configurations......",
+ message = health_check_utils.check_path(self.NAME, '/etc/chef-server/')
+ if not message == "":
+ self._set_status(0, message)
+
+ message = health_check_utils.check_path(self.NAME, '/opt/chef-server/')
+ if not message == "":
+ self._set_status(0, message)
+
+ return None
+
+ def ansible_check(self):
+ """Placeholder for ansible check."""
+ print "Checking ansible......"
+ print ("[Done]")
+ self.code == 1
+ self.messages.append(
+ "[%s]Info: Package installer health check "
+ "has completed. No problems found, all systems "
+ "go." % self.NAME)
+ return (self.code, self.messages)
diff --git a/compass-tasks-base/actions/health_check/check_squid.py b/compass-tasks-base/actions/health_check/check_squid.py
new file mode 100644
index 0000000..5628a63
--- /dev/null
+++ b/compass-tasks-base/actions/health_check/check_squid.py
@@ -0,0 +1,128 @@
+# 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 Squid service."""
+import commands
+import os
+import pwd
+import socket
+
+from compass.actions.health_check import base
+from compass.actions.health_check import utils as health_check_utils
+
+
+class SquidCheck(base.BaseCheck):
+ """Squid health check class."""
+ NAME = "Squid Check"
+
+ def run(self):
+ """do health check."""
+ self.check_squid_files()
+ print "[Done]"
+ self.check_squid_service()
+ print "[Done]"
+ if self.code == 1:
+ self.messages.append(
+ "[%s]Info: Squid health check has completed. "
+ "No problems found, all systems go." % self.NAME)
+ return (self.code, self.messages)
+
+ def check_squid_files(self):
+ """Validates squid config, cache directory and ownership."""
+ print "Checking Squid Files......",
+ var_map = {
+ 'match_squid_conf': False,
+ 'match_squid_cache': False,
+ 'match_squid_ownership': False,
+ }
+
+ conf_err_msg = health_check_utils.check_path(
+ self.NAME,
+ "/etc/squid/squid.conf")
+ if not conf_err_msg == "":
+ self._set_status(0, conf_err_msg)
+ elif int(oct(os.stat('/etc/squid/squid.conf').st_mode)) < 100644:
+ self._set_status(
+ 0,
+ "[%s]Error: squid.conf has incorrect "
+ "file permissions" % self.NAME)
+ else:
+ var_map['match_squid_conf'] = True
+
+ squid_path_err_msg = health_check_utils.check_path(
+ self.NAME, '/var/squid/')
+ if not squid_path_err_msg == "":
+ self._set_status(0, squid_path_err_msg)
+ elif health_check_utils.check_path(
+ self.NAME,
+ '/var/squid/cache'
+ ) != "":
+ self._set_status(
+ 0,
+ health_check_utils.check_path(
+ self.NAME,
+ '/var/squid/cache'
+ )
+ )
+ else:
+ var_map['match_squid_cache'] = True
+ uid = os.stat('/var/squid/').st_uid
+ gid = os.stat('/var/squid/').st_gid
+ if uid != gid or pwd.getpwuid(23).pw_name != 'squid':
+ self._set_status(
+ 0,
+ "[%s]Error: /var/squid directory ownership "
+ "misconfigured" % self.NAME)
+ else:
+ var_map['match_squid_ownership'] = True
+
+ fails = []
+ for key in var_map.keys():
+ if var_map[key] is False:
+ fails.append(key)
+
+ if len(fails) != 0:
+ self.messages.append(
+ "[%s]Info: Failed components for squid config: "
+ "%s" % (
+ self.NAME,
+ ', '.join(item for item in fails)
+ )
+ )
+ return True
+
+ def check_squid_service(self):
+ """Checks if squid is running on port 3128."""
+
+ print "Checking Squid service......",
+ if 'squid' not in commands.getoutput('ps -ef'):
+ self._set_status(
+ 0,
+ "[%s]Error: squid service does not seem "
+ "running" % self.NAME)
+
+ try:
+ if 'squid' != socket.getservbyport(3128):
+ self._set_status(
+ 0,
+ "[%s]Error: squid is not listening on "
+ "3128" % self.NAME)
+
+ except Exception:
+ self._set_status(
+ 0,
+ "[%s]Error: No service is listening on 3128, "
+ "squid failed" % self.NAME)
+
+ return True
diff --git a/compass-tasks-base/actions/health_check/check_tftp.py b/compass-tasks-base/actions/health_check/check_tftp.py
new file mode 100644
index 0000000..7ca6405
--- /dev/null
+++ b/compass-tasks-base/actions/health_check/check_tftp.py
@@ -0,0 +1,96 @@
+# 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 TFTP service."""
+import os
+import socket
+import xmlrpclib
+
+from compass.actions.health_check import base
+from compass.actions.health_check import utils as health_check_utils
+
+
+class TftpCheck(base.BaseCheck):
+ """tftp health check class."""
+ NAME = "TFTP Check"
+
+ def run(self):
+ """do health check."""
+ method_name = "self.check_" + self.os_installer['name'] + "_tftp()"
+ return eval(method_name)
+
+ def check_cobbler_tftp(self):
+ """Checks if Cobbler manages TFTP service.
+
+ :note: we assume TFTP service is running at the
+ same machine where this health check runs at
+ """
+
+ 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_tftp'] == 0:
+ self.messages.append(
+ '[TFTP]Info: tftp service is not managed by Compass')
+ return (0, self.messages)
+ self.check_tftp_dir()
+ print "[Done]"
+ self.check_tftp_service()
+ print "[Done]"
+ if self.code == 1:
+ self.messages.append(
+ "[%s]Info: tftp service health check has completed. "
+ "No problems found, all systems go." % self.NAME)
+
+ return (self.code, self.messages)
+
+ def check_tftp_dir(self):
+ """Validates TFTP directories and configurations."""
+ print "Checking TFTP directories......",
+ if not os.path.exists('/var/lib/tftpboot/'):
+ self._set_status(
+ 0,
+ "[%s]Error: No tftp-boot libraries found, "
+ "please check if tftp server is properly "
+ "installed/managed" % self.NAME)
+
+ return True
+
+ def check_tftp_service(self):
+ """Checks if TFTP is running on port 69."""
+ print "Checking TFTP services......",
+ serv_err_msg = health_check_utils.check_service_running(self.NAME,
+ 'xinetd')
+ if not serv_err_msg == "":
+ self._set_status(0, serv_err_msg)
+
+ if 'tftp' != socket.getservbyport(69):
+ self._set_status(
+ 0,
+ "[%s]Error: tftp doesn't seem to be listening "
+ "on Port 60." % self.NAME)
+
+ return True
diff --git a/compass-tasks-base/actions/health_check/utils.py b/compass-tasks-base/actions/health_check/utils.py
new file mode 100644
index 0000000..369c5b6
--- /dev/null
+++ b/compass-tasks-base/actions/health_check/utils.py
@@ -0,0 +1,114 @@
+# 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.
+
+"""Compass Health Check heavy-lifting utilities"""
+import commands
+import os
+import platform
+import re
+
+
+def validate_setting(module, setting, param):
+ """Checks if a Compass setting exists in the config file.
+
+ :param module : module name to be checked
+ :type module : string
+ :param setting : compass setting wrapper
+ :type setting : python module
+ :param param : settings defined in compass config file
+ :type param : string
+
+ """
+ if hasattr(setting, param):
+ return True
+ else:
+ err_msg = "[%s]Error: no %s defined" % (module, param)
+ return err_msg
+
+
+def get_dist():
+ """Returns the operating system related information."""
+
+ os_version, version, release = platform.linux_distribution()
+ return (os_version.lower().strip(), version, release.lower().strip())
+
+
+def check_path(module_name, path):
+ """Checks if a directory or file exisits.
+
+ :param module_name : module name to be checked
+ :type module_name : string
+ :param path : path of the directory of file
+ :type path : string
+
+ """
+ err_msg = ""
+ if not os.path.exists(path):
+ err_msg = (
+ "[%s]Error: %s does not exist, "
+ "please check your configurations.") % (module_name, path)
+ return err_msg
+
+
+def check_service_running(module_name, service_name):
+ """Checks if a certain service is running.
+
+ :param module_name : module name to be checked
+ :type module_name : string
+ :param service_name : service name to be checked
+ :type service_name : string
+
+ """
+ err_msg = ""
+ if service_name not in commands.getoutput('ps -ef'):
+ err_msg = "[%s]Error: %s is not running." % (
+ module_name, service_name)
+
+ return err_msg
+
+
+def check_chkconfig(service_name):
+ """Checks if a service is enabled at the start up.
+
+ :param service_name : service name to be checked
+ :type service_name : string
+
+ """
+ chk_on = False
+ for service in os.listdir('/etc/rc3.d/'):
+ if service_name in service and 'S' in service:
+ chk_on = True
+ break
+
+ return chk_on
+
+
+def strip_name(name):
+ """Reformats names."""
+ if not any([s in name for s in "(,),-,_".split(',')]):
+ return name
+
+ paren_regex = re.compile("(.*?)\s*\(")
+ dash_regex = re.compile("(.*?)\s*\-")
+ under_dash_regex = re.compile("(.*?)\s*\_")
+
+ r1 = paren_regex.match(name)
+ r2 = dash_regex.match(name)
+ r3 = under_dash_regex.match(name)
+ shortest = 'AVeryLongStringForDefualt'
+ for r in [r1, r2, r3]:
+ if r and len(r.group(1)) < len(shortest):
+ shortest = r.group(1)
+
+ return shortest