cdist/bin/cdist

172 lines
5.7 KiB
Plaintext
Raw Normal View History

#!/usr/bin/env python3
#
# 2010-2011 Nico Schottelius (nico-cdist at schottelius.org)
#
# 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 sys
import subprocess # execute stuff
import os
import tempfile
import shutil
import logging
BASE_DIR = os.path.abspath(os.path.join(os.path.dirname(__file__), os.pardir))
logging.basicConfig(level=logging.DEBUG, format='%(levelname)s: %(message)s')
class Cdist:
"""Cdist main class to hold arbitrary data"""
version="2.0.0"
def __init__(self, hostname):
self.hostname = hostname
# Setup directory paths
self.temp_dir = tempfile.mkdtemp()
self.out_dir = os.path.join(self.temp_dir, "out")
os.mkdir(self.out_dir)
self.global_explorer_out_dir = os.path.join(self.out_dir, "explorer")
os.mkdir(self.global_explorer_out_dir)
# Given paths from installation
self.conf_dir = os.path.join(self.base_dir, "conf")
def cleanup(self):
# Do not use in __del__:
# http://docs.python.org/reference/datamodel.html#customization
# "other globals referenced by the __del__() method may already have been deleted
# or in the process of being torn down (e.g. the import machinery shutting down)"
#
print(self.tempdir)
shutil.rmtree(self.tempdir)
def logger(self,type, *args):
"""Ignore type for now, support later"""
print(*args)
def exit_error(self,*args):
self.logger("error", *args)
sys.exit(1)
def run_or_fail(self,*args, **kargs):
# newargs = ["echo"]
newargs = []
newargs.extend(*args)
print(newargs)
try:
subprocess.check_call(newargs, **kargs)
except subprocess.CalledProcessError:
self.exit_error("Command failed:", " ".join(newargs))
def remote_run_or_fail(self, *args, **kargs):
"""Run something on the remote side and fail is something breaks"""
newargs = ["ssh", "root@" + self.hostname]
newargs.extend(*args)
self.run_or_fail(newargs, **kargs)
def remove_remote_dir(self, destination):
self.remote_run_or_fail(["rm", "-rf", destination])
def transfer_dir(self, source, destination):
self.remove_remote_dir(destination)
self.run_or_fail(["scp", "-qr", source, "root@" + self.hostname + ":" + destination])
def remote_base_directory(self):
return "/var/lib/cdist"
def remote_conf_directory(self):
"""Returns path to remote main configuration directory"""
return os.path.join(self.remote_base_directory(), "conf")
def global_explorer_directory(self):
"""Returns path to directory containing the global explorers"""
return os.path.join(self.conf_directory(), "explorer")
def remote_global_explorer_directory(self):
"""Returns path to the remote directory containing the global explorers"""
return os.path.join(self.remote_conf_directory(), "explorer")
def remote_global_explorer_path(self,explorer):
"""Returns path to the remote explorer"""
return os.path.join(self.remote_global_explorer_directory(), explorer)
def global_explorer_output_path(self, explorer):
"""Returns path of the output for a global explorer"""
return os.path.join(self.global_explorer_out_dir, explorer)
def list_global_explorers(self):
"""Return list of available explorers"""
return os.listdir(self.global_explorer_directory())
def transfer_global_explorers(self):
self.transfer_dir(self.global_explorer_directory(), self.remote_global_explorer_directory())
def global_explore(self):
"""Run global explorers"""
explorers = self.list_global_explorers()
if(len(explorers) == 0):
self.exit_error("No explorers found in", self.global_explorer_directory())
self.transfer_global_explorers()
for explorer in explorers:
output = self.global_explorer_output_path(explorer)
output_fd = open(output, mode='w')
self.remote_run_or_fail([self.remote_global_explorer_path(explorer)], stdout=output_fd)
output_fd.close()
def init_deploy(self):
self.logger("info", "Creating clean directory structure")
# Ensure there is no old stuff, neither local nor remote
# run_or_fail(["rm -rf", "$__cdist_local_base_dir"])
#
# remote_run_or_fail(hostname, ["rm -rf", "${__cdist_remote_base_dir}"])
#
# # Create base directories
# run_or_fail(["mkdir -p", "$__cdist_local_base_dir"])
# remote_run_or_fail(hostname,["mkdir -p", "${__cdist_remote_base_dir}"])
#
# # Link configuraion source directory - consistent with remote
# run_or_fail(["ln -sf", "$__cdist_conf_dir", "$__cdist_local_base_dir/$__cdist_name_conf_dir"])
def deploy_to(self):
"""Mimic the old deploy to: Deploy to one host"""
self.logger("info", "Deploying to host", self.hostname)
self.init_deploy()
self.global_explore()
if __name__ == "__main__":
hostname=sys.argv[1]
# logger("info", "cdist", cdist_version, ": Configuring host", hostname)
for host in sys.argv[1:]:
c = Cdist(host)
c.deploy_to()
print(c.list_global_explorers())
c.cleanup()