forked from ungleich-public/cdist
		
	ugly -> bad
This commit is contained in:
		
					parent
					
						
							
								8c53ce78f5
							
						
					
				
			
			
				commit
				
					
						e6fc74c081
					
				
			
		
					 4 changed files with 146 additions and 94 deletions
				
			
		| 
						 | 
				
			
			@ -22,15 +22,14 @@
 | 
			
		|||
 | 
			
		||||
import logging
 | 
			
		||||
import os
 | 
			
		||||
import shutil
 | 
			
		||||
import sys
 | 
			
		||||
import time
 | 
			
		||||
import pprint
 | 
			
		||||
import itertools
 | 
			
		||||
import tempfile
 | 
			
		||||
import socket
 | 
			
		||||
 | 
			
		||||
import cdist
 | 
			
		||||
import cdist.hostsource
 | 
			
		||||
 | 
			
		||||
import cdist.exec.local
 | 
			
		||||
import cdist.exec.remote
 | 
			
		||||
| 
						 | 
				
			
			@ -61,55 +60,17 @@ class Config(object):
 | 
			
		|||
        self.local.create_files_dirs()
 | 
			
		||||
        self.remote.create_files_dirs()
 | 
			
		||||
 | 
			
		||||
    @staticmethod
 | 
			
		||||
    def hostfile_process_line(line):
 | 
			
		||||
        """Return host from read line or None if no host present."""
 | 
			
		||||
        if not line:
 | 
			
		||||
            return None
 | 
			
		||||
        # remove comment if present
 | 
			
		||||
        comment_index = line.find('#')
 | 
			
		||||
        if comment_index >= 0:
 | 
			
		||||
            host = line[:comment_index]
 | 
			
		||||
        else:
 | 
			
		||||
            host = line
 | 
			
		||||
        # remove leading and trailing whitespaces
 | 
			
		||||
        host = host.strip()
 | 
			
		||||
        # skip empty lines
 | 
			
		||||
        if host:
 | 
			
		||||
            return host
 | 
			
		||||
        else:
 | 
			
		||||
            return None
 | 
			
		||||
 | 
			
		||||
    @staticmethod
 | 
			
		||||
    def hosts(source):
 | 
			
		||||
        """Yield hosts from source.
 | 
			
		||||
           Source can be a sequence or filename (stdin if \'-\').
 | 
			
		||||
           In case of filename each line represents one host.
 | 
			
		||||
        """
 | 
			
		||||
        if isinstance(source, str):
 | 
			
		||||
            import fileinput
 | 
			
		||||
        try:
 | 
			
		||||
                for host in fileinput.input(files=(source)):
 | 
			
		||||
                    host = Config.hostfile_process_line(host)
 | 
			
		||||
                    if host:
 | 
			
		||||
                        yield host
 | 
			
		||||
            yield from cdist.hostsource.HostSource(source)()
 | 
			
		||||
        except (IOError, OSError, UnicodeError) as e:
 | 
			
		||||
            raise cdist.Error(
 | 
			
		||||
                        "Error reading hosts from file \'{}\': {}".format(
 | 
			
		||||
                    "Error reading hosts from \'{}\': {}".format(
 | 
			
		||||
                        source, e))
 | 
			
		||||
        else:
 | 
			
		||||
            if source:
 | 
			
		||||
                for host in source:
 | 
			
		||||
                    yield host
 | 
			
		||||
 | 
			
		||||
    @classmethod
 | 
			
		||||
    def commandline(cls, args):
 | 
			
		||||
        """Configure remote system"""
 | 
			
		||||
        import multiprocessing
 | 
			
		||||
 | 
			
		||||
        # FIXME: Refactor relict - remove later
 | 
			
		||||
        log = logging.getLogger("cdist")
 | 
			
		||||
 | 
			
		||||
    def _check_and_prepare_args(cls, args):
 | 
			
		||||
        if args.manifest == '-' and args.hostfile == '-':
 | 
			
		||||
            raise cdist.Error(("Cannot read both, manifest and host file, "
 | 
			
		||||
                               "from stdin"))
 | 
			
		||||
| 
						 | 
				
			
			@ -134,10 +95,6 @@ class Config(object):
 | 
			
		|||
            import atexit
 | 
			
		||||
            atexit.register(lambda: os.remove(initial_manifest_temp_path))
 | 
			
		||||
 | 
			
		||||
        process = {}
 | 
			
		||||
        failed_hosts = []
 | 
			
		||||
        time_start = time.time()
 | 
			
		||||
 | 
			
		||||
        # default remote cmd patterns
 | 
			
		||||
        args.remote_exec_pattern = None
 | 
			
		||||
        args.remote_copy_pattern = None
 | 
			
		||||
| 
						 | 
				
			
			@ -154,10 +111,29 @@ class Config(object):
 | 
			
		|||
            if args_dict['remote_copy'] is None:
 | 
			
		||||
                args.remote_copy_pattern = cdist.REMOTE_COPY + mux_opts
 | 
			
		||||
 | 
			
		||||
    @classmethod
 | 
			
		||||
    def _base_root_path(cls, args):
 | 
			
		||||
        if args.out_path:
 | 
			
		||||
            base_root_path = args.out_path
 | 
			
		||||
        else:
 | 
			
		||||
            base_root_path = tempfile.mkdtemp()
 | 
			
		||||
        return base_root_path
 | 
			
		||||
 | 
			
		||||
    @classmethod
 | 
			
		||||
    def commandline(cls, args):
 | 
			
		||||
        """Configure remote system"""
 | 
			
		||||
        import multiprocessing
 | 
			
		||||
 | 
			
		||||
        # FIXME: Refactor relict - remove later
 | 
			
		||||
        log = logging.getLogger("cdist")
 | 
			
		||||
 | 
			
		||||
        cls._check_and_prepare_args(args)
 | 
			
		||||
 | 
			
		||||
        process = {}
 | 
			
		||||
        failed_hosts = []
 | 
			
		||||
        time_start = time.time()
 | 
			
		||||
 | 
			
		||||
        base_root_path = cls._base_root_path(args)
 | 
			
		||||
 | 
			
		||||
        hostcnt = 0
 | 
			
		||||
        for host in itertools.chain(cls.hosts(args.host),
 | 
			
		||||
| 
						 | 
				
			
			@ -200,12 +176,7 @@ class Config(object):
 | 
			
		|||
                              " ".join(failed_hosts))
 | 
			
		||||
 | 
			
		||||
    @classmethod
 | 
			
		||||
    def onehost(cls, host, host_base_path, host_dir_name, args, parallel):
 | 
			
		||||
        """Configure ONE system"""
 | 
			
		||||
 | 
			
		||||
        log = logging.getLogger(host)
 | 
			
		||||
 | 
			
		||||
        try:
 | 
			
		||||
    def _resolve_remote_cmds(cls, args, host_base_path):
 | 
			
		||||
        control_path = os.path.join(host_base_path, "ssh-control-path")
 | 
			
		||||
        # If we constructed patterns for remote commands then there is
 | 
			
		||||
        # placeholder for ssh ControlPath, format it and we have unique
 | 
			
		||||
| 
						 | 
				
			
			@ -220,6 +191,16 @@ class Config(object):
 | 
			
		|||
            remote_copy = args.remote_copy_pattern.format(control_path)
 | 
			
		||||
        else:
 | 
			
		||||
            remote_copy = args.remote_copy
 | 
			
		||||
        return (remote_exec, remote_copy, )
 | 
			
		||||
 | 
			
		||||
    @classmethod
 | 
			
		||||
    def onehost(cls, host, host_base_path, host_dir_name, args, parallel):
 | 
			
		||||
        """Configure ONE system"""
 | 
			
		||||
 | 
			
		||||
        log = logging.getLogger(host)
 | 
			
		||||
 | 
			
		||||
        try:
 | 
			
		||||
            remote_exec, remote_copy = cls._resolve_remote_cmds(host_base_path)
 | 
			
		||||
            log.debug("remote_exec for host \"{}\": {}".format(
 | 
			
		||||
                host, remote_exec))
 | 
			
		||||
            log.debug("remote_copy for host \"{}\": {}".format(
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -30,40 +30,13 @@ import multiprocessing
 | 
			
		|||
 | 
			
		||||
import cdist
 | 
			
		||||
import cdist.exec.util as exec_util
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
# check whether addr is IPv6
 | 
			
		||||
try:
 | 
			
		||||
    # python 3.3+
 | 
			
		||||
    import ipaddress
 | 
			
		||||
 | 
			
		||||
    def _is_ipv6(addr):
 | 
			
		||||
        try:
 | 
			
		||||
            return ipaddress.ip_address(addr).version == 6
 | 
			
		||||
        except ValueError:
 | 
			
		||||
            return False
 | 
			
		||||
except ImportError:
 | 
			
		||||
    # fallback for older python versions
 | 
			
		||||
    import socket
 | 
			
		||||
 | 
			
		||||
    def _is_ipv6(addr):
 | 
			
		||||
        try:
 | 
			
		||||
            socket.inet_aton(addr)
 | 
			
		||||
            return False
 | 
			
		||||
        except socket.error:
 | 
			
		||||
            pass
 | 
			
		||||
        try:
 | 
			
		||||
            socket.inet_pton(socket.AF_INET6, addr)
 | 
			
		||||
            return True
 | 
			
		||||
        except socket.error:
 | 
			
		||||
            pass
 | 
			
		||||
        return False
 | 
			
		||||
import cdist.util.ipaddr as ipaddr
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
def _wrap_addr(addr):
 | 
			
		||||
    """If addr is IPv6 then return addr wrapped between '[' and ']',
 | 
			
		||||
    otherwise return it intact."""
 | 
			
		||||
    if _is_ipv6(addr):
 | 
			
		||||
    if ipaddr.is_ipv6(addr):
 | 
			
		||||
        return "".join(("[", addr, "]", ))
 | 
			
		||||
    else:
 | 
			
		||||
        return addr
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
							
								
								
									
										72
									
								
								cdist/hostsource.py
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										72
									
								
								cdist/hostsource.py
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,72 @@
 | 
			
		|||
# -*- coding: utf-8 -*-
 | 
			
		||||
#
 | 
			
		||||
# 2016 Darko Poljak (darko.poljak at gmail.com)
 | 
			
		||||
#
 | 
			
		||||
# This file is part of cdist.
 | 
			
		||||
#
 | 
			
		||||
# cdist is free software: you can redistribute it and/or modify
 | 
			
		||||
# it under the terms of the GNU General Public License as published by
 | 
			
		||||
# the Free Software Foundation, either version 3 of the License, or
 | 
			
		||||
# (at your option) any later version.
 | 
			
		||||
#
 | 
			
		||||
# cdist is distributed in the hope that it will be useful,
 | 
			
		||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
 | 
			
		||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 | 
			
		||||
# GNU General Public License for more details.
 | 
			
		||||
#
 | 
			
		||||
# You should have received a copy of the GNU General Public License
 | 
			
		||||
# along with cdist. If not, see <http://www.gnu.org/licenses/>.
 | 
			
		||||
#
 | 
			
		||||
#
 | 
			
		||||
 | 
			
		||||
import fileinput
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class HostSource(object):
 | 
			
		||||
    """
 | 
			
		||||
    Host source object.
 | 
			
		||||
    Source can be a sequence or filename (stdin if \'-\').
 | 
			
		||||
    In case of filename each line represents one host.
 | 
			
		||||
    """
 | 
			
		||||
    def __init__(self, source):
 | 
			
		||||
        self.source = source
 | 
			
		||||
 | 
			
		||||
    def _process_file_line(self, line):
 | 
			
		||||
        """Return host from read line or None if no host present."""
 | 
			
		||||
        if not line:
 | 
			
		||||
            return None
 | 
			
		||||
        # remove comment if present
 | 
			
		||||
        comment_index = line.find('#')
 | 
			
		||||
        if comment_index >= 0:
 | 
			
		||||
            host = line[:comment_index]
 | 
			
		||||
        else:
 | 
			
		||||
            host = line
 | 
			
		||||
        # remove leading and trailing whitespaces
 | 
			
		||||
        host = host.strip()
 | 
			
		||||
        # skip empty lines
 | 
			
		||||
        if host:
 | 
			
		||||
            return host
 | 
			
		||||
        else:
 | 
			
		||||
            return None
 | 
			
		||||
 | 
			
		||||
    def _hosts_from_sequence(self):
 | 
			
		||||
        for host in self.source:
 | 
			
		||||
            yield host
 | 
			
		||||
 | 
			
		||||
    def _hosts_from_file(self):
 | 
			
		||||
        for line in fileinput.input(files=(self.source)):
 | 
			
		||||
            host = self._process_file_line(line)
 | 
			
		||||
            if host:
 | 
			
		||||
                yield host
 | 
			
		||||
 | 
			
		||||
    def hosts(self):
 | 
			
		||||
        if not source:
 | 
			
		||||
            return
 | 
			
		||||
 | 
			
		||||
        if isinstance(self.source, str):
 | 
			
		||||
            yield from self._hosts_from_file()
 | 
			
		||||
        else:
 | 
			
		||||
            yield from self._hosts_from_sequence()
 | 
			
		||||
 | 
			
		||||
    def __call__(self):
 | 
			
		||||
        yield from self.hosts()
 | 
			
		||||
| 
						 | 
				
			
			@ -55,3 +55,29 @@ def resolve_target_addresses(host):
 | 
			
		|||
        host_fqdn = ''
 | 
			
		||||
 | 
			
		||||
    return (host, host_name, host_fqdn)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
# check whether addr is IPv6
 | 
			
		||||
try:
 | 
			
		||||
    # python 3.3+
 | 
			
		||||
    import ipaddress
 | 
			
		||||
 | 
			
		||||
    def is_ipv6(addr):
 | 
			
		||||
        try:
 | 
			
		||||
            return ipaddress.ip_address(addr).version == 6
 | 
			
		||||
        except ValueError:
 | 
			
		||||
            return False
 | 
			
		||||
except ImportError:
 | 
			
		||||
    # fallback for older python versions
 | 
			
		||||
    def is_ipv6(addr):
 | 
			
		||||
        try:
 | 
			
		||||
            socket.inet_aton(addr)
 | 
			
		||||
            return False
 | 
			
		||||
        except socket.error:
 | 
			
		||||
            pass
 | 
			
		||||
        try:
 | 
			
		||||
            socket.inet_pton(socket.AF_INET6, addr)
 | 
			
		||||
            return True
 | 
			
		||||
        except socket.error:
 | 
			
		||||
            pass
 | 
			
		||||
        return False
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue