diff options
author | Harry Huang <huangxiangyu5@huawei.com> | 2017-11-17 14:53:44 +0800 |
---|---|---|
committer | Harry Huang <huangxiangyu5@huawei.com> | 2017-12-21 16:36:30 +0800 |
commit | 8646b8d62cf4ca7b6bccae537a0c9e72ba45eab3 (patch) | |
tree | 73a9a983e0dd1423e9df928a78a5023a09d5a7f9 /compass-tasks/deployment/installers/os_installers/cobbler/cobbler.py | |
parent | 6234176ae292a75dcda5520324cb7857d6105988 (diff) |
Merge compass-tasks-osa and compass-tasks-k8s
JIRA: COMPASS-568
rename compass-tasks to compass-tasks-base.
add both osa and k8s support in compass-tasks
Change-Id: I438f5b17e509d4cb751ced0ffe640ec70899882f
Signed-off-by: Harry Huang <huangxiangyu5@huawei.com>
Diffstat (limited to 'compass-tasks/deployment/installers/os_installers/cobbler/cobbler.py')
-rw-r--r-- | compass-tasks/deployment/installers/os_installers/cobbler/cobbler.py | 449 |
1 files changed, 0 insertions, 449 deletions
diff --git a/compass-tasks/deployment/installers/os_installers/cobbler/cobbler.py b/compass-tasks/deployment/installers/os_installers/cobbler/cobbler.py deleted file mode 100644 index 9c2a935..0000000 --- a/compass-tasks/deployment/installers/os_installers/cobbler/cobbler.py +++ /dev/null @@ -1,449 +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. - -"""os installer cobbler plugin. -""" -import logging -import os -import shutil -import xmlrpclib - -from compass.deployment.installers.installer import OSInstaller -from compass.deployment.utils import constants as const -from compass.utils import setting_wrapper as compass_setting -from compass.utils import util -from copy import deepcopy - - -NAME = 'CobblerInstaller' - - -class CobblerInstaller(OSInstaller): - """cobbler installer""" - CREDENTIALS = "credentials" - USERNAME = 'username' - PASSWORD = 'password' - - INSTALLER_URL = "cobbler_url" - TMPL_DIR = 'tmpl_dir' - SYS_TMPL = 'system.tmpl' - SYS_TMPL_NAME = 'system.tmpl' - SYS_PROFILE_NAME = 'profile.tmpl' - PROFILE = 'profile' - - POWER_TYPE = 'power_type' - POWER_ADDR = 'power_address' - POWER_USER = 'power_user' - POWER_PASS = 'power_pass' - - def __init__(self, config_manager): - super(CobblerInstaller, self).__init__() - - self.config_manager = config_manager - installer_settings = self.config_manager.get_os_installer_settings() - try: - username = installer_settings[self.CREDENTIALS][self.USERNAME] - password = installer_settings[self.CREDENTIALS][self.PASSWORD] - cobbler_url = installer_settings[self.INSTALLER_URL] - self.tmpl_dir = CobblerInstaller.get_tmpl_path() - - except KeyError as ex: - raise KeyError(ex.message) - - # The connection is created when cobbler installer is initialized. - self.remote = self._get_cobbler_server(cobbler_url) - self.token = self._get_token(username, password) - self.pk_installer_config = None - - logging.debug('%s instance created', 'CobblerInstaller') - - @classmethod - def get_tmpl_path(cls): - return os.path.join(compass_setting.TMPL_DIR, 'cobbler') - - def __repr__(self): - return '%r[remote=%r,token=%r' % ( - self.__class__.__name__, self.remote, self.token) - - def _get_cobbler_server(self, cobbler_url): - if not cobbler_url: - logging.error("Cobbler URL is None!") - raise Exception("Cobbler URL cannot be None!") - - return xmlrpclib.Server(cobbler_url) - - def _get_token(self, username, password): - if self.remote is None: - raise Exception("Cobbler remote instance is None!") - return self.remote.login(username, password) - - def get_supported_oses(self): - """get supported os versions. - - note:: - In cobbler, we treat profile name as the indicator - of os version. It is just a simple indicator - and not accurate. - """ - profiles = self.remote.get_profiles() - oses = [] - for profile in profiles: - oses.append(profile['name']) - return oses - - def deploy(self): - """Sync cobbler to catch up the latest update config and start to - - install OS. Return both cluster and hosts deploy configs. The return - format: - { - "cluster": { - "id": 1, - "deployed_os_config": {}, - }, - "hosts": { - 1($clusterhost_id): { - "deployed_os_config": {...}, - }, - .... - } - } - """ - host_ids = self.config_manager.get_hosts_id_list_for_os_installation() - if not host_ids: - # No hosts need to install OS - logging.info("Cobbler: No host needs to install OS.") - return {} - - os_version = self.config_manager.get_os_version() - profile = self._get_profile_from_server(os_version) - - global_vars_dict = self._get_cluster_tmpl_vars_dict() - - self.update_profile_config_to_cobbler(profile, global_vars_dict) - - hosts_deploy_config = {} - - for host_id in host_ids: - hostname = self.config_manager.get_hostname(host_id) - vars_dict = self._get_host_tmpl_vars_dict(host_id, - global_vars_dict, - hostname=hostname, - profile=profile) - - self.update_host_config_to_cobbler(host_id, hostname, vars_dict) - - # set host deploy config - host_config = {} - host_config[const.DEPLOYED_OS_CONFIG] = vars_dict[const.OS_CONFIG] - hosts_deploy_config[host_id] = host_config - - # sync to cobbler and trigger installtion. - self._sync() - - cluster_config = global_vars_dict.setdefault(const.OS_CONFIG, {}) - - return { - const.CLUSTER: { - const.ID: self.config_manager.get_cluster_id(), - const.DEPLOYED_OS_CONFIG: cluster_config - }, - const.HOSTS: hosts_deploy_config - } - - def clean_progress(self): - """clean log files and config for hosts which to deploy.""" - clusterhost_list = self.config_manager.get_host_id_list() - log_dir_prefix = compass_setting.INSTALLATION_LOGDIR[NAME] - - for host_id in clusterhost_list: - hostname = self.config_manager.get_hostname(host_id) - self._clean_log(log_dir_prefix, hostname) - - def redeploy(self): - """redeploy hosts.""" - host_ids = self.config_manager.get_host_id_list() - if not host_ids: - logging.info("Cobbler: hostlist is None, no host is redeployed") - return - for host_id in host_ids: - hostname = self.config_manager.get_hostname(host_id) - sys_id = self._get_create_system(hostname) - if sys_id: - # enable netboot for this host - self._netboot_enabled(sys_id) - - self._sync() - - def set_package_installer_config(self, package_configs): - """Cobbler can install and configure package installer right after - - OS installation compelets by setting package_config info provided - by package installer. - - :param dict package_configs: The dict of config generated by package - installer for each clusterhost. The IDs - of clusterhosts are the keys of - package_configs. - """ - self.pk_installer_config = package_configs - - def _sync(self): - """Sync the updated config to cobbler and trigger installation.""" - try: - self.remote.sync(self.token) - os.system('sudo service rsyslog restart') - except Exception as ex: - logging.debug("Failed to sync cobbler server! Error: %s" % ex) - raise ex - - def dump_system_info(self, host_id): - - hostname = self.config_manager.get_hostname(host_id) - if self.remote is None or not hostname: - logging.info("[dump_system_info]Remote or hostname is None.") - return {} - - return self.remote.get_system_as_rendered(hostname) - - def _generate_system_config(self, host_id, host_vars_dict): - """Generate updated system config from the template. - - :param host_vars_dict: dict of variables for the system template to - generate system config dict for each host. - """ - os_version = self.config_manager.get_os_version() - - tmpl_path = os.path.join( - os.path.join(self.tmpl_dir, os_version), self.SYS_TMPL_NAME - ) - if not os.path.exists(tmpl_path): - err_msg = "Template '%s' does not exists!" % tmpl_path - logging.error(err_msg) - raise Exception(err_msg) - host_vars_dict[const.BASEINFO]['host_id'] = host_id - system_config = self.get_config_from_template(tmpl_path, - host_vars_dict) - - # update package config info to cobbler ksmeta - if self.pk_installer_config and host_id in self.pk_installer_config: - pk_config = self.pk_installer_config[host_id] - ksmeta = system_config.setdefault("ksmeta", {}) - util.merge_dict(ksmeta, pk_config) - system_config["ksmeta"] = ksmeta - - return system_config - - def _generate_profile_config(self, cluster_vars_dict): - os_version = self.config_manager.get_os_version() - tmpl_path = os.path.join( - os.path.join(self.tmpl_dir, os_version), self.SYS_PROFILE_NAME - ) - - return self.get_config_from_template(tmpl_path, cluster_vars_dict) - - def _get_profile_from_server(self, os_version): - """Get profile from cobbler server.""" - result = self.remote.find_profile({'name': os_version}) - if not result: - raise Exception("Cannot find profile for '%s'", os_version) - - profile = result[0] - return profile - - def _get_create_system(self, hostname): - """get system reference id for the host.""" - sys_name = hostname - sys_id = None - system_info = self.remote.find_system({"name": hostname}) - - if not system_info: - # Create a new system - sys_id = self.remote.new_system(self.token) - self.remote.modify_system(sys_id, "name", hostname, self.token) - logging.debug('create new system %s for %s', sys_id, sys_name) - else: - sys_id = self.remote.get_system_handle(sys_name, self.token) - - return sys_id - - def _get_profile_id(self, profilename): - """get profile reference id for the cluster.""" - return self.remote.get_profile_handle(profilename, self.token) - - def _clean_system(self, hostname): - """clean system.""" - sys_name = hostname - try: - self.remote.remove_system(sys_name, self.token) - logging.debug('system %s is removed', sys_name) - except Exception: - logging.debug('no system %s found to remove', sys_name) - - def _update_system_config(self, sys_id, system_config): - """update modify system.""" - for key, value in system_config.iteritems(): - self.remote.modify_system(sys_id, str(key), value, self.token) - - self.remote.save_system(sys_id, self.token) - - def _update_profile_config(self, profile_id, profile_config): - for key, value in profile_config.iteritems(): - self.remote.modify_profile(profile_id, str(key), value, self.token) - - self.remote.save_profile(profile_id, self.token) - - def _netboot_enabled(self, sys_id): - """enable netboot.""" - self.remote.modify_system(sys_id, 'netboot_enabled', True, self.token) - self.remote.save_system(sys_id, self.token) - - def _clean_log(self, log_dir_prefix, system_name): - """clean log.""" - log_dir = os.path.join(log_dir_prefix, system_name) - shutil.rmtree(log_dir, True) - - def update_host_config_to_cobbler(self, host_id, hostname, host_vars_dict): - """update host config and upload to cobbler server.""" - sys_id = self._get_create_system(hostname) - - system_config = self._generate_system_config(host_id, host_vars_dict) - logging.debug('%s system config to update: %s', host_id, system_config) - - self._update_system_config(sys_id, system_config) - self._netboot_enabled(sys_id) - - def update_profile_config_to_cobbler(self, profilename, cluster_vars_dict): - """update profile config and upload to cobbler server.""" - - profile_id = self._get_profile_id(profilename) - - profile_config = self._generate_profile_config(cluster_vars_dict) - logging.debug( - '%s profile config to update: %s', profilename, profile_config - ) - - self._update_profile_config(profile_id, profile_config) - - def delete_hosts(self): - hosts_id_list = self.config_manager.get_host_id_list() - logging.debug('delete hosts %s', hosts_id_list) - for host_id in hosts_id_list: - self.delete_single_host(host_id) - self._sync() - - def delete_single_host(self, host_id): - """Delete the host from cobbler server and clean up the installation - - progress. - """ - hostname = self.config_manager.get_hostname(host_id) - try: - log_dir_prefix = compass_setting.INSTALLATION_LOGDIR[NAME] - self._clean_system(hostname) - self._clean_log(log_dir_prefix, hostname) - except Exception as ex: - logging.error("Deleting host got exception: %s", ex) - logging.exception(ex) - - def _get_host_tmpl_vars_dict(self, host_id, global_vars_dict, **kwargs): - """Generate template variables dictionary.""" - vars_dict = {} - if global_vars_dict: - # Set cluster template vars_dict from cluster os_config. - vars_dict = deepcopy(global_vars_dict) - - # Set hostname, MAC address and hostname, networks, dns and so on. - host_baseinfo = self.config_manager.get_host_baseinfo(host_id) - vars_dict[const.BASEINFO] = host_baseinfo - - # Set profile - if self.PROFILE in kwargs: - profile = kwargs[self.PROFILE] - else: - os_version = self.config_manager.get_os_version() - profile = self._get_profile_from_server(os_version) - - vars_dict[const.BASEINFO][self.PROFILE] = profile - - metadata = self.config_manager.get_os_config_metadata() - os_config = self.config_manager.get_host_os_config(host_id) - - # Get template variables values from host os_config - host_vars_dict = self.get_tmpl_vars_from_metadata(metadata, os_config) - util.merge_dict( - vars_dict.setdefault(const.OS_CONFIG, {}), host_vars_dict - ) - return vars_dict - - def _get_cluster_tmpl_vars_dict(self): - metadata = self.config_manager.get_os_config_metadata() - os_config = self.config_manager.get_cluster_os_config() - - cluster_vas_dict = {} - cluster_vas_dict[const.OS_CONFIG] = \ - self.get_tmpl_vars_from_metadata(metadata, os_config) - - return cluster_vas_dict - - def _check_and_set_system_impi(self, host_id, sys_id): - if not sys_id: - logging.info("System is None!") - return False - - system = self.dump_system_info(host_id) - if system[self.POWER_TYPE] != 'ipmilan' or not system[self.POWER_USER]: - # Set sytem power type to ipmilan if needs and set IPMI info - ipmi_info = self.config_manager.get_host_ipmi_info(host_id) - if not ipmi_info: - logging.info('No IPMI information found! Failed power on.') - return False - - ipmi_ip, ipmi_user, ipmi_pass = ipmi_info - power_opts = {} - power_opts[self.POWER_TYPE] = 'ipmilan' - power_opts[self.POWER_ADDR] = ipmi_ip - power_opts[self.POWER_USER] = ipmi_user - power_opts[self.POWER_PASS] = ipmi_pass - - self._update_system_config(sys_id, power_opts) - - return True - - def poweron(self, host_id): - hostname = self.config_manager.get_hostname(host_id) - sys_id = self._get_create_system(hostname) - if not self._check_and_set_system_impi(sys_id): - return - - self.remote.power_system(sys_id, self.token, power='on') - logging.info("Host with ID=%d starts to power on!" % host_id) - - def poweroff(self, host_id): - hostname = self.config_manager.get_hostname(host_id) - sys_id = self._get_create_system(hostname) - if not self._check_and_set_system_impi(sys_id): - return - - self.remote.power_system(sys_id, self.token, power='off') - logging.info("Host with ID=%d starts to power off!" % host_id) - - def reset(self, host_id): - hostname = self.config_manager.get_hostname(host_id) - sys_id = self._get_create_system(hostname) - if not self._check_and_set_system_impi(sys_id): - return - - self.remote.power_system(sys_id, self.token, power='reboot') - logging.info("Host with ID=%d starts to reboot!" % host_id) |