From 8646b8d62cf4ca7b6bccae537a0c9e72ba45eab3 Mon Sep 17 00:00:00 2001 From: Harry Huang Date: Fri, 17 Nov 2017 14:53:44 +0800 Subject: 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 --- compass-tasks/actions/__init__.py | 13 - compass-tasks/actions/clean.py | 195 ------------ compass-tasks/actions/cli.py | 179 ----------- compass-tasks/actions/delete.py | 148 --------- compass-tasks/actions/deploy.py | 182 ----------- compass-tasks/actions/health_check/__init__.py | 13 - compass-tasks/actions/health_check/base.py | 57 ---- compass-tasks/actions/health_check/check.py | 96 ------ compass-tasks/actions/health_check/check_apache.py | 89 ------ compass-tasks/actions/health_check/check_celery.py | 115 ------- compass-tasks/actions/health_check/check_dhcp.py | 184 ----------- compass-tasks/actions/health_check/check_dns.py | 139 --------- compass-tasks/actions/health_check/check_hds.py | 97 ------ compass-tasks/actions/health_check/check_misc.py | 219 ------------- .../actions/health_check/check_os_installer.py | 151 --------- .../health_check/check_package_installer.py | 68 ---- compass-tasks/actions/health_check/check_squid.py | 128 -------- compass-tasks/actions/health_check/check_tftp.py | 96 ------ compass-tasks/actions/health_check/utils.py | 114 ------- compass-tasks/actions/install_callback.py | 181 ----------- compass-tasks/actions/patch.py | 69 ----- compass-tasks/actions/poll_switch.py | 162 ---------- compass-tasks/actions/reinstall.py | 38 --- compass-tasks/actions/search.py | 46 --- compass-tasks/actions/update_progress.py | 298 ------------------ compass-tasks/actions/util.py | 342 --------------------- 26 files changed, 3419 deletions(-) delete mode 100644 compass-tasks/actions/__init__.py delete mode 100644 compass-tasks/actions/clean.py delete mode 100644 compass-tasks/actions/cli.py delete mode 100644 compass-tasks/actions/delete.py delete mode 100644 compass-tasks/actions/deploy.py delete mode 100644 compass-tasks/actions/health_check/__init__.py delete mode 100644 compass-tasks/actions/health_check/base.py delete mode 100644 compass-tasks/actions/health_check/check.py delete mode 100644 compass-tasks/actions/health_check/check_apache.py delete mode 100644 compass-tasks/actions/health_check/check_celery.py delete mode 100644 compass-tasks/actions/health_check/check_dhcp.py delete mode 100644 compass-tasks/actions/health_check/check_dns.py delete mode 100644 compass-tasks/actions/health_check/check_hds.py delete mode 100644 compass-tasks/actions/health_check/check_misc.py delete mode 100644 compass-tasks/actions/health_check/check_os_installer.py delete mode 100644 compass-tasks/actions/health_check/check_package_installer.py delete mode 100644 compass-tasks/actions/health_check/check_squid.py delete mode 100644 compass-tasks/actions/health_check/check_tftp.py delete mode 100644 compass-tasks/actions/health_check/utils.py delete mode 100644 compass-tasks/actions/install_callback.py delete mode 100644 compass-tasks/actions/patch.py delete mode 100644 compass-tasks/actions/poll_switch.py delete mode 100644 compass-tasks/actions/reinstall.py delete mode 100644 compass-tasks/actions/search.py delete mode 100644 compass-tasks/actions/update_progress.py delete mode 100644 compass-tasks/actions/util.py (limited to 'compass-tasks/actions') diff --git a/compass-tasks/actions/__init__.py b/compass-tasks/actions/__init__.py deleted file mode 100644 index 4ee55a4..0000000 --- a/compass-tasks/actions/__init__.py +++ /dev/null @@ -1,13 +0,0 @@ -# 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/actions/clean.py b/compass-tasks/actions/clean.py deleted file mode 100644 index a4e9bc9..0000000 --- a/compass-tasks/actions/clean.py +++ /dev/null @@ -1,195 +0,0 @@ -# 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. - -"""Module to clean installers -""" -import logging -import xmlrpclib - -from compass.actions import util - -try: - import chef -except ImportError: - pass - -class CobblerInstaller(object): - """cobbler installer""" - CREDENTIALS = "credentials" - USERNAME = 'username' - PASSWORD = 'password' - - INSTALLER_URL = "cobbler_url" - - def __init__(self, settings): - username = settings[self.CREDENTIALS][self.USERNAME] - password = settings[self.CREDENTIALS][self.PASSWORD] - cobbler_url = settings[self.INSTALLER_URL] - try: - self.remote = xmlrpclib.Server(cobbler_url) - self.token = self.remote.login(username, password) - logging.info('cobbler %s client created', cobbler_url) - except Exception as error: - logging.error( - 'failed to login %s with (%s, %s)', - cobbler_url, username, password - ) - logging.exception(error) - - def clean(self): - systems = self.remote.get_systems() - for system in systems: - system_name = system['name'] - try: - self.remote.remove_system(system_name, self.token) - logging.info('system %s is removed', system_name) - except Exception as error: - logging.error( - 'failed to remove system %s', system_name - ) - logging.exception(error) - - -class AnsibleInstaller(object): - - def __init__(self, settings): - return - - def clean(self): - pass - - -class ChefInstaller(object): - DATABAGS = "databags" - CHEFSERVER_URL = "chef_url" - CHEFSERVER_DNS = "chef_server_dns" - CHEFSERVER_IP = "chef_server_ip" - KEY_DIR = "key_dir" - CLIENT = "client_name" - - def __init__(self, settings): - installer_url = settings.get(self.CHEFSERVER_URL, None) - key_dir = settings.get(self.KEY_DIR, None) - client = settings.get(self.CLIENT, None) - try: - if installer_url and key_dir and client: - self.api = chef.ChefAPI(installer_url, key_dir, client) - else: - self.api = chef.autoconfigure() - logging.info( - 'chef client created %s(%s, %s)', - installer_url, key_dir, client - ) - except Exception as error: - logging.error( - 'failed to create chef client %s(%s, %s)', - installer_url, key_dir, client - ) - logging.exception(error) - - def clean(self): - try: - for node_name in chef.Node.list(api=self.api): - node = chef.Node(node_name, api=self.api) - node.delete() - logging.info('delete node %s', node_name) - except Exception as error: - logging.error('failed to delete some nodes') - logging.exception(error) - - try: - for client_name in chef.Client.list(api=self.api): - if client_name in ['chef-webui', 'chef-validator']: - continue - client = chef.Client(client_name, api=self.api) - client.delete() - logging.info('delete client %s', client_name) - except Exception as error: - logging.error('failed to delete some clients') - logging.exception(error) - - try: - for env_name in chef.Environment.list(api=self.api): - if env_name == '_default': - continue - env = chef.Environment(env_name, api=self.api) - env.delete() - logging.info('delete env %s', env_name) - except Exception as error: - logging.error('failed to delete some envs') - logging.exception(error) - - try: - for databag_name in chef.DataBag.list(api=self.api): - databag = chef.DataBag(databag_name, api=self.api) - for item_name, item in databag.items(): - item.delete() - logging.info( - 'delete item %s from databag %s', - item_name, databag_name - ) - except Exception as error: - logging.error('failed to delete some databag items') - logging.exception(error) - - -OS_INSTALLERS = { - 'cobbler': CobblerInstaller -} -PK_INSTALLERS = { - 'chef_installer': ChefInstaller, - 'ansible_installer': AnsibleInstaller -} - - -def clean_os_installer( - os_installer_name, os_installer_settings -): - with util.lock('serialized_action', timeout=100) as lock: - if not lock: - raise Exception( - 'failed to acquire lock to clean os installer' - ) - - if os_installer_name not in OS_INSTALLERS: - logging.error( - '%s not found in os_installers', - os_installer_name - ) - - os_installer = OS_INSTALLERS[os_installer_name]( - os_installer_settings - ) - os_installer.clean() - - -def clean_package_installer( - package_installer_name, package_installer_settings -): - with util.lock('serialized_action', timeout=100) as lock: - if not lock: - raise Exception( - 'failed to acquire lock to clean package installer' - ) - - if package_installer_name not in PK_INSTALLERS: - logging.error( - '%s not found in os_installers', - package_installer_name - ) - - package_installer = PK_INSTALLERS[package_installer_name]( - package_installer_settings - ) - package_installer.clean() diff --git a/compass-tasks/actions/cli.py b/compass-tasks/actions/cli.py deleted file mode 100644 index c9058ed..0000000 --- a/compass-tasks/actions/cli.py +++ /dev/null @@ -1,179 +0,0 @@ -# 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 Command Line Interface""" -import logging -import subprocess -import sys - -from compass.actions.health_check import check -from compass.db.api import database - -from compass.utils import flags -from compass.utils import logsetting -from compass.utils import setting_wrapper as setting -from compass.utils.util import pretty_print - - -ACTION_MAP = { - "check": "apache celery dhcp dns hds misc os_installer " - "package_installer squid tftp".split(" "), - "refresh": "db sync".split(" "), -} - - -class BootCLI(object): - """CLI to do compass check.""" - - def __init__(self): - return - - def run(self, args): - """cli takes the commands and calls respective modules.""" - action = self.get_action(args) - if action is None: - self.print_help() - else: - module = self.get_module(action, args) - if module == "invalid": - self.print_help(action) - else: - method = "self.run_" + action + "(module)" - eval(method) - - @classmethod - def get_action(cls, args): - """This method returns an action type. - - .. note:: - For 'compass check dhcp' command, it will return 'check'. - """ - if len(args) == 1: - return None - elif args[1] in ACTION_MAP.keys(): - return args[1] - return None - - @classmethod - def get_module(cls, action, args): - """This method returns a module. - - .. note:: - For 'compass check dhcp' command, it will return 'dhcp'. - """ - if len(args) <= 2: - return None - elif args[2] in ACTION_MAP[action]: - return args[2] - return "invalid" - - def run_check(self, module=None): - """This provides a flexible sanity check. - - .. note:: - param module default set to None. - if parameter module is none. Compass checks all modules. - If module specified, Compass will only check such module. - """ - if module is None: - pretty_print("Starting: Compass Health Check", - "==============================") - chk = check.BootCheck() - res = chk.run() - self.output_check_result(res) - - else: - pretty_print("Checking Module: %s" % module, - "============================") - chk = check.BootCheck() - method = "chk._check_" + module + "()" - res = eval(method) - print "\n".join(msg for msg in res[1]) - - @classmethod - def output_check_result(cls, result): - """output check result.""" - if result == {}: - return - pretty_print("\n", - "===============================", - "* Compass Health Check Report *", - "===============================") - successful = True - for key in result.keys(): - if result[key][0] == 0: - successful = False - print "%s" % "\n".join(item for item in result[key][1]) - - print "====================" - if successful is True: - print "Compass Check completes. No problems found, all systems go" - sys.exit(0) - else: - print ( - "Compass has ERRORS shown above. Please fix them before " - "deploying!") - sys.exit(1) - - @classmethod - def run_refresh(cls, action=None): - """Run refresh.""" - # TODO(xicheng): replace refresh.sh with refresh.py - if action is None: - pretty_print("Refreshing Compass...", - "=================") - subprocess.Popen( - ['/opt/compass/bin/refresh.sh'], shell=True) - elif action == "db": - pretty_print("Refreshing Compass Database...", - "===================") - subprocess.Popen( - ['/opt/compass/bin/manage_db.py createdb'], shell=True) - else: - pretty_print("Syncing with Installers...", - "================") - subprocess.Popen( - ['/opt/compass/bin/manage_db.py sync_from_installers'], - shell=True - ) - - @classmethod - def print_help(cls, module_help=""): - """print help.""" - if module_help == "": - pretty_print("usage\n=====", - "compass ", - "type 'compass {action} --help' for detailed " - "command list") - - elif module_help == "refresh": - pretty_print("usage\n=====", - "compass refresh [%s]" % - "|".join(action for action in ACTION_MAP['refresh'])) - - else: - pretty_print("usage\n=====", - "compass check [%s]" % - "|".join(action for action in ACTION_MAP['check'])) - sys.exit(2) - - -def main(): - """Compass cli entry point.""" - flags.init() - logsetting.init() - database.init() - cli = BootCLI() - output = cli.run(sys.argv) - return sys.exit(output) diff --git a/compass-tasks/actions/delete.py b/compass-tasks/actions/delete.py deleted file mode 100644 index d89994d..0000000 --- a/compass-tasks/actions/delete.py +++ /dev/null @@ -1,148 +0,0 @@ -# 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. - -"""Module to delete a given cluster -""" -import logging - -from compass.actions import util -from compass.db.api import cluster as cluster_api -from compass.db.api import host as host_api -from compass.db.api import user as user_db -from compass.deployment.deploy_manager import DeployManager -from compass.deployment.utils import constants as const - - -def delete_cluster( - cluster_id, host_id_list, - username=None, delete_underlying_host=False -): - """Delete cluster and all clusterhosts on it. - - :param cluster_id: id of the cluster. - :type cluster_id: int - :param host_id_list: list of host id. - :type host_id_list: list of int. - - If delete_underlying_host is set, all underlying hosts will - be deleted. - - .. note:: - The function should be called out of database session. - """ - with util.lock('serialized_action', timeout=100) as lock: - if not lock: - raise Exception('failed to acquire lock to delete cluster') - - user = user_db.get_user_object(username) - - cluster_info = util.ActionHelper.get_cluster_info(cluster_id, user) - adapter_id = cluster_info[const.ADAPTER_ID] - - adapter_info = util.ActionHelper.get_adapter_info( - adapter_id, cluster_id, user) - hosts_info = util.ActionHelper.get_hosts_info( - cluster_id, host_id_list, user) - - deploy_manager = DeployManager(adapter_info, cluster_info, hosts_info) - - deploy_manager.remove_hosts( - package_only=not delete_underlying_host, - delete_cluster=True - ) - util.ActionHelper.delete_cluster( - cluster_id, host_id_list, user, - delete_underlying_host - ) - - -def delete_cluster_host( - cluster_id, host_id, - username=None, delete_underlying_host=False -): - """Delete clusterhost. - - :param cluster_id: id of the cluster. - :type cluster_id: int - :param host_id: id of the host. - :type host_id: int - - If delete_underlying_host is set, the underlying host - will be deleted too. - - .. note:: - The function should be called out of database session. - """ - with util.lock('serialized_action', timeout=100) as lock: - if not lock: - raise Exception('failed to acquire lock to delete clusterhost') - - user = user_db.get_user_object(username) - cluster_info = util.ActionHelper.get_cluster_info(cluster_id, user) - adapter_id = cluster_info[const.ADAPTER_ID] - - adapter_info = util.ActionHelper.get_adapter_info( - adapter_id, cluster_id, user) - hosts_info = util.ActionHelper.get_hosts_info( - cluster_id, [host_id], user) - - deploy_manager = DeployManager(adapter_info, cluster_info, hosts_info) - - deploy_manager.remove_hosts( - package_only=not delete_underlying_host, - delete_cluster=False - ) - util.ActionHelper.delete_cluster_host( - cluster_id, host_id, user, - delete_underlying_host - ) - - -def delete_host( - host_id, cluster_id_list, username=None -): - """Delete host and all clusterhosts on it. - - :param host_id: id of the host. - :type host_id: int - - .. note:: - The function should be called out of database session. - """ - with util.lock('serialized_action', timeout=100) as lock: - if not lock: - raise Exception('failed to acquire lock to delete host') - - user = user_db.get_user_object(username) - for cluster_id in cluster_id_list: - cluster_info = util.ActionHelper.get_cluster_info( - cluster_id, user) - adapter_id = cluster_info[const.ADAPTER_ID] - - adapter_info = util.ActionHelper.get_adapter_info( - adapter_id, cluster_id, user) - hosts_info = util.ActionHelper.get_hosts_info( - cluster_id, [host_id], user) - - deploy_manager = DeployManager( - adapter_info, cluster_info, hosts_info) - - deploy_manager.remove_hosts( - package_only=True, - delete_cluster=False - ) - - util.ActionHelper.delete_host( - host_id, user - ) diff --git a/compass-tasks/actions/deploy.py b/compass-tasks/actions/deploy.py deleted file mode 100644 index 53179f5..0000000 --- a/compass-tasks/actions/deploy.py +++ /dev/null @@ -1,182 +0,0 @@ -# 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. - -"""Module to deploy a given cluster -""" -import logging - -from compass.actions import util -from compass.db.api import cluster as cluster_db -from compass.db.api import health_check_report as health_check_db -from compass.db.api import user as user_db -from compass.deployment.deploy_manager import DeployManager -from compass.deployment.utils import constants as const - - -def deploy(cluster_id, hosts_id_list, username=None): - """Deploy clusters. - - :param cluster_hosts: clusters and hosts in each cluster to deploy. - :type cluster_hosts: dict of int or str to list of int or str - - .. note:: - The function should be called out of database session. - """ - with util.lock('serialized_action', timeout=1000) as lock: - if not lock: - raise Exception('failed to acquire lock to deploy') - - user = user_db.get_user_object(username) - - cluster_info = util.ActionHelper.get_cluster_info(cluster_id, user) - adapter_id = cluster_info[const.ADAPTER_ID] - - adapter_info = util.ActionHelper.get_adapter_info( - adapter_id, cluster_id, user) - hosts_info = util.ActionHelper.get_hosts_info( - cluster_id, hosts_id_list, user) - - deploy_successful = True - try: - deploy_manager = DeployManager( - adapter_info, cluster_info, hosts_info) - # deploy_manager.prepare_for_deploy() - logging.debug('Created deploy manager with %s %s %s' - % (adapter_info, cluster_info, hosts_info)) - deployed_config = deploy_manager.deploy() - except Exception as error: - logging.exception(error) - deploy_successful = False - - if deploy_successful: - util.ActionHelper.save_deployed_config(deployed_config, user) - util.ActionHelper.update_state( - cluster_id, hosts_id_list, user, state='INSTALLING' - ) - else: - util.ActionHelper.update_state( - cluster_id, hosts_id_list, user, state='ERROR', - message='failed to start deployment', severity='ERROR' - ) - - -def redeploy(cluster_id, username=None): - """Deploy clusters. - - :param cluster_hosts: clusters and hosts in each cluster to deploy. - :type cluster_hosts: dict of int or str to list of int or str - """ - with util.lock('serialized_action') as lock: - if not lock: - raise Exception('failed to acquire lock to deploy') - - user = user_db.get_user_object(username) - cluster_info = util.ActionHelper.get_cluster_info(cluster_id, user) - adapter_id = cluster_info[const.ADAPTER_ID] - - adapter_info = util.ActionHelper.get_adapter_info( - adapter_id, cluster_id, user) - - cluster_hosts = cluster_db.list_cluster_hosts(cluster_id, user) - hosts_id_list = [host['id'] for host in cluster_hosts] - - hosts_info = util.ActionHelper.get_hosts_info( - cluster_id, hosts_id_list, user) - - deploy_successful = True - try: - deploy_manager = DeployManager( - adapter_info, cluster_info, hosts_info) - # deploy_manager.prepare_for_deploy() - deploy_manager.redeploy() - except Exception as error: - logging.exception(error) - deploy_successful = False - if deploy_successful: - util.ActionHelper.update_state( - cluster_id, hosts_id_list, user, state='INSTALLING', - ) - else: - util.ActionHelper.update_state( - cluster_id, hosts_id_list, user, state='ERROR', - message='failed to start redeployment', severity='ERROR' - ) - - -def health_check(cluster_id, report_uri, username): - with util.lock('cluster_health_check') as lock: - if not lock: - raise Exception('failed to acquire lock to check health') - - user = user_db.get_user_object(username) - cluster_info = util.ActionHelper.get_cluster_info(cluster_id, user) - adapter_id = cluster_info[const.ADAPTER_ID] - - adapter_info = util.ActionHelper.get_adapter_info( - adapter_id, cluster_id, user - ) - - deploy_manager = DeployManager(adapter_info, cluster_info, None) - try: - deploy_manager.check_cluster_health(report_uri) - except Exception as exc: - logging.error("health_check exception: ============= %s" % exc) - data = {'state': 'error', 'error_message': str(exc), 'report': {}} - reports = health_check_db.list_health_reports( - cluster_id, user=user) - if not reports: - # Exception before executing command remotely for health check. - # No reports names sending back yet. Create a report - name = 'pre_remote_health_check' - health_check_db.add_report_record( - cluster_id, name, user=user, **data - ) - - health_check_db.update_multi_reports(cluster_id, user=user, **data) - - -class ServerPowerMgmt(object): - """Power management for bare-metal machines by IPMI command.""" - @staticmethod - def poweron(machine_id, user): - """Power on the specified machine.""" - pass - - @staticmethod - def poweroff(machine_id, user): - pass - - @staticmethod - def reset(machine_id, user): - pass - - -class HostPowerMgmt(object): - """Power management for hosts installed OS by OS installer. OS installer - - will poweron/poweroff/reset host. - - """ - @staticmethod - def poweron(host_id, user): - """Power on the specified host.""" - pass - - @staticmethod - def poweroff(host_id, user): - pass - - @staticmethod - def reset(host_id, user): - pass diff --git a/compass-tasks/actions/health_check/__init__.py b/compass-tasks/actions/health_check/__init__.py deleted file mode 100644 index 4ee55a4..0000000 --- a/compass-tasks/actions/health_check/__init__.py +++ /dev/null @@ -1,13 +0,0 @@ -# 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/actions/health_check/base.py b/compass-tasks/actions/health_check/base.py deleted file mode 100644 index 22b6fae..0000000 --- a/compass-tasks/actions/health_check/base.py +++ /dev/null @@ -1,57 +0,0 @@ -# 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/actions/health_check/check.py b/compass-tasks/actions/health_check/check.py deleted file mode 100644 index c1adbc6..0000000 --- a/compass-tasks/actions/health_check/check.py +++ /dev/null @@ -1,96 +0,0 @@ -# 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/actions/health_check/check_apache.py b/compass-tasks/actions/health_check/check_apache.py deleted file mode 100644 index 294d6f9..0000000 --- a/compass-tasks/actions/health_check/check_apache.py +++ /dev/null @@ -1,89 +0,0 @@ -# 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/actions/health_check/check_celery.py b/compass-tasks/actions/health_check/check_celery.py deleted file mode 100644 index 2d8d27c..0000000 --- a/compass-tasks/actions/health_check/check_celery.py +++ /dev/null @@ -1,115 +0,0 @@ -# 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/actions/health_check/check_dhcp.py b/compass-tasks/actions/health_check/check_dhcp.py deleted file mode 100644 index e3bae1e..0000000 --- a/compass-tasks/actions/health_check/check_dhcp.py +++ /dev/null @@ -1,184 +0,0 @@ -# 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/actions/health_check/check_dns.py b/compass-tasks/actions/health_check/check_dns.py deleted file mode 100644 index 843d7e2..0000000 --- a/compass-tasks/actions/health_check/check_dns.py +++ /dev/null @@ -1,139 +0,0 @@ -# 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/actions/health_check/check_hds.py b/compass-tasks/actions/health_check/check_hds.py deleted file mode 100644 index d176f1f..0000000 --- a/compass-tasks/actions/health_check/check_hds.py +++ /dev/null @@ -1,97 +0,0 @@ -# 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/actions/health_check/check_misc.py b/compass-tasks/actions/health_check/check_misc.py deleted file mode 100644 index b8beb1b..0000000 --- a/compass-tasks/actions/health_check/check_misc.py +++ /dev/null @@ -1,219 +0,0 @@ -# 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/actions/health_check/check_os_installer.py b/compass-tasks/actions/health_check/check_os_installer.py deleted file mode 100644 index 6ef9818..0000000 --- a/compass-tasks/actions/health_check/check_os_installer.py +++ /dev/null @@ -1,151 +0,0 @@ -# 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/actions/health_check/check_package_installer.py b/compass-tasks/actions/health_check/check_package_installer.py deleted file mode 100644 index efcd8e8..0000000 --- a/compass-tasks/actions/health_check/check_package_installer.py +++ /dev/null @@ -1,68 +0,0 @@ -# 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/actions/health_check/check_squid.py b/compass-tasks/actions/health_check/check_squid.py deleted file mode 100644 index 5628a63..0000000 --- a/compass-tasks/actions/health_check/check_squid.py +++ /dev/null @@ -1,128 +0,0 @@ -# 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/actions/health_check/check_tftp.py b/compass-tasks/actions/health_check/check_tftp.py deleted file mode 100644 index 7ca6405..0000000 --- a/compass-tasks/actions/health_check/check_tftp.py +++ /dev/null @@ -1,96 +0,0 @@ -# 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/actions/health_check/utils.py b/compass-tasks/actions/health_check/utils.py deleted file mode 100644 index 369c5b6..0000000 --- a/compass-tasks/actions/health_check/utils.py +++ /dev/null @@ -1,114 +0,0 @@ -# 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 diff --git a/compass-tasks/actions/install_callback.py b/compass-tasks/actions/install_callback.py deleted file mode 100644 index 14d2639..0000000 --- a/compass-tasks/actions/install_callback.py +++ /dev/null @@ -1,181 +0,0 @@ -# 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. - -"""Module to receive installation callback. - - .. moduleauthor:: Xiaodong Wang -""" -import logging - -from compass.actions import util -from compass.db.api import cluster as cluster_api -from compass.db.api import host as host_api -from compass.db.api import user as user_db -from compass.deployment.deploy_manager import DeployManager -from compass.deployment.utils import constants as const - - -def os_installed( - host_id, clusterhosts_ready, clusters_os_ready, - username=None -): - """Callback when os is installed. - - :param host_id: host that os is installed. - :type host_id: integer - :param clusterhosts_ready: the clusterhosts that should trigger ready. - :param clusters_os_ready: the cluster that should trigger os ready. - - .. note:: - The function should be called out of database session. - """ - with util.lock('serialized_action') as lock: - if not lock: - raise Exception( - 'failed to acquire lock to ' - 'do the post action after os installation' - ) - logging.info( - 'os installed on host %s ' - 'with cluster host ready %s cluster os ready %s', - host_id, clusterhosts_ready, clusters_os_ready - ) - if username: - user = user_db.get_user_object(username) - else: - user = None - os_installed_triggered = False - for cluster_id, clusterhost_ready in clusterhosts_ready.items(): - if not clusterhost_ready and os_installed_triggered: - continue - cluster_id = int(cluster_id) - cluster_info = util.ActionHelper.get_cluster_info( - cluster_id, user) - adapter_id = cluster_info[const.ADAPTER_ID] - - adapter_info = util.ActionHelper.get_adapter_info( - adapter_id, cluster_id, user) - hosts_info = util.ActionHelper.get_hosts_info( - cluster_id, [host_id], user) - - deploy_manager = DeployManager( - adapter_info, cluster_info, hosts_info) - - if not os_installed_triggered: - deploy_manager.os_installed() - util.ActionHelper.host_ready(host_id, True, user) - os_installed_triggered = True - - if clusterhost_ready: - # deploy_manager.cluster_os_installed() - util.ActionHelper.cluster_host_ready( - cluster_id, host_id, False, user - ) - - if util.ActionHelper.is_cluster_os_ready(cluster_id, user): - logging.info("deploy_manager begin cluster_os_installed") - deploy_manager.cluster_os_installed() - - -def package_installed( - cluster_id, host_id, cluster_ready, - host_ready, username=None -): - """Callback when package is installed. - - :param cluster_id: cluster id. - :param host_id: host id. - :param cluster_ready: if the cluster should trigger ready. - :param host_ready: if the host should trigger ready. - - .. note:: - The function should be called out of database session. - """ - with util.lock('serialized_action') as lock: - if not lock: - raise Exception( - 'failed to acquire lock to ' - 'do the post action after package installation' - ) - logging.info( - 'package installed on cluster %s host %s ' - 'with cluster ready %s host ready %s', - cluster_id, host_id, cluster_ready, host_ready - ) - - if username: - user = user_db.get_user_object(username) - else: - user = None - cluster_info = util.ActionHelper.get_cluster_info(cluster_id, user) - adapter_id = cluster_info[const.ADAPTER_ID] - - adapter_info = util.ActionHelper.get_adapter_info( - adapter_id, cluster_id, user) - hosts_info = util.ActionHelper.get_hosts_info( - cluster_id, [host_id], user) - - deploy_manager = DeployManager(adapter_info, cluster_info, hosts_info) - - deploy_manager.package_installed() - util.ActionHelper.cluster_host_ready(cluster_id, host_id, True, user) - if cluster_ready: - util.ActionHelper.cluster_ready(cluster_id, False, user) - if host_ready: - util.ActionHelper.host_ready(host_id, False, user) - - -def cluster_installed( - cluster_id, clusterhosts_ready, - username=None -): - """Callback when cluster is installed. - - :param cluster_id: cluster id - :param clusterhosts_ready: clusterhosts that should trigger ready. - - .. note:: - The function should be called out of database session. - """ - with util.lock('serialized_action') as lock: - if not lock: - raise Exception( - 'failed to acquire lock to ' - 'do the post action after cluster installation' - ) - logging.info( - 'package installed on cluster %s with clusterhosts ready %s', - cluster_id, clusterhosts_ready - ) - if username: - user = user_db.get_user_object(username) - else: - user = None - cluster_info = util.ActionHelper.get_cluster_info(cluster_id, user) - adapter_id = cluster_info[const.ADAPTER_ID] - - adapter_info = util.ActionHelper.get_adapter_info( - adapter_id, cluster_id, user) - hosts_info = util.ActionHelper.get_hosts_info( - cluster_id, clusterhosts_ready.keys(), user) - - deploy_manager = DeployManager(adapter_info, cluster_info, hosts_info) - - deploy_manager.cluster_installed() - util.ActionHelper.cluster_ready(cluster_id, True, user) - for host_id, clusterhost_ready in clusterhosts_ready.items(): - if clusterhost_ready: - util.ActionHelper.cluster_host_ready( - cluster_id, host_id, False, user - ) diff --git a/compass-tasks/actions/patch.py b/compass-tasks/actions/patch.py deleted file mode 100644 index 6d29be6..0000000 --- a/compass-tasks/actions/patch.py +++ /dev/null @@ -1,69 +0,0 @@ -# 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. - -"""Module to patch an existing cluster -""" -import logging -import simplejson as json - -from compass.actions import util -from compass.db.api import cluster as cluster_db -from compass.db.api import user as user_db -from compass.deployment.deploy_manager import Patcher -from compass.deployment.utils import constants as const - - -def patch(cluster_id, username=None): - """Patch cluster. - - :param cluster_id: id of the cluster - :type cluster_id: int - - .. note:: - The function should be called out of database session. - """ - with util.lock('serialized_action', timeout=1000) as lock: - if not lock: - raise Exception('failed to acquire lock to deploy') - - user = user_db.get_user_object(username) - cluster_hosts = cluster_db.list_cluster_hosts(cluster_id, user) - hosts_id_list = [host['id'] for host in cluster_hosts] - cluster_info = util.ActionHelper.get_cluster_info(cluster_id, user) - adapter_id = cluster_info[const.ADAPTER_ID] - - adapter_info = util.ActionHelper.get_adapter_info( - adapter_id, cluster_id, user) - hosts_info = util.ActionHelper.get_hosts_info( - cluster_id, hosts_id_list, user) - patch_successful = True - try: - patcher = Patcher( - adapter_info, cluster_info, hosts_info, cluster_hosts) - patched_config = patcher.patch() - except Exception as error: - logging.exception(error) - patch_successful = False - - if patch_successful: - clean_payload = '{"patched_roles": []}' - clean_payload = json.loads(clean_payload) - for cluster_host in cluster_hosts: - cluster_db.update_cluster_host( - cluster_id, cluster_host['id'], user, **clean_payload) - logging.info( - "cleaning up patched roles for host id: %s", - cluster_host['id'] - ) - logging.info("Patch successful: %s", patched_config) diff --git a/compass-tasks/actions/poll_switch.py b/compass-tasks/actions/poll_switch.py deleted file mode 100644 index 5c29b01..0000000 --- a/compass-tasks/actions/poll_switch.py +++ /dev/null @@ -1,162 +0,0 @@ -# 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. - -"""Module to provider function to poll switch.""" -import logging -import netaddr - -from compass.actions import util -from compass.db.api import database -from compass.db.api import switch as switch_api -from compass.db.api import user as user_api -from compass.hdsdiscovery.hdmanager import HDManager - - -def _poll_switch(ip_addr, credentials, req_obj='mac', oper="SCAN"): - """Poll switch by ip addr. - - - Args: - ip_addr: ip addr of the switch. - credentials: credentials of the switch. - - Returns: switch attributes dict and list of machine attributes dict. - """ - under_monitoring = 'under_monitoring' - unreachable = 'unreachable' - polling_error = 'error' - hdmanager = HDManager() - vendor, state, err_msg = hdmanager.get_vendor(ip_addr, credentials) - if not vendor: - logging.info("*****error_msg: %s****", err_msg) - logging.error('no vendor found or match switch %s', ip_addr) - return ( - { - 'vendor': vendor, 'state': state, 'err_msg': err_msg - }, { - } - ) - - logging.debug( - 'hdmanager learn switch from %s', ip_addr - ) - results = [] - try: - results = hdmanager.learn( - ip_addr, credentials, vendor, req_obj, oper - ) - except Exception as error: - logging.exception(error) - state = unreachable - err_msg = ( - 'SNMP walk for querying MAC addresses timedout' - ) - return ( - { - 'vendor': vendor, 'state': state, 'err_msg': err_msg - }, { - } - ) - - logging.info("pollswitch %s result: %s", ip_addr, results) - if not results: - logging.error( - 'no result learned from %s', ip_addr - ) - state = polling_error - err_msg = 'No result learned from SNMP walk' - return ( - {'vendor': vendor, 'state': state, 'err_msg': err_msg}, - {} - ) - - logging.info('poll switch result: %s' % str(results)) - machine_dicts = {} - for machine in results: - mac = machine['mac'] - port = machine['port'] - vlan = int(machine['vlan']) - if vlan: - vlans = [vlan] - else: - vlans = [] - if mac not in machine_dicts: - machine_dicts[mac] = {'mac': mac, 'port': port, 'vlans': vlans} - else: - machine_dicts[mac]['port'] = port - machine_dicts[mac]['vlans'].extend(vlans) - - logging.debug('update switch %s state to under monitoring', ip_addr) - state = under_monitoring - return ( - {'vendor': vendor, 'state': state, 'err_msg': err_msg}, - machine_dicts.values() - ) - - -def poll_switch(poller_email, ip_addr, credentials, - req_obj='mac', oper="SCAN"): - """Query switch and update switch machines. - - .. note:: - When polling switch succeeds, for each mac it got from polling switch, - A Machine record associated with the switch is added to the database. - - :param ip_addr: switch ip address. - :type ip_addr: str - :param credentials: switch crednetials. - :type credentials: dict - :param req_obj: the object requested to query from switch. - :type req_obj: str - :param oper: the operation to query the switch. - :type oper: str, should be one of ['SCAN', 'GET', 'SET'] - - .. note:: - The function should be called out of database session scope. - """ - poller = user_api.get_user_object(poller_email) - ip_int = long(netaddr.IPAddress(ip_addr)) - with util.lock('poll switch %s' % ip_addr, timeout=120) as lock: - if not lock: - raise Exception( - 'failed to acquire lock to poll switch %s' % ip_addr - ) - - # TODO(grace): before repoll the switch, set the state to repolling. - # and when the poll switch is timeout, set the state to error. - # the frontend should only consider some main state like INTIALIZED, - # ERROR and SUCCESSFUL, REPOLLING is as an intermediate state to - # indicate the switch is in learning the mac of the machines connected - # to it. - logging.debug('poll switch: %s', ip_addr) - switch_dict, machine_dicts = _poll_switch( - ip_addr, credentials, req_obj=req_obj, oper=oper - ) - switches = switch_api.list_switches(ip_int=ip_int, user=poller) - if not switches: - logging.error('no switch found for %s', ip_addr) - return - - for switch in switches: - for machine_dict in machine_dicts: - logging.info('add machine: %s', machine_dict) - machine_dict['owner_id'] = poller.id - switch_api.add_switch_machine( - switch['id'], False, user=poller, **machine_dict - ) - switch_api.update_switch( - switch['id'], - user=poller, - **switch_dict - ) diff --git a/compass-tasks/actions/reinstall.py b/compass-tasks/actions/reinstall.py deleted file mode 100644 index 62d1bcb..0000000 --- a/compass-tasks/actions/reinstall.py +++ /dev/null @@ -1,38 +0,0 @@ -# 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. - -"""Module to reinstall a given cluster - - .. moduleauthor:: Xiaodong Wang -""" -import logging - -from compass.actions import util -from compass.db.api import database - - -def reinstall(cluster_hosts): - """Reinstall clusters. - - :param cluster_hosts: clusters and hosts in each cluster to reinstall. - :type cluster_hosts: dict of int or str to list of int or str - - .. note:: - The function should be called out of database session. - """ - with util.lock('serialized_action') as lock: - if not lock: - raise Exception( - 'failed to acquire lock to reinstall') - logging.debug('reinstall cluster_hosts: %s', cluster_hosts) diff --git a/compass-tasks/actions/search.py b/compass-tasks/actions/search.py deleted file mode 100644 index 73ce1d9..0000000 --- a/compass-tasks/actions/search.py +++ /dev/null @@ -1,46 +0,0 @@ -# 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. - -"""Module to search configs of given clusters - - .. moduleauthor:: Xiaodong Wang -""" -import logging - -from compass.actions import util -from compass.config_management.utils.config_manager import ConfigManager -from compass.db.api import database - - -def search(cluster_hosts, cluster_propreties_match, - cluster_properties_name, host_properties_match, - host_properties_name): - """search clusters. - - :param cluster_hosts: clusters and hosts in each cluster to search. - :type cluster_hosts: dict of int or str to list of int or str - - .. note:: - The function should be called out of database session. - """ - logging.debug('search cluster_hosts: %s', cluster_hosts) - with database.session(): - cluster_hosts, os_versions, target_systems = ( - util.update_cluster_hosts(cluster_hosts)) - manager = ConfigManager() - return manager.filter_cluster_and_hosts( - cluster_hosts, os_versions, - target_systems, cluster_propreties_match, - cluster_properties_name, host_properties_match, - host_properties_name) diff --git a/compass-tasks/actions/update_progress.py b/compass-tasks/actions/update_progress.py deleted file mode 100644 index 67a9963..0000000 --- a/compass-tasks/actions/update_progress.py +++ /dev/null @@ -1,298 +0,0 @@ -# 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. - -"""Module to update status and installing progress of the given cluster. - - .. moduleauthor:: Xiaodong Wang -""" -import logging - -from compass.actions import util -from compass.db.api import adapter_holder as adapter_api -from compass.db.api import cluster as cluster_api -from compass.db.api import host as host_api -from compass.db.api import user as user_api -from compass.log_analyzor import progress_calculator -from compass.utils import setting_wrapper as setting - - -def update_progress(): - """Update status and installing progress of the given cluster. - - :param cluster_hosts: clusters and hosts in each cluster to update. - :type cluster_hosts: dict of int or str to list of int or str - - .. note:: - The function should be called out of the database session scope. - In the function, it will update the database cluster_state and - host_state table for the deploying cluster and hosts. - - The function will also query log_progressing_history table to get - the lastest installing progress and the position of log it has - processed in the last run. The function uses these information to - avoid recalculate the progress from the beginning of the log file. - After the progress got updated, these information will be stored back - to the log_progressing_history for next time run. - """ - with util.lock('log_progressing', timeout=60, blocking=False) as lock: - if not lock: - logging.error( - 'failed to acquire lock to calculate installation progress' - ) - return - - logging.info('update installing progress') - - user = user_api.get_user_object(setting.COMPASS_ADMIN_EMAIL) - hosts = host_api.list_hosts(user=user) - host_mapping = {} - for host in hosts: - if 'id' not in host: - logging.error('id is not in host %s', host) - continue - host_id = host['id'] - if 'os_name' not in host: - logging.error('os_name is not in host %s', host) - continue - if 'os_installer' not in host: - logging.error('os_installer is not in host %s', host) - continue - host_dirname = setting.HOST_INSTALLATION_LOGDIR_NAME - if host_dirname not in host: - logging.error( - '%s is not in host %s', host_dirname, host - ) - continue - host_state = host_api.get_host_state(host_id, user=user) - if 'state' not in host_state: - logging.error('state is not in host state %s', host_state) - continue - if host_state['state'] == 'INSTALLING': - host_log_histories = host_api.get_host_log_histories( - host_id, user=user - ) - host_log_history_mapping = {} - for host_log_history in host_log_histories: - if 'filename' not in host_log_history: - logging.error( - 'filename is not in host log history %s', - host_log_history - ) - continue - host_log_history_mapping[ - host_log_history['filename'] - ] = host_log_history - host_mapping[host_id] = ( - host, host_state, host_log_history_mapping - ) - else: - logging.info( - 'ignore host state %s since it is not in installing', - host_state - ) - adapters = adapter_api.list_adapters(user=user) - adapter_mapping = {} - for adapter in adapters: - if 'id' not in adapter: - logging.error( - 'id not in adapter %s', adapter - ) - continue - if 'package_installer' not in adapter: - logging.info( - 'package_installer not in adapter %s', adapter - ) - continue - adapter_id = adapter['id'] - adapter_mapping[adapter_id] = adapter - clusters = cluster_api.list_clusters(user=user) - cluster_mapping = {} - for cluster in clusters: - if 'id' not in cluster: - logging.error('id not in cluster %s', cluster) - continue - cluster_id = cluster['id'] - if 'adapter_id' not in cluster: - logging.error( - 'adapter_id not in cluster %s', - cluster - ) - continue - cluster_state = cluster_api.get_cluster_state( - cluster_id, - user=user - ) - if 'state' not in cluster_state: - logging.error('state not in cluster state %s', cluster_state) - continue - cluster_mapping[cluster_id] = (cluster, cluster_state) - clusterhosts = cluster_api.list_clusterhosts(user=user) - clusterhost_mapping = {} - for clusterhost in clusterhosts: - if 'clusterhost_id' not in clusterhost: - logging.error( - 'clusterhost_id not in clusterhost %s', - clusterhost - ) - continue - clusterhost_id = clusterhost['clusterhost_id'] - if 'cluster_id' not in clusterhost: - logging.error( - 'cluster_id not in clusterhost %s', - clusterhost - ) - continue - cluster_id = clusterhost['cluster_id'] - if cluster_id not in cluster_mapping: - logging.info( - 'ignore clusterhost %s ' - 'since the cluster_id ' - 'is not in cluster_mapping %s', - clusterhost, cluster_mapping - ) - continue - cluster, _ = cluster_mapping[cluster_id] - if 'flavor_name' not in cluster: - logging.error( - 'flavor_name is not in clusterhost %s related cluster', - clusterhost - ) - continue - clusterhost_dirname = setting.CLUSTERHOST_INATALLATION_LOGDIR_NAME - if clusterhost_dirname not in clusterhost: - logging.error( - '%s is not in clusterhost %s', - clusterhost_dirname, clusterhost - ) - continue - adapter_id = cluster['adapter_id'] - if adapter_id not in adapter_mapping: - logging.info( - 'ignore clusterhost %s ' - 'since the adapter_id %s ' - 'is not in adaper_mapping %s', - clusterhost, adapter_id, adapter_mapping - ) - continue - adapter = adapter_mapping[adapter_id] - if 'package_installer' not in adapter: - logging.info( - 'ignore clusterhost %s ' - 'since the package_installer is not define ' - 'in adapter %s', - clusterhost, adapter - ) - continue - package_installer = adapter['package_installer'] - clusterhost['package_installer'] = package_installer - clusterhost['adapter_name'] = adapter['name'] - clusterhost_state = cluster_api.get_clusterhost_self_state( - clusterhost_id, user=user - ) - if 'state' not in clusterhost_state: - logging.error( - 'state not in clusterhost_state %s', - clusterhost_state - ) - continue - if clusterhost_state['state'] == 'INSTALLING': - clusterhost_log_histories = ( - cluster_api.get_clusterhost_log_histories( - clusterhost_id, user=user - ) - ) - clusterhost_log_history_mapping = {} - for clusterhost_log_history in clusterhost_log_histories: - if 'filename' not in clusterhost_log_history: - logging.error( - 'filename not in clusterhost_log_history %s', - clusterhost_log_history - ) - continue - clusterhost_log_history_mapping[ - clusterhost_log_history['filename'] - ] = clusterhost_log_history - clusterhost_mapping[clusterhost_id] = ( - clusterhost, clusterhost_state, - clusterhost_log_history_mapping - ) - else: - logging.info( - 'ignore clusterhost state %s ' - 'since it is not in installing', - clusterhost_state - ) - - progress_calculator.update_host_progress( - host_mapping) - for host_id, (host, host_state, host_log_history_mapping) in ( - host_mapping.items() - ): - host_api.update_host_state( - host_id, user=user, - percentage=host_state.get('percentage', 0), - message=host_state.get('message', ''), - severity=host_state.get('severity', 'INFO') - ) - for filename, host_log_history in ( - host_log_history_mapping.items() - ): - host_api.add_host_log_history( - host_id, filename=filename, user=user, - position=host_log_history.get('position', 0), - percentage=host_log_history.get('percentage', 0), - partial_line=host_log_history.get('partial_line', ''), - message=host_log_history.get('message', ''), - severity=host_log_history.get('severity', 'INFO'), - line_matcher_name=host_log_history.get( - 'line_matcher_name', 'start' - ) - ) - progress_calculator.update_clusterhost_progress( - clusterhost_mapping) - for ( - clusterhost_id, - (clusterhost, clusterhost_state, clusterhost_log_history_mapping) - ) in ( - clusterhost_mapping.items() - ): - cluster_api.update_clusterhost_state( - clusterhost_id, user=user, - percentage=clusterhost_state.get('percentage', 0), - message=clusterhost_state.get('message', ''), - severity=clusterhost_state.get('severity', 'INFO') - ) - for filename, clusterhost_log_history in ( - clusterhost_log_history_mapping.items() - ): - cluster_api.add_clusterhost_log_history( - clusterhost_id, user=user, filename=filename, - position=clusterhost_log_history.get('position', 0), - percentage=clusterhost_log_history.get('percentage', 0), - partial_line=clusterhost_log_history.get( - 'partial_line', ''), - message=clusterhost_log_history.get('message', ''), - severity=clusterhost_log_history.get('severity', 'INFO'), - line_matcher_name=( - clusterhost_log_history.get( - 'line_matcher_name', 'start' - ) - ) - ) - progress_calculator.update_cluster_progress( - cluster_mapping) - for cluster_id, (cluster, cluster_state) in cluster_mapping.items(): - cluster_api.update_cluster_state( - cluster_id, user=user - ) diff --git a/compass-tasks/actions/util.py b/compass-tasks/actions/util.py deleted file mode 100644 index 4d9f855..0000000 --- a/compass-tasks/actions/util.py +++ /dev/null @@ -1,342 +0,0 @@ -# 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. - -"""Module to provide util for actions - - .. moduleauthor:: Xiaodong Wang ,xiaodongwang@huawei.com> -""" -import logging -import redis - -from contextlib import contextmanager - -from compass.db.api import adapter_holder as adapter_db -from compass.db.api import cluster as cluster_db -from compass.db.api import host as host_db -from compass.db.api import machine as machine_db -from compass.deployment.utils import constants as const - - -@contextmanager -def lock(lock_name, blocking=True, timeout=10): - """acquire a lock to do some actions. - - The lock is acquired by lock_name among the whole distributed - systems. - """ - # TODO(xicheng): in future we should explicitly told which redis - # server we want to talk to make the lock works on distributed - # systems. - redis_instance = redis.Redis() - instance_lock = redis_instance.lock(lock_name, timeout=timeout) - owned = False - try: - locked = instance_lock.acquire(blocking=blocking) - if locked: - owned = True - logging.debug('acquired lock %s', lock_name) - yield instance_lock - else: - logging.info('lock %s is already hold', lock_name) - yield None - - except Exception as error: - logging.info( - 'redis fails to acquire the lock %s', lock_name) - logging.exception(error) - yield None - - finally: - if owned: - instance_lock.acquired_until = 0 - instance_lock.release() - logging.debug('released lock %s', lock_name) - else: - logging.debug('nothing to release %s', lock_name) - - -class ActionHelper(object): - - @staticmethod - def get_adapter_info(adapter_id, cluster_id, user): - """Get adapter information. Return a dictionary as below, - - { - "id": 1, - "name": "xxx", - "flavors": [ - { - "flavor_name": "xxx", - "roles": ['xxx', 'yyy', ...], - "template": "xxx.tmpl" - }, - ... - ], - "metadata": { - "os_config": { - ... - }, - "package_config": { - ... - } - }, - "os_installer": { - "name": "cobbler", - "settings": {....} - }, - "pk_installer": { - "name": "chef", - "settings": {....} - }, - ... - } - To view a complete output, please refer to backend doc. - """ - - adapter_info = adapter_db.get_adapter(adapter_id, user=user) - metadata = cluster_db.get_cluster_metadata(cluster_id, user=user) - adapter_info.update({const.METADATA: metadata}) - - for flavor_info in adapter_info[const.FLAVORS]: - roles = flavor_info[const.ROLES] - flavor_info[const.ROLES] = ActionHelper._get_role_names(roles) - - return adapter_info - - @staticmethod - def _get_role_names(roles): - return [role[const.NAME] for role in roles] - - @staticmethod - def get_cluster_info(cluster_id, user): - """Get cluster information.Return a dictionary as below, - - { - "id": 1, - "adapter_id": 1, - "os_version": "CentOS-6.5-x86_64", - "name": "cluster_01", - "flavor": { - "flavor_name": "zzz", - "template": "xx.tmpl", - "roles": [...] - } - "os_config": {..}, - "package_config": {...}, - "deployed_os_config": {}, - "deployed_package_config": {}, - "owner": "xxx" - } - """ - - cluster_info = cluster_db.get_cluster(cluster_id, user=user) - - # convert roles retrieved from db into a list of role names - roles_info = cluster_info.setdefault( - const.FLAVOR, {}).setdefault(const.ROLES, []) - cluster_info[const.FLAVOR][const.ROLES] = \ - ActionHelper._get_role_names(roles_info) - - # get cluster config info - cluster_config = cluster_db.get_cluster_config(cluster_id, user=user) - cluster_info.update(cluster_config) - - deploy_config = cluster_db.get_cluster_deployed_config(cluster_id, - user=user) - cluster_info.update(deploy_config) - - return cluster_info - - @staticmethod - def get_hosts_info(cluster_id, hosts_id_list, user): - """Get hosts information. Return a dictionary as below, - - { - "hosts": { - 1($host_id): { - "reinstall_os": True, - "mac": "xxx", - "name": "xxx", - "roles": [xxx, yyy] - }, - "networks": { - "eth0": { - "ip": "192.168.1.1", - "netmask": "255.255.255.0", - "is_mgmt": True, - "is_promiscuous": False, - "subnet": "192.168.1.0/24" - }, - "eth1": {...} - }, - "os_config": {}, - "package_config": {}, - "deployed_os_config": {}, - "deployed_package_config": {} - }, - 2: {...}, - .... - } - } - """ - - hosts_info = {} - for host_id in hosts_id_list: - info = cluster_db.get_cluster_host(cluster_id, host_id, user=user) - logging.debug("checking on info %r %r" % (host_id, info)) - - info[const.ROLES] = ActionHelper._get_role_names(info[const.ROLES]) - - # TODO(grace): Is following line necessary?? - info.setdefault(const.ROLES, []) - - config = cluster_db.get_cluster_host_config(cluster_id, - host_id, - user=user) - info.update(config) - - networks = info[const.NETWORKS] - networks_dict = {} - # Convert networks from list to dictionary format - for entry in networks: - nic_info = {} - nic_info = { - entry[const.NIC]: { - const.IP_ADDR: entry[const.IP_ADDR], - const.NETMASK: entry[const.NETMASK], - const.MGMT_NIC_FLAG: entry[const.MGMT_NIC_FLAG], - const.PROMISCUOUS_FLAG: entry[const.PROMISCUOUS_FLAG], - const.SUBNET: entry[const.SUBNET] - } - } - networks_dict.update(nic_info) - - info[const.NETWORKS] = networks_dict - - hosts_info[host_id] = info - - return hosts_info - - @staticmethod - def save_deployed_config(deployed_config, user): - """Save deployed config.""" - cluster_config = deployed_config[const.CLUSTER] - cluster_id = cluster_config[const.ID] - del cluster_config[const.ID] - - cluster_db.update_cluster_deployed_config(cluster_id, user=user, - **cluster_config) - - hosts_id_list = deployed_config[const.HOSTS].keys() - for host_id in hosts_id_list: - config = deployed_config[const.HOSTS][host_id] - cluster_db.update_cluster_host_deployed_config(cluster_id, - host_id, - user=user, - **config) - - @staticmethod - def update_state( - cluster_id, host_id_list, user, **kwargs - ): - # update all clusterhosts state - for host_id in host_id_list: - cluster_db.update_cluster_host_state( - cluster_id, - host_id, - user=user, - **kwargs - ) - - # update cluster state - cluster_db.update_cluster_state( - cluster_id, - user=user, - **kwargs - ) - - @staticmethod - def delete_cluster( - cluster_id, host_id_list, user, delete_underlying_host=False - ): - """Delete cluster. - - If delete_underlying_host is set, underlying hosts will also - be deleted. - """ - if delete_underlying_host: - for host_id in host_id_list: - host_db.del_host( - host_id, True, True, user=user - ) - cluster_db.del_cluster( - cluster_id, True, True, user=user - ) - - @staticmethod - def delete_cluster_host( - cluster_id, host_id, user, delete_underlying_host=False - ): - """Delete clusterhost. - - If delete_underlying_host set, also delete underlying host. - """ - if delete_underlying_host: - host_db.del_host( - host_id, True, True, user=user - ) - cluster_db.del_cluster_host( - cluster_id, host_id, True, True, user=user - ) - - @staticmethod - def delete_host(host_id, user): - host_db.del_host( - host_id, True, True, user=user - ) - - @staticmethod - def host_ready(host_id, from_database_only, user): - """Trigger host ready.""" - host_db.update_host_state_internal( - host_id, from_database_only=from_database_only, - user=user, ready=True - ) - - @staticmethod - def cluster_host_ready( - cluster_id, host_id, from_database_only, user - ): - """Trigger clusterhost ready.""" - cluster_db.update_cluster_host_state_internal( - cluster_id, host_id, from_database_only=from_database_only, - user=user, ready=True - ) - - @staticmethod - def is_cluster_os_ready(cluster_id, user=None): - return cluster_db.is_cluster_os_ready(cluster_id, user=user) - - @staticmethod - def cluster_ready(cluster_id, from_database_only, user): - """Trigger cluster ready.""" - cluster_db.update_cluster_state_internal( - cluster_id, from_database_only=from_database_only, - user=user, ready=True - ) - - @staticmethod - def get_machine_IPMI(machine_id, user): - machine_info = machine_db.get_machine(machine_id, user=user) - return machine_info[const.IPMI_CREDS] -- cgit 1.2.3-korg