move out banner, fail at emulator

Signed-off-by: Nico Schottelius <nico@kr.ethz.ch>
This commit is contained in:
Nico Schottelius 2011-09-26 11:05:18 +02:00
parent cf920ca3e9
commit 16d58dcac7
5 changed files with 140 additions and 122 deletions

204
bin/cdist
View file

@ -32,40 +32,7 @@ import stat
import sys
import tempfile
BANNER = """
.. . .x+=:. s
dF @88> z` ^% :8
'88bu. %8P . <k .88
. '*88888bu . .@8Ned8" :888ooo
.udR88N ^"*8888N .@88u .@^%8888" -*8888888
<888'888k beWE "888L ''888E` x88: `)8b. 8888
9888 'Y" 888E 888E 888E 8888N=*8888 8888
9888 888E 888E 888E %8" R88 8888
9888 888E 888F 888E @8Wou 9% .8888Lu=
?8888u../ .888N..888 888& .888888P` ^%888*
"8888P' `"888*"" R888" ` ^"F 'Y"
"P' "" ""
"""
VERSION = "2.0.1"
logging.basicConfig(level=logging.INFO, format='%(levelname)s: %(message)s')
log = logging.getLogger()
def file_to_list(filename):
"""Return list from \n seperated file"""
if os.path.isfile(filename):
file_fd = open(filename, "r")
lines = file_fd.readlines()
file_fd.close()
# Remove \n from all lines
lines = map(lambda s: s.strip(), lines)
else:
lines = []
return lines
log = logging.getLogger(__name__)
class Cdist:
"""Cdist main class to hold arbitrary data"""
@ -73,20 +40,22 @@ class Cdist:
def __init__(self, target_host,
initial_manifest=False, remote_user="root",
home=None, debug=False):
self.target_host = target_host
self.path = cdist.path.Path(target_host,
self.target_host = target_host
self.debug = debug
self.remote_user = remote_user
self.remote_prefix = ["ssh", self.remote_user + "@" + self.target_host]
self.path = cdist.path.Path(self.target_host,
initial_manifest=initial_manifest,
remote_user=remote_user,
remote_user=self.remote_user,
remote_prefix=self.remote_prefix,
base_dir=home,
debug=debug)
self.debug = debug
self.objects_prepared = []
self.remote_user = remote_user
def cleanup(self):
self.path.cleanup()
@ -94,71 +63,69 @@ class Cdist:
"""Run global explorers"""
explorers = self.path.list_global_explorers()
if(len(explorers) == 0):
raise CdistError("No explorers found in", self.global_explorer_dir)
raise CdistError("No explorers found in", self.path.global_explorer_dir)
self.transfer_global_explorers()
self.path.transfer_global_explorers()
for explorer in explorers:
output = self.global_explorer_output_path(explorer)
output = self.path.global_explorer_output_path(explorer)
output_fd = open(output, mode='w')
cmd = []
cmd.append("__explorer=" + REMOTE_GLOBAL_EXPLORER_DIR)
cmd.append(self.remote_global_explorer_path(explorer))
cmd.append("__explorer=" + cdist.path.REMOTE_GLOBAL_EXPLORER_DIR)
cmd.append(self.path.remote_global_explorer_path(explorer))
self.run_or_fail(cmd, stdout=output_fd, remote=True)
cdist.exec.run_or_fail(cmd, stdout=output_fd, remote_prefix=self.remote_prefix)
output_fd.close()
def run_type_explorer(self, cdist_object):
"""Run type specific explorers for objects"""
# Based on bin/cdist-object-explorer-run
# Transfering explorers for this type
type = self.get_type_from_object(cdist_object)
self.transfer_type_explorers(type)
type = self.path.get_type_from_object(cdist_object)
self.path.transfer_type_explorers(type)
cmd = []
cmd.append("__explorer=" + REMOTE_GLOBAL_EXPLORER_DIR)
cmd.append("__type_explorer=" + self.remote_type_explorer_dir(type))
cmd.append("__object=" + self.remote_object_dir(cdist_object))
cmd.append("__object_id=" + self.get_object_id_from_object(cdist_object))
cmd.append("__object_fq=" + cdist_object)
cmd.append("__explorer=" + cdist.path.REMOTE_GLOBAL_EXPLORER_DIR)
cmd.append("__type_explorer=" + self.path.remote_type_explorer_dir(type))
cmd.append("__object=" + self.path.remote_object_dir(cdist_object))
cmd.append("__object_id=" + self.path.get_object_id_from_object(cdist_object))
cmd.append("__object_fq=" + cdist_object)
# Need to transfer at least the parameters for objects to be useful
self.transfer_object_parameter(cdist_object)
self.path.transfer_object_parameter(cdist_object)
explorers = self.list_type_explorers(type)
explorers = self.path.list_type_explorers(type)
for explorer in explorers:
remote_cmd = cmd + [os.path.join(self.remote_type_explorer_dir(type), explorer)]
output = os.path.join(self.type_explorer_output_dir(cdist_object), explorer)
remote_cmd = cmd + [os.path.join(self.path.remote_type_explorer_dir(type), explorer)]
output = os.path.join(self.path.type_explorer_output_dir(cdist_object), explorer)
output_fd = open(output, mode='w')
log.debug("%s exploring %s using %s storing to %s",
cdist_object, explorer, remote_cmd, output)
self.run_or_fail(remote_cmd, stdout=output_fd, remote=True)
self.run_or_fail(remote_cmd, stdout=output_fd, remote_prefix=self.remote_prefix)
output_fd.close()
def init_deploy(self):
"""Ensure the base directories are cleaned up"""
log.debug("Creating clean directory structure")
self.path.remove_remote_dir(REMOTE_BASE_DIR)
self.path.remote_mkdir(REMOTE_BASE_DIR)
self.path.remove_remote_dir(cdist.path.REMOTE_BASE_DIR)
self.path.remote_mkdir(cdist.path.REMOTE_BASE_DIR)
def run_initial_manifest(self):
"""Run the initial manifest"""
env = { "__manifest" : self.manifest_dir }
self.run_manifest(self.initial_manifest, extra_env=env)
env = { "__manifest" : self.path.manifest_dir }
self.run_manifest(self.path.initial_manifest, extra_env=env)
def run_type_manifest(self, cdist_object):
"""Run manifest for a specific object"""
type = self.get_type_from_object(cdist_object)
manifest = self.type_dir(type, "manifest")
type = self.path.get_type_from_object(cdist_object)
manifest = self.path.type_dir(type, "manifest")
log.debug("%s: Running %s", cdist_object, manifest)
if os.path.exists(manifest):
env = { "__object" : self.object_dir(cdist_object),
"__object_id": self.get_object_id_from_object(cdist_object),
"__object_fq": cdist_object,
"__type": self.type_dir(type)
env = { "__object" : self.path.object_dir(cdist_object),
"__object_id": self.path.get_object_id_from_object(cdist_object),
"__object_fq": cdist_object,
"__type": self.path.type_dir(type)
}
self.run_manifest(manifest, extra_env=env)
@ -166,32 +133,32 @@ class Cdist:
"""Run a manifest"""
log.debug("Running manifest %s, env=%s", manifest, extra_env)
env = os.environ.copy()
env['PATH'] = self.bin_dir + ":" + env['PATH']
env['PATH'] = self.path.bin_dir + ":" + env['PATH']
# Information required in every manifest
env['__target_host'] = self.target_host
env['__global'] = self.out_dir
env['__target_host'] = self.target_host
env['__global'] = self.path.out_dir
# Legacy stuff to make cdist-type-emulator work
env['__cdist_core_dir'] = os.path.join(self.base_dir, "core")
env['__cdist_local_base_dir'] = self.temp_dir
env['__cdist_core_dir'] = os.path.join(self.path.base_dir, "core")
env['__cdist_local_base_dir'] = self.path.temp_dir
# Submit information to new type emulator
env['__cdist_manifest'] = manifest
env['__cdist_type_base_dir'] = self.type_base_dir
env['__cdist_type_base_dir'] = self.path.type_base_dir
# Other environment stuff
if extra_env:
env.update(extra_env)
self.shell_run_or_debug_fail(manifest, [manifest], env=env)
cdist.exec.shell_run_or_debug_fail(manifest, [manifest], env=env)
def object_run(self, cdist_object, mode):
"""Run gencode or code for an object"""
log.debug("Running %s from %s", mode, cdist_object)
file=os.path.join(self.object_dir(cdist_object), "require")
requirements = file_to_list(file)
type = self.get_type_from_object(cdist_object)
file=os.path.join(self.path.object_dir(cdist_object), "require")
requirements = cdist.path.file_to_list(file)
type = self.path.get_type_from_object(cdist_object)
for requirement in requirements:
log.debug("Object %s requires %s", cdist_object, requirement)
@ -201,22 +168,22 @@ class Cdist:
# Setup env Variable:
#
env = os.environ.copy()
env['__target_host'] = self.target_host
env['__global'] = self.out_dir
env["__object"] = self.object_dir(cdist_object)
env["__object_id"] = self.get_object_id_from_object(cdist_object)
env["__object_fq"] = cdist_object
env["__type"] = self.type_dir(type)
env['__target_host'] = self.target_host
env['__global'] = self.path.out_dir
env["__object"] = self.path.object_dir(cdist_object)
env["__object_id"] = self.path.get_object_id_from_object(cdist_object)
env["__object_fq"] = cdist_object
env["__type"] = self.path.type_dir(type)
if mode == "gencode":
paths = [
self.type_dir(type, "gencode-local"),
self.type_dir(type, "gencode-remote")
self.path.type_dir(type, "gencode-local"),
self.path.type_dir(type, "gencode-remote")
]
for bin in paths:
if os.path.isfile(bin):
# omit "gen" from gencode and use it for output base
outfile=os.path.join(self.object_dir(cdist_object),
outfile=os.path.join(self.path.object_dir(cdist_object),
os.path.basename(bin)[3:])
outfile_fd = open(outfile, "w")
@ -225,7 +192,7 @@ class Cdist:
outfile_fd.write(CODE_HEADER)
outfile_fd.flush()
self.shell_run_or_debug_fail(bin, [bin], env=env, stdout=outfile_fd)
cdist.exec.shell_run_or_debug_fail(bin, [bin], env=env, stdout=outfile_fd)
outfile_fd.close()
status = os.stat(outfile)
@ -238,23 +205,24 @@ class Cdist:
os.chmod(outfile, stat.S_IXUSR | stat.S_IRUSR | stat.S_IWUSR)
# Mark object as changed
open(os.path.join(self.object_dir(cdist_object), "changed"), "w").close()
open(os.path.join(self.path.object_dir(cdist_object), "changed"), "w").close()
if mode == "code":
local_dir = self.object_dir(cdist_object)
remote_dir = self.remote_object_dir(cdist_object)
local_dir = self.path.object_dir(cdist_object)
remote_dir = self.path.remote_object_dir(cdist_object)
bin = os.path.join(local_dir, "code-local")
if os.path.isfile(bin):
self.run_or_fail([bin], remote=False)
cdist.exec.run_or_fail([bin])
local_remote_code = os.path.join(local_dir, "code-remote")
remote_remote_code = os.path.join(remote_dir, "code-remote")
if os.path.isfile(local_remote_code):
self.transfer_file(local_remote_code, remote_remote_code)
self.run_or_fail([remote_remote_code], remote=True)
self.path.transfer_file(local_remote_code, remote_remote_code)
# FIXME: remote_prefix
cdist.exec.run_or_fail([remote_remote_code], remote_prefix=self.remote_prefix)
def stage_prepare(self):
"""Do everything for a deploy, minus the actual code stage"""
@ -278,13 +246,13 @@ class Cdist:
self.run_type_manifest(cdist_object)
self.objects_prepared.append(cdist_object)
objects = self.list_objects()
objects = self.path.list_objects()
def stage_run(self):
"""The final (and real) step of deployment"""
log.debug("Actual run objects")
# Now do the final steps over the existing objects
for cdist_object in self.list_objects():
for cdist_object in self.path.list_objects():
log.debug("Run object: %s", cdist_object)
self.object_run(cdist_object, mode="gencode")
self.object_run(cdist_object, mode="code")
@ -308,11 +276,6 @@ class Cdist:
self.deploy_to()
self.cleanup()
def banner(args):
"""Guess what :-)"""
print(BANNER)
sys.exit(0)
def config(args):
"""Configure remote system"""
process = {}
@ -343,11 +306,11 @@ def install(args):
def emulator():
"""Emulate type commands (i.e. __file and co)"""
type = os.path.basename(sys.argv[0])
type_dir = os.path.join(os.environ['__cdist_type_base_dir'], type)
param_dir = os.path.join(type_dir, "parameter")
global_dir = os.environ['__global']
object_source = os.environ['__cdist_manifest']
type = os.path.basename(sys.argv[0])
type_dir = os.path.join(os.environ['__cdist_type_base_dir'], type)
param_dir = os.path.join(type_dir, "parameter")
global_dir = os.environ['__global']
object_source = os.environ['__cdist_manifest']
parser = argparse.ArgumentParser(add_help=False)
@ -457,16 +420,16 @@ def commandline():
help='Set log level to debug', action='store_true')
# Main subcommand parser
parser['main'] = argparse.ArgumentParser(description='cdist ' + VERSION)
parser['main'] = argparse.ArgumentParser(description='cdist ' + cdist.VERSION)
parser['main'].add_argument('-V', '--version',
help='Show version', action='version',
version='%(prog)s ' + VERSION)
version='%(prog)s ' + cdist.VERSION)
parser['sub'] = parser['main'].add_subparsers(title="Commands")
# Banner
parser['banner'] = parser['sub'].add_parser('banner',
add_help=False)
parser['banner'].set_defaults(func=banner)
parser['banner'].set_defaults(func=cdist.banner.banner)
# Config and install (common stuff)
parser['configinstall'] = argparse.ArgumentParser(add_help=False)
@ -511,19 +474,24 @@ def commandline():
if __name__ == "__main__":
try:
if re.match(TYPE_PREFIX, os.path.basename(sys.argv[0])):
logging.basicConfig(level=logging.INFO, format='%(levelname)s: %(message)s')
# Import generic cdist options
sys.path.insert(0,
os.path.abspath(os.path.join(os.path.dirname(__file__),
'../lib')))
import cdist
if re.match(cdist.TYPE_PREFIX, os.path.basename(sys.argv[0])):
emulator()
else:
# Add our own library path
sys.path.insert(0,
os.path.abspath(os.path.join(os.path.dirname(__file__),
'../lib')))
import cdist.banner
import cdist.exec
import cdist.path
commandline()
except KeyboardInterrupt:
sys.exit(0)
except CdistError as e:
except cdist.Error as e:
log.error(e)
sys.exit(1)

View file

@ -1 +0,0 @@
cdist

View file

@ -19,6 +19,9 @@
#
#
TYPE_PREFIX = "__"
VERSION = "2.0.2"
class Error(Exception):
"""Base exception class for this project"""
pass

46
lib/cdist/banner.py Normal file
View file

@ -0,0 +1,46 @@
# -*- coding: utf-8 -*-
#
# 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 logging
import sys
log = logging.getLogger(__name__)
BANNER = """
.. . .x+=:. s
dF @88> z` ^% :8
'88bu. %8P . <k .88
. '*88888bu . .@8Ned8" :888ooo
.udR88N ^"*8888N .@88u .@^%8888" -*8888888
<888'888k beWE "888L ''888E` x88: `)8b. 8888
9888 'Y" 888E 888E 888E 8888N=*8888 8888
9888 888E 888E 888E %8" R88 8888
9888 888E 888F 888E @8Wou 9% .8888Lu=
?8888u../ .888N..888 888& .888888P` ^%888*
"8888P' `"888*"" R888" ` ^"F 'Y"
"P' "" ""
"""
def banner(args):
"""Guess what :-)"""
print(BANNER)
sys.exit(0)

View file

@ -33,7 +33,6 @@ REMOTE_GLOBAL_EXPLORER_DIR = os.path.join(REMOTE_CONF_DIR, "explorer")
CODE_HEADER = "#!/bin/sh -e\n"
DOT_CDIST = ".cdist"
TYPE_PREFIX = "__"
log = logging.getLogger(__name__)
@ -58,7 +57,7 @@ class Path:
def __init__(self, target_host,
initial_manifest=False, remote_user="root",
base_dir=None, debug=False):
remote_prefix=False, base_dir=None, debug=False):
# Base and Temp Base
if base_dir:
@ -70,7 +69,10 @@ class Path:
self.target_host = target_host
self.remote_user = remote_user
self.remote_prefix = ["ssh", self.remote_user + "@" + self.target_host]
if remote_prefix:
self.remote_prefix = remote_prefix
else:
self.remote_prefix = ["ssh", self.remote_user + "@" + self.target_host]
self.conf_dir = os.path.join(self.base_dir, "conf")
self.cache_base_dir = os.path.join(self.base_dir, "cache")