diff --git a/.gitignore b/.gitignore index 15ecebb..da093cf 100644 --- a/.gitignore +++ b/.gitignore @@ -1,2 +1,2 @@ SOURCES/gpgkey-F7910D93CA83D77348595C0E899014C0463C12BB.gpg -SOURCES/nmstate-0.2.6.tar.gz +SOURCES/nmstate-0.2.10.tar.gz diff --git a/.nmstate.metadata b/.nmstate.metadata index 75ddca6..cd27192 100644 --- a/.nmstate.metadata +++ b/.nmstate.metadata @@ -1,2 +1,2 @@ 7bcc63976a8d449b3adc57f40d7a476106889042 SOURCES/gpgkey-F7910D93CA83D77348595C0E899014C0463C12BB.gpg -9da848bd1955e436235fa89239e3f55535593211 SOURCES/nmstate-0.2.6.tar.gz +bc4887583287e29494aca5dbbca58699dc5cfc3d SOURCES/nmstate-0.2.10.tar.gz diff --git a/SOURCES/BZ_1806249-ActiveConnection-Handle-uninitialized-device.patch b/SOURCES/BZ_1806249-ActiveConnection-Handle-uninitialized-device.patch deleted file mode 100644 index 604032f..0000000 --- a/SOURCES/BZ_1806249-ActiveConnection-Handle-uninitialized-device.patch +++ /dev/null @@ -1,93 +0,0 @@ -From 60dd21358c94c7bae08410100af99cd5eb34ecc6 Mon Sep 17 00:00:00 2001 -From: Fernando Fernandez Mancera -Date: Mon, 2 Mar 2020 14:30:09 +0100 -Subject: [PATCH] ActiveConnection: Handle uninitialized device - -Handle `ActiveConnection._nmdev` being None. This should fix a Traceback -when the openvswitch service is not running: - -Traceback (most recent call last): - File "/usr/lib/python3.6/site-packages/libnmstate/nm/connection.py", line 226, in _active_connection_callback - ac.devname, ac.reason - File "/usr/lib/python3.6/site-packages/libnmstate/nm/active_connection.py", line 171, in devname - return self._nmdev.get_iface() -AttributeError: 'NoneType' object has no attribute 'get_iface' - -Signed-off-by: Fernando Fernandez Mancera ---- - libnmstate/nm/active_connection.py | 16 +++++++++------- - libnmstate/nm/connection.py | 2 +- - 2 files changed, 10 insertions(+), 8 deletions(-) - -diff --git a/libnmstate/nm/active_connection.py b/libnmstate/nm/active_connection.py -index 7b70b2a..c81ee2b 100644 ---- a/libnmstate/nm/active_connection.py -+++ b/libnmstate/nm/active_connection.py -@@ -1,5 +1,5 @@ - # --# Copyright (c) 2019 Red Hat, Inc. -+# Copyright (c) 2019-2020 Red Hat, Inc. - # - # This file is part of nmstate - # -@@ -86,7 +86,7 @@ class ActiveConnection: - if self._mainloop.is_action_canceled(e): - logging.debug( - "Connection deactivation aborted on %s: error=%s", -- self._nmdev.get_iface(), -+ self.devname, - e, - ) - else: -@@ -105,20 +105,19 @@ class ActiveConnection: - else: - self._mainloop.quit( - "Connection deactivation failed on {}: " -- "error={}".format(self._nmdev.get_iface(), e) -+ "error={}".format(self.devname, e) - ) - return - - if success: - logging.debug( -- "Connection deactivation succeeded on %s", -- self._nmdev.get_iface(), -+ "Connection deactivation succeeded on %s", self.devname, - ) - self._mainloop.execute_next_action() - else: - self._mainloop.quit( - "Connection deactivation failed on %s: error=unknown" -- % self._nmdev.get_iface() -+ % self.devname - ) - - @property -@@ -168,7 +167,10 @@ class ActiveConnection: - - @property - def devname(self): -- return self._nmdev.get_iface() -+ if self._nmdev: -+ return self._nmdev.get_iface() -+ else: -+ return None - - @property - def nmdevice(self): -diff --git a/libnmstate/nm/connection.py b/libnmstate/nm/connection.py -index 3dc1ee1..2076734 100644 ---- a/libnmstate/nm/connection.py -+++ b/libnmstate/nm/connection.py -@@ -223,7 +223,7 @@ class ConnectionProfile: - else: - self._mainloop.quit( - "Connection activation failed on {}: reason={}".format( -- ac.devname, ac.reason -+ devname, ac.reason - ) - ) - --- -2.24.1 - diff --git a/SOURCES/BZ_1809330-Bond-mode-change.patch b/SOURCES/BZ_1809330-Bond-mode-change.patch deleted file mode 100644 index 195677a..0000000 --- a/SOURCES/BZ_1809330-Bond-mode-change.patch +++ /dev/null @@ -1,135 +0,0 @@ -From b78579503ac16b9f7c71a023532fcb5f1586bc1d Mon Sep 17 00:00:00 2001 -From: Gris Ge -Date: Mon, 9 Mar 2020 22:16:18 +0800 -Subject: [PATCH] nm applier: only create ethernet when explicitly - -Creating ethernet configuration when user not requested will -cause two major problems: - * Adding slave to newly create bridge will cause bridge link down. - * Cannot switch bond mode from 1(active-backup) to 5(balance-tlb). - -To fix the problem, only create ethernet/wired setting when user -explicitly requested. - -Remove the xfail of test case for changing bond mode from 1(active-backup) -to 5(balance-tlb). - -Remove the workaround in test case for adding slave to newly created -bridge without link state down. - -Add test case showing old ethernet configuration will not be removed when -desire state does not include so. - -Signed-off-by: Gris Ge ---- - libnmstate/netapplier.py | 8 +++++--- - libnmstate/nm/applier.py | 31 ++++++++++++++++++++++++++----- - 2 files changed, 31 insertions(+), 8 deletions(-) - -diff --git a/libnmstate/netapplier.py b/libnmstate/netapplier.py -index cc6b6e3..d9d10cf 100644 ---- a/libnmstate/netapplier.py -+++ b/libnmstate/netapplier.py -@@ -152,7 +152,9 @@ def _apply_ifaces_state( - state2edit = _create_editable_desired_state( - desired_state, current_state, new_interfaces - ) -- ifaces2edit, ifaces_edit_configs = _edit_interfaces(state2edit) -+ ifaces2edit, ifaces_edit_configs = _edit_interfaces( -+ state2edit, original_desired_state -+ ) - nm.applier.set_ifaces_admin_state( - ifaces2add + ifaces2edit, - con_profiles=ifaces_add_configs + ifaces_edit_configs, -@@ -231,7 +233,7 @@ def _add_interfaces(new_interfaces, desired_state): - return (ifaces2add, ifaces_configs) - - --def _edit_interfaces(state2edit): -+def _edit_interfaces(state2edit, original_desired_state): - logging.debug("Editing interfaces: %s", list(state2edit.interfaces)) - - ifaces2edit = list(state2edit.interfaces.values()) -@@ -244,7 +246,7 @@ def _edit_interfaces(state2edit): - ) - proxy_ifaces = nm.applier.prepare_proxy_ifaces_desired_state(iface2prepare) - ifaces_configs = nm.applier.prepare_edited_ifaces_configuration( -- iface2prepare + proxy_ifaces -+ iface2prepare + proxy_ifaces, original_desired_state - ) - nm.applier.edit_existing_ifaces(ifaces_configs) - -diff --git a/libnmstate/nm/applier.py b/libnmstate/nm/applier.py -index 77e869e..8d31e35 100644 ---- a/libnmstate/nm/applier.py -+++ b/libnmstate/nm/applier.py -@@ -69,7 +69,10 @@ def prepare_new_ifaces_configuration(ifaces_desired_state): - ) - - return [ -- _build_connection_profile(iface_desired_state) -+ _build_connection_profile( -+ iface_desired_state, -+ original_desired_iface_state=iface_desired_state, -+ ) - for iface_desired_state in ifaces_desired_state - ] - -@@ -89,7 +92,9 @@ def edit_existing_ifaces(con_profiles): - connection_profile.add(save_to_disk=True) - - --def prepare_edited_ifaces_configuration(ifaces_desired_state): -+def prepare_edited_ifaces_configuration( -+ ifaces_desired_state, original_desired_state -+): - con_profiles = [] - - for iface_desired_state in ifaces_desired_state: -@@ -101,8 +106,13 @@ def prepare_edited_ifaces_configuration(ifaces_desired_state): - if nmdev: - cur_con_profile = connection.ConnectionProfile() - cur_con_profile.import_by_device(nmdev) -+ original_desired_iface_state = original_desired_state.interfaces.get( -+ ifname, {} -+ ) - new_con_profile = _build_connection_profile( -- iface_desired_state, base_con_profile=cur_con_profile -+ iface_desired_state, -+ base_con_profile=cur_con_profile, -+ original_desired_iface_state=original_desired_iface_state, - ) - if not new_con_profile.devname: - set_conn = new_con_profile.profile.get_setting_connection() -@@ -366,7 +376,14 @@ def _generate_hash_iface_name(name): - return name_[:MAXIMUM_INTERFACE_LENGTH].decode() - - --def _build_connection_profile(iface_desired_state, base_con_profile=None): -+def _build_connection_profile( -+ iface_desired_state, -+ base_con_profile=None, -+ original_desired_iface_state=None, -+): -+ if original_desired_iface_state is None: -+ original_desired_iface_state = {} -+ - iface_type = translator.Api2Nm.get_iface_type( - iface_desired_state[Interface.TYPE] - ) -@@ -401,7 +418,11 @@ def _build_connection_profile(iface_desired_state, base_con_profile=None): - con_setting.set_master(master, master_type) - settings.append(con_setting.setting) - -- wired_setting = wired.create_setting(iface_desired_state, base_profile) -+ # Only apply wired/ethernet configuration based on original desire -+ # state rather than the merged one. -+ wired_setting = wired.create_setting( -+ original_desired_iface_state, base_profile -+ ) - if wired_setting: - settings.append(wired_setting) - --- -2.18.2 - diff --git a/SOURCES/BZ_1809330-Fix-bond-regression.patch b/SOURCES/BZ_1809330-Fix-bond-regression.patch deleted file mode 100644 index 698f258..0000000 --- a/SOURCES/BZ_1809330-Fix-bond-regression.patch +++ /dev/null @@ -1,96 +0,0 @@ -From 58ea1d895fbc7bf474153274a05cc4fad8fa44f4 Mon Sep 17 00:00:00 2001 -From: Gris Ge -Date: Wed, 11 Mar 2020 10:37:03 +0800 -Subject: [PATCH] nm bond: workaround on miimon=100 option - -The NM will ignore the `miimon=100`(the default option) when -wired/ethernet setting not included due to bug: - https://bugzilla.redhat.com/show_bug.cgi?id=1806549 - -This cause verification error when user try to set `miimon=100` on -existing bond. - -To workaround that, always include `miimon` option when querying bond -options. - -Integration test case included. - -Signed-off-by: Gris Ge - -In addition: - -nm applier: Sort interface creation/modification order - -The bond or bridge will take its first slave's MAC address, hence -NetworkManager by default will activate the slaves in the order of its -interface name. - -When nmstate create or editing bond/bridge, the `autoconnect` feature -will cause NetworkManager activating the slaves in unexpected order -which then generate different MAC address of bond and bridge. - -To fix this problem, sort the interface creation and modification order. - -Signed-off-by: Gris Ge ---- - libnmstate/nm/applier.py | 13 +++++++++++-- - libnmstate/nm/bond.py | 3 +++ - tests/integration/bond_test.py | 8 ++++++++ - tests/lib/nm/applier_test.py | 24 +++++++++++++++++------- - 4 files changed, 39 insertions(+), 9 deletions(-) - -diff --git a/libnmstate/nm/applier.py b/libnmstate/nm/applier.py -index 8d31e35..1291469 100644 ---- a/libnmstate/nm/applier.py -+++ b/libnmstate/nm/applier.py -@@ -20,6 +20,7 @@ - import base64 - import hashlib - import itertools -+from operator import attrgetter - - from libnmstate.error import NmstateValueError - from libnmstate.schema import Interface -@@ -57,7 +58,11 @@ IFACE_NAME_METADATA = "_iface_name" - - - def create_new_ifaces(con_profiles): -- for connection_profile in con_profiles: -+ # By default, NetworkManager will activate the slave profiles in the order -+ # of sorted interface name. To make sure user get the same MAC address -+ # after reboot for bond/bridge/etc, sort the interfaces to be created -+ # as autoconnect=True will activate the profile at the creation time. -+ for connection_profile in sorted(con_profiles, key=attrgetter("con_id")): - connection_profile.add(save_to_disk=True) - - -@@ -78,7 +83,11 @@ def prepare_new_ifaces_configuration(ifaces_desired_state): - - - def edit_existing_ifaces(con_profiles): -- for connection_profile in con_profiles: -+ # By default, NetworkManager will activate the slave profiles in the order -+ # of sorted interface name. To make sure user get the same MAC address -+ # after reboot for bond/bridge/etc, sort the interfaces to be updated -+ # as autoconnect=True will activate the profile at the profile update time. -+ for connection_profile in sorted(con_profiles, key=attrgetter("con_id")): - devname = connection_profile.devname - nmdev = device.get_device_by_name(devname) - cur_con_profile = None -diff --git a/libnmstate/nm/bond.py b/libnmstate/nm/bond.py -index b1291c4..310ef6e 100644 ---- a/libnmstate/nm/bond.py -+++ b/libnmstate/nm/bond.py -@@ -86,6 +86,9 @@ def _get_options(nm_device): - if option == "arp_ip_target": - value = value.replace(" ", ",") - options[option] = value -+ # Workaround of https://bugzilla.redhat.com/show_bug.cgi?id=1806549 -+ if "miimon" not in options: -+ options["miimon"] = bond_setting.get_option_default("miimon") - return options - - --- -2.24.1 - diff --git a/SOURCES/BZ_1815112-Support-static-dns-on-DHCP.patch b/SOURCES/BZ_1815112-Support-static-dns-on-DHCP.patch deleted file mode 100644 index 41e960c..0000000 --- a/SOURCES/BZ_1815112-Support-static-dns-on-DHCP.patch +++ /dev/null @@ -1,103 +0,0 @@ -From fd503cdcfb8138b1c181916050c4c0d5cc826ae7 Mon Sep 17 00:00:00 2001 -From: Gris Ge -Date: Thu, 19 Mar 2020 22:14:12 +0800 -Subject: [PATCH] dns: support static DNS with dynamic IP - -Added the support of static DNS configuration with dynamic IP interface as -long as specified interface has `InterfaceIP.AUTO_DNS` set to False. - -When choosing interface to storing DNS configuration, the interface with -static address and gateway is preferred over dynamic interface with -`InterfaceIP.AUTO_DNS` set to False. - -Added Unit test cases and integration test cases. - -Signed-off-by: Gris Ge ---- - libnmstate/metadata.py | 6 +----- - libnmstate/nm/dns.py | 34 +++++++++++++++++++++++++++++----- - 2 files changed, 30 insertions(+), 10 deletions(-) - -diff --git a/libnmstate/metadata.py b/libnmstate/metadata.py -index 37d6b96..b268ba3 100644 ---- a/libnmstate/metadata.py -+++ b/libnmstate/metadata.py -@@ -242,12 +242,8 @@ def _generate_dns_metadata(desired_state, current_state): - if _dns_config_not_changed(desired_state, current_state): - _preserve_current_dns_metadata(desired_state, current_state) - else: -- ifaces_routes = { -- ifname: [r.to_dict() for r in routes] -- for ifname, routes in desired_state.config_iface_routes.items() -- } - ipv4_iface, ipv6_iface = nm.dns.find_interfaces_for_name_servers( -- ifaces_routes -+ desired_state - ) - _save_dns_metadata( - desired_state, -diff --git a/libnmstate/nm/dns.py b/libnmstate/nm/dns.py -index 008b034..0ab28e4 100644 ---- a/libnmstate/nm/dns.py -+++ b/libnmstate/nm/dns.py -@@ -27,6 +27,8 @@ from libnmstate.nm import active_connection as nm_ac - from libnmstate.nm import route as nm_route - from libnmstate.schema import DNS - from libnmstate.schema import Interface -+from libnmstate.schema import InterfaceIP -+from libnmstate.schema import InterfaceIPv6 - - - DNS_DEFAULT_PRIORITY_VPN = 50 -@@ -123,17 +125,26 @@ def get_dns_config_iface_names(acs_and_ipv4_profiles, acs_and_ipv6_profiles): - return iface_names - - --def find_interfaces_for_name_servers(iface_routes): -+def find_interfaces_for_name_servers(desired_state): - """ - Find interfaces to store the DNS configurations: - * Interface with static gateway configured. -+ * Interface with dynamic IP and auto-dns: False. - 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), -- ) -+ iface_routes = { -+ ifname: [r.to_dict() for r in routes] -+ for ifname, routes in desired_state.config_iface_routes.items() -+ } -+ ipv4_iface = nm_route.get_static_gateway_iface( -+ Interface.IPV4, iface_routes -+ ) or _get_auto_dns_false_iface(Interface.IPV4, desired_state.interfaces) -+ -+ ipv6_iface = nm_route.get_static_gateway_iface( -+ Interface.IPV6, iface_routes -+ ) or _get_auto_dns_false_iface(Interface.IPV6, desired_state.interfaces) -+ return ipv4_iface, ipv6_iface - - - def get_indexed_dns_config_by_iface( -@@ -179,3 +190,16 @@ def _get_ip_profile_dns_config(ip_profile): - DNS.SEARCH: ip_profile.props.dns_search, - DNS_METADATA_PRIORITY: ip_profile.props.dns_priority, - } -+ -+ -+def _get_auto_dns_false_iface(family, iface_states): -+ for iface_name, iface_state in iface_states.items(): -+ ip_state = iface_state.get(family, {}) -+ if ip_state.get(InterfaceIP.ENABLED) and not ip_state.get( -+ InterfaceIP.AUTO_DNS -+ ): -+ if ip_state.get(InterfaceIP.DHCP) or ip_state.get( -+ InterfaceIPv6.AUTOCONF -+ ): -+ return iface_name -+ return None --- -2.18.2 - diff --git a/SOURCES/BZ_1816043_Support_3_nameserver.patch b/SOURCES/BZ_1816043_Support_3_nameserver.patch deleted file mode 100644 index 8307d8f..0000000 --- a/SOURCES/BZ_1816043_Support_3_nameserver.patch +++ /dev/null @@ -1,45 +0,0 @@ -From e4bfd9436500aa26dcc82d346039e8b1b886d64c Mon Sep 17 00:00:00 2001 -From: Gris Ge -Date: Wed, 25 Mar 2020 11:27:55 +0800 -Subject: [PATCH] dns: Enable support of 3+ unmixed DNS name server - -Support 3 or more IPv4/IPv6 only DNS name servers. -Still not supported 3+ IPv4 and IPv6 mixed name servers. - -A warning will be emitted when 4 or more DNS name severs defined. - -Integration test cases added. - -Signed-off-by: Gris Ge ---- - libnmstate/validator.py | 13 +++++++++++-- - 1 file changed, 11 insertions(+), 2 deletions(-) - -diff --git a/libnmstate/validator.py b/libnmstate/validator.py -index a817930..0e61858 100644 ---- a/libnmstate/validator.py -+++ b/libnmstate/validator.py -@@ -166,9 +166,18 @@ def validate_dns(state): - dns_servers = ( - state.get(DNS.KEY, {}).get(DNS.CONFIG, {}).get(DNS.SERVER, []) - ) -- if len(dns_servers) > 2: -+ if len(dns_servers) > 3: -+ logging.warning( -+ "The libc resolver may not support more than 3 nameservers." -+ ) -+ if ( -+ len(dns_servers) > 2 -+ and any(is_ipv6_address(n) for n in dns_servers) -+ and any(not is_ipv6_address(n) for n in dns_servers) -+ ): - raise NmstateNotImplementedError( -- "Nmstate only support at most 2 DNS name servers" -+ "Three or more nameservers are only supported when using " -+ "either IPv4 or IPv6 nameservers but not both." - ) - - --- -2.18.2 - diff --git a/SOURCES/BZ_1817466-use-kernel-runtime-bridge-status.patch b/SOURCES/BZ_1817466-use-kernel-runtime-bridge-status.patch deleted file mode 100644 index d75d82e..0000000 --- a/SOURCES/BZ_1817466-use-kernel-runtime-bridge-status.patch +++ /dev/null @@ -1,112 +0,0 @@ -From 3b5cfe36b1b754369cb8d3cc0d461068bf6bb8aa Mon Sep 17 00:00:00 2001 -From: Fernando Fernandez Mancera -Date: Wed, 25 Mar 2020 12:21:15 +0100 -Subject: [PATCH 06/10] nm.bridge: get ports from sysfs - -Unmanaged ports were not being shown when showing or editting the -bridge. In order to fix that, nmstate is retrieving the bridge ports -from sysfs instead of NetworkManager on-disk configuration. - -Ref: https://bugzilla.redhat.com/1806452 - -Signed-off-by: Fernando Fernandez Mancera ---- - libnmstate/nm/bridge.py | 55 +++++++++++++++++--------- - tests/integration/linux_bridge_test.py | 34 ++++++++++++++++ - 2 files changed, 71 insertions(+), 18 deletions(-) - -diff --git a/libnmstate/nm/bridge.py b/libnmstate/nm/bridge.py -index e0ab8e4..672214d 100644 ---- a/libnmstate/nm/bridge.py -+++ b/libnmstate/nm/bridge.py -@@ -17,6 +17,9 @@ - # along with this program. If not, see . - # - -+import glob -+import os -+ - from libnmstate.error import NmstateNotImplementedError - from libnmstate.nm import connection - from libnmstate.nm import nmclient -@@ -25,6 +28,12 @@ from libnmstate.schema import LinuxBridge as LB - - BRIDGE_TYPE = "bridge" - -+BRIDGE_PORT_NMSTATE_TO_SYSFS = { -+ LB.Port.STP_HAIRPIN_MODE: "hairpin_mode", -+ LB.Port.STP_PATH_COST: "path_cost", -+ LB.Port.STP_PRIORITY: "priority", -+} -+ - - def create_setting(options, base_con_profile): - bridge_setting = _get_current_bridge_setting(base_con_profile) -@@ -106,10 +115,10 @@ def get_info(nmdev): - if not bridge_setting: - return info - -- port_profiles = _get_slave_profiles(nmdev) -+ port_names_sysfs = _get_slaves_names_from_sysfs(nmdev.get_iface()) - props = bridge_setting.props - info[LB.CONFIG_SUBTREE] = { -- LB.PORT_SUBTREE: _get_bridge_ports_info(port_profiles), -+ LB.PORT_SUBTREE: _get_bridge_ports_info(port_names_sysfs), - LB.OPTIONS_SUBTREE: { - LB.Options.MAC_AGEING_TIME: props.ageing_time, - LB.Options.GROUP_FORWARD_MASK: props.group_forward_mask, -@@ -139,25 +148,35 @@ def _get_bridge_setting(nmdev): - return bridge_setting - - --def _get_bridge_ports_info(port_profiles): -- ports_info = [] -- for p in port_profiles: -- port_info = _get_bridge_port_info(p) -- if port_info: -- ports_info.append(port_info) -- return ports_info -+def _get_bridge_ports_info(port_names_sysfs): -+ return [_get_bridge_port_info(name) for name in port_names_sysfs] - - --def _get_bridge_port_info(port_profile): -- """Report port information.""" -+def _get_bridge_port_info(port_name): -+ """Report port runtime information from sysfs.""" -+ port = {LB.Port.NAME: port_name} -+ for option, option_sysfs in BRIDGE_PORT_NMSTATE_TO_SYSFS.items(): -+ sysfs_path = f"/sys/class/net/{port_name}/brport/{option_sysfs}" -+ with open(sysfs_path) as f: -+ option_value = int(f.read()) -+ if option == LB.Port.STP_HAIRPIN_MODE: -+ option_value = bool(option_value) -+ port[option] = option_value -+ return port - -- port_setting = port_profile.get_setting_bridge_port() -- return { -- LB.Port.NAME: port_profile.get_interface_name(), -- LB.Port.STP_PRIORITY: port_setting.props.priority, -- LB.Port.STP_HAIRPIN_MODE: port_setting.props.hairpin_mode, -- LB.Port.STP_PATH_COST: port_setting.props.path_cost, -- } -+ -+def _get_slaves_names_from_sysfs(master): -+ """ -+ We need to use glob in order to get the slaves name due to bug in -+ NetworkManager. -+ Ref: https://bugzilla.redhat.com/show_bug.cgi?id=1809547 -+ """ -+ slaves = [] -+ for sysfs_slave in glob.iglob(f"/sys/class/net/{master}/lower_*"): -+ # The format is lower_, we need to remove the "lower_" prefix -+ prefix_length = len("lower_") -+ slaves.append(os.path.basename(sysfs_slave)[prefix_length:]) -+ return slaves - - - def _get_slave_profiles(master_device): --- -2.25.1 - diff --git a/SOURCES/BZ_1817477-retry-verification-after-failing.patch b/SOURCES/BZ_1817477-retry-verification-after-failing.patch deleted file mode 100644 index 295728a..0000000 --- a/SOURCES/BZ_1817477-retry-verification-after-failing.patch +++ /dev/null @@ -1,212 +0,0 @@ -From 73d51a5f40b21010a35ce0b33fa5738ddbb8f97d Mon Sep 17 00:00:00 2001 -From: Fernando Fernandez Mancera -Date: Mon, 16 Mar 2020 11:53:28 +0100 -Subject: [PATCH 03/10] netapplier: retry verification after failing - -When failing on verification nmstate is retrying it up to 5 times with a -sleep interval of 1 seconds. This will fix two issues: - - * During the verification sometimes ethtool is reporting 'unknown' in - duplex state. This is due a lack of time for some NICs to update the - information. We have noticed it only with Broadcom BCM57840 NetXtreme II - NIC but it could affect to other NICs. - - * When switching from DHCP without DHCP server to static IPV6(IPv4 - disabled), the nmstate will fail with verification failure showing IPv6 - is still disabled. - -Signed-off-by: Fernando Fernandez Mancera - -In addition: - -netapplier: do not modify the desired_state during verification - -The desired_state is being modified during verification. Instead of -modifying the desired_state, nmstate should make a copy of it and then -modify the copy. - -Signed-off-by: Fernando Fernandez Mancera - -In addition: - -nm.nmclient: remove delayed quit from the mainloop - -The delayed quit is not needed anymore as nmstate is retrying the -verification step up to five times with an sleep interval of one second. - -Signed-off-by: Fernando Fernandez Mancera - -In addition: - -nm.checkpoint: fix incorrect interval when adding a timer - -According to GLib documentation the interval specified when using -timeout_add() is on miliseconds. - -Signed-off-by: Fernando Fernandez Mancera - -In addition: - -nm sriov: Properly return when device not exists - -When interface does not exists, the `nm.sriov._has_sriov_capability()` -will raise: - -```python - def _has_sriov_capability(ifname): - dev = device.get_device_by_name(ifname) -> if nmclient.NM.DeviceCapabilities.SRIOV & dev.props.capabilities: -E AttributeError: 'NoneType' object has no attribute 'props' -``` - -Fixed by add additional check on whether device is None. - -Also fixed the integration test which incorrectly using eth0 which is -not test NIC, changed to eth1. - -Signed-off-by: Gris Ge -Signed-off-by: Fernando Fernandez Mancera - -In addition: - -nm.sriov: fix typo in sr-iov device capabilities - -Signed-off-by: Fernando Fernandez Mancera ---- - examples/eth1_with_sriov.yml | 13 +++++++++++++ - libnmstate/netapplier.py | 24 +++++++++++++++++++----- - libnmstate/nm/checkpoint.py | 2 +- - libnmstate/nm/nmclient.py | 16 ++-------------- - libnmstate/nm/sriov.py | 7 +++---- - tests/integration/examples_test.py | 14 ++++++++++++++ - 6 files changed, 52 insertions(+), 24 deletions(-) - create mode 100644 examples/eth1_with_sriov.yml - -diff --git a/libnmstate/netapplier.py b/libnmstate/netapplier.py -index d9d10cf..e001793 100644 ---- a/libnmstate/netapplier.py -+++ b/libnmstate/netapplier.py -@@ -36,9 +36,12 @@ from libnmstate.error import NmstateError - from libnmstate.error import NmstateLibnmError - from libnmstate.error import NmstatePermissionError - from libnmstate.error import NmstateValueError -+from libnmstate.error import NmstateVerificationError - from libnmstate.nm import nmclient - - MAINLOOP_TIMEOUT = 35 -+VERIFY_RETRY_INTERNAL = 1 -+VERIFY_RETRY_TIMEOUT = 5 - - - @_warn_keyword_as_positional -@@ -159,8 +162,18 @@ def _apply_ifaces_state( - ifaces2add + ifaces2edit, - con_profiles=ifaces_add_configs + ifaces_edit_configs, - ) -+ verified = False - if verify_change: -- _verify_change(desired_state) -+ for _ in range(VERIFY_RETRY_TIMEOUT): -+ try: -+ _verify_change(desired_state) -+ verified = True -+ break -+ except NmstateVerificationError: -+ time.sleep(VERIFY_RETRY_INTERNAL) -+ if not verified: -+ _verify_change(desired_state) -+ - if not commit: - return checkpoint - except nm.checkpoint.NMCheckPointPermissionError: -@@ -204,10 +217,11 @@ def _list_new_interfaces(desired_state, current_state): - - def _verify_change(desired_state): - current_state = state.State(netinfo.show()) -- desired_state.verify_interfaces(current_state) -- desired_state.verify_routes(current_state) -- desired_state.verify_dns(current_state) -- desired_state.verify_route_rule(current_state) -+ verifiable_desired_state = copy.deepcopy(desired_state) -+ verifiable_desired_state.verify_interfaces(current_state) -+ verifiable_desired_state.verify_routes(current_state) -+ verifiable_desired_state.verify_dns(current_state) -+ verifiable_desired_state.verify_route_rule(current_state) - - - @contextmanager -diff --git a/libnmstate/nm/checkpoint.py b/libnmstate/nm/checkpoint.py -index bb8f5d6..771a46b 100644 ---- a/libnmstate/nm/checkpoint.py -+++ b/libnmstate/nm/checkpoint.py -@@ -127,7 +127,7 @@ class CheckPoint: - raise NMCheckPointCreationError(str(e)) - - GLib.timeout_add( -- self._timeout * 0.5, self._refresh_checkpoint_timeout, None, -+ self._timeout * 500, self._refresh_checkpoint_timeout, None, - ) - - def _refresh_checkpoint_timeout(self, data): -diff --git a/libnmstate/nm/nmclient.py b/libnmstate/nm/nmclient.py -index 31c6020..cc5ee9b 100644 ---- a/libnmstate/nm/nmclient.py -+++ b/libnmstate/nm/nmclient.py -@@ -41,8 +41,6 @@ GObject - _mainloop = None - _nmclient = None - --MAINLOOP_TEARDOWN_DELAY = 500 # msec -- - NM_MANAGER_ERROR_DOMAIN = "nm-manager-error-quark" - _NMCLIENT_CLEANUP_TIMEOUT = 5 - -@@ -138,7 +136,8 @@ class _MainLoop: - logging.debug("Executing NM action: func=%s", func.__name__) - func(*args, **kwargs) - else: -- self._execute_teardown_action() -+ logging.debug("NM action queue exhausted, quiting mainloop") -+ self._mainloop.quit() - - def push_action(self, func, *args, **kwargs): - action = (func, args, kwargs) -@@ -245,17 +244,6 @@ class _MainLoop: - self.execute_next_action() - return False - -- def _execute_teardown_action(self): -- # Some actions are not getting updated fast enough in the -- # kernel/cache. Wait a bit before quitting the mainloop. -- GLib.timeout_add( -- MAINLOOP_TEARDOWN_DELAY, self._execute_graceful_quit, None -- ) -- -- def _execute_graceful_quit(self, _): -- logging.debug("NM action queue exhausted, quiting mainloop") -- self._mainloop.quit() -- - - class _NmClient: - def __init__(self): -diff --git a/libnmstate/nm/sriov.py b/libnmstate/nm/sriov.py -index 2a627cc..cfc0f9a 100644 ---- a/libnmstate/nm/sriov.py -+++ b/libnmstate/nm/sriov.py -@@ -129,10 +129,9 @@ def _remove_sriov_vfs_in_setting(vfs_config, sriov_setting, vf_ids_to_remove): - - def _has_sriov_capability(ifname): - dev = device.get_device_by_name(ifname) -- if nmclient.NM.DeviceCapabilities.SRIOV & dev.props.capabilities: -- return True -- -- return False -+ return dev and ( -+ nmclient.NM.DeviceCapabilities.SRIOV & dev.props.capabilities -+ ) - - - def get_info(device): --- -2.25.1 - diff --git a/SOURCES/BZ_1817478-allow-missing-arp-ip-target-if-arp-interval-is-disabled.patch b/SOURCES/BZ_1817478-allow-missing-arp-ip-target-if-arp-interval-is-disabled.patch deleted file mode 100644 index d76fa81..0000000 --- a/SOURCES/BZ_1817478-allow-missing-arp-ip-target-if-arp-interval-is-disabled.patch +++ /dev/null @@ -1,84 +0,0 @@ -From 37f47c373a99771d42799941ba96cf4f8a173c75 Mon Sep 17 00:00:00 2001 -From: Gris Ge -Date: Thu, 26 Mar 2020 19:50:03 +0800 -Subject: [PATCH 09/10] state: allow missing arp_ip_target when ARP monitoring - disabled - -Got verification failure when disabling `arp_interval` of existing bond -regarding `arp_ip_target: ''` not included in new state. - -This is because NetworkManager does not store `arp_ip_target: ''` in -on-disk profile when `arp_interval` is zero/disabled. - -The fix is allowing backend to skip `arp_ip_target` when ARP monitoring -is disabled(`arp_interval==0`) by fix the bond option before -verification. - -Added function `libnmstate.applier.bond.iface_state_pre_verify_fix()`. - -Introduced `self._pre_verification_fix()` to `State.verify_interfaces()` -allowing `state.py` to delegating state modification to interface -specific function without knowing the detail. - -Integration test case added. - -Signed-off-by: Gris Ge ---- - libnmstate/appliers/bond.py | 13 +++++++++ - libnmstate/state.py | 10 +++++++ - tests/integration/bond_test.py | 39 +++++++++++++++++++++++--- - tests/integration/testlib/assertlib.py | 21 ++++++++++++++ - 4 files changed, 79 insertions(+), 4 deletions(-) - -diff --git a/libnmstate/appliers/bond.py b/libnmstate/appliers/bond.py -index 785d8f3..5602adb 100644 ---- a/libnmstate/appliers/bond.py -+++ b/libnmstate/appliers/bond.py -@@ -113,3 +113,16 @@ def get_bond_named_option_value_by_id(option_name, option_id_value): - with contextlib.suppress(ValueError, IndexError): - return option_value[int(option_id_value)] - return option_id_value -+ -+ -+def fix_bond_option_arp_monitor(cur_iface_state): -+ """ -+ Fix the current iface_state by -+ adding 'arp_ip_target=""' when ARP monitor is disabled by `arp_interval=0` -+ """ -+ bond_options = cur_iface_state[Bond.CONFIG_SUBTREE][Bond.OPTIONS_SUBTREE] -+ if ( -+ bond_options.get("arp_interval") in ("0", 0) -+ and "arp_ip_target" not in bond_options -+ ): -+ bond_options["arp_ip_target"] = "" -diff --git a/libnmstate/state.py b/libnmstate/state.py -index 960558a..98be33d 100644 ---- a/libnmstate/state.py -+++ b/libnmstate/state.py -@@ -321,6 +321,7 @@ class State: - - metadata.remove_ifaces_metadata(self) - other_state.sanitize_dynamic_ip() -+ other_state._pre_verification_fix() - - self.merge_interfaces(other_state) - -@@ -329,6 +330,15 @@ class State: - - self._assert_interfaces_equal(other_state) - -+ def _pre_verification_fix(self): -+ """ -+ Invoking iface specific fixes. -+ Supposed to only run againt current state. -+ """ -+ for iface_state in self.interfaces.values(): -+ if iface_state.get(Interface.TYPE) == InterfaceType.BOND: -+ bond.fix_bond_option_arp_monitor(iface_state) -+ - def verify_routes(self, other_state): - for iface_name, routes in self.config_iface_routes.items(): - other_routes = other_state.config_iface_routes.get(iface_name, []) --- -2.25.1 - diff --git a/SOURCES/BZ_1819738-Don-t-merge-bond-options-when-bond-mode-changed.patch b/SOURCES/BZ_1819738-Don-t-merge-bond-options-when-bond-mode-changed.patch deleted file mode 100644 index 7703150..0000000 --- a/SOURCES/BZ_1819738-Don-t-merge-bond-options-when-bond-mode-changed.patch +++ /dev/null @@ -1,211 +0,0 @@ -From 238fb9542c4365ae13f6b4f0c2cd6ffcd427e561 Mon Sep 17 00:00:00 2001 -From: Gris Ge -Date: Wed, 1 Apr 2020 20:26:40 +0800 -Subject: [PATCH] bond: Don't merge bond options when bond mode changed - -When changing bond mode, user is required to provide all bond options -and no bond options will be merged from current state. - -When changing bond mode, full deactivation is required in NetworkManager -do to bug https://bugzilla.redhat.com/show_bug.cgi?id=1819137 - -Procedure to fix this issue: - * Generate a metadata if bond mode changed. - * After merge, use desire bond option only if bond mode changed. - * In NM profile modification, deactivate the interface before - modification if bond mode changed. - -Added integration test case and unit test cases. - -Signed-off-by: Gris Ge ---- - libnmstate/appliers/bond.py | 62 +++++++++++++++++++++++++++++++++++++ - libnmstate/metadata.py | 2 ++ - libnmstate/nm/applier.py | 18 +++++++++++ - libnmstate/state.py | 9 ++++++ - 4 files changed, 91 insertions(+) - -diff --git a/libnmstate/appliers/bond.py b/libnmstate/appliers/bond.py -index 5602adb..2a3f0a1 100644 ---- a/libnmstate/appliers/bond.py -+++ b/libnmstate/appliers/bond.py -@@ -18,9 +18,16 @@ - # - - import contextlib -+import logging - - from libnmstate.schema import Bond - from libnmstate.schema import BondMode -+from libnmstate.schema import Interface -+from libnmstate.schema import InterfaceState -+from libnmstate.schema import InterfaceType -+ -+BOND_MODE_CHANGED_METADATA = "_bond_mode_changed" -+NON_UP_STATES = (InterfaceState.DOWN, InterfaceState.ABSENT) - - - class BondNamedOptions: -@@ -126,3 +133,58 @@ def fix_bond_option_arp_monitor(cur_iface_state): - and "arp_ip_target" not in bond_options - ): - bond_options["arp_ip_target"] = "" -+ -+ -+def generate_bond_mode_change_metadata(desire_state, current_state): -+ for iface_name, iface_state in desire_state.interfaces.items(): -+ current_iface_state = current_state.interfaces.get(iface_name, {}) -+ if ( -+ iface_state.get( -+ Interface.TYPE, current_iface_state.get(Interface.TYPE) -+ ) -+ != InterfaceType.BOND -+ ): -+ continue -+ if iface_state.get(Interface.STATE) in NON_UP_STATES: -+ # Ignore bond mode change on absent/down interface -+ continue -+ current_bond_mode = current_iface_state.get( -+ Bond.CONFIG_SUBTREE, {} -+ ).get(Bond.MODE) -+ desire_bond_mode = iface_state.get(Bond.CONFIG_SUBTREE, {}).get( -+ Bond.MODE -+ ) -+ if ( -+ desire_bond_mode -+ and current_bond_mode -+ and desire_bond_mode != current_bond_mode -+ ): -+ logging.warning( -+ "Discarding all current bond options as interface " -+ f"{iface_name} has bond mode changed" -+ ) -+ iface_state[BOND_MODE_CHANGED_METADATA] = True -+ -+ -+def remove_bond_mode_change_metadata(iface_state): -+ iface_state.pop(BOND_MODE_CHANGED_METADATA, None) -+ -+ -+def is_bond_mode_changed(iface_state): -+ return iface_state.get(BOND_MODE_CHANGED_METADATA) -+ -+ -+def discard_merged_data_on_mode_change(merged_iface_state, desire_iface_state): -+ """ -+ When bond mode changed, use original desire bond options instead of merging -+ from current state. -+ """ -+ if is_bond_mode_changed(merged_iface_state): -+ if merged_iface_state.get(Bond.CONFIG_SUBTREE, {}).get( -+ Bond.OPTIONS_SUBTREE -+ ): -+ merged_iface_state[Bond.CONFIG_SUBTREE][ -+ Bond.OPTIONS_SUBTREE -+ ] = desire_iface_state[Bond.CONFIG_SUBTREE].get( -+ Bond.OPTIONS_SUBTREE, {} -+ ) -diff --git a/libnmstate/metadata.py b/libnmstate/metadata.py -index b268ba3..bdc8b3c 100644 ---- a/libnmstate/metadata.py -+++ b/libnmstate/metadata.py -@@ -53,6 +53,7 @@ def generate_ifaces_metadata(desired_state, current_state): - metadata is generated on interfaces, usable by the provider when - configuring the interface. - """ -+ bond.generate_bond_mode_change_metadata(desired_state, current_state) - _generate_link_master_metadata( - desired_state.interfaces, - current_state.interfaces, -@@ -91,6 +92,7 @@ def remove_ifaces_metadata(ifaces_state): - iface_state.pop(MASTER, None) - iface_state.pop(MASTER_TYPE, None) - iface_state.pop(BRPORT_OPTIONS, None) -+ bond.remove_bond_mode_change_metadata(iface_state) - iface_state.get(Interface.IPV4, {}).pop(ROUTES, None) - iface_state.get(Interface.IPV6, {}).pop(ROUTES, None) - iface_state.get(Interface.IPV4, {}).pop(DNS_METADATA, None) -diff --git a/libnmstate/nm/applier.py b/libnmstate/nm/applier.py -index 1291469..1ca0647 100644 ---- a/libnmstate/nm/applier.py -+++ b/libnmstate/nm/applier.py -@@ -18,6 +18,7 @@ - # - - import base64 -+import logging - import hashlib - import itertools - from operator import attrgetter -@@ -28,6 +29,7 @@ from libnmstate.schema import InterfaceState - from libnmstate.schema import InterfaceType - from libnmstate.schema import LinuxBridge as LB - from libnmstate.schema import OVSBridge as OvsB -+from libnmstate.appliers.bond import is_bond_mode_changed - - from . import bond - from . import bridge -@@ -169,6 +171,7 @@ def set_ifaces_admin_state(ifaces_desired_state, con_profiles=()): - master_ifaces_to_edit = set() - ifaces_to_edit = set() - remove_devs_actions = {} -+ devs_to_deactivate_beforehand = [] - - for iface_desired_state in ifaces_desired_state: - ifname = iface_desired_state[Interface.NAME] -@@ -199,6 +202,18 @@ def set_ifaces_admin_state(ifaces_desired_state, con_profiles=()): - new_ifaces_to_activate.add(ifname) - else: - if iface_desired_state[Interface.STATE] == InterfaceState.UP: -+ if is_bond_mode_changed(iface_desired_state): -+ # NetworkManager leaves leftover in sysfs for bond -+ # options when changing bond mode, bug: -+ # https://bugzilla.redhat.com/show_bug.cgi?id=1819137 -+ # Workaround: delete the bond interface from kernel and -+ # create again via full deactivation beforehand. -+ logging.debug( -+ f"Bond interface {ifname} is changing bond mode, " -+ "will do full deactivation before applying changes" -+ ) -+ devs_to_deactivate_beforehand.append(nmdev) -+ - if _is_master_iface(iface_desired_state): - master_ifaces_to_edit.add( - (nmdev, con_profiles_by_devname[ifname].profile) -@@ -230,6 +245,9 @@ def set_ifaces_admin_state(ifaces_desired_state, con_profiles=()): - ) - ) - -+ for dev in devs_to_deactivate_beforehand: -+ device.deactivate(dev) -+ - # Do not remove devices that are marked for editing. - for dev, _ in itertools.chain(master_ifaces_to_edit, ifaces_to_edit): - remove_devs_actions.pop(dev, None) -diff --git a/libnmstate/state.py b/libnmstate/state.py -index 98be33d..12bc414 100644 ---- a/libnmstate/state.py -+++ b/libnmstate/state.py -@@ -390,10 +390,19 @@ class State: - entries that appear only on one state are ignored. - This is a reverse recursive update operation. - """ -+ origin_self_state = State(self.state) - other_state = State(other_state.state) - for name in self.interfaces.keys() & other_state.interfaces.keys(): - dict_update(other_state.interfaces[name], self.interfaces[name]) - self._ifaces_state[name] = other_state.interfaces[name] -+ iface_state = self.interfaces[name] -+ if iface_state.get(Interface.TYPE) == InterfaceType.BOND: -+ origin_self_iface_state = origin_self_state.interfaces.get( -+ name -+ ) -+ bond.discard_merged_data_on_mode_change( -+ iface_state, origin_self_iface_state -+ ) - - def complement_master_interfaces_removal(self, other_state): - """ --- -2.18.2 - diff --git a/SOURCES/nmstate-0.2.10.tar.gz.asc b/SOURCES/nmstate-0.2.10.tar.gz.asc new file mode 100644 index 0000000..6a2ad0a --- /dev/null +++ b/SOURCES/nmstate-0.2.10.tar.gz.asc @@ -0,0 +1,17 @@ +-----BEGIN PGP SIGNATURE----- +Version: GnuPG v2.0.22 (GNU/Linux) + +iQIcBAABAgAGBQJenrWKAAoJEImQFMBGPBK7qPwQAMNvomlJRYIcU+/aAz87mDk3 +UGBV6JpXraID7T2xejHL4nEynuT4ib/iguLTrrkBXXDMgVCWsHJwqlL4Q0h9ptoO +M2/EJRmXZTEfJUlf1kWk6ODoQ5NJNpCLC+Ip0BMzO0zJysjdKsqDvSm5Cw650syE +8SI69Jj/UpOd/Nv8pgHsbhjejMcYIC6CfLiinEB1q/AtZC+tvvrxfmZzp+g3mbaM +tm1yNdsQRVB4w41h4yRFO44VWWg9AN+LoxrCUePONNCKbecf0tEBCnrBrK2hxdak +LGrAHMSN/F2MPaayULhyyZbbRQIsF2099XJs7e9uYayiHyOgh1N/dX+TC9ridFWM +XlnU2SvVHCUwtwr5CGAOW7VWcggoE48/QDl8RVj53gHat29Ry/GM9gbpSWVneFqi +InovzvfjNV0V/+l7Ug21LkkBHsIYJ22Fj6X7IEekijCz+x4zOcl2xHY7SKiVcnVs +/sYO0vBVnPUVS91CMVXvsUYmRfnDkMsiKvmFxVud1WpZeTgd1AW4zg3M1ueelDFi +c8aqYZr3/ziBvR1wjCz8kKYp3VhCQWRd4PjS6fqfY+cuuVxGdyzxBFYqK/h+D2AT +mk23RDMNpx+vGfa2cVLRMOSGfADxelRaRdo1TS2qKTpjE0ukM7FWhY3rRONiw4tL +5HKl5RrTQRfqMk2onmX3 +=cS1L +-----END PGP SIGNATURE----- diff --git a/SOURCES/nmstate-0.2.6.tar.gz.asc b/SOURCES/nmstate-0.2.6.tar.gz.asc deleted file mode 100644 index 80b3de2..0000000 --- a/SOURCES/nmstate-0.2.6.tar.gz.asc +++ /dev/null @@ -1,17 +0,0 @@ ------BEGIN PGP SIGNATURE----- -Version: GnuPG v2.0.22 (GNU/Linux) - -iQIcBAABAgAGBQJeVA3fAAoJEImQFMBGPBK7ZckQAJ3jBlRhfrcx/3c6W/oHdxNG -KK5k1pgWFbrYlNtg8KG7Oey19EBaZCtGKTo76nwYqW0826bFpX2XaEpYwtesD445 -aAKCa09PfTTHKI1fL1M86I8qUHuMNLnT2bYvVZRgyAIp4RV+6rc+1F20bVSf0diy -UX6n+J3bBOZQ+Vlr4YP6RVAf0JW+KFTXgQC4O7ssHxGHOAQAUTiwhO6dOqDlvI/0 -RkDXg2axyYHJCoh8pH4hXC6j6N9D63xjl7tlNCqICYyens+A+PRWgVDXkwoxQRB1 -b3pLwN8Cm9VClzB5EQmhoEQOyVfR0B2+y+QMr9wqPfDlW5r81Blvg/ZZ7/ahlVUI -fcY1J7/nMcHCMBFtnXAYlgpexYrZ/GGb7zKGAMczQMYhIoz07dyG0F7Ltk1+8g50 -RJP0fvmxDDmnhDwEWr8Sac+PmV8TAqkyNi1/54yL6ajZ1Vk1S+0Yg11vMT+IW6Q5 -SZv1udqombL7Yo3W7ta+ynP8ncZoS3Y9bHQito7O7N93wZrUFTc/X8UxhI/7Nrgv -YtQD2FT8FqTkSUK28TQyx0I51VG8PnXeeOAFgNwih30k6OoXtvHFDXLnAc+RlNBD -XxSbfPSuFxPzaexcxmdLfZKq+xcJqS7osEs0PFkOCPNuS4uDymEEsv7aC4GexWuS -bam/Yy2TBZtkDRZE3QEE -=o/C+ ------END PGP SIGNATURE----- diff --git a/SPECS/nmstate.spec b/SPECS/nmstate.spec index afefec7..d6f79eb 100644 --- a/SPECS/nmstate.spec +++ b/SPECS/nmstate.spec @@ -3,23 +3,14 @@ %define libname libnmstate Name: nmstate -Version: 0.2.6 -Release: 13%{?dist} +Version: 0.2.10 +Release: 1%{?dist} Summary: Declarative network manager API License: LGPLv2+ URL: https://github.com/%{srcname}/%{srcname} Source0: %{url}/releases/download/v%{version}/%{srcname}-%{version}.tar.gz Source1: %{url}/releases/download/v%{version}/%{srcname}-%{version}.tar.gz.asc Source2: gpgkey-F7910D93CA83D77348595C0E899014C0463C12BB.gpg -Patch1: BZ_1806249-ActiveConnection-Handle-uninitialized-device.patch -Patch2: BZ_1809330-Bond-mode-change.patch -Patch3: BZ_1809330-Fix-bond-regression.patch -Patch4: BZ_1815112-Support-static-dns-on-DHCP.patch -Patch5: BZ_1816043_Support_3_nameserver.patch -Patch6: BZ_1817477-retry-verification-after-failing.patch -Patch7: BZ_1817466-use-kernel-runtime-bridge-status.patch -Patch8: BZ_1817478-allow-missing-arp-ip-target-if-arp-interval-is-disabled.patch -Patch9: BZ_1819738-Don-t-merge-bond-options-when-bond-mode-changed.patch BuildArch: noarch BuildRequires: python3-devel BuildRequires: python3-setuptools @@ -36,7 +27,7 @@ provider support on the southbound. %package -n python3-%{libname} Summary: nmstate Python 3 API library -Requires: NetworkManager-libnm >= 1:1.22 +Requires: NetworkManager-libnm >= 1:1.22.8 # Use Recommends for NetworkManager because only access to NM DBus is required, # but NM could be running on a different host Recommends: NetworkManager @@ -74,26 +65,11 @@ gpgv2 --keyring %{SOURCE2} %{SOURCE1} %{SOURCE0} %{python3_sitelib}/%{srcname}-*.egg-info/ %changelog -* Thu Apr 09 2020 Gris Ge - 0.2.6-13 -- Don't merge bond option when mode changed. RHBZ #1819738 +* Tue Apr 21 2020 Fernando Fernandez Mancera - 0.2.10-1 +- Upgrade to 0.2.10 -* Thu Apr 09 2020 Gris Ge - 0.2.6-12 -- Rebuild due to failure of RCM tagging system. - -* Wed Apr 01 2020 Gris Ge - 0.2.6-11 -- Rebuild due to failure of RCM tagging system. - -* Wed Apr 01 2020 Gris Ge - 0.2.6-10 -- Dump the build number for z-stream. - -* Fri Mar 27 2020 Fernando Fernandez Mancera - 0.2.6-9 -- Allow missing arp_ip_target when ARP monitoring is disabled. RHBZ #1817478 - -* Fri Mar 27 2020 Fernando Fernandez Mancera - 0.2.6-8 -- Fix missing linux bridge slaves reporting. RHBZ #1817466 - -* Fri Mar 27 2020 Fernando Fernandez Mancera - 0.2.6-7 -- Fix verification errors due to outdated values. RHBZ #1817477 +* Tue Mar 31 2020 Fernando Fernandez Mancera - 0.2.9-1 +- Upgrade to 0.2.9 * Wed Mar 25 2020 Gris Ge - 0.2.6-6 - Support 3+ DNS name server(IPv4 only or IPv6 only). RHBZ #1816043