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