diff --git a/accounts/templatetags/tags_fingerprint.py b/accounts/templatetags/tags_fingerprint.py index d15c473..5688039 100644 --- a/accounts/templatetags/tags_fingerprint.py +++ b/accounts/templatetags/tags_fingerprint.py @@ -9,4 +9,4 @@ register = template.Library() def ssh_to_fingerprint(line): key = base64.b64decode(line.strip().split()[1].encode('ascii')) fp_plain = hashlib.md5(key).hexdigest() - return ':'.join(a+b for a, b in zip(fp_plain[::2], fp_plain[1::2])) + return ':'.join(a + b for a, b in zip(fp_plain[::2], fp_plain[1::2])) diff --git a/create/forms.py b/create/forms.py index 5b9fab5..fccf944 100644 --- a/create/forms.py +++ b/create/forms.py @@ -40,6 +40,7 @@ class NewVMForm(forms.Form): storage = forms.CharField(max_length=20, required=False) template = forms.CharField(required=False) images = forms.CharField(required=False) + cache_mode = forms.CharField(error_messages={'required': _('Please select HDD cache mode')}) hdd_size = forms.IntegerField(required=False) meta_prealloc = forms.BooleanField(required=False) virtio = forms.BooleanField(required=False) diff --git a/create/templates/create_instance.html b/create/templates/create_instance.html index 37189b7..f9a0692 100644 --- a/create/templates/create_instance.html +++ b/create/templates/create_instance.html @@ -77,6 +77,16 @@ </select> </div> </div> + <div class="form-group"> + <label class="col-sm-3 control-label">{% trans "HDD cache mode" %}</label> + <div class="col-sm-6"> + <select id="cache_mode" name="cache_mode" class="form-control"> + {% for mode, name in cache_modes %} + <option value="{{ mode }}">{% trans name %}</option> + {% endfor %} + </select> + </div> + </div> <div class="form-group"> <label class="col-sm-3 control-label">{% trans "Network" %}</label> <div class="col-sm-6"> @@ -159,6 +169,16 @@ </div> <label class="col-lg-1 control-label">{% trans "Image" %}</label> </div> + <div class="form-group"> + <label class="col-sm-3 control-label">{% trans "HDD cache mode" %}</label> + <div class="col-sm-6"> + <select id="cache_mode" name="cache_mode" class="form-control"> + {% for mode, name in cache_modes %} + <option value="{{ mode }}">{% trans name %}</option> + {% endfor %} + </select> + </div> + </div> <div class="form-group"> <label class="col-sm-3 control-label">{% trans "Network" %}</label> <div class="col-sm-6"> diff --git a/create/views.py b/create/views.py index 5b03f8c..c3e1139 100644 --- a/create/views.py +++ b/create/views.py @@ -42,6 +42,7 @@ def create_instance(request, compute_id): networks = sorted(conn.get_networks()) instances = conn.get_instances() get_images = sorted(conn.get_storages_images()) + cache_modes = sorted(conn.get_cache_modes().items()) mac_auto = util.randomMAC() except libvirtError as lib_err: error_messages.append(lib_err) @@ -123,11 +124,15 @@ def create_instance(request, compute_id): volumes[path] = conn.get_volume_type(path) except libvirtError as lib_err: error_messages.append(lib_err.message) + if data['cache_mode'] not in conn.get_cache_modes(): + error_msg = _("Invalid cache mode") + error_messages.append(error_msg) if not error_messages: uuid = util.randomUUID() try: conn.create_instance(data['name'], data['memory'], data['vcpu'], data['host_model'], - uuid, volumes, data['networks'], data['virtio'], data['mac']) + uuid, volumes, data['cache_mode'], data['networks'], data['virtio'], + data['mac']) create_instance = Instance(compute_id=compute_id, name=data['name'], uuid=uuid) create_instance.save() return HttpResponseRedirect(reverse('instance', args=[compute_id, data['name']])) diff --git a/instances/views.py b/instances/views.py index 29a1a1b..8d9afd9 100644 --- a/instances/views.py +++ b/instances/views.py @@ -103,7 +103,7 @@ def instances(request): conn.start(name) addlogmsg(request.user.username, instance.name, msg) return HttpResponseRedirect(request.get_full_path()) - + if 'getvvfile' in request.POST: msg = _("Send console.vv file") addlogmsg(request.user.username, instance.name, msg) diff --git a/vrtManager/create.py b/vrtManager/create.py index 1d37300..cc1f7f2 100644 --- a/vrtManager/create.py +++ b/vrtManager/create.py @@ -7,9 +7,17 @@ from webvirtcloud.settings import QEMU_CONSOLE_DEFAULT_TYPE def get_rbd_storage_data(stg): xml = stg.XMLDesc(0) ceph_user = util.get_xml_path(xml, "/pool/source/auth/@username") - ceph_host = util.get_xml_path(xml, "/pool/source/host/@name") - secrt_uuid = util.get_xml_path(xml, "/pool/source/auth/secret/@uuid") - return ceph_user, secrt_uuid, ceph_host + + def get_ceph_hosts(ctx): + hosts = [] + for host in ctx.xpathEval("/pool/source/host"): + name = host.prop("name") + if name: + hosts.append({'name': name, 'port': host.prop("port")}) + return hosts + ceph_hosts = util.get_xml_path(xml, func=get_ceph_hosts) + secret_uuid = util.get_xml_path(xml, "/pool/source/auth/secret/@uuid") + return ceph_user, secret_uuid, ceph_hosts class wvmCreate(wvmConnect): @@ -40,6 +48,17 @@ 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): size = int(size) * 1073741824 stg = self.get_storage(storage) @@ -121,7 +140,7 @@ class wvmCreate(wvmConnect): vol = self.get_volume_by_path(path) vol.delete() - def create_instance(self, name, memory, vcpu, host_model, uuid, images, networks, virtio, mac=None): + def create_instance(self, name, memory, vcpu, host_model, uuid, images, cache_mode, networks, virtio, mac=None): """ Create VM function """ @@ -162,19 +181,27 @@ class wvmCreate(wvmConnect): stg_type = util.get_xml_path(stg.XMLDesc(0), "/pool/@type") if stg_type == 'rbd': - ceph_user, secrt_uuid, ceph_host = get_rbd_storage_data(stg) + ceph_user, secret_uuid, ceph_hosts = get_rbd_storage_data(stg) xml += """<disk type='network' device='disk'> - <driver name='qemu' type='%s'/> + <driver name='qemu' type='%s' cache='%s'/> <auth username='%s'> <secret type='ceph' uuid='%s'/> </auth> - <source protocol='rbd' name='%s'> - <host name='%s' port='6789'/> - </source>""" % (img_type, ceph_user, secrt_uuid, image, ceph_host) + <source protocol='rbd' name='%s'>""" % (img_type, cache_mode, ceph_user, secret_uuid, image) + if isinstance(ceph_hosts, list): + for host in ceph_hosts: + if host.get('port'): + xml += """ + <host name='%s' port='%s'/>""" % (host.get('name'), host.get('port')) + else: + xml += """ + <host name='%s'/>""" % host.get('name') + xml += """ + </source>""" else: xml += """<disk type='file' device='disk'> - <driver name='qemu' type='%s'/> - <source file='%s'/>""" % (img_type, image) + <driver name='qemu' type='%s' cache='%s'/> + <source file='%s'/>""" % (img_type, cache_mode, image) if virtio: xml += """<target dev='vd%s' bus='virtio'/>""" % (disk_letters.pop(0),) diff --git a/vrtManager/instance.py b/vrtManager/instance.py index 4218aa4..0f3b258 100644 --- a/vrtManager/instance.py +++ b/vrtManager/instance.py @@ -81,7 +81,7 @@ class wvmInstances(wvmConnect): dom = self.get_instance(name) xml = dom.XMLDesc(VIR_DOMAIN_XML_SECURE) self.wvm.defineXML(xml) - + def graphics_type(self, name): inst = self.get_instance(name) console_type = util.get_xml_path(inst.XMLDesc(0), "/domain/devices/graphics/@type")