|
Packit Service |
0535c1 |
#
|
|
Packit Service |
0535c1 |
# Copyright (c) 2019-2020 Red Hat, Inc.
|
|
Packit Service |
0535c1 |
#
|
|
Packit Service |
0535c1 |
# This file is part of nmstate
|
|
Packit Service |
0535c1 |
#
|
|
Packit Service |
0535c1 |
# This program is free software: you can redistribute it and/or modify
|
|
Packit Service |
0535c1 |
# it under the terms of the GNU Lesser General Public License as published by
|
|
Packit Service |
0535c1 |
# the Free Software Foundation, either version 2.1 of the License, or
|
|
Packit Service |
0535c1 |
# (at your option) any later version.
|
|
Packit Service |
0535c1 |
#
|
|
Packit Service |
0535c1 |
# This program is distributed in the hope that it will be useful,
|
|
Packit Service |
0535c1 |
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
Packit Service |
0535c1 |
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
Packit Service |
0535c1 |
# GNU Lesser General Public License for more details.
|
|
Packit Service |
0535c1 |
#
|
|
Packit Service |
0535c1 |
# You should have received a copy of the GNU Lesser General Public License
|
|
Packit Service |
0535c1 |
# along with this program. If not, see <https://www.gnu.org/licenses/>.
|
|
Packit Service |
0535c1 |
#
|
|
Packit Service |
0535c1 |
|
|
Packit Service |
0535c1 |
import logging
|
|
Packit Service |
0535c1 |
|
|
Packit Service |
0535c1 |
from libnmstate.error import NmstateLibnmError
|
|
Packit Service |
0535c1 |
|
|
Packit Service |
0535c1 |
from .common import GLib
|
|
Packit Service |
0535c1 |
from .common import GObject
|
|
Packit Service |
0535c1 |
from .common import NM
|
|
Packit Service |
0535c1 |
|
|
Packit Service |
0535c1 |
|
|
Packit Service |
0535c1 |
NM_AC_STATE_CHANGED_SIGNAL = "state-changed"
|
|
Packit Service |
0535c1 |
|
|
Packit Service |
0535c1 |
|
|
Packit Service |
0535c1 |
class ActivationError(Exception):
|
|
Packit Service |
0535c1 |
pass
|
|
Packit Service |
0535c1 |
|
|
Packit Service |
0535c1 |
|
|
Packit Service |
0535c1 |
class ActiveConnection:
|
|
Packit Service |
0535c1 |
def __init__(self, context=None, nm_ac_con=None):
|
|
Packit Service |
0535c1 |
self._ctx = context
|
|
Packit Service |
0535c1 |
self._act_con = nm_ac_con
|
|
Packit Service |
0535c1 |
|
|
Packit Service |
0535c1 |
nmdevs = None
|
|
Packit Service |
0535c1 |
if nm_ac_con:
|
|
Packit Service |
0535c1 |
nmdevs = nm_ac_con.get_devices()
|
|
Packit Service |
0535c1 |
self._nmdev = nmdevs[0] if nmdevs else None
|
|
Packit Service |
0535c1 |
|
|
Packit Service |
0535c1 |
def import_by_device(self, nmdev=None):
|
|
Packit Service |
0535c1 |
assert self._act_con is None
|
|
Packit Service |
0535c1 |
|
|
Packit Service |
0535c1 |
if nmdev:
|
|
Packit Service |
0535c1 |
self._nmdev = nmdev
|
|
Packit Service |
0535c1 |
if self._nmdev:
|
|
Packit Service |
0535c1 |
self._act_con = self._nmdev.get_active_connection()
|
|
Packit Service |
0535c1 |
|
|
Packit Service |
0535c1 |
def deactivate(self):
|
|
Packit Service |
0535c1 |
"""
|
|
Packit Service |
0535c1 |
Deactivating the current active connection,
|
|
Packit Service |
0535c1 |
The profile itself is not removed.
|
|
Packit Service |
0535c1 |
|
|
Packit Service |
0535c1 |
For software devices, deactivation removes the devices from the kernel.
|
|
Packit Service |
0535c1 |
"""
|
|
Packit Service |
0535c1 |
act_connection = self._nmdev.get_active_connection()
|
|
Packit Service |
0535c1 |
if (
|
|
Packit Service |
0535c1 |
not act_connection
|
|
Packit Service |
0535c1 |
or act_connection.props.state
|
|
Packit Service |
0535c1 |
== NM.ActiveConnectionState.DEACTIVATED
|
|
Packit Service |
0535c1 |
):
|
|
Packit Service |
0535c1 |
return
|
|
Packit Service |
0535c1 |
|
|
Packit Service |
0535c1 |
if self._act_con != act_connection:
|
|
Packit Service |
0535c1 |
raise NmstateLibnmError(
|
|
Packit Service |
0535c1 |
"When deactivating active connection, the newly get "
|
|
Packit Service |
0535c1 |
f"NM.ActiveConnection {act_connection}"
|
|
Packit Service |
0535c1 |
f"is different from original request: {self._act_con}"
|
|
Packit Service |
0535c1 |
)
|
|
Packit Service |
0535c1 |
|
|
Packit Service |
0535c1 |
action = f"Deactivate profile: {self.devname}"
|
|
Packit Service |
0535c1 |
self._ctx.register_async(action)
|
|
Packit Service |
0535c1 |
handler_id = act_connection.connect(
|
|
Packit Service |
0535c1 |
NM_AC_STATE_CHANGED_SIGNAL,
|
|
Packit Service |
0535c1 |
self._wait_state_changed_callback,
|
|
Packit Service |
0535c1 |
action,
|
|
Packit Service |
0535c1 |
)
|
|
Packit Service |
0535c1 |
if act_connection.props.state != NM.ActiveConnectionState.DEACTIVATING:
|
|
Packit Service |
0535c1 |
user_data = (handler_id, action)
|
|
Packit Service |
0535c1 |
self._ctx.client.deactivate_connection_async(
|
|
Packit Service |
0535c1 |
act_connection,
|
|
Packit Service |
0535c1 |
self._ctx.cancellable,
|
|
Packit Service |
0535c1 |
self._deactivate_connection_callback,
|
|
Packit Service |
0535c1 |
user_data,
|
|
Packit Service |
0535c1 |
)
|
|
Packit Service |
0535c1 |
|
|
Packit Service |
0535c1 |
def _wait_state_changed_callback(self, act_con, state, reason, action):
|
|
Packit Service |
0535c1 |
if self._ctx.is_cancelled():
|
|
Packit Service |
0535c1 |
return
|
|
Packit Service |
0535c1 |
if act_con.props.state == NM.ActiveConnectionState.DEACTIVATED:
|
|
Packit Service |
0535c1 |
logging.debug(
|
|
Packit Service |
0535c1 |
"Connection deactivation succeeded on %s", self.devname,
|
|
Packit Service |
0535c1 |
)
|
|
Packit Service |
0535c1 |
self._ctx.finish_async(action)
|
|
Packit Service |
0535c1 |
|
|
Packit Service |
0535c1 |
def _deactivate_connection_callback(self, src_object, result, user_data):
|
|
Packit Service |
0535c1 |
handler_id, action = user_data
|
|
Packit Service |
0535c1 |
if self._ctx.is_cancelled():
|
|
Packit Service |
0535c1 |
if self._act_con:
|
|
Packit Service |
0535c1 |
self._act_con.handler_disconnect(handler_id)
|
|
Packit Service |
0535c1 |
return
|
|
Packit Service |
0535c1 |
|
|
Packit Service |
0535c1 |
try:
|
|
Packit Service |
0535c1 |
success = src_object.deactivate_connection_finish(result)
|
|
Packit Service |
0535c1 |
except GLib.Error as e:
|
|
Packit Service |
0535c1 |
if e.matches(
|
|
Packit Service |
0535c1 |
NM.ManagerError.quark(), NM.ManagerError.CONNECTIONNOTACTIVE
|
|
Packit Service |
0535c1 |
):
|
|
Packit Service |
0535c1 |
success = True
|
|
Packit Service |
0535c1 |
logging.debug(
|
|
Packit Service |
0535c1 |
"Connection is not active on {}, no need to "
|
|
Packit Service |
0535c1 |
"deactivate".format(self.devname)
|
|
Packit Service |
0535c1 |
)
|
|
Packit Service |
0535c1 |
else:
|
|
Packit Service |
0535c1 |
if self._act_con:
|
|
Packit Service |
0535c1 |
self._act_con.handler_disconnect(handler_id)
|
|
Packit Service |
0535c1 |
self._ctx.fail(
|
|
Packit Service |
0535c1 |
NmstateLibnmError(f"{action} failed: error={e}")
|
|
Packit Service |
0535c1 |
)
|
|
Packit Service |
0535c1 |
return
|
|
Packit Service |
0535c1 |
except Exception as e:
|
|
Packit Service |
0535c1 |
if self._act_con:
|
|
Packit Service |
0535c1 |
self._act_con.handler_disconnect(handler_id)
|
|
Packit Service |
0535c1 |
self._ctx.fail(
|
|
Packit Service |
0535c1 |
NmstateLibnmError(
|
|
Packit Service |
0535c1 |
f"BUG: Unexpected error when activating {self.devname} "
|
|
Packit Service |
0535c1 |
f"error={e}"
|
|
Packit Service |
0535c1 |
)
|
|
Packit Service |
0535c1 |
)
|
|
Packit Service |
0535c1 |
return
|
|
Packit Service |
0535c1 |
|
|
Packit Service |
0535c1 |
if not success:
|
|
Packit Service |
0535c1 |
if self._act_con:
|
|
Packit Service |
0535c1 |
self._act_con.handler_disconnect(handler_id)
|
|
Packit Service |
0535c1 |
self._ctx.fail(
|
|
Packit Service |
0535c1 |
NmstateLibnmError(
|
|
Packit Service |
0535c1 |
f"{action} failed: error='None returned from "
|
|
Packit Service |
0535c1 |
"deactivate_connection_finish()'"
|
|
Packit Service |
0535c1 |
)
|
|
Packit Service |
0535c1 |
)
|
|
Packit Service |
0535c1 |
|
|
Packit Service |
0535c1 |
@property
|
|
Packit Service |
0535c1 |
def nm_active_connection(self):
|
|
Packit Service |
0535c1 |
return self._act_con
|
|
Packit Service |
0535c1 |
|
|
Packit Service |
0535c1 |
@property
|
|
Packit Service |
0535c1 |
def devname(self):
|
|
Packit Service |
0535c1 |
if self._nmdev:
|
|
Packit Service |
0535c1 |
return self._nmdev.get_iface()
|
|
Packit Service |
0535c1 |
else:
|
|
Packit Service |
0535c1 |
return None
|
|
Packit Service |
0535c1 |
|
|
Packit Service |
0535c1 |
@property
|
|
Packit Service |
0535c1 |
def nmdevice(self):
|
|
Packit Service |
0535c1 |
return self._nmdev
|
|
Packit Service |
0535c1 |
|
|
Packit Service |
0535c1 |
@nmdevice.setter
|
|
Packit Service |
0535c1 |
def nmdevice(self, nmdev):
|
|
Packit Service |
0535c1 |
assert self._nmdev is None
|
|
Packit Service |
0535c1 |
self._nmdev = nmdev
|
|
Packit Service |
0535c1 |
|
|
Packit Service |
0535c1 |
|
|
Packit Service |
0535c1 |
def _is_device_master_type(nmdev):
|
|
Packit Service |
0535c1 |
if nmdev:
|
|
Packit Service |
0535c1 |
is_master_type = (
|
|
Packit Service |
0535c1 |
GObject.type_is_a(nmdev, NM.DeviceBond)
|
|
Packit Service |
0535c1 |
or GObject.type_is_a(nmdev, NM.DeviceBridge)
|
|
Packit Service |
0535c1 |
or GObject.type_is_a(nmdev, NM.DeviceTeam)
|
|
Packit Service |
0535c1 |
or GObject.type_is_a(nmdev, NM.DeviceOvsBridge)
|
|
Packit Service |
0535c1 |
)
|
|
Packit Service |
0535c1 |
return is_master_type
|
|
Packit Service |
0535c1 |
return False
|