Nikolay Pliashechnykov | 316823e | 2020-08-14 15:44:50 +0100 | [diff] [blame] | 1 | #!/usr/bin/python |
| 2 | import json |
| 3 | def lookup_near(ls, name): |
| 4 | for vm in ls: |
| 5 | if vm['id'] == name: |
| 6 | return vm['id'] |
| 7 | return False |
| 8 | def lookup_far(dc, name): |
| 9 | result_hvs = [] |
| 10 | for hv in dc: |
| 11 | res = lookup_near(dc[hv], name) |
| 12 | if res: |
| 13 | result_hvs.append(hv) |
| 14 | return result_hvs |
| 15 | lost_vms = {} |
| 16 | hypervisors = {} |
| 17 | hypervisor_pattern = "cmp" #Replace with your own pattern, ensure it's unique so it wouldn't mix up with VM names |
| 18 | skip_pattern = "------------" |
| 19 | current_hv = "" |
| 20 | vm_pattern = "-" |
| 21 | with open("virsh_vms", "rt") as f: |
| 22 | for line in f.readlines(): |
| 23 | line = line.replace("\n", "") |
| 24 | if skip_pattern in line: |
| 25 | continue |
| 26 | elif hypervisor_pattern in line: |
| 27 | current_hv = line.replace(":", "") |
| 28 | if current_hv in hypervisors: |
| 29 | print("Duplicate hypervisor %s, exiting" % current_hv) |
| 30 | break |
| 31 | else: |
| 32 | hypervisors[current_hv] = [] |
| 33 | elif vm_pattern in line: |
| 34 | if not current_hv: |
| 35 | print("Malformed virsh list, exiting") |
| 36 | break |
| 37 | vm_info_struct = [x for x in line.replace("\n", "").replace("\t"," ").replace("shut off", "shutoff").split(" ") if x] |
| 38 | if len(vm_info_struct) == 4: |
| 39 | iid, virsh_id, iname, state = vm_info_struct |
| 40 | hypervisors[current_hv].append({"id": iid, "state": state}) |
| 41 | elif len(vm_info_struct) == 3: #No UUID assigned |
| 42 | virsh_id, iname, state = vm_info_struct |
| 43 | if not lost_vms.has_key(current_hv): |
| 44 | lost_vms[current_hv] = [iname + ":" + state] |
| 45 | else: |
| 46 | lost_vms[current_hv].append(iname + ":" + state) |
| 47 | nova_out = "" |
| 48 | nova_vms = {} |
| 49 | with open("nova_vms", "rt") as f: |
| 50 | for line in f.readlines(): |
| 51 | if "servers" in line: |
| 52 | if "RESP BODY" in line: |
| 53 | nova_out = line.replace("RESP BODY: ", "").replace("\n", "") |
| 54 | nova_vms_json = json.loads(nova_out) |
| 55 | for vm in nova_vms_json['servers']: |
| 56 | vm_id = vm['id'] |
| 57 | vm_iname = vm['OS-EXT-SRV-ATTR:instance_name'] |
| 58 | vm_hv = vm['OS-EXT-SRV-ATTR:hypervisor_hostname'] |
| 59 | vm_state = vm['OS-EXT-STS:vm_state'] |
| 60 | if vm_hv not in nova_vms: |
| 61 | nova_vms[vm_hv] = [] |
| 62 | nova_vms[vm_hv].append({"id": vm_id, "name": vm_iname, "state": vm_state}) |
| 63 | rev = {} |
| 64 | lsdup = [] |
| 65 | for hv in hypervisors: |
| 66 | for vm in hypervisors[hv]: |
| 67 | if not vm['id'] in rev: |
| 68 | rev[vm['id']] = [hv+"(%s)"%vm['state']] |
| 69 | else: |
| 70 | rev[vm['id']].append(hv+"(%s)"%vm['state']) |
| 71 | for vm_id in rev: |
| 72 | if len(rev[vm_id]) > 1: |
| 73 | print "Duplicate VM: %s on %s" % (vm_id, rev[vm_id]) |
| 74 | lsdup.append(vm_id) |
| 75 | for hv in hypervisors: |
| 76 | if hv not in nova_vms and len(hypervisors[hv]) > 0: |
| 77 | #print "WARN: hypervisor %s exists but nova doesn't know that it has following VMs:" % hv |
| 78 | for vm in hypervisors[hv]: |
| 79 | if not lookup_far(nova_vms, vm["id"]): |
| 80 | print "Nova doesn't know that vm %s is running on %s" %(vm["id"], hv) |
| 81 | continue |
| 82 | for vm in hypervisors[hv]: |
| 83 | report = "" |
| 84 | if not lookup_near(nova_vms[hv], vm['id']): |
| 85 | if vm['id'] in lsdup: |
| 86 | continue |
| 87 | report += "WARN: VM %s is on hypervisor %s" % (vm['id'], hv) |
| 88 | nova_hvs = lookup_far(nova_vms, vm["id"]) |
| 89 | if nova_hvs: |
| 90 | report += ", but nova thinks it is running on %s." % (str(nova_hvs)) |
| 91 | else: |
| 92 | report += ", but nova doesn't know about it." |
| 93 | report += " VM state is %s " % vm['state'] |
| 94 | if report: |
| 95 | print(report) |
| 96 | if lost_vms: |
| 97 | print("Lost VMs report (existing in virsh without an UUID and completely untracked in Openstack)") |
| 98 | for hv in lost_vms: |
| 99 | print(hv+":") |
| 100 | for vm in lost_vms[hv]: |
| 101 | print(vm) |