{# Copyright Security Onion Solutions LLC and/or licensed to Security Onion Solutions LLC under one or more contributor license agreements. Licensed under the Elastic License 2.0 as shown at https://securityonion.net/license; you may not use this file except in compliance with the Elastic License 2.0. Note: Per the Elastic License 2.0, the second limitation states: "You may not move, change, disable, or circumvent the license key functionality in the software, and you may not remove or obscure any functionality in the software that is protected by the license key." #} {%- if 'hvn' in salt['pillar.get']('features', []) -%} {%- import_yaml 'soc/dyanno/hypervisor/hypervisor.yaml' as ANNOTATION -%} {%- from 'hypervisor/map.jinja' import HYPERVISORS -%} {%- set TEMPLATE = ANNOTATION.hypervisor.hosts.pop('defaultHost') -%} {%- macro update_description(description, cpu_free, mem_free, disk_free, copper_free, sfp_free, vm_list, cpu_total, mem_total, disk_total, copper_total, sfp_total) -%} # Hypervisor Configuration: {{ description }} ## Resource Summary | Resource | Available | Total | |-------------|-----------|-----------| | CPU Cores | {{ cpu_free }} | {{ cpu_total }} | | Memory (GB) | {{ mem_free }} | {{ mem_total }} | | Disk | {{ disk_free if disk_free else 'None' }} | {{ disk_total }} | | Copper | {{ copper_free if copper_free else 'None' }} | {{ copper_total }} | | SFP | {{ sfp_free if sfp_free else 'None' }} | {{ sfp_total }} | {%- if vm_list %} ## Virtual Machines | Name | Status | CPU | RAM(GB)| Disk | Copper | SFP | Last Updated | |--------------------|--------------------|-----|--------|------|--------|------|---------------------| {%- for hostname, vm_data in vm_list.items() %} | {{ hostname }}_{{ vm_data.get('config', {}).get('role', 'unknown') }} | {{ vm_data.get('status', {}).get('status', 'Unknown') }} | {{ vm_data.get('config', {}).get('cpu', 'N/A') }} | {{ vm_data.get('config', {}).get('memory', 'N/A') }} | {{ vm_data.get('config', {}).get('disk', '-') if vm_data.get('config', {}).get('disk') else '-' }} | {{ vm_data.get('config', {}).get('copper', '-') if vm_data.get('config', {}).get('copper') else '-' }} | {{ vm_data.get('config', {}).get('sfp', '-') if vm_data.get('config', {}).get('sfp') else '-' }} | {{ vm_data.get('status', {}).get('timestamp', 'Never') | replace('T', ' ') | regex_replace('\\.[0-9]+', '') }} | {%- endfor %} {%- else %} ## Virtual Machines No Virtual Machines Found {%- endif %} {%- endmacro -%} {%- macro update_label(label, total, free) -%} {{- label | replace('TOTAL', total | string) | replace('FREE', free | string) -}} {%- endmacro -%} {%- macro get_available_pci(hw_config, device_type, used_indices) -%} {%- set available = [] -%} {%- for idx in hw_config.get(device_type, {}).keys() -%} {%- if idx | string not in used_indices -%} {%- do available.append(idx) -%} {%- endif -%} {%- endfor -%} {{- available | join(',') -}} {%- endmacro -%} {%- for role in HYPERVISORS -%} {%- for hypervisor in HYPERVISORS[role].keys() -%} {%- set hw_config = HYPERVISORS[role][hypervisor].hardware -%} {%- set vms = HYPERVISORS[role][hypervisor].vms -%} {# Calculate used CPU and memory #} {%- set used_cpu = 0 -%} {%- set used_memory = 0 -%} {%- set ns = namespace(used_cpu=0, used_memory=0) -%} {%- for hostname, vm_data in vms.items() -%} {%- set vm_config = vm_data.config -%} {%- set ns.used_cpu = ns.used_cpu + vm_config.cpu | int -%} {%- set ns.used_memory = ns.used_memory + vm_config.memory | int -%} {%- endfor -%} {# Calculate available resources #} {%- set cpu_free = hw_config.cpu - ns.used_cpu -%} {%- set mem_free = hw_config.memory - ns.used_memory -%} {# Get used PCI indices #} {%- set used_disk = [] -%} {%- set used_copper = [] -%} {%- set used_sfp = [] -%} {%- for hostname, vm in vms.items() -%} {%- set config = vm.get('config', {}) -%} {%- do used_disk.extend((config.get('disk', '') | string).split(',') | map('trim') | list) -%} {%- do used_copper.extend((config.get('copper', '') | string).split(',') | map('trim') | list) -%} {%- do used_sfp.extend((config.get('sfp', '') | string).split(',') | map('trim') | list) -%} {%- endfor -%} {# Get available PCI indices #} {%- set disk_free = get_available_pci(hw_config, 'disk', used_disk) -%} {%- set copper_free = get_available_pci(hw_config, 'copper', used_copper) -%} {%- set sfp_free = get_available_pci(hw_config, 'sfp', used_sfp) -%} {# Get total resources #} {%- set cpu_total = hw_config.cpu -%} {%- set mem_total = hw_config.memory -%} {%- set disk_total = hw_config.disk.keys() | join(',') -%} {%- set copper_total = hw_config.copper.keys() | join(',') -%} {%- set sfp_total = hw_config.sfp.keys() | join(',') -%} {# Update field labels with total and free values #} {%- set updated_template = TEMPLATE.copy() -%} {%- set updated_elements = [] -%} {%- for field in updated_template.uiElements -%} {%- set updated_field = field.copy() -%} {%- if field.field == 'cpu' -%} {%- do updated_field.update({'label': field.label | replace('FREE', cpu_free | string) | replace('TOTAL', cpu_total | string)}) -%} {%- elif field.field == 'memory' -%} {%- do updated_field.update({'label': field.label | replace('FREE', mem_free | string) | replace('TOTAL', mem_total | string)}) -%} {%- elif field.field == 'disk' -%} {%- do updated_field.update({'label': field.label | replace('FREE', disk_free) | replace('TOTAL', disk_total)}) -%} {%- elif field.field == 'copper' -%} {%- do updated_field.update({'label': field.label | replace('FREE', copper_free) | replace('TOTAL', copper_total)}) -%} {%- elif field.field == 'sfp' -%} {%- do updated_field.update({'label': field.label | replace('FREE', sfp_free) | replace('TOTAL', sfp_total)}) -%} {%- endif -%} {%- do updated_elements.append(updated_field) -%} {%- endfor -%} {%- do updated_template.update({'uiElements': updated_elements}) -%} {%- do updated_template.update({ 'title': hypervisor, 'description': update_description( hypervisor, cpu_free, mem_free, disk_free, copper_free, sfp_free, vms, cpu_total, mem_total, disk_total, copper_total, sfp_total ) }) -%} {%- do ANNOTATION.hypervisor.hosts.update({hypervisor ~ 'VMs': updated_template}) -%} {%- endfor -%} {%- endfor -%} {{- ANNOTATION | yaml(False) -}} {%- else -%} {%- do salt.log.error( 'Hypervisor nodes are a feature supported only for customers with a valid license.' 'Contact Security Onion Solutions, LLC via our website at https://securityonionsolutions.com' 'for more information about purchasing a license to enable this feature.' ) -%} {%- endif -%}