Created
February 27, 2015 11:24
-
-
Save Morrolan/d99cb3059f5be6ef30d9 to your computer and use it in GitHub Desktop.
Zabbix Deployment Script
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
__author__ = 'ihavelock' | |
# system modules | |
import logging | |
import json | |
import argparse | |
import os | |
import shutil | |
import fileinput | |
# custom modules | |
import afcsupport3 | |
# third-party modules | |
# particular imports | |
################### CONSTANTS #################### | |
SETTINGS = r"config/config.json" | |
################### VARIABLES #################### | |
# | |
################### FUNCTIONS #################### | |
def begin(): | |
""" | |
As always, lets start at the beginning! | |
""" | |
# load our settings into a dict | |
settings = get_settings() | |
logging.basicConfig(filename=settings['log_file'], level=logging.DEBUG, | |
format='%(asctime)s %(levelname)s: %(message)s') | |
logging.info("\n\n\n") | |
logging.info("#########################################################################") | |
logging.info("#") | |
logging.info("# Zabbix Agent Config & Script Deployment Manager v0.1") | |
logging.info("# Written by Ian Havelock") | |
logging.info("#") | |
logging.info("#########################################################################") | |
# read commandline arguments | |
logging.info("Parsing commandline arguments.") | |
args = parse_arguments() | |
# stitch together the filename from the commandline parameter and the directory, and add file extension. | |
filename = args + ".json" | |
logging.info("User has specified '{0}' environment file as a parameter.") | |
file_path = os.path.join(settings['environment_dir'], filename) | |
# pass the filename to the JSON parser so that we (hopefully!) have a list containing a dict per server. | |
logging.info("Attempting to read server list.") | |
servers_list = parse_json(file_path) | |
logging.info("Checking that server list is correctly formed.") | |
check_integrity(servers_list) | |
logging.info("Attempting to process servers in list.") | |
process_server_list(servers_list) | |
# TODO: Check to see if RDP available, if so mount network share, if not stick file on holding area (TBD) | |
def get_settings(): | |
""" | |
Import settings from the JSON settings file! | |
:return: dict | |
""" | |
imported_settings = json.load(open(os.path.normpath(SETTINGS))) | |
#print(imported_settings) | |
settings_dict = imported_settings['config'][0] | |
return settings_dict | |
def parse_arguments(): | |
""" | |
Here we will parse the commandline arguments and switches | |
:return: list | |
""" | |
parser = argparse.ArgumentParser() | |
# tell our parser what to look for and a description of what it does. | |
parser.add_argument("--environment", "-e", | |
help="Please enter the environment that you wish to update, i.e. 'ST4'.") | |
# parse them to see if any were specified | |
argo = parser.parse_args() | |
# set our argdata variable to point to the environment parameter (perfectly fine if nothing is specified) | |
# By doing it this way, and adding another layer before the return, it allows us to easily expand the args later | |
# if required. | |
argdata = argo.environment | |
logging.info("Arguments passed: {0}".format(argdata)) | |
return argdata | |
def parse_json(env): | |
""" | |
Here we will first check to see if the file exists, and if so open it as a JSON object. | |
:param env: string representing the filepath of the settings file to open. | |
:return: list | |
""" | |
servers_list = None | |
# little bit of error handling in case the concatenated filename doesn't actually exist. | |
logging.info("Checking to see if specified JSON file exists.") | |
try: | |
imported_servers = json.load(open(os.path.normpath(env))) | |
servers_list = imported_servers['servers'] | |
except IOError: | |
e = "The environment file you have specified at '{0}' does not exist. Please try again.".format(env) | |
logging.error(e) | |
print(e) | |
exit(1) | |
return servers_list | |
def check_integrity(servers_list): | |
""" | |
What we'll do here is to check as we go that we get the expected object type, i.e. a dict where we expect a dict. | |
:param servers_list: | |
""" | |
try: | |
logging.info("Asserting that server list is actually a 'list' object.") | |
assert(isinstance(servers_list, list)) | |
except AssertionError: | |
e = "Type assertion failed - expected a list." | |
logging.error(e) | |
print(e) | |
exit(1) | |
logging.info("Asserting that all list entries are 'dict' object types.") | |
for server in servers_list: | |
try: | |
assert(isinstance(server, dict)) | |
except AssertionError: | |
e = "Type assertion failed - expected a dict." | |
logging.error(e) | |
print(e) | |
exit(1) | |
def process_server_list(servers_list): | |
""" | |
What we'll do here is to iterate through our list of servers, and do our processing as we go! | |
:param servers_list: | |
""" | |
settings = get_settings() | |
master_dir = settings['master_dir'] | |
temp_dir = settings['temp_dir'] | |
zabbix_conf = os.path.join(temp_dir, settings['zabbix_conf']) | |
for server in servers_list: | |
if os.path.exists(temp_dir): | |
logging.info("temp dir exists - deleting...") | |
shutil.rmtree(temp_dir) | |
if os.path.exists(master_dir): | |
logging.info("Copying master directory to temp directory.") | |
shutil.copytree(master_dir, temp_dir) | |
else: | |
e = "The directory '{0}' does not exist.".format(master_dir) | |
logging.error(e) | |
print(e) | |
# now that we have our temp_dir, lets go replace the hostname? | |
for line in fileinput.input(zabbix_conf, inplace=True): | |
print(line.replace('#HOSTNAME#', server['hostname']), end='') | |
copy_to_destination(server) | |
def copy_to_destination(server): | |
""" | |
:param server: | |
""" | |
settings = get_settings() | |
temp_dir = settings['temp_dir'] | |
if server['rdp'] == "True": | |
share = "\\\\" + server['ip'] + "\\" + server['path'] | |
logging.info("Share directory: {0}".format(str(os.path.normpath(share)))) | |
else: | |
share = settings['holding_area'] + "\\" + server['ip'] | |
logging.info("Share directory: {0}".format(str(os.path.normpath(share)))) | |
if not os.path.isdir(share): | |
os.makedirs(share) | |
username = server['domain'] + "\\" + server['username'] | |
password = server['password'] | |
logging.info("Attempting to mount share...") | |
afcsupport3.mount_share(share, username, password) | |
logging.info("Share mounted successfully.") | |
logging.info("Copying files to destination...") | |
recursive_overwrite(temp_dir, share) | |
def recursive_overwrite(src, dest, ignore=None): | |
if os.path.isdir(src): | |
if not os.path.isdir(dest): | |
os.makedirs(dest) | |
files = os.listdir(src) | |
if ignore is not None: | |
ignored = ignore(src, files) | |
else: | |
ignored = set() | |
for f in files: | |
if f not in ignored: | |
if not f.endswith('.exe'): # hack because I can't get the ignore shit to work! | |
logging.info("Copying '{0}' to '{1}'".format(str(f), dest)) | |
recursive_overwrite(os.path.join(src, f), | |
os.path.join(dest, f), | |
ignore) | |
else: | |
shutil.copyfile(src, dest) | |
def main(): | |
begin() | |
############################################### | |
if __name__ == "__main__": | |
main() |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment