black: Cover libnmstate/nm
Signed-off-by: Edward Haas <edwardh@redhat.com>
This commit is contained in:
parent
339fd1b754
commit
e5b86c0c0e
@ -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
|
||||
|
@ -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)
|
||||
|
@ -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):
|
||||
|
@ -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
|
||||
|
||||
|
@ -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
|
||||
|
@ -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,
|
||||
)
|
||||
|
||||
|
||||
|
@ -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):
|
||||
|
@ -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,
|
||||
}
|
||||
|
@ -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()
|
||||
]
|
||||
|
@ -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):
|
||||
|
@ -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:
|
||||
|
@ -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
|
||||
|
||||
|
@ -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:
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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,
|
||||
)
|
||||
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user