# -*- coding: utf-8 -*- # # 2011 Steven Armstrong (steven-cdist at armstrong.cc) # 2011-2015 Nico Schottelius (nico-cdist at schottelius.org) # 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 . # # import io import os import sys import re import subprocess import shutil import logging import tempfile import cdist import cdist.message from cdist import core class Local(object): """Execute commands locally. All interaction with the local side should be done through this class. Directly accessing the local side from python code is a bug. """ def __init__(self, target_host, exec_path=sys.argv[0], initial_manifest=None, base_path=None, add_conf_dirs=None): self.target_host = target_host # FIXME: stopped: create base that does not require moving later if base_path: base_path_parent = base_path else: base_path_parent = tempfile.mkdtemp() import atexit atexit.register(lambda: shutil.rmtree(base_path_parent)) self.hostdir = self._hostdir() self.base_path = os.path.join(base_path_parent, self.hostdir) self._init_log() self._init_permissions() self.mkdir(self.base_path) # FIXME: as well self._init_cache_dir(None) self.exec_path = exec_path self.custom_initial_manifest = initial_manifest self._add_conf_dirs = add_conf_dirs self._init_paths() self._init_object_marker() self._init_conf_dirs() @property def dist_conf_dir(self): return os.path.abspath(os.path.join(os.path.dirname(cdist.__file__), "conf")) @property def home_dir(self): if 'HOME' in os.environ: return os.path.join(os.environ['HOME'], ".cdist") else: return None def _hostdir(self): if os.path.isabs(self.target_host): hostdir = self.target_host[1:] else: hostdir = self.target_host return hostdir def _init_log(self): self.log = logging.getLogger(self.target_host) def _init_permissions(self): # Setup file permissions using umask os.umask(0o077) def _init_paths(self): # Depending on out_path self.bin_path = os.path.join(self.base_path, "bin") self.conf_path = os.path.join(self.base_path, "conf") self.global_explorer_out_path = os.path.join(self.base_path, "explorer") self.object_path = os.path.join(self.base_path, "object") self.messages_path = os.path.join(self.base_path, "messages") # Depending on conf_path self.global_explorer_path = os.path.join(self.conf_path, "explorer") self.manifest_path = os.path.join(self.conf_path, "manifest") self.initial_manifest = (self.custom_initial_manifest or os.path.join(self.manifest_path, "init")) self.type_path = os.path.join(self.conf_path, "type") def _init_object_marker(self): self.object_marker_file = os.path.join(self.base_path, "object_marker") # Does not need to be secure - just randomly different from .cdist self.object_marker_name = tempfile.mktemp(prefix='.cdist-', dir='') def _init_conf_dirs(self): self.conf_dirs = [] self.conf_dirs.append(self.dist_conf_dir) # Is the default place for user created explorer, type and manifest if self.home_dir: self.conf_dirs.append(self.home_dir) # Add directories defined in the CDIST_PATH environment variable if 'CDIST_PATH' in os.environ: cdist_path_dirs = re.split(r'(?