Skip to content

Commit

Permalink
Merge pull request rhinstaller#5539 from rvykydal/teamd-capabilities
Browse files Browse the repository at this point in the history
Teamd capabilities
  • Loading branch information
rvykydal authored Apr 12, 2024
2 parents 722f19d + 5d3bd4c commit 4272daa
Show file tree
Hide file tree
Showing 5 changed files with 97 additions and 2 deletions.
2 changes: 2 additions & 0 deletions pyanaconda/core/constants.py
Original file line number Diff line number Diff line change
Expand Up @@ -102,6 +102,8 @@
NETWORK_CONNECTION_TIMEOUT = 46 # in seconds
NETWORK_CONNECTED_CHECK_INTERVAL = 0.1 # in seconds

NETWORK_CAPABILITY_TEAM = 1

# Anaconda user agent
USER_AGENT = "%s (anaconda)/%s" % (get_product_name(), get_product_version())

Expand Down
37 changes: 37 additions & 0 deletions pyanaconda/modules/network/network.py
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@
from pyanaconda.core.kernel import kernel_arguments
from pyanaconda.core.dbus import DBus
from pyanaconda.core.signal import Signal
from pyanaconda.core.constants import NETWORK_CAPABILITY_TEAM
from pyanaconda.modules.common.base import KickstartService
from pyanaconda.modules.common.containers import TaskContainer
from pyanaconda.modules.common.structures.requirement import Requirement
Expand Down Expand Up @@ -69,13 +70,20 @@ def __init__(self):
self.current_hostname_changed = Signal()
self._hostname_service_proxy = self._get_hostname_proxy()

self._capabilities = []
self.capabilities_changed = Signal()

self.connected_changed = Signal()
# TODO fallback solution - use Gio/GNetworkMonitor ?
self.nm_client = get_new_nm_client()
if self.nm_client:
self.nm_client.connect("notify::%s" % NM.CLIENT_STATE, self._nm_state_changed)
initial_state = self.nm_client.get_state()
self.set_connected(self._nm_state_connected(initial_state))
self.nm_client.connect("notify::%s" % NM.CLIENT_CAPABILITIES,
self._nm_capabilities_changed)
nm_capabilities = self.nm_client.get_capabilities()
self.set_capabilities(self._get_capabilities_from_nm(nm_capabilities))

self._original_network_data = []
self._device_configurations = None
Expand Down Expand Up @@ -306,6 +314,35 @@ def is_connecting(self):
log.debug("Connectivity state can't be determined, assuming not connecting.")
return False

@property
def capabilities(self):
"""Capabilities of the network backend."""
if not self.nm_available:
log.debug("Capabilities can't be determined.")
return []

return self._capabilities

def set_capabilities(self, capabilities):
"""Set network capabilities."""
self._capabilities = capabilities
self.capabilities_changed.emit()
self.module_properties_changed.emit()
log.debug("Capabilities: %s", capabilities)

@staticmethod
def _get_capabilities_from_nm(nm_capabilities):
capabilities = []
if NM.Capability.TEAM in nm_capabilities:
capabilities.append(NETWORK_CAPABILITY_TEAM)

return capabilities

def _nm_capabilities_changed(self, *args):
nm_capabilities = self.nm_client.get_capabilities()
log.debug("NeworkManager capabilities changed to %s", nm_capabilities)
self.set_capabilities(self._get_capabilities_from_nm(nm_capabilities))

@staticmethod
def _nm_state_connected(state):
return state in (NM.State.CONNECTED_LOCAL,
Expand Down
10 changes: 10 additions & 0 deletions pyanaconda/modules/network/network_interface.py
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,7 @@ def connect_signals(self):
self.implementation.current_hostname_changed.connect(self.CurrentHostnameChanged)
self.watch_property("Connected", self.implementation.connected_changed)
self.implementation.configurations_changed.connect(self._device_configurations_changed)
self.watch_property("Capabilities", self.implementation.capabilities_changed)

@property
def Hostname(self) -> Str:
Expand Down Expand Up @@ -108,6 +109,15 @@ def IsConnecting(self) -> Bool:
"""
return self.implementation.is_connecting()

@property
def Capabilities(self) -> List[Int]:
"""The network backend capabilities
Supported capabilities:
team capability = 1
"""
return self.implementation.capabilities

def GetSupportedDevices(self) -> List[Structure]:
"""Get info about existing network devices supported by the module.
Expand Down
14 changes: 13 additions & 1 deletion pyanaconda/ui/gui/spokes/network.py
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@
from pyanaconda.core.configuration.anaconda import conf
from pyanaconda.core.util import startProgram
from pyanaconda.core.process_watchers import PidWatcher
from pyanaconda.core.constants import ANACONDA_ENVIRON
from pyanaconda.core.constants import ANACONDA_ENVIRON, NETWORK_CAPABILITY_TEAM
from pyanaconda.core import glib
from pyanaconda.modules.common.constants.services import NETWORK
from pyanaconda.modules.common.structures.network import NetworkDeviceConfiguration
Expand Down Expand Up @@ -364,6 +364,18 @@ def __init__(self, builder, client, network_module, spoke=None):
self.button_apply_hostname = self.builder.get_object("button_apply_hostname")
self.button_apply_hostname.connect("clicked", self.on_apply_hostname)

if NETWORK_CAPABILITY_TEAM not in self._network_module.Capabilities:
self._remove_team_selection()

def _remove_team_selection(self):
log.debug("team functionality is not supported")
model = self.builder.get_object("liststore_add_device")
for row in model:
if row[1] == "team":
model.remove(row.iter)
return True
return False

@property
def vbox(self):
return self.builder.get_object("networkControlBox_vbox")
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@
check_kickstart_interface, check_task_creation, PropertiesChangedCallback

from pyanaconda.core.constants import FIREWALL_DEFAULT, FIREWALL_ENABLED, \
FIREWALL_DISABLED, FIREWALL_USE_SYSTEM_DEFAULTS
FIREWALL_DISABLED, FIREWALL_USE_SYSTEM_DEFAULTS, NETWORK_CAPABILITY_TEAM
from pyanaconda.core.kernel import KernelArguments
from pyanaconda.modules.common.constants.services import NETWORK
from pyanaconda.modules.common.constants.objects import FIREWALL
Expand Down Expand Up @@ -60,14 +60,29 @@ class MockedNMClient():
def __init__(self):
self.state = NM.State.DISCONNECTED
self.state_callback = None
self.capabilities = []
self.capabilities_callback = None

def _connect_state_changed(self, callback):
self.state_callback = callback

def _set_state(self, state):
self.state = state
self.state_callback(state)

def get_state(self):
return self.state

def _connect_capabilities_changed(self, callback):
self.capabilities_callback = callback

def _set_capabilities(self, caps):
self.capabilities = caps
self.capabilities_callback(caps)

def get_capabilities(self):
return self.capabilities


class NetworkInterfaceTestCase(unittest.TestCase):
"""Test DBus interface for the Network module."""
Expand Down Expand Up @@ -211,6 +226,25 @@ def test_mocked_client_connectivity(self):
self.callback.assert_called_with(NETWORK.interface_name, {'Connected': True}, [])
assert not self.network_interface.IsConnecting()

def test_capabilities_default(self):
"""Test getting capabilities does not fail."""
assert self.network_interface.Capabilities == []

def test_capabilities(self):
"""Test capabilities property with mocked NMClient."""
nm_client = MockedNMClient()
nm_client._connect_capabilities_changed(self.network_module._nm_capabilities_changed)
self.network_module.nm_client = nm_client

nm_client._set_capabilities([NM.Capability.TEAM, NM.Capability.OVS])
assert self.network_interface.Capabilities == [NETWORK_CAPABILITY_TEAM]

nm_client._set_capabilities([])
assert self.network_interface.Capabilities == []

self.network_module.nm_client = None
assert self.network_interface.Capabilities == []

def test_nm_availability(self):
self.network_module.nm_client = None
assert self.network_interface.Connected
Expand Down

0 comments on commit 4272daa

Please sign in to comment.