def setUp(cls):
        # Create two unique labs
        lab1 = data_setup.create_labcontroller(fqdn=u'lab_%d' %
                                               int(time.time() * 1000))
        lab2 = data_setup.create_labcontroller(fqdn=u'lab_%d' %
                                               int(time.time() * 1000))

        # Create two distros and only put one in each lab.
        cls.distro_tree1 = data_setup.create_distro_tree()
        cls.distro_tree2 = data_setup.create_distro_tree()
        session.flush()
        cls.distro_tree1.lab_controller_assocs = [
            LabControllerDistroTree(lab_controller=lab2,
                                    url=u'http://notimportant')
        ]
        cls.distro_tree2.lab_controller_assocs = [
            LabControllerDistroTree(lab_controller=lab1,
                                    url=u'http://notimportant')
        ]

        # Create a user
        user = data_setup.create_user()

        # Create two systems but only put them in lab1.
        system1 = data_setup.create_system(owner=user)
        system2 = data_setup.create_system(owner=user)
        system1.lab_controller = lab1
        system2.lab_controller = lab1

        session.flush()

        # Create two jobs, one requiring distro_tree1 and one requiring distro_tree2
        job = '''
            <job>
                <whiteboard>%s</whiteboard>
                <recipeSet>
                    <recipe>
                        <distroRequires>
                            <distro_name op="=" value="%s" />
                        </distroRequires>
                        <hostRequires/>
                        <task name="/distribution/install" role="STANDALONE">
                            <params/>
                        </task>
                    </recipe>
                </recipeSet>
            </job>
                 '''
        xmljob1 = XmlJob(
            xmltramp.parse(
                job %
                (cls.distro_tree1.distro.name, cls.distro_tree1.distro.name)))
        xmljob2 = XmlJob(
            xmltramp.parse(
                job %
                (cls.distro_tree2.distro.name, cls.distro_tree2.distro.name)))

        cls.job1 = Jobs().process_xmljob(xmljob1, user)
        cls.job2 = Jobs().process_xmljob(xmljob2, user)
 def test_ack_jobxml(self):
     _response_type = u'ack'
     with session.begin():
         rs = self.job.recipesets[0]
         rs.nacked = RecipeSetResponse(type=_response_type)
     jobxml = XmlJob(xmltramp.parse(self.job.to_xml(clone=False).toprettyxml()))
     for xmlrecipeSet in jobxml.iter_recipeSets():
         response = xmlrecipeSet.get_xml_attr('response',unicode,None)
         self.assertEqual(response,_response_type)
Exemple #3
0
 def test_ack_jobxml(self):
     _response_type = u'ack'
     with session.begin():
         rs = self.job.recipesets[0]
         rs.nacked = RecipeSetResponse(type=_response_type)
     jobxml = XmlJob(
         xmltramp.parse(self.job.to_xml(clone=False).toprettyxml()))
     for xmlrecipeSet in jobxml.iter_recipeSets():
         response = xmlrecipeSet.get_xml_attr('response', unicode, None)
         self.assertEqual(response, _response_type)
 def test_ack_jobxml_clone(self):
     """
     Unline test_ack_jobxml, we do _not_ want to see our response in here
     """
     _response_type = u'ack'
     with session.begin():
         rs = self.job.recipesets[0]
         rs.nacked = RecipeSetResponse(type=_response_type)
     jobxml = XmlJob(xmltramp.parse(self.job.to_xml(clone=True).toprettyxml()))
     for xmlrecipeSet in jobxml.iter_recipeSets():
         response = xmlrecipeSet.get_xml_attr('response',unicode,None)
         self.assertEqual(response,None)
Exemple #5
0
 def test_ack_jobxml_clone(self):
     """
     Unline test_ack_jobxml, we do _not_ want to see our response in here
     """
     _response_type = u'ack'
     with session.begin():
         rs = self.job.recipesets[0]
         rs.nacked = RecipeSetResponse(type=_response_type)
     jobxml = XmlJob(
         xmltramp.parse(self.job.to_xml(clone=True).toprettyxml()))
     for xmlrecipeSet in jobxml.iter_recipeSets():
         response = xmlrecipeSet.get_xml_attr('response', unicode, None)
         self.assertEqual(response, None)
Exemple #6
0
 def test_uploading_job_with_invalid_hostRequires_raises_exception(self):
     session.begin()
     try:
         xmljob = XmlJob(
             xmltramp.parse('''
             <job>
                 <whiteboard>job with invalid hostRequires</whiteboard>
                 <recipeSet>
                     <recipe>
                         <distroRequires>
                             <distro_name op="=" value="BlueShoeLinux5-5" />
                         </distroRequires>
                         <hostRequires>
                             <memory op=">=" value="500MB" />
                         </hostRequires>
                         <task name="/distribution/install" role="STANDALONE">
                             <params/>
                         </task>
                     </recipe>
                 </recipeSet>
             </job>
             '''))
         self.assertRaises(
             BX, lambda: self.controller.process_xmljob(xmljob, self.user))
     finally:
         session.rollback()
Exemple #7
0
    def test_update_status_can_be_roundtripped_40214(self):
        complete_job_xml = pkg_resources.resource_string(
            'bkr.inttest', 'job_40214.xml')
        xmljob = XmlJob(xmltramp.parse(complete_job_xml))

        data_setup.create_tasks(xmljob)
        session.flush()

        # Import the job xml
        job = self.controller.process_xmljob(xmljob, self.user)
        session.flush()

        # Mark job waiting
        data_setup.mark_job_waiting(job)
        session.flush()

        # watchdog's should exist
        self.assertNotEqual(len(watchdogs_for_job(job)), 0)

        # Play back the original jobs results and status
        data_setup.playback_job_results(job, xmljob)
        session.flush()

        # Verify that the original status and results match
        self.assertEquals(TaskStatus.from_string(xmljob.wrappedEl('status')),
                          job.status)
        self.assertEquals(TaskResult.from_string(xmljob.wrappedEl('result')),
                          job.result)
        for i, recipeset in enumerate(xmljob.iter_recipeSets()):
            for j, recipe in enumerate(recipeset.iter_recipes()):
                self.assertEquals(
                    TaskStatus.from_string(recipe.wrappedEl('status')),
                    job.recipesets[i].recipes[j].status)
                self.assertEquals(
                    TaskResult.from_string(recipe.wrappedEl('result')),
                    job.recipesets[i].recipes[j].result)
                for k, task in enumerate(recipe.iter_tasks()):
                    self.assertEquals(
                        TaskStatus.from_string(task.status),
                        job.recipesets[i].recipes[j].tasks[k].status)
                    self.assertEquals(
                        TaskResult.from_string(task.result),
                        job.recipesets[i].recipes[j].tasks[k].result)

        # No watchdog's should exist when the job is complete
        self.assertEquals(len(watchdogs_for_job(job)), 0)
Exemple #8
0
 def test_uploading_job_without_recipeset_raises_exception(self):
     xmljob = XmlJob(
         xmltramp.parse('''
         <job>
             <whiteboard>job with norecipesets</whiteboard>
         </job>
         '''))
     with session.begin():
         self.assertRaises(
             BX, lambda: self.controller.process_xmljob(xmljob, self.user))
Exemple #9
0
 def test_job_xml_can_be_roundtripped(self):
     # Ideally the logic for parsing job XML into a Job instance would live in model code,
     # so that this test doesn't have to go through the web layer...
     complete_job_xml = pkg_resources.resource_string(
         'bkr.inttest', 'complete-job.xml')
     xmljob = XmlJob(xmltramp.parse(complete_job_xml))
     with session.begin():
         job = testutil.call(self.controller.process_xmljob, xmljob,
                             self.user)
     roundtripped_xml = job.to_xml(clone=True).toprettyxml(indent='    ')
     self.assertMultiLineEqual(roundtripped_xml, complete_job_xml)
    def test_update_status_can_be_roundtripped_40214(self):
        complete_job_xml = pkg_resources.resource_string('bkr.inttest', 'job_40214.xml')
        xmljob = XmlJob(xmltramp.parse(complete_job_xml))

        data_setup.create_tasks(xmljob)
        session.flush()
        
        # Import the job xml
        job = self.controller.process_xmljob(xmljob, self.user)
        session.flush()

        # Mark job waiting
        data_setup.mark_job_waiting(job)
        session.flush()

        # watchdog's should exist 
        self.assertNotEqual(len(watchdogs_for_job(job)), 0)

        # Play back the original jobs results and status
        data_setup.playback_job_results(job, xmljob)
        session.flush()
        
        # Verify that the original status and results match
        self.assertEquals(TaskStatus.from_string(xmljob.wrappedEl('status')), job.status)
        self.assertEquals(TaskResult.from_string(xmljob.wrappedEl('result')), job.result)
        for i, recipeset in enumerate(xmljob.iter_recipeSets()):
            for j, recipe in enumerate(recipeset.iter_recipes()):
                self.assertEquals(TaskStatus.from_string(recipe.wrappedEl('status')),
                        job.recipesets[i].recipes[j].status)
                self.assertEquals(TaskResult.from_string(recipe.wrappedEl('result')),
                        job.recipesets[i].recipes[j].result)
                for k, task in enumerate(recipe.iter_tasks()):
                    self.assertEquals(TaskStatus.from_string(task.status),
                            job.recipesets[i].recipes[j].tasks[k].status)
                    self.assertEquals(TaskResult.from_string(task.result),
                            job.recipesets[i].recipes[j].tasks[k].result)

        # No watchdog's should exist when the job is complete
        self.assertEquals(len(watchdogs_for_job(job)), 0)
Exemple #11
0
    def upload(self, jobxml, ignore_missing_tasks=False):
        """
        Queues a new job.

        :param jobxml: XML description of job to be queued
        :type jobxml: string
        :param ignore_missing_tasks: pass True for this parameter to cause 
            unknown tasks to be silently discarded (default is False)
        :type ignore_missing_tasks: bool
        """
        # xml.sax (and thus, xmltramp) expect raw bytes, not unicode
        if isinstance(jobxml, unicode):
            jobxml = jobxml.encode('utf8')
        xml = xmltramp_parse_untrusted(jobxml)
        xmljob = XmlJob(xml)
        job = self.process_xmljob(xmljob,
                                  identity.current.user,
                                  ignore_missing_tasks=ignore_missing_tasks)
        session.flush()  # so that we get an id
        return "J:%s" % job.id
Exemple #12
0
 def setUp(self):
     session.begin()
     from bkr.server.jobs import Jobs
     self.controller = Jobs()
     self.task = data_setup.create_task(name=u'/fake/task/here')
     distro_tree = data_setup.create_distro_tree()
     self.user = data_setup.create_user()
     self.xmljob = XmlJob(xmltramp.parse('''
         <job>
             <whiteboard>job with fake task</whiteboard>
             <recipeSet>
                 <recipe>
                     <distroRequires>
                         <distro_name op="=" value="%s" />
                     </distroRequires>
                     <hostRequires/>
                     <task name="%s" role="STANDALONE">
                         <params/>
                     </task>
                 </recipe>
             </recipeSet>
         </job>
         ''' % (distro_tree.distro.name, self.task.name)))
     session.flush()
Exemple #13
0
     try:
         # xml.sax (and thus, xmltramp) expect raw bytes, not unicode
         textxml = textxml.encode('utf8')
         if not confirmed:
             job_schema = lxml.etree.RelaxNG(self.job_schema_doc)
             if not job_schema.validate(lxml.etree.fromstring(textxml)):
                 log.debug('Job failed validation, with errors: %r',
                           job_schema.error_log)
                 return dict(
                     title=title,
                     form=self.job_form,
                     action='clone',
                     options={'xsd_errors': job_schema.error_log},
                     value=dict(textxml=textxml, confirmed=True),
                 )
         xmljob = XmlJob(xmltramp_parse_untrusted(textxml))
         job = self.process_xmljob(xmljob, identity.current.user)
         session.flush()
     except Exception, err:
         session.rollback()
         flash(_(u'Failed to import job because of: %s' % err))
         return dict(
             title=title,
             form=self.job_form,
             action='./clone',
             options={},
             value=dict(textxml="%s" % textxml, confirmed=confirmed),
         )
     else:
         self.success_redirect(job.id)
 return dict(
Exemple #14
0
     try:
         # xml.sax (and thus, xmltramp) expect raw bytes, not unicode
         textxml = textxml.encode('utf8')
         if not confirmed:
             job_schema = lxml.etree.RelaxNG(self.job_schema_doc)
             if not job_schema.validate(lxml.etree.fromstring(textxml)):
                 log.debug('Job failed validation, with errors: %r',
                         job_schema.error_log)
                 return dict(
                     title = title,
                     form = self.job_form,
                     action = 'clone',
                     options = {'xsd_errors': job_schema.error_log},
                     value = dict(textxml=textxml, confirmed=True),
                 )
         xmljob = XmlJob(xmltramp.parse(textxml))
         job = self.process_xmljob(xmljob,identity.current.user)
         session.flush()
     except Exception,err:
         session.rollback()
         flash(_(u'Failed to import job because of: %s' % err))
         return dict(
             title = title,
             form = self.job_form,
             action = './clone',
             options = {},
             value = dict(textxml = "%s" % textxml, confirmed=confirmed),
         )
     else:
         self.success_redirect(job.id)
 return dict(
Exemple #15
0
    def test_abort_recipe_bubbles_status_to_job(self):
        xmljob = XmlJob(
            xmltramp.parse('''
            <job>
                <whiteboard>job </whiteboard>
                <recipeSet>
                    <recipe>
                        <distroRequires>
                            <distro_name op="=" value="BlueShoeLinux5-5" />
                        </distroRequires>
                        <hostRequires/>
                        <task name="/distribution/install" role="STANDALONE">
                            <params/>
                        </task>
                    </recipe>
                </recipeSet>
                <recipeSet>
                    <recipe>
                        <distroRequires>
                            <distro_name op="=" value="BlueShoeLinux5-5" />
                        </distroRequires>
                        <hostRequires/>
                        <task name="/distribution/install" role="STANDALONE">
                            <params/>
                        </task>
                    </recipe>
                </recipeSet>
            </job>
            '''))
        job = self.controller.process_xmljob(xmljob, self.user)
        session.flush()
        for recipeset in job.recipesets:
            for recipe in recipeset.recipes:
                recipe.process()
                recipe.queue()
                recipe.schedule()
                recipe.waiting()

        # Abort the first recipe.
        job.recipesets[0].recipes[0].abort()
        job.update_status()

        # Verify that it and its children are aborted.
        self.assertEquals(job.recipesets[0].recipes[0].status,
                          TaskStatus.aborted)
        for task in job.recipesets[0].recipes[0].tasks:
            self.assertEquals(task.status, TaskStatus.aborted)

        # Verify that the second recipe and its children are still waiting.
        self.assertEquals(job.recipesets[1].recipes[0].status,
                          TaskStatus.waiting)
        for task in job.recipesets[1].recipes[0].tasks:
            self.assertEquals(task.status, TaskStatus.waiting)

        # Verify that the job still shows waiting.
        self.assertEquals(job.status, TaskStatus.waiting)

        # Abort the second recipe now.
        job.recipesets[1].recipes[0].abort()
        job.update_status()

        # Verify that the whole job shows aborted now.
        self.assertEquals(job.status, TaskStatus.aborted)