def check_job_status(self): # preventing circular import from ganeti_webmgr.jobs.models import Job if not self.last_job_id: return {} ct = ContentType.objects.get_for_model(self) qs = Job.objects.filter(content_type=ct, object_id=self.pk) jobs = qs.order_by("job_id") updates = {} status = 'unknown' op = None for job in jobs: try: data = self.rapi.GetJobStatus(job.job_id) if Job.valid_job(data): op = Job.parse_op(data) status = data['status'] except GanetiApiError: pass if status in ('success', 'error'): for k, v in Job.parse_persistent_info(data).items(): setattr(job, k, v) if status == 'unknown': job.status = "unknown" job.ignore_cache = False if status in ('success', 'error', 'unknown'): _updates = self._complete_job(self.cluster_id, self.hostname, op, status) # XXX if the delete flag is set in updates then delete this # model this happens here because _complete_job cannot delete # this model if _updates: if 'deleted' in _updates: # Delete ourselves. Also delete the job that caused us # to delete ourselves; see #8439 for "fun" details. # Order matters; the job's deletion cascades over us. # Revisit that when we finally nuke all this caching # bullshit. self.delete() job.delete() else: updates.update(_updates) # we only care about the very last job for resetting the cache flags if not jobs or status in ('success', 'error', 'unknown'): updates['ignore_cache'] = False updates['last_job'] = None return updates
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"])