Compare commits

...

No commits in common. "c8" and "c9" have entirely different histories.
c8 ... c9

11 changed files with 640 additions and 701 deletions

4
.gitignore vendored
View File

@ -1,2 +1,2 @@
SOURCES/nmstate-1.4.6.tar.gz SOURCES/nmstate-2.2.60.tar.gz
SOURCES/nmstate-vendor-1.4.6.tar.xz SOURCES/nmstate-vendor-2.2.60.tar.xz

View File

@ -1,2 +1,2 @@
2c5d46ae03fe2d836e165aa3562f03386d215fdf SOURCES/nmstate-1.4.6.tar.gz c0fac9220cfc06e6d1e53faff7491aadc75bace9 SOURCES/nmstate-2.2.60.tar.gz
4735ef08c31684624a7844832cc2ba20e67983f6 SOURCES/nmstate-vendor-1.4.6.tar.xz bf188a605750e38132df90b4709297b749915521 SOURCES/nmstate-vendor-2.2.60.tar.xz

View File

@ -1,60 +0,0 @@
From 0b530d4c8e75f60015d13c225b1c634389fbe798 Mon Sep 17 00:00:00 2001
From: Gris Ge <fge@redhat.com>
Date: Fri, 17 May 2024 13:12:14 +0800
Subject: [PATCH] clib: Use build.rs to fix SONAME
Use [`cargo:rustc-cdylib-link-arg`][1] to `build.rs` to fix the SONAME issue
of cargo.
Removed workarounds in rpm spec and `.cargo/config.toml`.
Changed Makefile to place `-lnmstate` after the source file to fix
compile issue on ubuntu 20.04 old gcc.
[1]: https://doc.rust-lang.org/cargo/reference/build-scripts.html#rustc-cdylib-link-arg
Signed-off-by: Gris Ge <fge@redhat.com>
---
rust/.cargo/config.toml | 3 ---
rust/src/clib/Cargo.toml | 1 +
rust/src/clib/build.rs | 6 ++++++
3 files changed, 7 insertions(+), 3 deletions(-)
create mode 100644 rust/src/clib/build.rs
diff --git a/rust/.cargo/config.toml b/rust/.cargo/config.toml
index 018e59d4..ca6c72f7 100644
--- a/rust/.cargo/config.toml
+++ b/rust/.cargo/config.toml
@@ -1,5 +1,2 @@
-[build]
-rustflags = "-Clink-arg=-Wl,-soname=libnmstate.so.1"
-
[target.x86_64-unknown-linux-gnu]
runner = 'sudo -E'
diff --git a/rust/src/clib/Cargo.toml b/rust/src/clib/Cargo.toml
index 462757ca..0eb00922 100644
--- a/rust/src/clib/Cargo.toml
+++ b/rust/src/clib/Cargo.toml
@@ -6,6 +6,7 @@ authors = ["Gris Ge <fge@redhat.com>"]
license = "Apache-2.0"
edition = "2018"
rust-version = "1.58"
+build = "build.rs"
[lib]
name = "nmstate"
diff --git a/rust/src/clib/build.rs b/rust/src/clib/build.rs
new file mode 100644
index 00000000..74ad7e48
--- /dev/null
+++ b/rust/src/clib/build.rs
@@ -0,0 +1,6 @@
+// SPDX-License-Identifier: Apache-2.0
+
+fn main() {
+ #[cfg(target_os = "linux")]
+ println!("cargo:rustc-cdylib-link-arg=-Wl,-soname=libnmstate.so.1");
+}
--
2.45.1

View File

@ -0,0 +1,63 @@
From 18fce5de48c2687131eab604c31c4738ffc2554c Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?=C3=8D=C3=B1igo=20Huguet?= <ihuguet@riseup.net>
Date: Mon, 4 May 2026 07:24:15 +0200
Subject: [PATCH] infiniband: restore detection of Ipoib iface type
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
Fixes 5e13d3f "Prefer LinkInfo::Kind as interface type". This commit
made to always prefer InfoKind over anything for Ethernet, but at the
same time it made to prefer LinkLayerType over InfoKind for Infiniband.
This causes that the Ipoib iface typeis not detected anymore, causing
two problems:
- Interfaces previously detected as Ipoib are now detected as
Infiniband, breaking some clients like nmstate.
- The Ipoib data is not parsed, as it is only done for Ipoib iface type.
Fix it by prefering the "Infiniband" generic type only if no InfoKind
was detected, or InfoKind::Other was detected.
Signed-off-by: Íñigo Huguet <ihuguet@riseup.net>
---
src/lib/query/iface.rs | 23 ++++++++++++++++-------
1 file changed, 16 insertions(+), 7 deletions(-)
diff --git a/src/lib/query/iface.rs b/src/lib/query/iface.rs
index 9e21070..cce4f40 100644
--- a/vendor/nispor/query/iface.rs
+++ b/vendor/nispor/query/iface.rs
@@ -420,14 +420,23 @@ pub(crate) fn parse_nl_msg_to_iface(
},
_ => IfaceType::Other(format!("{t:?}").to_lowercase()),
};
- // Always prefer InfoKind unless link type is loopback or
- // infiniband.
- if !matches!(
- iface_state.iface_type,
- IfaceType::Loopback | IfaceType::Infiniband
- ) {
- iface_state.iface_type = iface_type;
+
+ // We prefer LinkLayerType over InfoKind for loopback, as it
+ // is more accurate in this case. We also prefer it for
+ // infiniband, but only if we didn't detect a specific
+ // InfoKind (we detected Other). For example, Ipoib is more
+ // specific than Infiniband, but Other is not.
+ if iface_state.iface_type == IfaceType::Loopback
+ || (iface_state.iface_type == IfaceType::Infiniband
+ && matches!(iface_type, IfaceType::Other(_)))
+ {
+ continue;
}
+
+ // For any other case, we prefer InfoKind over LinkLayerType
+ // as it is almost always more accurate. LinkLayerType is
+ // set as ethernet for most device types.
+ iface_state.iface_type = iface_type;
}
}
for info in infos {
--
2.53.0

View File

@ -1,31 +0,0 @@
From 248cd0bff6e3d030ee72b62a8a8b0e37e9f2ef80 Mon Sep 17 00:00:00 2001
From: Fernando Fernandez Mancera <ffmancera@riseup.net>
Date: Tue, 29 Nov 2022 23:56:13 +0100
Subject: [PATCH] nm: reverse IPv6 order before adding them to setting
This is a downstream patch that needs to be applied before any other
patch. Please check:
https://github.com/nmstate/nmstate/commit/2d0cfd5ad8e049f30cad10d977a5fae8bc4e6b64
Signed-off-by: Fernando Fernandez Mancera <ffmancera@riseup.net>
---
libnmstate/nm/ipv6.py | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/libnmstate/nm/ipv6.py b/libnmstate/nm/ipv6.py
index 8e01fd70..7eb3196c 100644
--- a/libnmstate/nm/ipv6.py
+++ b/libnmstate/nm/ipv6.py
@@ -157,7 +157,7 @@ def _set_dynamic(setting_ip, is_dhcp, is_autoconf):
def _set_static(setting_ip, ip_addresses):
- for address in ip_addresses:
+ for address in reversed(ip_addresses):
if iplib.is_ipv6_link_local_addr(
address[InterfaceIPv6.ADDRESS_IP],
address[InterfaceIPv6.ADDRESS_PREFIX_LENGTH],
--
2.38.1

View File

@ -1,184 +0,0 @@
From daf5e4e2282312a80ade85ac5728babf8b9af8b5 Mon Sep 17 00:00:00 2001
From: Lubomir Rintel <lkundrak@v3.sk>
Date: Mon, 17 Jun 2024 19:25:07 +0200
Subject: [PATCH] nm: don't clear connection DNS if global DNS is not specified
If the global DNS state is not specified, let's not overwrite it in
Networkmanager profiles while doing unrelated changes.
This is consistent with mainline (Rust) version of nmstate.
Resolves: https://issues.redhat.com/browse/RHEL-31095
Signed-off-by: Lubomir Rintel <lkundrak@v3.sk>
Signed-off-by: Gris Ge <fge@redhat.com>
---
libnmstate/dns.py | 2 +-
libnmstate/nm/connection.py | 10 +++++++---
libnmstate/nm/ipv4.py | 11 ++++++-----
libnmstate/nm/ipv6.py | 11 ++++++-----
libnmstate/nm/profile.py | 8 +++++---
libnmstate/nm/profiles.py | 7 ++++++-
6 files changed, 31 insertions(+), 18 deletions(-)
diff --git a/libnmstate/dns.py b/libnmstate/dns.py
index 5bb512e8..f50b9bfd 100644
--- a/libnmstate/dns.py
+++ b/libnmstate/dns.py
@@ -51,7 +51,7 @@ class DnsState:
self._config_changed = False
self._cur_dns_state = deepcopy(cur_dns_state) if cur_dns_state else {}
self._dns_state = merge_dns(des_dns_state, cur_dns_state or {})
- if self._dns_state == REMOVE_DNS_CONFIG:
+ if des_dns_state is not None and self._dns_state == REMOVE_DNS_CONFIG:
self._config_changed = True
elif des_dns_state and des_dns_state.get(DNS.CONFIG):
if cur_dns_state:
diff --git a/libnmstate/nm/connection.py b/libnmstate/nm/connection.py
index 6448e372..a6aac82c 100644
--- a/libnmstate/nm/connection.py
+++ b/libnmstate/nm/connection.py
@@ -104,11 +104,15 @@ class _ConnectionSetting:
return self._setting
-def create_new_nm_simple_conn(iface, nm_profile):
+def create_new_nm_simple_conn(iface, nm_profile, clear_dns=False):
nm_iface_type = Api2Nm.get_iface_type(iface.type)
iface_info = iface.to_dict()
- ipv4_set = create_ipv4_setting(iface_info.get(Interface.IPV4), nm_profile)
- ipv6_set = create_ipv6_setting(iface_info.get(Interface.IPV6), nm_profile)
+ ipv4_set = create_ipv4_setting(
+ iface_info.get(Interface.IPV4), nm_profile, clear_dns
+ )
+ ipv6_set = create_ipv6_setting(
+ iface_info.get(Interface.IPV6), nm_profile, clear_dns
+ )
set_wait_ip(ipv4_set, ipv6_set, iface_info.get(Interface.WAIT_IP))
settings = [ipv4_set, ipv6_set]
con_setting = _ConnectionSetting()
diff --git a/libnmstate/nm/ipv4.py b/libnmstate/nm/ipv4.py
index 32b3428e..3f4de059 100644
--- a/libnmstate/nm/ipv4.py
+++ b/libnmstate/nm/ipv4.py
@@ -13,7 +13,7 @@ from .common import NM
INT32_MAX = 2**31 - 1
-def create_setting(config, base_con_profile):
+def create_setting(config, base_con_profile, clear_dns=True):
setting_ipv4 = None
if base_con_profile and config and config.get(InterfaceIPv4.ENABLED):
setting_ipv4 = base_con_profile.get_setting_ip4_config()
@@ -28,10 +28,11 @@ def create_setting(config, base_con_profile):
setting_ipv4.props.route_metric = Route.USE_DEFAULT_METRIC
setting_ipv4.clear_routes()
setting_ipv4.clear_routing_rules()
- setting_ipv4.clear_dns()
- setting_ipv4.clear_dns_searches()
- setting_ipv4.clear_dns_options(False)
- setting_ipv4.props.dns_priority = nm_dns.DEFAULT_DNS_PRIORITY
+ if clear_dns:
+ setting_ipv4.clear_dns()
+ setting_ipv4.clear_dns_searches()
+ setting_ipv4.clear_dns_options(False)
+ setting_ipv4.props.dns_priority = nm_dns.DEFAULT_DNS_PRIORITY
if not setting_ipv4:
setting_ipv4 = NM.SettingIP4Config.new()
diff --git a/libnmstate/nm/ipv6.py b/libnmstate/nm/ipv6.py
index f84d895c..fb3cdcf0 100644
--- a/libnmstate/nm/ipv6.py
+++ b/libnmstate/nm/ipv6.py
@@ -67,7 +67,7 @@ def get_info(active_connection, applied_config):
return info
-def create_setting(config, base_con_profile):
+def create_setting(config, base_con_profile, clear_dns=True):
setting_ip = None
if base_con_profile and config and config.get(InterfaceIPv6.ENABLED):
setting_ip = base_con_profile.get_setting_ip6_config()
@@ -82,10 +82,11 @@ def create_setting(config, base_con_profile):
setting_ip.props.gateway = None
setting_ip.props.route_table = Route.USE_DEFAULT_ROUTE_TABLE
setting_ip.props.route_metric = Route.USE_DEFAULT_METRIC
- setting_ip.clear_dns()
- setting_ip.clear_dns_searches()
- setting_ip.clear_dns_options(False)
- setting_ip.props.dns_priority = nm_dns.DEFAULT_DNS_PRIORITY
+ if clear_dns:
+ setting_ip.clear_dns()
+ setting_ip.clear_dns_searches()
+ setting_ip.clear_dns_options(False)
+ setting_ip.props.dns_priority = nm_dns.DEFAULT_DNS_PRIORITY
if not setting_ip:
setting_ip = NM.SettingIP6Config.new()
diff --git a/libnmstate/nm/profile.py b/libnmstate/nm/profile.py
index a0b1c8f8..acb849b6 100644
--- a/libnmstate/nm/profile.py
+++ b/libnmstate/nm/profile.py
@@ -273,7 +273,9 @@ class NmProfile:
self._iface.type == InterfaceType.ETHERNET and self._iface.is_peer
)
- def prepare_config(self, save_to_disk, gen_conf_mode=False):
+ def prepare_config(
+ self, save_to_disk, gen_conf_mode=False, clear_dns=True
+ ):
if self._iface.is_absent or (
self._iface.is_down
and not gen_conf_mode
@@ -307,7 +309,7 @@ class NmProfile:
# of nmstate should provide full/merged configure.
if self._iface.is_changed or self._iface.is_desired:
self._nm_simple_conn = create_new_nm_simple_conn(
- self._iface, self._nm_profile
+ self._iface, self._nm_profile, clear_dns
)
elif self._nm_profile:
self._nm_simple_conn = NM.SimpleConnection.new_clone(
@@ -316,7 +318,7 @@ class NmProfile:
else:
try:
self._nm_simple_conn = create_new_nm_simple_conn(
- self._iface, self._nm_profile
+ self._iface, self._nm_profile, clear_dns
)
# No error for undesired interface
except NmstateError:
diff --git a/libnmstate/nm/profiles.py b/libnmstate/nm/profiles.py
index e68efdf3..9ce21938 100644
--- a/libnmstate/nm/profiles.py
+++ b/libnmstate/nm/profiles.py
@@ -52,6 +52,7 @@ class NmProfiles:
def apply_config(self, net_state, save_to_disk):
if net_state.dns.config_changed:
+ clear_profile_dns = True
if net_state.use_global_dns:
apply_global_dns(
net_state.dns.config_servers,
@@ -60,6 +61,8 @@ class NmProfiles:
)
else:
apply_global_dns([], [], [])
+ else:
+ clear_profile_dns = False
self._prepare_state_for_profiles(net_state)
# The activation order on bridge/bond ports determins their controler's
@@ -74,7 +77,9 @@ class NmProfiles:
for profile in all_profiles:
profile.import_current()
- profile.prepare_config(save_to_disk, gen_conf_mode=False)
+ profile.prepare_config(
+ save_to_disk, gen_conf_mode=False, clear_dns=clear_profile_dns
+ )
_use_uuid_as_controller_and_parent(all_profiles)
changed_ovs_bridges_and_ifaces = {}
--
2.45.2

View File

@ -1,70 +0,0 @@
From 364842c0c09f9799a2c48a1bc3ce4debb1a3ddc2 Mon Sep 17 00:00:00 2001
From: Gris Ge <fge@redhat.com>
Date: Tue, 18 Jun 2024 13:44:55 +0800
Subject: [PATCH] dns: Do not touch iface DNS when apply identical DNS state
When applying the same DNS only desire state again, nmstate incorrectly
purged interface DNS.
The root cause is we only set `self.use_global_dns` to True when
DNS changed. The fix is set `self.use_global_dns` to True always unless
iface DNS is required.
Signed-off-by: Gris Ge <fge@redhat.com>
---
libnmstate/net_state.py | 12 +++++-------
1 file changed, 5 insertions(+), 7 deletions(-)
diff --git a/libnmstate/net_state.py b/libnmstate/net_state.py
index 7b208daa..fe6fc31d 100644
--- a/libnmstate/net_state.py
+++ b/libnmstate/net_state.py
@@ -32,7 +32,7 @@ class NetState:
gen_conf_mode=False,
ignored_dns_ifaces=None,
):
- self.use_global_dns = False
+ self.use_global_dns = True
if current_state is None:
current_state = {}
self._ifaces = Ifaces(
@@ -76,17 +76,17 @@ class NetState:
"interface profile, using global DNS"
)
logging.warning(
- "Storing DNS to NetworkManager via global dns API, "
- "this will cause __all__ interface level DNS settings "
- "been ignored"
+ "Storing DNS to NetworkManager via global DNS "
+ "API, this will cause __all__ interface level "
+ "DNS settings been ignored"
)
- self.use_global_dns = True
else:
if self.dns.is_purge() or self._is_iface_dns_prefered():
try:
self._ifaces.gen_dns_metadata(
self._dns, self._route, ignored_dns_ifaces
)
+ self.use_global_dns = False
except NmstateValueError as e:
if (
gen_conf_mode
@@ -99,14 +99,12 @@ class NetState:
"API, this will cause __all__ interface level "
"DNS settings been ignored"
)
- self.use_global_dns = True
elif self.dns.config_changed:
logging.warning(
"Storing DNS to NetworkManager via global DNS "
"API, this will cause __all__ interface level "
"DNS settings been ignored"
)
- self.use_global_dns = True
self._ifaces.gen_route_metadata(self._route)
self._ifaces.gen_route_rule_metadata(self._route_rule, self._route)
--
2.45.2

View File

@ -1,16 +0,0 @@
-----BEGIN PGP SIGNATURE-----
iQIzBAABCAAdFiEESP1vrlFad7SENoIch4lWe4cVzrwFAmZFuTcACgkQh4lWe4cV
zrx0Jg/9FaBh+ine42rKdD+vSITPnGMB2pNSgU8RMdb35fpypVE6Fx4zavvlN14r
rqO+DA57n2NAQ0Cj+n1HOaCxzbfYG2hAX8NwuFN3iY/KadqUdjdPx9G8vEzZDOFu
MCRZxUVIyrHBB9eoTLbhF6hd0XqWminHK43xaLZFBXZAe7DO9QEz+VxM77qsZaE5
EhxASs2mUERvjuY61h9lJb41DOxGLZBM5950S9lDM8cE9ZOi7H/8Q/8fhBPdHh5T
ubPZxsgEBQPEBPz6lE5g4Wcc8ggiCROEuUqRmOTpkb6smgFDsLtCBTakv1Z2U5Q0
YKdnDBfw7T9EV3dhkHR/AHvrLDUZ/bTwe6vO0GQBaSLG/WhvcftzuiDKTcqpAVOm
yUdxla1tinB0cDXohGb50VV9aHd9gFisoLGsPE7BJTqSKhCoQL2zToLHNaMnxNtz
/fJTOyGq1bBtchjbXjaoQO8sa/cxrllWlBYVjaTH7vqwgActrznos/N1sASrMfTw
H1VCKRgwurnomWoIbFNKxPnXNW0Lo31paWhW9wVD78J7Kf9xHrfYiOK2siYgSP7x
nVMuMHZ/j9/EOgHZAPZN3Aod0LWK0/WNwTyFB4IQcLWLaBYVhqlFhShtPo8MeIsJ
Wy7UQmGhtnP8Mt1DQTsfWCH8lQnWpIb84xHYXSEs+2e39GRDCq8=
=lwjx
-----END PGP SIGNATURE-----

View File

@ -0,0 +1,11 @@
-----BEGIN PGP SIGNATURE-----
iQEzBAABCgAdFiEEB/muyGFEOG2VdiELZqRHgbTrwtAFAmnojNsACgkQZqRHgbTr
wtAuOgf/fgqzvQh+cAUPLa1J1W1sA0ij8eXtOxRAK1wweUi9sS3Yg72rubTAtDGL
vgm6rGMNRHkrt13IKt1e/VwhM1IlZplj5mF4615+NnimokJksU2l9r0gw8KwkZvz
9LO2D6LNtz/qpHISX4VCULwZrW0JpTTpc+L0vJxtwhL5ZApG3n4jKipZ+x1o7f5l
oswDyTf90VcLhgiCMiSJdoVCfhxZJuttJVpIpYvPxD44tjpuFaa24e30k6S/zSop
tBFHnvDu6S0/pjKNG7/vzkSUWrbGeaOcopIQLeQQIE7XcFd1x0FrKUHkVAmXq9lu
k0Fi8L9C3+zuw1lCPEloVgCMcKAX6w==
=5HTd
-----END PGP SIGNATURE-----

View File

@ -94,6 +94,83 @@ V95yJtLnCnFdKlnyzT9HDepWfG8266hgBD+OQ/Kvhx6SmIImCgMOtcDW+fAz3X5L
YjVo4IPCmJLRb9b8kPX9JuJWDnYWd0SOB00ImaGeXd/kV8W30Lss1OeQ7iya/Ej7 YjVo4IPCmJLRb9b8kPX9JuJWDnYWd0SOB00ImaGeXd/kV8W30Lss1OeQ7iya/Ej7
t878uw4RVPKsgCQTWKOWhC0r0DNE/bskGrWZAJGC3M7yqzAErxiIOBKRwH2haegT t878uw4RVPKsgCQTWKOWhC0r0DNE/bskGrWZAJGC3M7yqzAErxiIOBKRwH2haegT
syMyW5sNgF43zvxzEHACZnbx+qzHYf+SeQg4pRxLlZj6/Udc3hM/j1cGkMMiwl23 syMyW5sNgF43zvxzEHACZnbx+qzHYf+SeQg4pRxLlZj6/Udc3hM/j1cGkMMiwl23
i2QY7dEEs/uMRtq8C8kSWg== i2QY7dEEs/uMRtq8C8kSWpkCDQRg3IskARAAwPd8TTsqamyztyFvxNlAiKu8fG4a
=259x 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
KfYnetRPLeXiMqWKTUaImA==
=a0yN
-----END PGP PUBLIC KEY BLOCK-----
-----BEGIN PGP PUBLIC KEY BLOCK-----
mQENBGC54gsBCACtCdyHeyKmLLyrS7K60vBA/ZzBjdNWo2gVzbp3uuXMYmYaVo4E
pIFxfkgtflefM8lZU//pFgCbj4l9uCyNrcMv5SDwR6T0JFoUyQgNVP2tc3d3Zzks
ktHOBxLyI0HSusKVXcYUSORcMLgW1QfpWWE01zND+Kur+9EQcKhkSVeh/APcDKh3
3OhiqKoo1zRQw/GyiXB8NY+/+zYmJc/Ag4ZL4zwTYfCcFYk2bUD3XWgYICqoY647
wlb398PdyJfKN3SNQdRUZ0zvMBxh6L5uN/CT92W5gey/m6UKfSiwmyzUcxtKvktA
g6DbWlIhjBhNssx/yJM/WWW8FE3piYpXhOQrABEBAAG0I8ONw7FpZ28gSHVndWV0
IDxpaHVndWV0QHJlZGhhdC5jb20+iQFOBBMBCAA4FiEEB/muyGFEOG2VdiELZqRH
gbTrwtAFAmC54gsCGwMFCwkIBwIGFQoJCAsCBBYCAwECHgECF4AACgkQZqRHgbTr
wtCGSQf+K/yt1oxk85ehjjmT/O+4PhMxPLDTTIbPWwJpSQ7paRkOa53VeA1gmI+m
miDK4CllrO90ZD6ZvzXjbXQP/MA1PDUNNOnCbXX+Tk9uZEx4GdWmkRbdEAOuBK8b
Vg7sH/2a/mtwAW/AYY/K8rcRGTDsNJAcNNfcXl61wGYWHuqyeNXmMB+Y3dXGUxKR
iJOcA0sO8d6DMCDMyeyAdREThbKT2pUfnXN9HdASBU8HHTmf2nyDAD6u/8EEMDfu
2Yb4VtCZ0k92mp/043JRbwJ56AUxdLbWFbBmYgrIeKAtyHaACv06PQXZpQ2dz+WP
S3URA/n5JvntMbIkarU7ftLuYTkn/LkBDQRgueILAQgAvm9vMG73bYZ5dp/TDKMk
y6E6mxi0TXVILfQV8bO2H1S2k19wNOIavqGtbH15QzsL6B2OuwHeAPkUkwQwV8Tz
NCbUFeQb8z5jWjdFVBi42JXwBQmQcYHKYjaOu/7kW+v/5pyfFRLPLfimYCF+YbhY
vTqSMrW4sInUXhUOL1mg0yxWEoZ6Qv3AlUsVc91Ok2j5f1UzjFg+7T4BEYc/pE+d
oP5y/mvYoUt+o6Ma6ENcBgsJ8JFRJTb1OTrXmzebCAW7Md+6rdXGz5mMeqW0QFGV
LgHS1euGza0Vm9wfjA6l3LMxW5jrmxLWsEiugbm4QPIxBR2u8HFVk/G6kBYxsNwd
3QARAQABiQE2BBgBCAAgFiEEB/muyGFEOG2VdiELZqRHgbTrwtAFAmC54gsCGwwA
CgkQZqRHgbTrwtD33wf+ORu+FgSV6m/5M8bsLNA2uh6jp3lFNT6CZy3yza/8Uxqt
RsucUc0qlWmnHbQmwCjAoHpapEtQNvisDgYGAo8ICw+Ij12psxOyFgh0inF7p2ms
86g1Km7DHzFE6B8gwakkVhN6QR+wzr3msJMfj+gfKCbmbuD7PQLjgJL4ITRbMj0u
XUuxEMD5z7mtWDDVscCna0bgaxX0KZC71ViWsPx7Wp1v6+kUzL4KLK1R/7xt6kim
2nJubv+VVuNkx8THxh6chgux1ev8z8fOKiPWcyYZ+wWhbr1Bt98Z24IV4BYY2Ee8
fOao91QN8xXpO4C1MljjqaWb3DWqvdBsTx/nUBPOlw==
=hJlJ
-----END PGP PUBLIC KEY BLOCK----- -----END PGP PUBLIC KEY BLOCK-----

File diff suppressed because it is too large Load Diff