forked from cockpit-project/cockpit-machines
-
Notifications
You must be signed in to change notification settings - Fork 0
/
check-machines-consoles
executable file
·180 lines (133 loc) · 7.64 KB
/
check-machines-consoles
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
#!/usr/bin/python3
# This file is part of Cockpit.
#
# Copyright (C) 2021 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 <http://www.gnu.org/licenses/>.
import os
import sys
# import Cockpit's machinery for test VMs and its browser test API
TEST_DIR = os.path.dirname(__file__)
sys.path.append(os.path.join(TEST_DIR, "common"))
sys.path.append(os.path.join(os.path.dirname(TEST_DIR), "bots/machine"))
from machineslib import VirtualMachinesCase # noqa
from testlib import no_retry_when_changed, nondestructive, test_main, wait, skipImage # noqa
@nondestructive
class TestMachinesConsoles(VirtualMachinesCase):
@no_retry_when_changed
@skipImage('spice-server does not exist ont rhel-9', "rhel-9-0")
def testExternalConsole(self):
b = self.browser
self.createVm("subVmTest1", graphics="spice")
self.login_and_go("/machines")
b.wait_in_text("body", "Virtual machines")
self.waitVmRow("subVmTest1")
b.wait_in_text("#vm-subVmTest1-state", "Running") # running or paused
self.goToVmPage("subVmTest1")
# since VNC is not defined for this VM, the view for "Desktop Viewer" is rendered by default
b.wait_in_text(".pf-c-console__manual-connection dl > div:first-child dd", "127.0.0.1")
b.wait_in_text(".pf-c-console__manual-connection dl > div:nth-child(2) dd", "5900")
b.click(".pf-c-console__remote-viewer-launch-vv") # "Launch Remote Viewer" button
b.wait_visible("#dynamically-generated-file") # is .vv file generated for download?
self.assertEqual(b.attr("#dynamically-generated-file", "href"),
u"data:application/x-virt-viewer,%5Bvirt-viewer%5D%0Atype%3Dspice%0Ahost%3D127.0.0.1%0Aport%3D5900%0Adelete-this-file%3D1%0Afullscreen%3D0%0A")
# HACK: clicking 'Launch Remote Viewer' kills execution context and thus CDP fails
b.reload()
b.enter_page("/machines")
# Go to the expanded console view
b.click("button:contains(Expand)")
# Check "More information"
b.click('.pf-c-console__remote-viewer .pf-c-expandable-section__toggle')
b.wait_in_text('.pf-c-expandable-section__content',
'Clicking "Launch remote viewer" will download')
b.assert_pixels("#vm-subVmTest1-consoles-page", "vm-details-console-external",
ignore=[".pf-c-expandable-section__toggle-icon"])
def testInlineConsole(self, urlroot=""):
b = self.browser
args = self.createVm("subVmTest1", "vnc")
if urlroot != "":
self.machine.execute('mkdir -p /etc/cockpit/ && echo "[WebService]\nUrlRoot=%s" > /etc/cockpit/cockpit.conf' % urlroot)
self.login_and_go("/machines", urlroot=urlroot)
b.wait_in_text("body", "Virtual machines")
self.waitVmRow("subVmTest1")
b.wait_in_text("#vm-subVmTest1-state", "Running") # running or paused
self.goToVmPage("subVmTest1")
# since VNC is defined for this VM, the view for "In-Browser Viewer" is rendered by default
b.wait_visible(".pf-c-console__vnc canvas")
# make sure the log file is full - then empty it and reboot the VM - the log file should fill up again
wait(lambda: "login as 'cirros' user." in self.machine.execute("cat {0}".format(args["logfile"])), delay=3)
self.machine.execute("echo '' > {0}".format(args["logfile"]))
b.click("#{0}-system-vnc-sendkey button".format("subVmTest1"))
b.click("#ctrl-alt-Delete")
wait(lambda: "Requesting system reboot" in self.machine.execute("cat {0}".format(args["logfile"])), delay=3)
def testInlineConsoleWithUrlRoot(self, urlroot=""):
self.testInlineConsole(urlroot="/webcon")
@skipImage('TODO: setlocale: No such file or directory', "arch")
@no_retry_when_changed
def testSerialConsole(self):
b = self.browser
m = self.machine
name = "vmWithSerialConsole"
self.createVm(name, graphics='vnc', ptyconsole=True)
self.login_and_go("/machines")
b.wait_in_text("body", "Virtual machines")
self.waitVmRow(name)
self.goToVmPage(name)
b.wait_in_text("#vm-{0}-state".format(name), "Running") # running or paused
b.click("#pf-c-console__type-selector")
b.wait_visible("#pf-c-console__type-selector + .pf-c-select__menu")
b.click("#SerialConsole button")
b.wait_not_present("#pf-c-console__type-selector + .pf-c-select__menu")
b.wait_in_text("#{0}-terminal .xterm-accessibility-tree".format(name), "cirros login")
b.click("#{0}-serialconsole-disconnect".format(name))
b.wait_text("#{0}-terminal".format(name), "Disconnected from serial console. Click the connect button.")
b.click("#{0}-serialconsole-connect".format(name))
b.wait_in_text("#{0}-terminal .xterm-accessibility-tree > div:nth-child(1)".format(name), "Connected to domain")
b.click("button:contains(Expand)")
b.assert_pixels("#vm-vmWithSerialConsole-consoles-page", "vm-details-console-serial")
# Add a second serial console
m.execute("virsh destroy vmWithSerialConsole && virt-xml --add-device vmWithSerialConsole --console pty,target_type=virtio && virsh start vmWithSerialConsole")
b.click("#pf-c-console__type-selector")
b.wait_visible("#pf-c-console__type-selector + .pf-c-select__menu")
b.click("li:contains('Serial console (console0)') button")
b.wait(lambda: m.execute("ps aux | grep 'virsh -c qemu:///system console vmWithSerialConsole console0'"))
b.click("#pf-c-console__type-selector")
b.click("li:contains('Serial console (console1)') button")
b.wait(lambda: m.execute("ps aux | grep 'virsh -c qemu:///system console vmWithSerialConsole console1'"))
# disconnecting the serial console closes the pty channel
self.allow_journal_messages("connection unexpectedly closed by peer",
".*Connection reset by peer")
self.allow_browser_errors("Disconnection timed out.")
self.allow_journal_messages(".* couldn't shutdown fd: Transport endpoint is not connected")
def testSwitchConsoleFromSerialToGraphical(self):
b = self.browser
name = "vmForSwitching"
self.createVm(name, graphics="vnc", ptyconsole=True)
self.login_and_go("/machines")
b.wait_in_text("body", "Virtual machines")
self.waitVmRow(name)
self.goToVmPage(name)
b.wait_in_text("#vm-{0}-state".format(name), "Running")
b.wait_visible("#vm-{0}-consoles".format(name))
b.wait_visible(".pf-c-console__vnc canvas")
b.click("#pf-c-console__type-selector")
b.wait_visible("#pf-c-console__type-selector + .pf-c-select__menu")
b.click("#SerialConsole button")
b.wait_not_present("#pf-c-console__type-selector + .pf-c-select__menu")
b.wait_not_present(".pf-c-console__vnc canvas")
b.wait_visible("#{}-terminal".format(name))
b.wait_not_present("#navbar-oops")
self.allowed_messages.append("connection unexpectedly closed by peer")
if __name__ == '__main__':
test_main()