1076 lines
42 KiB
Diff
1076 lines
42 KiB
Diff
diff -Nur nmstate-1.3.3.old/libnmstate/dns.py nmstate-1.3.3/libnmstate/dns.py
|
|
--- nmstate-1.3.3.old/libnmstate/dns.py 2022-08-11 23:22:22.000000000 +0800
|
|
+++ nmstate-1.3.3/libnmstate/dns.py 2023-02-15 15:48:33.668708842 +0800
|
|
@@ -144,6 +144,7 @@
|
|
Find interface to store the DNS configurations in the order of:
|
|
* Any interface with static gateway
|
|
* Any interface configured as dynamic IP with 'auto-dns:False'
|
|
+ The loopback interface is ignored.
|
|
Return tuple: (ipv4_iface, ipv6_iface)
|
|
"""
|
|
ipv4_iface, ipv6_iface = self._find_ifaces_with_static_gateways(
|
|
@@ -168,6 +169,8 @@
|
|
ipv4_iface = None
|
|
ipv6_iface = None
|
|
for iface_name, route_set in route_state.config_iface_routes.items():
|
|
+ if iface_name == "lo":
|
|
+ continue
|
|
for route in route_set:
|
|
if ipv4_iface and ipv6_iface:
|
|
return (ipv4_iface, ipv6_iface)
|
|
diff -Nur nmstate-1.3.3.old/libnmstate/ifaces/base_iface.py nmstate-1.3.3/libnmstate/ifaces/base_iface.py
|
|
--- nmstate-1.3.3.old/libnmstate/ifaces/base_iface.py 2023-02-15 15:48:11.745846015 +0800
|
|
+++ nmstate-1.3.3/libnmstate/ifaces/base_iface.py 2023-02-15 15:48:45.118768209 +0800
|
|
@@ -61,6 +61,7 @@
|
|
InterfaceIP.AUTO_ROUTES,
|
|
InterfaceIP.AUTO_GATEWAY,
|
|
InterfaceIP.AUTO_DNS,
|
|
+ InterfaceIP.AUTO_ROUTE_METRIC,
|
|
):
|
|
self._info.pop(dhcp_option, None)
|
|
|
|
@@ -123,7 +124,6 @@
|
|
|
|
|
|
class BaseIface:
|
|
- CONTROLLER_METADATA = "_controller"
|
|
CONTROLLER_TYPE_METADATA = "_controller_type"
|
|
DNS_METADATA = "_dns"
|
|
ROUTES_METADATA = "_routes"
|
|
@@ -253,7 +253,6 @@
|
|
self.ip_state(family).validate(
|
|
IPState(family, self._origin_info.get(family, {}))
|
|
)
|
|
- self._validate_port_ip()
|
|
ip_state = self.ip_state(family)
|
|
ip_state.remove_link_local_address()
|
|
self._info[family] = ip_state.to_dict()
|
|
@@ -302,7 +301,7 @@
|
|
if current_external_ids:
|
|
other._info[OvsDB.OVS_DB_SUBTREE].pop(OvsDB.EXTERNAL_IDS)
|
|
|
|
- def _validate_port_ip(self):
|
|
+ def validate_port_ip(self):
|
|
for family in (Interface.IPV4, Interface.IPV6):
|
|
ip_state = IPState(family, self._origin_info.get(family, {}))
|
|
if (
|
|
@@ -356,10 +355,11 @@
|
|
return False
|
|
|
|
def set_controller(self, controller_iface_name, controller_type):
|
|
- self._info[BaseIface.CONTROLLER_METADATA] = controller_iface_name
|
|
+ self._info[Interface.CONTROLLER] = controller_iface_name
|
|
self._info[BaseIface.CONTROLLER_TYPE_METADATA] = controller_type
|
|
if (
|
|
- not self.can_have_ip_as_port
|
|
+ controller_iface_name
|
|
+ and not self.can_have_ip_as_port
|
|
and controller_type != InterfaceType.VRF
|
|
):
|
|
for family in (Interface.IPV4, Interface.IPV6):
|
|
@@ -367,7 +367,7 @@
|
|
|
|
@property
|
|
def controller(self):
|
|
- return self._info.get(BaseIface.CONTROLLER_METADATA)
|
|
+ return self._info.get(Interface.CONTROLLER)
|
|
|
|
@property
|
|
def controller_type(self):
|
|
@@ -378,7 +378,8 @@
|
|
for port_name in self.port:
|
|
port_iface = ifaces.all_kernel_ifaces.get(port_name)
|
|
if port_iface:
|
|
- port_iface.set_controller(self.name, self.type)
|
|
+ if port_iface.controller != "":
|
|
+ port_iface.set_controller(self.name, self.type)
|
|
|
|
def update(self, info):
|
|
self._info.update(info)
|
|
@@ -444,6 +445,8 @@
|
|
state[Interface.STATE] = InterfaceState.DOWN
|
|
_convert_ovs_external_ids_values_to_string(state)
|
|
state.pop(BaseIface.PERMANENT_MAC_ADDRESS_METADATA, None)
|
|
+ if self.controller == "":
|
|
+ state.pop(Interface.CONTROLLER, None)
|
|
|
|
return state
|
|
|
|
diff -Nur nmstate-1.3.3.old/libnmstate/ifaces/ethtool.py nmstate-1.3.3/libnmstate/ifaces/ethtool.py
|
|
--- nmstate-1.3.3.old/libnmstate/ifaces/ethtool.py 2022-08-11 23:22:22.000000000 +0800
|
|
+++ nmstate-1.3.3/libnmstate/ifaces/ethtool.py 2023-02-15 15:48:33.672042194 +0800
|
|
@@ -176,6 +176,7 @@
|
|
"rx-ntuple-filter",
|
|
"rx-vlan-hw-parse",
|
|
"tx-vlan-hw-insert",
|
|
+ "highdma",
|
|
}
|
|
|
|
def __init__(self, feature_info):
|
|
diff -Nur nmstate-1.3.3.old/libnmstate/ifaces/ifaces.py nmstate-1.3.3/libnmstate/ifaces/ifaces.py
|
|
--- nmstate-1.3.3.old/libnmstate/ifaces/ifaces.py 2022-08-11 23:22:22.000000000 +0800
|
|
+++ nmstate-1.3.3/libnmstate/ifaces/ifaces.py 2023-02-15 15:48:45.118768209 +0800
|
|
@@ -1,22 +1,6 @@
|
|
-#
|
|
-# Copyright (c) 2020-2021 Red Hat, Inc.
|
|
-#
|
|
-# This file is part of nmstate
|
|
-#
|
|
-# This program is free software: you can redistribute it and/or modify
|
|
-# it under the terms of the GNU Lesser General Public License as published by
|
|
-# the Free Software Foundation, either version 2.1 of the License, or
|
|
-# (at your option) any later version.
|
|
-#
|
|
-# This program is distributed in the hope that it will be useful,
|
|
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
-# GNU Lesser General Public License for more details.
|
|
-#
|
|
-# You should have received a copy of the GNU Lesser General Public License
|
|
-# along with this program. If not, see <https://www.gnu.org/licenses/>.
|
|
-#
|
|
+# SPDX-License-Identifier: LGPL-2.1-or-later
|
|
|
|
+from copy import deepcopy
|
|
import logging
|
|
|
|
from libnmstate.error import NmstateKernelIntegerRoundedError
|
|
@@ -24,6 +8,7 @@
|
|
from libnmstate.error import NmstateVerificationError
|
|
from libnmstate.prettystate import format_desired_current_state_diff
|
|
from libnmstate.schema import BondMode
|
|
+from libnmstate.schema import Ethernet
|
|
from libnmstate.schema import Interface
|
|
from libnmstate.schema import InterfaceType
|
|
from libnmstate.schema import InterfaceState
|
|
@@ -97,18 +82,20 @@
|
|
self._cur_user_space_ifaces = _UserSpaceIfaces()
|
|
if cur_iface_infos:
|
|
for iface_info in cur_iface_infos:
|
|
- cur_iface = _to_specific_iface_obj(iface_info, save_to_disk)
|
|
+ cur_iface = _to_specific_iface_obj(
|
|
+ deepcopy(iface_info), save_to_disk
|
|
+ )
|
|
if cur_iface.is_user_space_only:
|
|
- self._user_space_ifaces.set(cur_iface)
|
|
+ self._user_space_ifaces.set(deepcopy(cur_iface))
|
|
self._cur_user_space_ifaces.set(cur_iface)
|
|
else:
|
|
- self._kernel_ifaces[cur_iface.name] = cur_iface
|
|
+ self._kernel_ifaces[cur_iface.name] = deepcopy(cur_iface)
|
|
self._cur_kernel_ifaces[cur_iface.name] = cur_iface
|
|
|
|
if des_iface_infos:
|
|
for iface_info in des_iface_infos:
|
|
iface = BaseIface(iface_info, save_to_disk)
|
|
- if not iface.is_up and self._gen_conf_mode:
|
|
+ if not (iface.is_up or iface.is_down) and self._gen_conf_mode:
|
|
continue
|
|
if iface.type == InterfaceType.UNKNOWN:
|
|
cur_ifaces = self._get_cur_ifaces(iface.name)
|
|
@@ -157,6 +144,7 @@
|
|
self._validate_infiniband_as_bridge_port()
|
|
self._validate_infiniband_as_bond_port()
|
|
self._apply_copy_mac_from()
|
|
+ self._validate_controller_and_port_list_conflict()
|
|
self.gen_metadata()
|
|
for iface in self.all_ifaces():
|
|
if iface.is_desired and iface.is_up:
|
|
@@ -164,6 +152,67 @@
|
|
|
|
self._pre_edit_validation_and_cleanup()
|
|
|
|
+ # Return True when SR-IOV `total-vfs` changed and having interface not
|
|
+ # exists in current.
|
|
+ def has_vf_count_change_and_missing_eth(self):
|
|
+ return self._has_vf_count_change() and self._has_missing_veth()
|
|
+
|
|
+ def _has_vf_count_change(self):
|
|
+ for iface in self.all_kernel_ifaces.values():
|
|
+ cur_iface = self._cur_kernel_ifaces.get(iface.name)
|
|
+ if (
|
|
+ cur_iface
|
|
+ and iface.is_desired
|
|
+ and iface.is_up
|
|
+ and iface.type == InterfaceType.ETHERNET
|
|
+ ):
|
|
+ des_vf_count = (
|
|
+ iface.original_desire_dict.get(Ethernet.CONFIG_SUBTREE, {})
|
|
+ .get(Ethernet.SRIOV_SUBTREE, {})
|
|
+ .get(Ethernet.SRIOV.TOTAL_VFS, 0)
|
|
+ )
|
|
+ cur_vf_count = (
|
|
+ cur_iface.raw.get(Ethernet.CONFIG_SUBTREE, {})
|
|
+ .get(Ethernet.SRIOV_SUBTREE, {})
|
|
+ .get(Ethernet.SRIOV.TOTAL_VFS, 0)
|
|
+ )
|
|
+ if des_vf_count != cur_vf_count:
|
|
+ return True
|
|
+ return False
|
|
+
|
|
+ def _has_missing_veth(self):
|
|
+ for iface in self.all_kernel_ifaces.values():
|
|
+ cur_iface = self._cur_kernel_ifaces.get(iface.name)
|
|
+ if cur_iface is None and iface.type == InterfaceType.ETHERNET:
|
|
+ return True
|
|
+ return False
|
|
+
|
|
+ # Return list of cloned iface_info(dictionary) which SRIOV PF conf only.
|
|
+ def get_sriov_pf_ifaces(self):
|
|
+ sriov_ifaces = []
|
|
+ for iface in self.all_kernel_ifaces.values():
|
|
+ if (
|
|
+ iface.is_desired
|
|
+ and iface.is_up
|
|
+ and iface.type == InterfaceType.ETHERNET
|
|
+ ):
|
|
+ sriov_conf = iface.original_desire_dict.get(
|
|
+ Ethernet.CONFIG_SUBTREE, {}
|
|
+ ).get(Ethernet.SRIOV_SUBTREE, {})
|
|
+ if sriov_conf:
|
|
+ eth_conf = iface.original_desire_dict.get(
|
|
+ Ethernet.CONFIG_SUBTREE
|
|
+ )
|
|
+ sriov_ifaces.append(
|
|
+ {
|
|
+ Interface.NAME: iface.name,
|
|
+ Interface.TYPE: InterfaceType.ETHERNET,
|
|
+ Interface.STATE: InterfaceState.UP,
|
|
+ Ethernet.CONFIG_SUBTREE: deepcopy(eth_conf),
|
|
+ }
|
|
+ )
|
|
+ return sriov_ifaces
|
|
+
|
|
@property
|
|
def _ignored_ifaces(self):
|
|
return [iface for iface in self.all_ifaces() if iface.is_ignore]
|
|
@@ -275,6 +324,13 @@
|
|
self._validate_ovs_patch_peers()
|
|
self._remove_unknown_type_interfaces()
|
|
self._validate_veth_peers()
|
|
+ self._resolve_controller_type()
|
|
+ self._validate_port_ip()
|
|
+
|
|
+ def _validate_port_ip(self):
|
|
+ for iface in self.all_ifaces():
|
|
+ if iface.is_desired and iface.is_up:
|
|
+ iface.validate_port_ip()
|
|
|
|
def _bring_port_up_if_not_in_desire(self):
|
|
"""
|
|
@@ -400,6 +456,72 @@
|
|
f"{iface.name} is in {iface.bond_mode} mode."
|
|
)
|
|
|
|
+ def _validate_controller_and_port_list_conflict(self):
|
|
+ """
|
|
+ Validate Check whether user defined both controller property and port
|
|
+ list of controller interface, examples of invalid desire state:
|
|
+ * eth1 has controller: br1, but br1 has no eth1 in port list
|
|
+ * eth2 has controller: br1, but br2 has eth2 in port list
|
|
+ * eth1 has controller: Some("") (detach), but br1 has eth1 in port
|
|
+ list
|
|
+ """
|
|
+ self._validate_controller_not_in_port_list()
|
|
+ self._validate_controller_in_other_port_list()
|
|
+
|
|
+ def _validate_controller_not_in_port_list(self):
|
|
+ for iface_name, iface in self._kernel_ifaces.items():
|
|
+ if (
|
|
+ not iface.is_up
|
|
+ or not iface.controller
|
|
+ or Interface.CONTROLLER not in iface.original_desire_dict
|
|
+ ):
|
|
+ continue
|
|
+ ctrl_iface = self._user_space_ifaces.get(
|
|
+ iface.controller, InterfaceType.OVS_BRIDGE
|
|
+ )
|
|
+ if not ctrl_iface:
|
|
+ ctrl_iface = self._kernel_ifaces.get(iface.controller)
|
|
+ if ctrl_iface:
|
|
+ if not ctrl_iface.is_desired:
|
|
+ continue
|
|
+ if ctrl_iface.port and iface_name not in ctrl_iface.port:
|
|
+ raise NmstateValueError(
|
|
+ f"Interface {iface_name} desired controller "
|
|
+ f"is {iface.controller}, but not listed in port "
|
|
+ "list of controller interface"
|
|
+ )
|
|
+
|
|
+ def _validate_controller_in_other_port_list(self):
|
|
+ port_to_ctrl = {}
|
|
+ for iface in self.all_ifaces():
|
|
+ if iface.is_controller and iface.is_desired and iface.is_up:
|
|
+ for port in iface.port:
|
|
+ port_to_ctrl[port] = iface.name
|
|
+
|
|
+ for iface in self._kernel_ifaces.values():
|
|
+ if (
|
|
+ not iface.is_desired
|
|
+ or not iface.is_up
|
|
+ or iface.controller is None
|
|
+ or iface.name not in port_to_ctrl
|
|
+ or Interface.CONTROLLER not in iface.original_desire_dict
|
|
+ ):
|
|
+ continue
|
|
+ ctrl_name = port_to_ctrl.get(iface.name)
|
|
+ if ctrl_name != iface.controller:
|
|
+ if iface.controller:
|
|
+ raise NmstateValueError(
|
|
+ f"Interface {iface.name} has controller property set "
|
|
+ f"to {iface.controller}, but been listed as "
|
|
+ f"port of controller {ctrl_name} "
|
|
+ )
|
|
+ else:
|
|
+ raise NmstateValueError(
|
|
+ f"Interface {iface.name} desired to detach controller "
|
|
+ "via controller property set to '', but "
|
|
+ f"still been listed as port of controller {ctrl_name}"
|
|
+ )
|
|
+
|
|
def _handle_controller_port_list_change(self):
|
|
"""
|
|
* Mark port interface as changed if controller removed.
|
|
@@ -419,6 +541,10 @@
|
|
changed_port = (des_port | cur_port) - (des_port & cur_port)
|
|
for iface_name in changed_port:
|
|
self._kernel_ifaces[iface_name].mark_as_changed()
|
|
+ if iface_name not in des_port:
|
|
+ self._kernel_ifaces[iface_name].set_controller(
|
|
+ None, None
|
|
+ )
|
|
if cur_iface:
|
|
for port_name in iface.config_changed_port(cur_iface):
|
|
if port_name in self._kernel_ifaces:
|
|
@@ -823,6 +949,24 @@
|
|
if port_name in ignored_kernel_iface_names:
|
|
iface.remove_port(port_name)
|
|
|
|
+ def _resolve_controller_type(self):
|
|
+ for iface in self._kernel_ifaces.values():
|
|
+ if (
|
|
+ iface.is_up
|
|
+ and iface.is_desired
|
|
+ and Interface.CONTROLLER in iface.original_desire_dict
|
|
+ and iface.controller
|
|
+ and iface.controller_type is None
|
|
+ ):
|
|
+ ctrl_iface = self._cur_user_space_ifaces.get(
|
|
+ iface.controller, InterfaceType.OVS_BRIDGE
|
|
+ )
|
|
+ if ctrl_iface is None:
|
|
+ ctrl_iface = self._cur_kernel_ifaces.get(iface.controller)
|
|
+
|
|
+ if ctrl_iface:
|
|
+ iface.set_controller(iface.controller, ctrl_iface.type)
|
|
+
|
|
|
|
def _to_specific_iface_obj(info, save_to_disk):
|
|
iface_type = info.get(Interface.TYPE, InterfaceType.UNKNOWN)
|
|
diff -Nur nmstate-1.3.3.old/libnmstate/ifaces/linux_bridge.py nmstate-1.3.3/libnmstate/ifaces/linux_bridge.py
|
|
--- nmstate-1.3.3.old/libnmstate/ifaces/linux_bridge.py 2022-08-11 23:22:22.000000000 +0800
|
|
+++ nmstate-1.3.3/libnmstate/ifaces/linux_bridge.py 2023-02-15 15:48:33.672042194 +0800
|
|
@@ -192,9 +192,9 @@
|
|
# There is no good way to detect kernel HZ in user space. Hence
|
|
# we check whether certain value is rounded.
|
|
if cur_value != value:
|
|
- if value >= 8 * (10 ** 6):
|
|
+ if value >= 8 * (10**6):
|
|
if abs(value - cur_value) <= int(
|
|
- value / 8 * (10 ** 6)
|
|
+ value / 8 * (10**6)
|
|
):
|
|
return key, value, cur_value
|
|
else:
|
|
diff -Nur nmstate-1.3.3.old/libnmstate/netapplier.py nmstate-1.3.3/libnmstate/netapplier.py
|
|
--- nmstate-1.3.3.old/libnmstate/netapplier.py 2022-08-11 23:22:22.000000000 +0800
|
|
+++ nmstate-1.3.3/libnmstate/netapplier.py 2023-02-15 15:48:45.118768209 +0800
|
|
@@ -24,7 +24,7 @@
|
|
|
|
from libnmstate import validator
|
|
from libnmstate.error import NmstateVerificationError
|
|
-from libnmstate.schema import InterfaceType
|
|
+from libnmstate.schema import Interface
|
|
|
|
from .net_state import NetState
|
|
from .nmstate import create_checkpoints
|
|
@@ -73,20 +73,56 @@
|
|
|
|
desired_state = copy.deepcopy(desired_state)
|
|
remove_the_reserved_secrets(desired_state)
|
|
+
|
|
with plugin_context() as plugins:
|
|
validator.schema_validate(desired_state)
|
|
current_state = show_with_plugins(
|
|
plugins, include_status_data=True, include_secrets=True
|
|
)
|
|
validator.validate_capabilities(
|
|
- desired_state, plugins_capabilities(plugins)
|
|
+ copy.deepcopy(desired_state), plugins_capabilities(plugins)
|
|
)
|
|
ignored_ifnames = _get_ignored_interface_names(plugins)
|
|
net_state = NetState(
|
|
desired_state, ignored_ifnames, current_state, save_to_disk
|
|
)
|
|
checkpoints = create_checkpoints(plugins, rollback_timeout)
|
|
- _apply_ifaces_state(plugins, net_state, verify_change, save_to_disk)
|
|
+ # When we have VF count changes and missing eth, it might be user
|
|
+ # referring future VF in the same desire state, we just apply
|
|
+ # VF changes state only first.
|
|
+ if net_state.ifaces.has_vf_count_change_and_missing_eth():
|
|
+ sriov_ifaces = net_state.ifaces.get_sriov_pf_ifaces()
|
|
+ if sriov_ifaces:
|
|
+ pf_net_state = NetState(
|
|
+ {Interface.KEY: sriov_ifaces},
|
|
+ ignored_ifnames,
|
|
+ current_state,
|
|
+ save_to_disk,
|
|
+ )
|
|
+ _apply_ifaces_state(
|
|
+ plugins,
|
|
+ pf_net_state,
|
|
+ verify_change,
|
|
+ save_to_disk,
|
|
+ has_sriov_pf=True,
|
|
+ )
|
|
+ # Refresh the current state
|
|
+ current_state = show_with_plugins(
|
|
+ plugins, include_status_data=True, include_secrets=True
|
|
+ )
|
|
+ validator.validate_capabilities(
|
|
+ desired_state, plugins_capabilities(plugins)
|
|
+ )
|
|
+ ignored_ifnames = _get_ignored_interface_names(plugins)
|
|
+ net_state = NetState(
|
|
+ copy.deepcopy(desired_state),
|
|
+ ignored_ifnames,
|
|
+ current_state,
|
|
+ save_to_disk,
|
|
+ )
|
|
+ _apply_ifaces_state(
|
|
+ plugins, net_state, verify_change, save_to_disk, has_sriov_pf=False
|
|
+ )
|
|
if commit:
|
|
destroy_checkpoints(plugins, checkpoints)
|
|
else:
|
|
@@ -117,13 +153,17 @@
|
|
rollback_checkpoints(plugins, checkpoint)
|
|
|
|
|
|
-def _apply_ifaces_state(plugins, net_state, verify_change, save_to_disk):
|
|
+def _apply_ifaces_state(
|
|
+ plugins, net_state, verify_change, save_to_disk, has_sriov_pf=False
|
|
+):
|
|
for plugin in plugins:
|
|
- plugin.apply_changes(net_state, save_to_disk)
|
|
+ # Do not allow plugin to modify the net_state for future verification
|
|
+ tmp_net_state = copy.deepcopy(net_state)
|
|
+ plugin.apply_changes(tmp_net_state, save_to_disk)
|
|
|
|
verified = False
|
|
if verify_change:
|
|
- if _net_state_contains_sriov_interface(net_state):
|
|
+ if has_sriov_pf:
|
|
# If SR-IOV is present, the verification timeout is being increased
|
|
# to avoid timeouts due to slow drivers like i40e.
|
|
verify_retry = VERIFY_RETRY_COUNT_SRIOV
|
|
@@ -140,14 +180,6 @@
|
|
_verify_change(plugins, net_state)
|
|
|
|
|
|
-def _net_state_contains_sriov_interface(net_state):
|
|
- for iface in net_state.ifaces.all_kernel_ifaces.values():
|
|
- if iface.type == InterfaceType.ETHERNET and iface.is_sriov:
|
|
- return True
|
|
-
|
|
- return False
|
|
-
|
|
-
|
|
def _verify_change(plugins, net_state):
|
|
current_state = remove_metadata_leftover(
|
|
show_with_plugins(plugins, include_secrets=True)
|
|
diff -Nur nmstate-1.3.3.old/libnmstate/netinfo.py nmstate-1.3.3/libnmstate/netinfo.py
|
|
--- nmstate-1.3.3.old/libnmstate/netinfo.py 2022-08-11 23:22:22.000000000 +0800
|
|
+++ nmstate-1.3.3/libnmstate/netinfo.py 2023-02-15 15:48:33.672042194 +0800
|
|
@@ -39,6 +39,7 @@
|
|
plugins,
|
|
include_status_data=include_status_data,
|
|
include_secrets=include_secrets,
|
|
+ include_controller_prop=False,
|
|
)
|
|
)
|
|
|
|
diff -Nur nmstate-1.3.3.old/libnmstate/nispor/base_iface.py nmstate-1.3.3/libnmstate/nispor/base_iface.py
|
|
--- nmstate-1.3.3.old/libnmstate/nispor/base_iface.py 2022-08-11 23:22:22.000000000 +0800
|
|
+++ nmstate-1.3.3/libnmstate/nispor/base_iface.py 2023-02-15 15:48:33.672042194 +0800
|
|
@@ -115,6 +115,8 @@
|
|
if ethtool_info_dict:
|
|
iface_info[Ethtool.CONFIG_SUBTREE] = ethtool_info_dict
|
|
|
|
+ if self.np_iface.controller:
|
|
+ iface_info[Interface.CONTROLLER] = self.np_iface.controller
|
|
return iface_info
|
|
|
|
|
|
@@ -219,6 +221,7 @@
|
|
"rx-ntuple-filter",
|
|
"rx-vlan-hw-parse",
|
|
"tx-vlan-hw-insert",
|
|
+ "highdma",
|
|
]
|
|
|
|
def __init__(self, np_ethtool):
|
|
diff -Nur nmstate-1.3.3.old/libnmstate/nm/connection.py nmstate-1.3.3/libnmstate/nm/connection.py
|
|
--- nmstate-1.3.3.old/libnmstate/nm/connection.py 2023-02-15 15:48:11.739845988 +0800
|
|
+++ nmstate-1.3.3/libnmstate/nm/connection.py 2023-02-15 15:48:33.672042194 +0800
|
|
@@ -94,7 +94,7 @@
|
|
self._setting = new
|
|
|
|
def set_controller(self, controller, port_type):
|
|
- if controller is not None:
|
|
+ if controller:
|
|
self._setting.props.master = controller
|
|
self._setting.props.slave_type = port_type
|
|
|
|
@@ -186,7 +186,7 @@
|
|
settings.extend(create_ovs_interface_setting(patch_state, dpdk_state))
|
|
elif iface.type == InterfaceType.INFINIBAND:
|
|
ib_setting = create_infiniband_setting(
|
|
- iface_info,
|
|
+ iface,
|
|
nm_profile,
|
|
iface.original_desire_dict,
|
|
)
|
|
diff -Nur nmstate-1.3.3.old/libnmstate/nm/device.py nmstate-1.3.3/libnmstate/nm/device.py
|
|
--- nmstate-1.3.3.old/libnmstate/nm/device.py 2022-08-11 23:22:22.000000000 +0800
|
|
+++ nmstate-1.3.3/libnmstate/nm/device.py 2023-02-15 15:48:45.122101559 +0800
|
|
@@ -106,39 +106,41 @@
|
|
self._iface_name = iface_name
|
|
self._iface_type = iface_type
|
|
self._nm_dev = nm_dev
|
|
+ self._action = None
|
|
|
|
def run(self):
|
|
- action = f"Delete device: {self._iface_type} {self._iface_name}"
|
|
- user_data = action
|
|
- self._ctx.register_async(action)
|
|
+ self._action = f"Delete device: {self._iface_type} {self._iface_name}"
|
|
+ retried = False
|
|
+ self._ctx.register_async(self._action)
|
|
self._nm_dev.delete_async(
|
|
- self._ctx.cancellable, self._delete_device_callback, user_data
|
|
+ self._ctx.cancellable, self._delete_device_callback, retried
|
|
)
|
|
|
|
- def _delete_device_callback(self, nm_dev, result, user_data):
|
|
- action = user_data
|
|
+ def _delete_device_callback(self, nm_dev, result, retried):
|
|
if self._ctx.is_cancelled():
|
|
return
|
|
- error = None
|
|
try:
|
|
nm_dev.delete_finish(result)
|
|
+ self._ctx.finish_async(self._action)
|
|
except Exception as e:
|
|
- error = e
|
|
-
|
|
- if not nm_dev.is_real():
|
|
- logging.debug(
|
|
- f"Interface is deleted and not real/exist anymore: "
|
|
- f"iface={self._iface_name} type={self._iface_type}"
|
|
- )
|
|
- if error:
|
|
- logging.debug(f"Ignored error: {error}")
|
|
- self._ctx.finish_async(action)
|
|
- else:
|
|
- self._ctx.fail(
|
|
- NmstateLibnmError(
|
|
- f"{action} failed: error={error or 'unknown'}"
|
|
+ if not nm_dev.is_real():
|
|
+ logging.debug(
|
|
+ f"Interface is deleted and not real/exist anymore: "
|
|
+ f"iface={self._iface_name} type={self._iface_type}"
|
|
+ )
|
|
+ logging.debug(f"Ignored error: {e}")
|
|
+ self._ctx.finish_async(self._action)
|
|
+ elif retried:
|
|
+ self._ctx.fail(
|
|
+ NmstateLibnmError(f"{self._action} failed: error={e}")
|
|
+ )
|
|
+ else:
|
|
+ retried = True
|
|
+ self._nm_dev.delete_async(
|
|
+ self._ctx.cancellable,
|
|
+ self._delete_device_callback,
|
|
+ retried,
|
|
)
|
|
- )
|
|
|
|
|
|
def list_devices(client):
|
|
diff -Nur nmstate-1.3.3.old/libnmstate/nm/infiniband.py nmstate-1.3.3/libnmstate/nm/infiniband.py
|
|
--- nmstate-1.3.3.old/libnmstate/nm/infiniband.py 2022-08-11 23:22:22.000000000 +0800
|
|
+++ nmstate-1.3.3/libnmstate/nm/infiniband.py 2023-02-14 18:48:57.083997920 +0800
|
|
@@ -71,7 +71,9 @@
|
|
return None
|
|
|
|
|
|
-def create_setting(iface_info, base_con_profile, original_iface_info):
|
|
+def create_setting(iface, base_con_profile, original_iface_info):
|
|
+ iface.pre_edit_validation_and_cleanup()
|
|
+ iface_info = iface.to_dict()
|
|
ib_config = iface_info.get(InfiniBand.CONFIG_SUBTREE)
|
|
if not ib_config:
|
|
return None
|
|
diff -Nur nmstate-1.3.3.old/libnmstate/nm/ipv4.py nmstate-1.3.3/libnmstate/nm/ipv4.py
|
|
--- nmstate-1.3.3.old/libnmstate/nm/ipv4.py 2022-08-11 23:22:22.000000000 +0800
|
|
+++ nmstate-1.3.3/libnmstate/nm/ipv4.py 2023-02-15 15:48:33.672042194 +0800
|
|
@@ -27,7 +27,7 @@
|
|
from ..ifaces import BaseIface
|
|
from .common import NM
|
|
|
|
-INT32_MAX = 2 ** 31 - 1
|
|
+INT32_MAX = 2**31 - 1
|
|
|
|
|
|
def create_setting(config, base_con_profile):
|
|
@@ -77,6 +77,9 @@
|
|
# when the DHCP timeout expired, set it to the maximum value to
|
|
# make this unlikely.
|
|
setting_ipv4.props.dhcp_timeout = INT32_MAX
|
|
+ route_metric = config.get(InterfaceIPv4.AUTO_ROUTE_METRIC)
|
|
+ if route_metric is not None:
|
|
+ setting_ipv4.props.route_metric = route_metric
|
|
elif config.get(InterfaceIPv4.ADDRESS):
|
|
setting_ipv4.props.method = NM.SETTING_IP4_CONFIG_METHOD_MANUAL
|
|
_add_addresses(setting_ipv4, config[InterfaceIPv4.ADDRESS])
|
|
@@ -129,6 +132,8 @@
|
|
info[InterfaceIPv4.AUTO_GATEWAY] = not props.never_default
|
|
info[InterfaceIPv4.AUTO_DNS] = not props.ignore_auto_dns
|
|
info[InterfaceIPv4.AUTO_ROUTE_TABLE_ID] = props.route_table
|
|
+ if props.route_metric >= 0:
|
|
+ info[InterfaceIPv4.AUTO_ROUTE_METRIC] = props.route_metric
|
|
if props.dhcp_client_id:
|
|
info[InterfaceIPv4.DHCP_CLIENT_ID] = props.dhcp_client_id
|
|
|
|
diff -Nur nmstate-1.3.3.old/libnmstate/nm/ipv6.py nmstate-1.3.3/libnmstate/nm/ipv6.py
|
|
--- nmstate-1.3.3.old/libnmstate/nm/ipv6.py 2023-02-15 15:48:11.737845979 +0800
|
|
+++ nmstate-1.3.3/libnmstate/nm/ipv6.py 2023-02-15 15:50:14.713397220 +0800
|
|
@@ -31,7 +31,7 @@
|
|
from .common import NM
|
|
|
|
IPV6_DEFAULT_ROUTE_METRIC = 1024
|
|
-INT32_MAX = 2 ** 31 - 1
|
|
+INT32_MAX = 2**31 - 1
|
|
|
|
|
|
def get_info(active_connection, applied_config):
|
|
@@ -73,6 +73,8 @@
|
|
info[InterfaceIPv6.AUTO_ROUTE_TABLE_ID] = props.route_table
|
|
if props.dhcp_duid:
|
|
info[InterfaceIPv6.DHCP_DUID] = props.dhcp_duid
|
|
+ if props.route_metric > 0:
|
|
+ info[InterfaceIPv6.AUTO_ROUTE_METRIC] = props.route_metric
|
|
info[InterfaceIPv6.ADDR_GEN_MODE] = (
|
|
InterfaceIPv6.ADDR_GEN_MODE_STABLE_PRIVACY
|
|
if props.addr_gen_mode
|
|
@@ -146,6 +148,10 @@
|
|
if route_table:
|
|
setting_ip.props.route_table = route_table
|
|
|
|
+ route_metric = config.get(InterfaceIPv6.AUTO_ROUTE_METRIC)
|
|
+ if route_metric is not None:
|
|
+ setting_ip.props.route_metric = route_metric
|
|
+
|
|
elif ip_addresses:
|
|
_set_static(setting_ip, ip_addresses)
|
|
else:
|
|
diff -Nur nmstate-1.3.3.old/libnmstate/nm/ovs.py nmstate-1.3.3/libnmstate/nm/ovs.py
|
|
--- nmstate-1.3.3.old/libnmstate/nm/ovs.py 2022-08-11 23:22:22.000000000 +0800
|
|
+++ nmstate-1.3.3/libnmstate/nm/ovs.py 2023-02-15 15:48:33.672042194 +0800
|
|
@@ -22,6 +22,7 @@
|
|
|
|
from libnmstate.ifaces import ovs
|
|
from libnmstate.ifaces.bridge import BridgeIface
|
|
+from libnmstate.ifaces.ovs import OvsBridgeIface
|
|
from libnmstate.ifaces.ovs import OvsPortIface
|
|
from libnmstate.schema import Interface
|
|
from libnmstate.schema import InterfaceType
|
|
@@ -33,7 +34,6 @@
|
|
|
|
|
|
CONTROLLER_TYPE_METADATA = "_controller_type"
|
|
-CONTROLLER_METADATA = "_controller"
|
|
SETTING_OVS_EXTERNALIDS = "SettingOvsExternalIDs"
|
|
SETTING_OVS_EXTERNAL_IDS_SETTING_NAME = "ovs-external-ids"
|
|
|
|
@@ -338,17 +338,24 @@
|
|
iface_name = iface.name
|
|
iface_info = iface.to_dict()
|
|
port_options = iface_info.get(BridgeIface.BRPORT_OPTIONS_METADATA)
|
|
- if ovs.is_ovs_lag_port(port_options):
|
|
- port_name = port_options[OB.Port.NAME]
|
|
+ if port_options:
|
|
+ if ovs.is_ovs_lag_port(port_options):
|
|
+ port_name = port_options[OB.Port.NAME]
|
|
+ else:
|
|
+ port_name = iface_name
|
|
else:
|
|
+ # User is attaching system port to OVS bridge via `controller` property
|
|
+ # with OVS bridge not mentioned in desired state
|
|
port_name = iface_name
|
|
+ port_options = {}
|
|
+
|
|
return OvsPortIface(
|
|
{
|
|
Interface.NAME: port_name,
|
|
Interface.TYPE: InterfaceType.OVS_PORT,
|
|
Interface.STATE: iface.state,
|
|
OB.OPTIONS_SUBTREE: port_options,
|
|
- CONTROLLER_METADATA: iface_info[CONTROLLER_METADATA],
|
|
+ Interface.CONTROLLER: iface_info[Interface.CONTROLLER],
|
|
CONTROLLER_TYPE_METADATA: iface_info[CONTROLLER_TYPE_METADATA],
|
|
}
|
|
)
|
|
@@ -356,3 +363,17 @@
|
|
|
|
def _is_nm_support_ovs_external_ids():
|
|
return hasattr(NM, SETTING_OVS_EXTERNALIDS)
|
|
+
|
|
+
|
|
+def set_ovs_iface_controller_info(iface_infos):
|
|
+ pending_changes = {}
|
|
+ for iface_info in iface_infos:
|
|
+ if iface_info.get(Interface.TYPE) == InterfaceType.OVS_BRIDGE:
|
|
+ iface = OvsBridgeIface(info=iface_info, save_to_disk=True)
|
|
+ for port in iface.port:
|
|
+ pending_changes[port] = iface.name
|
|
+
|
|
+ for iface_info in iface_infos:
|
|
+ ctrl_name = pending_changes.get(iface_info[Interface.NAME])
|
|
+ if ctrl_name:
|
|
+ iface_info[Interface.CONTROLLER] = ctrl_name
|
|
diff -Nur nmstate-1.3.3.old/libnmstate/nm/plugin.py nmstate-1.3.3/libnmstate/nm/plugin.py
|
|
--- nmstate-1.3.3.old/libnmstate/nm/plugin.py 2022-08-11 23:22:22.000000000 +0800
|
|
+++ nmstate-1.3.3/libnmstate/nm/plugin.py 2023-02-15 15:48:33.672042194 +0800
|
|
@@ -49,6 +49,7 @@
|
|
from .ovs import get_ovs_bridge_info
|
|
from .ovs import get_ovsdb_external_ids
|
|
from .ovs import has_ovs_capability
|
|
+from .ovs import set_ovs_iface_controller_info
|
|
from .profiles import NmProfiles
|
|
from .profiles import get_all_applied_configs
|
|
from .team import get_info as get_team_info
|
|
@@ -192,6 +193,8 @@
|
|
|
|
info.append(iface_info)
|
|
|
|
+ set_ovs_iface_controller_info(info)
|
|
+
|
|
info.sort(key=itemgetter("name"))
|
|
|
|
return info
|
|
@@ -293,7 +296,7 @@
|
|
def generate_configurations(self, net_state):
|
|
if not hasattr(NM, "keyfile_write"):
|
|
raise NmstateNotSupportedError(
|
|
- f"Current NetworkManager version does not support generating "
|
|
+ "Current NetworkManager version does not support generating "
|
|
"configurations, please upgrade to 1.30 or later versoin."
|
|
)
|
|
return NmProfiles(None).generate_config_strings(net_state)
|
|
diff -Nur nmstate-1.3.3.old/libnmstate/nm/profile.py nmstate-1.3.3/libnmstate/nm/profile.py
|
|
--- nmstate-1.3.3.old/libnmstate/nm/profile.py 2023-02-15 15:48:11.748846029 +0800
|
|
+++ nmstate-1.3.3/libnmstate/nm/profile.py 2023-02-15 15:48:45.122101559 +0800
|
|
@@ -139,6 +139,11 @@
|
|
else:
|
|
return ""
|
|
|
|
+ def disable_autoconnect(self):
|
|
+ if self._nm_simple_conn:
|
|
+ nm_conn_setting = self._nm_simple_conn.get_setting_connection()
|
|
+ nm_conn_setting.props.autoconnect = False
|
|
+
|
|
def update_controller(self, controller):
|
|
nm_simple_conn_update_controller(self._nm_simple_conn, controller)
|
|
|
|
@@ -186,8 +191,10 @@
|
|
elif self._iface.is_down:
|
|
if self._nm_ac:
|
|
self._add_action(NmProfile.ACTION_DEACTIVATE)
|
|
- elif self._iface.is_virtual and self._nm_dev:
|
|
+ if self._iface.is_virtual and self._nm_dev:
|
|
self._add_action(NmProfile.ACTION_DELETE_DEVICE)
|
|
+ if self._nm_dev and not self._nm_dev.get_managed():
|
|
+ self._add_action(NmProfile.ACTION_DEACTIVATE)
|
|
|
|
if self._iface.raw.get(ROUTE_REMOVED):
|
|
# This is a workaround for NM bug:
|
|
@@ -276,7 +283,12 @@
|
|
)
|
|
|
|
def prepare_config(self, save_to_disk, gen_conf_mode=False):
|
|
- if self._iface.is_absent or self._iface.is_down:
|
|
+ if self._iface.is_absent or (
|
|
+ self._iface.is_down
|
|
+ and not gen_conf_mode
|
|
+ and self._nm_dev
|
|
+ and self._nm_dev.get_managed()
|
|
+ ):
|
|
return
|
|
|
|
# Don't create new profile if original desire does not ask
|
|
@@ -312,7 +324,9 @@
|
|
self._gen_actions()
|
|
if not self.has_pending_change:
|
|
return
|
|
- if self._iface.is_absent or self._iface.is_down:
|
|
+ if self._iface.is_absent or (
|
|
+ self._iface.is_down and self._nm_dev and self._nm_dev.get_managed()
|
|
+ ):
|
|
return
|
|
# Don't create new profile if original desire does not ask
|
|
# anything besides state:up and not been marked as changed.
|
|
@@ -411,6 +425,9 @@
|
|
def _deactivate(self):
|
|
if self._deactivated:
|
|
return
|
|
+ self._nm_ac = (
|
|
+ self._nm_dev.get_active_connection() if self._nm_dev else None
|
|
+ )
|
|
if self._nm_ac:
|
|
ActiveConnectionDeactivate(
|
|
self._ctx, self._iface.name, self._iface.type, self._nm_ac
|
|
diff -Nur nmstate-1.3.3.old/libnmstate/nm/profiles.py nmstate-1.3.3/libnmstate/nm/profiles.py
|
|
--- nmstate-1.3.3.old/libnmstate/nm/profiles.py 2022-08-11 23:22:22.000000000 +0800
|
|
+++ nmstate-1.3.3/libnmstate/nm/profiles.py 2023-02-15 15:48:45.122101559 +0800
|
|
@@ -26,6 +26,7 @@
|
|
from libnmstate.schema import Interface
|
|
from libnmstate.schema import InterfaceState
|
|
from libnmstate.schema import InterfaceType
|
|
+from libnmstate.schema import OvsDB
|
|
|
|
from .common import NM
|
|
from .device import is_externally_managed
|
|
@@ -51,9 +52,11 @@
|
|
_append_nm_ovs_port_iface(net_state)
|
|
all_profiles = []
|
|
for iface in net_state.ifaces.all_ifaces():
|
|
- if iface.is_up:
|
|
+ if iface.is_up or iface.is_down:
|
|
profile = NmProfile(self._ctx, iface)
|
|
profile.prepare_config(save_to_disk=False, gen_conf_mode=True)
|
|
+ if iface.is_down:
|
|
+ profile.disable_autoconnect()
|
|
all_profiles.append(profile)
|
|
|
|
_use_uuid_as_controller_and_parent(all_profiles)
|
|
@@ -123,16 +126,18 @@
|
|
subordinate of NM OVS port profile which is port of the OVS bridge
|
|
profile.
|
|
We need to create/delete this NM OVS port profile accordingly.
|
|
+ We skip this action if ovs interface is not changed.
|
|
"""
|
|
nm_ovs_port_ifaces = {}
|
|
|
|
for iface in net_state.ifaces.all_kernel_ifaces.values():
|
|
if iface.controller_type == InterfaceType.OVS_BRIDGE:
|
|
+ has_ovs_change = _has_ovs_changes(iface, net_state)
|
|
nm_ovs_port_iface = create_iface_for_nm_ovs_port(iface)
|
|
iface.set_controller(
|
|
nm_ovs_port_iface.name, InterfaceType.OVS_PORT
|
|
)
|
|
- if iface.is_desired or iface.is_changed:
|
|
+ if (iface.is_desired or iface.is_changed) and has_ovs_change:
|
|
nm_ovs_port_iface.mark_as_changed()
|
|
nm_ovs_port_ifaces[nm_ovs_port_iface.name] = nm_ovs_port_iface
|
|
|
|
@@ -390,6 +395,10 @@
|
|
iface = nm_profile.iface
|
|
if not iface.is_up:
|
|
continue
|
|
+ # InfiniBand setting does not support UUID as parent
|
|
+ if iface.type == InterfaceType.INFINIBAND:
|
|
+ continue
|
|
+
|
|
if (
|
|
iface.controller
|
|
and (iface.is_changed or iface.is_desired)
|
|
@@ -434,3 +443,28 @@
|
|
):
|
|
return True
|
|
return False
|
|
+
|
|
+
|
|
+def _has_ovs_changes(iface, net_state):
|
|
+ """
|
|
+ Return False only when below all matches:
|
|
+ * Desired interface is up
|
|
+ * Desire state did not mentioned its OVS bridge controller
|
|
+ * Interface has no changed to controller property
|
|
+ * Interface has no ovs-db setting change in desire state
|
|
+ """
|
|
+ ctrl_iface = net_state.ifaces.get_iface(
|
|
+ iface.controller, InterfaceType.OVS_BRIDGE
|
|
+ )
|
|
+ if (
|
|
+ iface.is_desired
|
|
+ and iface.is_up
|
|
+ and ctrl_iface
|
|
+ and not ctrl_iface.is_desired
|
|
+ and not ctrl_iface.is_changed
|
|
+ and Interface.CONTROLLER not in iface.original_desire_dict
|
|
+ and OvsDB.KEY not in iface.original_desire_dict
|
|
+ ):
|
|
+ return False
|
|
+
|
|
+ return True
|
|
diff -Nur nmstate-1.3.3.old/libnmstate/nmstate.py nmstate-1.3.3/libnmstate/nmstate.py
|
|
--- nmstate-1.3.3.old/libnmstate/nmstate.py 2022-08-11 23:22:22.000000000 +0800
|
|
+++ nmstate-1.3.3/libnmstate/nmstate.py 2023-02-15 15:48:33.672042194 +0800
|
|
@@ -73,6 +73,7 @@
|
|
include_status_data=None,
|
|
info_type=_INFO_TYPE_RUNNING,
|
|
include_secrets=False,
|
|
+ include_controller_prop=True,
|
|
):
|
|
for plugin in plugins:
|
|
plugin.refresh_content()
|
|
@@ -81,7 +82,7 @@
|
|
report["capabilities"] = plugins_capabilities(plugins)
|
|
|
|
report[Interface.KEY] = _get_interface_info_from_plugins(
|
|
- plugins, info_type
|
|
+ plugins, info_type, include_controller_prop=include_controller_prop
|
|
)
|
|
|
|
report[Route.KEY] = _get_routes_from_plugins(plugins, info_type)
|
|
@@ -103,6 +104,7 @@
|
|
|
|
if not include_secrets:
|
|
hide_the_secrets(report)
|
|
+
|
|
return report
|
|
|
|
|
|
@@ -185,7 +187,9 @@
|
|
return chose_plugin
|
|
|
|
|
|
-def _get_interface_info_from_plugins(plugins, info_type):
|
|
+def _get_interface_info_from_plugins(
|
|
+ plugins, info_type, include_controller_prop=True
|
|
+):
|
|
all_ifaces = {}
|
|
IFACE_PRIORITY_METADATA = "_plugin_priority"
|
|
IFACE_PLUGIN_SRC_METADATA = "_plugin_source"
|
|
@@ -287,6 +291,8 @@
|
|
for iface in all_ifaces.values():
|
|
iface.pop(IFACE_PRIORITY_METADATA)
|
|
iface.pop(IFACE_PLUGIN_SRC_METADATA)
|
|
+ if not include_controller_prop:
|
|
+ iface.pop(Interface.CONTROLLER, None)
|
|
|
|
return sorted(all_ifaces.values(), key=itemgetter(Interface.NAME))
|
|
|
|
@@ -404,6 +410,7 @@
|
|
plugins,
|
|
info_type=_INFO_TYPE_RUNNING_CONFIG,
|
|
include_secrets=include_secrets,
|
|
+ include_controller_prop=False,
|
|
)
|
|
|
|
|
|
diff -Nur nmstate-1.3.3.old/libnmstate/plugin.py nmstate-1.3.3/libnmstate/plugin.py
|
|
--- nmstate-1.3.3.old/libnmstate/plugin.py 2022-08-11 23:22:22.000000000 +0800
|
|
+++ nmstate-1.3.3/libnmstate/plugin.py 2023-02-14 18:35:05.960135769 +0800
|
|
@@ -32,6 +32,7 @@
|
|
PLUGIN_CAPABILITY_ROUTE = "route"
|
|
PLUGIN_CAPABILITY_ROUTE_RULE = "route_rule"
|
|
PLUGIN_CAPABILITY_DNS = "dns"
|
|
+ PLUGIN_CAPABILITY_OVSDB_GLOBAL = "ovsdb_global"
|
|
|
|
DEFAULT_PRIORITY = 10
|
|
|
|
diff -Nur nmstate-1.3.3.old/libnmstate/plugins/nmstate_plugin_ovsdb.py nmstate-1.3.3/libnmstate/plugins/nmstate_plugin_ovsdb.py
|
|
--- nmstate-1.3.3.old/libnmstate/plugins/nmstate_plugin_ovsdb.py 2022-08-11 23:22:22.000000000 +0800
|
|
+++ nmstate-1.3.3/libnmstate/plugins/nmstate_plugin_ovsdb.py 2023-02-14 18:35:05.960135769 +0800
|
|
@@ -156,8 +156,16 @@
|
|
return NmstatePlugin.DEFAULT_PRIORITY + 1
|
|
|
|
@property
|
|
+ def capabilities(self):
|
|
+ return [
|
|
+ NmstatePlugin.PLUGIN_CAPABILITY_OVSDB_GLOBAL,
|
|
+ ]
|
|
+
|
|
+ @property
|
|
def plugin_capabilities(self):
|
|
- return NmstatePlugin.PLUGIN_CAPABILITY_IFACE
|
|
+ return [
|
|
+ NmstatePlugin.PLUGIN_CAPABILITY_IFACE,
|
|
+ ]
|
|
|
|
def get_interfaces(self):
|
|
ifaces = []
|
|
diff -Nur nmstate-1.3.3.old/libnmstate/schema.py nmstate-1.3.3/libnmstate/schema.py
|
|
--- nmstate-1.3.3.old/libnmstate/schema.py 2023-02-15 15:48:11.742846002 +0800
|
|
+++ nmstate-1.3.3/libnmstate/schema.py 2023-02-15 15:48:33.672042194 +0800
|
|
@@ -48,6 +48,7 @@
|
|
MTU = "mtu"
|
|
COPY_MAC_FROM = "copy-mac-from"
|
|
ACCEPT_ALL_MAC_ADDRESSES = "accept-all-mac-addresses"
|
|
+ CONTROLLER = "controller"
|
|
|
|
|
|
class Route:
|
|
@@ -148,6 +149,7 @@
|
|
AUTO_GATEWAY = "auto-gateway"
|
|
AUTO_ROUTES = "auto-routes"
|
|
AUTO_ROUTE_TABLE_ID = "auto-route-table-id"
|
|
+ AUTO_ROUTE_METRIC = "auto-route-metric"
|
|
|
|
|
|
class InterfaceIPv4(InterfaceIP):
|
|
diff -Nur nmstate-1.3.3.old/libnmstate/validator.py nmstate-1.3.3/libnmstate/validator.py
|
|
--- nmstate-1.3.3.old/libnmstate/validator.py 2022-08-11 23:22:22.000000000 +0800
|
|
+++ nmstate-1.3.3/libnmstate/validator.py 2023-02-14 18:35:05.960135769 +0800
|
|
@@ -23,6 +23,7 @@
|
|
import jsonschema as js
|
|
|
|
from libnmstate.schema import Interface
|
|
+from libnmstate.schema import OvsDB
|
|
from libnmstate.schema import InterfaceType
|
|
from libnmstate.error import NmstateDependencyError
|
|
|
|
@@ -43,6 +44,7 @@
|
|
|
|
def validate_capabilities(state, capabilities):
|
|
validate_interface_capabilities(state.get(Interface.KEY, []), capabilities)
|
|
+ validate_ovsdb_global_cap(state.get(OvsDB.KEY, {}), capabilities)
|
|
|
|
|
|
def validate_interface_capabilities(ifaces_state, capabilities):
|
|
@@ -78,3 +80,15 @@
|
|
"Interfaces count exceeds the limit %s in desired state",
|
|
MAX_SUPPORTED_INTERFACES,
|
|
)
|
|
+
|
|
+
|
|
+def validate_ovsdb_global_cap(ovsdb_global_conf, capabilities):
|
|
+ if (
|
|
+ ovsdb_global_conf
|
|
+ and NmstatePlugin.PLUGIN_CAPABILITY_OVSDB_GLOBAL not in capabilities
|
|
+ ):
|
|
+ raise NmstateDependencyError(
|
|
+ "Missing plugin for ovs-db global configuration, "
|
|
+ "please try to install 'nmstate-plugin-ovsdb' or other plugin "
|
|
+ "provides NmstatePlugin.PLUGIN_CAPABILITY_OVSDB_GLOBAL"
|
|
+ )
|
|
diff -Nur nmstate-1.3.3.old/libnmstate/VERSION nmstate-1.3.3/libnmstate/VERSION
|
|
--- nmstate-1.3.3.old/libnmstate/VERSION 2022-08-11 23:22:22.000000000 +0800
|
|
+++ nmstate-1.3.3/libnmstate/VERSION 2023-02-15 15:48:33.668708842 +0800
|
|
@@ -1 +1 @@
|
|
-1.3.3
|
|
+1.3.4
|