Esempio n. 1
0
    def _update_vm(self, cluster, info, data, updated, callback):
        """
        updates an individual VirtualMachine, this is the actual work function

        @param cluster - cluster this node is on
        @param info - info from ganeti
        @param data - data from database
        @param updated - counter object
        @param callback - callback fired when method is complete.
        """
        name = info['name']
        if name in data:
            id, mtime, status = data[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
                parsed = VirtualMachine.parse_persistent_info(info)
                if 'delete' in parsed:
                    VirtualMachine.objects.filter(pk=id).delete()
                else:
                    VirtualMachine.objects.filter(pk=id) \
                        .update(serialized_info=cPickle.dumps(info), **parsed)
                updated += 1
        else:
            # new vm
            vm = VirtualMachine(cluster=cluster, hostname=info['name'])
            vm.info = info
            vm.save()
            id = vm.id
            updated += 1

        callback(id)
Esempio n. 2
0
    def setUp(self):
        self.tearDown()
        models.client.GanetiRapiClient = RapiProxy

        cluster = Cluster(hostname='test.cluster',
                          slug='test',
                          username='******',
                          password='******')
        cluster.id = 23  # XXX MySQL DB does not reset auto-increment IDs when an object is removed
        cluster.save()
        cluster.sync_nodes()

        template = VirtualMachineTemplate(template_name="Template1",
                                          cluster=cluster)
        template.disks = [{'size': 500}]
        template.nics = [{'mode': 'bridged', 'link': ''}]
        template.save()

        instance = VirtualMachine(hostname='new.vm.hostname', cluster=cluster)
        instance.info = INSTANCE
        instance.disks = []
        instance.nics = []
        instance.save()

        # Users
        self.create_users([
            ('superuser', {
                'is_superuser': True
            }),
            'cluster_admin',
            'create_vm',
            'unauthorized',
        ])
        self.cluster_admin.grant('admin', cluster)
        self.create_vm.grant('create_vm', cluster)

        self.create_template_data = dict(
            cluster=cluster.pk,
            template_name='foo_bar',
            memory=512,
            disk_template='plain',
            disk_count=0,
            nic_count=0,
        )

        self.cluster = cluster
        self.template = template
        self.instance = instance
        self.c = Client()
Esempio n. 3
0
    def setUp(self):
        self.tearDown()
        models.client.GanetiRapiClient = RapiProxy

        cluster = Cluster(hostname='test.cluster', slug='test',
                          username='******', password='******')
        cluster.id = 23  # XXX MySQL DB does not reset auto-increment
                         # IDs when an object is removed
        cluster.save()
        cluster.sync_nodes()

        template = VirtualMachineTemplate(template_name="Template1",
                                          cluster=cluster)
        template.disks = [{'size': 500}]
        template.nics = [{'mode': 'bridged', 'link': ''}]
        template.save()

        instance = VirtualMachine(hostname='new.vm.hostname', cluster=cluster)
        instance.info = INSTANCE
        instance.disks = []
        instance.nics = []
        instance.save()

        # Users
        self.create_users([
            ('superuser', {'is_superuser': True}),
            'cluster_admin',
            'create_vm',
            'unauthorized',
        ])
        self.cluster_admin.grant('admin', cluster)
        self.create_vm.grant('create_vm', cluster)

        self.create_template_data = dict(
            cluster=cluster.pk,
            template_name='foo_bar',
            memory=512,
            disk_template='plain',
            disk_count=0,
            nic_count=0,
        )

        self.cluster = cluster
        self.template = template
        self.instance = instance
        self.c = Client()
Esempio n. 4
0
def template_to_instance(template, hostname, owner):
    """
    Instantiate a VM template with a given hostname and owner.
    """

    cluster = template.cluster
    beparams = {"vcpus": template.vcpus}
    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,
        "ip_check": template.ip_check,
        "name_check": template.name_check,
        "pnode": template.pnode,
        "beparams": beparams,
    }

    if template.snode:
        kwargs.update({"snode": template.snode})
    # secondary node isn't set, check if drdb is set (this shouldn't happen if
    # form validation is correct)
    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
Esempio n. 5
0
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 = {}
    info = cluster.info
    hv = 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 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'])):
        raise Http403(
            _('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, request.POST)
        if form.is_valid():
            data = form.cleaned_data
            start = data.get('start')
            no_install = data.get('no_install')
            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')
            disks = data.get('disks')
            disk_size = data.get('disk_size')
            nics = data.get('nics')
            memory = data.get('memory')
            # 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
            hv = data.get('hypervisor')
            hvparams = {}
            hvparam_fields = ()

            if hv == 'xen-pvm':
                hvparam_fields = ('kernel_path', 'root_path')
            elif hv == 'xen-hvm':
                hvparam_fields = (
                    'boot_order',
                    'disk_type',
                    'nic_type',
                    'cdrom_image_path',
                )
            elif hv == 'kvm':
                hvparam_fields = [
                    'kernel_path',
                    'root_path',
                    'serial_console',
                    'boot_order',
                    'disk_type',
                    'cdrom_image_path',
                    'nic_type',
                ]

                # Check before adding cdrom2; see #11655.
                if has_cdrom2(cluster):
                    hvparam_fields.append('cdrom2_image_path')

                # Force cdrom disk type to IDE; see #9297.
                hvparams['cdrom_disk_type'] = 'ide'

            for field in hvparam_fields:
                hvparams[field] = data[field]

            # 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

            try:
                job_id = cluster.rapi.CreateInstance('create', hostname,
                        disk_template,
                        disks,nics,
                        no_install=no_install,
                        start=start, os=os,
                        pnode=pnode, snode=snode,
                        name_check=name_check, ip_check=name_check,
                        iallocator=iallocator_hostname,
                        hypervisor=hv,
                        hvparams=hvparams,
                        beparams={"memory": memory, "vcpus":vcpus})
            except GanetiApiError, e:
                msg = '%s: %s' % (_('Error creating virtual machine on this cluster'),e)
                form._errors["cluster"] = form.error_class([msg])
            else:
                # 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

                # 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.  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, job)
                else:
                    grantee.grant('admin', vm)
                    log_action('CREATE', user, vm)

                return HttpResponseRedirect(
                reverse('instance-detail', args=[cluster.slug, vm.hostname]))

        cluster_defaults = {}
        if 'cluster' in request.POST and request.POST['cluster'] != '':
            try:
                cluster =  Cluster.objects.get(pk=request.POST['cluster'])
                if cluster.info:
                    cluster_defaults = cluster_default_info(cluster)
            except Cluster.DoesNotExist:
                pass
Esempio n. 7
0
def template_to_instance(template, hostname, owner):
    """
    Instantiate a VM template with a given hostname and owner.
    """

    cluster = template.cluster
    beparams = {
        "vcpus": template.vcpus,
    }
    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,
        "ip_check": template.ip_check,
        "name_check": template.name_check,
        "pnode": template.pnode,
        "beparams": beparams,
    }

    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
Esempio n. 8
0
def missing_db(request):
    """
    View for displaying VirtualMachines missing from the database
    """
    user = request.user
    if user.is_superuser:
        clusters = Cluster.objects.all()
    else:
        clusters = user.get_objects_any_perms(Cluster, ['admin'])
        if not clusters:
            raise Http403(NO_PRIVS)

    vms = []
    for cluster in clusters:
        for hostname in cluster.missing_in_db:
            vms.append(('%s:%s' % (cluster.id, hostname), hostname))

    if request.method == 'POST':
        # process updates if this was a form submission
        form = ImportForm(vms, request.POST)
        if form.is_valid():
            # update all selected VirtualMachines
            data = form.cleaned_data
            owner = data['owner']
            vm_ids = data['virtual_machines']

            import_ready = defaultdict(lambda:0)
            orphaned = defaultdict(lambda:0)

            # create missing VMs
            for vm in vm_ids:
                cluster_id, host = vm.split(':')
                cluster = Cluster.objects.get(id=cluster_id)
                VirtualMachine(hostname=host, cluster=cluster, owner=owner).save()
                import_ready[cluster.pk] -= 1
                if owner is None:
                    orphaned[cluster.pk] += 1


            # remove created vms from the list
            vms = filter(lambda x: unicode(x[0]) not in vm_ids, vms)

    else:
        form = ImportForm(vms)

    vms = {}
    for cluster in clusters:
        for hostname in cluster.missing_in_db:
            vms[hostname] = ('%s:%s' % (cluster.id, hostname), cluster.hostname, hostname)
    vmhostnames = vms.keys()
    vmhostnames.sort()

    vms_tuplelist = []
    for i in vmhostnames:
        vms_tuplelist.append(vms[i])

    vms = vms_tuplelist

    return render_to_response("ganeti/importing/missing_db.html", {
        'vms': vms,
        'form':form,
        },
        context_instance=RequestContext(request),
    )