package pikvm; use strict; use base 'Exporter'; use Exporter; use lockapi; use testapi; use utils; our @EXPORT = qw(open_pikvm open_subpage power_switch upload_iso_file attach_iso_file detach_iso_file delete_iso_file boot_iso select_stream select_source os_power_off); # The background virtual machine will open the web browser and will # point it to the correct address automatically. This routine will # handle the login into the pikvm web page. sub open_pikvm { my $ip_address = get_var("KVM_IP"); # There is a warning that the connection is not safe. # Make sure we will go past this and proceed to the page # anyway. if (check_screen("pikvm_connection_warning", timeout => 20)) { assert_and_click("pikvm_connection_button_advanced"); assert_and_click("pikvm_connection_link_proceed"); } # Check that we have reached that destination. # We prolong the wait time here if there were hiccoughs # on the network. assert_screen("pikvm_kvm_login", timeout => 60); # Login to the PiKVM web administration. type_very_safely("admin"); sleep(1); send_key("tab"); sleep(1); type_very_safely("fedoraftw"); assert_and_click("pikvm_button_login"); assert_screen("pikvm_kvm_welcome_screen"); } # This routine opens the appropriate subpage # on the PiKVM main screen. We have not created # needles for all of the subpages, so if you # are getting errors, you need to create them. sub open_subpage { my $subpage = shift; # Click on the button in the upper menu # to open the subpage. assert_and_click("pikvm_open_$subpage"); assert_screen("pikvm_subpage_opened_$subpage"); } # This operates the powerswitch and is able to operate # one of the buttons in a certain way. You can choose # the $action - short, long, reset. Usually, the short # press will switch the computer on, the long press # will switch it off anytime, and reset will reboot it. sub power_switch { my $action = shift; unless ($action) { $action = "reset"; } # Click on the icons to open the menu assert_and_click("pikvm_power_switch"); assert_and_click("pikvm_power_action_$action"); if (check_screen("pikvm_confirmation_ok", timeout => 5)) { click_lastmatch(); } } # This routine will download the $iso from the link # that is passed via test variables. Note, that downloading # usually takes some time. sub upload_iso_file { my ($iso, $name) = @_; # Click on the Drive button to access the upload assert_and_click("pikvm_open_drive"); # If anything is attached, detach it. if (check_screen("pikvm_drive_attached")) { assert_and_click("pikvm_drive_disconnect"); } # Open the Upload dialogue assert_and_click("pikvm_select_upload_image"); # Check that the Upload dialogue has opened assert_screen("pikvm_upload_dialogue_opened"); # Click into the URL line has been reached. assert_and_click("pikvm_url_line"); # Type in the download link type_very_safely($iso); # Confirm the Upload with the Upload button assert_and_click("pikvm_upload_button_upload"); # If the image already exists do nothing and # confirm the error message. if (check_screen("pikvm_image_already_exists", timeout => 30)) { assert_and_click("pikvm_button_ok"); } else { # Wait until the upload is complete. With bigger downloads # the screen went off so we will move the mouse occasionally # to make sure it will not shut down. while (check_screen("pikvm_upload_dialogue_opened")) { mouse_set(500, 500); sleep(15); mouse_set(200, 200); sleep(5); } } # Dismiss the dialogue assert_and_click("pikvm_open_drive"); } # This routine will attach the uploaded iso file # to the PiKVM's drive slot to make it available # for installations. You can select the $drive # which would be a "cdrom" or a "flash". sub attach_iso_file { my ($name, $drive) = @_; # Open the Drive menu assert_and_click("pikvm_open_drive"); # Deattach if anything is left from previous attempts. if (check_screen("pikvm_drive_attached")) { assert_and_click("pikvm_drive_disconnect"); } # Click onto File selector assert_and_click("pikvm_open_file_selector"); # Select the reqired image assert_and_click("pikvm_select_iso_$name"); # Select the type assert_and_click("pikvm_select_type_$drive"); # Attach the iso image assert_and_click("pikvm_connect_drive_server"); # Check it has been connected assert_screen("pikvm_drive_attached"); # Dismiss the Drive menu assert_and_click("pikvm_open_drive"); } # This routine disconnects the drive from # the server again. When the drive stays # connected, sometimes the bare machine stops # reporting either UEFI or BIOS method to boot # the machine. Disconnecting the image prevents # this from happening. sub detach_iso_file { assert_and_click("pikvm_open_drive"); assert_and_click("pikvm_drive_disconnect"); assert_screen("pikvm_drive_detached"); assert_and_click("pikvm_open_drive"); } # This routine deletes the ISO file from the PiKVM's # disk. We are currently not using this anywhere, # because deleting the ISO file between two similar # tests would cost a lot of time to download it again. sub delete_iso_file { my $name = shift; assert_and_click("pikvm_open_drive"); assert_and_click("pikvm_open_file_selector"); assert_and_click("pikvm_select_iso_$name"); assert_and_click("pikvm_drive_button_delete"); assert_and_click("pikvm_confirmation_ok"); assert_screen("pikvm_image_not_selected"); assert_and_click("pikvm_open_drive"); } # This routine will boot the attached iso image # in the machine connected to PiKVM. It passes the # $key to invoke a boot up menu and it then chooses # the installation source depending on $bootway, which # can be either "efi" or "bios". If nothing is chosen, # "efi" will be selected automatically. sub boot_iso { my ($key, $bootway) = @_; my $count = 10; # As soon as we see this tag, we will send the $key to enter # the boot selection mode. Note, that if the needle is missing or # not correct, the system might not be able to select the boot # source. if (check_screen("pikvm_boot_devices_select", timeout => 30)) { send_key($key); } # Check that we have reached the boot up menu. Otherwise no need to continue. assert_screen("pikvm_boot_devices_shown"); # Navigate through the boot devices menu and select the appropriate one. if ($bootway eq "bios") { send_key_until_needlematch("pikvm_boot_boot_bios", "down"); } else { send_key_until_needlematch("pikvm_boot_boot_uefi", "down"); } # Confirm the selection using Enter. send_key("ret"); sleep(5); # To let the VM settle. # The Grub menu should appear with "Test this media" as a default # selection. However, we do not want to go with that because the # check slows down the process. Therefore, we will move one step # up and select to boot the installer without any testing. send_key("up"); sleep(1); send_key("ret"); } # This routine is similar to boot_iso but it uses different needles # to identify the sources. Also, it will not send the extra key presses # to select the correct GRUB entry. sub select_source { my ($key, $bootway) = @_; my $count = 10; # Start sending the key to enter the boot menu immediately # after the system starts and repeat for some time. # Any other, less invasive method was not reliable. if (check_screen("pikvm_boot_devices_select", timeout => 60)) { send_key($key); } else {die;} # Check that we have reached the boot up menu. # Otherwise no need to continue. assert_screen("pikvm_boot_devices_shown"); # If we have selected BIOS boot, perform it. # Otherwise do an UEFI boot and select the boot menu # entry accordingly. Because these early stages do not # respond to mouse reliably, use keys to navigate # through the menu. if ($bootway eq "bios") { send_key_until_needlematch("pikvm_boot_installed_bios", "down"); } else { send_key_until_needlematch("pikvm_boot_installed_uefi", "down"); } # Confirm the selection using Enter. send_key("ret"); } # This routine will power off/logout the running bare metal # machine from within an installed system. sub os_power_off { my $action = shift; if (check_screen("pikvm_system_off_button")) { click_lastmatch(); assert_and_click("pikvm_menu_off_button"); if ($action eq "poweroff") { assert_and_click("pikvm_system_poweroff"); assert_and_click("pikvm_system_poweroff_confirm"); } elsif ($action eq "logout") { assert_and_click("pikvm_system_logout"); assert_and_click("pikvm_system_logout_confirm"); } } else { if ($action eq "poweroff") { enter_cmd("shutdown -h now"); } elsif ($action eq "logout") { enter_cmd("logout"); } } } # Set the stream to MPEG or WebRTC. # PiKVM has two ways to send the screens and this # will select it. We want to use the MPEG version, # because it works on Chromium and the needles are # created using this approach. sub select_stream { my $stream = shift; assert_and_click("pikvm_open_system"); assert_and_click("pikvm_source_$stream"); assert_and_click("pikvm_open_system"); }