Exemplo n.º 1
0
    def setUp(self):
        self.tearDown()

        self.cluster = Cluster(hostname='test.example.test', slug='OSL_TEST')
        self.cluster.save()
        self.vm = VirtualMachine(hostname='vm1.example.bak',
                                 cluster=self.cluster)
        self.vm.save()

        User(id=1, username='******').save()
        settings.ANONYMOUS_USER_ID = 1

        self.user = User(id=2, username='******')
        self.user.set_password('secret')
        self.user.save()
        self.user1 = User(id=3, username='******')
        self.user1.set_password('secret')
        self.user1.grant("admin", self.cluster)
        self.user1.grant("admin", self.vm)
        self.user1.save()
        self.user2 = User(id=4, username="******")
        self.user2.set_password("secret")
        self.user2.is_superuser = True
        self.user2.save()

        self.c = Client()
Exemplo n.º 2
0
    def setUp(self):
        self.tearDown()

        self.user = User(id=2, username='******')
        self.user.set_password('secret')
        self.user.save()

        self.group = Group(name='testing_group')
        self.group.save()

        self.cluster0 = Cluster(hostname='test0', slug='OSL_TEST0')
        self.cluster0.save()
        self.cluster1 = Cluster(hostname='test1', slug='OSL_TEST1')
        self.cluster1.save()

        self.vm0 = VirtualMachine(hostname='vm0', cluster=self.cluster0)
        self.vm1 = VirtualMachine(hostname='vm1', cluster=self.cluster0,
                                  owner=self.user.get_profile())
        # self.vm2 = VirtualMachine(hostname='vm2', cluster=cluster0)
        self.vm3 = VirtualMachine(hostname='vm3', cluster=self.cluster1)
        self.vm4 = VirtualMachine(hostname='vm4', cluster=self.cluster1,
                                  owner=self.user.get_profile())
        # self.vm5 = VirtualMachine(hostname='vm5', cluster=cluster1)
        self.vm0.save()
        self.vm1.save()
        self.vm3.save()
        self.vm4.save()

        self.c = Client()
        self.owner = self.user.get_profile()
Exemplo n.º 3
0
 def create_virtual_machine(self, cluster=None, hostname="vm1.example.bak"):
     if cluster is None:
         cluster = Cluster(hostname="test.example.bak", slug="OSL_TEST", username="******", password="******")
     cluster.save()
     cluster.sync_nodes()
     vm = VirtualMachine(cluster=cluster, hostname=hostname)
     vm.save()
     return vm, cluster
Exemplo n.º 4
0
 def create_virtual_machine(self, cluster=None, hostname='vm1.example.bak'):
     if cluster is None:
         cluster = Cluster(hostname='test.example.bak',
                           slug='OSL_TEST',
                           username='******',
                           password='******')
     cluster.save()
     cluster.sync_nodes()
     vm = VirtualMachine(cluster=cluster, hostname=hostname)
     vm.save()
     return vm, cluster
Exemplo n.º 5
0
    def setUp(self):
        self.tearDown()

        self.user = User(id=2, username='******')
        self.user.set_password('secret')
        self.user.save()

        self.group = Group(name='testing_group')
        self.group.save()

        self.cluster0 = Cluster(hostname='test0', slug='OSL_TEST0')
        self.cluster0.save()
        self.cluster1 = Cluster(hostname='test1', slug='OSL_TEST1')
        self.cluster1.save()

        self.vm0 = VirtualMachine(hostname='vm0', cluster=self.cluster0)
        self.vm1 = VirtualMachine(hostname='vm1',
                                  cluster=self.cluster0,
                                  owner=self.user.get_profile())
        # self.vm2 = VirtualMachine(hostname='vm2', cluster=cluster0)
        self.vm3 = VirtualMachine(hostname='vm3', cluster=self.cluster1)
        self.vm4 = VirtualMachine(hostname='vm4',
                                  cluster=self.cluster1,
                                  owner=self.user.get_profile())
        # self.vm5 = VirtualMachine(hostname='vm5', cluster=cluster1)
        self.vm0.save()
        self.vm1.save()
        self.vm3.save()
        self.vm4.save()

        self.c = Client()
        self.owner = self.user.get_profile()
Exemplo n.º 6
0
    def test_missing_in_ganeti(self):
        """
        Tests missing_in_ganeti property
        """
        cluster = Cluster(hostname='ganeti.example.test')
        cluster.save()
        vm_current = VirtualMachine(cluster=cluster,
                                    hostname='gimager2.example.bak')
        vm_removed = VirtualMachine(cluster=cluster,
                                    hostname='does.not.exist.org')
        vm_current.save()
        vm_removed.save()

        self.assertEqual([u'does.not.exist.org'], cluster.missing_in_ganeti)

        vm_current.delete()
        vm_removed.delete()
        cluster.delete()
Exemplo n.º 7
0
    def test_sync_virtual_machines(self):
        """
        Tests synchronizing cached virtuals machines (stored in db) with info
        the ganeti cluster is storing

        Verifies:
            * VMs no longer in ganeti are deleted
            * VMs missing from the database are added
        """
        cluster = Cluster(hostname='ganeti.example.test')
        cluster.save()
        vm_missing = 'gimager.example.bak'
        vm_current = VirtualMachine(cluster=cluster,
                                    hostname='gimager2.example.bak')
        vm_removed = VirtualMachine(cluster=cluster,
                                    hostname='does.not.exist.org')
        vm_current.save()
        vm_removed.save()

        cluster.sync_virtual_machines()
        self.assertTrue(VirtualMachine.objects.get(cluster=cluster,
                                                   hostname=vm_missing),
                        'missing vm was not created')
        self.assertTrue(
            VirtualMachine.objects.get(
                cluster=cluster,
                hostname=vm_current.hostname),
            'previously existing vm was not created')
        self.assertTrue(
            VirtualMachine.objects.filter(
                cluster=cluster,
                hostname=vm_removed.hostname),
            "vm not in ganeti was not removed from db")

        cluster.sync_virtual_machines(True)
        self.assertFalse(
            VirtualMachine.objects.filter(
                cluster=cluster,
                hostname=vm_removed.hostname),
            'vm not present in ganeti was not removed from db')

        vm_removed.delete()
        vm_current.delete()
        cluster.delete()
Exemplo n.º 8
0
    def test_sync_virtual_machines(self):
        """
        Tests synchronizing cached virtuals machines (stored in db) with info
        the ganeti cluster is storing

        Verifies:
            * VMs no longer in ganeti are deleted
            * VMs missing from the database are added
        """
        cluster = Cluster(hostname='ganeti.example.test')
        cluster.save()
        vm_missing = 'gimager.example.bak'
        vm_current = VirtualMachine(cluster=cluster,
                                    hostname='gimager2.example.bak')
        vm_removed = VirtualMachine(cluster=cluster,
                                    hostname='does.not.exist.org')
        vm_current.save()
        vm_removed.save()

        cluster.sync_virtual_machines()
        self.assertTrue(
            VirtualMachine.objects.get(cluster=cluster, hostname=vm_missing),
            'missing vm was not created')
        self.assertTrue(
            VirtualMachine.objects.get(cluster=cluster,
                                       hostname=vm_current.hostname),
            'previously existing vm was not created')
        self.assertTrue(
            VirtualMachine.objects.filter(cluster=cluster,
                                          hostname=vm_removed.hostname),
            "vm not in ganeti was not removed from db")

        cluster.sync_virtual_machines(True)
        self.assertFalse(
            VirtualMachine.objects.filter(cluster=cluster,
                                          hostname=vm_removed.hostname),
            'vm not present in ganeti was not removed from db')

        vm_removed.delete()
        vm_current.delete()
        cluster.delete()
Exemplo n.º 9
0
class ImportViews(TestCase):

    def setUp(self):
        self.tearDown()

        self.user = User(id=2, username='******')
        self.user.set_password('secret')
        self.user.save()

        self.group = Group(name='testing_group')
        self.group.save()

        self.cluster0 = Cluster(hostname='test0', slug='OSL_TEST0')
        self.cluster0.save()
        self.cluster1 = Cluster(hostname='test1', slug='OSL_TEST1')
        self.cluster1.save()

        self.vm0 = VirtualMachine(hostname='vm0', cluster=self.cluster0)
        self.vm1 = VirtualMachine(hostname='vm1', cluster=self.cluster0,
                                  owner=self.user.get_profile())
        # self.vm2 = VirtualMachine(hostname='vm2', cluster=cluster0)
        self.vm3 = VirtualMachine(hostname='vm3', cluster=self.cluster1)
        self.vm4 = VirtualMachine(hostname='vm4', cluster=self.cluster1,
                                  owner=self.user.get_profile())
        # self.vm5 = VirtualMachine(hostname='vm5', cluster=cluster1)
        self.vm0.save()
        self.vm1.save()
        self.vm3.save()
        self.vm4.save()

        self.c = Client()
        self.owner = self.user.get_profile()

    def tearDown(self):
        VirtualMachine.objects.all().delete()
        Cluster.objects.all().delete()
        Organization.objects.all().delete()
        Profile.objects.all().delete()
        User.objects.all().delete()
        Group.objects.all().delete()

    def test_orphans_view(self):
        """
        Test orphans view
        """
        url = '/import/orphans/'

        # anonymous user
        response = self.c.get(url, follow=True)
        self.assertEqual(200, response.status_code)
        self.assertTemplateUsed(response, 'registration/login.html')

        # unauthorized user
        self.assertTrue(self.c.login(username=self.user.username,
                                     password='******'))
        response = self.c.get(url)
        self.assertEqual(403, response.status_code)

        # authorized get (cluster admin perm)
        self.user.grant('admin', self.cluster0)
        response = self.c.get(url)
        self.assertEqual(200, response.status_code)
        self.assertEqual('text/html; charset=utf-8', response['content-type'])
        self.assertTemplateUsed(response, 'ganeti/importing/orphans.html')
        self.assertEqual([(self.vm0.id, 'test0', 'vm0')],
                         response.context['vms'])
        self.user.revoke_all(self.cluster0)

        # authorized get (superuser)
        self.user.is_superuser = True
        self.user.save()
        response = self.c.get(url)
        self.assertEqual(200, response.status_code)
        self.assertEqual('text/html; charset=utf-8', response['content-type'])
        self.assertTemplateUsed(response, 'ganeti/importing/orphans.html')
        self.assertEqual([(self.vm0.id, 'test0', 'vm0'),
                         (self.vm3.id, 'test1', 'vm3')],
                         response.context['vms'])
        self.user.is_superuser = False
        self.user.save()

        # POST - invalid vm
        self.user.grant('admin', self.cluster0)
        data = {'virtual_machines': [-1], 'owner': self.owner.id}
        response = self.c.post(url, data)
        self.assertEqual(200, response.status_code)
        self.assertEqual('text/html; charset=utf-8', response['content-type'])
        self.assertTemplateUsed(response, 'ganeti/importing/orphans.html')
        self.assertTrue(response.context['form'].errors)

        # POST - invalid owner
        data = {'virtual_machines': [self.vm0.id], 'owner': -1}
        response = self.c.post(url, data)
        self.assertEqual(200, response.status_code)
        self.assertEqual('text/html; charset=utf-8', response['content-type'])
        self.assertTemplateUsed(response, 'ganeti/importing/orphans.html')
        self.assertTrue(response.context['form'].errors)

        # POST - user does not have perms for cluster
        data = {'virtual_machines': [self.vm3.id], 'owner': self.owner.id}
        response = self.c.post(url, data)
        self.assertEqual(200, response.status_code)
        self.assertEqual('text/html; charset=utf-8', response['content-type'])
        self.assertTemplateUsed(response, 'ganeti/importing/orphans.html')
        self.assertTrue(response.context['form'].errors)

        # POST - success
        data = {'virtual_machines': [self.vm0.id], 'owner': self.owner.id}
        response = self.c.post(url, data)
        self.assertEqual(200, response.status_code)
        self.assertEqual('text/html; charset=utf-8', response['content-type'])
        self.assertTemplateUsed(response, 'ganeti/importing/orphans.html')
        self.assertFalse(response.context['form'].errors)
        self.assertEqual([], response.context['vms'])

    def test_missing_ganeti(self):
        """
        Tests view for Virtual Machines missing from ganeti
        """
        url = '/import/missing/'
        self.cluster0.rapi.GetInstances.response = ['vm0', 'vm2']
        self.cluster1.rapi.GetInstances.response = ['vm3', 'vm5']

        # anonymous user
        response = self.c.get(url, follow=True)
        self.assertEqual(200, response.status_code)
        self.assertTemplateUsed(response, 'registration/login.html')

        # unauthorized user
        self.assertTrue(self.c.login(username=self.user.username,
                                     password='******'))
        response = self.c.get(url)
        self.assertEqual(403, response.status_code)

        # authorized get (cluster admin perm)
        self.user.grant('admin', self.cluster0)
        response = self.c.get(url)
        self.assertEqual(200, response.status_code)
        self.assertEqual('text/html; charset=utf-8', response['content-type'])
        self.assertTemplateUsed(response, 'ganeti/importing/missing.html')
        self.assertEqual([('vm1', 'test0', 'vm1')], response.context['vms'])
        self.user.revoke_all(self.cluster0)

        # authorized get (superuser)
        self.user.is_superuser = True
        self.user.save()
        response = self.c.get(url)
        self.assertEqual(200, response.status_code)
        self.assertEqual('text/html; charset=utf-8', response['content-type'])
        self.assertTemplateUsed(response, 'ganeti/importing/missing.html')
        self.assertEqual([('vm1', 'test0', 'vm1'),
                         ('vm4', 'test1', 'vm4')],
                         response.context['vms'])
        self.user.is_superuser = False
        self.user.save()

        # POST - invalid vm
        self.user.grant('admin', self.cluster0)
        data = {'virtual_machines': [-1]}
        response = self.c.post(url, data)
        self.assertEqual(200, response.status_code)
        self.assertEqual('text/html; charset=utf-8', response['content-type'])
        self.assertTemplateUsed(response, 'ganeti/importing/missing.html')
        self.assertTrue(response.context['form'].errors)

        # POST - user does not have perms for cluster
        data = {'virtual_machines': [self.vm3.hostname]}
        response = self.c.post(url, data)
        self.assertEqual(200, response.status_code)
        self.assertEqual('text/html; charset=utf-8', response['content-type'])
        self.assertTemplateUsed(response, 'ganeti/importing/missing.html')
        self.assertTrue(response.context['form'].errors)

        # POST - success
        data = {'virtual_machines': ['vm1']}
        response = self.c.post(url, data)
        self.assertEqual(200, response.status_code)
        self.assertEqual('text/html; charset=utf-8', response['content-type'])
        self.assertTemplateUsed(response, 'ganeti/importing/missing.html')
        self.assertFalse(response.context['form'].errors)
        self.assertEqual([], response.context['vms'])

    def test_missing_db(self):
        """
        Tests view for Virtual Machines missing from database
        """
        url = '/import/missing_db/'
        self.cluster0.rapi.GetInstances.response = ['vm0', 'vm2']
        self.cluster1.rapi.GetInstances.response = ['vm3', 'vm5']

        # anonymous user
        response = self.c.get(url, follow=True)
        self.assertEqual(200, response.status_code)
        self.assertTemplateUsed(response, 'registration/login.html')

        # unauthorized user
        self.assertTrue(self.c.login(username=self.user.username,
                                     password='******'))
        response = self.c.get(url)
        self.assertEqual(403, response.status_code)

        # authorized get (cluster admin perm)
        self.user.grant('admin', self.cluster0)
        response = self.c.get(url)
        self.assertEqual(200, response.status_code)
        self.assertEqual('text/html; charset=utf-8', response['content-type'])
        self.assertTemplateUsed(response, 'ganeti/importing/missing_db.html')

        cid_vm_hostname = Template('$cid:$hostname')
        c_vm2 = cid_vm_hostname.substitute(
            cid=self.cluster0.id, hostname='vm2')
        self.assertEqual([(c_vm2, u'test0', u'vm2')],
                         response.context['vms'])
        self.user.revoke_all(self.cluster0)

        # authorized get (superuser)
        self.user.is_superuser = True
        self.user.save()
        response = self.c.get(url)
        self.assertEqual(200, response.status_code)
        self.assertEqual('text/html; charset=utf-8', response['content-type'])
        self.assertTemplateUsed(response, 'ganeti/importing/missing_db.html')
        c_vm5 = cid_vm_hostname.substitute(
            cid=self.cluster1.id, hostname='vm5')
        self.assertEqual([(c_vm2, u'test0', u'vm2'),
                          (c_vm5, u'test1', u'vm5')],
                         response.context['vms'])
        self.user.is_superuser = False
        self.user.save()

        # POST - invalid vm
        self.user.grant('admin', self.cluster0)
        data = {'virtual_machines': [-1]}
        response = self.c.post(url, data)
        self.assertEqual(200, response.status_code)
        self.assertEqual('text/html; charset=utf-8', response['content-type'])
        self.assertTemplateUsed(response, 'ganeti/importing/missing_db.html')
        self.assertTrue(response.context['form'].errors)

        # POST - invalid owner
        data = {'virtual_machines': [self.vm0.id], 'owner': -1}
        response = self.c.post(url, data)
        self.assertEqual(200, response.status_code)
        self.assertEqual('text/html; charset=utf-8', response['content-type'])
        self.assertTemplateUsed(response, 'ganeti/importing/missing_db.html')
        self.assertTrue(response.context['form'].errors)

        # POST - user does not have perms for cluster
        data = {'virtual_machines': [self.vm3.hostname],
                'owner': self.owner.id}
        response = self.c.post(url, data)
        self.assertEqual(200, response.status_code)
        self.assertEqual('text/html; charset=utf-8', response['content-type'])
        self.assertTemplateUsed(response, 'ganeti/importing/missing_db.html')
        self.assertTrue(response.context['form'].errors)

        # POST - success
        data = {'virtual_machines': [c_vm2], 'owner': self.owner.id}
        response = self.c.post(url, data)
        self.assertEqual(200, response.status_code)
        self.assertEqual('text/html; charset=utf-8', response['content-type'])
        self.assertTemplateUsed(response, 'ganeti/importing/missing_db.html')
        self.assertFalse(response.context['form'].errors)
        self.assertEqual([], response.context['vms'])
        self.assertTrue(VirtualMachine.objects.filter(hostname='vm2').exists())
Exemplo n.º 10
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 PermissionDenied(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] = (u'%s:%s' % (cluster.id, hostname),
                             unicode(cluster.hostname), unicode(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), )
Exemplo n.º 11
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 = {}
    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
Exemplo n.º 12
0
    def test_used_resources(self):
        """
        Tests retrieving dictionary of resources used by a cluster user
        """
        c1 = Cluster(hostname="testing1", slug="test1")
        c2 = Cluster(hostname="testing2", slug="test2")
        c3 = Cluster(hostname="testing3", slug="test3")
        user = User(username="******")
        quota = {"disk": 26, "ram": 6, "virtual_cpus": 14}

        for i in (c1, c2, c3, user):
            i.save()

        owner = user.get_profile()
        c1.set_quota(owner, quota)
        c3.set_quota(owner, quota)

        # test used_resources returns zeros for no values
        result = owner.used_resources(cluster=c1)
        self.assertEqual(0, result['ram'])
        self.assertEqual(0, result['disk'])
        self.assertEqual(0, result['virtual_cpus'])

        vm11 = VirtualMachine(hostname="1one",
                              owner=owner,
                              cluster=c1,
                              status="running")
        vm21 = VirtualMachine(hostname="2one",
                              owner=owner,
                              cluster=c2,
                              status="running")
        vm31 = VirtualMachine(hostname="3one",
                              owner=owner,
                              cluster=c2,
                              status="running")

        vm12 = VirtualMachine(hostname="1two",
                              owner=owner,
                              cluster=c1,
                              status="running",
                              ram=1,
                              virtual_cpus=3,
                              disk_size=6)
        vm22 = VirtualMachine(hostname="2two",
                              owner=owner,
                              cluster=c2,
                              status="running",
                              ram=1,
                              virtual_cpus=3,
                              disk_size=6)
        vm32 = VirtualMachine(hostname="3two",
                              owner=owner,
                              cluster=c3,
                              status="running",
                              ram=1,
                              virtual_cpus=3,
                              disk_size=6)

        vm13 = VirtualMachine(hostname="1three",
                              owner=owner,
                              cluster=c1,
                              status="stopped",
                              ram=1,
                              virtual_cpus=3,
                              disk_size=6)
        vm23 = VirtualMachine(hostname="2three",
                              owner=owner,
                              cluster=c2,
                              status="stopped",
                              ram=1,
                              virtual_cpus=3,
                              disk_size=6)
        vm33 = VirtualMachine(hostname="3three",
                              owner=owner,
                              cluster=c3,
                              status="stopped",
                              ram=1,
                              virtual_cpus=3,
                              disk_size=6)

        for i in (vm11, vm12, vm13, vm21, vm22, vm23, vm31, vm32, vm33):
            i.save()

        # multiple clusters - every VM
        result = owner.used_resources(cluster=None, only_running=False)
        self.assertTrue(c1.id in result.keys())
        self.assertTrue(c2.id in result.keys())
        self.assertTrue(c3.id in result.keys())
        self.assertEqual(result[c1.id]["disk"], 12)
        self.assertEqual(result[c1.id]["ram"], 2)
        self.assertEqual(result[c1.id]["virtual_cpus"], 6)
        self.assertEqual(result[c1.id], result[c3.id])

        # multiple clusters - only running VMs
        result = owner.used_resources(cluster=None, only_running=True)
        self.assertTrue(c1.id in result.keys())
        self.assertTrue(c2.id in result.keys())
        self.assertTrue(c3.id in result.keys())
        self.assertEqual(result[c1.id]["disk"], 12)
        self.assertEqual(result[c1.id]["ram"], 1)
        self.assertEqual(result[c1.id]["virtual_cpus"], 3)
        self.assertEqual(result[c1.id], result[c3.id])

        # single cluster - every VM
        result = owner.used_resources(cluster=c1, only_running=False)
        self.assertEqual(result["disk"], 12)
        self.assertEqual(result["ram"], 2)
        self.assertEqual(result["virtual_cpus"], 6)

        # single cluster - only running VMs
        result = owner.used_resources(cluster=c1, only_running=True)
        self.assertEqual(result["disk"], 12)
        self.assertEqual(result["ram"], 1)
        self.assertEqual(result["virtual_cpus"], 3)
Exemplo n.º 13
0
    def test_missing_in_ganeti(self):
        """
        Tests missing_in_ganeti property
        """
        cluster = Cluster(hostname='ganeti.example.test')
        cluster.save()
        vm_current = VirtualMachine(cluster=cluster,
                                    hostname='gimager2.example.bak')
        vm_removed = VirtualMachine(cluster=cluster,
                                    hostname='does.not.exist.org')
        vm_current.save()
        vm_removed.save()

        self.assertEqual([u'does.not.exist.org'], cluster.missing_in_ganeti)

        vm_current.delete()
        vm_removed.delete()
        cluster.delete()
Exemplo n.º 14
0
    def test_view_overview(self):
        """
        Tests overview (status) page
        """
        # TODO: in future, add Ganeti errors checking

        cluster1 = Cluster(hostname='cluster1', slug='cluster1')
        cluster1.save()
        vm1 = VirtualMachine(hostname='vm2.example.bak', cluster=cluster1)
        vm1.save()
        job = Job(job_id=233, obj=self.vm, cluster=self.cluster,
                  finished="2011-01-07 21:59", status="error")
        job.save()
        job1 = Job(job_id=1234, obj=vm1, cluster=cluster1,
                   finished="2011-01-05 21:59", status="error")
        job1.save()
        job.rapi.GetJobStatus.response = JOB_ERROR

        url = "/"
        args = []
        template = "ganeti/overview.html"
        mimetype = "text/html; charset=utf-8"
        status = 200

        # anonymous user
        response = self.c.get(url % args, follow=True)
        self.assertEqual(200, response.status_code)
        self.assertTemplateUsed(response, 'registration/login.html')

        # authorized user (non-admin)
        self.user.grant("admin", self.vm)
        self.user.save()
        self.assertTrue(self.c.login(username=self.user.username,
                        password='******'))
        response = self.c.get(url % args)
        self.assertEqual(status, response.status_code)
        self.assertEqual(mimetype, response['content-type'])
        self.assertTemplateUsed(response, template)
        clusters = response.context['cluster_list']
        self.assertTrue(self.cluster not in clusters)
        self.assertEqual(0, len(clusters))
        self.assertEqual(0, response.context["orphaned"])
        self.assertEqual(0, response.context["missing"])
        self.assertEqual(0, response.context["import_ready"])

        # authorized user (admin on one cluster)
        self.assertTrue(self.c.login(username=self.user1.username,
                        password='******'))
        response = self.c.get(url % args)
        self.assertEqual(status, response.status_code)
        self.assertEqual(mimetype, response['content-type'])
        self.assertTemplateUsed(response, template)
        clusters = response.context['cluster_list']
        self.assertTrue(self.cluster in clusters)
        self.assertEqual(1, len(clusters))
        self.assertEqual(1, response.context["orphaned"])
        self.assertEqual(1, response.context["missing"])
        self.assertEqual(2, response.context["import_ready"])

        # authorized user (superuser)
        self.assertTrue(self.c.login(username=self.user2.username,
                        password='******'))
        response = self.c.get(url % args)
        self.assertEqual(status, response.status_code)
        self.assertEqual(mimetype, response['content-type'])
        self.assertTemplateUsed(response, template)
        clusters = response.context['cluster_list']
        self.assertTrue(self.cluster in clusters)
        self.assertTrue(cluster1 in clusters)
        self.assertEqual(2, len(clusters))
        self.assertEqual(2, response.context["orphaned"])
        self.assertEqual(2, response.context["missing"])
        self.assertEqual(4, response.context["import_ready"])
Exemplo n.º 15
0
class ImportViews(TestCase):
    def setUp(self):
        self.tearDown()

        self.user = User(id=2, username='******')
        self.user.set_password('secret')
        self.user.save()

        self.group = Group(name='testing_group')
        self.group.save()

        self.cluster0 = Cluster(hostname='test0', slug='OSL_TEST0')
        self.cluster0.save()
        self.cluster1 = Cluster(hostname='test1', slug='OSL_TEST1')
        self.cluster1.save()

        self.vm0 = VirtualMachine(hostname='vm0', cluster=self.cluster0)
        self.vm1 = VirtualMachine(hostname='vm1',
                                  cluster=self.cluster0,
                                  owner=self.user.get_profile())
        # self.vm2 = VirtualMachine(hostname='vm2', cluster=cluster0)
        self.vm3 = VirtualMachine(hostname='vm3', cluster=self.cluster1)
        self.vm4 = VirtualMachine(hostname='vm4',
                                  cluster=self.cluster1,
                                  owner=self.user.get_profile())
        # self.vm5 = VirtualMachine(hostname='vm5', cluster=cluster1)
        self.vm0.save()
        self.vm1.save()
        self.vm3.save()
        self.vm4.save()

        self.c = Client()
        self.owner = self.user.get_profile()

    def tearDown(self):
        VirtualMachine.objects.all().delete()
        Cluster.objects.all().delete()
        Organization.objects.all().delete()
        Profile.objects.all().delete()
        User.objects.all().delete()
        Group.objects.all().delete()

    def test_orphans_view(self):
        """
        Test orphans view
        """
        url = '/import/orphans/'

        # anonymous user
        response = self.c.get(url, follow=True)
        self.assertEqual(200, response.status_code)
        self.assertTemplateUsed(response, 'registration/login.html')

        # unauthorized user
        self.assertTrue(
            self.c.login(username=self.user.username, password='******'))
        response = self.c.get(url)
        self.assertEqual(403, response.status_code)

        # authorized get (cluster admin perm)
        self.user.grant('admin', self.cluster0)
        response = self.c.get(url)
        self.assertEqual(200, response.status_code)
        self.assertEqual('text/html; charset=utf-8', response['content-type'])
        self.assertTemplateUsed(response, 'ganeti/importing/orphans.html')
        self.assertEqual([(self.vm0.id, 'test0', 'vm0')],
                         response.context['vms'])
        self.user.revoke_all(self.cluster0)

        # authorized get (superuser)
        self.user.is_superuser = True
        self.user.save()
        response = self.c.get(url)
        self.assertEqual(200, response.status_code)
        self.assertEqual('text/html; charset=utf-8', response['content-type'])
        self.assertTemplateUsed(response, 'ganeti/importing/orphans.html')
        self.assertEqual([(self.vm0.id, 'test0', 'vm0'),
                          (self.vm3.id, 'test1', 'vm3')],
                         response.context['vms'])
        self.user.is_superuser = False
        self.user.save()

        # POST - invalid vm
        self.user.grant('admin', self.cluster0)
        data = {'virtual_machines': [-1], 'owner': self.owner.id}
        response = self.c.post(url, data)
        self.assertEqual(200, response.status_code)
        self.assertEqual('text/html; charset=utf-8', response['content-type'])
        self.assertTemplateUsed(response, 'ganeti/importing/orphans.html')
        self.assertTrue(response.context['form'].errors)

        # POST - invalid owner
        data = {'virtual_machines': [self.vm0.id], 'owner': -1}
        response = self.c.post(url, data)
        self.assertEqual(200, response.status_code)
        self.assertEqual('text/html; charset=utf-8', response['content-type'])
        self.assertTemplateUsed(response, 'ganeti/importing/orphans.html')
        self.assertTrue(response.context['form'].errors)

        # POST - user does not have perms for cluster
        data = {'virtual_machines': [self.vm3.id], 'owner': self.owner.id}
        response = self.c.post(url, data)
        self.assertEqual(200, response.status_code)
        self.assertEqual('text/html; charset=utf-8', response['content-type'])
        self.assertTemplateUsed(response, 'ganeti/importing/orphans.html')
        self.assertTrue(response.context['form'].errors)

        # POST - success
        data = {'virtual_machines': [self.vm0.id], 'owner': self.owner.id}
        response = self.c.post(url, data)
        self.assertEqual(200, response.status_code)
        self.assertEqual('text/html; charset=utf-8', response['content-type'])
        self.assertTemplateUsed(response, 'ganeti/importing/orphans.html')
        self.assertFalse(response.context['form'].errors)
        self.assertEqual([], response.context['vms'])

    def test_missing_ganeti(self):
        """
        Tests view for Virtual Machines missing from ganeti
        """
        url = '/import/missing/'
        self.cluster0.rapi.GetInstances.response = ['vm0', 'vm2']
        self.cluster1.rapi.GetInstances.response = ['vm3', 'vm5']

        # anonymous user
        response = self.c.get(url, follow=True)
        self.assertEqual(200, response.status_code)
        self.assertTemplateUsed(response, 'registration/login.html')

        # unauthorized user
        self.assertTrue(
            self.c.login(username=self.user.username, password='******'))
        response = self.c.get(url)
        self.assertEqual(403, response.status_code)

        # authorized get (cluster admin perm)
        self.user.grant('admin', self.cluster0)
        response = self.c.get(url)
        self.assertEqual(200, response.status_code)
        self.assertEqual('text/html; charset=utf-8', response['content-type'])
        self.assertTemplateUsed(response, 'ganeti/importing/missing.html')
        self.assertEqual([('vm1', 'test0', 'vm1')], response.context['vms'])
        self.user.revoke_all(self.cluster0)

        # authorized get (superuser)
        self.user.is_superuser = True
        self.user.save()
        response = self.c.get(url)
        self.assertEqual(200, response.status_code)
        self.assertEqual('text/html; charset=utf-8', response['content-type'])
        self.assertTemplateUsed(response, 'ganeti/importing/missing.html')
        self.assertEqual([('vm1', 'test0', 'vm1'), ('vm4', 'test1', 'vm4')],
                         response.context['vms'])
        self.user.is_superuser = False
        self.user.save()

        # POST - invalid vm
        self.user.grant('admin', self.cluster0)
        data = {'virtual_machines': [-1]}
        response = self.c.post(url, data)
        self.assertEqual(200, response.status_code)
        self.assertEqual('text/html; charset=utf-8', response['content-type'])
        self.assertTemplateUsed(response, 'ganeti/importing/missing.html')
        self.assertTrue(response.context['form'].errors)

        # POST - user does not have perms for cluster
        data = {'virtual_machines': [self.vm3.hostname]}
        response = self.c.post(url, data)
        self.assertEqual(200, response.status_code)
        self.assertEqual('text/html; charset=utf-8', response['content-type'])
        self.assertTemplateUsed(response, 'ganeti/importing/missing.html')
        self.assertTrue(response.context['form'].errors)

        # POST - success
        data = {'virtual_machines': ['vm1']}
        response = self.c.post(url, data)
        self.assertEqual(200, response.status_code)
        self.assertEqual('text/html; charset=utf-8', response['content-type'])
        self.assertTemplateUsed(response, 'ganeti/importing/missing.html')
        self.assertFalse(response.context['form'].errors)
        self.assertEqual([], response.context['vms'])

    def test_missing_db(self):
        """
        Tests view for Virtual Machines missing from database
        """
        url = '/import/missing_db/'
        self.cluster0.rapi.GetInstances.response = ['vm0', 'vm2']
        self.cluster1.rapi.GetInstances.response = ['vm3', 'vm5']

        # anonymous user
        response = self.c.get(url, follow=True)
        self.assertEqual(200, response.status_code)
        self.assertTemplateUsed(response, 'registration/login.html')

        # unauthorized user
        self.assertTrue(
            self.c.login(username=self.user.username, password='******'))
        response = self.c.get(url)
        self.assertEqual(403, response.status_code)

        # authorized get (cluster admin perm)
        self.user.grant('admin', self.cluster0)
        response = self.c.get(url)
        self.assertEqual(200, response.status_code)
        self.assertEqual('text/html; charset=utf-8', response['content-type'])
        self.assertTemplateUsed(response, 'ganeti/importing/missing_db.html')

        cid_vm_hostname = Template('$cid:$hostname')
        c_vm2 = cid_vm_hostname.substitute(cid=self.cluster0.id,
                                           hostname='vm2')
        self.assertEqual([(c_vm2, u'test0', u'vm2')], response.context['vms'])
        self.user.revoke_all(self.cluster0)

        # authorized get (superuser)
        self.user.is_superuser = True
        self.user.save()
        response = self.c.get(url)
        self.assertEqual(200, response.status_code)
        self.assertEqual('text/html; charset=utf-8', response['content-type'])
        self.assertTemplateUsed(response, 'ganeti/importing/missing_db.html')
        c_vm5 = cid_vm_hostname.substitute(cid=self.cluster1.id,
                                           hostname='vm5')
        self.assertEqual([(c_vm2, u'test0', u'vm2'),
                          (c_vm5, u'test1', u'vm5')], response.context['vms'])
        self.user.is_superuser = False
        self.user.save()

        # POST - invalid vm
        self.user.grant('admin', self.cluster0)
        data = {'virtual_machines': [-1]}
        response = self.c.post(url, data)
        self.assertEqual(200, response.status_code)
        self.assertEqual('text/html; charset=utf-8', response['content-type'])
        self.assertTemplateUsed(response, 'ganeti/importing/missing_db.html')
        self.assertTrue(response.context['form'].errors)

        # POST - invalid owner
        data = {'virtual_machines': [self.vm0.id], 'owner': -1}
        response = self.c.post(url, data)
        self.assertEqual(200, response.status_code)
        self.assertEqual('text/html; charset=utf-8', response['content-type'])
        self.assertTemplateUsed(response, 'ganeti/importing/missing_db.html')
        self.assertTrue(response.context['form'].errors)

        # POST - user does not have perms for cluster
        data = {
            'virtual_machines': [self.vm3.hostname],
            'owner': self.owner.id
        }
        response = self.c.post(url, data)
        self.assertEqual(200, response.status_code)
        self.assertEqual('text/html; charset=utf-8', response['content-type'])
        self.assertTemplateUsed(response, 'ganeti/importing/missing_db.html')
        self.assertTrue(response.context['form'].errors)

        # POST - success
        data = {'virtual_machines': [c_vm2], 'owner': self.owner.id}
        response = self.c.post(url, data)
        self.assertEqual(200, response.status_code)
        self.assertEqual('text/html; charset=utf-8', response['content-type'])
        self.assertTemplateUsed(response, 'ganeti/importing/missing_db.html')
        self.assertFalse(response.context['form'].errors)
        self.assertEqual([], response.context['vms'])
        self.assertTrue(VirtualMachine.objects.filter(hostname='vm2').exists())
Exemplo n.º 16
0
class TestGeneralViews(TestCase, ViewTestMixin):

    def setUp(self):
        self.tearDown()

        self.cluster = Cluster(hostname='test.example.test', slug='OSL_TEST')
        self.cluster.save()
        self.vm = VirtualMachine(hostname='vm1.example.bak',
                                 cluster=self.cluster)
        self.vm.save()

        User(id=1, username='******').save()
        settings.ANONYMOUS_USER_ID = 1

        self.user = User(id=2, username='******')
        self.user.set_password('secret')
        self.user.save()
        self.user1 = User(id=3, username='******')
        self.user1.set_password('secret')
        self.user1.grant("admin", self.cluster)
        self.user1.grant("admin", self.vm)
        self.user1.save()
        self.user2 = User(id=4, username="******")
        self.user2.set_password("secret")
        self.user2.is_superuser = True
        self.user2.save()

        self.c = Client()

    def tearDown(self):
        SSHKey.objects.all().delete()
        Cluster.objects.all().delete()
        User.objects.all().delete()
        Group.objects.all().delete()
        Job.objects.all().delete()

    def test_view_overview(self):
        """
        Tests overview (status) page
        """
        # TODO: in future, add Ganeti errors checking

        cluster1 = Cluster(hostname='cluster1', slug='cluster1')
        cluster1.save()
        vm1 = VirtualMachine(hostname='vm2.example.bak', cluster=cluster1)
        vm1.save()
        job = Job(job_id=233, obj=self.vm, cluster=self.cluster,
                  finished="2011-01-07 21:59", status="error")
        job.save()
        job1 = Job(job_id=1234, obj=vm1, cluster=cluster1,
                   finished="2011-01-05 21:59", status="error")
        job1.save()
        job.rapi.GetJobStatus.response = JOB_ERROR

        url = "/"
        args = []
        template = "ganeti/overview.html"
        mimetype = "text/html; charset=utf-8"
        status = 200

        # anonymous user
        response = self.c.get(url % args, follow=True)
        self.assertEqual(200, response.status_code)
        self.assertTemplateUsed(response, 'registration/login.html')

        # authorized user (non-admin)
        self.user.grant("admin", self.vm)
        self.user.save()
        self.assertTrue(self.c.login(username=self.user.username,
                        password='******'))
        response = self.c.get(url % args)
        self.assertEqual(status, response.status_code)
        self.assertEqual(mimetype, response['content-type'])
        self.assertTemplateUsed(response, template)
        clusters = response.context['cluster_list']
        self.assertTrue(self.cluster not in clusters)
        self.assertEqual(0, len(clusters))
        self.assertEqual(0, response.context["orphaned"])
        self.assertEqual(0, response.context["missing"])
        self.assertEqual(0, response.context["import_ready"])

        # authorized user (admin on one cluster)
        self.assertTrue(self.c.login(username=self.user1.username,
                        password='******'))
        response = self.c.get(url % args)
        self.assertEqual(status, response.status_code)
        self.assertEqual(mimetype, response['content-type'])
        self.assertTemplateUsed(response, template)
        clusters = response.context['cluster_list']
        self.assertTrue(self.cluster in clusters)
        self.assertEqual(1, len(clusters))
        self.assertEqual(1, response.context["orphaned"])
        self.assertEqual(1, response.context["missing"])
        self.assertEqual(2, response.context["import_ready"])

        # authorized user (superuser)
        self.assertTrue(self.c.login(username=self.user2.username,
                        password='******'))
        response = self.c.get(url % args)
        self.assertEqual(status, response.status_code)
        self.assertEqual(mimetype, response['content-type'])
        self.assertTemplateUsed(response, template)
        clusters = response.context['cluster_list']
        self.assertTrue(self.cluster in clusters)
        self.assertTrue(cluster1 in clusters)
        self.assertEqual(2, len(clusters))
        self.assertEqual(2, response.context["orphaned"])
        self.assertEqual(2, response.context["missing"])
        self.assertEqual(4, response.context["import_ready"])

    def test_used_resources(self):
        """ tests the used_resources view """

        group0 = Group.objects.create(name='group0')
        group1 = Group.objects.create(name='group1')
        self.user.groups.add(group0)
        self.user1.groups.add(group1)

        url = "/used_resources/"
        args = {}
        template = "ganeti/overview/used_resources_data.html"
        mimetype = "text/html; charset=utf-8"

        # anonymous user
        response = self.c.get(url, args, follow=True)
        self.assertEqual(200, response.status_code)
        self.assertTemplateUsed(response, 'registration/login.html')

        # 404 - no id
        self.assertTrue(self.c.login(username=self.user.username,
                        password='******'))
        response = self.c.get(url, {})
        self.assertEqual(404, response.status_code)

        # 404 - invalid id
        response = self.c.get(url, {'id': 1234567})
        self.assertEqual(404, response.status_code)

        # unauthorized user (different user)
        response = self.c.get(url, {'id': self.user2.get_profile().pk})
        self.assertEqual(403, response.status_code)

        # unauthorized user (in different group)
        self.assertTrue(self.c.login(username=self.user.username,
                        password='******'))
        response = self.c.get(url, {'id': group1.organization.pk})
        self.assertEqual(403, response.status_code)

        # authorized user (same user)
        response = self.c.get(url, {'id': self.user.get_profile().pk})
        self.assertEqual(200, response.status_code)
        self.assertEqual(mimetype, response['content-type'])
        self.assertTemplateUsed(response, template)

        # authorized user (in group)
        response = self.c.get(url, {'id': group0.organization.pk})
        self.assertEqual(200, response.status_code)
        self.assertEqual(mimetype, response['content-type'])
        self.assertTemplateUsed(response, template)

        # authorized user (superuser)
        self.assertTrue(self.c.login(username=self.user2.username,
                        password='******'))
        response = self.c.get(url, {'id': self.user.get_profile().pk})
        self.assertEqual(200, response.status_code)
        self.assertEqual(mimetype, response['content-type'])
        self.assertTemplateUsed(response, template)

        # authorized user (superuser)
        self.assertTrue(self.c.login(username=self.user2.username,
                        password='******'))
        response = self.c.get(url, {'id': group1.organization.pk})
        self.assertEqual(200, response.status_code)
        self.assertEqual(mimetype, response['content-type'])
        self.assertTemplateUsed(response, template)

    def test_view_ssh_keys(self):
        """ tests retrieving all sshkeys from the gwm instance """

        # add some keys
        SSHKey.objects.create(key="ssh-rsa test test@test", user=self.user)
        SSHKey.objects.create(key="ssh-dsa test asd@asd", user=self.user)
        SSHKey.objects.create(key="ssh-dsa test foo@bar", user=self.user1)

        self.user.revoke_all(self.vm)
        self.user.revoke_all(self.cluster)
        self.user1.revoke_all(self.vm)
        self.user1.revoke_all(self.cluster)
        self.user2.revoke_all(self.vm)
        self.user2.revoke_all(self.cluster)

        # get API key
        # import settings
        key = settings.WEB_MGR_API_KEY

        url = '/keys/%s/'
        args = (key,)

        # cluster without users who have admin perms
        response = self.c.get(url % args)
        self.assertEqual(200, response.status_code)
        self.assertEquals("application/json", response["content-type"])
        self.assertEqual(len(json.loads(response.content)), 0)
        self.assertNotContains(response, "test@test")
        self.assertNotContains(response, "asd@asd")

        # vm with users who have admin perms
        # grant admin permission to first user
        self.user.grant("admin", self.vm)
        self.user1.grant("admin", self.cluster)

        response = self.c.get(url % args)
        self.assertEqual(200, response.status_code)
        self.assertEquals("application/json", response["content-type"])
        self.assertEqual(len(json.loads(response.content)), 3)
        self.assertContains(response, "test@test", count=1)
        self.assertContains(response, "asd@asd", count=1)
        self.assertContains(response, "foo@bar", count=1)
Exemplo n.º 17
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 = {}
    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