def setUp(self): with session.begin(): self.owner = data_setup.create_user(password=u"owner") self.privileged = data_setup.create_user(password=u"privileged") self.system = data_setup.create_system( owner=self.owner, shared=True, lab_controller=data_setup.create_labcontroller() ) data_setup.configure_system_power(self.system) self.system.custom_access_policy.add_rule(permission=SystemPermission.control_system, user=self.privileged) self.unprivileged = data_setup.create_user(password=u"unprivileged") data_setup.create_running_job(system=self.system) self.browser = self.get_browser()
def setUp(self): with session.begin(): self.owner = data_setup.create_user(password=u'owner') self.privileged = data_setup.create_user(password=u'privileged') self.system = data_setup.create_system( owner=self.owner, shared=True, lab_controller=data_setup.create_labcontroller()) data_setup.configure_system_power(self.system) self.system.custom_access_policy.add_rule( permission=SystemPermission.control_system, user=self.privileged) self.unprivileged = data_setup.create_user( password=u'unprivileged') data_setup.create_running_job(system=self.system) self.browser = self.get_browser()
def test_reserved_openstack_instance(self): with session.begin(): owner = data_setup.create_user( email_address=u'*****@*****.**') distro_tree = data_setup.create_distro_tree( distro_name=u'MicrowaveOS', variant=u'ThreeHeats', arch=u'x86_64') job = data_setup.create_running_job( owner=owner, virt=True, instance_id=uuid.UUID('00000000-1111-2222-3333-444444444444'), distro_tree=distro_tree, whiteboard=u'Operation Righteous Cowboy Lightning', recipe_whiteboard=u'Everything Sunny All the Time Always') recipe = job.recipesets[0].recipes[0] data_setup.mark_recipe_installation_finished( recipe, fqdn=u'bitenuker.ge.invalid') with session.begin(): bkr.server.mail.reservesys_notify(recipe) self.assertEqual(len(self.mail_capture.captured_mails), 1) sender, rcpts, raw_msg = self.mail_capture.captured_mails[0] self.assertEqual(rcpts, [owner.email_address]) msg = email.message_from_string(raw_msg) self.assertEqual(msg['To'], owner.email_address) self.assertEqual(msg['Subject'], '[Beaker System Reserved] bitenuker.ge.invalid') self.assertEqual(msg['X-Beaker-Notification'], 'system-reservation') expected_mail_body = u"""\ ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** This System is reserved by [email protected] To return this system early, you can click on 'Release System' against this recipe from the Web UI. Ensure you have your logs off the system before returning to Beaker. %(base)srecipes/%(recipeid)s For system details, see: http://openstack.example.invalid/dashboard/project/instances/00000000-1111-2222-3333-444444444444/ For the default root password, see: %(base)sprefs Beaker Test information: HOSTNAME=bitenuker.ge.invalid JOBID=%(jobid)s RECIPEID=%(recipeid)s DISTRO=MicrowaveOS ThreeHeats x86_64 ARCHITECTURE=x86_64 Job Whiteboard: Operation Righteous Cowboy Lightning Recipe Whiteboard: Everything Sunny All the Time Always ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** **""" \ % dict(base=get_server_base(), recipeid=recipe.id, jobid=job.id) actual_mail_body = msg.get_payload(decode=True) self.assertMultiLineEqual(actual_mail_body, expected_mail_body)
def test_system_reserved_notification(self): with session.begin(): owner = data_setup.create_user( email_address=u'*****@*****.**') system = data_setup.create_system( fqdn=u'funcooker.ge.invalid', lab_controller=data_setup.create_labcontroller()) distro_tree = data_setup.create_distro_tree( distro_name=u'MicrowaveOS', variant=u'ThreeHeats', arch=u'x86_64') job = data_setup.create_running_job( owner=owner, system=system, distro_tree=distro_tree, whiteboard=u'Chain Reaction of Mental Anguish', recipe_whiteboard=u'Christmas Attack Zone') recipe = job.recipesets[0].recipes[0] with session.begin(): bkr.server.mail.reservesys_notify(job.recipesets[0].recipes[0]) self.assertEqual(len(self.mail_capture.captured_mails), 1) sender, rcpts, raw_msg = self.mail_capture.captured_mails[0] self.assertEqual(rcpts, [owner.email_address]) msg = email.message_from_string(raw_msg) self.assertEqual(msg['To'], owner.email_address) self.assertEqual(msg['Subject'], '[Beaker System Reserved] funcooker.ge.invalid') self.assertEqual(msg['X-Beaker-Notification'], 'system-reservation') expected_mail_body = u"""\ ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** This System is reserved by [email protected] To return this system early, you can click on 'Release System' against this recipe from the Web UI. Ensure you have your logs off the system before returning to Beaker. %(base)srecipes/%(recipeid)s For ssh, kvm, serial and power control operations please look here: %(base)sview/funcooker.ge.invalid For the default root password, see: %(base)sprefs Beaker Test information: HOSTNAME=funcooker.ge.invalid JOBID=%(jobid)s RECIPEID=%(recipeid)s DISTRO=MicrowaveOS ThreeHeats x86_64 ARCHITECTURE=x86_64 Job Whiteboard: Chain Reaction of Mental Anguish Recipe Whiteboard: Christmas Attack Zone ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** **""" \ % dict(base=get_server_base(), recipeid=recipe.id, jobid=job.id) actual_mail_body = msg.get_payload(decode=True) self.assertEqual(actual_mail_body, expected_mail_body)
def test_system_reserved_notification_on(self): with session.begin(): owner = data_setup.create_user( email_address=u'*****@*****.**') system = data_setup.create_system(fqdn=u'funcooker.ge.invalid', lab_controller=data_setup.create_labcontroller()) distro_tree = data_setup.create_distro_tree(distro_name=u'MicrowaveOS-20141016.0', variant=u'ThreeHeats', arch=u'x86_64') job = data_setup.create_running_job(owner=owner, system=system, distro_tree=distro_tree, whiteboard=u'Chain Reaction of Mental Anguish', recipe_whiteboard=u'Christmas Attack Zone') recipe = job.recipesets[0].recipes[0] mail_capture_thread.start_capturing() with session.begin(): bkr.server.mail.reservesys_notify(job.recipesets[0].recipes[0]) captured_mails = mail_capture_thread.stop_capturing() self.assertEqual(len(captured_mails), 1) sender, rcpts, raw_msg = captured_mails[0] self.assertEqual(rcpts, [owner.email_address]) msg = email.message_from_string(raw_msg) self.assertEqual(msg['To'], owner.email_address) self.assertEqual(msg['Subject'], '[Beaker System Reserved] funcooker.ge.invalid') self.assertEqual(msg['X-Beaker-Notification'], 'system-reservation') expected_mail_body = u"""\ ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** This System is reserved by [email protected] To return this system early, you can click on 'Release System' against this recipe from the Web UI. Ensure you have your logs off the system before returning to Beaker. %(base)srecipes/%(recipeid)s For ssh, kvm, serial and power control operations please look here: %(base)sview/funcooker.ge.invalid For the default root password, see: %(base)sprefs Beaker Test information: HOSTNAME=funcooker.ge.invalid JOBID=%(jobid)s RECIPEID=%(recipeid)s DISTRO=MicrowaveOS-20141016.0 ThreeHeats x86_64 ARCHITECTURE=x86_64 Job Whiteboard: Chain Reaction of Mental Anguish Recipe Whiteboard: Christmas Attack Zone ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** **""" \ % dict(base=get_server_base(), recipeid=recipe.id, jobid=job.id) actual_mail_body = msg.get_payload(decode=True) self.assertEqual(actual_mail_body, expected_mail_body)
def test_shows_currently_running_recipe(self): b = self.browser login(b) with session.begin(): job = data_setup.create_running_job() recipe = job.recipesets[0].recipes[0] self.go_to_system_view(recipe.resource.system) usage = b.find_element_by_class_name('system-quick-usage') usage.find_element_by_xpath('.//span[@class="label" and text()="Reserved"]') usage.find_element_by_xpath('.//a[text()="%s"]' % recipe.t_id)
def test_opening_running_recipe_does_not_mark_it_reviewed(self): with session.begin(): job = data_setup.create_running_job(owner=self.user) recipe = job.recipesets[0].recipes[0] self.assertEqual(recipe.get_reviewed_state(self.user), False) b = self.browser self.go_to_recipe_view(recipe) b.find_element_by_xpath('//h1[normalize-space(string(.))="Job: %s"]' % job.t_id) with session.begin(): self.assertEqual(recipe.get_reviewed_state(self.user), False)
def test_reserved_openstack_instance(self): with session.begin(): owner = data_setup.create_user( email_address=u'*****@*****.**') distro_tree = data_setup.create_distro_tree(distro_name=u'MicrowaveOS', variant=u'ThreeHeats', arch=u'x86_64') job = data_setup.create_running_job(owner=owner, virt=True, instance_id=uuid.UUID('00000000-1111-2222-3333-444444444444'), distro_tree=distro_tree, whiteboard=u'Operation Righteous Cowboy Lightning', recipe_whiteboard=u'Everything Sunny All the Time Always') recipe = job.recipesets[0].recipes[0] data_setup.mark_recipe_installation_finished(recipe, fqdn=u'bitenuker.ge.invalid') with session.begin(): bkr.server.mail.reservesys_notify(recipe) self.assertEqual(len(self.mail_capture.captured_mails), 1) sender, rcpts, raw_msg = self.mail_capture.captured_mails[0] self.assertEqual(rcpts, [owner.email_address]) msg = email.message_from_string(raw_msg) self.assertEqual(msg['To'], owner.email_address) self.assertEqual(msg['Subject'], '[Beaker System Reserved] bitenuker.ge.invalid') self.assertEqual(msg['X-Beaker-Notification'], 'system-reservation') expected_mail_body = u"""\ ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** This System is reserved by [email protected] To return this system early, you can click on 'Release System' against this recipe from the Web UI. Ensure you have your logs off the system before returning to Beaker. %(base)srecipes/%(recipeid)s For system details, see: http://openstack.example.invalid/dashboard/project/instances/00000000-1111-2222-3333-444444444444/ For the default root password, see: %(base)sprefs Beaker Test information: HOSTNAME=bitenuker.ge.invalid JOBID=%(jobid)s RECIPEID=%(recipeid)s DISTRO=MicrowaveOS ThreeHeats x86_64 ARCHITECTURE=x86_64 Job Whiteboard: Operation Righteous Cowboy Lightning Recipe Whiteboard: Everything Sunny All the Time Always ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** **""" \ % dict(base=get_server_base(), recipeid=recipe.id, jobid=job.id) actual_mail_body = msg.get_payload(decode=True) self.assertMultiLineEqual(actual_mail_body, expected_mail_body)
def test_opening_running_recipe_does_not_mark_it_reviewed(self): with session.begin(): job = data_setup.create_running_job() recipe = job.recipesets[0].recipes[0] self.assertEqual(recipe.get_reviewed_state(self.user), False) b = self.browser login(b, user=self.user.user_name, password='******') go_to_recipe_view(b, recipe) b.find_element_by_xpath('//h1[contains(string(.), "%s")]' % recipe.t_id) with session.begin(): self.assertEqual(recipe.get_reviewed_state(self.user), False)
def test_recipe_is_extended(self): # The external watchdog script is supposed to print the number of seconds # by which the watchdog timer should be extended. with session.begin(): system = data_setup.create_system(lab_controller=self.get_lc(), fqdn='watchdog.script.please.extend.600') job = data_setup.create_running_job(system=system) self.addCleanup(self.cleanup_job, job) recipe = job.recipesets[0].recipes[0] recipe.extend(-1) wait_for_condition(lambda: self.check_watchdog_extended(recipe, 600))
def test_filter_finished_jobs(self): with session.begin(): completed_job = data_setup.create_completed_job(task_status=TaskStatus.completed) cancelled_job = data_setup.create_completed_job(task_status=TaskStatus.cancelled) aborted_job = data_setup.create_completed_job(task_status=TaskStatus.aborted) running_job = data_setup.create_running_job() out = run_client(['bkr', 'job-list', '--finished']) self.assertIn(completed_job.t_id, out) self.assertIn(cancelled_job.t_id, out) self.assertIn(aborted_job.t_id, out) self.assertNotIn(running_job.t_id, out)
def test_recipe_is_aborted_on_script_failure(self): # If the external watchdog script exits non-zero, # beaker-watchdog ignores its output and aborts the recipe. with session.begin(): system = data_setup.create_system(lab_controller=self.get_lc(), fqdn='watchdog.script.please.crash') job = data_setup.create_running_job(system=system) self.addCleanup(self.cleanup_job, job) recipe = job.recipesets[0].recipes[0] recipe.extend(-1) wait_for_condition(lambda: self.check_watchdog_expiry(recipe))
def test_add_msg_when_cancelling_running_job_successful(self): with session.begin(): job_owner = data_setup.create_user(password=u'owner') job = data_setup.create_running_job(owner=job_owner) run_client(['bkr', 'job-cancel', job.t_id, '--username', job_owner.user_name, '--password', 'owner', '--msg=test adding cancel message']) with session.begin(): session.refresh(job) self.assertEquals(job.activity[0].action, u'Cancelled') self.assertEquals(job.recipesets[0].recipes[0].tasks[0].results[0].log, 'test adding cancel message')
def test_duplicate_logs_are_filtered_out(self): # Even if the db contains multiple rows referencing the same filename # (which it shouldn't) we want recipe.files() to filter those out # before returning them, to avoid breaking beaker-transfer. with session.begin(): job = data_setup.create_running_job() recipe = job.recipesets[0].recipes[0] recipe.logs.extend([ LogRecipe(path=u'/', filename=u'imadupe.log'), LogRecipe(path=u'/', filename=u'imadupe.log'), ]) logs = self.server.recipes.files(recipe.id) self.assertEqual(len(logs), 1) self.assertEqual(logs[0]['filename'], u'imadupe.log')
def test_filter_finished_jobs(self): with session.begin(): completed_job = data_setup.create_completed_job( task_status=TaskStatus.completed) cancelled_job = data_setup.create_completed_job( task_status=TaskStatus.cancelled) aborted_job = data_setup.create_completed_job( task_status=TaskStatus.aborted) running_job = data_setup.create_running_job() out = run_client(['bkr', 'job-list', '--finished']) self.assertIn(completed_job.t_id, out) self.assertIn(cancelled_job.t_id, out) self.assertIn(aborted_job.t_id, out) self.assertNotIn(running_job.t_id, out)
def test_filter_unfinished_jobs(self): with session.begin(): queued_job = data_setup.create_queued_job() running_job = data_setup.create_running_job() waiting_job = data_setup.create_waiting_job() scheduled_job = data_setup.create_scheduled_job() installing_job = data_setup.create_installing_job() completed_job = data_setup.create_completed_job() out = run_client(['bkr', 'job-list', '--unfinished']) self.assertIn(queued_job.t_id, out) self.assertIn(running_job.t_id, out) self.assertIn(waiting_job.t_id, out) self.assertIn(scheduled_job.t_id, out) self.assertIn(installing_job.t_id, out) self.assertNotIn(completed_job.t_id, out)
def test_system_reserved_notification_off(self): with session.begin(): owner = data_setup.create_user(email_address=u'*****@*****.**', notify_reservesys=False) system = data_setup.create_system(fqdn=u'funcooker.ge.valid', lab_controller=data_setup.create_labcontroller()) distro_tree = data_setup.create_distro_tree(arch=u'x86_64') job = data_setup.create_running_job(owner=owner, system=system, distro_tree=distro_tree, whiteboard=u'This is a whiteboard', recipe_whiteboard=u'This is another whiteboard') mail_capture_thread.start_capturing() with session.begin(): bkr.server.mail.reservesys_notify(job.recipesets[0].recipes[0]) captured_mails = mail_capture_thread.stop_capturing(wait=False) self.assertEqual(len(captured_mails), 0)
def test_lab_controller_remove(self): b = self.browser with session.begin(): lc = data_setup.create_labcontroller() # When an LC is removed, we de-associate all systems, cancel all # running recipes, and remove all distro tree associations. So this # test creates a system, job, and distro tree in the lab to cover # all those cases. sys = data_setup.create_system(lab_controller=lc) job = data_setup.create_running_job(lab_controller=lc) distro_tree = data_setup.create_distro_tree(lab_controllers=[lc]) b.get(get_server_base() + 'labcontrollers') b.find_element_by_xpath( "//table[@id='widget']/tbody/tr/" "td[preceding-sibling::td/a[normalize-space(text())='%s']]" "/a[normalize-space(text())='Remove']" % lc.fqdn).click() # confirm deletion b.find_element_by_xpath( '//button[@type="button" and .//text()="Delete"]').click() self.assert_('%s removed' % lc.fqdn in b.find_element_by_css_selector('.flash').text) with session.begin(): session.expire_all() # check lc activity self.assertEquals(lc.activity[0].field_name, u'Removed') self.assertEquals(lc.activity[0].action, u'Changed') self.assertEquals(lc.activity[0].new_value, u'True') self.assertEquals(lc.activity[1].field_name, u'Disabled') self.assertEquals(lc.activity[1].action, u'Changed') self.assertEquals(lc.activity[1].new_value, u'True') # check system activity self.assertEquals(sys.activity[0].field_name, u'lab_controller') self.assertEquals(sys.activity[0].action, u'Changed') self.assertEquals(sys.activity[0].new_value, None) # check job status job.update_status() self.assertEquals(job.status, TaskStatus.cancelled) # check distro tree activity self.assertEquals(distro_tree.activity[0].field_name, u'lab_controller_assocs') self.assertEquals(distro_tree.activity[0].action, u'Removed')
def test_lab_controller_remove(self): b = self.browser with session.begin(): lc = data_setup.create_labcontroller() # When an LC is removed, we de-associate all systems, cancel all # running recipes, and remove all distro tree associations. So this # test creates a system, job, and distro tree in the lab to cover # all those cases. sys = data_setup.create_system(lab_controller=lc) job = data_setup.create_running_job(lab_controller=lc) distro_tree = data_setup.create_distro_tree(lab_controllers=[lc]) b.get(get_server_base() + "labcontrollers") b.find_element_by_xpath( "//table[@id='widget']/tbody/tr/" "td[preceding-sibling::td/a[normalize-space(text())='%s']]" "/a[normalize-space(text())='Remove']" % lc.fqdn ).click() # confirm deletion b.find_element_by_xpath('//button[@type="button" and .//text()="Delete"]').click() self.assert_("%s removed" % lc.fqdn in b.find_element_by_css_selector(".flash").text) with session.begin(): session.expire_all() # check lc activity self.assertEquals(lc.activity[0].field_name, u"Removed") self.assertEquals(lc.activity[0].action, u"Changed") self.assertEquals(lc.activity[0].new_value, u"True") self.assertEquals(lc.activity[1].field_name, u"Disabled") self.assertEquals(lc.activity[1].action, u"Changed") self.assertEquals(lc.activity[1].new_value, u"True") # check system activity self.assertEquals(sys.activity[0].field_name, u"lab_controller") self.assertEquals(sys.activity[0].action, u"Changed") self.assertEquals(sys.activity[0].new_value, None) # check job status job.update_status() self.assertEquals(job.status, TaskStatus.cancelled) # check distro tree activity self.assertEquals(distro_tree.activity[0].field_name, u"lab_controller_assocs") self.assertEquals(distro_tree.activity[0].action, u"Removed")