def modify(request, cluster_slug, instance): vm, cluster = get_vm_and_cluster_or_404(cluster_slug, instance) user = request.user if not (user.is_superuser or user.has_any_perms(vm, ['admin', 'modify']) or user.has_perm('admin', cluster)): raise PermissionDenied( 'You do not have permissions to edit this virtual machine') hv = get_hypervisor(vm) if hv == 'kvm': hv_form = KvmModifyVirtualMachineForm template = 'ganeti/virtual_machine/edit_kvm.html' elif hv == 'xen-pvm': hv_form = PvmModifyVirtualMachineForm template = 'ganeti/virtual_machine/edit_pvm.html' elif hv == 'xen-hvm': hv_form = HvmModifyVirtualMachineForm template = 'ganeti/virtual_machine/edit_hvm.html' else: hv_form = None template = 'ganeti/virtual_machine/edit_base.html' # XXX no matter what, we're gonna call hv_form() and die. Let's do it # louder than usual. >:3 msg = "Hey, guys, implementation error in views/vm.py:modify" raise RuntimeError(msg) if request.method == 'POST': form = hv_form(vm, request.POST) form.owner = vm.owner form.vm = vm form.cluster = cluster if form.is_valid(): data = form.cleaned_data request.session['edit_form'] = data request.session['edit_vm'] = vm.id return HttpResponseRedirect( reverse('instance-modify-confirm', args=[cluster.slug, vm.hostname])) elif request.method == 'GET': if 'edit_form' in request.session \ and vm.id == request.session['edit_vm']: form = hv_form(vm, request.session['edit_form']) else: form = hv_form(vm) return render_to_response( template, {'cluster': cluster, 'instance': vm, 'form': form, 'balloon': has_balloonmem(cluster) }, context_instance=RequestContext(request), )
def modify(request, cluster_slug, instance): vm, cluster = get_vm_and_cluster_or_404(cluster_slug, instance) user = request.user if not (user.is_superuser or user.has_any_perms(vm, ['admin', 'modify']) or user.has_perm('admin', cluster)): raise PermissionDenied( 'You do not have permissions to edit this virtual machine') hv = get_hypervisor(vm) if hv == 'kvm': hv_form = KvmModifyVirtualMachineForm template = 'ganeti/virtual_machine/edit_kvm.html' elif hv == 'xen-pvm': hv_form = PvmModifyVirtualMachineForm template = 'ganeti/virtual_machine/edit_pvm.html' elif hv == 'xen-hvm': hv_form = HvmModifyVirtualMachineForm template = 'ganeti/virtual_machine/edit_hvm.html' else: hv_form = None template = 'ganeti/virtual_machine/edit_base.html' # XXX no matter what, we're gonna call hv_form() and die. Let's do it # louder than usual. >:3 msg = "Hey, guys, implementation error in views/vm.py:modify" raise RuntimeError(msg) if request.method == 'POST': form = hv_form(vm, request.POST) form.owner = vm.owner form.vm = vm form.cluster = cluster if form.is_valid(): data = form.cleaned_data request.session['edit_form'] = data request.session['edit_vm'] = vm.id return HttpResponseRedirect( reverse('instance-modify-confirm', args=[cluster.slug, vm.hostname])) elif request.method == 'GET': if 'edit_form' in request.session \ and vm.id == request.session['edit_vm']: form = hv_form(vm, request.session['edit_form']) else: form = hv_form(vm) return render_to_response( template, { 'cluster': cluster, 'instance': vm, 'form': form, 'balloon': has_balloonmem(cluster) }, context_instance=RequestContext(request), )
def instance_to_template(vm, name): """ Create, save, and return a VM template representing all of the information in the VM instance. The name is given to the template to distinguish it from other templates. """ template = VirtualMachineTemplate() # Basic stuff first. template.template_name = name template.description = "" template.cluster = vm.cluster template.start = vm.info["admin_state"] template.disk_template = vm.info["disk_template"] template.os = vm.operating_system # Backend parameters. template.vcpus = vm.virtual_cpus template.memory = vm.ram if has_balloonmem(vm.cluster): template.minmem = vm.minram template.disks = [{"size": size} for size in vm.info["disk.sizes"]] template.disk_type = vm.info["hvparams"]["disk_type"] template.nics = [{ "mode": mode, "link": link } for mode, link in zip(vm.info["nic.modes"], vm.info["nic.links"])] template.nic_type = vm.info["hvparams"]["nic_type"] # Hypervisor parameters. template.kernel_path = vm.info["hvparams"]["kernel_path"] template.root_path = vm.info["hvparams"]["root_path"] template.serial_console = vm.info["hvparams"]["serial_console"] template.boot_order = vm.info["hvparams"]["boot_order"] template.cdrom_image_path = vm.info["hvparams"]["cdrom_image_path"] template.cdrom2_image_path = vm.info["hvparams"]["cdrom2_image_path"] template.save() return template
def instance_to_template(vm, name): """ Create, save, and return a VM template representing all of the information in the VM instance. The name is given to the template to distinguish it from other templates. """ template = VirtualMachineTemplate() # Basic stuff first. template.template_name = name template.description = "" template.cluster = vm.cluster template.start = vm.info["admin_state"] template.disk_template = vm.info["disk_template"] template.os = vm.operating_system # Backend parameters. template.vcpus = vm.virtual_cpus template.memory = vm.ram if has_balloonmem(vm.cluster): template.minmem = vm.minram template.disks = [{"size": size} for size in vm.info["disk.sizes"]] template.disk_type = vm.info["hvparams"]["disk_type"] template.nics = [{"mode": mode, "link": link} for mode, link in zip(vm.info["nic.modes"], vm.info["nic.links"])] template.nic_type = vm.info["hvparams"]["nic_type"] # Hypervisor parameters. template.kernel_path = vm.info["hvparams"]["kernel_path"] template.root_path = vm.info["hvparams"]["root_path"] template.serial_console = vm.info["hvparams"]["serial_console"] template.boot_order = vm.info["hvparams"]["boot_order"] template.cdrom_image_path = vm.info["hvparams"]["cdrom_image_path"] template.cdrom2_image_path = vm.info["hvparams"]["cdrom2_image_path"] template.save() return template
def template_to_instance(template, hostname, owner): """ Instantiate a VM template with a given hostname and owner. """ cluster = template.cluster beparams = { "vcpus": template.vcpus, } hvparams = {} hv = template.hypervisor or cluster.info["default_hypervisor"] kvm = hv == 'kvm' pvm = hv == 'xen-pvm' hvm = hv == 'xen-hvm' kvm_or_hvm = kvm or hvm kvm_or_pvm = kvm or pvm if kvm_or_hvm: hvparams.update(boot_order=template.boot_order) hvparams.update(cdrom_image_path=template.cdrom_image_path) hvparams.update(nic_type=template.nic_type) hvparams.update(disk_type=template.disk_type) if kvm_or_pvm: hvparams.update(kernel_path=template.kernel_path) hvparams.update(root_path=template.root_path) if kvm: hvparams.update(cdrom2_image_path=template.cdrom2_image_path) hvparams.update(serial_console=template.serial_console) memory = template.memory if has_balloonmem(cluster): minram = template.minmem beparams['minmem'] = minram beparams['maxmem'] = memory else: beparams['memory'] = memory vcpus = template.vcpus disk_size = template.disks[0]["size"] kwargs = { "os": template.os, "hypervisor": hv, "ip_check": template.ip_check, "name_check": template.name_check, "beparams": beparams, "no_install": template.no_install, "start": template.start, "hvparams": hvparams, } # Using auto allocator if template.iallocator: default_iallocator = cluster.info['default_iallocator'] kwargs.update(iallocator=default_iallocator) # Not using allocator, pass pnode else: kwargs.update(pnode=template.pnode) # Also pass in snode if it exists (drdb) if template.snode: kwargs.update(snode=template.snode) # secondary node isn't set but we're using drdb, so programming error # (this shouldn't happen if form validation is done correctly) elif template.disk_template == 'drdb': msg = 'Disk template set to drdb, but no secondary node set' raise RuntimeError(msg) job_id = cluster.rapi.CreateInstance('create', hostname, template.disk_template, template.disks, template.nics, **kwargs) vm = VirtualMachine() vm.cluster = cluster vm.hostname = hostname vm.ram = memory if has_balloonmem(cluster): vm.minram = minram vm.virtual_cpus = vcpus vm.disk_size = disk_size vm.owner = owner vm.ignore_cache = True # Do a dance to get the VM and the job referencing each other. vm.save() job = Job.objects.create(job_id=job_id, obj=vm, cluster=cluster) job.save() vm.last_job = job vm.save() # Grant admin permissions to the owner. owner.permissable.grant('admin', vm) return vm
def cluster_default_info(cluster, hypervisor=None): """ Returns a dictionary containing the following default values set on a cluster: iallocator, hypervisors, vcpus, ram, nictype, nicmode, kernelpath, rootpath, serialconsole, bootorder, imagepath """ # Create variables so that dictionary lookups are not so horrendous. info = cluster.info beparams = info['beparams']['default'] hvs = info['enabled_hypervisors'] if hypervisor is not None: if hypervisor not in hvs: raise RuntimeError("Was asked to deal with a cluster/HV mismatch") else: hv = hypervisor else: hv = info['default_hypervisor'] hvparams = info['hvparams'][hv] if hv == 'kvm': c = constants.KVM_CHOICES elif hv == 'xen-hvm' or hv == 'xen-pvm': c = constants.HVM_CHOICES if hv == 'xen-pvm': # PVM does not have disk types or nic types, so these options get # taken from HVM. This does not affect forms as pvm ignores # the disk_type and nic_type fields. hvparams['disk_type'] = info['hvparams']['xen-hvm']['disk_type'] hvparams['nic_type'] = info['hvparams']['xen-hvm']['nic_type'] else: c = constants.NO_CHOICES disktypes = c['disk_type'] nictypes = c['nic_type'] bootdevices = c['boot_order'] try: iallocator_info = info['default_iallocator'] except: iallocator_info = None if 'nicparams' in info: nic_mode = info['nicparams']['default']['mode'] nic_link = info['nicparams']['default']['link'] else: nic_mode = None nic_link = None extraparams = { 'boot_devices': bootdevices, 'disk_types': disktypes, 'hypervisor': hv, 'hypervisors': zip(hvs, hvs), 'iallocator': iallocator_info, 'nic_types': nictypes, 'nic_mode': nic_mode, 'nic_link': nic_link, 'vcpus': beparams['vcpus'], } if has_balloonmem(cluster): extraparams['memory'] = beparams['maxmem'] else: extraparams['memory'] = beparams['memory'] return dict(hvparams, **extraparams)
def modify_confirm(request, cluster_slug, instance): vm, cluster = get_vm_and_cluster_or_404(cluster_slug, instance) hv = get_hypervisor(vm) if hv == 'kvm': hv_form = KvmModifyVirtualMachineForm elif hv == 'xen-pvm': hv_form = PvmModifyVirtualMachineForm elif hv == 'xen-hvm': hv_form = HvmModifyVirtualMachineForm else: hv_form = None # XXX no matter what, we're gonna call hv_form() and die. Let's do it # louder than usual. >:3 msg = "Hey, guys, implementation error in views/vm.py:modify_confirm" raise RuntimeError(msg) user = request.user power = user.is_superuser or user.has_any_perms(vm, ['admin', 'power']) if not (user.is_superuser or user.has_any_perms(vm, ['admin', 'modify']) or user.has_perm('admin', cluster)): raise PermissionDenied( _('You do not have permissions to edit this virtual machine')) if request.method == "POST": if 'edit' in request.POST: return HttpResponseRedirect( reverse("instance-modify", args=[cluster.slug, vm.hostname])) elif 'reboot' in request.POST or 'save' in request.POST: form = ModifyConfirmForm(request.POST) form.session = request.session form.owner = vm.owner form.vm = vm form.cluster = cluster if form.is_valid(): beparams = {} data = form.cleaned_data rapi_dict = data['rapi_dict'] nics = rapi_dict.pop('nics') beparams['vcpus'] = rapi_dict.pop('vcpus') if has_balloonmem(cluster): beparams['maxmem'] = rapi_dict.pop('maxmem') beparams['minmem'] = rapi_dict.pop('minmem') else: beparams['memory'] = rapi_dict.pop('memory') os_name = rapi_dict.pop('os') notes = rapi_dict.pop('notes') job_id = cluster.rapi.ModifyInstance( instance, nics=nics, os_name=os_name, hvparams=rapi_dict, beparams=beparams) # Create job and update message on virtual machine detail page job = Job.objects.create(job_id=job_id, obj=vm, cluster=cluster) VirtualMachine.objects \ .filter(id=vm.id).update(last_job=job, ignore_cache=True, note_text=notes) # log information about modifying this instance log_action('EDIT', user, vm) if 'reboot' in request.POST and vm.info['status'] == 'running': if power: # Reboot the vm job = vm.reboot() log_action('VM_REBOOT', user, vm, job) else: raise PermissionDenied( _("Sorry, but you do not have permission " "to reboot this machine.")) # Redirect to instance-detail return HttpResponseRedirect( reverse("instance-detail", args=[cluster.slug, vm.hostname])) elif 'cancel' in request.POST: # Remove session variables. if 'edit_form' in request.session: del request.session['edit_form'] # Redirect to instance-detail return HttpResponseRedirect( reverse("instance-detail", args=[cluster.slug, vm.hostname])) elif request.method == "GET": form = ModifyConfirmForm() session = request.session if 'edit_form' not in request.session: return HttpResponseBadRequest('Incorrect Session Data') data = session['edit_form'] info = vm.info hvparams = info['hvparams'] old_set = dict( vcpus=info['beparams']['vcpus'], os=info['os'], notes=vm.note_text ) if has_balloonmem(cluster): old_set['maxmem'] = info['beparams']['maxmem'] old_set['minmem'] = info['beparams']['minmem'] else: old_set['memory'] = info['beparams']['memory'] nic_count = len(info['nic.links']) for i in xrange(nic_count): old_set['nic_link_%s' % i] = info['nic.links'][i] old_set['nic_mac_%s' % i] = info['nic.macs'][i] # Add hvparams to the old_set old_set.update(hvparams) instance_diff = {} fields = hv_form(vm, data).fields for key in data.keys(): if key in ['memory', 'maxmem', 'minmem']: diff = compare(render_storage(old_set[key]), render_storage(data[key])) elif key == 'os': oses = os_prettify([old_set[key], data[key]]) if len(oses) > 1: """ XXX - Special case for a cluster with two different types of optgroups (i.e. Image, Debootstrap). The elements at 00 and 10: The optgroups The elements at 010 and 110: Tuple containing the OS Name and OS value. The elements at 0101 and 1101: String containing the OS Name """ oses[0][1][0] = list(oses[0][1][0]) oses[1][1][0] = list(oses[1][1][0]) oses[0][1][0][1] = '%s (%s)' % (oses[0][1][0][1], oses[0][0]) oses[1][1][0][1] = '%s (%s)' % (oses[1][1][0][1], oses[1][0]) oses = oses[0][1] + oses[1][1] diff = compare(oses[0][1], oses[1][1]) else: oses = oses[0][1] diff = compare(oses[0][1], oses[1][1]) # diff = compare(oses[0][1], oses[1][1]) if key in ['nic_count', 'nic_count_original']: continue elif key not in old_set.keys(): diff = "" instance_diff[fields[key].label] = _('Added') else: diff = compare(old_set[key], data[key]) if diff != "": label = fields[key].label instance_diff[label] = diff # remove mac if it has not changed for i in xrange(nic_count): if fields['nic_mac_%s' % i].label not in instance_diff: del data['nic_mac_%s' % i] # Repopulate form with changed values form.fields['rapi_dict'] = CharField(widget=HiddenInput, initial=json.dumps(data)) return render_to_response( 'ganeti/virtual_machine/edit_confirm.html', { 'cluster': cluster, 'form': form, 'instance': vm, 'instance_diff': instance_diff, 'power': power, }, context_instance=RequestContext(request), )
def modify_confirm(request, cluster_slug, instance): vm, cluster = get_vm_and_cluster_or_404(cluster_slug, instance) hv = get_hypervisor(vm) if hv == 'kvm': hv_form = KvmModifyVirtualMachineForm elif hv == 'xen-pvm': hv_form = PvmModifyVirtualMachineForm elif hv == 'xen-hvm': hv_form = HvmModifyVirtualMachineForm else: hv_form = None # XXX no matter what, we're gonna call hv_form() and die. Let's do it # louder than usual. >:3 msg = "Hey, guys, implementation error in views/vm.py:modify_confirm" raise RuntimeError(msg) user = request.user power = user.is_superuser or user.has_any_perms(vm, ['admin', 'power']) if not (user.is_superuser or user.has_any_perms(vm, ['admin', 'modify']) or user.has_perm('admin', cluster)): raise PermissionDenied( _('You do not have permissions to edit this virtual machine')) if request.method == "POST": if 'edit' in request.POST: return HttpResponseRedirect( reverse("instance-modify", args=[cluster.slug, vm.hostname])) elif 'reboot' in request.POST or 'save' in request.POST: form = ModifyConfirmForm(request.POST) form.session = request.session form.owner = vm.owner form.vm = vm form.cluster = cluster if form.is_valid(): beparams = {} data = form.cleaned_data rapi_dict = data['rapi_dict'] nics = rapi_dict.pop('nics') beparams['vcpus'] = rapi_dict.pop('vcpus') if has_balloonmem(cluster): beparams['maxmem'] = rapi_dict.pop('maxmem') beparams['minmem'] = rapi_dict.pop('minmem') else: beparams['memory'] = rapi_dict.pop('memory') os_name = rapi_dict.pop('os') notes = rapi_dict.pop('notes') job_id = cluster.rapi.ModifyInstance(instance, nics=nics, os_name=os_name, hvparams=rapi_dict, beparams=beparams) # Create job and update message on virtual machine detail page job = Job.objects.create(job_id=job_id, obj=vm, cluster=cluster) VirtualMachine.objects \ .filter(id=vm.id).update(last_job=job, ignore_cache=True, note_text=notes) # log information about modifying this instance log_action('EDIT', user, vm) if 'reboot' in request.POST and vm.info['status'] == 'running': if power: # Reboot the vm job = vm.reboot() log_action('VM_REBOOT', user, vm, job) else: raise PermissionDenied( _("Sorry, but you do not have permission " "to reboot this machine.")) # Redirect to instance-detail return HttpResponseRedirect( reverse("instance-detail", args=[cluster.slug, vm.hostname])) elif 'cancel' in request.POST: # Remove session variables. if 'edit_form' in request.session: del request.session['edit_form'] # Redirect to instance-detail return HttpResponseRedirect( reverse("instance-detail", args=[cluster.slug, vm.hostname])) elif request.method == "GET": form = ModifyConfirmForm() session = request.session if 'edit_form' not in request.session: return HttpResponseBadRequest('Incorrect Session Data') data = session['edit_form'] info = vm.info hvparams = info['hvparams'] old_set = dict(vcpus=info['beparams']['vcpus'], os=info['os'], notes=vm.note_text) if has_balloonmem(cluster): old_set['maxmem'] = info['beparams']['maxmem'] old_set['minmem'] = info['beparams']['minmem'] else: old_set['memory'] = info['beparams']['memory'] nic_count = len(info['nic.links']) for i in xrange(nic_count): old_set['nic_link_%s' % i] = info['nic.links'][i] old_set['nic_mac_%s' % i] = info['nic.macs'][i] # Add hvparams to the old_set old_set.update(hvparams) instance_diff = {} fields = hv_form(vm, data).fields for key in data.keys(): if key in ['memory', 'maxmem', 'minmem']: diff = compare(render_storage(old_set[key]), render_storage(data[key])) elif key == 'os': oses = os_prettify([old_set[key], data[key]]) if len(oses) > 1: """ XXX - Special case for a cluster with two different types of optgroups (i.e. Image, Debootstrap). The elements at 00 and 10: The optgroups The elements at 010 and 110: Tuple containing the OS Name and OS value. The elements at 0101 and 1101: String containing the OS Name """ oses[0][1][0] = list(oses[0][1][0]) oses[1][1][0] = list(oses[1][1][0]) oses[0][1][0][1] = '%s (%s)' % (oses[0][1][0][1], oses[0][0]) oses[1][1][0][1] = '%s (%s)' % (oses[1][1][0][1], oses[1][0]) oses = oses[0][1] + oses[1][1] diff = compare(oses[0][1], oses[1][1]) else: oses = oses[0][1] diff = compare(oses[0][1], oses[1][1]) # diff = compare(oses[0][1], oses[1][1]) if key in ['nic_count', 'nic_count_original']: continue elif key not in old_set.keys(): diff = "" instance_diff[fields[key].label] = _('Added') else: diff = compare(old_set[key], data[key]) if diff != "": label = fields[key].label instance_diff[label] = diff # remove mac if it has not changed for i in xrange(nic_count): if fields['nic_mac_%s' % i].label not in instance_diff: del data['nic_mac_%s' % i] # Repopulate form with changed values form.fields['rapi_dict'] = CharField(widget=HiddenInput, initial=json.dumps(data)) return render_to_response( 'ganeti/virtual_machine/edit_confirm.html', { 'cluster': cluster, 'form': form, 'instance': vm, 'instance_diff': instance_diff, 'power': power, }, context_instance=RequestContext(request), )