summaryrefslogtreecommitdiffstats
path: root/openstack/gather-diff-instances.py
blob: 534110ff7335ad81a123fd7d0b81455a5c800db0 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
#!/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
        fixed_ips = db.fixed_ip_get_by_instance(context.get_admin_context(), instance.uuid)
        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:
        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()