#!/usr/bin/python # -*- coding: utf-8 -*- # This file is part of Cockpit. # # Copyright (C) 2013 Red Hat, Inc. # # Cockpit is free software; you can redistribute it and/or modify it # under the terms of the GNU Lesser General Public License as published by # the Free Software Foundation; either version 2.1 of the License, or # (at your option) any later version. # # Cockpit is distributed in the hope that it will be useful, but # WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU # Lesser General Public License for more details. # # You should have received a copy of the GNU Lesser General Public License # along with Cockpit; If not, see . import parent from testlib import * from common import testvm class TestServices(MachineCase): def setUp(self): MachineCase.setUp(self) # Make sure the system finishes "booting" so that # when we add additional services to this target below # we don't race with the boot process self.machine.execute("systemctl start default.target") def testBasic(self): m = self.machine b = self.browser m.write("/etc/systemd/system/test.service", """ [Unit] Description=Test Service [Service] ExecStart=/bin/sh /usr/local/bin/test-service [Install] WantedBy=default.target """) m.write("/usr/local/bin/test-service", """ #! /bin/sh trap "echo STOP" 0 echo START while true; do sleep 5 echo WORKING done """) m.write("/etc/systemd/system/test-fail.service", """ [Unit] Description=Failing Test Service [Service] ExecStart=/usr/bin/false """) m.write("/etc/systemd/system/test-template@.service", """ [Unit] Description=Test Template for %I [Service] ExecStart=/usr/local/bin/test-service %I """) m.write("/etc/systemd/system/test.timer", """ [Unit] Description=Test Timer [Timer] OnCalendar=*:1/2 """) # After writing files out tell systemd about them m.execute("systemctl daemon-reload") self.machine.execute("systemctl start default.target") self.login_and_go("/system/services") def svc_sel(service): return 'tr[data-goto-unit="%s"]' % service def wait_service_state(service, state): b.wait_present(svc_sel(service)); b.wait_in_text(svc_sel(service), state) def wait_service_in_panel(service, title): b.wait_in_text(".panel:contains('%s') .panel-heading" % service, title) b.wait_in_text("#services", "test.service") wait_service_in_panel("test.service", "Disabled") m.execute("systemctl start test.service") wait_service_state("test.service", "running") m.execute("systemctl stop test.service") wait_service_in_panel("test.service", "Disabled") m.execute("systemctl enable test.service") wait_service_state("test.service", "inactive") unit_action_btn = '#service-valid .list-group-item:nth-child(1) .btn-group' file_action_btn = '#service-valid .list-group-item:nth-child(2) .btn-group' # Selects Timer tab b.click('#services-filter :nth-child(4)') b.wait_present(svc_sel('test.timer')) m.execute("systemctl start test.timer") b.wait_in_text(svc_sel('test.timer'), "Today") b.wait_in_text(svc_sel('test.timer'), "unknown") m.execute("systemctl stop test.timer") # Selects Services tab b.click('#services-filter :nth-child(2)') b.wait_present(svc_sel('test.service')) b.click(svc_sel("test.service")) b.wait_visible('#service-valid') b.wait_in_text('#service-valid', "inactive") b.wait_action_btn(unit_action_btn, "Start") b.click_action_btn(unit_action_btn) b.wait_in_text('#service-valid', "active") b.wait_action_btn(unit_action_btn, "Stop") b.wait_in_text('#service-log', "START") b.wait_in_text('#service-log', "WORKING") b.wait_in_text('#service-valid', "enabled") b.wait_action_btn(file_action_btn, "Disable") b.click_action_btn(file_action_btn) b.wait_in_text('#service-valid', "disabled") b.wait_action_btn(file_action_btn, "Enable") b.go("#/") b.wait_in_text("#services", "test-fail.service") b.wait_visible(svc_sel("test-fail.service")) b.click(svc_sel("test-fail.service")) b.wait_visible('#service-valid') b.wait_in_text('#service-valid', "inactive") b.wait_action_btn(unit_action_btn, "Start") b.click_action_btn(unit_action_btn) b.wait_in_text('#service-valid', "failed") b.go("#/") b.wait_in_text("#services", "test-fail.service") wait_service_state("test-fail.service", "failed") # Instantiate a template b.wait_in_text("#services", "test-template@.service") b.wait_visible(svc_sel("test-template@.service")) b.click(svc_sel("test-template@.service")) b.wait_visible('#service-template') b.set_val("#service-template input", "//param-f//o//o//") b.click("#service-template button") b.wait_visible("#service-valid") b.wait_text("#service-unit .panel-heading", "Test Template for param-f/o/o") b.wait_text("#service-valid a[data-goto-unit]", "test-template@.service") b.click("#service-valid a[data-goto-unit]") b.wait_visible("#service-template") self.allow_journal_messages("Failed to get realtime timestamp: Cannot assign requested address") def testApi(self): m = self.machine b = self.browser m.write("/etc/systemd/system/test.service", """ [Unit] Description=Test Service [Service] ExecStart=/bin/sh -c "while true; do sleep 5; done" [Install] WantedBy=default.target """) # After writing files out tell systemd about them m.execute("systemctl daemon-reload") self.login_and_go("/playground/service#/test") b.wait_text('#exists', 'true') b.wait_text('#state', '"stopped"') b.wait_text('#enabled', 'false') b.click('#start') b.wait_text('#state', '"running"') b.click('#stop') b.wait_text('#state', '"stopped"') b.click('#enable') b.wait_text('#enabled', 'true') b.click('#disable') b.wait_text('#enabled', 'false') b.go('#/foo') b.wait_text('#exists', 'false') def testCreateTimer(self): m = self.machine b = self.browser def svc_sel(service): return 'tr[data-goto-unit="%s"]' % service def wait_systemctl_timer(time): with testvm.Timeout(seconds=20, machine=m, error_message="Timeout while waiting for systemctl list-timers"): m.execute("cmd='systemctl list-timers'; until $cmd | grep -m 1 '%s'; do sleep 1; done" % time) m.execute("timedatectl set-timezone UTC") m.execute("timedatectl set-ntp off; timedatectl set-time '2020-01-01 15:30:00'") self.login_and_go("/system/services") b.click('#services-filter :nth-child(4)') b.wait_visible("#create-timer") b.click('#create-timer') b.wait_popup("timer-dialog") b.set_val("#servicename", "testing timer") b.set_val("#command", "/bin/sh -c '/bin/date >> /tmp/date'") b.click("#boot-or-specific-time button") b.click("#boot-or-specific-time .dropdown-menu li[value=2] a") b.wait_in_text("#boot-or-specific-time button", "At specific time") b.set_val("#hr", "24") b.set_val("#min", "6s") b.click("#timer-save-button") # checks for invalid input messages b.wait_text("#servicename-error", "Only alphabets, numbers, : , _ , . , @ , - are allowed.") b.wait_text("#description-error", "This field cannot be empty.") b.wait_text("#command-error", "") b.wait_text("#min-error", "Minute needs to be a number between 0-59") b.wait_text("#hr-error", "Hour needs to be a number between 0-23") b.click("#drop-repeat button") b.click("#drop-repeat .dropdown-menu li[value=10080] a") b.click("[data-content='add'][data-index=0]") b.wait_present("[data-content='minutes'][data-index=1]") b.wait_present("[data-content='hours'][data-index=0]") b.set_val("[data-index=0][data-content='hours']", "s") b.set_val("[data-index=1][data-content='minutes']", "w") b.click("#timer-save-button") b.wait_present("[data-content='hr-error'][data-index=0]") b.wait_text("[data-content='hr-error'][data-index=0]", "Hour needs to be a number between 0-23") b.wait_present("[data-content='min-error'][data-index=1]") b.wait_text("[data-content='min-error'][data-index=1]", "Minute needs to be a number between 0-59") # creates a new yearly timer at 2020-01-01 16:00 and at 2021-01-01 01:22 b.set_val("#servicename", "yearly_timer") b.set_val("#description", "Yearly timer") b.click("#drop-repeat button") b.click("#drop-repeat .dropdown-menu li[value=525600] a") b.click("[data-content='add'][data-index=0]") b.wait_present("[data-content='datepicker'][data-index=0]") b.set_val(".bootstrap-datepicker[data-index=0]","2020-01-01") b.set_val("[data-index=0][data-content='hours']", "16") b.set_val("[data-index=0][data-content='minutes']", "00") b.wait_present("[data-content='datepicker'][data-index=1]") b.set_val(".bootstrap-datepicker[data-index=1]","2021-01-01") b.set_val("[data-index=1][data-content='hours']", "01") b.set_val("[data-index=1][data-content='minutes']", "22") b.click("#timer-save-button") b.wait_popdown("timer-dialog") b.wait_present(svc_sel('yearly_timer.timer')) m.execute("timedatectl set-time '2020-01-01 15:30:00'") m.execute("systemctl start yearly_timer.timer") b.wait_present(svc_sel('yearly_timer.timer')) b.wait_in_text(svc_sel('yearly_timer.timer'), "Yearly timer") wait_systemctl_timer("Wed 2020-01-01 16:00") self.assertIn("Wed 2020-01-01 16:00", m.execute("systemctl list-timers")) m.execute("timedatectl set-time '2020-01-01 16:10:00'") # checks if yearly timer repeats yearly on 2021-01-01 01:22 wait_systemctl_timer("Fri 2021-01-01 01:22") self.assertIn("Fri 2021-01-01 01:22", m.execute("systemctl list-timers")) m.execute("systemctl stop yearly_timer.timer") # creates a new monthly timer that runs on 6th at 14:12 and 8th at 21:12 of every month b.wait_visible("#create-timer") b.click('#create-timer') b.wait_popup("timer-dialog") b.set_val("#servicename", "monthly_timer") b.set_val("#description", "Monthly timer") b.set_val("#command", "/bin/sh -c '/bin/date >> /tmp/date'") b.click("#boot-or-specific-time button") b.click("#boot-or-specific-time .dropdown-menu li[value=2] a") b.click("#drop-repeat button") b.click("#drop-repeat .dropdown-menu li[value=44640] a") b.wait_present("[data-content='month-days'][data-index=0]") b.click("[data-content='add'][data-index=0]") b.click("[data-index=0][data-content='month-days'] button") b.click("[data-index=0][data-content='month-days'] .dropdown-menu li[value=6] a") b.set_val("[data-index=0][data-content='hours']", "14") b.set_val("[data-index=0][data-content='minutes']", "12") b.wait_present("[data-content='month-days'][data-index=1]") b.click("[data-index=1][data-content='month-days'] button") b.click("[data-index=1][data-content='month-days'] .dropdown-menu li[value=8] a") b.set_val("[data-index=1][data-content='hours']", "21") b.set_val("[data-index=1][data-content='minutes']", "12") b.click("#timer-save-button") b.wait_popdown("timer-dialog") b.wait_present(svc_sel('monthly_timer.timer')) m.execute("timedatectl set-time '2020-01-01 16:15:00'") m.execute("systemctl start monthly_timer.timer") b.wait_present(svc_sel('monthly_timer.timer')) b.wait_in_text(svc_sel('monthly_timer.timer'), "Monthly timer") wait_systemctl_timer("Mon 2020-01-06 14:12") self.assertIn("Mon 2020-01-06 14:12", m.execute("systemctl list-timers")) m.execute("timedatectl set-time '2020-01-07 00:00:00'") wait_systemctl_timer("Wed 2020-01-08 21:12") self.assertIn("Wed 2020-01-08 21:12", m.execute("systemctl list-timers")) # checks if timer runs on next month February 2020 on same dates m.execute("timedatectl set-time '2020-01-08 21:23'") wait_systemctl_timer("Thu 2020-02-06 14:12") self.assertIn("Thu 2020-02-06 14:12", m.execute("systemctl list-timers")) # checks if timer runs on 8th March 2020 at 21:12 m.execute("timedatectl set-time '2020-03-07 00:00:00'") wait_systemctl_timer("Sun 2020-03-08 21:12") self.assertIn("Sun 2020-03-08 21:12", m.execute("systemctl list-timers")) m.execute("systemctl stop monthly_timer.timer") # creates a new weekly timer that runs on Fri at 12:45 and Sun at 20:12 every week b.wait_visible("#create-timer") b.click('#create-timer') b.wait_popup("timer-dialog") b.set_val("#servicename", "weekly_timer") b.set_val("#description", "Weekly timer") b.set_val("#command", "/bin/sh -c '/bin/date >> /tmp/date'") b.click("#boot-or-specific-time button") b.click("#boot-or-specific-time .dropdown-menu li[value=2] a") b.click("#drop-repeat button") b.click("#drop-repeat .dropdown-menu li[value=10080] a") b.wait_present("[data-content='week-days'][data-index=0]") b.click("[data-content='add'][data-index=0]") b.click("[data-index=0][data-content='week-days'] button") b.click("[data-index=0][data-content='week-days'] .dropdown-menu li[value=5] a") b.set_val("[data-index=0][data-content='hours']", "12") b.set_val("[data-index=0][data-content='minutes']", "45") b.wait_present("[data-content='week-days'][data-index=1]") b.click("[data-index=1][data-content='week-days'] button") b.click("[data-index=1][data-content='week-days'] .dropdown-menu li[value=7] a") b.set_val("[data-index=1][data-content='hours']", "20") b.set_val("[data-index=1][data-content='minutes']", "12") b.click("#timer-save-button") b.wait_popdown("timer-dialog") b.wait_present(svc_sel('weekly_timer.timer')) m.execute("timedatectl set-time '2020-03-07 00:00:00'") m.execute("systemctl start weekly_timer.timer") b.wait_present(svc_sel('weekly_timer.timer')) b.wait_in_text(svc_sel('weekly_timer.timer'), "Weekly timer") wait_systemctl_timer("Sun 2020-03-08 20:12") self.assertIn("Sun 2020-03-08 20:12", m.execute("systemctl list-timers")) m.execute("timedatectl set-time '2020-03-09 00:00:00'") wait_systemctl_timer("Fri 2020-03-13 12:45") self.assertIn("Fri 2020-03-13 12:45", m.execute("systemctl list-timers")) # checks if timer runs on next week's Friday and Sunday m.execute("timedatectl set-time '2020-03-14 00:00:00'") wait_systemctl_timer("Sun 2020-03-15 20:12") self.assertIn("Sun 2020-03-15 20:12", m.execute("systemctl list-timers")) m.execute("timedatectl set-time '2020-03-17 00:00:00'") wait_systemctl_timer("Fri 2020-03-20 12:45") self.assertIn("Fri 2020-03-20 12:45", m.execute("systemctl list-timers")) m.execute("systemctl stop weekly_timer.timer") # creates a new daily timer that runs at 2:40 and at 21:15 every day b.wait_visible("#create-timer") b.click('#create-timer') b.wait_popup("timer-dialog") b.set_val("#servicename", "daily_timer") b.set_val("#description", "Daily timer") b.set_val("#command", "/bin/sh -c '/bin/date >> /tmp/date'") b.click("#boot-or-specific-time button") b.click("#boot-or-specific-time .dropdown-menu li[value=2] a") b.click("#drop-repeat button") b.click("#drop-repeat .dropdown-menu li[value=1440] a") b.click("[data-content='add'][data-index=0]") b.set_val("[data-index=0][data-content='hours']", "2") b.set_val("[data-index=0][data-content='minutes']", "40") b.set_val("[data-index=1][data-content='hours']", "21") b.set_val("[data-index=1][data-content='minutes']", "15") b.click("#timer-save-button") b.wait_popdown("timer-dialog") b.wait_present(svc_sel('daily_timer.timer')) m.execute("timedatectl set-time '2020-03-17 00:00:00'") m.execute("systemctl start daily_timer.timer") b.wait_present(svc_sel('daily_timer.timer')) b.wait_in_text(svc_sel('daily_timer.timer'), "Daily timer") wait_systemctl_timer("Tue 2020-03-17 02:40") self.assertIn("Tue 2020-03-17 02:40", m.execute("systemctl list-timers")) m.execute("timedatectl set-time '2020-03-17 03:00:00'") wait_systemctl_timer("Tue 2020-03-17 21:15") self.assertIn("Tue 2020-03-17 21:15", m.execute("systemctl list-timers")) # checks if timer runs on friday 2020-04-10 at 02:40 and 21:15 m.execute("timedatectl set-time '2020-04-10 00:00:00'") wait_systemctl_timer("Fri 2020-04-10 02:40") self.assertIn("Fri 2020-04-10 02:40", m.execute("systemctl list-timers")) m.execute("timedatectl set-time '2020-04-10 03:00:00'") wait_systemctl_timer("Fri 2020-04-10 21:15") self.assertIn("Fri 2020-04-10 21:15", m.execute("systemctl list-timers")) m.execute("systemctl stop daily_timer.timer") # creates a new houry timer that runs at *:05 and at *:26 b.wait_visible("#create-timer") b.click('#create-timer') b.wait_popup("timer-dialog") b.set_val("#servicename", "hourly_timer") b.set_val("#description", "Hourly timer") b.set_val("#command", "/bin/sh -c '/bin/date >> /tmp/date'") b.click("#boot-or-specific-time button") b.click("#boot-or-specific-time .dropdown-menu li[value=2] a") b.click("#drop-repeat button") b.click("#drop-repeat .dropdown-menu li[value=60] a") b.click("[data-content='add'][data-index=0]") b.set_val("[data-index=0][data-content='minutes']", "05") b.set_val("[data-index=1][data-content='minutes']", "26") b.click("#timer-save-button") b.wait_popdown("timer-dialog") b.wait_present(svc_sel('hourly_timer.timer')) m.execute("timedatectl set-time '2020-04-10 03:00:00'") m.execute("systemctl start hourly_timer.timer") b.wait_present(svc_sel('hourly_timer.timer')) b.wait_in_text(svc_sel('hourly_timer.timer'), "Hourly timer") wait_systemctl_timer("Fri 2020-04-10 03:05") self.assertIn("Fri 2020-04-10 03:05", m.execute("systemctl list-timers")) m.execute("timedatectl set-time '2020-04-10 03:07:00'") wait_systemctl_timer("Fri 2020-04-10 03:26") self.assertIn("Fri 2020-04-10 03:26", m.execute("systemctl list-timers")) m.execute("timedatectl set-time '2020-04-10 04:00:00'") wait_systemctl_timer("Fri 2020-04-10 04:05") # checks if timer runs on next hour at 5 min and 26 min self.assertIn("Fri 2020-04-10 04:05", m.execute("systemctl list-timers")) m.execute("timedatectl set-time '2020-04-10 04:10:00'") wait_systemctl_timer("Fri 2020-04-10 04:26") self.assertIn("Fri 2020-04-10 04:26", m.execute("systemctl list-timers")) m.execute("systemctl stop hourly_timer.timer") # creates a new timer that runs at today at 23:59 b.wait_visible("#create-timer") b.click('#create-timer') b.wait_popup("timer-dialog") b.set_val("#servicename", "no_repeat_timer") b.set_val("#description", "No repeat timer") b.set_val("#command", "/bin/sh -c '/bin/date >> /tmp/date'") b.click("#boot-or-specific-time button") b.click("#boot-or-specific-time .dropdown-menu li[value=2] a") b.set_val("#hr", "23") b.set_val("#min", "59") b.click("#timer-save-button") b.wait_popdown("timer-dialog") b.wait_present(svc_sel('no_repeat_timer.timer')) b.wait_in_text(svc_sel('no_repeat_timer.timer'), "No repeat timer") m.execute("timedatectl set-time '2020-04-10 04:10:00'") m.execute("systemctl start no_repeat_timer.timer") b.wait_present(svc_sel('no_repeat_timer.timer')) wait_systemctl_timer("Fri 2020-04-10 23:59") self.assertIn("Fri 2020-04-10 23:59", m.execute("systemctl list-timers")) m.execute("systemctl stop no_repeat_timer.timer") # creates a boot timer that runs after 10 sec from boot b.wait_visible("#create-timer") b.click('#create-timer') b.wait_popup("timer-dialog") b.set_val("#servicename", "boot_timer") b.set_val("#description", "Boot timer") b.set_val("#command", "/bin/sh -c 'echo hello >> /tmp/hello'") b.click("#boot-or-specific-time button") b.click("#boot-or-specific-time .dropdown-menu li[value=1] a") b.set_val("#boot-time", "2") b.click("#timer-save-button") b.wait_popdown("timer-dialog") b.wait_present(svc_sel('boot_timer.timer')) m.execute("systemctl enable boot_timer.timer") m.spawn("sync && sync && sync && sleep 0.1 && reboot", "reboot") m.wait_reboot() m.start_cockpit() with testvm.Timeout(seconds=15, machine=m, error_message="Timeout while waiting for boot timer to run"): m.execute("while [ ! -f /tmp/hello ] ; do sleep 0.5; done") self.assertIn("hello", m.execute("cat /tmp/hello")) m.execute("timedatectl set-ntp on") self.allow_restart_journal_messages() if __name__ == '__main__': test_main()