# -*- 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 io 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, base_root_path, host_dir_name, exec_path=sys.argv[0], initial_manifest=None, add_conf_dirs=None, cache_path_pattern=None): self.target_host = target_host 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._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'(?