diff --git a/salt/salt/engines/master/virtual_node_manager.py b/salt/salt/engines/master/virtual_node_manager.py index 6425a0063..bc203fb59 100644 --- a/salt/salt/engines/master/virtual_node_manager.py +++ b/salt/salt/engines/master/virtual_node_manager.py @@ -316,7 +316,7 @@ def validate_hardware_request(model_config: dict, requested_hw: dict) -> Tuple[b for hw_type in ['disk', 'copper', 'sfp']: if hw_type in requested_hw and requested_hw[hw_type]: try: - indices = [int(x) for x in str(requested_hw[hw_type]).split(',')] + indices = [int(x) for x in str(requested_hw[hw_type]).split('\n')] log.debug("Checking if %s indices %s exist in model", hw_type, indices) if hw_type not in model_config['hardware']: @@ -405,7 +405,7 @@ def check_hardware_availability(hypervisor_path: str, vm_name: str, requested_hw # Track unique resources for hw_type in ['disk', 'copper', 'sfp']: if hw_type in config and config[hw_type]: - indices = [int(x) for x in str(config[hw_type]).split(',')] + indices = [int(x) for x in str(config[hw_type]).split('\n')] for idx in indices: used_resources[hw_type][idx] = basename.replace('_sensor', '') # Store VM name without role log.debug("VM %s is using %s indices: %s", basename, hw_type, indices) @@ -432,7 +432,7 @@ def check_hardware_availability(hypervisor_path: str, vm_name: str, requested_hw # Check for hardware conflicts for hw_type in ['disk', 'copper', 'sfp']: if hw_type in requested_hw and requested_hw[hw_type]: - requested_indices = [int(x) for x in str(requested_hw[hw_type]).split(',')] + requested_indices = [int(x) for x in str(requested_hw[hw_type]).split('\n')] log.debug("Checking for %s conflicts - Requesting indices: %s, Currently in use: %s", hw_type, requested_indices, used_resources[hw_type]) conflicts = {} # {index: vm_name} @@ -636,7 +636,7 @@ def process_vm_creation(hypervisor_path: str, vm_config: dict) -> None: # Add PCI devices for hw_type in ['disk', 'copper', 'sfp']: if hw_type in vm_config and vm_config[hw_type]: - indices = [int(x) for x in str(vm_config[hw_type]).split(',')] + indices = [int(x) for x in str(vm_config[hw_type]).split('\n')] for idx in indices: hw_config = {int(k): v for k, v in model_config['hardware'][hw_type].items()} pci_id = hw_config[idx] diff --git a/salt/soc/dyanno/hypervisor/hypervisor.yaml b/salt/soc/dyanno/hypervisor/hypervisor.yaml index e2a0028a8..c282d4e7b 100644 --- a/salt/soc/dyanno/hypervisor/hypervisor.yaml +++ b/salt/soc/dyanno/hypervisor/hypervisor.yaml @@ -6,28 +6,77 @@ hypervisor: syntax: json uiElements: - field: hostname - label: "Enter the hostname" + label: "Hostname" + forcedType: string + required: true + readonly: true - field: role - label: "sensor or searchnode" + label: "Role" + required: true + readonly: true + options: + - searchnode + - sensor + - receiver + - idh + - heavynode + - fleet - field: network_mode label: "Choose static4 or dhcp4. If static4, populate IP details below." + required: true + readonly: true + options: + - static4 + - dhcp4 - field: ip4 label: "IP Address with netmask. ex. 192.168.1.10/24" + forcedType: string + regex: '^(\d{1,3}\.){3}\d{1,3}/\d{1,2}$' + regexFailureMessage: "Enter a properly formatted CIDR address" + readonly: true - field: gw4 label: "Gateway" + forcedType: string + regex: '^(\d{1,3}\.){3}\d{1,3}$' + regexFailureMessage: "Enter a properly formatted IP address" + readonly: true - field: dns4 label: "DNS. Comma separated list. ex. 192.168.1.1,8.8.8.8" + forcedType: string + regex: '^(\d{1,3}\.){3}\d{1,3}$' + regexFailureMessage: "Enter a properly formatted IP address" + readonly: true - field: search4 label: "Search domain" + forcedType: string + readonly: true - field: cpu label: "CPU cores to assign. Free: FREE | Total: TOTAL" + forcedType: int + required: true + readonly: true - field: memory label: "Memory to assign, in GB. Free: FREE | Total: TOTAL" + required: true + readonly: true + forcedType: int - field: disk - label: "Disk(s) for passthrough. Comma separated list. Free: FREE | Total: TOTAL" + label: "Disk(s) for passthrough. Line-delimited list. Free: FREE | Total: TOTAL" + required: true + readonly: true + forcedType: '[]int' + multiline: true - field: copper - label: "Copper port(s) for passthrough. Comma separated list. Free: FREE | Total: TOTAL" + label: "Copper port(s) for passthrough. Line-delimited list. Free: FREE | Total: TOTAL" + required: true + readonly: true + forcedType: '[]int' + multiline: true - field: sfp - label: "SFP port(s) for passthrough. Comma separated list. Free: FREE | Total: TOTAL" + label: "SFP port(s) for passthrough. Line-delimited list. Free: FREE | Total: TOTAL" + required: true + readonly: true + forcedType: '[]int' + multiline: true file: true global: true diff --git a/salt/soc/dyanno/hypervisor/soc_hypervisor.yaml.jinja b/salt/soc/dyanno/hypervisor/soc_hypervisor.yaml.jinja index cb8be8b18..0f409eada 100644 --- a/salt/soc/dyanno/hypervisor/soc_hypervisor.yaml.jinja +++ b/salt/soc/dyanno/hypervisor/soc_hypervisor.yaml.jinja @@ -24,16 +24,16 @@ |-------------|-----------|-----------| | 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 }} | +| Disk | {{ disk_free | replace('\n', ',') if disk_free else 'None' }} | {{ disk_total | replace('\n', ',') }} | +| Copper | {{ copper_free | replace('\n', ',') if copper_free else 'None' }} | {{ copper_total | replace('\n', ',') }} | +| SFP | {{ sfp_free | replace('\n', ',') if sfp_free else 'None' }} | {{ sfp_total | replace('\n', ',') }} | {%- if vm_list %} ## Virtual Machines -| Name | Status | CPU | RAM(GB)| Disk | Copper | SFP | Last Updated | -|--------------------|--------------------|-----|--------|------|--------|------|---------------------| +| Name | Status | CPU Cores | Memory (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]+', '') }} | +| {{ 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', '-') | replace('\n', ',') if vm_data.get('config', {}).get('disk') else '-' }} | {{ vm_data.get('config', {}).get('copper', '-') | replace('\n', ',') if vm_data.get('config', {}).get('copper') else '-' }} | {{ vm_data.get('config', {}).get('sfp', '-') | replace('\n', ',') 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 @@ -81,9 +81,9 @@ No Virtual Machines Found {%- 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) -%} +{%- do used_disk.extend((config.get('disk', '') | string).split('\n') | map('trim') | list) -%} +{%- do used_copper.extend((config.get('copper', '') | string).split('\n') | map('trim') | list) -%} +{%- do used_sfp.extend((config.get('sfp', '') | string).split('\n') | map('trim') | list) -%} {%- endfor -%} {# Get available PCI indices #} @@ -94,9 +94,9 @@ No Virtual Machines Found {# 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(',') -%} +{%- set disk_total = hw_config.disk.keys() | join('\n') -%} +{%- set copper_total = hw_config.copper.keys() | join('\n') -%} +{%- set sfp_total = hw_config.sfp.keys() | join('\n') -%} {# Update field labels with total and free values #} {%- set updated_template = TEMPLATE.copy() -%} @@ -108,11 +108,11 @@ No Virtual Machines Found {%- 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)}) -%} +{%- do updated_field.update({'label': field.label | replace('FREE', disk_free) | replace('TOTAL', disk_total | replace('\n', ','))}) -%} {%- elif field.field == 'copper' -%} -{%- do updated_field.update({'label': field.label | replace('FREE', copper_free) | replace('TOTAL', copper_total)}) -%} +{%- do updated_field.update({'label': field.label | replace('FREE', copper_free) | replace('TOTAL', copper_total | replace('\n', ','))}) -%} {%- elif field.field == 'sfp' -%} -{%- do updated_field.update({'label': field.label | replace('FREE', sfp_free) | replace('TOTAL', sfp_total)}) -%} +{%- do updated_field.update({'label': field.label | replace('FREE', sfp_free) | replace('TOTAL', sfp_total | replace('\n', ','))}) -%} {%- endif -%} {%- do updated_elements.append(updated_field) -%} {%- endfor -%}