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