black: Cover libnmstate/nm

Signed-off-by: Edward Haas <edwardh@redhat.com>
This commit is contained in:
Edward Haas 2019-06-16 10:19:38 +03:00
parent 339fd1b754
commit e5b86c0c0e
18 changed files with 362 additions and 266 deletions

View File

@ -32,7 +32,6 @@ class ActivationError(Exception):
class ActiveConnection(object):
def __init__(self, active_connection=None):
self.handlers = set()
self._act_con = active_connection
@ -68,8 +67,9 @@ class ActiveConnection(object):
act_connection = self._nmdev.get_active_connection()
mainloop = nmclient.mainloop()
if not act_connection or act_connection.props.state in (
nmclient.NM.ActiveConnectionState.DEACTIVATING,
nmclient.NM.ActiveConnectionState.DEACTIVATED):
nmclient.NM.ActiveConnectionState.DEACTIVATING,
nmclient.NM.ActiveConnectionState.DEACTIVATED,
):
# Nothing left to do here, call the next action.
mainloop.execute_next_action()
return
@ -90,22 +90,28 @@ class ActiveConnection(object):
if self._mainloop.is_action_canceled(e):
logging.debug(
'Connection deactivation aborted on %s: error=%s',
self._nmdev.get_iface(), e)
self._nmdev.get_iface(),
e,
)
else:
self._mainloop.quit(
'Connection deactivation failed on {}: error={}'.format(
self._nmdev.get_iface(), e))
self._nmdev.get_iface(), e
)
)
return
if success:
logging.debug(
'Connection deactivation succeeded on %s',
self._nmdev.get_iface())
self._nmdev.get_iface(),
)
self._mainloop.execute_next_action()
else:
self._mainloop.quit(
'Connection deactivation failed on %s: error=unknown' %
self._nmdev.get_iface())
'Connection deactivation failed on %s: error=unknown'
% self._nmdev.get_iface()
)
def refresh_state(self):
self._state = self._act_con.get_state()
@ -116,18 +122,20 @@ class ActiveConnection(object):
nm_acsreason = nmclient.NM.ActiveConnectionStateReason
if self._state == nm_acs.DEACTIVATED:
unable_to_activate = (
not self._nmdev or
(
self._state_reason is not None and
self._state_reason != nm_acsreason.DEVICE_DISCONNECTED
) or
self._nmdev.get_active_connection() is not self._act_con
not self._nmdev
or (
self._state_reason is not None
and self._state_reason != nm_acsreason.DEVICE_DISCONNECTED
)
or self._nmdev.get_active_connection() is not self._act_con
)
if unable_to_activate:
self._alternative_state = AlternativeACState.FAIL
# Use the device-state as an alternative to determine if active.
elif (self.nmdev_state <= nmclient.NM.DeviceState.DISCONNECTED or
self.nmdev_state > nmclient.NM.DeviceState.DEACTIVATING):
elif (
self.nmdev_state <= nmclient.NM.DeviceState.DISCONNECTED
or self.nmdev_state > nmclient.NM.DeviceState.DEACTIVATING
):
self._alternative_state = AlternativeACState.FAIL
@property
@ -136,14 +144,15 @@ class ActiveConnection(object):
if self._state == nm_acs.ACTIVATED:
return True
elif self._state == nm_acs.ACTIVATING:
# master connections qualify as activated once they
# reach IP-Config state. That is because they may
# wait for slave devices to attach
return (
_is_device_master_type(self._nmdev) and
nmclient.NM.DeviceState.IP_CONFIG <= self.nmdev_state <=
nmclient.NM.DeviceState.ACTIVATED
)
# master connections qualify as activated once they
# reach IP-Config state. That is because they may
# wait for slave devices to attach
return (
_is_device_master_type(self._nmdev)
and nmclient.NM.DeviceState.IP_CONFIG
<= self.nmdev_state
<= nmclient.NM.DeviceState.ACTIVATED
)
return False
@ -179,18 +188,21 @@ class ActiveConnection(object):
@property
def nmdev_state(self):
return (self._nmdev.get_state() if self._nmdev
else nmclient.NM.DeviceState.UNKNOWN)
return (
self._nmdev.get_state()
if self._nmdev
else nmclient.NM.DeviceState.UNKNOWN
)
def _is_device_master_type(nmdev):
if nmdev:
gobject = nmclient.GObject
is_master_type = (
gobject.type_is_a(nmdev, nmclient.NM.DeviceBond) or
gobject.type_is_a(nmdev, nmclient.NM.DeviceBridge) or
gobject.type_is_a(nmdev, nmclient.NM.DeviceTeam) or
gobject.type_is_a(nmdev, nmclient.NM.DeviceOvsBridge)
gobject.type_is_a(nmdev, nmclient.NM.DeviceBond)
or gobject.type_is_a(nmdev, nmclient.NM.DeviceBridge)
or gobject.type_is_a(nmdev, nmclient.NM.DeviceTeam)
or gobject.type_is_a(nmdev, nmclient.NM.DeviceOvsBridge)
)
return is_master_type
return False

View File

@ -77,7 +77,8 @@ def prepare_edited_ifaces_configuration(ifaces_desired_state):
cur_con_profile = connection.ConnectionProfile()
cur_con_profile.import_by_device(nmdev)
new_con_profile = _build_connection_profile(
iface_desired_state, base_con_profile=cur_con_profile)
iface_desired_state, base_con_profile=cur_con_profile
)
if not new_con_profile.devname:
set_conn = new_con_profile.profile.get_setting_connection()
set_conn.props.interface_name = iface_desired_state['name']
@ -136,24 +137,29 @@ def set_ifaces_admin_state(ifaces_desired_state, con_profiles=()):
master_iface_types = ovs.BRIDGE_TYPE, bond.BOND_TYPE, LB.TYPE
if iface_desired_state['type'] in master_iface_types:
master_ifaces_to_edit.add(
(nmdev, con_profiles_by_devname[ifname].profile))
(nmdev, con_profiles_by_devname[ifname].profile)
)
else:
ifaces_to_edit.add(
(nmdev, con_profiles_by_devname[ifname].profile))
(nmdev, con_profiles_by_devname[ifname].profile)
)
elif iface_desired_state['state'] in ('down', 'absent'):
nmdevs = _get_affected_devices(iface_desired_state)
for nmdev in nmdevs:
devs_actions[nmdev] = [device.deactivate, device.delete]
if nmdev.get_device_type() in (
nmclient.NM.DeviceType.OVS_BRIDGE,
nmclient.NM.DeviceType.OVS_PORT,
nmclient.NM.DeviceType.OVS_INTERFACE):
nmclient.NM.DeviceType.OVS_BRIDGE,
nmclient.NM.DeviceType.OVS_PORT,
nmclient.NM.DeviceType.OVS_INTERFACE,
):
devs_actions[nmdev].append(device.delete_device)
else:
raise NmstateValueError(
'Invalid state {} for interface {}'.format(
iface_desired_state['state'],
iface_desired_state['name']))
iface_desired_state['name'],
)
)
for ifname in new_ifaces_to_activate:
device.activate(dev=None, connection_id=ifname)
@ -243,7 +249,8 @@ def prepare_proxy_ifaces_desired_state(ifaces_desired_state):
continue
port_options = ovs.translate_port_options(port_opts_metadata)
port_iface_desired_state = _create_ovs_port_iface_desired_state(
iface_desired_state, port_options)
iface_desired_state, port_options
)
new_ifaces_desired_state.append(port_iface_desired_state)
# The "visible" slave/interface needs to point to the port profile
iface_desired_state[MASTER_METADATA] = port_iface_desired_state['name']
@ -301,8 +308,9 @@ def _build_connection_profile(iface_desired_state, base_con_profile=None):
elif iface_type == bridge.BRIDGE_TYPE:
bridge_options = iface_desired_state.get('bridge', {}).get('options')
if bridge_options:
linux_bridge_setting = bridge.create_setting(bridge_options,
base_profile)
linux_bridge_setting = bridge.create_setting(
bridge_options, base_profile
)
settings.append(linux_bridge_setting)
elif iface_type == ovs.BRIDGE_TYPE:
ovs_bridge_options = ovs.translate_bridge_options(iface_desired_state)

View File

@ -32,7 +32,9 @@ def create_setting(options):
if not success:
raise NmstateValueError(
'Invalid bond option: \{}\=\'{}\''.format(
option_name, option_value))
option_name, option_value
)
)
return bond_setting
@ -42,10 +44,7 @@ def is_bond_type_id(type_id):
def get_bond_info(nm_device):
return {
'slaves': get_slaves(nm_device),
'options': get_options(nm_device)
}
return {'slaves': get_slaves(nm_device), 'options': get_options(nm_device)}
def get_options(nm_device):

View File

@ -115,9 +115,9 @@ def get_info(nmdev):
LB.STP_PRIORITY: bridge_setting.props.priority,
LB.STP_FORWARD_DELAY: bridge_setting.props.forward_delay,
LB.STP_HELLO_TIME: bridge_setting.props.hello_time,
LB.STP_MAX_AGE: bridge_setting.props.max_age
}
}
LB.STP_MAX_AGE: bridge_setting.props.max_age,
},
},
}
return info

View File

@ -74,8 +74,9 @@ class _NMDbusManager(object):
OBJ_PATH = '/org/freedesktop/NetworkManager'
def __init__(self):
mng_proxy = _NMDbus.bus.get_object(_NMDbus.BUS_NAME,
_NMDbusManager.OBJ_PATH)
mng_proxy = _NMDbus.bus.get_object(
_NMDbus.BUS_NAME, _NMDbusManager.OBJ_PATH
)
self.properties = dbus.Interface(mng_proxy, DBUS_STD_PROPERTIES_IFNAME)
self.interface = dbus.Interface(mng_proxy, _NMDbusManager.IF_NAME)
@ -87,7 +88,6 @@ def get_checkpoints():
class CheckPoint(object):
def __init__(self, timeout=60, autodestroy=True, dbuspath=None):
self._manager = nmdbus_manager()
self._timeout = timeout
@ -111,14 +111,16 @@ class CheckPoint(object):
devs = []
timeout = self._timeout
cp_flags = (
CHECKPOINT_CREATE_FLAG_DELETE_NEW_CONNECTIONS |
CHECKPOINT_CREATE_FLAG_DISCONNECT_NEW_DEVICES
CHECKPOINT_CREATE_FLAG_DELETE_NEW_CONNECTIONS
| CHECKPOINT_CREATE_FLAG_DISCONNECT_NEW_DEVICES
)
try:
dbuspath = self._manager.interface.CheckpointCreate(devs, timeout,
cp_flags)
logging.debug('Checkpoint %s created for all devices: %s',
dbuspath, timeout)
dbuspath = self._manager.interface.CheckpointCreate(
devs, timeout, cp_flags
)
logging.debug(
'Checkpoint %s created for all devices: %s', dbuspath, timeout
)
self._dbuspath = dbuspath
except dbus.exceptions.DBusException as e:
if e.get_dbus_name() == NM_PERMISSION_DENIED:
@ -135,12 +137,12 @@ class CheckPoint(object):
def rollback(self):
try:
result = self._manager.interface.CheckpointRollback(
self._dbuspath)
result = self._manager.interface.CheckpointRollback(self._dbuspath)
except dbus.exceptions.DBusException as e:
raise NMCheckPointError(str(e))
logging.debug('Checkpoint %s rollback executed: %s', self._dbuspath,
result)
logging.debug(
'Checkpoint %s rollback executed: %s', self._dbuspath, result
)
return result
@property

View File

@ -23,7 +23,6 @@ from .active_connection import ActiveConnection
class ConnectionProfile(object):
def __init__(self, profile=None):
self._con_profile = profile
self._nmclient = nmclient.client()
@ -94,8 +93,7 @@ class ConnectionProfile(object):
)
def activate(self):
self._mainloop.push_action(
self.safe_activate_async)
self._mainloop.push_action(self.safe_activate_async)
@property
def profile(self):
@ -136,9 +134,9 @@ class ConnectionProfile(object):
elif self.nmdevice:
self.import_by_device()
elif not self.profile:
err_msg = (
'Missing base properties: profile={}, id={}, dev={}'.format(
self.profile, self.con_id, self.devname)
err_format = 'Missing base properties: profile={}, id={}, dev={}'
err_msg = err_format.format(
self.profile, self.con_id, self.devname
)
self._mainloop.quit(err_msg)
@ -150,7 +148,9 @@ class ConnectionProfile(object):
if ac.is_activating:
logging.debug(
'Connection activation in progress: dev=%s, state=%s',
ac.devname, ac.state)
ac.devname,
ac.state,
)
self.waitfor_active_connection_async(ac)
return
@ -177,29 +177,40 @@ class ConnectionProfile(object):
if self._mainloop.is_action_canceled(e):
logging.debug(
'Connection activation canceled on %s %s: error=%s',
act_type, act_object, e)
act_type,
act_object,
e,
)
elif self._is_connection_unavailable(e):
logging.warning('Connection unavailable on %s %s, retrying',
act_type, act_object)
logging.warning(
'Connection unavailable on %s %s, retrying',
act_type,
act_object,
)
self._reset_profile()
self._mainloop.execute_last_action()
else:
self._mainloop.quit(
'Connection activation failed on {} {}: error={}'.format(
act_type, act_object, e))
act_type, act_object, e
)
)
return
if nm_act_con is None:
act_type, act_object = self._get_activation_metadata()
self._mainloop.quit(
'Connection activation failed on {} {}: error=unknown'.format(
act_type, act_object)
act_type, act_object
)
)
else:
devname = nm_act_con.props.connection.get_interface_name()
logging.debug(
'Connection activation initiated: dev=%s, con-state=%s',
devname, nm_act_con.props.state)
devname,
nm_act_con.props.state,
)
ac = ActiveConnection(nm_act_con)
if ac.is_active:
@ -209,14 +220,18 @@ class ConnectionProfile(object):
else:
self._mainloop.quit(
'Connection activation failed on {}: reason={}'.format(
ac.devname, ac.reason))
ac.devname, ac.reason
)
)
@staticmethod
def _is_connection_unavailable(err):
return (isinstance(err, nmclient.GLib.GError) and
err.domain == 'nm-manager-error-quark' and
err.code == 2 and
'is not available on the device' in err.message)
return (
isinstance(err, nmclient.GLib.GError)
and err.domain == 'nm-manager-error-quark'
and err.code == 2
and 'is not available on the device' in err.message
)
def _get_activation_metadata(self):
if self._nmdevice:
@ -233,19 +248,20 @@ class ConnectionProfile(object):
def waitfor_active_connection_async(self, ac):
ac.handlers.add(
ac.nm_active_connection.connect(
'state-changed', self._waitfor_active_connection_callback, ac)
'state-changed', self._waitfor_active_connection_callback, ac
)
)
def _waitfor_active_connection_callback(self,
_nm_act_con,
_state,
_reason,
ac):
def _waitfor_active_connection_callback(
self, _nm_act_con, _state, _reason, ac
):
ac.refresh_state()
if ac.is_active:
logging.debug(
'Connection activation succeeded: dev=%s, con-state=%s',
ac.devname, ac.state)
ac.devname,
ac.state,
)
for handler_id in ac.handlers:
ac.nm_active_connection.handler_disconnect(handler_id)
self._mainloop.execute_next_action()
@ -254,7 +270,9 @@ class ConnectionProfile(object):
ac.nm_active_connection.handler_disconnect(handler_id)
self._mainloop.quit(
'Connection activation failed on {}: reason={}'.format(
ac.devname, ac.reason))
ac.devname, ac.reason
)
)
@staticmethod
def _add_connection_callback(src_object, result, user_data):
@ -263,11 +281,9 @@ class ConnectionProfile(object):
con = src_object.add_connection_finish(result)
except Exception as e:
if mainloop.is_action_canceled(e):
logging.debug(
'Connection adding canceled: error=%s', e)
logging.debug('Connection adding canceled: error=%s', e)
else:
mainloop.quit(
'Connection adding failed: error={}'.format(e))
mainloop.quit('Connection adding failed: error={}'.format(e))
return
if con is None:
@ -287,12 +303,15 @@ class ConnectionProfile(object):
target = 'con/' + str(self.con_id)
if self._mainloop.is_action_canceled(e):
logging.debug('Connection deletion aborted on %s: error=%s',
target, e)
logging.debug(
'Connection deletion aborted on %s: error=%s', target, e
)
else:
self._mainloop.quit(
'Connection deletion failed on {}: error={}'.format(
target, e))
target, e
)
)
return
devname = src_object.get_interface_name()
@ -302,7 +321,8 @@ class ConnectionProfile(object):
else:
self._mainloop.quit(
'Connection deletion failed: '
'dev={}, error=unknown'.format(devname))
'dev={}, error=unknown'.format(devname)
)
@staticmethod
def _commit_changes_callback(src_object, result, user_data):
@ -315,7 +335,9 @@ class ConnectionProfile(object):
else:
mainloop.quit(
'Connection update failed: error={}, dev={}/{}'.format(
e, nmdev.props.interface, nmdev.props.state))
e, nmdev.props.interface, nmdev.props.state
)
)
return
devname = src_object.get_interface_name()
@ -323,15 +345,16 @@ class ConnectionProfile(object):
logging.debug('Connection update succeeded: dev=%s', devname)
mainloop.execute_next_action()
else:
mainloop.quit('Connection update failed: '
'dev={}, error=unknown'.format(devname))
mainloop.quit(
'Connection update failed: '
'dev={}, error=unknown'.format(devname)
)
def _reset_profile(self):
self._con_profile = None
class ConnectionSetting(object):
def __init__(self, con_setting=None):
self._setting = con_setting
@ -343,7 +366,8 @@ class ConnectionSetting(object):
con_setting.props.type = iface_type
con_setting.props.autoconnect = True
con_setting.props.autoconnect_slaves = (
nmclient.NM.SettingConnectionAutoconnectSlaves.YES)
nmclient.NM.SettingConnectionAutoconnectSlaves.YES
)
self._setting = con_setting
self._log_connection_info('ConnectionSetting.create')
@ -373,22 +397,24 @@ class ConnectionSetting(object):
def _log_connection_info(self, source):
setting = self._setting
logging.debug(
'Connection settings for %s:\n' +
'\n'.join([
'id: %s',
'iface: %s',
'uuid: %s',
'type: %s',
'autoconnect: %s',
'autoconnect_slaves: %s'
]),
'Connection settings for %s:\n'
+ '\n'.join(
[
'id: %s',
'iface: %s',
'uuid: %s',
'type: %s',
'autoconnect: %s',
'autoconnect_slaves: %s',
]
),
source,
setting.props.id,
setting.props.interface_name,
setting.props.uuid,
setting.props.type,
setting.props.autoconnect,
setting.props.autoconnect_slaves
setting.props.autoconnect_slaves,
)

View File

@ -81,7 +81,9 @@ def _wait_for_active_connection_async(dev, connection_profile):
if act_conn.is_activating:
logging.debug(
'Connection activation in progress: dev=%s, state=%s',
act_conn.devname, act_conn.state)
act_conn.devname,
act_conn.state,
)
conn = connection.ConnectionProfile(connection_profile)
conn.waitfor_active_connection_async(act_conn)
return True
@ -100,7 +102,8 @@ def _reapply_callback(src_object, result, user_data):
logging.debug('Device reapply aborted on %s: error=%s', devname, e)
else:
mainloop.quit(
'Device reapply failed on {}: error={}'.format(devname, e))
'Device reapply failed on {}: error={}'.format(devname, e)
)
return
if success:
@ -108,7 +111,8 @@ def _reapply_callback(src_object, result, user_data):
mainloop.execute_next_action()
else:
mainloop.quit(
'Device reapply failed: dev={}, error=unknown'.format(devname))
'Device reapply failed: dev={}, error=unknown'.format(devname)
)
def modify(dev, connection_profile):
@ -158,8 +162,12 @@ def _modify_callback(src_object, result, user_data):
if mainloop.is_action_canceled(e):
logging.debug('Device reapply aborted on %s: error=%s', devname, e)
else:
logging.debug('Device reapply failed on %s: error=%s\n'
'Fallback to device activation', devname, e)
logging.debug(
'Device reapply failed on %s: error=%s\n'
'Fallback to device activation',
devname,
e,
)
_activate_async(src_object)
return
@ -169,7 +177,9 @@ def _modify_callback(src_object, result, user_data):
else:
logging.debug(
'Device reapply failed, fallback to device activation: dev=%s, '
'error=unknown', devname)
'error=unknown',
devname,
)
_activate_async(src_object)
@ -179,9 +189,11 @@ def _requires_activation(dev, connection_profile):
if configured_mtu:
current_mtu = int(dev.get_mtu())
if configured_mtu != current_mtu:
logging.debug('Device reapply does not support mtu changes, '
'fallback to device activation: dev=%s',
dev.get_iface())
logging.debug(
'Device reapply does not support mtu changes, '
'fallback to device activation: dev=%s',
dev.get_iface(),
)
return True
return False
@ -207,9 +219,7 @@ def _safe_delete_device_async(nmdev):
user_data = mainloop, nmdev
nmdev.delete_async(
mainloop.cancellable,
_delete_device_callback,
user_data,
mainloop.cancellable, _delete_device_callback, user_data
)
@ -220,24 +230,34 @@ def _delete_device_callback(src_object, result, user_data):
# pylint: disable=catching-non-exception
except nmclient.GLib.GError as e:
# pylint: enable=catching-non-exception
if e.matches(nmclient.Gio.DBusError.quark(),
nmclient.Gio.DBusError.UNKNOWN_METHOD):
logging.debug('Device %s has been already deleted: error=%s',
nmdev.get_iface(), e)
if e.matches(
nmclient.Gio.DBusError.quark(),
nmclient.Gio.DBusError.UNKNOWN_METHOD,
):
logging.debug(
'Device %s has been already deleted: error=%s',
nmdev.get_iface(),
e,
)
mainloop.execute_next_action()
else:
mainloop.quit(
'Device deletion failed on {}: error={}'.format(
nmdev.get_iface(), e))
nmdev.get_iface(), e
)
)
return
except Exception as e:
if mainloop.is_action_canceled(e):
logging.debug('Device deletion aborted on %s: error=%s',
nmdev.get_iface(), e)
logging.debug(
'Device deletion aborted on %s: error=%s', nmdev.get_iface(), e
)
else:
mainloop.quit(
'Device deletion failed on {}: error={}'.format(
nmdev.get_iface(), e))
nmdev.get_iface(), e
)
)
return
devname = src_object.get_iface()
@ -246,7 +266,8 @@ def _delete_device_callback(src_object, result, user_data):
mainloop.execute_next_action()
else:
mainloop.quit(
'Device deletion failed: dev={}, error=unknown'.format(devname))
'Device deletion failed: dev={}, error=unknown'.format(devname)
)
def get_device_by_name(devname):

View File

@ -40,10 +40,7 @@ IPV6_ADDRESS_LENGTH = 128
def get_running():
dns_state = {
DNS.SERVER: [],
DNS.SEARCH: []
}
dns_state = {DNS.SERVER: [], DNS.SEARCH: []}
client = nmclient.client()
for dns_conf in client.get_dns_configuration():
iface_name = dns_conf.get_interface()
@ -54,7 +51,8 @@ def get_running():
# appended also.
raise NmstateInternalError(
'Missing interface for IPv6 link-local DNS server '
'entry {}'.format(ns))
'entry {}'.format(ns)
)
ns_addr = '{}%{}'.format(ns, iface_name)
else:
ns_addr = ns
@ -66,10 +64,7 @@ def get_running():
def get_config(acs_and_ipv4_profiles, acs_and_ipv6_profiles):
dns_conf = {
DNS.SERVER: [],
DNS.SEARCH: []
}
dns_conf = {DNS.SERVER: [], DNS.SEARCH: []}
tmp_dns_confs = []
for ac, ip_profile in chain(acs_and_ipv6_profiles, acs_and_ipv4_profiles):
if not ip_profile.props.dns and not ip_profile.props.dns_search:
@ -133,12 +128,15 @@ def find_interfaces_for_name_servers(iface_routes):
Return two interface names for IPv4 and IPv6 name servers.
The interface name will be None if failed to find proper interface.
"""
return (nm_route.get_static_gateway_iface(Interface.IPV4, iface_routes),
nm_route.get_static_gateway_iface(Interface.IPV6, iface_routes))
return (
nm_route.get_static_gateway_iface(Interface.IPV4, iface_routes),
nm_route.get_static_gateway_iface(Interface.IPV6, iface_routes),
)
def get_indexed_dns_config_by_iface(acs_and_ipv4_profiles,
acs_and_ipv6_profiles):
def get_indexed_dns_config_by_iface(
acs_and_ipv4_profiles, acs_and_ipv6_profiles
):
"""
Get current DNS config indexed by interface name.
Return dict like {
@ -160,13 +158,15 @@ def get_indexed_dns_config_by_iface(acs_and_ipv4_profiles,
for ac, ip_profile in acs_and_ipv6_profiles:
if ip_profile.props.dns or ip_profile.props.dns_search:
iface_name = nm_ac.ActiveConnection(ac).devname
iface_dns_configs[iface_name][Interface.IPV6] = (
_get_ip_profile_dns_config(ip_profile))
iface_dns_configs[iface_name][
Interface.IPV6
] = _get_ip_profile_dns_config(ip_profile)
for ac, ip_profile in acs_and_ipv4_profiles:
if ip_profile.props.dns or ip_profile.props.dns_search:
iface_name = nm_ac.ActiveConnection(ac).devname
iface_dns_configs[iface_name][Interface.IPV4] = (
_get_ip_profile_dns_config(ip_profile))
iface_dns_configs[iface_name][
Interface.IPV4
] = _get_ip_profile_dns_config(ip_profile)
return iface_dns_configs
@ -175,5 +175,5 @@ def _get_ip_profile_dns_config(ip_profile):
return {
DNS.SERVER: ip_profile.props.dns,
DNS.SEARCH: ip_profile.props.dns_search,
DNS_METADATA_PRIORITY: ip_profile.props.dns_priority
DNS_METADATA_PRIORITY: ip_profile.props.dns_priority,
}

View File

@ -44,33 +44,38 @@ def create_setting(config, base_con_profile):
if not setting_ipv4:
setting_ipv4 = nmclient.NM.SettingIP4Config.new()
setting_ipv4.props.method = (
nmclient.NM.SETTING_IP4_CONFIG_METHOD_DISABLED)
setting_ipv4.props.method = nmclient.NM.SETTING_IP4_CONFIG_METHOD_DISABLED
if config and config.get('enabled'):
if config.get('dhcp'):
setting_ipv4.props.method = (
nmclient.NM.SETTING_IP4_CONFIG_METHOD_AUTO)
setting_ipv4.props.ignore_auto_routes = (
not config.get('auto-routes', True))
setting_ipv4.props.never_default = (
not config.get('auto-gateway', True))
setting_ipv4.props.ignore_auto_dns = (
not config.get('auto-dns', True))
nmclient.NM.SETTING_IP4_CONFIG_METHOD_AUTO
)
setting_ipv4.props.ignore_auto_routes = not config.get(
'auto-routes', True
)
setting_ipv4.props.never_default = not config.get(
'auto-gateway', True
)
setting_ipv4.props.ignore_auto_dns = not config.get(
'auto-dns', True
)
elif config.get('address'):
setting_ipv4.props.method = (
nmclient.NM.SETTING_IP4_CONFIG_METHOD_MANUAL)
nmclient.NM.SETTING_IP4_CONFIG_METHOD_MANUAL
)
_add_addresses(setting_ipv4, config['address'])
nm_route.add_routes(
setting_ipv4, config.get(nm_route.ROUTE_METADATA, []))
setting_ipv4, config.get(nm_route.ROUTE_METADATA, [])
)
nm_dns.add_dns(setting_ipv4, config.get(nm_dns.DNS_METADATA, {}))
return setting_ipv4
def _add_addresses(setting_ipv4, addresses):
for address in addresses:
naddr = nmclient.NM.IPAddress.new(socket.AF_INET,
address['ip'],
address['prefix-length'])
naddr = nmclient.NM.IPAddress.new(
socket.AF_INET, address['ip'], address['prefix-length']
)
setting_ipv4.add_address(naddr)
@ -88,7 +93,8 @@ def get_info(active_connection):
ip_profile = get_ip_profile(active_connection)
if ip_profile:
info['dhcp'] = ip_profile.get_method() == (
nmclient.NM.SETTING_IP4_CONFIG_METHOD_AUTO)
nmclient.NM.SETTING_IP4_CONFIG_METHOD_AUTO
)
if info['dhcp']:
info['auto-routes'] = not ip_profile.props.ignore_auto_routes
info['auto-gateway'] = not ip_profile.props.never_default
@ -111,7 +117,7 @@ def get_info(active_connection):
addresses = [
{
'ip': address.get_address(),
'prefix-length': int(address.get_prefix())
'prefix-length': int(address.get_prefix()),
}
for address in ip4config.get_addresses()
]

View File

@ -68,7 +68,7 @@ def get_info(active_connection):
addresses = [
{
'ip': address.get_address(),
'prefix-length': int(address.get_prefix())
'prefix-length': int(address.get_prefix()),
}
for address in ipconfig.get_addresses()
]
@ -102,8 +102,7 @@ def create_setting(config, base_con_profile):
setting_ip = nmclient.NM.SettingIP6Config.new()
if not config or not config.get('enabled'):
setting_ip.props.method = (
nmclient.NM.SETTING_IP6_CONFIG_METHOD_IGNORE)
setting_ip.props.method = nmclient.NM.SETTING_IP6_CONFIG_METHOD_IGNORE
return setting_ip
is_dhcp = config.get('dhcp', False)
@ -112,17 +111,17 @@ def create_setting(config, base_con_profile):
if is_dhcp or is_autoconf:
_set_dynamic(setting_ip, is_dhcp, is_autoconf)
setting_ip.props.ignore_auto_routes = (
not config.get('auto-routes', True))
setting_ip.props.never_default = (
not config.get('auto-gateway', True))
setting_ip.props.ignore_auto_dns = (
not config.get('auto-dns', True))
setting_ip.props.ignore_auto_routes = not config.get(
'auto-routes', True
)
setting_ip.props.never_default = not config.get('auto-gateway', True)
setting_ip.props.ignore_auto_dns = not config.get('auto-dns', True)
elif ip_addresses:
_set_static(setting_ip, ip_addresses)
else:
setting_ip.props.method = (
nmclient.NM.SETTING_IP6_CONFIG_METHOD_LINK_LOCAL)
nmclient.NM.SETTING_IP6_CONFIG_METHOD_LINK_LOCAL
)
nm_route.add_routes(setting_ip, config.get(nm_route.ROUTE_METADATA, []))
nm_dns.add_dns(setting_ip, config.get(nm_dns.DNS_METADATA, {}))
@ -132,36 +131,37 @@ def create_setting(config, base_con_profile):
def _set_dynamic(setting_ip, is_dhcp, is_autoconf):
if not is_dhcp and is_autoconf:
raise NmstateNotImplementedError(
'Autoconf without DHCP is not supported yet')
'Autoconf without DHCP is not supported yet'
)
if is_dhcp and is_autoconf:
setting_ip.props.method = (
nmclient.NM.SETTING_IP6_CONFIG_METHOD_AUTO)
setting_ip.props.method = nmclient.NM.SETTING_IP6_CONFIG_METHOD_AUTO
elif is_dhcp and not is_autoconf:
setting_ip.props.method = (
nmclient.NM.SETTING_IP6_CONFIG_METHOD_DHCP)
setting_ip.props.method = nmclient.NM.SETTING_IP6_CONFIG_METHOD_DHCP
def _set_static(setting_ip, ip_addresses):
for address in ip_addresses:
if iplib.is_ipv6_link_local_addr(address['ip'],
address['prefix-length']):
logging.warning('IPv6 link local address '
'{a[ip]}/{a[prefix-length]} is ignored '
'when applying desired state'
.format(a=address))
if iplib.is_ipv6_link_local_addr(
address['ip'], address['prefix-length']
):
logging.warning(
'IPv6 link local address '
'{a[ip]}/{a[prefix-length]} is ignored '
'when applying desired state'.format(a=address)
)
else:
naddr = nmclient.NM.IPAddress.new(socket.AF_INET6,
address['ip'],
address['prefix-length'])
naddr = nmclient.NM.IPAddress.new(
socket.AF_INET6, address['ip'], address['prefix-length']
)
setting_ip.add_address(naddr)
if setting_ip.props.addresses:
setting_ip.props.method = (
nmclient.NM.SETTING_IP6_CONFIG_METHOD_MANUAL)
setting_ip.props.method = nmclient.NM.SETTING_IP6_CONFIG_METHOD_MANUAL
else:
setting_ip.props.method = (
nmclient.NM.SETTING_IP6_CONFIG_METHOD_LINK_LOCAL)
nmclient.NM.SETTING_IP6_CONFIG_METHOD_LINK_LOCAL
)
def get_ip_profile(active_connection):

View File

@ -23,9 +23,10 @@ import logging
import six
import gi
try:
gi.require_version('NM', '1.0') # NOQA: F402
from gi.repository import NM # pylint: disable=no-name-in-module
from gi.repository import NM # pylint: disable=no-name-in-module
except ValueError:
NM = None
@ -55,7 +56,8 @@ def client(refresh=False):
'Check the documentation for more information.'
)
raise error.NmstateDependencyError(
'Missing introspection data for libnm')
'Missing introspection data for libnm'
)
return _nmclient
@ -122,7 +124,8 @@ class _MainLoop(object):
def run(self, timeout):
if not isinstance(timeout, six.integer_types):
raise error.NmstateValueError(
"Invalid timeout value: should be an integer")
"Invalid timeout value: should be an integer"
)
if not self.actions_exists():
return _MainLoop.SUCCESS
@ -167,9 +170,11 @@ class _MainLoop(object):
self._cancel_cancellables()
def is_action_canceled(self, err):
return (isinstance(err, GLib.GError) and
err.domain == 'g-io-error-quark' and
err.code == Gio.IOErrorEnum.CANCELLED)
return (
isinstance(err, GLib.GError)
and err.domain == 'g-io-error-quark'
and err.code == Gio.IOErrorEnum.CANCELLED
)
@property
def error(self):
@ -180,9 +185,7 @@ class _MainLoop(object):
timeout_result = []
data = (self._mainloop, timeout_result)
timeout_id = GLib.timeout_add(
int(timeout * 1000),
_MainLoop._timeout_cb,
data
int(timeout * 1000), _MainLoop._timeout_cb, data
)
yield
if timeout_result:

View File

@ -33,12 +33,7 @@ PORT_PROFILE_PREFIX = 'ovs-port-'
CAPABILITY = 'openvswitch'
_BRIDGE_OPTION_NAMES = [
'fail-mode',
'mcast-snooping-enable',
'rstp',
'stp'
]
_BRIDGE_OPTION_NAMES = ['fail-mode', 'mcast-snooping-enable', 'rstp', 'stp']
_PORT_OPTION_NAMES = [
@ -47,7 +42,7 @@ _PORT_OPTION_NAMES = [
'bond-mode',
'lacp',
'bond-updelay',
'bond-downdelay'
'bond-downdelay',
]
@ -74,7 +69,9 @@ def create_bridge_setting(options):
else:
raise NmstateValueError(
'Invalid OVS bridge option: \{}\=\'{}\''.format(
option_name, option_value))
option_name, option_value
)
)
return bridge_setting
@ -97,7 +94,9 @@ def create_port_setting(options):
else:
raise NmstateValueError(
'Invalid OVS port option: \{}\=\'{}\''.format(
option_name, option_value))
option_name, option_value
)
)
return port_setting
@ -146,7 +145,7 @@ def get_ovs_info(bridge_device, devices_info):
return {
'port': _get_bridge_ports_info(port_profiles, devices_info),
'options': _get_bridge_options(bridge_device)
'options': _get_bridge_options(bridge_device),
}
@ -202,8 +201,9 @@ def _get_bridge_options(bridge_device):
bridge_options['stp'] = bridge_setting.props.stp_enable
bridge_options['rstp'] = bridge_setting.props.rstp_enable
bridge_options['fail-mode'] = bridge_setting.props.fail_mode or ''
bridge_options['mcast-snooping-enable'] = (
bridge_setting.props.mcast_snooping_enable)
bridge_options[
'mcast-snooping-enable'
] = bridge_setting.props.mcast_snooping_enable
return bridge_options

View File

@ -48,20 +48,21 @@ def get_running(acs_and_ip_cfgs):
if not iface_name:
raise NmstateInternalError(
'Got connection {} has not interface name'.format(
active_connection.get_id()))
active_connection.get_id()
)
)
for nm_route in ip_cfg.props.routes:
table_id = _get_per_route_table_id(
nm_route,
iplib.KERNEL_MAIN_ROUTE_TABLE_ID)
route_entry = _nm_route_to_route(
nm_route,
table_id,
iface_name)
nm_route, iplib.KERNEL_MAIN_ROUTE_TABLE_ID
)
route_entry = _nm_route_to_route(nm_route, table_id, iface_name)
if route_entry:
routes.append(route_entry)
routes.sort(key=itemgetter(Route.TABLE_ID,
Route.NEXT_HOP_INTERFACE,
Route.DESTINATION))
routes.sort(
key=itemgetter(
Route.TABLE_ID, Route.NEXT_HOP_INTERFACE, Route.DESTINATION
)
)
return routes
@ -81,7 +82,9 @@ def get_config(acs_and_ip_profiles):
if not iface_name:
raise NmstateInternalError(
'Got connection {} has not interface name'.format(
active_connection.get_id()))
active_connection.get_id()
)
)
default_table_id = ip_profile.props.route_table
if gateway:
routes.append(
@ -89,7 +92,9 @@ def get_config(acs_and_ip_profiles):
gateway,
ip_profile.props.route_metric,
default_table_id,
iface_name))
iface_name,
)
)
# NM supports multiple route table in single profile:
# https://bugzilla.redhat.com/show_bug.cgi?id=1436531
# The `ipv4.route-table` and `ipv6.route-table` will be the default
@ -97,15 +102,14 @@ def get_config(acs_and_ip_profiles):
# still specify route table id.
for nm_route in nm_routes:
table_id = _get_per_route_table_id(nm_route, default_table_id)
route_entry = _nm_route_to_route(
nm_route,
table_id,
iface_name)
route_entry = _nm_route_to_route(nm_route, table_id, iface_name)
if route_entry:
routes.append(route_entry)
routes.sort(key=itemgetter(Route.TABLE_ID,
Route.NEXT_HOP_INTERFACE,
Route.DESTINATION))
routes.sort(
key=itemgetter(
Route.TABLE_ID, Route.NEXT_HOP_INTERFACE, Route.DESTINATION
)
)
return routes
@ -116,7 +120,8 @@ def _get_per_route_table_id(nm_route, default_table_id):
def _nm_route_to_route(nm_route, table_id, iface_name):
dst = '{ip}/{prefix}'.format(
ip=nm_route.get_dest(), prefix=nm_route.get_prefix())
ip=nm_route.get_dest(), prefix=nm_route.get_prefix()
)
next_hop = nm_route.get_next_hop() or ''
metric = int(nm_route.get_metric())
@ -145,13 +150,16 @@ def _get_default_route_config(gateway, metric, default_table_id, iface_name):
def add_routes(setting_ip, routes):
for route in routes:
if route[Route.DESTINATION] in (IPV4_DEFAULT_GATEWAY_DESTINATION,
IPV6_DEFAULT_GATEWAY_DESTINATION):
if route[Route.DESTINATION] in (
IPV4_DEFAULT_GATEWAY_DESTINATION,
IPV6_DEFAULT_GATEWAY_DESTINATION,
):
if setting_ip.get_gateway():
raise NmstateNotImplementedError(
'Only a single default gateway is supported due to a '
'limitation of NetworkManager: '
'https://bugzilla.redhat.com/1707396')
'https://bugzilla.redhat.com/1707396'
)
_add_route_gateway(setting_ip, route)
else:
_add_specfic_route(setting_ip, route)
@ -166,21 +174,25 @@ def _add_specfic_route(setting_ip, route):
family = socket.AF_INET
metric = route.get(Route.METRIC, Route.USE_DEFAULT_METRIC)
next_hop = route[Route.NEXT_HOP_ADDRESS]
ip_route = nmclient.NM.IPRoute.new(family, destination, prefix_len,
next_hop, metric)
ip_route = nmclient.NM.IPRoute.new(
family, destination, prefix_len, next_hop, metric
)
table_id = route.get(Route.TABLE_ID, Route.USE_DEFAULT_ROUTE_TABLE)
ip_route.set_attribute(NM_ROUTE_TABLE_ATTRIBUTE,
nmclient.GLib.Variant.new_uint32(table_id))
ip_route.set_attribute(
NM_ROUTE_TABLE_ATTRIBUTE, nmclient.GLib.Variant.new_uint32(table_id)
)
# Duplicate route entry will be ignored by libnm.
setting_ip.add_route(ip_route)
def _add_route_gateway(setting_ip, route):
setting_ip.props.gateway = route[Route.NEXT_HOP_ADDRESS]
setting_ip.props.route_table = route.get(Route.TABLE_ID,
Route.USE_DEFAULT_ROUTE_TABLE)
setting_ip.props.route_metric = route.get(Route.METRIC,
Route.USE_DEFAULT_METRIC)
setting_ip.props.route_table = route.get(
Route.TABLE_ID, Route.USE_DEFAULT_ROUTE_TABLE
)
setting_ip.props.route_metric = route.get(
Route.METRIC, Route.USE_DEFAULT_METRIC
)
def get_static_gateway_iface(family, iface_routes):
@ -188,9 +200,11 @@ def get_static_gateway_iface(family, iface_routes):
Return one interface with gateway for given IP family.
Return None if not found.
"""
destination = (IPV6_DEFAULT_GATEWAY_DESTINATION
if family == Interface.IPV6
else IPV4_DEFAULT_GATEWAY_DESTINATION)
destination = (
IPV6_DEFAULT_GATEWAY_DESTINATION
if family == Interface.IPV6
else IPV4_DEFAULT_GATEWAY_DESTINATION
)
for iface_name, routes in six.viewitems(iface_routes):
for route in routes:
if route[Route.DESTINATION] == destination:

View File

@ -48,12 +48,14 @@ class Api2Nm(object):
'linux-bridge': nmclient.NM.SETTING_BRIDGE_SETTING_NAME,
}
try:
Api2Nm._iface_types_map.update({
ovs_types = {
'ovs-bridge': nmclient.NM.SETTING_OVS_BRIDGE_SETTING_NAME,
'ovs-port': nmclient.NM.SETTING_OVS_PORT_SETTING_NAME,
'ovs-interface': (
nmclient.NM.SETTING_OVS_INTERFACE_SETTING_NAME),
})
nmclient.NM.SETTING_OVS_INTERFACE_SETTING_NAME
),
}
Api2Nm._iface_types_map.update(ovs_types)
except AttributeError:
pass
@ -97,19 +99,19 @@ class Nm2Api(object):
bond_mode = bond_options['mode']
del bond_options['mode']
return {
'link-aggregation':
{
'mode': bond_mode,
'slaves': [slave.props.interface for slave in bond_slaves],
'options': bond_options
}
'link-aggregation': {
'mode': bond_mode,
'slaves': [slave.props.interface for slave in bond_slaves],
'options': bond_options,
}
}
@staticmethod
def get_iface_type(name):
if Nm2Api._iface_types_map is None:
Nm2Api._iface_types_map = Nm2Api._swap_dict_keyval(
Api2Nm.get_iface_type_map())
Api2Nm.get_iface_type_map()
)
return Nm2Api._iface_types_map.get(name, IFACE_TYPE_UNKNOWN)
@staticmethod

View File

@ -39,7 +39,8 @@ def create_setting(iface_state, base_con_profile):
user_setting = None
if base_con_profile:
user_setting = base_con_profile.get_setting_by_name(
nmclient.NM.SETTING_USER_SETTING_NAME)
nmclient.NM.SETTING_USER_SETTING_NAME
)
if user_setting:
user_setting = user_setting.duplicate()
@ -63,7 +64,8 @@ def get_info(device):
try:
user_setting = connection.profile.get_setting_by_name(
nmclient.NM.SETTING_USER_SETTING_NAME)
nmclient.NM.SETTING_USER_SETTING_NAME
)
description = user_setting.get_data(NMSTATE_DESCRIPTION)
if description:
info['description'] = description

View File

@ -52,6 +52,6 @@ def get_info(device):
if device.get_device_type() == nmclient.NM.DeviceType.VLAN:
info['vlan'] = {
'id': device.props.vlan_id,
'base-iface': device.props.parent.get_iface()
'base-iface': device.props.parent.get_iface(),
}
return info

View File

@ -45,11 +45,11 @@ class WiredSetting(object):
def __bool__(self):
return bool(
self.mac or
self.mtu or
self.speed or
self.duplex or
(self.auto_negotiation is not None)
self.mac
or self.mtu
or self.speed
or self.duplex
or (self.auto_negotiation is not None)
)
# TODO: drop when py2 is no longer needed
@ -61,7 +61,7 @@ class WiredSetting(object):
self.mac,
self.speed,
self.duplex,
self.auto_negotiation
self.auto_negotiation,
)

View File

@ -88,6 +88,7 @@ commands =
-S \
--check \
{posargs} \
libnmstate/nm \
tests
[testenv:pylint]