# -*- coding: utf-8 -*- # # 2011 Steven Armstrong (steven-cdist at armstrong.cc) # 2011-2015 Nico Schottelius (nico-cdist at schottelius.org) # 2016-2017 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 os import sys import re import subprocess import shutil import logging import tempfile import time import datetime import cdist import cdist.message from cdist import core import cdist.exec.util as exec_util CONF_SUBDIRS_LINKED = ["explorer", "files", "manifest", "type", ] 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, target_host_tags, base_root_path, host_dir_name, exec_path=sys.argv[0], initial_manifest=None, add_conf_dirs=None, cache_path_pattern=None, quiet_mode=False): self.target_host = target_host if target_host_tags is None: self.target_host_tags = "" else: self.target_host_tags = ",".join(target_host_tags) self.hostdir = host_dir_name self.base_path = os.path.join(base_root_path, "data") self.exec_path = exec_path self.custom_initial_manifest = initial_manifest self._add_conf_dirs = add_conf_dirs self.cache_path_pattern = cache_path_pattern self.quiet_mode = quiet_mode self._init_log() self._init_permissions() self.mkdir(self.base_path) # FIXME: create dir that does not require moving later self._init_cache_dir(None) 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): return cdist.home_dir() def _init_log(self): self.log = logging.getLogger(self.target_host[0]) # logger is not pickable, so remove it when we pickle def __getstate__(self): state = self.__dict__.copy() if 'log' in state: del state['log'] return state # recreate logger when we unpickle def __setstate__(self, state): self.__dict__.update(state) self._init_log() 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") self.files_path = os.path.join(self.conf_path, "files") # 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'(?