From 7538ddab4f6b834cc3247e0e69576d0b27f52c2b Mon Sep 17 00:00:00 2001 From: catborise Date: Fri, 29 May 2020 00:43:26 +0300 Subject: [PATCH] Add all settings to appsettings page & Convert settings choices --- accounts/forms.py | 3 +- .../migrations/0003_auto_20200604_0930.py | 24 +++ accounts/models.py | 1 - accounts/templates/accounts-list.html | 6 +- accounts/urls.py | 2 +- accounts/views.py | 21 +-- appsettings/migrations/0001_initial.py | 5 +- .../migrations/0002_auto_20200523_1553.py | 80 --------- .../migrations/0002_auto_20200527_1603.py | 82 +++++++++ appsettings/models.py | 9 +- appsettings/templates/appsettings.html | 28 +-- appsettings/views.py | 69 ++++---- computes/templates/overview.html | 3 +- console/views.py | 3 +- create/templates/create_instance_w1.html | 2 +- create/templates/create_instance_w2.html | 16 +- create/views.py | 108 +++++++----- datasource/urls.py | 13 +- dev/scss/wvc-main.scss | 6 +- instances/templates/instance.html | 164 +++++++++--------- instances/views.py | 76 ++++---- logs/views.py | 1 + storages/views.py | 9 +- vrtManager/create.py | 105 ++++++----- vrtManager/instance.py | 8 +- vrtManager/storage.py | 13 +- webvirtcloud/settings.py.template | 44 +---- 27 files changed, 454 insertions(+), 447 deletions(-) create mode 100644 accounts/migrations/0003_auto_20200604_0930.py delete mode 100644 appsettings/migrations/0002_auto_20200523_1553.py create mode 100644 appsettings/migrations/0002_auto_20200527_1603.py diff --git a/accounts/forms.py b/accounts/forms.py index db53ed5..4127ac4 100644 --- a/accounts/forms.py +++ b/accounts/forms.py @@ -9,8 +9,7 @@ class UserAddForm(forms.Form): name = forms.CharField(label="Name", error_messages={'required': _('No User name has been entered')}, max_length=20) - password = forms.CharField(required=not settings.ALLOW_EMPTY_PASSWORD, - error_messages={'required': _('No password has been entered')},) + password = forms.CharField(required=not settings.ALLOW_EMPTY_PASSWORD, error_messages={'required': _('No password has been entered')},) def clean_name(self): name = self.cleaned_data['name'] diff --git a/accounts/migrations/0003_auto_20200604_0930.py b/accounts/migrations/0003_auto_20200604_0930.py new file mode 100644 index 0000000..05c9232 --- /dev/null +++ b/accounts/migrations/0003_auto_20200604_0930.py @@ -0,0 +1,24 @@ +# Generated by Django 2.2.12 on 2020-06-04 09:30 + +import django.core.validators +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('accounts', '0002_permissionset'), + ] + + operations = [ + migrations.AlterField( + model_name='userattributes', + name='max_cpus', + field=models.IntegerField(default=2, help_text='-1 for unlimited. Any integer value', validators=[django.core.validators.MinValueValidator(-1)]), + ), + migrations.AlterField( + model_name='userattributes', + name='max_instances', + field=models.IntegerField(default=2, help_text='-1 for unlimited. Any integer value', validators=[django.core.validators.MinValueValidator(-1)]), + ), + ] diff --git a/accounts/models.py b/accounts/models.py index 02192fe..759455c 100644 --- a/accounts/models.py +++ b/accounts/models.py @@ -1,4 +1,3 @@ -from django.conf import settings from django.contrib.auth.models import User from django.core.validators import MinValueValidator from django.db import models diff --git a/accounts/templates/accounts-list.html b/accounts/templates/accounts-list.html index 72b6d14..b9c3487 100644 --- a/accounts/templates/accounts-list.html +++ b/accounts/templates/accounts-list.html @@ -68,8 +68,8 @@ + {% endblock %} {% block script %} diff --git a/console/views.py b/console/views.py index bdfddd5..bbbabc8 100644 --- a/console/views.py +++ b/console/views.py @@ -3,8 +3,7 @@ from django.shortcuts import render from libvirt import libvirtError from instances.models import Instance from vrtManager.instance import wvmInstance -from webvirtcloud.settings import WS_PUBLIC_PORT -from webvirtcloud.settings import WS_PUBLIC_HOST +from webvirtcloud.settings import WS_PUBLIC_PORT, WS_PUBLIC_HOST def console(request): diff --git a/create/templates/create_instance_w1.html b/create/templates/create_instance_w1.html index 425936f..612afd8 100644 --- a/create/templates/create_instance_w1.html +++ b/create/templates/create_instance_w1.html @@ -83,7 +83,7 @@
-
+
{% csrf_token %}
diff --git a/create/templates/create_instance_w2.html b/create/templates/create_instance_w2.html index 7a24872..7186cd2 100644 --- a/create/templates/create_instance_w2.html +++ b/create/templates/create_instance_w2.html @@ -199,7 +199,7 @@
@@ -303,7 +303,7 @@
-
+
{% csrf_token %}
@@ -423,7 +423,7 @@
@@ -516,7 +516,7 @@
-
+
{% csrf_token %}
@@ -636,7 +636,7 @@
@@ -788,8 +788,7 @@ '{% endfor %}' + '' + ' -> ' + value + ' ' + - '' + - ''; + ''; selected_list_html += li; counter++; }); @@ -797,7 +796,6 @@ $('#disk_list_div').addClass('d-none'); } $('#img-list').html(selected_list_html); - } }); @@ -822,7 +820,7 @@ $.each(input_value.split(','), function (index, value) { let li = '
  • eth' + counter + ' -> ' + value + ' ' + - '
  • '; + ''; selected_list_html += li; counter++; }); diff --git a/create/views.py b/create/views.py index 30e2475..5b2b6c6 100644 --- a/create/views.py +++ b/create/views.py @@ -8,23 +8,12 @@ from admin.decorators import superuser_only from computes.models import Compute from create.models import Flavor from create.forms import FlavorAddForm, NewVMForm +from appsettings.models import AppSettings from instances.models import Instance from vrtManager.create import wvmCreate from vrtManager import util from logs.views import addlogmsg - 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 webvirtcloud.settings import INSTANCE_VOLUME_DEFAULT_IO -from webvirtcloud.settings import INSTANCE_VOLUME_DEFAULT_DETECT_ZEROES -from webvirtcloud.settings import INSTANCE_VOLUME_DEFAULT_DISCARD -from webvirtcloud.settings import INSTANCE_ARCH_DEFAULT_TYPE -from webvirtcloud.settings import INSTANCE_FIRMWARE_DEFAULT_TYPE - @superuser_only def create_instance_select_type(request, compute_id): @@ -40,6 +29,7 @@ def create_instance_select_type(request, compute_id): hypervisors = list() meta_prealloc = False compute = get_object_or_404(Compute, pk=compute_id) + appsettings = AppSettings.objects.all() try: conn = wvmCreate(compute.hostname, compute.login, compute.password, compute.type) @@ -48,8 +38,8 @@ def create_instance_select_type(request, compute_id): # 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 - default_arch = INSTANCE_ARCH_DEFAULT_TYPE + default_machine = appsettings.get(key="INSTANCE_MACHINE_DEFAULT_TYPE").value + default_arch = appsettings.get(key="INSTANCE_ARCH_DEFAULT_TYPE").value if request.method == 'POST': if 'create_xml' in request.POST: @@ -93,28 +83,33 @@ def create_instance(request, compute_id, arch, machine): meta_prealloc = False compute = get_object_or_404(Compute, pk=compute_id) flavors = Flavor.objects.filter().order_by('id') + appsettings = AppSettings.objects.all() try: conn = wvmCreate(compute.hostname, compute.login, compute.password, compute.type) - default_firmware = INSTANCE_FIRMWARE_DEFAULT_TYPE - default_cpu_mode = INSTANCE_CPU_DEFAULT_MODE + default_firmware = appsettings.get(key="INSTANCE_FIRMWARE_DEFAULT_TYPE").value + default_cpu_mode = appsettings.get(key="INSTANCE_CPU_DEFAULT_MODE").value instances = conn.get_instances() videos = conn.get_video_models(arch, machine) cache_modes = sorted(conn.get_cache_modes().items()) - default_cache = INSTANCE_VOLUME_DEFAULT_CACHE.lower() - default_io = INSTANCE_VOLUME_DEFAULT_IO.lower() - default_zeroes = INSTANCE_VOLUME_DEFAULT_DETECT_ZEROES.lower() - default_discard = INSTANCE_VOLUME_DEFAULT_DISCARD.lower() + default_cache = appsettings.get(key="INSTANCE_VOLUME_DEFAULT_CACHE").value + default_io = appsettings.get(key="INSTANCE_VOLUME_DEFAULT_IO").value + default_zeroes = appsettings.get(key="INSTANCE_VOLUME_DEFAULT_DETECT_ZEROES").value + default_discard = appsettings.get(key="INSTANCE_VOLUME_DEFAULT_DISCARD").value + default_disk_format = appsettings.get(key="INSTANCE_VOLUME_DEFAULT_FORMAT").value + default_disk_owner_uid = int(appsettings.get(key="INSTANCE_VOLUME_DEFAULT_OWNER_UID").value) + default_disk_owner_gid = int(appsettings.get(key="INSTANCE_VOLUME_DEFAULT_OWNER_GID").value) + default_scsi_disk_model = appsettings.get(key="INSTANCE_VOLUME_DEFAULT_SCSI_CONTROLLER").value listener_addr = QEMU_CONSOLE_LISTEN_ADDRESSES mac_auto = util.randomMAC() disk_devices = conn.get_disk_device_types(arch, machine) disk_buses = conn.get_disk_bus_types(arch, machine) - default_bus = INSTANCE_VOLUME_DEFAULT_BUS + default_bus = appsettings.get(key="INSTANCE_VOLUME_DEFAULT_BUS").value networks = sorted(conn.get_networks()) nwfilters = conn.get_nwfilters() storages = sorted(conn.get_storages(only_actives=True)) - default_graphics = QEMU_CONSOLE_DEFAULT_TYPE + default_graphics = appsettings.get(key="QEMU_CONSOLE_DEFAULT_TYPE").value dom_caps = conn.get_dom_capabilities(arch, machine) caps = conn.get_capabilities(arch) @@ -177,18 +172,29 @@ def create_instance(request, compute_id, arch, machine): error_messages.append(error_msg) else: try: - path = conn.create_volume(data['storage'], - data['name'], - data['hdd_size'], - metadata=meta_prealloc) + path = conn.create_volume( + data['storage'], + data['name'], + data['hdd_size'], + default_disk_format, + meta_prealloc, + default_disk_owner_uid, + default_disk_owner_gid) volume = dict() + volume['device'] = 'disk' volume['path'] = path volume['type'] = conn.get_volume_type(path) - volume['device'] = 'disk' - if data['virtio']: - volume['bus'] = INSTANCE_VOLUME_DEFAULT_BUS + volume['cache_mode'] = data['cache_mode'] + volume['bus'] = default_bus + if volume['bus'] == 'scsi': + volume['scsi_model'] = default_scsi_disk_model + volume['discard_mode'] = default_discard + volume['detect_zeroes_mode'] = default_zeroes + volume['io_mode'] = default_io + volume_list.append(volume) is_disk_created = True + except libvirtError as lib_err: error_messages.append(lib_err) elif data['template']: @@ -198,16 +204,25 @@ def create_instance(request, compute_id, arch, machine): error_msg = _("Image has already exist. Please check volumes or change instance name") error_messages.append(error_msg) else: - clone_path = conn.clone_from_template(data['name'], - templ_path, - data['storage'], - metadata=meta_prealloc) + clone_path = conn.clone_from_template( + data['name'], + templ_path, + data['storage'], + meta_prealloc, + default_disk_owner_uid, + default_disk_owner_gid) volume = dict() volume['path'] = clone_path volume['type'] = conn.get_volume_type(clone_path) volume['device'] = 'disk' - if data['virtio']: - volume['bus'] = INSTANCE_VOLUME_DEFAULT_BUS + volume['cache_mode'] = data['cache_mode'] + volume['bus'] = default_bus + if volume['bus'] == 'scsi': + volume['scsi_model'] = default_scsi_disk_model + volume['discard_mode'] = default_discard + volume['detect_zeroes_mode'] = default_zeroes + volume['io_mode'] = default_io + volume_list.append(volume) is_disk_created = True else: @@ -223,6 +238,13 @@ def create_instance(request, compute_id, arch, machine): volume['type'] = conn.get_volume_type(path) volume['device'] = request.POST.get('device' + str(idx), '') volume['bus'] = request.POST.get('bus' + str(idx), '') + if volume['bus'] == 'scsi': + volume['scsi_model'] = default_scsi_disk_model + volume['cache_mode'] = data['cache_mode'] + volume['discard_mode'] = default_discard + volume['detect_zeroes_mode'] = default_zeroes + volume['io_mode'] = default_io + volume_list.append(volume) except libvirtError as lib_err: error_messages.append(lib_err) @@ -253,23 +275,19 @@ def create_instance(request, compute_id, arch, machine): arch=arch, machine=machine, firmware=firmware, - images=volume_list, - cache_mode=data['cache_mode'], - io_mode=default_io, - discard_mode=default_discard, - detect_zeroes_mode=default_zeroes, - networks=data['networks'], + volumes=volume_list, + networks=data['networks'], virtio=data['virtio'], - listen_addr=data["listener_addr"], + listen_addr=data["listener_addr"], nwfilter=data["nwfilter"], - graphics=data["graphics"], + graphics=data["graphics"], video=data["video"], - console_pass=data["console_pass"], + 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.") + msg = _("Instance is created") messages.success(request, msg) addlogmsg(request.user.username, create_instance.name, msg) return HttpResponseRedirect(reverse('instance', args=[compute_id, data['name']])) diff --git a/datasource/urls.py b/datasource/urls.py index 2979a4e..d250fe7 100644 --- a/datasource/urls.py +++ b/datasource/urls.py @@ -1,12 +1,9 @@ -from django.conf.urls import url +from django.urls import path from . import views urlpatterns = [ - url(r'^openstack/$', - views.os_index, name='ds_openstack_index'), - url(r'^openstack/(?P[\w\-\.]+)/meta_data.json$', - views.os_metadata_json, name='ds_openstack_metadata'), - url(r'^openstack/(?P[\w\-\.]+)/user_data$', - views.os_userdata, name='ds_openstack_userdata'), - url(r'^vdi/(?P[0-9]+)/(?P[\w\-\.]+)/$', views.get_vdi_url, name='vdi_url'), + path('openstack/', views.os_index, name='ds_openstack_index'), + path('openstack//meta_data.json', views.os_metadata_json, name='ds_openstack_metadata'), + path('openstack//user_data', views.os_userdata, name='ds_openstack_userdata'), + path('vdi///', views.get_vdi_url, name='vdi_url'), ] diff --git a/dev/scss/wvc-main.scss b/dev/scss/wvc-main.scss index 225f3ae..44da71a 100644 --- a/dev/scss/wvc-main.scss +++ b/dev/scss/wvc-main.scss @@ -1,3 +1,3 @@ -@import 'dev/scss/wvc-theme/flatly/variables'; -@import 'dev/scss/bootstrap-overrides.scss'; -@import 'dev/scss/wvc-theme/flatly/bootswatch'; \ No newline at end of file +@import 'dev/scss//wvc-theme/flatly/variables'; +@import 'dev/scss//bootstrap-overrides.scss'; +@import 'dev/scss//wvc-theme/flatly/bootswatch'; \ No newline at end of file diff --git a/instances/templates/instance.html b/instances/templates/instance.html index 60a6fc0..e1a6f42 100644 --- a/instances/templates/instance.html +++ b/instances/templates/instance.html @@ -121,7 +121,7 @@
    - {% ifequal status 1 %} + {% if status == 1 %}

    {% trans "This action sends an ACPI shutdown signal to the instance." %}

    {% csrf_token %} @@ -200,8 +200,8 @@
    {% endif %} - {% endifequal %} - {% ifequal status 3 %} + {% endif %} + {% if status == 3 %} {% if request.user.is_superuser %}

    {% trans "This action restore the instance after suspend." %}

    @@ -226,8 +226,8 @@
    {% endif %} - {% endifequal %} - {% ifequal status 5 %} + {% endif %} + {% if status == 5 %}

    {% trans "Click on Boot button to start this instance." %}

    {% csrf_token %} @@ -240,7 +240,7 @@
    - {% endifequal %} + {% endif %}
    @@ -253,33 +253,33 @@ {% trans "Console" %} - {% if show_access_root_password %} + {% if show_access_root_password == 'True' %} {% endif %} - {% if show_access_ssh_keys %} + {% if show_access_ssh_keys == 'True' %} {% endif %} - {% ifequal status 1 %} + {% if status == 1 %} - {% endifequal %} + {% endif %}

    {% trans "This action opens a new window with a VNC connection to the console of the instance." %}

    - {% ifequal status 1 %} + {% if status == 1 %}
    @@ -293,10 +293,10 @@
    {% else %} - {% endifequal %} + {% endif %}
    - {% if show_access_root_password %} + {% if show_access_root_password == 'True' %}

    {% trans "You need shut down your instance and enter a new root password." %}

    {% csrf_token %} @@ -305,22 +305,22 @@
    - {% ifequal status 5 %} + {% if status == 5 %} {% else %} - {% endifequal %} + {% endif %}
    {% endif %} - {% if show_access_ssh_keys %} + {% if show_access_ssh_keys == 'True' %}

    {% trans "You need shut down your instance and choose your public key." %}

    {% csrf_token %}
    - {% if publickeys %} {% for key in publickeys %} @@ -331,16 +331,16 @@
    - {% ifequal status 5 %} + {% if status == 5 %} {% else %} - {% endifequal %} + {% endif %}
    {% endif %} - {% ifequal status 1 %} + {% if status == 1 %}

    {% trans "This action opens a remote viewer with a connection to the console of the instance." %}

    @@ -351,7 +351,7 @@
    - {% endifequal %} + {% endif %}
    @@ -408,11 +408,11 @@
    - {% ifequal status 5 %} + {% if status == 5 %} {% else %} - {% endifequal %} + {% endif %}
    {% else %} @@ -493,11 +493,11 @@
    {% endfor %} - {% ifequal status 5 %} + {% if status == 5 %} {% else %} - {% endifequal %} + {% endif %} {% else %} {% trans "You don't have permission for resizing instance" %} @@ -526,7 +526,7 @@
    - {% ifequal status 5 %} + {% if status == 5 %}

    {% trans "This may take more than an hour, depending on how much content is on your droplet and how large the disk is." %}

    {% csrf_token %}
    @@ -534,16 +534,16 @@
    - {% ifequal status 5 %} + {% if status == 5 %} {% else %} - {% endifequal %} + {% endif %}
    {% else %}

    {% trans "To take a snapshot please Power Off the instance." %}

    - {% endifequal %} + {% endif %}
    {% if snapshots %} @@ -563,7 +563,7 @@
    {% csrf_token %} - {% ifequal status 5 %} + {% if status == 5 %} @@ -572,7 +572,7 @@ title="{% trans "To restore snapshots you need Power Off the instance." %}"> - {% endifequal %} + {% endif %}
    @@ -668,11 +668,11 @@

    {% trans "Autostart your instance when host server is power on " %} - {% ifequal autostart 0 %} + {% if autostart == 0 %} {% else %} - {% endifequal %} + {% endif %}

    @@ -681,23 +681,23 @@
    {% csrf_token %}
    - {% ifequal status 5 %} + {% if status == 5 %}

    {% trans "Enable Boot Menu for your instance when it starts up " %} - {% ifequal bootmenu 0 %} + {% if bootmenu == 0 %} {% else %} - {% endifequal %} + {% endif %} {% else %} - {% ifequal bootmenu 0 %} + {% if bootmenu == 0 %}

    **** {% trans "Please shutdown instance to modify boot menu" %} ****

    - {% endifequal %} - {% endifequal %} + {% endif %} + {% endif %}
    - {% ifequal bootmenu 1 %} + {% if bootmenu == 1 %}
    {% for idx, val in boot_order.items %} @@ -734,7 +734,7 @@
    - {% endifequal %} + {% endif %}
    @@ -866,7 +866,7 @@ {% include 'edit_instance_volume.html' with id=forloop.counter0 %} - {% ifequal status 5 %} + {% if status == 5 %} @@ -880,16 +880,15 @@ - {% endifequal %} + {% endif %} - {% endfor %} - +
    -
    +
    @@ -957,10 +956,10 @@
    @@ -972,7 +971,7 @@
    @@ -983,7 +982,7 @@ @@ -992,7 +991,7 @@ @@ -1116,7 +1115,7 @@
    - +
    @@ -1140,7 +1139,7 @@
    - +
    @@ -1148,7 +1147,7 @@
    - +
    @@ -1156,7 +1155,7 @@
    - +
    @@ -1164,7 +1163,7 @@
    - +
    @@ -1183,7 +1182,7 @@
    - {% ifequal status 5 %} + {% if status == 5 %} - {% endifequal %} + {% endif %}
    @@ -1241,11 +1240,11 @@
    - {% ifequal status 5 %} + {% if status == 5 %} {% else %} - {% endifequal %} + {% endif %}
    @@ -1264,11 +1263,11 @@ {% endfor %}
    - {% ifequal status 5 %} + {% if status == 5 %} {% else %} - {% endifequal %} + {% endif %}
    @@ -1302,11 +1301,11 @@ {% if console_passwd %} {% trans "Show" %} {% endif %} - {% ifequal status 5 %} + {% if status == 5 %} {% else %} - {% endifequal %} + {% endif %} @@ -1334,11 +1333,11 @@
    - {% ifequal status 5 %} + {% if status == 5 %} {% else %} - {% endifequal %} + {% endif %}
    @@ -1410,14 +1409,14 @@
    - {% ifequal disk.format 'qcow2' %} + {% if disk.format == 'qcow2' %}
    {% trans 'Metadata' %}
    - {% endifequal %} + {% endif %}
    @@ -1439,11 +1438,11 @@ - {% ifequal status 5 %} + {% if status == 5 %} {% else %} - {% endifequal %} + {% endif %}
    @@ -1475,11 +1474,11 @@
    - {% ifequal status 5 %} + {% if status == 5 %} {% else %} - {% endifequal %} + {% endif %}
    @@ -1497,11 +1496,11 @@ {% endfor %} - {% ifequal status 5 %} + {% if status == 5 %} {% else %} - {% endifequal %} + {% endif %} @@ -1669,10 +1668,9 @@

    {% trans "Delete storage for instance?" %}

    {% if request.user.is_superuser or userinstance.is_delete %} - {% ifequal status 3 %} + {% if status == 3 %} {% else %} -
    {% csrf_token %}
    @@ -1690,7 +1688,7 @@ {% endif %} - {% endifequal %} + {% endif %} {% else %} {% endif %} diff --git a/instances/views.py b/instances/views.py index be7a2fb..295511a 100644 --- a/instances/views.py +++ b/instances/views.py @@ -13,9 +13,9 @@ from django.shortcuts import render, get_object_or_404 from django.utils.translation import ugettext_lazy as _ from computes.models import Compute from instances.models import Instance +from appsettings.models import AppSettings from django.contrib.auth.models import User from accounts.models import UserInstance, UserSSHKey -from appsettings.models import AppSettings from vrtManager.hostdetails import wvmHostDetails from vrtManager.instance import wvmInstance, wvmInstances from vrtManager.connection import connection_manager @@ -64,7 +64,7 @@ def allinstances(request): error_messages.append(lib_err) addlogmsg(request.user.username, request.POST.get("name", "instance"), lib_err) - view_style = settings.VIEW_INSTANCES_LIST_STYLE + view_style = AppSettings.objects.get(key="VIEW_INSTANCES_LIST_STYLE").value return render(request, 'allinstances.html', locals()) @@ -111,10 +111,11 @@ def instance(request, compute_id, vname): computes_count = computes.count() users = User.objects.all().order_by('username') publickeys = UserSSHKey.objects.filter(user_id=request.user.id) + appsettings = AppSettings.objects.all() keymaps = settings.QEMU_KEYMAPS - console_types = settings.QEMU_CONSOLE_TYPES + console_types = appsettings.get(key="QEMU_CONSOLE_DEFAULT_TYPE").choices_as_list console_listen_addresses = settings.QEMU_CONSOLE_LISTEN_ADDRESSES - bottom_bar = AppSettings.objects.get(key="VIEW_INSTANCE_DETAIL_BOTTOM_BAR").value + bottom_bar = appsettings.get(key="VIEW_INSTANCE_DETAIL_BOTTOM_BAR").value try: userinstance = UserInstance.objects.get(instance__compute_id=compute_id, instance__name=vname, @@ -144,7 +145,7 @@ def instance(request, compute_id, vname): return int(float(size_str)) def get_clone_free_names(size=10): - prefix = settings.CLONE_INSTANCE_DEFAULT_PREFIX + prefix = appsettings.get(key="CLONE_INSTANCE_DEFAULT_PREFIX").value free_names = [] existing_names = [i.name for i in Instance.objects.filter(name__startswith=prefix)] index = 1 @@ -179,21 +180,22 @@ def instance(request, compute_id, vname): disk_size += int(disk['size']) >> 30 if ua.max_instances > 0 and instance > ua.max_instances: + quota_debug = appsettings.get(key="QUOTA_DEBUG").value msg = "instance" - if settings.QUOTA_DEBUG: - msg += " (%s > %s)" % (instance, ua.max_instances) + if quota_debug: + msg += f" ({instance} > {ua.max_instances})" if ua.max_cpus > 0 and cpu > ua.max_cpus: msg = "cpu" - if settings.QUOTA_DEBUG: - msg += " (%s > %s)" % (cpu, ua.max_cpus) + if quota_debug: + msg += f" ({cpu} > {ua.max_cpus})" if ua.max_memory > 0 and memory > ua.max_memory: msg = "memory" - if settings.QUOTA_DEBUG: - msg += " (%s > %s)" % (memory, ua.max_memory) + if quota_debug: + msg += f" ({memory} > {ua.max_memory})" if ua.max_disk_size > 0 and disk_size > ua.max_disk_size: msg = "disk" - if settings.QUOTA_DEBUG: - msg += " (%s > %s)" % (disk_size, ua.max_disk_size) + if quota_debug: + msg += f" ({disk_size} > {ua.max_disk_size})" return msg def get_new_disk_dev(media, disks, bus): @@ -314,18 +316,21 @@ def instance(request, compute_id, vname): io_modes = sorted(conn.get_io_modes().items()) discard_modes = sorted(conn.get_discard_modes().items()) detect_zeroes_modes = sorted(conn.get_detect_zeroes_modes().items()) - default_io = settings.INSTANCE_VOLUME_DEFAULT_IO - default_discard = settings.INSTANCE_VOLUME_DEFAULT_DISCARD - default_zeroes = settings.INSTANCE_VOLUME_DEFAULT_DETECT_ZEROES - default_cache = settings.INSTANCE_VOLUME_DEFAULT_CACHE - default_format = settings.INSTANCE_VOLUME_DEFAULT_FORMAT - default_owner = settings.INSTANCE_VOLUME_DEFAULT_OWNER + default_bus = appsettings.get(key="INSTANCE_VOLUME_DEFAULT_BUS").value + default_io = appsettings.get(key="INSTANCE_VOLUME_DEFAULT_IO").value + default_discard = appsettings.get(key="INSTANCE_VOLUME_DEFAULT_DISCARD").value + default_zeroes = appsettings.get(key="INSTANCE_VOLUME_DEFAULT_DETECT_ZEROES").value + default_cache = appsettings.get(key="INSTANCE_VOLUME_DEFAULT_CACHE").value + default_format = appsettings.get(key="INSTANCE_VOLUME_DEFAULT_FORMAT").value + default_disk_owner_uid = int(appsettings.get(key="INSTANCE_VOLUME_DEFAULT_OWNER_UID").value) + default_disk_owner_gid = int(appsettings.get(key="INSTANCE_VOLUME_DEFAULT_OWNER_GID").value) + formats = conn.get_image_formats() - show_access_root_password = settings.SHOW_ACCESS_ROOT_PASSWORD - show_access_ssh_keys = settings.SHOW_ACCESS_SSH_KEYS - clone_instance_auto_name = settings.CLONE_INSTANCE_AUTO_NAME - default_bus = settings.INSTANCE_VOLUME_DEFAULT_BUS + show_access_root_password = appsettings.get(key="SHOW_ACCESS_ROOT_PASSWORD").value + show_access_ssh_keys = appsettings.get(key="SHOW_ACCESS_SSH_KEYS").value + clone_instance_auto_name = appsettings.get(key="CLONE_INSTANCE_AUTO_NAME").value + try: instance = Instance.objects.get(compute_id=compute_id, name=vname) @@ -520,7 +525,7 @@ def instance(request, compute_id, vname): error_messages.append(msg) else: conn.resize_disk(disks_new) - msg = _("Resize") + msg = _("Disk resize") addlogmsg(request.user.username, instance.name, msg) messages.success(request, msg) return HttpResponseRedirect(request.get_full_path() + '#resize') @@ -539,9 +544,9 @@ def instance(request, compute_id, vname): cache = request.POST.get('cache', default_cache) target_dev = get_new_disk_dev(media, disks, bus) - source = conn_create.create_volume(storage, name, size, format, meta_prealloc, default_owner) + source = conn_create.create_volume(storage, name, size, format, meta_prealloc, default_disk_owner_uid, default_disk_owner_gid) conn.attach_disk(target_dev, source, target_bus=bus, driver_type=format, cache_mode=cache) - msg = _('Attach new disk {} ({})'.format(name, format)) + msg = _(f"Attach new disk {name} ({format})") addlogmsg(request.user.username, instance.name, msg) return HttpResponseRedirect(request.get_full_path() + '#disks') @@ -810,8 +815,11 @@ def instance(request, compute_id, vname): if 'set_console_type' in request.POST: console_type = request.POST.get('console_type', '') - conn.set_console_type(console_type) msg = _("Set VNC type") + if console_type in console_types: + conn.set_console_type(console_type) + else: + msg = _("Console type not supported") addlogmsg(request.user.username, instance.name, msg) return HttpResponseRedirect(request.get_full_path() + '#vncsettings') @@ -943,13 +951,13 @@ def instance(request, compute_id, vname): if 'add_owner' in request.POST: user_id = int(request.POST.get('user_id', '')) - if settings.ALLOW_INSTANCE_MULTIPLE_OWNER: + if appsettings.get(key="ALLOW_INSTANCE_MULTIPLE_OWNER").value == 'True': check_inst = UserInstance.objects.filter(instance=instance, user_id=user_id) else: check_inst = UserInstance.objects.filter(instance=instance) if check_inst: - msg = _("Owner already added") + msg = _("One owner is allowed and owner already added") error_messages.append(msg) else: add_user_inst = UserInstance(instance=instance, user_id=user_id) @@ -975,10 +983,13 @@ def instance(request, compute_id, vname): quota_msg = check_user_quota(1, vcpu, memory, disk_sum) check_instance = Instance.objects.filter(name=clone_data['name']) + clone_data['disk_owner_uid'] = default_disk_owner_uid + clone_data['disk_owner_gid'] = default_disk_owner_gid + for post in request.POST: clone_data[post] = request.POST.get(post, '').strip() - if clone_instance_auto_name and not clone_data['name']: + if clone_instance_auto_name == 'True' and not clone_data['name']: auto_vname = clone_free_names[0] clone_data['name'] = auto_vname clone_data['clone-net-mac-0'] = _get_dhcp_mac_address(auto_vname) @@ -1016,7 +1027,8 @@ def instance(request, compute_id, vname): msg = _("Clone of '%s'" % instance.name) addlogmsg(request.user.username, new_instance.name, msg) - if settings.CLONE_INSTANCE_AUTO_MIGRATE: + + if appsettings.get(key="CLONE_INSTANCE_AUTO_MIGRATE").value == 'True': new_compute = Compute.objects.order_by('?').first() migrate_instance(new_compute, new_instance, xml_del=True, offline=True) return HttpResponseRedirect( @@ -1326,7 +1338,7 @@ def random_mac_address(request): def guess_clone_name(request): dhcp_file = '/srv/webvirtcloud/dhcpd.conf' - prefix = settings.CLONE_INSTANCE_DEFAULT_PREFIX + prefix = appsettings.get(key="CLONE_INSTANCE_DEFAULT_PREFIX").value if os.path.isfile(dhcp_file): instance_names = [i.name for i in Instance.objects.filter(name__startswith=prefix)] with open(dhcp_file, 'r') as f: diff --git a/logs/views.py b/logs/views.py index c04e284..06f0d90 100644 --- a/logs/views.py +++ b/logs/views.py @@ -6,6 +6,7 @@ from django.shortcuts import render from django.urls import reverse from admin.decorators import superuser_only +from appsettings.models import AppSettings from instances.models import Instance from logs.models import Logs diff --git a/storages/views.py b/storages/views.py index cf6e6c4..b47528e 100644 --- a/storages/views.py +++ b/storages/views.py @@ -4,6 +4,7 @@ from django.http import HttpResponseRedirect, HttpResponse from django.utils.translation import ugettext_lazy as _ from django.urls import reverse from computes.models import Compute +from appsettings.models import AppSettings from storages.forms import AddStgPool, AddImage, CloneImage from vrtManager.storage import wvmStorage, wvmStorages from libvirt import libvirtError @@ -143,8 +144,12 @@ def storage(request, compute_id, pool): if data['meta_prealloc'] and data['format'] == 'qcow2': meta_prealloc = True try: - name = conn.create_volume(data['name'], data['size'], data['format'], meta_prealloc) - messages.success(request, _("Image file {} is created successfully".format(name))) + disk_owner = AppSettings.objects.filter(key__startswith="INSTANCE_VOLUME_DEFAULT_OWNER") + disk_owner_uid = int(disk_owner.get(key="INSTANCE_VOLUME_DEFAULT_OWNER_UID").value) + disk_owner_gid = int(disk_owner.get(key="INSTANCE_VOLUME_DEFAULT_OWNER_GID").value) + + name = conn.create_volume(data['name'], data['size'], data['format'], meta_prealloc, disk_owner_uid, disk_owner_gid) + messages.success(request, _(f"Image file {name} is created successfully")) return HttpResponseRedirect(request.get_full_path()) except libvirtError as lib_err: error_messages.append(lib_err) diff --git a/vrtManager/create.py b/vrtManager/create.py index 8c6d2cf..40d86c4 100644 --- a/vrtManager/create.py +++ b/vrtManager/create.py @@ -1,9 +1,6 @@ import string from vrtManager import util from vrtManager.connection import wvmConnect -from webvirtcloud.settings import INSTANCE_VOLUME_DEFAULT_OWNER as DEFAULT_OWNER -from webvirtcloud.settings import INSTANCE_VOLUME_DEFAULT_FORMAT -from webvirtcloud.settings import INSTANCE_VOLUME_DEFAULT_SCSI_CONTROLLER def get_rbd_storage_data(stg): @@ -23,7 +20,6 @@ def get_rbd_storage_data(stg): class wvmCreate(wvmConnect): - image_format = INSTANCE_VOLUME_DEFAULT_FORMAT def get_storages_images(self): """ @@ -52,7 +48,7 @@ class wvmCreate(wvmConnect): """Get guest capabilities""" return util.get_xml_path(self.get_cap_xml(), "/capabilities/host/cpu/arch") - def create_volume(self, storage, name, size, image_format=image_format, metadata=False, owner=DEFAULT_OWNER): + def create_volume(self, storage, name, size, image_format, metadata=False, disk_owner_uid=0, disk_owner_gid=0): size = int(size) * 1073741824 stg = self.get_storage(storage) storage_type = util.get_xml_path(stg.XMLDesc(0), "/pool/@type") @@ -65,16 +61,16 @@ class wvmCreate(wvmConnect): else: alloc = size metadata = False - xml = """ + xml = f""" - %s - %s - %s + {name} + {size} + {alloc} - + - %s - %s + {disk_owner_uid} + {disk_owner_gid} 0644 @@ -83,7 +79,7 @@ class wvmCreate(wvmConnect): - """ % (name, size, alloc, image_format, owner['uid'], owner['guid']) + """ stg.createXML(xml, metadata) try: stg.refresh(0) @@ -120,7 +116,7 @@ class wvmCreate(wvmConnect): vol = self.get_volume_by_path(vol_path) return vol.storagePoolLookupByVolume() - def clone_from_template(self, clone, template, storage=None, metadata=False, owner=DEFAULT_OWNER): + def clone_from_template(self, clone, template, storage=None, metadata=False, disk_owner_uid=0, disk_owner_gid=0): vol = self.get_volume_by_path(template) if not storage: stg = vol.storagePoolLookupByVolume() @@ -133,16 +129,16 @@ class wvmCreate(wvmConnect): clone += '.img' else: metadata = False - xml = """ + xml = f""" - %s + {clone} 0 0 - + - %s - %s + {disk_owner_uid} + {disk_owner_gid} 0644 @@ -151,7 +147,7 @@ class wvmCreate(wvmConnect): - """ % (clone, format, owner['uid'], owner['guid']) + """ stg.createXMLFrom(xml, vol, metadata) clone_vol = stg.storageVolLookupByName(clone) return clone_vol.path() @@ -163,11 +159,9 @@ class wvmCreate(wvmConnect): vol = self.get_volume_by_path(path) vol.delete() - def create_instance(self, name, memory, vcpu, vcpu_mode, uuid, arch, machine, firmware, images, + def create_instance(self, name, memory, vcpu, vcpu_mode, uuid, arch, machine, firmware, volumes, networks, nwfilter, graphics, virtio, listen_addr, - video="vga", console_pass="random", mac=None, - cache_mode=None, io_mode=None, discard_mode=None, detect_zeroes_mode=None, - qemu_ga=True): + video="vga", console_pass="random", mac=None, qemu_ga=True): """ Create VM function """ @@ -176,17 +170,17 @@ class wvmCreate(wvmConnect): memory = int(memory) * 1024 - xml = """ - - %s + xml = f""" + + {name} None - %s - %s - %s""" % (dom_caps["domain"], name, uuid, memory, vcpu) + {uuid} + {memory} + {vcpu}""" if dom_caps["os_support"] == 'yes': - xml += """ - %s""" % (arch, machine, caps["os_type"]) + xml += f""" + {caps["os_type"]}""" xml += """ """ @@ -221,8 +215,8 @@ class wvmCreate(wvmConnect): elif vcpu_mode == "": pass else: - xml += """ - %s""" % vcpu_mode + xml += f""" + {vcpu_mode}""" xml += """""" xml += """ @@ -239,17 +233,18 @@ class wvmCreate(wvmConnect): sd_disk_letters = list(string.ascii_lowercase) add_cd = True - disk_opts = '' - if cache_mode is not None and cache_mode != 'default': - disk_opts += "cache='%s' " % cache_mode - if io_mode is not None and io_mode != 'default': - disk_opts += "io='%s' " % io_mode - if discard_mode is not None and discard_mode != 'default': - disk_opts += "discard='%s' " % discard_mode - if detect_zeroes_mode is not None and detect_zeroes_mode != 'default': - disk_opts += "detect_zeroes='%s' " % detect_zeroes_mode + for volume in volumes: + + disk_opts = '' + if volume['cache_mode'] is not None and volume['cache_mode'] != 'default': + disk_opts += f"cache='{volume['cache_mode']}' " + if volume['io_mode'] is not None and volume['io_mode'] != 'default': + disk_opts += f"io='{volume['io_mode']}' " + if volume['discard_mode'] is not None and volume['discard_mode'] != 'default': + disk_opts += f"discard='{volume['discard_mode']}' " + if volume['detect_zeroes_mode'] is not None and volume['detect_zeroes_mode'] != 'default': + disk_opts += f"detect_zeroes='{volume['detect_zeroes_mode']}' " - for volume in images: stg = self.get_storage_by_vol_path(volume['path']) stg_type = util.get_xml_path(stg.XMLDesc(0), "/pool/@type") @@ -275,7 +270,7 @@ class wvmCreate(wvmConnect): else: xml += """""" % volume['device'] xml += """ """ % (volume['type'], disk_opts) - xml += """ """ % volume['path'] + xml += f""" """ % volume['path'] if volume.get('bus') == 'virtio': xml += """""" % (vd_disk_letters.pop(0), volume.get('bus')) @@ -304,15 +299,15 @@ class wvmCreate(wvmConnect): xml += """""" if volume.get('bus') == 'scsi': - xml += """""" % INSTANCE_VOLUME_DEFAULT_SCSI_CONTROLLER + xml += f"""""" for net in networks.split(','): xml += """""" if mac: - xml += """""" % mac - xml += """""" % net + xml += f"""""" + xml += f"""""" if nwfilter: - xml += """""" % nwfilter + xml += f"""""" if virtio: xml += """""" xml += """""" @@ -332,18 +327,18 @@ class wvmCreate(wvmConnect): xml += """""" xml += """""" - xml += """ - - """ % (graphics, console_pass, listen_addr) + xml += f""" + + """ if qemu_ga and virtio: xml += """ """ - xml += """ """ % video + """ self._defineXML(xml) diff --git a/vrtManager/instance.py b/vrtManager/instance.py index 25229d9..f91cd07 100644 --- a/vrtManager/instance.py +++ b/vrtManager/instance.py @@ -22,8 +22,6 @@ from collections import OrderedDict from vrtManager import util from vrtManager.connection import wvmConnect from vrtManager.storage import wvmStorage, wvmStorages -from webvirtcloud.settings import QEMU_CONSOLE_TYPES -from webvirtcloud.settings import INSTANCE_VOLUME_DEFAULT_OWNER as OWNER class wvmInstances(wvmConnect): @@ -909,7 +907,7 @@ class wvmInstance(wvmConnect): current_type = self.get_console_type() if current_type == console_type: return True - if console_type == '' or console_type not in QEMU_CONSOLE_TYPES: + if console_type == '': return False xml = self._XMLDesc(VIR_DOMAIN_XML_SECURE) root = ElementTree.fromstring(xml) @@ -1203,8 +1201,8 @@ class wvmInstance(wvmConnect): - {OWNER['uid']} - {OWNER['guid']} + {clone_data['disk_owner_uid']} + {clone_data['disk_owner_gid']} 0644 diff --git a/vrtManager/storage.py b/vrtManager/storage.py index ff3e05f..7ea802a 100644 --- a/vrtManager/storage.py +++ b/vrtManager/storage.py @@ -1,6 +1,5 @@ from vrtManager import util from vrtManager.connection import wvmConnect -from webvirtcloud.settings import INSTANCE_VOLUME_DEFAULT_OWNER as OWNER class wvmStorages(wvmConnect): @@ -210,7 +209,7 @@ class wvmStorage(wvmConnect): ) return vol_list - def create_volume(self, name, size, vol_fmt='qcow2', metadata=False, owner=OWNER): + def create_volume(self, name, size, vol_fmt='qcow2', metadata=False, disk_owner_uid=0, disk_owner_gid=0): size = int(size) * 1073741824 storage_type = self.get_type() alloc = size @@ -230,8 +229,8 @@ class wvmStorage(wvmConnect): - {owner['uid']} - {owner['guid']} + {disk_owner_uid} + {disk_owner_gid} 0644 """ @@ -246,7 +245,7 @@ class wvmStorage(wvmConnect): self._createXML(xml, metadata) return name - def clone_volume(self, name, target_file, vol_fmt=None, metadata=False, mode='0644', file_suffix='img', owner=OWNER): + def clone_volume(self, name, target_file, vol_fmt=None, metadata=False, mode='0644', file_suffix='img', disk_owner_uid=0, disk_owner_gid=0): vol = self.get_volume(name) if not vol_fmt: vol_fmt = self.get_volume_type(name) @@ -267,8 +266,8 @@ class wvmStorage(wvmConnect): - {owner['uid']} - {owner['guid']} + {disk_owner_uid} + {disk_owner_gid} {mode} """ diff --git a/webvirtcloud/settings.py.template b/webvirtcloud/settings.py.template index efaeceb..d0d4023 100644 --- a/webvirtcloud/settings.py.template +++ b/webvirtcloud/settings.py.template @@ -174,52 +174,10 @@ LIBVIRT_KEEPALIVE_INTERVAL = 5 LIBVIRT_KEEPALIVE_COUNT = 5 ALLOW_INSTANCE_MULTIPLE_OWNER = True +ALLOW_EMPTY_PASSWORD = False NEW_USER_DEFAULT_INSTANCES = [] CLONE_INSTANCE_DEFAULT_PREFIX = 'instance' CLONE_INSTANCE_AUTO_NAME = False CLONE_INSTANCE_AUTO_MIGRATE = False LOGS_PER_PAGE = 100 -QUOTA_DEBUG = True -ALLOW_EMPTY_PASSWORD = True -SHOW_ACCESS_ROOT_PASSWORD = False -SHOW_ACCESS_SSH_KEYS = False - -# available list style: default (grouped), nongrouped -VIEW_INSTANCES_LIST_STYLE = 'grouped' - -# available volume format: raw, qcow2, qcow -INSTANCE_VOLUME_DEFAULT_FORMAT = 'qcow2' - -# available bus types: virtio, scsi, ide, usb, sata -INSTANCE_VOLUME_DEFAULT_BUS = 'virtio' - -#SCSI types: virtio-scsi, lsilogic -INSTANCE_VOLUME_DEFAULT_SCSI_CONTROLLER = 'virtio-scsi' - -# Volume cache: default, directsync, none, unsafe, writeback, writethrough -INSTANCE_VOLUME_DEFAULT_CACHE = 'directsync' - -# Volume io mode: default, native, threads -INSTANCE_VOLUME_DEFAULT_IO = 'default' - -# Volume detect zeroes mode: default, on, off, unmap -INSTANCE_VOLUME_DEFAULT_DETECT_ZEROES = 'default' - -# Volume discard mode: default, unmap, ignore -INSTANCE_VOLUME_DEFAULT_DISCARD = 'default' - -# up to os, 0=root, 107=qemu or libvirt-bin(for ubuntu) -INSTANCE_VOLUME_DEFAULT_OWNER = {'uid': 0, 'guid': 0} - -# Cpu modes: host-model, host-passthrough, custom -INSTANCE_CPU_DEFAULT_MODE = 'host-model' - -# Chipset/Machine: pc or q35 for x86_64 -INSTANCE_MACHINE_DEFAULT_TYPE = 'q35' - -# Firmware: BIOS or UEFI for x86_64 -INSTANCE_FIRMWARE_DEFAULT_TYPE = 'BIOS' - -# Architecture: x86_64, i686, etc -INSTANCE_ARCH_DEFAULT_TYPE = 'x86_64'