#!/usr/bin/python3 -cimport os, sys; os.execv(os.path.dirname(sys.argv[1]) + "/../common/pywrap", sys.argv) # # Copyright (C) 2013 Red Hat, Inc. # SPDX-License-Identifier: LGPL-2.1-or-later import netlib import testlib @testlib.nondestructive class TestNetworkingBasic(netlib.NetworkCase): def testBasic(self): b = self.browser m = self.machine if not m.ostree_image: # screenshot assumes running firewalld and absent virbr0 (in particular, *3* interfaces) m.execute("systemctl start firewalld") # ensure PCP is on for pixel tests, so that we get the zoom/range selectors if b.pixels_label: m.execute("systemctl start pmlogger") self.login_and_go("/network") b.wait_visible("#networking") iface = 'cockpit1' self.add_veth(iface, dhcp_cidr="10.111.113.2/20") self.nm_activate_eth(iface) self.wait_for_iface(iface) b.wait_not_present("#network-interface") b.wait_in_text("#networking-graphs", "Transmitting") b.wait_in_text("#networking-graphs", "Receiving") # PCP is only enabled for pixel tests # zoom/range selectors are hidden when PCP is disabled if b.pixels_label: b.click("#zoom-control button:nth-of-type(2)") b.wait_in_text("#zoom-control button.pf-v6-c-menu-toggle", "1 hour") b.click("#zoom-control button.pf-v6-c-menu-toggle") b.click(".pf-v6-c-menu ul li:nth-child(3) > button") b.wait_in_text("#zoom-control button.pf-v6-c-menu-toggle", "5 minutes") # FIXME: rtl test was flaky, debug it and remove the skip b.assert_pixels( "#networking", "network-main", ignore=[ "td[data-label=Sending]", "td[data-label=Receiving]", "td[data-label='IP address']", "#networking-graphs .pf-v6-l-grid", ".cockpit-log-panel .pf-v6-c-card__body", "#networking-firewall-summary .pf-v6-c-card__body", ], # IPv6 addresses vary wildly, and their different rendered widths change the column widths skip_layouts=['medium', 'mobile', 'rtl'] ) # Details of test iface self.select_iface(iface) b.wait_visible("#network-interface") b.assert_pixels("#network-interface .network-interface-details", "network-interface", mock={ "#network-interface-mac": "11:22:33:44:55:66", ".networking-interface-status": "12.123.123.123/20, fedc:0:0:0:1234:ff:abcd:1234/64", }) con_id = testlib.wait(lambda: self.iface_con_id(iface)) # Toggle "Connect automatically" # b.wait_visible('#autoreconnect:checked') b.set_checked('#autoreconnect', val=False) self.assertEqual(m.execute(f"nmcli -g connection.autoconnect con show {con_id}"), "no\n") b.wait_visible('#autoreconnect:not(:checked)') b.set_checked('#autoreconnect', val=True) b.wait_visible('#autoreconnect:checked') self.assertEqual(m.execute(f"nmcli -g connection.autoconnect con show {con_id}"), "yes\n") # Configure a manual IPv4 address self.configure_iface_setting('IPv4') b.wait_visible("#network-ip-settings-dialog") b.select_from_dropdown("#network-ip-settings-dialog select", "manual") # Manual mode disables automatic switches b.wait_visible("#network-ip-settings-dialog [data-field='dns'] input[type=checkbox]:disabled") b.wait_visible("#network-ip-settings-dialog [data-field='dns_search'] input[type=checkbox]:disabled") b.wait_visible("#network-ip-settings-dialog [data-field='routes'] input[type=checkbox]:disabled") # Test IPv4 validation # Address b.set_input_text('#network-ip-settings-address-0', "192.168.48.10.2") b.set_input_text('#network-ip-settings-netmask-0', "24") b.click("#network-ip-settings-save") b.wait_in_text(".pf-v6-c-alert", "Invalid IP address: 192.168.48.10.2") b.set_input_text('#network-ip-settings-address-0', "192.168.256.10") b.click("#network-ip-settings-save") b.wait_in_text(".pf-v6-c-alert", "Invalid IP address: 192.168.256.10") b.set_input_text('#network-ip-settings-address-0', "192.168.48.10") b.set_input_text('#network-ip-settings-gateway', "192.168.48.") b.click("#network-ip-settings-save") # Gateway b.wait_in_text(".pf-v6-c-alert", "Invalid gateway address: 192.168.48.") b.set_input_text('#network-ip-settings-gateway', "192.168.48.1") # DNS b.click("#network-ip-settings-dns-add") b.set_input_text('#network-ip-settings-dns-server-0', "8..8") b.click("#network-ip-settings-save") b.wait_in_text(".pf-v6-c-alert", "Invalid DNS address: 8..8") b.set_input_text('#network-ip-settings-dns-server-0', "8.8.8.8") # Route b.click("#network-ip-settings-route-add") b.set_input_text('#network-ip-settings-route-address-0', "192") b.set_input_text('#network-ip-settings-route-netmask-0', "24") b.set_input_text('#network-ip-settings-route-gateway-0', "192.168.48.1") b.set_input_text('#network-ip-settings-route-metric-0', "500") b.click("#network-ip-settings-save") b.wait_in_text(".pf-v6-c-alert", "Invalid destination address: 192") b.set_input_text('#network-ip-settings-route-address-0', "192.168.66.0") b.set_input_text('#network-ip-settings-route-gateway-0', "not.an.ip.address") b.click("#network-ip-settings-save") b.wait_in_text(".pf-v6-c-alert", "Invalid gateway address: not.an.ip.address") b.set_input_text('#network-ip-settings-route-gateway-0', "192.168.48.1") b.set_input_text('#network-ip-settings-address-0', "1.2.3.4") b.set_input_text('#network-ip-settings-netmask-0', "255.255.0.8") b.set_input_text('#network-ip-settings-gateway', "1.2.3.1") b.click("#network-ip-settings-save") b.wait_text_not("#network-ip-settings-error h4", "") b.set_input_text('#network-ip-settings-netmask-0', "255.255.192.0") b.click("#network-ip-settings-save") b.wait_not_present("#network-ip-settings-dialog") self.wait_for_iface_setting("IPv4", "Address 1.2.3.4/18Gateway 1.2.3.1DNS 8.8.8.8") m.execute(f"until ip a show dev {iface} | grep -q 'inet 1.2.3.4/18'; do sleep 0.3; done", timeout=10) # Add IPv4 route without optional properties self.configure_iface_setting('IPv4') b.wait_visible("#network-ip-settings-dialog") # route without metric and next-hop address b.set_input_text('#network-ip-settings-route-address-0', "192.168.67.0") b.set_input_text('#network-ip-settings-route-netmask-0', "24") b.set_input_text('#network-ip-settings-route-gateway-0', "") b.set_input_text('#network-ip-settings-route-metric-0', "") b.click("#network-ip-settings-save") b.wait_not_present("#network-ip-settings-dialog") route = m.execute(f"nmcli -t -f ipv4.routes con sh {iface}").strip() self.assertEqual(route, "ipv4.routes:192.168.67.0/24") # route without metric self.configure_iface_setting('IPv4') b.wait_visible("#network-ip-settings-dialog") b.set_input_text('#network-ip-settings-route-address-0', "192.168.68.0") b.set_input_text('#network-ip-settings-route-netmask-0', "24") b.set_input_text('#network-ip-settings-route-gateway-0', "192.168.48.1") b.set_input_text('#network-ip-settings-route-metric-0', "") b.click("#network-ip-settings-save") b.wait_not_present("#network-ip-settings-dialog") route = m.execute(f"nmcli -t -f ipv4.routes con sh {iface}").strip() self.assertEqual(route, "ipv4.routes:192.168.68.0/24 192.168.48.1") # route without next-hop address self.configure_iface_setting('IPv4') b.wait_visible("#network-ip-settings-dialog") b.set_input_text('#network-ip-settings-route-address-0', "192.168.69.0") b.set_input_text('#network-ip-settings-route-netmask-0', "24") b.set_input_text('#network-ip-settings-route-gateway-0', "") b.set_input_text('#network-ip-settings-route-metric-0', "500") b.click("#network-ip-settings-save") b.wait_not_present("#network-ip-settings-dialog") route = m.execute(f"nmcli -t -f ipv4.routes con sh {iface}").strip() self.assertEqual(route, "ipv4.routes:192.168.69.0/24 500") # Configure manual IPv6 address b.click("#networking-edit-ipv6") b.wait_visible("#network-ip-settings-dialog") b.select_from_dropdown("#network-ip-settings-select-method", "manual") # Test IPv6 validation # Address b.set_input_text('#network-ip-settings-address-0', "2001:db8::10::1") b.set_input_text('#network-ip-settings-netmask-0', "64") b.click("#network-ip-settings-save") b.wait_in_text(".pf-v6-c-alert", "Invalid IP address: 2001:db8::10::1") b.set_input_text('#network-ip-settings-address-0', "no:ipv6:here::1") b.set_input_text('#network-ip-settings-netmask-0', "64") b.click("#network-ip-settings-save") b.wait_in_text(".pf-v6-c-alert", "Invalid IP address: no:ipv6:here::1") b.set_input_text('#network-ip-settings-address-0', "2001:db8::10:2") b.set_input_text('#network-ip-settings-netmask-0', "64") b.set_input_text('#network-ip-settings-gateway', "2001:db8::10:q") b.click("#network-ip-settings-save") # Gateway b.wait_in_text(".pf-v6-c-alert", "Invalid gateway address: 2001:db8::10:q") b.set_input_text('#network-ip-settings-gateway', "2001:db8::10:1") # DNS b.click("#network-ip-settings-dns-add") b.set_input_text('#network-ip-settings-dns-server-0', "2001:db8:64:::") b.click("#network-ip-settings-save") b.wait_in_text(".pf-v6-c-alert", "Invalid DNS address: 2001:db8:64:::") b.set_input_text('#network-ip-settings-dns-server-0', "2001:db8:cafe::1") # Route b.click("#network-ip-settings-route-add") b.set_input_text('#network-ip-settings-route-address-0', "2001") b.set_input_text('#network-ip-settings-route-netmask-0', "48") b.set_input_text('#network-ip-settings-route-gateway-0', "2001:db8::10:1") b.set_input_text('#network-ip-settings-route-metric-0', "500") b.click("#network-ip-settings-save") b.wait_in_text(".pf-v6-c-alert", "Invalid destination address: 2001") b.set_input_text('#network-ip-settings-route-address-0', "2001:db8:face::") b.set_input_text('#network-ip-settings-route-gateway-0', "::db8:cafe::1") b.click("#network-ip-settings-save") b.wait_in_text(".pf-v6-c-alert", "Invalid gateway address: ::db8:cafe::1") b.set_input_text('#network-ip-settings-route-gateway-0', "2001:db8::10:1") b.set_input_text("#network-ip-settings-address-0", "2001::1") b.set_input_text("#network-ip-settings-netmask-0", "64") b.set_input_text("#network-ip-settings-gateway", "::") b.click("button:contains('Save')") b.wait_not_present("#network-ip-settings-dialog") self.wait_for_iface_setting("IPv6", "Address 2001::1/64DNS 2001:db8:cafe::1") m.execute(f"until ip a show dev {iface} | grep -q 'inet6 2001::1/64 scope global'; do sleep 0.3; done", timeout=10) # Add IPv6 route without optional properties self.configure_iface_setting('IPv6') b.wait_visible("#network-ip-settings-dialog") # route without metric and next-hop address b.set_input_text('#network-ip-settings-route-address-0', "2001:db8:face::") b.set_input_text('#network-ip-settings-route-netmask-0', "64") b.set_input_text('#network-ip-settings-route-gateway-0', "") b.set_input_text('#network-ip-settings-route-metric-0', "") b.click("#network-ip-settings-save") b.wait_not_present("#network-ip-settings-dialog") route = m.execute(f"nmcli -t -f ipv6.routes con sh {iface}").strip() self.assertEqual(route, "ipv6.routes:2001:db8:face::/64") # route without metric self.configure_iface_setting('IPv6') b.wait_visible("#network-ip-settings-dialog") b.set_input_text('#network-ip-settings-route-address-0', "2001:db8:face:1::") b.set_input_text('#network-ip-settings-route-netmask-0', "64") b.set_input_text('#network-ip-settings-route-gateway-0', "2001:db8::10:1") b.set_input_text('#network-ip-settings-route-metric-0', "") b.click("#network-ip-settings-save") b.wait_not_present("#network-ip-settings-dialog") route = m.execute(f"nmcli -t -f ipv6.routes con sh {iface}").strip() self.assertEqual(route, "ipv6.routes:2001:db8:face:1::/64 2001:db8::10:1") # route without next-hop address self.configure_iface_setting('IPv6') b.wait_visible("#network-ip-settings-dialog") b.set_input_text('#network-ip-settings-route-address-0', "2001:db8:face:2::") b.set_input_text('#network-ip-settings-route-netmask-0', "64") b.set_input_text('#network-ip-settings-route-gateway-0', "") b.set_input_text('#network-ip-settings-route-metric-0', "500") b.click("#network-ip-settings-save") b.wait_not_present("#network-ip-settings-dialog") route = m.execute(f"nmcli -t -f ipv6.routes con sh {iface}").strip() self.assertEqual(route, "ipv6.routes:2001:db8:face:2::/64 500") # Disconnect self.wait_onoff("label[for='interface-switch']", val=True) self.toggle_onoff("label[for='interface-switch']") self.wait_for_iface_setting('Status', 'Inactive') # Reconnect through the UI self.toggle_onoff("label[for='interface-switch']") b.wait_in_text(f"#network-interface .pf-v6-c-card:contains('{iface}')", "1.2.3.4/18") # Disconnect from the CLI, UI reacts m.execute(f"nmcli device disconnect {iface}") self.wait_onoff("label[for='interface-switch']", val=False) # Switch it back to "auto" from the command line and bring it # up again # m.execute(f"nmcli connection modify '{con_id}' ipv4.method auto") m.execute(f"nmcli connection modify '{con_id}' ipv4.gateway ''") m.execute(f"nmcli connection modify '{con_id}' ipv4.addresses ''") self.wait_for_iface_setting('IPv4', "Automatic") m.execute(f"nmcli connection up '{con_id}'") self.wait_for_iface_setting('Status', '10.111.') # Switch off automatic DNS # self.configure_iface_setting('IPv4') b.wait_visible("#network-ip-settings-dialog") self.wait_onoff("#network-ip-settings-dialog [data-field='dns']", val=True) self.toggle_onoff("#network-ip-settings-dialog [data-field='dns']") # The "DNS search domains" setting should follow suit self.wait_onoff("#network-ip-settings-dialog [data-field='dns_search']", val=False) b.click("#network-ip-settings-save") b.wait_not_present("#network-ip-settings-dialog") testlib.wait(lambda: "yes" in m.execute(f"nmcli -f ipv4.ignore-auto-dns connection show '{con_id}'")) # Validate that IPv6 addresses are properly shortened # def set_and_check_ipv6(expected: str, addr: str, mask: str = "64", gateway: str = "::"): self.configure_iface_setting('IPv6') b.wait_visible("#network-ip-settings-dialog") b.set_input_text("#network-ip-settings-address-0", addr) b.set_input_text("#network-ip-settings-netmask-0", mask) b.set_input_text("#network-ip-settings-gateway", gateway) b.click("button:contains('Save')") b.wait_not_present("#network-ip-settings-dialog") self.wait_for_iface_setting("IPv6", f"Address {expected}") set_and_check_ipv6("2001:db8::ff00:42:8329/64", "2001:db8:0000:0000:0000:ff00:0042:8329") set_and_check_ipv6("2001::1/48", "2001:0:0:0:0:0:0:1", "48") set_and_check_ipv6("::1/128", "0:0:0:0:0:0:0:1", "128") set_and_check_ipv6("::/64", "0:0:0:0:0:0:0:0") set_and_check_ipv6("2001:db0:0:1::1428:57ab", "2001:0db0:0000:0001:0000:0000:1428:57ab") # first longest sequence is replaced set_and_check_ipv6("2001::aaaa:0:0:aaaa:bbbb/64", "2001:0000:0000:aaaa:0000:0000:aaaa:bbbb") # no compression needed set_and_check_ipv6("2001:db8:100:200:300:4:5000:6/64", "2001:db8:100:200:300:4:5000:6") # no compression for single fields of zero, only drop leading zeros set_and_check_ipv6("2001:0:a:0:a:0:a:0/64", "2001:0000:000a:0000:000a:0000:000a:0000") # left sequence is not the longest set_and_check_ipv6("2001:0:0:ffff::1/64", "2001:0:0:ffff:0:0:0:1") # left sequence is not the longest (full address) set_and_check_ipv6("2001:0:0:aaaa::1/64", "2001:0000:0000:aaaa:0000:0000:0000:0001") # left sequence is the longest set_and_check_ipv6("2001::1000:0:0:1/64", "2001:0000:0000:0000:1000:0000:0000:0001") # same length zeros are at the start and at the end set_and_check_ipv6("::db0:0:1:1:0:0/64", "0:0:db0:0:1:1:0:0") # end is longer set_and_check_ipv6("0:0:db0:0:1::/64", "0:0:db0:0:1:0:0:0") # start is longer set_and_check_ipv6("::db0:0:1:0:0/64", "0:0:0:db0:0:1:0:0") # check that default gateway is also shortened set_and_check_ipv6("2001:db8:cafe::1/64", "2001:db8:cafe:0:0:0:0:1", "64", "2001:0db8:cafe:0000:0000:0000:0000:0010") self.configure_iface_setting('IPv6') b.wait_visible("#network-ip-settings-dialog") b.wait_attr_contains("#network-ip-settings-gateway", "value", "2001:db8:cafe::10") b.go("/network") # Create a bridge interface and disable it to test if disabled connections can be modified. # Connection exists, is down and the device itself does not exist as long as the connection is down m.execute("nmcli con add con-name cockpitbr type bridge ifname cockpitbr ipv4.meth disab ipv6.meth disab") self.addCleanup(m.execute, "nmcli con del cockpitbr") self.wait_for_iface("cockpitbr", prefix="No carrier") m.execute("nmcli con down cockpitbr") self.wait_for_iface("cockpitbr", active=False) # check that connection exists but interface does not m.execute("nmcli con sh | grep -q 'cockpitbr'") m.execute("ip link sh | grep -q --invert-match 'cockpitbr'") self.select_iface("cockpitbr") b.wait_visible("#network-interface") self.wait_for_iface_setting("Status", "Inactive") # Configure IPv4 address self.configure_iface_setting("IPv4") b.wait_visible("#network-ip-settings-dialog") b.select_from_dropdown("#network-ip-settings-select-method", "manual") b.wait_visible("#network-ip-settings-address-0") b.set_input_text("#network-ip-settings-address-0", "10.0.5.10") b.set_input_text("#network-ip-settings-netmask-0", "24") b.set_input_text("#network-ip-settings-gateway", "10.0.5.1") b.click("#network-ip-settings-save") self.wait_for_iface_setting("IPv4", "Address 10.0.5.10/24Gateway 10.0.5.1") self.wait_for_iface_setting("Status", "Inactive") # Configure IPv6 address self.configure_iface_setting("IPv6") b.wait_visible("#network-ip-settings-dialog") b.select_from_dropdown("#network-ip-settings-select-method", "manual") b.wait_visible("#network-ip-settings-address-0") b.set_input_text("#network-ip-settings-address-0", "2001:db8::10") b.set_input_text("#network-ip-settings-netmask-0", "64") b.set_input_text("#network-ip-settings-gateway", "2001:db8::1") b.click("#network-ip-settings-save") self.wait_for_iface_setting("IPv6", "Address 2001:db8::10/64Gateway 2001:db8::1") self.wait_for_iface_setting("Status", "Inactive") # Start the interface and verify new address is set b.click("#interface-switch") self.wait_for_iface_setting("Status", "10.0.5.10/24,") m.execute("ip addr sh cockpitbr | grep -q 'inet 10.0.5.10/24'") m.execute("ip addr sh cockpitbr | grep -q 'inet6 2001:db8::10/64'") def testIpHelper(self): b = self.browser m = self.machine self.login_and_go("/network") b.wait_visible("#networking") iface = "cockpit1" self.add_veth(iface, dhcp_cidr="10.111.113.2/20") self.nm_activate_eth(iface) self.wait_for_iface(iface) b.click("button:contains('cockpit1')") # wait until dialog initialized b.click("#networking-edit-ipv4:contains('edit')") b.wait_visible("#network-ip-settings-dialog") b.select_from_dropdown("#network-ip-settings-select-method", "manual") b.wait_visible("#network-ip-settings-address-0") # test class A IP b.set_input_text("#network-ip-settings-address-0", "10.0.5.1") b.wait_val("#network-ip-settings-netmask-0", "8") b.set_input_text("#network-ip-settings-netmask-0", "") # test class B IP b.set_input_text("#network-ip-settings-address-0", "172.16.44.2") b.wait_val("#network-ip-settings-netmask-0", "16") b.set_input_text("#network-ip-settings-netmask-0", "") # test class C IP b.set_input_text("#network-ip-settings-address-0", "192.168.1.1") b.wait_val("#network-ip-settings-netmask-0", "24") b.set_input_text("#network-ip-settings-netmask-0", "") # others | Need to manually reset fields b.set_input_text("#network-ip-settings-netmask-0", "") b.set_input_text("#network-ip-settings-gateway", "") b.set_input_text("#network-ip-settings-address-0", "225.4.3.2") b.wait_val("#network-ip-settings-netmask-0", "") b.wait_val("#network-ip-settings-gateway", "") # free manual edit & save b.set_input_text("#network-ip-settings-address-0", "192.168.1.1") b.set_input_text("#network-ip-settings-netmask-0", "25") b.set_input_text("#network-ip-settings-gateway", "192.168.1.126") b.click("#network-ip-settings-save") b.wait_not_present("#network-ip-settings-dialog") self.assertIn("192.168.1.1/25", m.execute(f"nmcli -g ipv4.addresses connection show {iface}")) self.assertIn("192.168.1.126", m.execute(f"nmcli -g ipv4.gateway connection show {iface}")) b.click("#networking-edit-ipv4:contains('edit')") b.wait_visible("#network-ip-settings-dialog") # gateway is not changed after it has been explicitly edited by user b.set_input_text("#network-ip-settings-gateway", "192.168.20.7") b.set_input_text("#network-ip-settings-address-0", "10.0.0.5") b.wait_val("#network-ip-settings-gateway", "192.168.20.7") b.set_input_text("#network-ip-settings-address-0", "192.168.2.5") b.set_input_text("#network-ip-settings-netmask-0", "24") b.wait_val("#network-ip-settings-gateway", "192.168.20.7") b.click("#network-ip-settings-save") b.wait_not_present("#network-ip-settings-dialog") self.wait_for_iface_setting("IPv4", "Address 192.168.2.5/24Gateway 192.168.20.7") # Test classless gateway prefilling # the gateway is set to the first usable address in subnet # for subnets with prefix smaller than 30 b.click("#networking-edit-ipv4:contains('edit')") b.wait_visible("#network-ip-settings-dialog") b.set_input_text("#network-ip-settings-address-0", "10.11.101.240") b.set_input_text("#network-ip-settings-netmask-0", "8") b.wait_val("#network-ip-settings-gateway", "10.0.0.1") # /13 b.set_input_text("#network-ip-settings-netmask-0", "255.248.0.0") b.wait_val("#network-ip-settings-gateway", "10.8.0.1") b.set_input_text("#network-ip-settings-netmask-0", "15") b.wait_val("#network-ip-settings-gateway", "10.10.0.1") # /23 b.set_input_text("#network-ip-settings-netmask-0", "255.255.254.0") b.wait_val("#network-ip-settings-gateway", "10.11.100.1") b.set_input_text("#network-ip-settings-netmask-0", "24") b.wait_val("#network-ip-settings-gateway", "10.11.101.1") # /25 # first subnet smaller than 255 addresses, first address no longer ends with ".1" b.set_input_text("#network-ip-settings-netmask-0", "255.255.255.128") b.wait_val("#network-ip-settings-gateway", "10.11.101.129") b.set_input_text("#network-ip-settings-netmask-0", "27") b.wait_val("#network-ip-settings-gateway", "10.11.101.225") # /28 # host address is the same as network address b.set_input_text("#network-ip-settings-netmask-0", "255.255.255.240") b.wait_val("#network-ip-settings-gateway", "") # for prefixes 30-32 gateway is not set b.set_input_text("#network-ip-settings-address-0", "10.11.101.244") b.set_input_text("#network-ip-settings-netmask-0", "28") b.wait_val("#network-ip-settings-gateway", "10.11.101.241") # /30 b.set_input_text("#network-ip-settings-netmask-0", "255.255.255.252") b.wait_val("#network-ip-settings-gateway", "") b.set_input_text("#network-ip-settings-netmask-0", "28") b.wait_val("#network-ip-settings-gateway", "10.11.101.241") b.set_input_text("#network-ip-settings-netmask-0", "31") b.wait_val("#network-ip-settings-gateway", "") b.set_input_text("#network-ip-settings-netmask-0", "28") b.wait_val("#network-ip-settings-gateway", "10.11.101.241") # /32 b.set_input_text("#network-ip-settings-netmask-0", "255.255.255.255") b.wait_val("#network-ip-settings-gateway", "") # wrong prefixes b.set_input_text("#network-ip-settings-netmask-0", "33") b.wait_val("#network-ip-settings-gateway", "") b.set_input_text("#network-ip-settings-netmask-0", "asd23") b.wait_val("#network-ip-settings-gateway", "") # Mask does not change after it's been set b.set_input_text("#network-ip-settings-address-0", "10.11.101.244") b.set_input_text("#network-ip-settings-netmask-0", "255.255.254.0") b.set_input_text("#network-ip-settings-address-0", "192.168.88.13") b.wait_val("#network-ip-settings-netmask-0", "255.255.254.0") # but gateway does as it has not been set explicitly b.wait_val("#network-ip-settings-gateway", "192.168.88.1") # set gateway, then change host address to different network b.set_input_text("#network-ip-settings-gateway", "192.168.89.254") b.set_input_text("#network-ip-settings-address-0", "172.16.11.12") # both gateway and masks are unchanged b.wait_val("#network-ip-settings-netmask-0", "255.255.254.0") b.wait_val("#network-ip-settings-gateway", "192.168.89.254") b.set_input_text("#network-ip-settings-address-0", "192.168.88.13") b.click("#network-ip-settings-save") b.wait_not_present("#network-ip-settings-dialog") self.wait_for_iface_setting("IPv4", "Address 192.168.88.13/23Gateway 192.168.89.254") # IPv6 prefilling b.click("#networking-edit-ipv6:contains('edit')") b.wait_visible("#network-ip-settings-dialog") b.select_from_dropdown("#network-ip-settings-select-method", "manual") b.wait_visible("#network-ip-settings-address-0") # nothing is filled when plain IPv4 is entered b.set_input_text("#network-ip-settings-address-0", "10.11.101.240") b.wait_val("#network-ip-settings-netmask-0", "") b.wait_val("#network-ip-settings-gateway", "") # prefix length does not accept network mask b.set_input_text("#network-ip-settings-netmask-0", "255.255.240.0") b.wait_val("#network-ip-settings-gateway", "") # default prefix is /64 b.set_input_text("#network-ip-settings-address-0", "2001:db8:cafe:face:0:0:dcba:a") b.set_input_text("#network-ip-settings-netmask-0", "64") b.wait_val("#network-ip-settings-gateway", "2001:db8:cafe:face::1") b.set_input_text("#network-ip-settings-netmask-0", "97") b.wait_val("#network-ip-settings-gateway", "2001:db8:cafe:face::8000:1") b.set_input_text("#network-ip-settings-netmask-0", "105") b.wait_val("#network-ip-settings-gateway", "2001:db8:cafe:face::dc80:1") # for prefixes 126-128 gateway is not set b.set_input_text("#network-ip-settings-netmask-0", "126") b.wait_val("#network-ip-settings-gateway", "") b.set_input_text("#network-ip-settings-netmask-0", "105") b.wait_val("#network-ip-settings-gateway", "2001:db8:cafe:face::dc80:1") b.set_input_text("#network-ip-settings-netmask-0", "127") b.wait_val("#network-ip-settings-gateway", "") b.set_input_text("#network-ip-settings-netmask-0", "105") b.wait_val("#network-ip-settings-gateway", "2001:db8:cafe:face::dc80:1") b.set_input_text("#network-ip-settings-netmask-0", "128") b.wait_val("#network-ip-settings-gateway", "") # gateway is not set when host address is network address b.set_input_text("#network-ip-settings-address-0", "2001:db8:0:face:0:0:0:0") b.set_input_text("#network-ip-settings-netmask-0", "66") b.wait_val("#network-ip-settings-gateway", "") # gateway is not set when host address is first address b.set_input_text("#network-ip-settings-address-0", "2001:db8:0:face::1") b.wait_val("#network-ip-settings-gateway", "") # gateway is not changed after it's been set manually b.set_input_text("#network-ip-settings-address-0", "2001:db8:0:face::15") b.set_input_text("#network-ip-settings-netmask-0", "106") b.set_input_text("#network-ip-settings-gateway", "2001:db8:cafe:face::dc80:aaab") b.set_input_text("#network-ip-settings-address-0", "2001:db8:0:face:dead::15") b.wait_val("#network-ip-settings-gateway", "2001:db8:cafe:face::dc80:aaab") # after changing prefix gateway is still unchanged b.set_input_text("#network-ip-settings-netmask-0", "32") b.wait_val("#network-ip-settings-gateway", "2001:db8:cafe:face::dc80:aaab") b.set_input_text("#network-ip-settings-address-0", "2001:db8::1") b.click("#network-ip-settings-save") b.wait_not_present("#network-ip-settings-dialog") self.wait_for_iface_setting("IPv6", "Address 2001:db8::1/32Gateway 2001:db8:cafe:face::dc80:aaab") def testNoService(self): b = self.browser m = self.machine iface = "cockpit42" self.add_veth(iface) self.addCleanup(m.execute, "systemctl enable --now NetworkManager") def assert_running(): b.wait_not_present("#networking-nm-crashed") b.wait_not_present("#networking-nm-disabled") b.wait_visible("#networking-graphs") b.wait_in_text("#networking-interfaces", iface) def assert_stopped(enabled): # should hide graphs and actions and show the appropriate notification b.wait_not_present("#networking-graphs") b.wait_not_present("#networking-interfaces") if enabled: b.wait_visible("#networking-nm-crashed") b.wait_not_present("#networking-nm-disabled") else: b.wait_not_present("#networking-nm-crashed") b.wait_visible("#networking-nm-disabled") def assert_not_found(): # should hide graphs and actions and show the appropriate notification b.wait_not_present("#networking-graphs") b.wait_not_present("#networking-interfaces") b.wait_visible("#networking-nm-not-found") self.login_and_go("/network") assert_running() # stop/start NM on CLI, page should notice m.execute("systemctl stop NetworkManager") assert_stopped(enabled=True) m.execute("systemctl start NetworkManager") assert_running() # stop NM, test inline start button m.execute("systemctl stop NetworkManager") assert_stopped(enabled=True) b.click("#networking-nm-crashed button") assert_running() # stop NM, test troubleshoot button m.execute("systemctl stop NetworkManager") assert_stopped(enabled=True) b.click("#networking-nm-crashed a") b.enter_page("/system/services") b.wait_text(".service-name", "Network Manager") b.click(".service-top-panel button.pf-v6-c-menu-toggle") b.click("#services-page > .pf-v6-c-menu button.pf-v6-c-menu__item:contains('Start')") b.wait_in_text("#statuses", "Running") # networking page should notice start from Services page b.go("/network") b.enter_page("/network") assert_running() # stop and disable NM, enablement info notification m.execute("systemctl stop NetworkManager; systemctl disable NetworkManager") assert_stopped(enabled=False) b.click("#networking-nm-disabled button") assert_running() testlib.wait(lambda: m.execute("systemctl is-enabled NetworkManager")) # /usr in ostree is readonly if not m.ostree_image: # remove the NM service file, test 'no-found' notification # This works for ND tests since there is a self.addCleanup(m.execute, "systemctl enable --now NetworkManager") in the start of the test self.restore_file('/usr/lib/systemd/system/NetworkManager.service') m.execute("rm /usr/lib/systemd/system/NetworkManager.service; systemctl daemon-reload; systemctl stop NetworkManager") assert_not_found() self.allow_journal_messages(".*org.freedesktop.NetworkManager.*") # Killing NM affects realmd as well self.allow_journal_messages(".*org.freedesktop.realmd.Service.*") def testUnprivileged(self): b = self.browser m = self.machine self.login_and_go("/network", superuser=False) b.wait_visible("#networking") iface = 'cockpit1' self.add_veth(iface, dhcp_cidr="10.111.113.2/20") self.nm_activate_eth(iface) self.wait_for_iface(iface) con_id = testlib.wait(lambda: self.iface_con_id(iface)) mac = m.execute(f"cat /sys/class/net/{iface}/address").strip() self.select_iface(iface) b.wait_visible("#network-interface") # On/Off button is disabled, but shows the correct value b.wait_visible("#interface-switch:disabled") self.wait_onoff("label[for='interface-switch']", val=True) # not editable b.wait_visible('#autoreconnect:disabled') b.wait_not_present("#networking-edit-ipv4") b.wait_not_present("#networking-edit-mac") b.wait_text("#network-interface-mac", mac.upper()) # unpriv UI reacts to system change m.execute(f"nmcli device disconnect {iface}") self.wait_onoff("label[for='interface-switch']", val=False) m.execute(f"nmcli connection up '{con_id}'") self.wait_onoff("label[for='interface-switch']", val=True) # UI becomes editable when gaining privileges b.become_superuser() b.wait_visible('#autoreconnect:not(disabled)') b.wait_visible("#networking-edit-ipv4") b.wait_visible("#networking-edit-mac") b.wait_visible("#interface-switch:not(disabled)") if __name__ == '__main__': testlib.test_main()