%PDF- %PDF-
Direktori : /lib/python2.7/site-packages/salt/modules/inspectlib/ |
Current File : //lib/python2.7/site-packages/salt/modules/inspectlib/kiwiproc.py |
# -*- coding: utf-8 -*- # # Copyright 2016 SUSE LLC # # 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. # Import python libs from __future__ import absolute_import import os from xml.dom import minidom import platform import socket try: import grp import pwd except ImportError: pass # Import salt libs import salt.utils.files from salt.modules.inspectlib.exceptions import InspectorKiwiProcessorException # Import third party libs try: from lxml import etree except ImportError: from salt._compat import ElementTree as etree class KiwiExporter(object): ''' Exports system description as Kiwi configuration. ''' def __init__(self, grains, format): self.__grains__ = grains self.format = format self._data = type('data', (), {}) self.name = None def load(self, **descr): ''' Load data by keys. :param data: :return: ''' for obj, data in descr.items(): setattr(self._data, obj, data) return self def export(self, name): ''' Export to the Kiwi config.xml as text. :return: ''' self.name = name root = self._create_doc() self._set_description(root) self._set_preferences(root) self._set_repositories(root) self._set_users(root) self._set_packages(root) return '\n'.join([line for line in minidom.parseString( etree.tostring(root, encoding='UTF-8', pretty_print=True)).toprettyxml(indent=" ").split("\n") if line.strip()]) def _get_package_manager(self): ''' Get package manager. :return: ''' ret = None if self.__grains__.get('os_family') in ('Kali', 'Debian'): ret = 'apt-get' elif self.__grains__.get('os_family', '') == 'Suse': ret = 'zypper' elif self.__grains__.get('os_family', '') == 'redhat': ret = 'yum' if ret is None: raise InspectorKiwiProcessorException('Unsupported platform: {0}'.format(self.__grains__.get('os_family'))) return ret def _set_preferences(self, node): ''' Set preferences. :return: ''' pref = etree.SubElement(node, 'preferences') pacman = etree.SubElement(pref, 'packagemanager') pacman.text = self._get_package_manager() p_version = etree.SubElement(pref, 'version') p_version.text = '0.0.1' p_type = etree.SubElement(pref, 'type') p_type.set('image', 'vmx') for disk_id, disk_data in self._data.system.get('disks', {}).items(): if disk_id.startswith('/dev'): p_type.set('filesystem', disk_data.get('type') or 'ext3') break p_type.set('installiso', 'true') p_type.set('boot', "vmxboot/suse-leap42.1") p_type.set('format', self.format) p_type.set('bootloader', 'grub2') p_type.set('timezone', __salt__['timezone.get_zone']()) p_type.set('hwclock', __salt__['timezone.get_hwclock']()) return pref def _get_user_groups(self, user): ''' Get user groups. :param user: :return: ''' return [g.gr_name for g in grp.getgrall() if user in g.gr_mem] + [grp.getgrgid(pwd.getpwnam(user).pw_gid).gr_name] def _set_users(self, node): ''' Create existing local users. <users group="root"> <user password="$1$wYJUgpM5$RXMMeASDc035eX.NbYWFl0" home="/root" name="root"/> </users> :param node: :return: ''' # Get real local users with the local passwords shadow = {} with salt.utils.files.fopen('/etc/shadow') as rfh: for sh_line in rfh.read().split(os.linesep): if sh_line.strip(): login, pwd = sh_line.split(":")[:2] if pwd and pwd[0] not in '!*': shadow[login] = {'p': pwd} with salt.utils.files.fopen('/etc/passwd') as rfh: for ps_line in rfh.read().split(os.linesep): if ps_line.strip(): ps_line = ps_line.strip().split(':') if ps_line[0] in shadow: shadow[ps_line[0]]['h'] = ps_line[5] shadow[ps_line[0]]['s'] = ps_line[6] shadow[ps_line[0]]['g'] = self._get_user_groups(ps_line[0]) users_groups = [] users_node = etree.SubElement(node, 'users') for u_name, u_data in shadow.items(): user_node = etree.SubElement(users_node, 'user') user_node.set('password', u_data['p']) user_node.set('home', u_data['h']) user_node.set('name', u_name) users_groups.extend(u_data['g']) users_node.set('group', ','.join(users_groups)) return users_node def _set_repositories(self, node): ''' Create repositories. :param node: :return: ''' priority = 99 for repo_id, repo_data in self._data.software.get('repositories', {}).items(): if type(repo_data) == list: repo_data = repo_data[0] if repo_data.get('enabled') or not repo_data.get('disabled'): # RPM and Debian, respectively uri = repo_data.get('baseurl', repo_data.get('uri')) if not uri: continue repo = etree.SubElement(node, 'repository') if self.__grains__.get('os_family') in ('Kali', 'Debian'): repo.set('alias', repo_id) repo.set('distribution', repo_data['dist']) else: repo.set('alias', repo_data['alias']) if self.__grains__.get('os_family', '') == 'Suse': repo.set('type', 'yast2') # TODO: Check for options! repo.set('priority', str(priority)) source = etree.SubElement(repo, 'source') source.set('path', uri) # RPM and Debian, respectively priority -= 1 def _set_packages(self, node): ''' Set packages and collections. :param node: :return: ''' pkgs = etree.SubElement(node, 'packages') for pkg_name, pkg_version in sorted(self._data.software.get('packages', {}).items()): pkg = etree.SubElement(pkgs, 'package') pkg.set('name', pkg_name) # Add collections (SUSE) if self.__grains__.get('os_family', '') == 'Suse': for ptn_id, ptn_data in self._data.software.get('patterns', {}).items(): if ptn_data.get('installed'): ptn = etree.SubElement(pkgs, 'namedCollection') ptn.set('name', ptn_id) return pkgs def _set_description(self, node): ''' Create a system description. :return: ''' hostname = socket.getfqdn() or platform.node() descr = etree.SubElement(node, 'description') author = etree.SubElement(descr, 'author') author.text = "salt.modules.node on {0}".format(hostname) contact = etree.SubElement(descr, 'contact') contact.text = 'root@{0}'.format(hostname) specs = etree.SubElement(descr, 'specification') specs.text = 'Rebuild of {0}, based on Salt inspection.'.format(hostname) return descr def _create_doc(self): ''' Create document. :return: ''' root = etree.Element('image') root.set('schemaversion', '6.3') root.set('name', self.name) return root