cdist configuration management
Latest manual: https://www.cdi.st/manual/latest/
Home page: https://www.cdi.st
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
154 lines
5.4 KiB
154 lines
5.4 KiB
# -*- coding: utf-8 -*- |
|
# |
|
# 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 <http://www.gnu.org/licenses/>. |
|
# |
|
# |
|
|
|
import cdist |
|
# needed for cdist.argparse |
|
import cdist.banner |
|
import cdist.config |
|
import cdist.install |
|
import cdist.shell |
|
import cdist.inventory |
|
import cdist.argparse |
|
import cdist.log |
|
import cdist.config |
|
import cdist.install |
|
import sys |
|
import os |
|
import os.path |
|
import collections |
|
import uuid |
|
import shutil |
|
|
|
|
|
def find_cdist_exec_in_path(): |
|
"""Search cdist executable in os.get_exec_path() entries. |
|
""" |
|
for path in os.get_exec_path(): |
|
cdist_path = os.path.join(path, 'cdist') |
|
if os.access(cdist_path, os.X_OK): |
|
return cdist_path |
|
return None |
|
|
|
|
|
_mydir = os.path.dirname(__file__) |
|
|
|
|
|
def find_cdist_exec(): |
|
"""Search cdist executable starting from local lib directory. |
|
|
|
Detect if ../scripts/cdist (from local lib direcotry) exists and |
|
if it is executable. If not then try to find cdist exec path in |
|
os.get_exec_path() entries. If no cdist path is found rasie |
|
cdist.Error. |
|
""" |
|
cdist_path = os.path.abspath(os.path.join(_mydir, '..', 'scripts', |
|
'cdist')) |
|
if os.access(cdist_path, os.X_OK): |
|
return cdist_path |
|
cdist_path = find_cdist_exec_in_path() |
|
if not cdist_path: |
|
raise cdist.Error('Cannot find cdist executable from local lib ' |
|
'directory: {}, nor in PATH: {}.'.format( |
|
_mydir, os.environ.get('PATH'))) |
|
return cdist_path |
|
|
|
|
|
ACTION_CONFIG = 'config' |
|
ACTION_INSTALL = 'install' |
|
|
|
|
|
def _process_hosts_simple(action, host, manifest, verbose, |
|
cdist_path=None): |
|
"""Perform cdist action ('config' or 'install') on hosts with specified |
|
manifest using default other cdist options. host parameter can be a |
|
string or iterbale of hosts. verbose is a desired verbosity level |
|
which defaults to VERBOSE_INFO. cdist_path is path to cdist executable, |
|
if it is None then integration lib tries to find it. |
|
""" |
|
if isinstance(host, str): |
|
hosts = [host, ] |
|
elif isinstance(host, collections.Iterable): |
|
hosts = host |
|
else: |
|
raise cdist.Error('Invalid host argument: {}'.format(host)) |
|
|
|
# Setup sys.argv[0] since cdist relies on command line invocation. |
|
if not cdist_path: |
|
cdist_path = find_cdist_exec() |
|
sys.argv[0] = cdist_path |
|
|
|
cname = action.title() |
|
module = getattr(cdist, action) |
|
theclass = getattr(module, cname) |
|
|
|
# Build argv for cdist and use argparse for argument parsing. |
|
remote_out_dir_base = os.path.join('/', 'var', 'lib', 'cdist') |
|
uid = str(uuid.uuid1()) |
|
out_dir = remote_out_dir_base + uid |
|
cache_path_pattern = '%h-' + uid |
|
argv = [action, '-i', manifest, '-r', out_dir, '-C', cache_path_pattern, ] |
|
for i in range(verbose): |
|
argv.append('-v') |
|
for x in hosts: |
|
argv.append(x) |
|
|
|
parser, cfg = cdist.argparse.parse_and_configure(argv, singleton=False) |
|
args = cfg.get_args() |
|
configuration = cfg.get_config(section='GLOBAL') |
|
|
|
theclass.construct_remote_exec_copy_patterns(args) |
|
base_root_path = theclass.create_base_root_path(None) |
|
|
|
for target_host in args.host: |
|
host_base_path, hostdir = theclass.create_host_base_dirs( |
|
target_host, base_root_path) |
|
theclass.onehost(target_host, None, host_base_path, hostdir, args, |
|
parallel=False, configuration=configuration, |
|
remove_remote_files_dirs=True) |
|
shutil.rmtree(base_root_path) |
|
|
|
|
|
def configure_hosts_simple(host, manifest, |
|
verbose=cdist.argparse.VERBOSE_INFO, |
|
cdist_path=None): |
|
"""Configure hosts with specified manifest using default other cdist |
|
options. host parameter can be a string or iterbale of hosts. verbose |
|
is a desired verbosity level which defaults to VERBOSE_INFO. |
|
cdist_path is path to cdist executable, if it is None then integration |
|
lib tries to find it. |
|
""" |
|
_process_hosts_simple(action=ACTION_CONFIG, host=host, |
|
manifest=manifest, verbose=verbose, |
|
cdist_path=cdist_path) |
|
|
|
|
|
def install_hosts_simple(host, manifest, |
|
verbose=cdist.argparse.VERBOSE_INFO, |
|
cdist_path=None): |
|
"""Install hosts with specified manifest using default other cdist |
|
options. host parameter can be a string or iterbale of hosts. verbose |
|
is a desired verbosity level which defaults to VERBOSE_INFO. |
|
cdist_path is path to cdist executable, if it is None then integration |
|
lib tries to find it. |
|
""" |
|
_process_hosts_simple(action=ACTION_INSTALL, host=host, |
|
manifest=manifest, verbose=verbose, |
|
cdist_path=cdist_path)
|
|
|