from flask import current_app from capsulflask.db import get_model # { # "capsul-123abc45": { # "id": "capsul-123abc45", # "public_ipv4": "123.123.123.123", # "public_ipv6": "::::", # "host": "baikal", # "network_name": "public1", # "virtual_bridge_name": "virbr1", # "desired_state": "running" # }, # { ... }, # ... # } def get_all_vms_from_db() -> dict: db_hosts = get_model().list_hosts_with_networks(None) db_vms_by_host_and_network = get_model().non_deleted_vms_by_host_and_network(None) db_vms_by_id = dict() for kv in db_hosts.items(): host_id = kv[0] value = kv[1] for network in value['networks']: if host_id in db_vms_by_host_and_network and network['network_name'] in db_vms_by_host_and_network[host_id]: for vm in db_vms_by_host_and_network[host_id][network['network_name']]: vm['network_name'] = network['network_name'] vm['virtual_bridge_name'] = network['virtual_bridge_name'] vm['host'] = host_id db_vms_by_id[vm['id']] = vm # for vm in db_vms: # if vm["id"] not in db_vms_by_id: # # TODO # raise Exception("non_deleted_vms_by_host_and_network did not return a vm that was returned by all_vm_ids_with_desired_state") # else: # db_vms_by_id[vm["id"]]["state"] = vm["desired_state"] return db_vms_by_id # this returns the same shape of object as get_all_vms_from_db except it has 'state' instead of 'desired_state' def get_all_vms_from_hosts(db_vms_by_id: dict) -> dict: virt_vms_by_id = current_app.config["HUB_MODEL"].get_all_by_id() db_hosts = get_model().list_hosts_with_networks(None) for vm_id, virt_vm in virt_vms_by_id.items(): if vm_id in db_vms_by_id: if 'host' not in virt_vm: virt_vm['host'] = db_vms_by_id[vm_id]['host'] if 'network_name' not in virt_vm: virt_vm['network_name'] = db_vms_by_id[vm_id]['network_name'] else: if 'host' not in virt_vm: virt_vm['host'] = "unknown" if 'network_name' not in virt_vm: virt_vm['network_name'] = "unknown" if virt_vm['host'] in db_hosts and virt_vm['network_name'] in db_hosts[virt_vm['host']]: virt_vm['virtual_bridge_name'] = db_hosts[virt_vm['host']][virt_vm['network_name']]['virtual_bridge_name'] else: virt_vm['virtual_bridge_name'] = "unknown" return virt_vms_by_id def ensure_vms_and_db_are_synced(): pass # # Now creating the capsuls running status ui # # # for vm in db_vms: # db_ids_dict[vm['id']] = vm['desired_state'] # for vm in virt_vms: # virt_ids_dict[vm['id']] = vm['desired_state'] # errors = list() # for id in db_ids_dict: # if id not in virt_ids_dict: # errors.append(f"{id} is in the database but not in the virtualization model") # elif db_ids_dict[id] != virt_ids_dict[id]: # errors.append(f"{id} has the desired state {db_ids_dict[id]} in the database but current state {virt_ids_dict[id]} in the virtualization model") # for id in virt_ids_dict: # if id not in db_ids_dict: # errors.append(f"{id} is in the virtualization model but not in the database") # if len(errors) > 0: # email_addresses_raw = current_app.config['ADMIN_EMAIL_ADDRESSES'].split(",") # email_addresses = list(filter(lambda x: len(x) > 6, map(lambda x: x.strip(), email_addresses_raw ) )) # current_app.logger.info(f"cron_task: sending inconsistency warning email to {','.join(email_addresses)}:") # for error in errors: # current_app.logger.info(f"cron_task: {error}.") # current_app.config["FLASK_MAIL_INSTANCE"].send( # Message( # "Capsul Consistency Check Failed", # sender=current_app.config["MAIL_DEFAULT_SENDER"], # body="\n".join(errors), # recipients=email_addresses # ) # )