From 8c031b1a00cc22d23ca99f82d68039f22b85eddf Mon Sep 17 00:00:00 2001 From: Denis Meltsaykin Date: Fri, 3 Apr 2015 13:19:06 +0000 Subject: [PATCH] Initial commit apply_patches.py - script to patch/revert several nodes with patches keeping order mos_apply_mu.py - script to install updates repository into nodes (still in progress) fuel_repo_update.py - sketch of script to update Fuel's repository list via REST-API Change-Id: Iebf530f77c5eaf167ab8921b4f2ddf786f56310c --- scripts/apply_patches.py | 87 ++++++++++++ scripts/custom.pkg | 12 ++ scripts/fuel_repo_update.py | 55 ++++++++ scripts/mos_apply_mu.py | 273 ++++++++++++++++++++++++++++++++++++ scripts/patches.list | 8 ++ 5 files changed, 435 insertions(+) create mode 100644 scripts/apply_patches.py create mode 100644 scripts/custom.pkg create mode 100644 scripts/fuel_repo_update.py create mode 100644 scripts/mos_apply_mu.py create mode 100644 scripts/patches.list diff --git a/scripts/apply_patches.py b/scripts/apply_patches.py new file mode 100644 index 0000000..0c0d89a --- /dev/null +++ b/scripts/apply_patches.py @@ -0,0 +1,87 @@ +#!/usr/bin/env python +import sys +import json +import os +import subprocess + +#subprocess.Popen (["ssh", "127.0.0.1", 'patch --dry-run -Ntbp0'], stdin=file,stdout=log, stderr=log) + +CONFIG_FILE = "patches.list" +cfg = dict() +logfile = "patch_apply.log" +dry_run = True + +def cat_file_via_pipe(file, host): + patch={ + True:"patch --dry-run -d / -Ntbp0", + False:"patch -d / -Ntbp0" + } + PIPE=subprocess.PIPE + try: + fp=open(file,'r') + except Exception as e: + msg="Error opening file {0}: {1}\n".format(file, e.args[1]) + print (msg) + LOG(msg) + return False + cmdline=["ssh", host, patch[dry_run]+reverse] + print (cmdline) + pp=subprocess.Popen(cmdline, stdin=fp, stdout=log, stderr=log) + pp.wait() + fp.close() + if pp.returncode != 0: + print ("Something went wrong, see {0} for infomation".format(logfile)) + return False + return True + +def read_config(): + global cfg + try: + file = open(CONFIG_FILE, 'r') + cfg = json.load(file) + file.close() + except: + print ("Couldn't load config-file") + os.exit(1) + +def apply_patches(): + patches = cfg['patches'] + if reverse != "": + patches=reversed(cfg['patches']) + for node in cfg['nodes']: + for patch in patches: + LOG("\n>>>>>>>>>START of PATCHING {0} with {1} (dry-run:{2})\n\n".format( + node,patch,dry_run)) + retval=cat_file_via_pipe(patch, node) + if retval is False: + msg="Unable to apply patch {0} to {1} (dry-run:{2})\n".format(patch, node, dry_run) + else: + msg="Successfuly patched {0} to {1} (dry-run:{2})\n".format(patch, node, dry_run) + LOG(msg) + print (msg) + LOG("\n<<<<<<<< 0) and (all_envs == True): + print ("You should only select either --env-id or --all-envs.") + print (usage) + sys.exit(5) + if (env_id == 0) and (all_envs == False): + print ("At least one option (env-id or all-envs) must be set.") + print (usage) + sys.exit(6) + + repo_install = { + 'ubuntu': """(grep -q "updates" /etc/apt/sources.list || echo -e "\ndeb http://{0}:8080/updates/ubuntu precise main" >> /etc/apt/sources.list); apt-get update; apt-get upgrade -y""".format(master_ip), + 'centos': """yum-config-manager --add-repo=http://{0}:8080/updates/centos/os/x86_64/; yum update --skip-broken -y --nogpgcheck""".format(master_ip) + } + + +def get_downloads_list(): + global pkgs + try: + file=open(path,'r') + pkgs=json.load(file) + file.close() + except: + return None + return True + +def packages_download (): + #check if dst dir exists if not create it (and others) + try: + os.makedirs(dest) + except os.error as err: + if err.args[0] != 17: + print ("Error during creating directory {0}: {1}".format( + dest, err.args[1])) + return (None) + + retval = 0 + for pkg in pkgs.values(): + for t in pkg: + cmd="wget -c -P{0} \"{1}\"".format(dest, t) + print ("Running: {0}".format(cmd)) + retval += os.system(cmd) + + if retval != 0: + print ("Some downloads are failed!") + return (retval) + +def get_nodes (): + req = urllib2.Request('http://127.0.0.1:8000/api/v1/nodes/') + req.add_header('X-Auth-Token',token) + nodes = json.load(urllib2.urlopen(req)) + return nodes + +def get_operational_envs (nodes, env_list): + for node in nodes: + if (node['status'] == "ready"): + if try_offline == True: env_list.add(node['cluster']) + elif node['online'] == True: env_list.add(node['cluster']) + +def do_node_update (nodes, env_list): + to_update = set() + for env in env_list: + for node in nodes: + if node['cluster'] == env: + if try_offline == True: + to_update.add((node['ip'], node['os_platform'])) + elif node['online'] == True: + to_update.add((node['ip'], node['os_platform'])) + + if install_custom == True: + if get_downloads_list() is not None: + packages_download() + else: + print ("Unable to get packages list from file {0}".format(path)) + + print (to_update) + if really == True: + log = open(logfile, 'w',0) + else: + log = open('/dev/null', 'w') + + should = len(to_update) + have = 0 + for ip,os_version in to_update: + log.write("-------------- UPDATING {0} -----------------\n".format(ip)) + cmdline = ["ssh", "-t", "-t", str(ip), repo_install[os_version]] + print (cmdline) + log.write(str(cmdline)+"\n") + if really == True: + tmp=subprocess.Popen(cmdline, stdin=None, stdout=log, stderr=log) + tmp.wait() + if tmp.returncode != 0: + msg="Update procedure on {0} returned FAIL({1}). Check log for details.\n".format(ip,tmp.returncode) + else: + msg="Update procedure on {0} completed with success!\n".format(ip) + have += 1 + print(msg) + log.write(msg) + if install_custom == True: + do_install_custom(ip, os_version, flag=really, logfp=log) + log.write("---------------- DONE -------------------\n") + msg = "Total: {0} out of {1} nodes updated successfully.\n".format(have, should) + print (msg) + log.write(msg) + log.flush() + log.close() + +def do_install_custom (ip, os_version, flag=False, logfp=None): + install={"ubuntu": "/usr/bin/dpkg -i ", "centos": "rpm -Uvh "} + if pkgs is None: return (None) + + for package in pkgs[os_version]: + cmdline=["scp", dest+package.split("/")[-1], str(ip)+":/tmp/"] + print (cmdline) + if flag == True: + tmp = subprocess.Popen(cmdline, stdin=None, stdout=logfp, stderr=logfp) + tmp.wait() + if tmp.returncode != 0: + msg = "Error in copying {0} to {1}. Installation skipped. See log for information\n".format( + package.split("/")[-1], ip) + print (msg) + logfp.write (msg) + continue + else: + msg = "Copied {0} to {1}\n".format(package.split("/")[-1], ip) + print (msg) + logfp.write (msg) + + cmdline=["ssh","-t", "-t", str(ip), "{0}".format(install[os_version]+"/tmp/"+package.split("/")[-1])] + print (cmdline) + if flag == True: + tmp = subprocess.Popen(cmdline, stdin=None, stdout=logfp, stderr=logfp) + tmp.wait() + if tmp.returncode != 0: + msg = "Installation {0} on {1} returned FAIL. Please check log.\n".format( + package.split("/")[-1],ip) + else: + msg = "Installation {0} on {1} completed with success!.\n".format( + package.split("/")[-1],ip) + print (msg) + logfp.write(msg) + +if __name__ == "__main__": + arg_parse() + + ks = client.Client (username=username, password=password, + tenant_name=tenant, auth_url=auth) + token = ks.auth_token + + env_list = set() + nodes = get_nodes() + + if (env_id > 0): + env_list.add(env_id) + else: + get_operational_envs(nodes,env_list) + + print ("Following envs will be updated: " + ",".join([str(x) for x in env_list])) + do_node_update(nodes, env_list) + sys.exit(0) diff --git a/scripts/patches.list b/scripts/patches.list new file mode 100644 index 0000000..d02113e --- /dev/null +++ b/scripts/patches.list @@ -0,0 +1,8 @@ +{ + "nodes": [ + "127.0.0.1" + ], + "patches": [ + "./a.patch" + ] +} -- 2.45.2