diff --git a/instances/templates/instance.html b/instances/templates/instance.html index 5a43dcd..79cfe41 100644 --- a/instances/templates/instance.html +++ b/instances/templates/instance.html @@ -309,6 +309,11 @@ {% trans "Resize Instance" %} +
  • + + {% trans "Add New Volume" %} + +
  • @@ -390,6 +395,88 @@ {% endif %}
    +
    + {% if request.user.is_superuser or userinstace.is_change %} +
    {% csrf_token %} +

    {% trans "Volume parameters" %}

    +
    + +
    + +
    +
    +
    + +
    + +
    +
    + +
    +
    +
    + +
    + +
    +
    +
    + +
    + +
    + +
    +
    + +
    + +
    +
    +
    + +
    + +
    +
    +
    + +
    + +
    +
    + {% ifequal status 5 %} + + {% else %} + + {% endifequal %} +
    + {% else %} + {% trans "You don't have permission for resizing instance" %} + + {% endif %} +
    +
    diff --git a/instances/views.py b/instances/views.py index 8dd0a3f..d6d5c61 100644 --- a/instances/views.py +++ b/instances/views.py @@ -4,7 +4,7 @@ import json import socket import crypt import re -from string import letters, digits +import string from random import choice from bisect import insort from django.http import HttpResponse, HttpResponseRedirect @@ -18,6 +18,7 @@ from accounts.models import UserInstance, UserSSHKey from vrtManager.hostdetails import wvmHostDetails from vrtManager.instance import wvmInstance, wvmInstances from vrtManager.connection import connection_manager +from vrtManager.create import wvmCreate from vrtManager.util import randomPasswd from libvirt import libvirtError, VIR_DOMAIN_XML_SECURE from webvirtcloud.settings import QEMU_KEYMAPS, QEMU_CONSOLE_TYPES @@ -279,13 +280,25 @@ def instance(request, compute_id, vname): msg += " (%s > %s)" % (disk_size, ua.max_disk_size) return msg + def get_new_disk_dev(disks, bus): + if bus == "virtio": + dev_base = "vd" + else: + dev_base = "sd" + existing_devs = [ disk['dev'] for disk in disks ] + for l in string.lowercase: + dev = dev_base + l + if dev not in existing_devs: + return dev + raise Exception(_('None available device name')) + try: conn = wvmInstance(compute.hostname, compute.login, compute.password, compute.type, vname) - + status = conn.get_status() autostart = conn.get_autostart() vcpu = conn.get_vcpu() @@ -318,6 +331,13 @@ def instance(request, compute_id, vname): console_passwd = conn.get_console_passwd() clone_free_names = get_clone_free_names() user_quota_msg = check_user_quota(0, 0, 0, 0) + storages = sorted(conn.get_storages()) + cache_modes = sorted(conn.get_cache_modes().items()) + default_cache = settings.INSTANCE_VOLUME_DEFAULT_CACHE + default_format = settings.INSTANCE_VOLUME_DEFAULT_FORMAT + formats = conn.get_image_formats() + default_bus = settings.INSTANCE_VOLUME_DEFAULT_BUS + busses = conn.get_busses() try: instance = Instance.objects.get(compute_id=compute_id, name=vname) @@ -457,6 +477,27 @@ def instance(request, compute_id, vname): addlogmsg(request.user.username, instance.name, msg) return HttpResponseRedirect(request.get_full_path() + '#resize') + if 'addvolume' in request.POST and (request.user.is_superuser or userinstace.is_change): + connCreate = wvmCreate(compute.hostname, + compute.login, + compute.password, + compute.type) + storage = request.POST.get('storage', '') + name = request.POST.get('name', '') + extension = request.POST.get('extension', '') + format = request.POST.get('format', '') + size = request.POST.get('size', 0) + meta_prealloc = request.POST.get('meta_prealloc', False) + bus = request.POST.get('bus', '') + cache = request.POST.get('cache', '') + target = get_new_disk_dev(disks, bus) + + path = connCreate.create_volume(storage, name, size, format, meta_prealloc, extension) + conn.attach_disk(path, target, subdriver=format, cache=cache, targetbus=bus) + msg = _('Attach new disk') + addlogmsg(request.user.username, instance.name, msg) + return HttpResponseRedirect(request.get_full_path() + '#resize') + if 'umount_iso' in request.POST: image = request.POST.get('path', '') dev = request.POST.get('umount_iso', '') diff --git a/vrtManager/connection.py b/vrtManager/connection.py index c62c6e4..b9c6a26 100644 --- a/vrtManager/connection.py +++ b/vrtManager/connection.py @@ -380,6 +380,25 @@ class wvmConnect(object): interface.append(inface) return interface + def get_cache_modes(self): + """Get cache available modes""" + return { + 'default': 'Default', + 'none': 'Disabled', + 'writethrough': 'Write through', + 'writeback': 'Write back', + 'directsync': 'Direct sync', # since libvirt 0.9.5 + 'unsafe': 'Unsafe', # since libvirt 0.9.7 + } + + def get_busses(self): + """Get available busses""" + return [ 'ide', 'scsi', 'usb', 'virtio' ] + + def get_image_formats(self): + """Get available image formats""" + return [ 'raw', 'qcow', 'qcow2' ] + def get_iface(self, name): return self.wvm.interfaceLookupByName(name) diff --git a/vrtManager/create.py b/vrtManager/create.py index 15f1cd8..9fc8d98 100644 --- a/vrtManager/create.py +++ b/vrtManager/create.py @@ -48,23 +48,12 @@ class wvmCreate(wvmConnect): """Get guest capabilities""" return util.get_xml_path(self.get_cap_xml(), "/capabilities/host/cpu/arch") - def get_cache_modes(self): - """Get cache available modes""" - return { - 'default': 'Default', - 'none': 'Disabled', - 'writethrough': 'Write through', - 'writeback': 'Write back', - 'directsync': 'Direct sync', # since libvirt 0.9.5 - 'unsafe': 'Unsafe', # since libvirt 0.9.7 - } - - def create_volume(self, storage, name, size, format='qcow2', metadata=False): + def create_volume(self, storage, name, size, format='qcow2', metadata=False, image_extension='img'): size = int(size) * 1073741824 stg = self.get_storage(storage) storage_type = util.get_xml_path(stg.XMLDesc(0), "/pool/@type") if storage_type == 'dir': - name += '.img' + name += '.' + image_extension alloc = 0 else: alloc = size diff --git a/vrtManager/instance.py b/vrtManager/instance.py index 0777b35..14feab1 100644 --- a/vrtManager/instance.py +++ b/vrtManager/instance.py @@ -340,6 +340,22 @@ class wvmInstance(wvmConnect): xmldom = ElementTree.tostring(tree) self._defineXML(xmldom) + def attach_disk(self, source, target, sourcetype='file', type='disk', driver='qemu', subdriver='raw', cache='none', targetbus='ide'): + tree = ElementTree.fromstring(self._XMLDesc(0)) + xml_disk = """ + + + + + + """ % (sourcetype, type, driver, subdriver, cache, source, target, targetbus) + if self.get_status() == 5: + devices = tree.find('devices') + elm_disk = ElementTree.fromstring(xml_disk) + devices.append(elm_disk) + xmldom = ElementTree.tostring(tree) + self._defineXML(xmldom) + def cpu_usage(self): cpu_usage = {} if self.get_status() == 1: diff --git a/webvirtcloud/settings.py b/webvirtcloud/settings.py index 724fb1a..1f87d20 100644 --- a/webvirtcloud/settings.py +++ b/webvirtcloud/settings.py @@ -124,3 +124,6 @@ ALLOW_EMPTY_PASSWORD = True SHOW_ACCESS_ROOT_PASSWORD = False SHOW_ACCESS_SSH_KEYS = False SHOW_PROFILE_EDIT_PASSWORD = False +INSTANCE_VOLUME_DEFAULT_FORMAT = 'qcow2' +INSTANCE_VOLUME_DEFAULT_BUS = 'virtio' +INSTANCE_VOLUME_DEFAULT_CACHE = 'directsync'