mirror of
https://github.com/retspen/webvirtcloud
synced 2025-07-31 12:41:08 +00:00
Enrich Instance Create operation: -add capability to create arm, ppc, i686, aarch64 instances, -add option to choose firmware, -add options to choose chipset. -add capability to choose volume driver options. -add new default settings
This commit is contained in:
parent
28b001e7cb
commit
dd16a5b2d5
14 changed files with 828 additions and 211 deletions
|
|
@ -33,8 +33,9 @@ class FlavorAddForm(forms.Form):
|
|||
class NewVMForm(forms.Form):
|
||||
name = forms.CharField(error_messages={'required': _('No Virtual Machine name has been entered')},
|
||||
max_length=64)
|
||||
firmware = forms.CharField(max_length=50, required=False)
|
||||
vcpu = forms.IntegerField(error_messages={'required': _('No VCPU has been entered')})
|
||||
host_model = forms.BooleanField(required=False)
|
||||
vcpu_mode = forms.CharField(max_length=20, required=False)
|
||||
disk = forms.IntegerField(required=False)
|
||||
memory = forms.IntegerField(error_messages={'required': _('No RAM size has been entered')})
|
||||
networks = forms.CharField(error_messages={'required': _('No Network pool has been choosen')})
|
||||
|
|
@ -48,8 +49,9 @@ class NewVMForm(forms.Form):
|
|||
virtio = forms.BooleanField(required=False)
|
||||
qemu_ga = forms.BooleanField(required=False)
|
||||
mac = forms.CharField(required=False)
|
||||
console_pass = forms.CharField(required=False,empty_value="", widget=forms.PasswordInput())
|
||||
video = forms.CharField(error_messages={'required': _('Please select a graphic display')})
|
||||
console_pass = forms.CharField(required=False, empty_value="", widget=forms.PasswordInput())
|
||||
graphics = forms.CharField(error_messages={'required': _('Please select a graphics type')})
|
||||
video = forms.CharField(error_messages={'required': _('Please select a video driver')})
|
||||
listener_addr = forms.ChoiceField(required=True, widget=forms.RadioSelect, choices=QEMU_CONSOLE_LISTEN_ADDRESSES)
|
||||
|
||||
def clean_name(self):
|
||||
|
|
|
|||
151
create/templates/create_instance_w1.html
Normal file
151
create/templates/create_instance_w1.html
Normal file
|
|
@ -0,0 +1,151 @@
|
|||
{% extends "base.html" %}
|
||||
{% load i18n %}
|
||||
{% load staticfiles %}
|
||||
{% block title %}{% trans "Create new instance - Select Type" %}{% endblock %}
|
||||
|
||||
{% block content %}
|
||||
<!-- Page Heading -->
|
||||
<div class="row">
|
||||
<div class="col-lg-12">
|
||||
<h1 class="page-header">{% trans "New instance on" %} {{ compute.name }}</h1>
|
||||
</div>
|
||||
</div>
|
||||
<!-- /.row -->
|
||||
{% include 'errors_block.html' %}
|
||||
{% include 'pleasewaitdialog.html' %}
|
||||
|
||||
|
||||
{% if form.errors %}
|
||||
{% for field in form %}
|
||||
{% for error in field.errors %}
|
||||
<div class="alert alert-danger">
|
||||
<strong>{{ error|escape }}</strong>
|
||||
</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" id="max-width-page">
|
||||
<div class="col-lg-12">
|
||||
<div role="tabpanel">
|
||||
<!-- Nav tabs -->
|
||||
<ul class="nav nav-tabs" role="tablist">
|
||||
<li role="presentation" class="active">
|
||||
<a href="#select_architecture" aria-controls="flavor" role="tab" data-toggle="tab">
|
||||
{% trans "Architecture" %}
|
||||
</a>
|
||||
</li>
|
||||
<li role="presentation">
|
||||
<a href="#addFromXML" aria-controls="addFromXML" role="tab" data-toggle="tab">
|
||||
{% trans "XML" %}
|
||||
</a>
|
||||
</li>
|
||||
</ul>
|
||||
<!-- Tab panes -->
|
||||
<div class="tab-content">
|
||||
<div role="tabpanel" class="tab-pane tab-pane-bordered active" id="select_architecture">
|
||||
<div class="well">
|
||||
<div class="center-block">
|
||||
<form class="form-horizontal" method="post" role="form">{% csrf_token %}
|
||||
<div class="form-group">
|
||||
<label class="col-sm-3 control-label">{% trans "Architecture" %}</label>
|
||||
<div class="col-sm-6">
|
||||
<select class="form-control" id="select_archs" name="archs" onchange="get_machine_types({{ compute_id }}, value);">
|
||||
{% for hpv in hypervisors %}
|
||||
<option value="{{ hpv }}" {% if hpv == default_arch %}selected{% endif %}>{{ hpv }}</option>
|
||||
{% endfor %}
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label class="col-sm-3 control-label">{% trans "Chipset" %}</label>
|
||||
<div class="col-sm-6">
|
||||
<select class="form-control" id="select_chipset" name="chipset">
|
||||
<!-- fill with script -->
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<div class="col-sm-6 col-lg-offset-3">
|
||||
<button class="btn btn-block btn-primary" type="button" name="create_instance" onclick="goto_create()">
|
||||
{% trans "Next >" %}
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
<div class="clearfix"></div>
|
||||
</div>
|
||||
<div role="tabpanel" class="tab-pane tab-pane-bordered" id="addFromXML">
|
||||
<div class="well">
|
||||
<form class="form-horizontal" method="post" role="form">{% csrf_token %}
|
||||
<div class="col-sm-12" id="xmlheight">
|
||||
<input type="hidden" name="dom_xml"/>
|
||||
<textarea id="editor"></textarea>
|
||||
</div>
|
||||
<button type="submit" class="btn btn-primary" name="create_xml" onclick="showPleaseWaitDialog()">
|
||||
{% trans "Create" %}
|
||||
</button>
|
||||
</form>
|
||||
</div>
|
||||
<div class="clearfix"/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{% endblock %}
|
||||
{% block script %}
|
||||
<script>
|
||||
$(document).ready(function () {
|
||||
let arch = $("#select_archs").val();
|
||||
get_machine_types({{ compute_id }}, arch);
|
||||
});
|
||||
|
||||
function get_machine_types(compute_id, arch) {
|
||||
get_machine_type_url = "/computes/" + compute_id + "/archs/" + arch + "/machines";
|
||||
$.getJSON(get_machine_type_url, function (data) {
|
||||
$("#select_chipset").find('option').remove();
|
||||
$("#select_archs").val(arch);
|
||||
$.each(data['machines'], function(i, item) {
|
||||
if (item == '{{ default_machine }}') {
|
||||
var selected = 'selected';
|
||||
}else{
|
||||
var selected = '';
|
||||
}
|
||||
$("#select_chipset").append('<option value="' + item + '"' + selected +'>' + item + '</option>');
|
||||
});
|
||||
});
|
||||
}
|
||||
</script>
|
||||
|
||||
<script src="{% static "js/ace.js" %}"></script>
|
||||
<script>
|
||||
var editor = ace.edit("editor");
|
||||
editor.getSession().setMode("ace/mode/xml");
|
||||
|
||||
var input = $('input[name="dom_xml"]');
|
||||
editor.getSession().on("change",function () {
|
||||
input.val(editor.getSession().getValue());
|
||||
})
|
||||
</script>
|
||||
{% if request.user.is_superuser %}
|
||||
<script>
|
||||
function goto_create() {
|
||||
let compute = '{{ compute.id }}';
|
||||
let arch = $("#select_archs").val();
|
||||
let machine = $("#select_chipset").val();
|
||||
create_machine_url = "/computes/" + compute + "/create/archs/" + arch + "/machines/" + machine;
|
||||
{#url = "{% url 'create_instance' compute.id 'x86_64' 'pc' %}".replace(/x86_64/, arch).replace(/pc/, machine);#}
|
||||
window.location.href = create_machine_url;
|
||||
}
|
||||
|
||||
</script>
|
||||
{% endif %}
|
||||
{% endblock %}
|
||||
|
|
@ -9,7 +9,9 @@
|
|||
<!-- Page Heading -->
|
||||
<div class="row">
|
||||
<div class="col-lg-12">
|
||||
<h1 class="page-header">{% trans "New instance on" %} {{ compute.name }}</h1>
|
||||
<h1 class="page-header">
|
||||
{% trans "New instance on" %} {{ compute.name }}
|
||||
</h1>
|
||||
</div>
|
||||
</div>
|
||||
<!-- /.row -->
|
||||
|
|
@ -37,6 +39,11 @@
|
|||
<div role="tabpanel">
|
||||
<!-- Nav tabs -->
|
||||
<ul class="nav nav-tabs" role="tablist">
|
||||
<li role="presentation">
|
||||
<a class="pull-right" href="#" role="tab" data-toggle="tab" onclick="goto_compute()">
|
||||
<span class="glyphicon glyphicon-arrow-left"></span>
|
||||
</a>
|
||||
</li>
|
||||
<li role="presentation" class="active">
|
||||
<a href="#flavor" aria-controls="flavor" role="tab" data-toggle="tab">
|
||||
{% trans "Flavor" %}
|
||||
|
|
@ -52,11 +59,6 @@
|
|||
{% trans "Template" %}
|
||||
</a>
|
||||
</li>
|
||||
<li role="presentation">
|
||||
<a href="#addFromXML" aria-controls="addFromXML" role="tab" data-toggle="tab">
|
||||
{% trans "XML" %}
|
||||
</a>
|
||||
</li>
|
||||
</ul>
|
||||
<!-- Tab panes -->
|
||||
<div class="tab-content">
|
||||
|
|
@ -112,9 +114,43 @@
|
|||
<input type="hidden" name="hdd_size" value="{{ flavor.disk }}">
|
||||
</div>
|
||||
</div>
|
||||
{% if firmwares %}
|
||||
<div class="form-group">
|
||||
<label class="col-sm-3 control-label">{% trans "Firmware" %}</label>
|
||||
<div class="col-sm-6">
|
||||
<select class="form-control" 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 %}
|
||||
{% if dom_caps.cpu_modes %}
|
||||
<div class="form-group">
|
||||
<label class="col-sm-3 control-label">{% trans "VCPU Config" %}</label>
|
||||
<div class="col-sm-6">
|
||||
<select id="vcpu_mode" name="vcpu_mode" class="form-control">
|
||||
<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 }}" {% ifequal mode default_cpu_mode %}selected {% endifequal %}>
|
||||
{% trans mode %}
|
||||
</option>
|
||||
{% endif %}
|
||||
{% endfor %}
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
{% endif %}
|
||||
<div class="form-group">
|
||||
<label class="col-sm-3 control-label">{% trans "Storage" %}</label>
|
||||
|
||||
<div class="col-sm-6">
|
||||
<input type="hidden" name="cache_mode" value="default">
|
||||
<select name="storage" class="form-control">
|
||||
|
|
@ -166,6 +202,18 @@
|
|||
<input type="text" class="form-control" name="mac" maxlength="17" value="{{ mac_auto }}" required pattern="[a-zA-Z0-9:]+">
|
||||
</div>
|
||||
</div>
|
||||
{% if dom_caps.graphics_support == 'yes' %}
|
||||
<div class="form-group">
|
||||
<label class="col-sm-3 control-label">{% trans "Graphics" %}</label>
|
||||
<div class="col-sm-6">
|
||||
<select name="graphics" class="form-control">
|
||||
{% for graphics in dom_caps.graphics_types %}
|
||||
<option value="{{ graphics }}" {% if default_graphics == graphics %}selected{% endif %}>{{ graphics }}</option>
|
||||
{% endfor %}
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
{% endif %}
|
||||
<div class="form-group">
|
||||
<label class="col-sm-3 control-label">{% trans "Video" %}</label>
|
||||
<div class="col-sm-6">
|
||||
|
|
@ -196,13 +244,6 @@
|
|||
</select>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label class="col-sm-3 control-label">{% trans "Host-Model" %}</label>
|
||||
<div class="col-sm-6">
|
||||
<input type="checkbox" name="host_model" value="true" checked>
|
||||
</div>
|
||||
<label class="col-lg-1 control-label">{% trans "CPU" %}</label>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label class="col-sm-3 control-label">{% trans "Guest Agent" %}</label>
|
||||
<div class="col-sm-6">
|
||||
|
|
@ -258,19 +299,47 @@
|
|||
<input type="text" class="form-control" name="name" placeholder="{% trans "Name" %}" maxlength="64" required pattern="[a-zA-Z0-9\.\-_]+">
|
||||
</div>
|
||||
</div>
|
||||
{% if firmwares %}
|
||||
<div class="form-group">
|
||||
<label class="col-sm-3 control-label">{% trans "Firmware" %}</label>
|
||||
<div class="col-sm-7">
|
||||
<select class="form-control" 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="form-group">
|
||||
<label class="col-sm-3 control-label">{% trans "VCPU" %}</label>
|
||||
<div class="col-sm-7">
|
||||
<input type="text" class="form-control" name="vcpu" value="1" maxlength="2" required pattern="[0-9]">
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label class="col-sm-3 control-label">{% trans "Host-Model" %}</label>
|
||||
{% if dom_caps.cpu_modes %}
|
||||
<div class="form-group">
|
||||
<label class="col-sm-3 control-label">{% trans "VCPU Config" %}</label>
|
||||
<div class="col-sm-7">
|
||||
<input type="checkbox" name="host_model" value="true" checked>
|
||||
<select id="vcpu_mode" name="vcpu_mode" class="form-control">
|
||||
<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 }}" {% ifequal mode default_cpu_mode %}selected {% endifequal %}>
|
||||
{% trans mode %}
|
||||
</option>
|
||||
{% endif %}
|
||||
{% endfor %}
|
||||
</select>
|
||||
</div>
|
||||
<label class="col-sm-1 control-label">{% trans "CPU" %}</label>
|
||||
</div>
|
||||
{% endif %}
|
||||
<div class="form-group">
|
||||
<label class="col-sm-3 control-label">{% trans "RAM" %}</label>
|
||||
<div class="col-sm-7">
|
||||
|
|
@ -351,6 +420,18 @@
|
|||
</select>
|
||||
</div>
|
||||
</div>
|
||||
{% if dom_caps.graphics_support == 'yes' %}
|
||||
<div class="form-group">
|
||||
<label class="col-sm-3 control-label">{% trans "Graphics" %}</label>
|
||||
<div class="col-sm-7">
|
||||
<select name="graphics" class="form-control">
|
||||
{% for graphics in dom_caps.graphics_types %}
|
||||
<option value="{{ graphics }}" {% if default_graphics == graphics %}selected{% endif %}>{{ graphics }}</option>
|
||||
{% endfor %}
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
{% endif %}
|
||||
<div class="form-group">
|
||||
<label class="col-sm-3 control-label">{% trans "Video" %}</label>
|
||||
<div class="col-sm-7">
|
||||
|
|
@ -393,15 +474,18 @@
|
|||
<input type="checkbox" name="virtio" value="true" checked>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<div class="col-sm-7 col-sm-offset-3">
|
||||
{% if storages %}
|
||||
<button type="submit" class="btn btn-primary" name="create" formnovalidate onclick="showPleaseWaitDialog()" value="1">
|
||||
<button type="submit" class="btn btn-block btn-primary" name="create" formnovalidate onclick="showPleaseWaitDialog()" value="1">
|
||||
{% trans "Create" %}
|
||||
</button>
|
||||
{% else %}
|
||||
<button class="btn btn-primary disabled">
|
||||
<button class="btn btn-block btn-primary disabled">
|
||||
{% trans "Create" %}
|
||||
</button>
|
||||
{% endif %}
|
||||
</div></div>
|
||||
</form>
|
||||
</div>
|
||||
<div class="clearfix"></div>
|
||||
|
|
@ -416,6 +500,18 @@
|
|||
<input type="text" class="form-control" name="name" placeholder="{% trans "Name" %}" maxlength="64" required pattern="[a-zA-Z0-9\.\-_]+">
|
||||
</div>
|
||||
</div>
|
||||
{% if firmwares %}
|
||||
<div class="form-group">
|
||||
<label class="col-sm-3 control-label">{% trans "Firmware" %}</label>
|
||||
<div class="col-sm-7">
|
||||
<select class="form-control" 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="form-group">
|
||||
<label class="col-sm-3 control-label">{% trans "VCPU" %}</label>
|
||||
<div class="col-sm-7">
|
||||
|
|
@ -423,11 +519,25 @@
|
|||
</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label class="col-sm-3 control-label">{% trans "Host-Model" %}</label>
|
||||
<label class="col-sm-3 control-label">{% trans "VCPU Config" %}</label>
|
||||
<div class="col-sm-7">
|
||||
<input type="checkbox" name="host_model" value="true" checked>
|
||||
<select id="vcpu_mode" name="vcpu_mode" class="form-control">
|
||||
<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 }}" {% ifequal mode default_cpu_mode %}selected {% endifequal %}>
|
||||
{% trans mode %}
|
||||
</option>
|
||||
{% endif %}
|
||||
{% endfor %}
|
||||
</select>
|
||||
</div>
|
||||
<label class="col-sm-1 control-label">{% trans "CPU" %}</label>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label class="col-sm-3 control-label">{% trans "RAM" %}</label>
|
||||
|
|
@ -437,7 +547,7 @@
|
|||
<label class="col-sm-1 control-label">{% trans "MB" %}</label>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label class="col-sm-3 control-label">{% trans "HDD" %}</label>
|
||||
<label class="col-sm-3 control-label">{% trans "Template Disk" %}</label>
|
||||
<input id="images" name="images" type="hidden" value=""/>
|
||||
<div class="col-sm-3">
|
||||
<select class="form-control" onchange="get_template_vols({{ compute_id }}, value);">
|
||||
|
|
@ -510,6 +620,18 @@
|
|||
</select>
|
||||
</div>
|
||||
</div>
|
||||
{% if dom_caps.graphics_support == 'yes' %}
|
||||
<div class="form-group">
|
||||
<label class="col-sm-3 control-label">{% trans "Graphics" %}</label>
|
||||
<div class="col-sm-7">
|
||||
<select name="graphics" class="form-control">
|
||||
{% for graphics in dom_caps.graphics_types %}
|
||||
<option value="{{ graphics }}" {% if default_graphics == graphics %}selected{% endif %}>{{ graphics }}</option>
|
||||
{% endfor %}
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
{% endif %}
|
||||
<div class="form-group">
|
||||
<label class="col-sm-3 control-label">{% trans "Video" %}</label>
|
||||
<div class="col-sm-7">
|
||||
|
|
@ -552,31 +674,19 @@
|
|||
<input type="checkbox" name="virtio" value="true" checked>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{% if storages %}
|
||||
<button type="submit" class="btn btn-primary" name="create" value="1" formnovalidate onclick="showPleaseWaitDialog()">
|
||||
{% trans "Create" %}
|
||||
</button>
|
||||
{% else %}
|
||||
<button class="btn btn-primary disabled">
|
||||
{% trans "Create" %}
|
||||
</button>
|
||||
{% endif %}
|
||||
</form>
|
||||
</div>
|
||||
<div class="clearfix"></div>
|
||||
</div>
|
||||
|
||||
<div role="tabpanel" class="tab-pane tab-pane-bordered" id="addFromXML">
|
||||
<div class="well">
|
||||
<form class="form-horizontal" method="post" role="form">{% csrf_token %}
|
||||
<div class="col-sm-12" id="xmlheight">
|
||||
<input type="hidden" name="dom_xml"/>
|
||||
<textarea id="editor"></textarea>
|
||||
<div class="form-group">
|
||||
<div class="col-sm-7 col-sm-offset-3">
|
||||
{% if storages %}
|
||||
<button type="submit" class="btn btn-block btn-primary" name="create" value="1" formnovalidate onclick="showPleaseWaitDialog()">
|
||||
{% trans "Create" %}
|
||||
</button>
|
||||
{% else %}
|
||||
<button class="btn btn-primary disabled">
|
||||
{% trans "Create" %}
|
||||
</button>
|
||||
{% endif %}
|
||||
</div>
|
||||
</div>
|
||||
<button type="submit" class="btn btn-primary" name="create_xml" onclick="showPleaseWaitDialog()">
|
||||
{% trans "Create" %}
|
||||
</button>
|
||||
</form>
|
||||
</div>
|
||||
<div class="clearfix"></div>
|
||||
|
|
@ -589,7 +699,7 @@
|
|||
<script src="{% static "js/bootstrap-multiselect.js" %}"></script>
|
||||
<script>
|
||||
function toggleValue(string, updated_value, checked) {
|
||||
var result = '';
|
||||
let result = '';
|
||||
if (checked) {
|
||||
result = string;
|
||||
if (result != '') result += ',';
|
||||
|
|
@ -620,15 +730,15 @@
|
|||
return '';
|
||||
},
|
||||
onChange: function (element, checked) {
|
||||
var input_value = toggleValue($('#images').val(), element.val(), checked);
|
||||
let input_value = toggleValue($('#images').val(), element.val(), checked);
|
||||
$('#images').val(input_value);
|
||||
|
||||
var selected_list_html = '';
|
||||
var counter = 0;
|
||||
let selected_list_html = '';
|
||||
let counter = 0;
|
||||
if (input_value != '') {
|
||||
$('#disk_list_div').show();
|
||||
$.each(input_value.split(','), function (index, value) {
|
||||
var li = '<li>hdd' + counter + ' - ' +
|
||||
let 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>' +
|
||||
|
|
@ -668,13 +778,13 @@
|
|||
return '100%';
|
||||
},
|
||||
onChange: function (element, checked) {
|
||||
var input_value = toggleValue($('#networks').val(), element.val(), checked);
|
||||
let input_value = toggleValue($('#networks').val(), element.val(), checked);
|
||||
$('#networks').val(input_value);
|
||||
var selected_list_html = '';
|
||||
var counter = 0;
|
||||
let selected_list_html = '';
|
||||
let counter = 0;
|
||||
if (input_value != '') {
|
||||
$.each(input_value.split(','), function (index, value) {
|
||||
var li = '<li>eth' + counter +
|
||||
let li = '<li>eth' + counter +
|
||||
' -> ' + value + ' ' +
|
||||
'<a class="btn-link pull-right" onclick="javascript:$(\'#network-control\').multiselect(\'deselect\', \'' + value + '\', true)"><i class="fa fa-remove"></i></a></a></li>';
|
||||
selected_list_html += li;
|
||||
|
|
@ -686,6 +796,8 @@
|
|||
});
|
||||
});
|
||||
|
||||
$("id[vcpu_mode]").multiselect();
|
||||
|
||||
function get_cust_vols(compute_id, pool) {
|
||||
get_vol_url = "/computes/" + compute_id + "/storage/" + pool + "/volumes";
|
||||
$.getJSON(get_vol_url, function (data) {
|
||||
|
|
@ -708,11 +820,12 @@
|
|||
$("#template").removeAttr("disabled");
|
||||
$("#storage").val(pool).change();
|
||||
$("#storage").removeAttr("disabled");
|
||||
|
||||
}
|
||||
|
||||
function get_disk_bus_choices(compute_id, dev_idx, disk_type){
|
||||
get_diskBus_url = "/computes/" + compute_id + "/disk/" + disk_type + "/buses";
|
||||
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) {
|
||||
|
|
@ -721,15 +834,12 @@
|
|||
});
|
||||
}
|
||||
</script>
|
||||
|
||||
<script src="{% static "js/ace.js" %}"></script>
|
||||
<script>
|
||||
var editor = ace.edit("editor");
|
||||
editor.getSession().setMode("ace/mode/xml");
|
||||
|
||||
var input = $('input[name="dom_xml"]');
|
||||
editor.getSession().on("change",function () {
|
||||
input.val(editor.getSession().getValue());
|
||||
})
|
||||
</script>
|
||||
{% if request.user.is_superuser %}
|
||||
<script>
|
||||
function goto_compute() {
|
||||
let compute = {{ compute.id }}
|
||||
window.location.href = "{% url 'create_instance_select_type' 1 %}".replace(1, compute);
|
||||
}
|
||||
</script>
|
||||
{% endif %}
|
||||
{% endblock %}
|
||||
138
create/views.py
138
create/views.py
|
|
@ -13,25 +13,76 @@ from libvirt import libvirtError
|
|||
from webvirtcloud.settings import QEMU_CONSOLE_LISTEN_ADDRESSES
|
||||
from webvirtcloud.settings import INSTANCE_VOLUME_DEFAULT_CACHE
|
||||
from webvirtcloud.settings import INSTANCE_VOLUME_DEFAULT_BUS
|
||||
from webvirtcloud.settings import INSTANCE_CPU_DEFAULT_MODE
|
||||
from webvirtcloud.settings import INSTANCE_MACHINE_DEFAULT_TYPE
|
||||
from webvirtcloud.settings import QEMU_CONSOLE_DEFAULT_TYPE
|
||||
from django.contrib import messages
|
||||
from logs.views import addlogmsg
|
||||
|
||||
|
||||
@login_required
|
||||
def create_instance(request, compute_id):
|
||||
"""
|
||||
:param request:
|
||||
:param compute_id:
|
||||
:return:
|
||||
"""
|
||||
def create_instance_select_type(request, compute_id):
|
||||
|
||||
if not request.user.is_superuser:
|
||||
return HttpResponseRedirect(reverse('index'))
|
||||
|
||||
conn = None
|
||||
error_messages = []
|
||||
storages = []
|
||||
networks = []
|
||||
error_messages = list()
|
||||
storages = list()
|
||||
networks = list()
|
||||
hypervisors = list()
|
||||
meta_prealloc = False
|
||||
compute = get_object_or_404(Compute, pk=compute_id)
|
||||
|
||||
try:
|
||||
conn = wvmCreate(compute.hostname,
|
||||
compute.login,
|
||||
compute.password,
|
||||
compute.type)
|
||||
instances = conn.get_instances()
|
||||
all_hypervisors = conn.get_hypervisors_machines()
|
||||
# Supported hypervisors by webvirtcloud: i686, x86_64(for now)
|
||||
supported_arch = ["x86_64", "i686", "aarch64", "armv7l", "ppc64", "ppc64le", "s390x"]
|
||||
hypervisors = [hpv for hpv in all_hypervisors.keys() if hpv in supported_arch ]
|
||||
default_machine = INSTANCE_MACHINE_DEFAULT_TYPE
|
||||
|
||||
if request.method == 'POST':
|
||||
if 'create_xml' in request.POST:
|
||||
xml = request.POST.get('dom_xml', '')
|
||||
try:
|
||||
name = util.get_xml_path(xml, '/domain/name')
|
||||
except util.etree.Error as err:
|
||||
name = None
|
||||
if name in instances:
|
||||
error_msg = _("A virtual machine with this name already exists")
|
||||
error_messages.append(error_msg)
|
||||
else:
|
||||
try:
|
||||
conn._defineXML(xml)
|
||||
return HttpResponseRedirect(reverse('instance', args=[compute_id, name]))
|
||||
except libvirtError as lib_err:
|
||||
error_messages.append(lib_err.message)
|
||||
|
||||
except libvirtError as lib_err:
|
||||
error_messages.append(lib_err)
|
||||
|
||||
return render(request, 'create_instance_w1.html', locals())
|
||||
|
||||
@login_required
|
||||
def create_instance(request, compute_id, arch, machine):
|
||||
"""
|
||||
:param request:
|
||||
:param compute_id:
|
||||
:return:
|
||||
"""
|
||||
if not request.user.is_superuser:
|
||||
return HttpResponseRedirect(reverse('index'))
|
||||
|
||||
conn = None
|
||||
error_messages = list()
|
||||
storages = list()
|
||||
networks = list()
|
||||
hypervisors = list()
|
||||
firmwares = list()
|
||||
meta_prealloc = False
|
||||
compute = get_object_or_404(Compute, pk=compute_id)
|
||||
flavors = Flavor.objects.filter().order_by('id')
|
||||
|
|
@ -42,18 +93,34 @@ def create_instance(request, compute_id):
|
|||
compute.password,
|
||||
compute.type)
|
||||
|
||||
default_cpu_mode = INSTANCE_CPU_DEFAULT_MODE
|
||||
instances = conn.get_instances()
|
||||
videos = conn.get_video_models()
|
||||
videos = conn.get_video_models(arch, machine)
|
||||
cache_modes = sorted(conn.get_cache_modes().items())
|
||||
default_cache = INSTANCE_VOLUME_DEFAULT_CACHE
|
||||
listener_addr = QEMU_CONSOLE_LISTEN_ADDRESSES
|
||||
mac_auto = util.randomMAC()
|
||||
disk_devices = conn.get_disk_device_types()
|
||||
disk_buses = conn.get_disk_bus_types()
|
||||
disk_devices = conn.get_disk_device_types(arch, machine)
|
||||
disk_buses = conn.get_disk_bus_types(arch, machine)
|
||||
default_bus = INSTANCE_VOLUME_DEFAULT_BUS
|
||||
networks = sorted(conn.get_networks())
|
||||
nwfilters = conn.get_nwfilters()
|
||||
storages = sorted(conn.get_storages(only_actives=True))
|
||||
default_graphics = QEMU_CONSOLE_DEFAULT_TYPE
|
||||
|
||||
dom_caps = conn.get_dom_capabilities(arch, machine)
|
||||
caps = conn.get_capabilities(arch)
|
||||
|
||||
hv_supports_uefi = conn.supports_uefi_xml(dom_caps["loader_enums"])
|
||||
# Add BIOS
|
||||
label = conn.label_for_firmware_path(arch, None)
|
||||
if label: firmwares.append(label)
|
||||
# Add UEFI
|
||||
loader_path = conn.find_uefi_path_for_arch(arch, dom_caps["loaders"])
|
||||
label = conn.label_for_firmware_path(arch, loader_path)
|
||||
if label: firmwares.append(label)
|
||||
firmwares = list(set(firmwares))
|
||||
|
||||
except libvirtError as lib_err:
|
||||
error_messages.append(lib_err)
|
||||
|
||||
|
|
@ -81,24 +148,9 @@ def create_instance(request, compute_id):
|
|||
delete_flavor = Flavor.objects.get(id=flavor_id)
|
||||
delete_flavor.delete()
|
||||
return HttpResponseRedirect(request.get_full_path())
|
||||
if 'create_xml' in request.POST:
|
||||
xml = request.POST.get('dom_xml', '')
|
||||
try:
|
||||
name = util.get_xml_path(xml, '/domain/name')
|
||||
except util.etree.Error as err:
|
||||
name = None
|
||||
if name in instances:
|
||||
error_msg = _("A virtual machine with this name already exists")
|
||||
error_messages.append(error_msg)
|
||||
else:
|
||||
try:
|
||||
conn._defineXML(xml)
|
||||
return HttpResponseRedirect(reverse('instance', args=[compute_id, name]))
|
||||
except libvirtError as lib_err:
|
||||
error_messages.append(lib_err.message)
|
||||
if 'create' in request.POST:
|
||||
volume_list = []
|
||||
|
||||
volume_list = list()
|
||||
is_disk_created = False
|
||||
clone_path = ""
|
||||
form = NewVMForm(request.POST)
|
||||
if form.is_valid():
|
||||
|
|
@ -124,8 +176,9 @@ def create_instance(request, compute_id):
|
|||
volume['path'] = path
|
||||
volume['type'] = conn.get_volume_type(path)
|
||||
volume['device'] = 'disk'
|
||||
volume['bus'] = 'virtio'
|
||||
volume['bus'] = INSTANCE_VOLUME_DEFAULT_BUS
|
||||
volume_list.append(volume)
|
||||
is_disk_created = True
|
||||
except libvirtError as lib_err:
|
||||
error_messages.append(lib_err.message)
|
||||
elif data['template']:
|
||||
|
|
@ -140,8 +193,9 @@ def create_instance(request, compute_id):
|
|||
volume['path'] = clone_path
|
||||
volume['type'] = conn.get_volume_type(clone_path)
|
||||
volume['device'] = 'disk'
|
||||
volume['bus'] = 'virtio'
|
||||
volume['bus'] = INSTANCE_VOLUME_DEFAULT_BUS
|
||||
volume_list.append(volume)
|
||||
is_disk_created = True
|
||||
else:
|
||||
if not data['images']:
|
||||
error_msg = _("First you need to create or select an image")
|
||||
|
|
@ -164,10 +218,15 @@ def create_instance(request, compute_id):
|
|||
if not error_messages:
|
||||
uuid = util.randomUUID()
|
||||
try:
|
||||
conn.create_instance(data['name'], data['memory'], data['vcpu'], data['host_model'],
|
||||
uuid, volume_list, data['cache_mode'], data['networks'], data['virtio'],
|
||||
data["listener_addr"], data["nwfilter"], data["video"], data["console_pass"],
|
||||
data['mac'], data['qemu_ga'])
|
||||
conn.create_instance(name=data['name'], memory=data['memory'], vcpu=data['vcpu'],
|
||||
vcpu_mode=data['vcpu_mode'], uuid=uuid, arch=arch, machine=machine,
|
||||
firmware=data["firmware"],
|
||||
images=volume_list, cache_mode=data['cache_mode'],
|
||||
networks=data['networks'], virtio=data['virtio'],
|
||||
listen_addr=data["listener_addr"], nwfilter=data["nwfilter"],
|
||||
graphics=data["graphics"], video=data["video"],
|
||||
console_pass=data["console_pass"], mac=data['mac'],
|
||||
qemu_ga=data['qemu_ga'])
|
||||
create_instance = Instance(compute_id=compute_id, name=data['name'], uuid=uuid)
|
||||
create_instance.save()
|
||||
msg = _("Instance is created.")
|
||||
|
|
@ -176,8 +235,9 @@ def create_instance(request, compute_id):
|
|||
return HttpResponseRedirect(reverse('instance', args=[compute_id, data['name']]))
|
||||
except libvirtError as lib_err:
|
||||
if data['hdd_size'] or len(volume_list) > 0:
|
||||
for vol in volume_list:
|
||||
conn.delete_volume(vol['path'])
|
||||
if is_disk_created:
|
||||
for vol in volume_list:
|
||||
conn.delete_volume(vol['path'])
|
||||
error_messages.append(lib_err)
|
||||
conn.close()
|
||||
return render(request, 'create_instance.html', locals())
|
||||
return render(request, 'create_instance_w2.html', locals())
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue