1
0
Fork 0
mirror of https://github.com/retspen/webvirtcloud synced 2026-11-08 11:16:47 +00:00
webvirtcloud/instances/templates/create_instance_w2.html
catborise ca74c02c4f fix(templates): the fields of the create modals are named by their labels
An accessibility scan with every modal opened found 49 fields without a
name: the labels of the instance create forms (custom, template and each
flavor's modal), the interface, network, secret and storage pool modals
did not point at their fields. Each label now has a for= and its field an
id, prefixed per form (and per flavor), so a click on the label focuses
the field too. The "Advanced" collapse buttons and the memory and
processing bars are named.

The VCPU config select had id="vcpu_mode" in each of these forms, nine
times on the create page; the unique-ID test did not see it as the test
driver reports no CPU modes. The id goes (nothing used it), and the test
now renders that branch.
2026-10-19 20:01:36 +03:00

943 lines
65 KiB
HTML

{% extends "base.html" %}
{% load i18n %}
{% load static %}
{% load operations %}
{% load bootstrap_icons %}
{% block title %}{% trans "Create new instance" %}{% endblock %}
{% block style %}
<link href="{% static "css/tom-select.bootstrap5.min.css" %}" rel="stylesheet">
<style>
/* the chosen images and networks are listed below the pickers, not in them */
#image-control + .ts-wrapper .ts-control > .item, #network-control + .ts-wrapper .ts-control > .item { display: none; }
</style>
{% endblock %}
{% block page_heading %}
{% blocktrans with host=compute.name %}New instance on {{ host }} {% endblocktrans %}
{% endblock page_heading %}
{% block content %}
{% include 'pleasewaitdialog.html' %}
{% if form.errors %}
{% for field in form %}
{% for error in field.errors %}
<div class="alert alert-danger">
<strong>{{ field.label }}:</strong> <span>{{ error|escape }}</span>
</div>
{% endfor %}
{% endfor %}
{% for error in form.non_field_errors %}
<div class="alert alert-danger">
<strong>{{ error|escape }}</strong>
</div>
{% endfor %}
{% endif %}
<div class="row">
<div class="col-lg-12">
<div role="tabpanel">
<!-- Nav tabs -->
<ul class="nav nav-tabs" role="tablist" aria-label="Instance create method">
<li class="nav-item" role="presentation">
<button class="nav-link float-end" data-bs-toggle="tab" data-bs-target="#" type="button" role="tab" aria-controls="go_compute" title="{% trans "Back" %}" onclick="goto_compute()">
<span>{% bs_icon 'arrow-left'%} </span>
</button>
</li>
<li class="nav-item" role="presentation">
<button class="nav-link active" data-bs-toggle="tab" data-bs-target="#flavor" type="button" role="tab" aria-controls="flavor" aria-selected="true">
{% trans "Flavor" %}
</button>
</li>
<li class="nav-item" role="presentation">
<button class="nav-link" data-bs-toggle="tab" data-bs-target="#addCustom" type="button" role="tab" aria-controls="addCustom" aria-selected="false">
{% trans "Custom" %}
</button>
</li>
<li class="nav-item" role="presentation">
<button class="nav-link" data-bs-toggle="tab" data-bs-target="#add-from-temp" type="button" role="tab" aria-controls="add-from-temp" aria-selected="false">
{% trans "Template" %}
</button>
</li>
</ul>
<!-- Tab panes -->
<div class="tab-content">
<div role="tabpanel" class="tab-pane tab-pane-bordered active" id="flavor">
{% include 'create_flav_block.html' %}
<h3 class="page-header">{% trans "Create from flavor" %}</h3>
{% if not flavors %}
<div class="col-lg-12">
<div class="alert alert-warning shadow-sm">
{% bs_icon 'exclamation-triangle'%} <strong>{% trans "Warning" %}:</strong> {% trans "Hypervisor doesn't have any Flavors" %}
</div>
</div>
{% else %}
<div class="table-responsive">
<table class="table table-hover">
<thead>
<tr>
<th scope="col">#</th>
<th scope="col">{% trans "Name" %}</th>
<th scope="col">{% trans "VCPU" %}</th>
<th scope="col">{% trans "RAM" %}</th>
<th scope="col">{% trans "HDD" %}</th>
<th scope="colgroup" colspan="2">{% trans "Action" %}</th>
</tr>
</thead>
<tbody>
{% for flavor in flavors %}
<tr>
<td>{{ forloop.counter }}</td>
<td>{{ flavor.label }}</td>
<td>{{ flavor.vcpu }}</td>
<td>{{ flavor.memory }} {% trans "MB" %}</td>
<td>{{ flavor.disk }} {% trans "GB" %}</td>
<td style="width:5px;">
<div class="modal fade" id="addVMflavor{{ forloop.counter }}" tabindex="-1" role="dialog" aria-labelledby="addVMFlavorLabel" aria-hidden="true">
<div class="modal-dialog">
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title">{% trans "Create Virtual Machine" %} ({{ flavor.label }})</h5>
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
</div>
<form method="post" role="form" aria-label="Create instance from flavor form">{% csrf_token %}{% submission_key %}
<div class="modal-body">
<div class="row">
<label for="flavor{{ flavor.id }}_name" class="col-sm-4 col-form-label">{% trans "Name" %}</label>
<div class="col-sm-7">
<input id="flavor{{ flavor.id }}_name" type="text" class="form-control" name="name"
placeholder="{% trans "Name" %}" maxlength="64" required
pattern="[a-zA-Z0-9\.\-_]+">
<input type="hidden" name="vcpu" value="{{ flavor.vcpu }}">
<input type="hidden" name="memory" value="{{ flavor.memory }}">
<input type="hidden" name="hdd_size" value="{{ flavor.disk }}">
</div>
</div>
{% if firmwares %}
<div class="row">
<label for="flavor{{ flavor.id }}_firmware" class="col-sm-4 col-form-label">{% trans "Firmware" %}</label>
<div class="col-sm-7">
<select id="flavor{{ flavor.id }}_firmware" class="form-select" name="firmware">
{% for frm in firmwares %}
<option value="{{ frm }}" {% if frm in default_firmware %}selected{% endif %}>{{ frm }}</option>
{% endfor %}
</select>
</div>
</div>
{% endif %}
{% if dom_caps.cpu_modes %}
<div class="row">
<label for="flavor{{ flavor.id }}_vcpu_mode" class="col-sm-4 col-form-label">{% trans "VCPU Config" %}</label>
<div class="col-sm-7">
<select id="flavor{{ flavor.id }}_vcpu_mode" class="form-select" name="vcpu_mode">
<option value=""> {% trans 'no-mode' %}</option>
{% for mode in dom_caps.cpu_modes %}
{% if mode == 'custom' %}
<optgroup label="Custom CPU Models">
{% for model in dom_caps.cpu_custom_models %}
<option value="{{ model }}"> {% trans model %}</option>
{% endfor %}
</optgroup>
{% else %}
<option value="{{ mode }}" {% if mode == default_cpu_mode %}selected {% endif %}>
{% trans mode %}
</option>
{% endif %}
{% endfor %}
</select>
</div>
</div>
{% endif %}
<div class="row">
<label for="flavor{{ flavor.id }}_storage" class="col-sm-4 col-form-label">{% trans "Storage" %}</label>
<div class="col-sm-7">
<input type="hidden" name="cache_mode" value="default">
<select id="flavor{{ flavor.id }}_storage" class="form-select" name="storage">
{% if storages %}
{% for storage in storages %}
<option value="{{ storage }}">{{ storage }}</option>
{% endfor %}
{% else %}
<option value="">{% trans "None" %}</option>
{% endif %}
</select>
</div>
</div>
<div class="row">
<label for="flavor{{ flavor.id }}_networks" class="col-sm-4 col-form-label">{% trans "Network" %}</label>
<div class="col-sm-7">
<select id="flavor{{ flavor.id }}_networks" class="form-select" name="networks">
{% for network in networks %}
<option value="{{ network }}">{{ network }}</option>
{% endfor %}
</select>
</div>
</div>
<div class="row">
<label class="col-sm-4 col-form-label">{% trans "Advanced" %}</label>
<div class="d-grid col-sm-7">
<button class="btn btn-outline-light" type="button" title="{% trans "Advanced" %}" data-bs-toggle="collapse" data-bs-target="#flav-add-collapse-{{ flavor.id }}" aria-expanded="false" aria-controls="flav-add-collapse-{{ flavor.id }}">
<span>{% bs_icon 'caret-down'%} </span>
</button>
</div>
</div>
<div class="collapse" id="flav-add-collapse-{{ flavor.id }}">
<div class="row">
<label for="flavor{{ flavor.id }}_mac" class="col-sm-4 col-form-label">{% trans "MAC" %}</label>
<div class="col-sm-7">
<input id="flavor{{ flavor.id }}_mac" type="text" class="form-control" name="mac" maxlength="17" value="{{ mac_auto }}" required pattern="[a-zA-Z0-9:]+">
</div>
</div>
<div class="row">
<label for="flavor{{ flavor.id }}_nwfilter" class="col-sm-4 col-form-label">{% trans "NWFilter" %}</label>
<div class="col-sm-7">
<select id="flavor{{ flavor.id }}_nwfilter" class="form-select" name="nwfilter">
<option value="">{% trans "None" %}</option>
{% for nwfilter in nwfilters %}
<option value="{{ nwfilter }}">{{ nwfilter }}</option>
{% endfor %}
</select>
</div>
</div>
<div class="row">
<label for="flavor{{ flavor.id }}_net_model" class="col-sm-4 col-form-label">{% trans "NIC Type" %} </label>
<div class="col-sm-7">
<select id="flavor{{ flavor.id }}_net_model" class="form-select" name="net_model">
{% for model in net_models_host %}
<option value="{{ model }}" {% if model == default_nic_type %} selected {% endif %}>{{ model }}</option>
{% endfor %}
</select>
</div>
</div>
<div class="row">
<label for="flavor{{ flavor.id }}_cache_mode" class="col-sm-4 col-form-label">{% trans "HDD cache mode" %}</label>
<div class="col-sm-7">
<select id="flavor{{ flavor.id }}_cache_mode" class="form-select" name="cache_mode">
{% for mode, name in cache_modes %}
<option value="{{ mode }}" {% if mode == default_cache %}selected {% endif %}>
{% trans name %}</option>
{% endfor %}
</select>
</div>
</div>
<div class="row">
<label for="flavor{{ flavor.id }}_video" class="col-sm-4 col-form-label">{% trans "Video" %}</label>
<div class="col-sm-7">
<select id="flavor{{ flavor.id }}_video" class="form-select" name="video">
{% if not videos %}
<option value="vga">vga</option>
<option value="cirrus">cirrus</option>
{% endif %}
{% for video in videos %}
<option value="{{ video }}" {% if default_video == video %}selected{% endif %}>{{ video }}</option>
{% endfor %}
</select>
</div>
</div>
<div class="row">
<label for="flavor{{ flavor.id }}_listener_addr" class="col-sm-4 col-form-label">{% trans "Console Access" %}</label>
<div class="col-sm-7">
<select id="flavor{{ flavor.id }}_listener_addr" class="form-select" name="listener_addr">
{% for addr, label in listener_addr %}
<option value="{{ addr }}" {% if addr == "0.0.0.0" %} selected {% endif %}>{{ label }}</option>
{% endfor %}
</select>
</div>
</div>
<div class="row">
<label for="flavor{{ flavor.id }}_add_cdrom" class="col-sm-4 col-form-label">{% trans "Add CD-Rom" %}</label>
<div class="col-sm-7">
<select id="flavor{{ flavor.id }}_add_cdrom" class="form-select" name="add_cdrom">
<option value="None" {% if bus == default_cdrom %}selected{% endif %}>--{% trans "False" %}--</option>
{% for bus in cdrom_buses %}
<option value="{{ bus }}" {% if bus == default_cdrom %}selected {% endif %}>
{% trans bus %}
</option>
{% endfor %}
</select>
</div>
</div>
<div class="row">
<label for="flavor{{ flavor.id }}_add_input" class="col-sm-4 col-form-label">{% trans "Add Input Device" %}</label>
<div class="col-sm-7">
<select id="flavor{{ flavor.id }}_add_input" class="form-select" name="add_input">
<option value="None" {% if bus == default_input_device_bus %}selected{% endif %}>--{% trans "False" %}--</option>
{% for bus in input_device_buses %}
<option value="{{ bus }}" {% if bus == default_input_device_bus %}selected{% endif %}>
{% trans bus %}
</option>
{% endfor %}
</select>
</div>
</div>
<div class="row">
<label for="flavor{{ flavor.id }}_qemu_ga" class="col-sm-4 col-form-label">{% trans "Guest Agent" %}</label>
<div class="col-sm-7">
<input id="flavor{{ flavor.id }}_qemu_ga" type="checkbox" name="qemu_ga" value="true" checked>
</div>
</div>
{% if virtio_support %}
<div class="row">
<label for="flavor{{ flavor.id }}_virtio" class="col-sm-4 col-form-label">{% trans "VirtIO" %}</label>
<div class="col-sm-7">
<input id="flavor{{ flavor.id }}_virtio" type="checkbox" name="virtio" value="{{ virtio_support }}" checked>
</div>
</div>
{% endif %}
</div>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-secondary" data-bs-dismiss="modal">{% trans "Close" %}</button>
{% if storages %}
<button type="submit" class="btn btn-primary" name="create">{% trans "Create" %}</button>
{% else %}
<button class="btn btn-primary disabled">{% trans "Create" %}</button>
{% endif %}
</div>
</form>
</div>
</div>
</div>
<a data-bs-toggle="modal" href="#addVMflavor{{ forloop.counter }}" class="btn btn-sm btn-secondary" title="{% trans "Create Virtual Machine" %}">
<span >{% bs_icon 'plus'%} </span>
</a>
</td>
<td style="width:5px;">
<form action="{% url 'instances:flavor_delete' flavor.id %}" method="post" role="form" aria-label="Delete flavor form">
{% csrf_token %}
<button type="submit" class="btn btn-sm btn-secondary" name="delete_flavor" title="{% trans "Delete" %}" onclick="return confirm('{% trans "Are you sure?" %}')">
{% bs_icon 'trash' %}
</button>
</form>
</td>
</tr>
{% endfor %}
</tbody>
</table>
</div>
{% endif %}
<div class="clearfix"></div>
</div>
<div role="tabpanel" class="tab-pane tab-pane-bordered" id="addCustom">
<div>
<form method="post" role="form" aria-label="Create custom instance form">{% csrf_token %}{% submission_key %}
<div class="row">
<label for="custom_name" class="col-sm-3 col-form-label">{% trans "Name" %}</label>
<div class="col-sm-7">
<input id="custom_name" type="text" class="form-control" name="name" placeholder="{% trans "Name" %}" maxlength="64" required pattern="[a-zA-Z0-9\.\-_]+">
</div>
</div>
{% if firmwares %}
<div class="row">
<label for="select_firmware" class="col-sm-3 col-form-label">{% trans "Firmware" %}</label>
<div class="col-sm-7">
<select class="form-select" id="select_firmware" name="firmware">
{% for frm in firmwares %}
<option value="{{ frm }}" {% if frm == default_firmware %}selected{% endif %}>{{ frm }}</option>
{% endfor %}
</select>
</div>
</div>
{% endif %}
<div class="row">
<label for="custom_vcpu" class="col-sm-3 col-form-label">{% trans "VCPU" %}</label>
<div class="col-sm-7">
<input id="custom_vcpu" type="text" class="form-control" name="vcpu" value="1" maxlength="2" required pattern="[0-9]">
</div>
</div>
{% if dom_caps.cpu_modes %}
<div class="row">
<label for="custom_vcpu_mode" class="col-sm-3 col-form-label">{% trans "VCPU Config" %}</label>
<div class="col-sm-7">
<select id="custom_vcpu_mode" class="form-select" name="vcpu_mode">
<option value=""> {% trans 'no-mode' %}</option>
{% for mode in dom_caps.cpu_modes %}
{% if mode == 'custom' %}
<optgroup label="Custom CPU Models">
{% for model in dom_caps.cpu_custom_models %}
<option value="{{ model }}"> {% trans model %}</option>
{% endfor %}
</optgroup>
{% else %}
<option value="{{ mode }}" {% if mode == default_cpu_mode %}selected {% endif %}>
{% trans mode %}
</option>
{% endif %}
{% endfor %}
</select>
</div>
</div>
{% endif %}
<div class="row">
<label for="custom_memory" class="col-sm-3 col-form-label">{% trans "RAM" %}</label>
<div class="col-sm-7">
<input id="custom_memory" type="text" class="form-control" name="memory" value="512" maxlength="5" required pattern="[0-9]+">
</div>
<label class="col-sm-1 col-form-label">{% trans "MB" %}</label>
</div>
<div id="disk_list_div" class="row d-none">
<label class="col-sm-3 col-form-label" id="added_disks">{% trans "Added Disks" %}</label>
<div class="col-sm-7">
<ul id="img-list" class="row">
<!-- populated from javascript -->
</ul>
</div>
</div>
<div class="row">
<label for="storage-control" class="col-sm-3 col-form-label">{% trans "HDD" %}</label>
<input id="images" name="images" type="hidden" value=""/>
<div class="col-sm-3">
<select class="form-select" id="storage-control" name="storage-control" onchange="get_cust_vols({{ compute_id }}, value);">
{% if storages %}
<option value disabled selected>{% trans "Select pool" %}...</option>
{% for storage in storages %}
<option value="{{ storage }}" >{{ storage }}</option>
{% endfor %}
{% else %}
<option value="">{% trans "None" %}</option>
{% endif %}
</select>
</div>
<div class="col-sm-4">
<select class="form-select" id="image-control" name="image-control" multiple="multiple">
<!-- populated from javascript -->
</select>
</div>
</div>
<div class="row">
<label for="network-control" class="col-sm-3 col-form-label">{% trans "Network" %}</label>
<div class="col-sm-7">
<ul id="net-list">
<!-- populated from javascript -->
</ul>
<input id="networks" type="hidden" name="networks" value=""/>
<select class="form-select" id="network-control" name="network-control" multiple="multiple">
{% for network in networks %}
<option value="{{ network }}">{{ network }}</option>
{% endfor %}
</select>
</div>
</div>
<div class="row">
<label class="col-sm-3 col-form-label">{% trans "Advanced" %}</label>
<div class="d-grid col-sm-7">
<button class="btn btn-outline-light" type="button" title="{% trans "Advanced" %}" data-bs-toggle="collapse" data-bs-target="#custadvcollapse" aria-expanded="false" aria-controls="custadvcollapse">
<span>{% bs_icon 'caret-down'%} </span>
</button>
</div>
</div>
<div class="collapse" id="custadvcollapse">
<div class="row meta-prealloc">
<label for="custom_meta_prealloc" class="col-sm-3 col-form-label">{% trans "Disk Metadata" %}</label>
<div class="col-sm-7">
<input id="custom_meta_prealloc" type="checkbox" name="meta_prealloc" title="{% trans "Metadata preallocation" %}" value="true">
</div>
<label class="col-lg-1 col-form-label">{% trans "Image" %}</label>
</div>
<div class="row">
<label for="cache_mode" class="col-sm-3 col-form-label">{% trans "HDD Cache Mode" %}</label>
<div class="col-sm-7">
<select class="form-select" id="cache_mode" name="cache_mode">
{% for mode, name in cache_modes %}
<option value="{{ mode }}" {% if mode == default_cache %}selected {% endif %}>
{% trans name %}</option>
{% endfor %}
</select>
</div>
</div>
<div class="row">
<label for="custom_nwfilter" class="col-sm-3 col-form-label">{% trans "NWFilter" %}</label>
<div class="col-sm-7">
<select id="custom_nwfilter" class="form-select" name="nwfilter">
<option value="">{% trans "None" %}</option>
{% for nwfilter in nwfilters %}
<option value="{{ nwfilter }}">{{ nwfilter }}</option>
{% endfor %}
</select>
</div>
</div>
<div class="row">
<label for="custom_net_model" class="col-sm-3 col-form-label">{% trans "NIC Type" %} </label>
<div class="col-sm-7">
<select id="custom_net_model" class="form-select" name="net_model">
{% for model in net_models_host %}
<option value="{{ model }}" {% if model == default_nic_type %} selected {% endif %}>{{ model }}</option>
{% endfor %}
</select>
</div>
</div>
<div class="row">
<label for="custom_video" class="col-sm-3 col-form-label">{% trans "Video" %}</label>
<div class="col-sm-7">
<select id="custom_video" class="form-select" name="video">
{% if not videos %}
<option value="vga">vga</option>
<option value="cirrus">cirrus</option>
{% endif %}
{% for video in videos %}
<option value="{{ video }}">{{ video }}</option>
{% endfor %}
</select>
</div>
</div>
<div class="row">
<label for="custom_listener_addr" class="col-sm-3 col-form-label">{% trans "Console Access" %}</label>
<div class="col-sm-7">
<select id="custom_listener_addr" class="form-select" name="listener_addr">
{% for addr, label in listener_addr %}
<option value="{{ addr }}" {% if addr == "0.0.0.0" %} selected {% endif %}>{{ label }}</option>
{% endfor %}
</select>
</div>
</div>
<div class="row">
<label for="add_cdrom" class="col-sm-3 col-form-label">{% trans "Add CD-Rom" %}</label>
<div class="col-sm-7">
<select class="form-select" id="add_cdrom" name="add_cdrom">
<option value="None" {% if bus == default_cdrom %}selected{% endif %} >--{% trans "False" %}--</option>
{% for bus in cdrom_buses %}
<option value="{{ bus }}" {% if bus == default_cdrom %}selected {% endif %}>
{% trans bus %}
</option>
{% endfor %}
</select>
</div>
</div>
<div class="row">
<label for="add_input" class="col-sm-3 col-form-label">{% trans "Add Input Device" %}</label>
<div class="col-sm-7">
<select class="form-select" id="add_input" name="add_input">
<option value="None" {% if bus == default_input_device_bus %}selected{% endif %}>--{% trans "False" %}--</option>
{% for bus in input_device_buses %}
<option value="{{ bus }}" {% if bus == default_input_device_bus %}selected{% endif %}>
{% trans bus %}
</option>
{% endfor %}
</select>
</div>
</div>
<div class="row">
<label for="custom_qemu_ga" class="col-sm-3 col-form-label">{% trans "Guest Agent" %}</label>
<div class="col-sm-6">
<input id="custom_qemu_ga" type="checkbox" name="qemu_ga" value="true" checked>
</div>
</div>
{% if virtio_support %}
<div class="row">
<label for="custom_virtio" class="col-sm-3 col-form-label">{% trans "VirtIO" %}</label>
<div class="col-sm-6">
<input id="custom_virtio" type="checkbox" name="virtio" value="{{ virtio_support }}" checked>
</div>
</div>
{% endif %}
</div>
<div class="row">
<div class="d-grid col-sm-7 offset-3">
{% if storages %}
<button type="submit" class="btn btn-primary" name="create" formnovalidate value="1">
{% trans "Create" %}
</button>
{% else %}
<button class="btn btn-primary disabled">
{% trans "Create" %}
</button>
{% endif %}
</div>
</div>
</form>
</div>
<div class="clearfix"></div>
</div>
<div role="tabpanel" class="tab-pane tab-pane-bordered" id="add-from-temp">
<div>
<form method="post" role="form" aria-label="Create instance from template form">{% csrf_token %}{% submission_key %}
<div class="row">
<label for="template_name" class="col-sm-3 col-form-label">{% trans "Name" %}</label>
<div class="col-sm-7">
<input id="template_name" type="text" class="form-control" name="name" placeholder="{% trans "Name" %}" maxlength="64" required pattern="[a-zA-Z0-9\.\-_]+">
</div>
</div>
{% if firmwares %}
<div class="row">
<label for="template_firmware" class="col-sm-3 col-form-label">{% trans "Firmware" %}</label>
<div class="col-sm-7">
<select id="template_firmware" class="form-select" name="firmware">
{% for frm in firmwares %}
<option value="{{ frm }}" {% if frm == default_firmware %}selected{% endif %}>{{ frm }}</option>
{% endfor %}
</select>
</div>
</div>
{% endif %}
<div class="row">
<label for="template_vcpu" class="col-sm-3 col-form-label">{% trans "VCPU" %}</label>
<div class="col-sm-7">
<input id="template_vcpu" type="text" class="form-control" name="vcpu" value="1" maxlength="2" required pattern="[0-9]">
</div>
</div>
<div class="row">
<label for="template_vcpu_mode" class="col-sm-3 col-form-label">{% trans "VCPU Config" %}</label>
<div class="col-sm-7">
<select id="template_vcpu_mode" class="form-select" name="vcpu_mode">
<option value=""> {% trans 'no-mode' %}</option>
{% for mode in dom_caps.cpu_modes %}
{% if mode == 'custom' %}
<optgroup label="Custom CPU Models">
{% for model in dom_caps.cpu_custom_models %}
<option value="{{ model }}"> {% trans model %}</option>
{% endfor %}
</optgroup>
{% else %}
<option value="{{ mode }}" {% if mode == default_cpu_mode %}selected{% endif %}>
{% trans mode %}
</option>
{% endif %}
{% endfor %}
</select>
</div>
</div>
<div class="row">
<label for="template_memory" class="col-sm-3 col-form-label">{% trans "RAM" %}</label>
<div class="col-sm-7">
<input id="template_memory" type="text" class="form-control" name="memory" value="512" maxlength="5" required pattern="[0-9]+">
</div>
<label class="col-sm-1 col-form-label">{% trans "MB" %}</label>
</div>
<div class="row">
<label for="template_disk" class="col-sm-3 col-form-label">{% trans "Template Disk" %}</label>
<div class="col-sm-3">
<select class="form-select" id="template_disk" onchange="get_template_vols({{ compute_id }}, value);">
{% if storages %}
<option value disabled selected>{% trans "Select pool" %}...</option>
{% for storage in storages %}
<option value="{{ storage }}" >{{ storage }}</option>
{% endfor %}
{% else %}
<option value="">{% trans "None" %}</option>
{% endif %}
</select>
</div>
<div class="col-sm-4">
<select class="form-select" id="template" name="template" disabled>
<!-- populated from javascript -->
</select>
</div>
</div>
<div class="row">
<label for="storage" class="col-sm-3 col-form-label">{% trans "Storage" %}</label>
<div class="col-sm-7">
<select class="form-select" id="storage" name="storage" disabled>
{% if storages %}
{% for storage in storages %}
<option value="{{ storage }}" >{{ storage }}</option>
{% endfor %}
{% else %}
<option value="">{% trans "None" %}</option>
{% endif %}
</select>
</div>
</div>
<div class="row">
<label for="template_networks" class="col-sm-3 col-form-label">{% trans "Network/MAC" %}</label>
<div class="col-sm-3">
<select id="template_networks" class="form-select" name="networks">
{% for network in networks %}
<option value="{{ network }}">{{ network }}</option>
{% endfor %}
</select>
</div>
<div class="col-sm-4">
<input type="text" class="form-control" name="mac" maxlength="17" value="{{ mac_auto }}" required pattern="[a-zA-Z0-9:]+">
</div>
</div>
<div class="row">
<label class="col-sm-3 col-form-label">{% trans "Advanced" %}</label>
<div class="d-grid col-sm-7">
<button class="btn btn-outline-light" type="button" title="{% trans "Advanced" %}" data-bs-toggle="collapse" data-bs-target="#tempAdvCollapse" aria-expanded="false" aria-controls="tempAdvCollapse">
<span>{% bs_icon 'caret-down'%} </span>
</button>
</div>
</div>
<div class="collapse" id="tempAdvCollapse">
<div class="row meta-prealloc">
<label for="template_meta_prealloc" class="col-sm-3 col-form-label">{% trans "Disk Metadata" %}</label>
<div class="col-sm-7">
<input id="template_meta_prealloc" type="checkbox" name="meta_prealloc" title="{% trans "Metadata preallocation" %}" value="true">
</div>
<label class="col-lg-1 col-form-label">{% trans "Image" %}</label>
</div>
<div class="row">
<label for="template_cache_mode" class="col-sm-3 col-form-label">{% trans "HDD cache mode" %}</label>
<div class="col-sm-7">
<select id="template_cache_mode" class="form-select" name="cache_mode">
{% for mode, name in cache_modes %}
<option value="{{ mode }}" {% if mode == default_cache %}selected{% endif %}>
{% trans name %}</option>
{% endfor %}
</select>
</div>
</div>
<div class="row">
<label for="template_nwfilter" class="col-sm-3 col-form-label">{% trans "NWFilter" %}</label>
<div class="col-sm-7">
<select id="template_nwfilter" class="form-select" name="nwfilter">
<option value="">{% trans "None" %}</option>
{% for nwfilter in nwfilters %}
<option value="{{ nwfilter }}">{{ nwfilter }}</option>
{% endfor %}
</select>
</div>
</div>
<div class="row">
<label for="template_net_model" class="col-sm-3 col-form-label">{% trans "NIC Type" %} </label>
<div class="col-sm-7">
<select id="template_net_model" class="form-select" name="net_model">
{% for model in net_models_host %}
<option value="{{ model }}" {% if model == default_nic_type %} selected {% endif %}>{{ model }}</option>
{% endfor %}
</select>
</div>
</div>
<div class="row">
<label for="template_video" class="col-sm-3 col-form-label">{% trans "Video" %}</label>
<div class="col-sm-7">
<select id="template_video" class="form-select" name="video">
{% if not videos %}
<option value="vga">vga</option>
<option value="cirrus">cirrus</option>
{% endif %}
{% for video in videos %}
<option value="{{ video }}">{{ video }}</option>
{% endfor %}
</select>
</div>
</div>
<div class="row">
<label for="template_listener_addr" class="col-sm-3 col-form-label">{% trans "Console Access" %}</label>
<div class="col-sm-7">
<select id="template_listener_addr" class="form-select" name="listener_addr">
{% for addr, label in listener_addr %}
<option value="{{ addr }}" {% if addr == "0.0.0.0" %} selected {% endif %}>{{ label }}</option>
{% endfor %}
</select>
</div>
</div>
<div class="row">
<label for="template_add_cdrom" class="col-sm-3 col-form-label">{% trans "Add CD-Rom" %}</label>
<div class="col-sm-7">
<select id="template_add_cdrom" class="form-select" name="add_cdrom">
<option value="None" {% if bus == default_cdrom %}selected{% endif %}>--{% trans "False" %}--</option>
{% for bus in cdrom_buses %}
<option value="{{ bus }}" {% if bus == default_cdrom %}selected {% endif %}>
{% trans bus %}
</option>
{% endfor %}
</select>
</div>
</div>
<div class="row">
<label for="template_add_input" class="col-sm-3 col-form-label">{% trans "Add Input Device" %}</label>
<div class="col-sm-7">
<select id="template_add_input" class="form-select" name="add_input">
<option value="None" {% if bus == default_input_device_bus %}selected{% endif %}>--{% trans "False" %}--</option>
{% for bus in input_device_buses %}
<option value="{{ bus }}" {% if bus == default_input_device_bus %}selected{% endif %}>
{% trans bus %}
</option>
{% endfor %}
</select>
</div>
</div>
<div class="row">
<label for="template_qemu_ga" class="col-sm-3 col-form-label">{% trans "Guest Agent" %}</label>
<div class="col-sm-6">
<input id="template_qemu_ga" type="checkbox" name="qemu_ga" value="true" checked>
</div>
</div>
{% if virtio_support %}
<div class="row">
<label for="template_virtio" class="col-sm-3 col-form-label">{% trans "VirtIO" %}</label>
<div class="col-sm-6">
<input id="template_virtio" type="checkbox" name="virtio" value="{{ virtio_support }}" checked>
</div>
</div>
{% endif %}
</div>
<div class="row">
<div class="d-grid col-sm-7 offset-3">
{% if storages %}
<button type="submit" class="btn btn-primary" name="create" value="1" formnovalidate>
{% trans "Create" %}
</button>
{% else %}
<button class="btn btn-primary disabled">
{% trans "Create" %}
</button>
{% endif %}
</div>
</div>
</form>
</div>
<div class="clearfix"></div>
</div>
</div><!-- /Tab panes -->
</div>
</div>
</div>
{% endblock %}
{% block script %}
<script src="{% static 'js/tom-select.complete.min.js' %}"></script>
<script>
function toggleValue(string, updated_value, checked) {
let result = '';
if (checked) {
result = string;
if (result != '') result += ',';
result += updated_value;
} else {
$.each(string.split(','), function (index, value) {
if (value == updated_value) return;
if (result != '') result += ',';
result += value;
});
}
return result;
}
$(document).ready(function () {
images_control = new TomSelect('#image-control', {
plugins: ['checkbox_options'],
placeholder: 'Add image...',
hidePlaceholder: false,
onItemAdd: function (value) { update_images(value, true); },
onItemRemove: function (value) { update_images(value, false); },
});
function update_images(value, checked) {
let input_value = toggleValue($('#images').val(), value, checked);
$('#images').val(input_value);
let selected_list_html = '';
let counter = 0;
if (input_value != '') {
$('#disk_list_div').removeClass('d-none');
$.each(input_value.split(','), function (index, value) {
var li = '<li>hdd' + counter + ' - ' +
'<select name="device' + counter + '" class="image-format" onchange="get_disk_bus_choices({{ compute_id }},' + counter + ', value);">' +
'{% for dev in disk_devices %}' +
'<option value=' + '"{{ dev }}">' + '{% trans dev %}</option>' +
'{% endfor %}' +
'</select>' +
'<select id="bus' + counter + '" name="bus' + counter + '" class="image-format">' +
'{% for bus in disk_buses %}' +
'<option value=' + '"{{ bus }}"' +
'{% if bus == default_bus %}selected{% endif %}>' +
'{% trans bus %}</option>' +
'{% endfor %}' +
'</select>' +
' -> ' + value + ' ' +
'<a class="btn-link float-end" onclick="images_control.removeItem(\'' + value + '\')"> X </a></li>';
selected_list_html += li;
counter++;
});
}else {
$('#disk_list_div').addClass('d-none');
}
$('#img-list').html(selected_list_html);
}
networks_control = new TomSelect('#network-control', {
plugins: ['checkbox_options'],
placeholder: 'Add network',
hidePlaceholder: false,
onItemAdd: function (value) { update_networks(value, true); },
onItemRemove: function (value) { update_networks(value, false); },
});
function update_networks(value, checked) {
let input_value = toggleValue($('#networks').val(), value, checked);
$('#networks').val(input_value);
let selected_list_html = '';
mac_array = [];
net_counter = 0;
if (input_value != '') {
$.each(input_value.split(','), function (index, value) {
let li = '<li><input type="text" class="input-xs" name="mac'+ net_counter +'" maxlength="17" required pattern="[a-zA-Z0-9:]+" onchange="populate_mac(' + net_counter +')">' +
' eth' + net_counter +
' -> ' + value + ' ' +
'<a class="btn-link float-end" onclick="networks_control.removeItem(\'' + value + '\')"> X </a></li>';
random_mac(net_counter);
selected_list_html += li;
net_counter++;
});
}
$('#net-list').html(selected_list_html);
}
});
var images_control, networks_control;
var mac_array = [];
function random_mac(c) {
$.getJSON("{% url 'instances:random_mac_address' %}", function (data) {
mac_array[c] = data['mac'];
$('input[name="mac' + c + '"').val(data['mac']);
populate_mac(c);
});
}
function populate_mac(c){
mac_array[c] = $('input[name="mac' + c + '"').val();
$('input[name="mac"').val(mac_array.join(","));
}
function get_cust_vols(compute_id, pool) {
get_vol_url = "/computes/" + compute_id + "/storage/" + pool + "/volumes";
$.getJSON(get_vol_url, function (data) {
images_control.clearOptions();
$.each(data['vols'], function(i, item) {
images_control.addOption({value: item, text: item});
});
});
}
function get_template_vols(compute_id, pool) {
get_vol_url = "/computes/" + compute_id + "/storage/" + pool + "/volumes";
$.getJSON(get_vol_url, function (data) {
$("#template").find('option').remove();
$.each(data['vols'], function(i, item) {
$("#template").append($("<option>").val(item).text(item));
});
});
$("#template").removeAttr("disabled");
$("#storage").val(pool).change();
$("#storage").removeAttr("disabled");
}
function get_disk_bus_choices(compute_id, dev_idx, disk_type){
let arch = $('select[name="arch"]').val();
let machine = $("select[id='machine-control']").val();
get_diskBus_url = "/computes/" + compute_id + "/archs/" + arch + "/machines/" + machine + "/disks/" + disk_type + "/buses";
$.getJSON(get_diskBus_url, function (data) {
$("#bus" + dev_idx).find('option').remove();
$.each(data['bus'], function(i, item) {
$("#bus" + dev_idx).append($("<option>").val(item).text(item));
});
});
}
</script>
{% if request.user.is_superuser %}
<script>
function goto_compute() {
let compute = {{ compute.id }};
window.location.href = "{% url 'instances:create_instance_select_type' 1 %}".replace(1, compute);
}
</script>
{% endif %}
{% endblock %}