From 0ceb4089c199edcdaa5fd7067c0a5ae4b66e7ca0 Mon Sep 17 00:00:00 2001 From: Kevin Fenzi Date: Thu, 23 Jan 2014 11:34:13 -0700 Subject: [PATCH] Add gather-diff-instances script from cloud --- .../gather-diff-instances.py | 166 ++++++++++++++++++ 1 file changed, 166 insertions(+) create mode 100755 scripts/gather-diff-instances/gather-diff-instances.py diff --git a/scripts/gather-diff-instances/gather-diff-instances.py b/scripts/gather-diff-instances/gather-diff-instances.py new file mode 100755 index 0000000..35555a4 --- /dev/null +++ b/scripts/gather-diff-instances/gather-diff-instances.py @@ -0,0 +1,166 @@ +#!/usr/bin/python +# skvidal +# fedoraproject.org - +# run the json outputter +# output to /var/log/instance-lists/timestamp +# compare newest one to the last one +# mail results to mailto, if any + + +destdir='/var/log/instance-lists/' +mailto='admin@fedoraproject.org' + + +import sys +import time +import json +import glob +import os +import smtplib +from email.MIMEText import MIMEText + +from nova import context +from nova import db +from nova import flags + + + +def list_vms(host=None): + """ + make a list of vms and expand out their fixed_ip and floating ips sensibly + """ + flags.parse_args([]) + my_instances = [] + if host is None: + instances = db.instance_get_all(context.get_admin_context()) + else: + instances = db.instance_get_all_by_host( + context.get_admin_context(), host) + + for instance in instances: + my_inst = {} + my_inst = dict(instance).copy() + for (k,v) in my_inst.items(): + try: + json.encoder(v) + except TypeError, e: + v = str(v) + my_inst[k] = v + + ec2_id = db.get_ec2_instance_id_by_uuid(context.get_admin_context(), instance.uuid) + ec2_id = 'i-' + hex(int(ec2_id)).replace('0x', '').zfill(8) + my_inst['ec2_id'] = ec2_id + try: + fixed_ips = db.fixed_ip_get_by_instance(context.get_admin_context(), instance.uuid) + except: + pass + my_inst['fixed_ips'] = [ ip.address for ip in fixed_ips ] + my_inst['floating_ips'] = [] + for ip in fixed_ips: + my_inst['floating_ips'].extend([ f_ip.address for f_ip in db.floating_ip_get_by_fixed_address(context.get_admin_context(), ip.address)]) + + my_instances.append(my_inst) + return my_instances + + + +def diff_instances(old, new): + """ + Take 2 lists of instances @old, @new + diff them and return a list of strings citing changes. + """ + old_uuids = {} + new_uuids = {} + for vm in old: + old_uuids[vm['uuid']] = vm + + for vm in new: + new_uuids[vm['uuid']] = vm + + uuids = set(new_uuids.keys() + old_uuids.keys()) + ret = [] + removed = [] + added = [] + for uuid in sorted(uuids): + if uuid not in new_uuids: + vm = old_uuids[uuid] + removed.append(vm) + + elif uuid not in old_uuids: + vm = new_uuids[uuid] + added.append(vm) + + + else: + old_vm = old_uuids[uuid] + new_vm = new_uuids[uuid] + changed = [] + for k,v in old_vm.items(): + if v != new_vm.get(k, 'NOT_A_MATCH'): + changed.append(k) + if changed: + ret.append('Changes to: %s' % uuid) + for k in changed: + ret.append(" %s changed from '%s' to '%s'" % (k, old_vm[k], new_vm[k])) + + if added: + ret.append('Instance(s) Added:\n') + for vm in added: + ret.append(' %s %s %s %s' % (uuid, vm['display_name'], vm['floating_ips'][0], vm['key_name'])) + if removed: + ret.append('Instance(s) Removed:\n') + for vm in removed: + if vm['floating_ips'][0]: + ret.append(' %s %s %s %s' % (uuid, vm['display_name'], vm['floating_ips'][0], vm['key_name'])) + + return ret + + + +def email(to, subject, text): + """ + send email + """ + mail_from = 'cloudadmin@fedoraproject.org' + mail_to = '%s' % to + + output = text + + msg = MIMEText(output) + msg['Subject'] = subject + msg['From'] = mail_from + msg['To'] = mail_to + s = smtplib.SMTP() + s.connect() + s.sendmail(mail_from, [mail_to], msg.as_string()) + s.close() + + +def main(): + if not os.path.exists(destdir): + os.makedirs(destdir) + + + # get the instances list + new_instances = list_vms() + now=time.strftime('%Y-%m-%d-%H:%M.json') + f = open(destdir + '/' + now, 'w') + f.write(json.dumps(new_instances)) + f.close() + + # get the last one + fns = [fn for fn in glob.glob(destdir + '/*.json') ] + if len(fns) < 2: + return + + last = sorted(fns)[-2] + old_instances = json.load(open(last)) + res = diff_instances(old_instances, new_instances) + + if res: + email(mailto, "Changes to cloud instances", '\n'.join(res)) + + +if __name__ == "__main__": + main() +