def _update_cache(): """ Updates the cache for all all VirtualMachines in all clusters. This method processes the data in bulk, where possible, to reduce runtime. Generally this should be faster than refreshing individual VirtualMachines. """ timer = Timer() print '------[cache update]-------------------------------' for cluster in Cluster.objects.all(): print '%s:' % cluster.hostname base = cluster.virtual_machines.all() infos = cluster.instances(bulk=True) timer.tick('info fetched from ganeti ') updated = 0 mtimes = base.values_list('hostname', 'id', 'mtime', 'status') d = {} for name, id, mtime, status in mtimes: d[name] = (id, float(mtime) if mtime else None, status) timer.tick('mtimes fetched from db ') for info in infos: name = info['name'] if name in d: id, mtime, status = d[name] if not mtime or mtime < info['mtime'] \ or status != info['status']: #print ' Virtual Machine (updated) : %s' % name #print ' %s :: %s' % (mtime, datetime.fromtimestamp(info['mtime'])) # only update the whole object if it is new or modified. # # XXX status changes will not always be reflected in mtime # explicitly check status to see if it has changed. failing # to check this would result in state changes being lost data = VirtualMachine.parse_persistent_info(info) VirtualMachine.objects.filter(pk=id) \ .update(serialized_info=cPickle.dumps(info), **data) updated += 1 else: # new vm vm = VirtualMachine(cluster=cluster, hostname=info['name']) vm.info = info vm.save() # batch update the cache updated time for all VMs in this cluster. This # will set the last updated time for both VMs that were modified and for # those that weren't. even if it wasn't modified we want the last # updated time to be up to date. # # XXX don't bother checking to see whether this query needs to run. It # normal usage it will almost always need to base.update(cached=datetime.now()) timer.tick('records or timestamps updated') print ' updated: %s out of %s' % (updated, len(infos)) timer.stop() return timer.ticks
def test_used_resources(self): """ Tests retrieving dictionary of resources used by a cluster user """ owner = ClusterUser(name='owner') owner.save() c = Cluster(hostname='testing') c.save() vm0 = VirtualMachine(hostname='one', owner=owner, cluster=c) vm1 = VirtualMachine(hostname='two', ram=1, virtual_cpus=3, disk_size=5, owner=owner, cluster=c) vm2 = VirtualMachine(hostname='three', ram=2, virtual_cpus=4, disk_size=6, owner=owner, cluster=c) vm3 = VirtualMachine(hostname='four', ram=3, virtual_cpus=5, disk_size=7, cluster=c) vm0.save() vm1.save() vm2.save() vm3.save() used = owner.used_resources self.assertEqual(1+2, used['ram']) self.assertEqual(3+4, used['virtual_cpus']) self.assertEqual(5+6, used['disk'])
def create(request, cluster_slug=None): """ Create a new instance Store in DB and Create on given cluster """ user = request.user if not(user.is_superuser or user.has_any_perms(Cluster, ['admin', 'create_vm'])): return render_403(request, 'You do not have permission to create virtual machines') if cluster_slug is not None: cluster = get_object_or_404(Cluster, slug=cluster_slug) else: cluster = None if request.method == 'POST': form = NewVirtualMachineForm(user, None, request.POST) if form.is_valid(): data = form.cleaned_data start = data.get('start') owner = data.get('owner') grantee = data.get('grantee') cluster = data.get('cluster') hostname = data.get('hostname') disk_template = data.get('disk_template') # Default to not pass in pnode and snode # since these will be set if the form is correct pnode = None snode = None os = data.get('os') name_check = data.get('name_check') iallocator = data.get('iallocator') # Hidden fields iallocator_hostname = None if 'iallocator_hostname' in data: iallocator_hostname = data.get('iallocator_hostname') # BEPARAMS vcpus = data.get('vcpus') disk_size = data.get('disk_size') memory = data.get('memory') nic_mode = data.get('nic_mode') nic_link = data.get('nic_link') nic_type = data.get('nic_type') # If iallocator was not checked do not pass in the iallocator # name. If iallocator was checked don't pass snode,pnode. if not iallocator: iallocator_hostname = None pnode = data.get('pnode') # If drbd is being used assign the secondary node if disk_template == 'drbd' and pnode is not None: snode = data.get('snode') # Create dictionary of only parameters supposed to be in hvparams hvparams = dict() hvparam_fields = ('kernel_path', 'root_path', 'serial_console', 'boot_order', 'disk_type', 'cdrom_image_path',) for field in hvparam_fields: hvparams[field] = data[field] try: # XXX attempt to load the virtual machine. This ensure that if # there was a previous vm with the same hostname, but had not # successfully been deleted, then it will be deleted now try: VirtualMachine.objects.get(cluster=cluster, hostname=hostname) except VirtualMachine.DoesNotExist: pass job_id = cluster.rapi.CreateInstance('create', hostname, disk_template, [{"size": disk_size, }],[{'mode':nic_mode, 'link':nic_link, }], start=start, os=os, vcpus=vcpus, pnode=pnode, snode=snode, name_check=name_check, ip_check=name_check, iallocator=iallocator_hostname, hvparams=hvparams, beparams={"memory": memory}) # Check for a vm recovery, If it is not found then if 'vm_recovery' in data: vm = data['vm_recovery'] vm_template = vm.template else: vm_template = VirtualMachineTemplate() vm = VirtualMachine(owner=owner) vm.cluster = cluster vm.hostname = hostname vm.ram = memory vm.virtual_cpus = vcpus vm.disk_size = disk_size # save temporary template # XXX copy each property in data. Avoids errors from properties # that don't exist on the model for k,v in data.items(): setattr(vm_template, k, v) vm_template.save() vm.template = vm_template vm.ignore_cache = True vm.save() job = Job.objects.create(job_id=job_id, obj=vm, cluster=cluster) VirtualMachine.objects.filter(pk=vm.pk).update(last_job=job) # grant admin permissions to the owner. Only do this for new # VMs. otherwise we run the risk of granting perms to a # different owner. We should be preventing that elsewhere, but # lets be extra careful since this check is cheap. if 'vm_recovery' in data: log_action('VM_RECOVER', user, vm) else: grantee.grant('admin', vm) log_action('CREATE', user, vm) return HttpResponseRedirect( reverse('instance-detail', args=[cluster.slug, vm.hostname])) except GanetiApiError, e: msg = 'Error creating virtual machine on this cluster: %s' % e form._errors["cluster"] = form.error_class([msg])
def create(request, cluster_slug=None): """ Create a new instance Store in DB and Create on given cluster """ user = request.user if not(user.is_superuser or user.has_any_perms(Cluster, ['admin', 'create_vm'])): return render_403(request, 'You do not have permission to create virtual \ machines') if cluster_slug is not None: cluster = get_object_or_404(Cluster, slug=cluster_slug) else: cluster = None if request.method == 'POST': form = NewVirtualMachineForm(user, None, request.POST) if form.is_valid(): data = form.cleaned_data owner = data['owner'] cluster = data['cluster'] hostname = data['hostname'] disk_template = data['disk_template'] # Default to not pass in pnode and snode # since these will be set if the form is correct pnode = None snode = None os = data['os'] name_check = data['name_check'] iallocator = data['iallocator'] # Hidden fields iallocator_hostname = None if 'iallocator_hostname' in data: iallocator_hostname = data['iallocator_hostname'] # BEPARAMS vcpus = data['vcpus'] disk_size = data['disk_size'] ram = data['ram'] nicmode = data['nicmode'] niclink = data['niclink'] nictype = data['nictype'] # HVPARAMS disktype = data['disk_type'] kernelpath = data['kernelpath'] rootpath = data['rootpath'] serialconsole = data['serialconsole'] bootorder = data['bootorder'] imagepath = data['imagepath'] # If iallocator was not checked do not pass in the iallocator # name. If iallocator was checked don't pass snode,pnode. if not iallocator: iallocator_hostname = None pnode = data['pnode'] # If drbd is being used assign the secondary node if disk_template == 'drbd' and pnode is not None: snode = data['snode'] try: job_id = cluster.rapi.CreateInstance('create', hostname, disk_template, [{"size": disk_size, }],[{'mode':nicmode, 'link':niclink, }], os=os, vcpus=vcpus, pnode=pnode, snode=snode, name_check=name_check, ip_check=name_check, iallocator=iallocator_hostname, hvparams={'kernel_path': kernelpath, \ 'root_path': rootpath, \ 'serial_console':serialconsole, \ 'boot_order':bootorder, \ 'nic_type':nictype, \ 'disk_type':disktype,\ 'cdrom_image_path':imagepath}, beparams={"memory": ram}) # Wait for job to process as the error will not happen # right away sleep(2) jobstatus = cluster.rapi.GetJobStatus(job_id) # raise an exception if there was an error in the job if jobstatus["status"] == 'error': raise GanetiApiError(jobstatus["opresult"]) vm = VirtualMachine(cluster=cluster, owner=owner, hostname=hostname, disk_size=disk_size, ram=ram, virtual_cpus=vcpus) vm.ignore_cache = True vm.save() job = Job.objects.create(job_id=job_id, obj=vm, cluster=cluster) VirtualMachine.objects.filter(id=vm.id).update(last_job=job) # log information about creating the machine log_action(user, vm, "created") # grant admin permissions to the owner data['grantee'].grant('admin', vm) return HttpResponseRedirect( \ reverse('instance-detail', args=[cluster.slug, vm.hostname])) except GanetiApiError, e: msg = 'Error creating virtual machine on this cluster: %s' % e form._errors["cluster"] = form.error_class([msg])