From f2b058c5391eb825c76e198f3c2017388155e2d6 Mon Sep 17 00:00:00 2001 From: CentOS Sources Date: Tue, 16 May 2023 06:04:44 +0000 Subject: [PATCH] import nmstate-1.4.2-4.el8 --- .gitignore | 3 + .nmstate.metadata | 3 + ...-order-before-adding-them-to-setting.patch | 31 + ...when-creating-profile-if-not-desired.patch | 66 ++ SOURCES/BZ_2160416-fix-SRIOV.patch | 206 ++++++ SOURCES/Enable_clib_yml_api.patch | 636 ++++++++++++++++++ SOURCES/nmstate-1.4.2.tar.gz.asc | 16 + SPECS/nmstate.spec | 502 ++++++++++++++ 8 files changed, 1463 insertions(+) create mode 100644 .gitignore create mode 100644 .nmstate.metadata create mode 100644 SOURCES/BZ_2132570-nm-reverse-IPv6-order-before-adding-them-to-setting.patch create mode 100644 SOURCES/BZ_2160416-Ignore-error-when-creating-profile-if-not-desired.patch create mode 100644 SOURCES/BZ_2160416-fix-SRIOV.patch create mode 100644 SOURCES/Enable_clib_yml_api.patch create mode 100644 SOURCES/nmstate-1.4.2.tar.gz.asc create mode 100644 SPECS/nmstate.spec diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..c4e9e56 --- /dev/null +++ b/.gitignore @@ -0,0 +1,3 @@ +SOURCES/nmstate-1.4.2.tar.gz +SOURCES/nmstate-vendor-1.4.2.tar.xz +SOURCES/nmstate.gpg diff --git a/.nmstate.metadata b/.nmstate.metadata new file mode 100644 index 0000000..4736678 --- /dev/null +++ b/.nmstate.metadata @@ -0,0 +1,3 @@ +165eba0069da41758442f1d2efa8cae180417882 SOURCES/nmstate-1.4.2.tar.gz +0815a374c7acca14db28b47347e43797d4b3d570 SOURCES/nmstate-vendor-1.4.2.tar.xz +5c1d9d65f9db4fedc9dc96e0fb6cac0a86749c88 SOURCES/nmstate.gpg diff --git a/SOURCES/BZ_2132570-nm-reverse-IPv6-order-before-adding-them-to-setting.patch b/SOURCES/BZ_2132570-nm-reverse-IPv6-order-before-adding-them-to-setting.patch new file mode 100644 index 0000000..9fea02b --- /dev/null +++ b/SOURCES/BZ_2132570-nm-reverse-IPv6-order-before-adding-them-to-setting.patch @@ -0,0 +1,31 @@ +From 248cd0bff6e3d030ee72b62a8a8b0e37e9f2ef80 Mon Sep 17 00:00:00 2001 +From: Fernando Fernandez Mancera +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 +--- + 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 + diff --git a/SOURCES/BZ_2160416-Ignore-error-when-creating-profile-if-not-desired.patch b/SOURCES/BZ_2160416-Ignore-error-when-creating-profile-if-not-desired.patch new file mode 100644 index 0000000..f7aa1d6 --- /dev/null +++ b/SOURCES/BZ_2160416-Ignore-error-when-creating-profile-if-not-desired.patch @@ -0,0 +1,66 @@ +From d7d732332e486cd8969ff4b5ef95a24cb68b5441 Mon Sep 17 00:00:00 2001 +From: Gris Ge +Date: Mon, 27 Feb 2023 12:17:05 +0800 +Subject: [PATCH] nm: Ignore error when creating profile if not desired + +When a undesired interface holding `autoconf: true` and `dhcp: false` +for IPv6, nmstate will fail with error: + + Autoconf without DHCP is not supported yet + +This is caused by `nm/connection.py` try to create `NM.SimpleConnection` +for every interface even not desired. + +This patch changed to: + * Only create new `NM.SimpleConnection` when desired or changed. + * Use current profile if exists when not desired or changed. + * Ignore error if not desired/changed. + +Integration test case included. + +Signed-off-by: Gris Ge +--- + libnmstate/nm/profile.py | 20 +++++++++++++++++--- + 1 file changed, 17 insertions(+), 3 deletions(-) + +diff --git a/libnmstate/nm/profile.py b/libnmstate/nm/profile.py +index ad1ad19f..1119cd1a 100644 +--- a/libnmstate/nm/profile.py ++++ b/libnmstate/nm/profile.py +@@ -24,6 +24,7 @@ from distutils.version import StrictVersion + import logging + import time + ++from libnmstate.error import NmstateError + from libnmstate.error import NmstateInternalError + from libnmstate.error import NmstateLibnmError + from libnmstate.error import NmstateNotSupportedError +@@ -321,9 +322,22 @@ class NmProfile: + # TODO: Use applied config as base profile + # Or even better remove the base profile argument as top level + # of nmstate should provide full/merged configure. +- self._nm_simple_conn = create_new_nm_simple_conn( +- self._iface, self._nm_profile +- ) ++ if self._iface.is_changed or self._iface.is_desired: ++ self._nm_simple_conn = create_new_nm_simple_conn( ++ self._iface, self._nm_profile ++ ) ++ elif self._nm_profile: ++ self._nm_simple_conn = NM.SimpleConnection.new_clone( ++ self._nm_profile ++ ) ++ else: ++ try: ++ self._nm_simple_conn = create_new_nm_simple_conn( ++ self._iface, self._nm_profile ++ ) ++ # No error for undesired interface ++ except NmstateError: ++ pass + + def save_config(self, save_to_disk): + self._check_sriov_support() +-- +2.39.2 + diff --git a/SOURCES/BZ_2160416-fix-SRIOV.patch b/SOURCES/BZ_2160416-fix-SRIOV.patch new file mode 100644 index 0000000..30d63d2 --- /dev/null +++ b/SOURCES/BZ_2160416-fix-SRIOV.patch @@ -0,0 +1,206 @@ +From d410b928c8f2a22d42d1974b62ab5b3164861184 Mon Sep 17 00:00:00 2001 +From: Gris Ge +Date: Thu, 23 Feb 2023 13:06:01 +0800 +Subject: [PATCH] nm: Fix error on SR-IOV + +When SR-IOV VF naming scheme is like `ens1f0v0`, nmstate will delete +the VF NM connection when applying this state: + +```yml +--- +interfaces: +- name: ens1f0 + type: ethernet + state: up + ethernet: + sr-iov: + total-vfs: 1 +- name: ens1f0v0 + type: ethernet + state: up + ipv4: + enabled: false + ipv6: + enabled: false +``` + +This is because `delete_other_profiles()` is checking +`self._nm_profile()` from active NM profile instead of newly created +one. The fix is using newly created profile `self._nm_simple_conn`. + +We also have race problem when activating PF along with VF, PF +activation might delete VF NIC which cause VF activation failed. To +workaround that, we activate PF first via `NmProfile.ACTION_SRIOV_PF` +and wait on it before start VF activation. + +Also problem found during SR-IOV investigations is we do extra +un-required modification to `NM.SettingOvsExternalIDs` even it is not +mentioned in desired. We skip overriding `NM.SettingOvsExternalIDs` when +not desired. + +Existing test case can cover the use cases. + +Signed-off-by: Gris Ge +--- + libnmstate/ifaces/ifaces.py | 18 +++++++++++++++++- + libnmstate/netapplier.py | 20 +++++++++++--------- + libnmstate/nm/connection.py | 2 +- + libnmstate/nm/profile.py | 12 ++++++++++-- + 4 files changed, 39 insertions(+), 13 deletions(-) + +diff --git a/libnmstate/ifaces/ifaces.py b/libnmstate/ifaces/ifaces.py +index 828ff578..470dc0e6 100644 +--- a/libnmstate/ifaces/ifaces.py ++++ b/libnmstate/ifaces/ifaces.py +@@ -157,6 +157,23 @@ class Ifaces: + def has_vf_count_change_and_missing_eth(self): + return self._has_vf_count_change() and self._has_missing_veth() + ++ def has_sriov_iface(self): ++ for iface in self.all_kernel_ifaces.values(): ++ if (iface.is_desired or iface.is_changed) and iface.is_up: ++ cur_iface = self._cur_kernel_ifaces.get(iface.name) ++ if ( ++ cur_iface ++ and cur_iface.raw.get(Ethernet.CONFIG_SUBTREE, {}).get( ++ Ethernet.SRIOV_SUBTREE, {} ++ ) ++ ) or iface.original_desire_dict.get( ++ Ethernet.CONFIG_SUBTREE, {} ++ ).get( ++ Ethernet.SRIOV_SUBTREE, {} ++ ): ++ return True ++ return False ++ + def _has_vf_count_change(self): + for iface in self.all_kernel_ifaces.values(): + cur_iface = self._cur_kernel_ifaces.get(iface.name) +@@ -664,7 +681,6 @@ class Ifaces: + return None + + def get_cur_iface(self, iface_name, iface_type): +- + iface = self._cur_kernel_ifaces.get(iface_name) + if iface and iface_type in (None, InterfaceType.UNKNOWN, iface.type): + return iface +diff --git a/libnmstate/netapplier.py b/libnmstate/netapplier.py +index ae909126..50a70a9c 100644 +--- a/libnmstate/netapplier.py ++++ b/libnmstate/netapplier.py +@@ -104,7 +104,7 @@ def apply( + pf_net_state, + verify_change, + save_to_disk, +- has_sriov_pf=True, ++ VERIFY_RETRY_COUNT_SRIOV, + ) + # Refresh the current state + current_state = show_with_plugins( +@@ -120,8 +120,16 @@ def apply( + current_state, + save_to_disk, + ) ++ ++ if net_state.ifaces.has_sriov_iface(): ++ # 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 ++ else: ++ verify_retry = VERIFY_RETRY_COUNT ++ + _apply_ifaces_state( +- plugins, net_state, verify_change, save_to_disk, has_sriov_pf=False ++ plugins, net_state, verify_change, save_to_disk, verify_retry + ) + if commit: + destroy_checkpoints(plugins, checkpoints) +@@ -154,7 +162,7 @@ def rollback(*, checkpoint=None): + + + def _apply_ifaces_state( +- plugins, net_state, verify_change, save_to_disk, has_sriov_pf=False ++ plugins, net_state, verify_change, save_to_disk, verify_retry + ): + for plugin in plugins: + # Do not allow plugin to modify the net_state for future verification +@@ -163,12 +171,6 @@ def _apply_ifaces_state( + + verified = False + if verify_change: +- 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 +- else: +- verify_retry = VERIFY_RETRY_COUNT + for _ in range(verify_retry): + try: + _verify_change(plugins, net_state) +diff --git a/libnmstate/nm/connection.py b/libnmstate/nm/connection.py +index 1fbb380b..6448e372 100644 +--- a/libnmstate/nm/connection.py ++++ b/libnmstate/nm/connection.py +@@ -240,7 +240,7 @@ def create_new_nm_simple_conn(iface, nm_profile): + InterfaceType.OVS_PORT, + ) + or iface.type == InterfaceType.OVS_BRIDGE +- ): ++ ) and OvsDB.OVS_DB_SUBTREE in iface.original_desire_dict: + nm_setting = create_ovsdb_external_ids_setting( + iface_info.get(OvsDB.OVS_DB_SUBTREE, {}) + ) +diff --git a/libnmstate/nm/profile.py b/libnmstate/nm/profile.py +index 53eaebed..ad1ad19f 100644 +--- a/libnmstate/nm/profile.py ++++ b/libnmstate/nm/profile.py +@@ -56,6 +56,7 @@ ROUTE_REMOVED = "_route_removed" + class NmProfile: + # For unmanged iface and desired to down + ACTION_ACTIVATE_FIRST = "activate_first" ++ ACTION_SRIOV_PF = "activate_sriov_pf" + ACTION_DEACTIVATE = "deactivate" + ACTION_DEACTIVATE_FIRST = "deactivate_first" + ACTION_DELETE_DEVICE = "delete_device" +@@ -77,6 +78,7 @@ class NmProfile: + ACTION_ACTIVATE_FIRST, + ACTION_DEACTIVATE_FIRST, + ACTION_TOP_CONTROLLER, ++ ACTION_SRIOV_PF, + ACTION_NEW_IFACES, + ACTION_OTHER_CONTROLLER, + ACTION_NEW_OVS_PORT, +@@ -181,6 +183,11 @@ class NmProfile: + else: + self._add_action(NmProfile.ACTION_NEW_IFACES) + else: ++ if ( ++ self._nm_dev.props.capabilities ++ & NM.DeviceCapabilities.SRIOV ++ ): ++ self._add_action(NmProfile.ACTION_SRIOV_PF) + if self._iface.type == InterfaceType.OVS_PORT: + self._add_action(NmProfile.ACTION_MODIFIED_OVS_PORT) + if self._iface.type == InterfaceType.OVS_INTERFACE: +@@ -462,6 +469,7 @@ class NmProfile: + + def do_action(self, action): + if action in ( ++ NmProfile.ACTION_SRIOV_PF, + NmProfile.ACTION_MODIFIED, + NmProfile.ACTION_MODIFIED_OVS_PORT, + NmProfile.ACTION_MODIFIED_OVS_IFACE, +@@ -559,8 +567,8 @@ class NmProfile: + or nm_profile.get_connection_type() == self._nm_iface_type + ) + and ( +- self._nm_profile is None +- or nm_profile.get_uuid() != self._nm_profile.get_uuid() ++ self._nm_simple_conn is None ++ or nm_profile.get_uuid() != self._nm_simple_conn.get_uuid() + ) + ): + ProfileDelete( +-- +2.39.2 + diff --git a/SOURCES/Enable_clib_yml_api.patch b/SOURCES/Enable_clib_yml_api.patch new file mode 100644 index 0000000..ed8cf9f --- /dev/null +++ b/SOURCES/Enable_clib_yml_api.patch @@ -0,0 +1,636 @@ +From ad2bfa136290e72cdfd4b7877b49b3fc07203f9c Mon Sep 17 00:00:00 2001 +From: Gris Ge +Date: Tue, 21 Feb 2023 16:26:22 +0800 +Subject: [PATCH] clib: Introduce YAML support + +Allowing both YAML and JSON input, the output format will matching input +format. + +For `nmstate_net_state_retrieve()`, user can use +`NMSTATE_FLAG_YAML_OUTPUT` flag to instruct the output to be YAML +format. + +Signed-off-by: Gris Ge +--- + rust/src/clib/Cargo.toml | 1 + + rust/src/clib/apply.rs | 2 +- + rust/src/clib/gen_conf.rs | 52 +++++++----- + rust/src/clib/nmstate.h.in | 55 +++++++------ + rust/src/clib/policy.rs | 57 ++++++++----- + rust/src/clib/query.rs | 49 ++++++++---- + .../{nmpolicy_test.c => nmpolicy_json_test.c} | 5 ++ + rust/src/clib/test/nmpolicy_yaml_test.c | 80 +++++++++++++++++++ + .../{nmstate_test.c => nmstate_json_test.c} | 5 ++ + rust/src/clib/test/nmstate_yaml_test.c | 34 ++++++++ + rust/src/lib/Cargo.toml | 3 + + rust/src/lib/net_state.rs | 14 +++- + 12 files changed, 274 insertions(+), 83 deletions(-) + rename rust/src/clib/test/{nmpolicy_test.c => nmpolicy_json_test.c} (96%) + create mode 100644 rust/src/clib/test/nmpolicy_yaml_test.c + rename rust/src/clib/test/{nmstate_test.c => nmstate_json_test.c} (87%) + create mode 100644 rust/src/clib/test/nmstate_yaml_test.c + +diff --git a/rust/src/clib/Cargo.toml b/rust/src/clib/Cargo.toml +index 97e4128c..ed391b3a 100644 +--- a/rust/src/clib/Cargo.toml ++++ b/rust/src/clib/Cargo.toml +@@ -16,6 +16,7 @@ crate-type = ["cdylib", "staticlib"] + nmstate = { path = "../lib", default-features = false } + libc = "0.2.74" + serde_json = "1.0" ++serde_yaml = "0.9" + log = "0.4.17" + serde = { version = "1.0.137", features = ["derive"] } + once_cell = "1.12.0" +diff --git a/rust/src/clib/apply.rs b/rust/src/clib/apply.rs +index 9a0d6fbc..67d39730 100644 +--- a/rust/src/clib/apply.rs ++++ b/rust/src/clib/apply.rs +@@ -74,7 +74,7 @@ pub extern "C" fn nmstate_net_state_apply( + }; + + let mut net_state = +- match nmstate::NetworkState::new_from_json(net_state_str) { ++ match nmstate::NetworkState::new_from_yaml(net_state_str) { + Ok(n) => n, + Err(e) => { + unsafe { +diff --git a/rust/src/clib/gen_conf.rs b/rust/src/clib/gen_conf.rs +index f63fb7b0..1ad7156b 100644 +--- a/rust/src/clib/gen_conf.rs ++++ b/rust/src/clib/gen_conf.rs +@@ -68,7 +68,7 @@ pub extern "C" fn nmstate_generate_configurations( + } + }; + +- let net_state = match nmstate::NetworkState::new_from_json(net_state_str) { ++ let net_state = match nmstate::NetworkState::new_from_yaml(net_state_str) { + Ok(n) => n, + Err(e) => { + unsafe { +@@ -80,28 +80,44 @@ pub extern "C" fn nmstate_generate_configurations( + } + }; + ++ let input_is_json = ++ serde_json::from_str::(net_state_str).is_ok(); + let result = net_state.gen_conf(); + unsafe { + *log = CString::new(logger.drain(now)).unwrap().into_raw(); + } + match result { +- Ok(s) => match serde_json::to_string(&s) { +- Ok(cfgs) => unsafe { +- *configs = CString::new(cfgs).unwrap().into_raw(); +- NMSTATE_PASS +- }, +- Err(e) => unsafe { +- *err_msg = +- CString::new(format!("serde_json::to_string failure: {e}")) +- .unwrap() +- .into_raw(); +- *err_kind = +- CString::new(format!("{}", nmstate::ErrorKind::Bug)) +- .unwrap() +- .into_raw(); +- NMSTATE_FAIL +- }, +- }, ++ Ok(s) => { ++ let serialize = if input_is_json { ++ serde_json::to_string(&s).map_err(|e| { ++ nmstate::NmstateError::new( ++ nmstate::ErrorKind::Bug, ++ format!("Failed to convert state {s:?} to JSON: {e}"), ++ ) ++ }) ++ } else { ++ serde_yaml::to_string(&s).map_err(|e| { ++ nmstate::NmstateError::new( ++ nmstate::ErrorKind::Bug, ++ format!("Failed to convert state {s:?} to YAML: {e}"), ++ ) ++ }) ++ }; ++ ++ match serialize { ++ Ok(cfgs) => unsafe { ++ *configs = CString::new(cfgs).unwrap().into_raw(); ++ NMSTATE_PASS ++ }, ++ Err(e) => unsafe { ++ *err_msg = ++ CString::new(e.msg().to_string()).unwrap().into_raw(); ++ *err_kind = ++ CString::new(e.kind().to_string()).unwrap().into_raw(); ++ NMSTATE_FAIL ++ }, ++ } ++ } + Err(e) => { + unsafe { + *err_msg = CString::new(e.msg()).unwrap().into_raw(); +diff --git a/rust/src/clib/nmstate.h.in b/rust/src/clib/nmstate.h.in +index 0879d47e..391477fd 100644 +--- a/rust/src/clib/nmstate.h.in ++++ b/rust/src/clib/nmstate.h.in +@@ -1,19 +1,4 @@ +-/* +- * Copyright 2021 Red Hat +- * +- * Licensed under the Apache License, Version 2.0 (the "License"); +- * you may not use this file except in compliance with the License. +- * You may obtain a copy of the License at +- * +- * http://www.apache.org/licenses/LICENSE-2.0 +- * +- * Unless required by applicable law or agreed to in writing, software +- * distributed under the License is distributed on an "AS IS" BASIS, +- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +- * See the License for the specific language governing permissions and +- * limitations under the License. +- */ +- ++// SPDX-License-Identifier: Apache-2.0 + + #ifndef _LIBNMSTATE_H_ + #define _LIBNMSTATE_H_ +@@ -44,6 +29,7 @@ extern "C" { + #define NMSTATE_FLAG_NO_COMMIT 1 << 5 + #define NMSTATE_FLAG_MEMORY_ONLY 1 << 6 + #define NMSTATE_FLAG_RUNNING_CONFIG_ONLY 1 << 7 ++#define NMSTATE_FLAG_YAML_OUTPUT 1 << 8 + + /** + * nmstate_net_state_retrieve - Retrieve network state +@@ -52,7 +38,7 @@ extern "C" { + * 0.1 + * + * Description: +- * Retrieve network state in the format of JSON. ++ * Retrieve network state in the format of JSON or YAML. + * + * @flags: + * Flags for special use cases: +@@ -60,6 +46,13 @@ extern "C" { + * No flag + * * NMSTATE_FLAG_KERNEL_ONLY + * Do not use external plugins, show kernel status only. ++ * * NMSTATE_FLAG_INCLUDE_SECRETS ++ * No not hide sercerts like password. ++ * * NMSTATE_FLAG_RUNNING_CONFIG_ONLY ++ * Only include running config excluding running status like auto ++ * IP addresses and routes, LLDP neighbors. ++ * * NMSTATE_FLAG_YAML_OUTPUT ++ * Show the state in YAML format + * @state: + * Output pointer of char array for network state in json format. + * The memory should be freed by nmstate_net_state_free(). +@@ -90,7 +83,7 @@ int nmstate_net_state_retrieve(uint32_t flags, char **state, char **log, + * 0.1 + * + * Description: +- * Apply network state in the format of JSON. ++ * Apply network state in the format of JSON or YAML. + * + * @flags: + * Flags for special use cases: +@@ -98,8 +91,12 @@ int nmstate_net_state_retrieve(uint32_t flags, char **state, char **log, + * No flag + * * NMSTATE_FLAG_KERNEL_ONLY + * Do not use external plugins, apply to kernel only. ++ * * NMSTATE_FLAG_NO_VERIFY ++ * Do not verify state after applied + * * NMSTATE_FLAG_NO_COMMIT + * Do not commit new state after verification ++ * * NMSTATE_FLAG_MEMORY_ONLY ++ * No not store network state to persistent. + * @state: + * Pointer of char array for network state in json format. + * @log: +@@ -119,7 +116,8 @@ int nmstate_net_state_retrieve(uint32_t flags, char **state, char **log, + * * NMSTATE_FAIL + * On failure. + */ +-int nmstate_net_state_apply(uint32_t flags, const char *state, uint32_t rollback_timeout, char **log, ++int nmstate_net_state_apply(uint32_t flags, const char *state, ++ uint32_t rollback_timeout, char **log, + char **err_kind, char **err_msg); + + /** +@@ -151,8 +149,8 @@ int nmstate_net_state_apply(uint32_t flags, const char *state, uint32_t rollback + * * NMSTATE_FAIL + * On failure. + */ +-int nmstate_checkpoint_commit(const char *checkpoint, char **log, char **err_kind, +- char **err_msg); ++int nmstate_checkpoint_commit(const char *checkpoint, char **log, ++ char **err_kind, char **err_msg); + + /** + * nmstate_checkpoint_rollback - Rollback the checkpoint +@@ -183,8 +181,8 @@ int nmstate_checkpoint_commit(const char *checkpoint, char **log, char **err_kin + * * NMSTATE_FAIL + * On failure. + */ +-int nmstate_checkpoint_rollback(const char *checkpoint, char **log, char **err_kind, +- char **err_msg); ++int nmstate_checkpoint_rollback(const char *checkpoint, char **log, ++ char **err_kind, char **err_msg); + + /** + * nmstate_generate_configurations - Generate network configurations +@@ -199,9 +197,10 @@ int nmstate_checkpoint_rollback(const char *checkpoint, char **log, char **err_k + * as value. + * + * @state: +- * Pointer of char array for network state in json format. ++ * Pointer of char array for network state in JSON or YAML format. + * @configs: +- * Output pointer of char array for network configures in json format. ++ * Output pointer of char array for network configures in JSON or ++ * YAML(depend on which format you use in @state) format. + * The memory should be freed by nmstate_net_state_free(). + * @log: + * Output pointer of char array for logging. +@@ -231,14 +230,14 @@ int nmstate_generate_configurations(const char *state, char **configs, + * 2.2 + * + * Description: +- * Generate new network state from policy again specifed state ++ * Generate new network state from policy again specified state + * + * @policy: +- * Pointer of char array for network policy in json format. ++ * Pointer of char array for network policy in JSON/YAML format. + * @current_state: + * Pointer of char array for current network state. + * @state: +- * Output pointer of char array for network state in json format. ++ * Output pointer of char array for network state in JSON/YAML format. + * The memory should be freed by nmstate_net_state_free(). + * @log: + * Output pointer of char array for logging. +diff --git a/rust/src/clib/policy.rs b/rust/src/clib/policy.rs +index ec8c46c1..ea7dd036 100644 +--- a/rust/src/clib/policy.rs ++++ b/rust/src/clib/policy.rs +@@ -67,6 +67,13 @@ pub extern "C" fn nmstate_net_state_from_policy( + } + }; + ++ let input_is_json = ++ if let Ok(policy_str) = unsafe { CStr::from_ptr(policy) }.to_str() { ++ serde_json::from_str::(policy_str).is_ok() ++ } else { ++ false ++ }; ++ + let mut policy = match deserilize_from_c_char::( + policy, err_kind, err_msg, + ) { +@@ -86,23 +93,37 @@ pub extern "C" fn nmstate_net_state_from_policy( + } + + match result { +- Ok(s) => match serde_json::to_string(&s) { +- Ok(state_str) => unsafe { +- *state = CString::new(state_str).unwrap().into_raw(); +- NMSTATE_PASS +- }, +- Err(e) => unsafe { +- *err_msg = +- CString::new(format!("serde_json::to_string failure: {e}")) +- .unwrap() +- .into_raw(); +- *err_kind = +- CString::new(format!("{}", nmstate::ErrorKind::Bug)) +- .unwrap() +- .into_raw(); +- NMSTATE_FAIL +- }, +- }, ++ Ok(s) => { ++ let serialize = if input_is_json { ++ serde_json::to_string(&s).map_err(|e| { ++ nmstate::NmstateError::new( ++ nmstate::ErrorKind::Bug, ++ format!("Failed to convert state {s:?} to JSON: {e}"), ++ ) ++ }) ++ } else { ++ serde_yaml::to_string(&s).map_err(|e| { ++ nmstate::NmstateError::new( ++ nmstate::ErrorKind::Bug, ++ format!("Failed to convert state {s:?} to YAML: {e}"), ++ ) ++ }) ++ }; ++ ++ match serialize { ++ Ok(state_str) => unsafe { ++ *state = CString::new(state_str).unwrap().into_raw(); ++ NMSTATE_PASS ++ }, ++ Err(e) => unsafe { ++ *err_msg = ++ CString::new(e.msg().to_string()).unwrap().into_raw(); ++ *err_kind = ++ CString::new(e.kind().to_string()).unwrap().into_raw(); ++ NMSTATE_FAIL ++ }, ++ } ++ } + Err(e) => { + unsafe { + *err_msg = CString::new(e.msg()).unwrap().into_raw(); +@@ -144,7 +165,7 @@ where + } + }; + +- match serde_json::from_str(content_str) { ++ match serde_yaml::from_str(content_str) { + Ok(n) => Some(n), + Err(e) => { + unsafe { +diff --git a/rust/src/clib/query.rs b/rust/src/clib/query.rs +index a24b9c83..12e44d05 100644 +--- a/rust/src/clib/query.rs ++++ b/rust/src/clib/query.rs +@@ -14,6 +14,7 @@ pub(crate) const NMSTATE_FLAG_INCLUDE_SECRETS: u32 = 1 << 4; + pub(crate) const NMSTATE_FLAG_NO_COMMIT: u32 = 1 << 5; + pub(crate) const NMSTATE_FLAG_MEMORY_ONLY: u32 = 1 << 6; + pub(crate) const NMSTATE_FLAG_RUNNING_CONFIG_ONLY: u32 = 1 << 7; ++pub(crate) const NMSTATE_FLAG_YAML_OUTPUT: u32 = 1 << 8; + + #[allow(clippy::not_unsafe_ptr_arg_deref)] + #[no_mangle] +@@ -72,23 +73,37 @@ pub extern "C" fn nmstate_net_state_retrieve( + } + + match result { +- Ok(s) => match serde_json::to_string(&s) { +- Ok(state_str) => unsafe { +- *state = CString::new(state_str).unwrap().into_raw(); +- NMSTATE_PASS +- }, +- Err(e) => unsafe { +- *err_msg = +- CString::new(format!("serde_json::to_string failure: {e}")) +- .unwrap() +- .into_raw(); +- *err_kind = +- CString::new(format!("{}", nmstate::ErrorKind::Bug)) +- .unwrap() +- .into_raw(); +- NMSTATE_FAIL +- }, +- }, ++ Ok(s) => { ++ let serialize = if (flags & NMSTATE_FLAG_YAML_OUTPUT) > 0 { ++ serde_yaml::to_string(&s).map_err(|e| { ++ nmstate::NmstateError::new( ++ nmstate::ErrorKind::Bug, ++ format!("Failed to convert state {s:?} to YAML: {e}"), ++ ) ++ }) ++ } else { ++ serde_json::to_string(&s).map_err(|e| { ++ nmstate::NmstateError::new( ++ nmstate::ErrorKind::Bug, ++ format!("Failed to convert state {s:?} to JSON: {e}"), ++ ) ++ }) ++ }; ++ ++ match serialize { ++ Ok(state_str) => unsafe { ++ *state = CString::new(state_str).unwrap().into_raw(); ++ NMSTATE_PASS ++ }, ++ Err(e) => unsafe { ++ *err_msg = ++ CString::new(e.msg().to_string()).unwrap().into_raw(); ++ *err_kind = ++ CString::new(e.kind().to_string()).unwrap().into_raw(); ++ NMSTATE_FAIL ++ }, ++ } ++ } + Err(e) => { + unsafe { + *err_msg = CString::new(e.msg()).unwrap().into_raw(); +diff --git a/rust/src/clib/test/nmpolicy_test.c b/rust/src/clib/test/nmpolicy_json_test.c +similarity index 96% +rename from rust/src/clib/test/nmpolicy_test.c +rename to rust/src/clib/test/nmpolicy_json_test.c +index 7a71a5f5..8a0444d4 100644 +--- a/rust/src/clib/test/nmpolicy_test.c ++++ b/rust/src/clib/test/nmpolicy_json_test.c +@@ -1,3 +1,6 @@ ++// SPDX-License-Identifier: Apache-2.0 ++ ++#include + #include + #include + #include +@@ -91,6 +94,8 @@ int main(void) { + rc = EXIT_FAILURE; + } + ++ assert(state[0] == '{'); ++ + nmstate_cstring_free(state); + nmstate_cstring_free(err_kind); + nmstate_cstring_free(err_msg); +diff --git a/rust/src/clib/test/nmpolicy_yaml_test.c b/rust/src/clib/test/nmpolicy_yaml_test.c +new file mode 100644 +index 00000000..7984f509 +--- /dev/null ++++ b/rust/src/clib/test/nmpolicy_yaml_test.c +@@ -0,0 +1,80 @@ ++// SPDX-License-Identifier: Apache-2.0 ++ ++#include ++#include ++#include ++#include ++#include ++ ++#include ++ ++int main(void) { ++ int rc = EXIT_SUCCESS; ++ const char *policy = "\ ++capture:\n\ ++ default-gw: override me with the cache\n\ ++ base-iface: >\n\ ++ interfaces.name == capture.default-gw.routes.running.0.next-hop-interface\n\ ++ base-iface-routes: >\n\ ++ routes.running.next-hop-interface ==\n\ ++ capture.default-gw.routes.running.0.next-hop-interface\n\ ++ bridge-routes: >\n\ ++ capture.base-iface-routes | routes.running.next-hop-interface:=\"br1\"\n\ ++desired:\n\ ++ interfaces:\n\ ++ - name: br1\n\ ++ description: Linux bridge with base interface as a port\n\ ++ type: linux-bridge\n\ ++ state: up\n\ ++ bridge:\n\ ++ options:\n\ ++ stp:\n\ ++ enabled: false\n\ ++ port:\n\ ++ - name: '{{ capture.base-iface.interfaces.0.name }}'\n\ ++ ipv4: '{{ capture.base-iface.interfaces.0.ipv4 }}'\n\ ++ routes:\n\ ++ config: '{{ capture.bridge-routes.routes.running }}'"; ++ const char *current_state = "\ ++interfaces:\n\ ++- name: eth1\n\ ++ type: ethernet\n\ ++ state: up\n\ ++ mac-address: 1c:c1:0c:32:3b:ff\n\ ++ ipv4:\n\ ++ address:\n\ ++ - ip: 192.0.2.251\n\ ++ prefix-length: 24\n\ ++ dhcp: false\n\ ++ enabled: true\n\ ++routes:\n\ ++ config:\n\ ++ - destination: 0.0.0.0/0\n\ ++ next-hop-address: 192.0.2.1\n\ ++ next-hop-interface: eth1\n\ ++ running:\n\ ++ - destination: 0.0.0.0/0\n\ ++ next-hop-address: 192.0.2.1\n\ ++ next-hop-interface: eth1"; ++ char *state = NULL; ++ char *err_kind = NULL; ++ char *err_msg = NULL; ++ char *log = NULL; ++ ++ if (nmstate_net_state_from_policy(policy, current_state, &state, &log, ++ &err_kind, &err_msg) == NMSTATE_PASS) ++ { ++ printf("%s\n", state); ++ } else { ++ printf("%s: %s\n", err_kind, err_msg); ++ rc = EXIT_FAILURE; ++ } ++ ++ assert(state[0] != '{'); ++ ++ nmstate_cstring_free(state); ++ nmstate_cstring_free(err_kind); ++ nmstate_cstring_free(err_msg); ++ nmstate_cstring_free(log); ++ exit(rc); ++} +diff --git a/rust/src/clib/test/nmstate_test.c b/rust/src/clib/test/nmstate_json_test.c +similarity index 87% +rename from rust/src/clib/test/nmstate_test.c +rename to rust/src/clib/test/nmstate_json_test.c +index 0e79cb15..1bfbcda7 100644 +--- a/rust/src/clib/test/nmstate_test.c ++++ b/rust/src/clib/test/nmstate_json_test.c +@@ -1,3 +1,6 @@ ++// SPDX-License-Identifier: Apache-2.0 ++ ++#include + #include + #include + #include +@@ -21,6 +24,8 @@ int main(void) { + rc = EXIT_FAILURE; + } + ++ assert(state[0] == '{'); ++ + nmstate_cstring_free(state); + nmstate_cstring_free(err_kind); + nmstate_cstring_free(err_msg); +diff --git a/rust/src/clib/test/nmstate_yaml_test.c b/rust/src/clib/test/nmstate_yaml_test.c +new file mode 100644 +index 00000000..de0f2486 +--- /dev/null ++++ b/rust/src/clib/test/nmstate_yaml_test.c +@@ -0,0 +1,34 @@ ++// SPDX-License-Identifier: Apache-2.0 ++ ++#include ++#include ++#include ++#include ++#include ++ ++#include ++ ++int main(void) { ++ int rc = EXIT_SUCCESS; ++ char *state = NULL; ++ char *err_kind = NULL; ++ char *err_msg = NULL; ++ char *log = NULL; ++ uint32_t flag = NMSTATE_FLAG_KERNEL_ONLY | NMSTATE_FLAG_YAML_OUTPUT; ++ ++ if (nmstate_net_state_retrieve(flag, &state, &log, &err_kind, &err_msg) ++ == NMSTATE_PASS) { ++ printf("%s\n", state); ++ } else { ++ printf("%s: %s\n", err_kind, err_msg); ++ rc = EXIT_FAILURE; ++ } ++ ++ assert(state[0] != '{'); ++ ++ nmstate_cstring_free(state); ++ nmstate_cstring_free(err_kind); ++ nmstate_cstring_free(err_msg); ++ nmstate_cstring_free(log); ++ exit(rc); ++} +diff --git a/rust/src/lib/Cargo.toml b/rust/src/lib/Cargo.toml +index a27d0e1a..0142026d 100644 +--- a/rust/src/lib/Cargo.toml ++++ b/rust/src/lib/Cargo.toml +@@ -15,6 +15,9 @@ edition = "2018" + [lib] + path = "lib.rs" + ++[dependencies] ++serde_yaml = "0.9" ++ + [dependencies.nispor] + version = "1.2.9" + optional = true +diff --git a/rust/src/lib/net_state.rs b/rust/src/lib/net_state.rs +index 8ab79642..fe5fea78 100644 +--- a/rust/src/lib/net_state.rs ++++ b/rust/src/lib/net_state.rs +@@ -274,7 +274,19 @@ impl NetworkState { + Ok(s) => Ok(s), + Err(e) => Err(NmstateError::new( + ErrorKind::InvalidArgument, +- format!("Invalid json string: {e}"), ++ format!("Invalid JSON string: {e}"), ++ )), ++ } ++ } ++ ++ /// Wrapping function of [serde_yaml::from_str()] with error mapped to ++ /// [NmstateError]. ++ pub fn new_from_yaml(net_state_yaml: &str) -> Result { ++ match serde_yaml::from_str(net_state_yaml) { ++ Ok(s) => Ok(s), ++ Err(e) => Err(NmstateError::new( ++ ErrorKind::InvalidArgument, ++ format!("Invalid YAML string: {e}"), + )), + } + } +-- +2.39.2 + diff --git a/SOURCES/nmstate-1.4.2.tar.gz.asc b/SOURCES/nmstate-1.4.2.tar.gz.asc new file mode 100644 index 0000000..7f3131a --- /dev/null +++ b/SOURCES/nmstate-1.4.2.tar.gz.asc @@ -0,0 +1,16 @@ +-----BEGIN PGP SIGNATURE----- + +iQIzBAABCAAdFiEE8f1XsqXpyNthgIbGbM3lj+QeKP8FAmPwSo0ACgkQbM3lj+Qe +KP/P7A/8DLoHZkeuCsDjCYQ5yk0pWSuEqDMZT4Qqk6khBJOtvx5L14oImlrpmOVr +iw3pclF/fl8wxcpPYwcVn2odJWryaZxKw3vNPfth47vEtk3RVZpIqHLsgcCOEcX1 +/czFbA4EJLZV67Qu4gEfrfjbTKEmcakXLI5qUbMDw0nwqx5BI/66iF5kZD4IGJui +MDVbe61wAatcOl5RU8Y0rFI6fz4a9PXVJEijHJC8ZMg/Vq4Q/aBErUZAQ9RKJmi7 +Uu2TLYv4JTMiWX/xspH+CJX7bbaJ9N7P/Z3NzEOKVlDGMmG7TN9QtpnuSF46Jv5K +LTLdr7mBSK3dnQ9vIwcmM8m/MWU2w9dxf7Oh8YCkjwlLk1ANnANHz+xBMx+qIM5e +uNB2iPL2nHTDLFVbOMp1dcZzvndgm3a5oS9L4nglVojvNqGTmkjeJaM5bk80HvxJ +i/onHNmNRnQeHn8xUT7EcBQXUBUCORExygTyJ1dsw+BwbncwV2lOSan7OJY53Os2 +Lm7kHRBtOPeJNK7NbF55eo+N2+1+n9XP7oiCaj//FwWXN6vh97afi7fp5men2MKr +xbBPtYP5BV5LT7/DxKW+AunL2UUtlYoeCI0wm16kDzL8VW1u1Arv5NtdQsSnONk9 +PChrlhPnITjIZ0o2+GrYYOROZPbMSl4oQtO0hTiUub2Vrf3sPIc= +=zl4m +-----END PGP SIGNATURE----- diff --git a/SPECS/nmstate.spec b/SPECS/nmstate.spec new file mode 100644 index 0000000..3eb6f65 --- /dev/null +++ b/SPECS/nmstate.spec @@ -0,0 +1,502 @@ +%?python_enable_dependency_generator +%define srcname nmstate +%define libname libnmstate + +Name: nmstate +Version: 1.4.2 +Release: 4%{?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: https://www.nmstate.io/nmstate.gpg +Source3: %{url}/releases/download/v%{version}/%{srcname}-vendor-%{version}.tar.xz +# Patches 0X are reserved to downstream only +Patch0: BZ_2132570-nm-reverse-IPv6-order-before-adding-them-to-setting.patch +Patch11: Enable_clib_yml_api.patch +Patch12: BZ_2160416-fix-SRIOV.patch +Patch13: BZ_2160416-Ignore-error-when-creating-profile-if-not-desired.patch +BuildRequires: python3-devel +BuildRequires: python3-setuptools +BuildRequires: gnupg2 +BuildRequires: rust-toolset +BuildRequires: pkg-config +Requires: python3-setuptools +Requires: python3-%{libname} = %{?epoch:%{epoch}:}%{version}-%{release} + +%description +Nmstate is a library with an accompanying command line tool that manages host +networking settings in a declarative manner and aimed to satisfy enterprise +needs to manage host networking through a northbound declarative API and multi +provider support on the southbound. + + +%package -n python3-%{libname} +Summary: nmstate Python 3 API library +BuildArch: noarch +Requires: NetworkManager-libnm >= 1:1.26.0 +# Use Recommends for NetworkManager because only access to NM DBus is required, +# but NM could be running on a different host +Recommends: NetworkManager +# Avoid automatically generated profiles +Recommends: NetworkManager-config-server +# Use Suggests for NetworkManager-ovs and NetworkManager-team since it is only +# required for OVS and team support +Suggests: NetworkManager-ovs +Suggests: NetworkManager-team +Requires: nispor +Requires: python3dist(varlink) + +%package -n nmstate-plugin-ovsdb +Summary: nmstate plugin for OVS database manipulation +BuildArch: noarch +Requires: python3-%{libname} = %{?epoch:%{epoch}:}%{version}-%{release} +# The python-openvswitch rpm pacakge is not in the same repo with nmstate, +# hence state it as Recommends, no requires. +Recommends: python3dist(ovs) + + +%package libs +Summary: C binding of nmstate +License: ASL 2.0 + +%package devel +Summary: C binding development files of nmstate +License: ASL 2.0 +Requires: nmstate-libs%{?_isa} = %{?epoch:%{epoch}:}%{version}-%{release} + +%description libs +This package contains the C binding of nmstate. + +%description devel +This package contains the C binding development files of nmstate. + +%description -n python3-%{libname} +This package contains the Python 3 library for nmstate. + +%description -n nmstate-plugin-ovsdb +This package contains the nmstate plugin for OVS database manipulation. + +%prep +gpg2 --import --import-options import-export,import-minimal %{SOURCE2} > ./gpgkey-mantainers.gpg +gpgv2 --keyring ./gpgkey-mantainers.gpg %{SOURCE1} %{SOURCE0} +%autosetup -p1 + +pushd rust +# Source3 is vendored dependencies +%cargo_prep -V 3 + +# The cargo_prep will create `.cargo/config` which take precedence over +# `.cargo/config.toml` shipped by upstream which fix the SONAME of cdylib. +# To workaround that, merge upstream rustflags into cargo_prep created one. +_FLAGS=`sed -ne 's/rustflags = "\(.\+\)"/\1/p' .cargo/config.toml` +sed -i -e "s/rustflags = \[\(.\+\), \]$/rustflags = [\1, \"$_FLAGS\"]/" \ + .cargo/config +rm .cargo/config.toml + +popd + +%build +%py3_build + +pushd rust +make +popd + +%install +%py3_install +pushd rust +env SKIP_PYTHON_INSTALL=1 \ + PREFIX=%{_prefix} \ + LIBDIR=%{_libdir} \ + %make_install +popd + +%files +%doc README.md +%doc examples/ +%{_mandir}/man8/nmstatectl.8* +%{_mandir}/man8/nmstate-autoconf.8* +%{python3_sitelib}/nmstatectl +%{_bindir}/nmstatectl +%{_bindir}/nmstatectl-rust +%{_bindir}/nmstate-autoconf + +%files -n python3-%{libname} +%license LICENSE +%{python3_sitelib}/%{libname} +%{python3_sitelib}/%{srcname}-*.egg-info/ +%exclude %{python3_sitelib}/%{libname}/plugins/nmstate_plugin_* +%exclude %{python3_sitelib}/%{libname}/plugins/__pycache__/nmstate_plugin_* + +%files -n nmstate-plugin-ovsdb +%{python3_sitelib}/%{libname}/plugins/nmstate_plugin_ovsdb* +%{python3_sitelib}/%{libname}/plugins/__pycache__/nmstate_plugin_ovsdb* + +%files libs +%license rust/LICENSE +%{_libdir}/libnmstate.so.* + +%files devel +%license LICENSE +%{_libdir}/libnmstate.so +%{_includedir}/nmstate.h +%{_libdir}/pkgconfig/nmstate.pc + +%post libs +/sbin/ldconfig + +%postun libs +/sbin/ldconfig + +%changelog +* Mon Feb 27 2023 Gris Ge - 1.4.2-4 +- Ignore undesired iface config. RHBZ#2160416 + +* Thu Feb 23 2023 Gris Ge - 1.4.2-3 +- Additional patch for SR-IOV. RHBZ#2160416 + +* Wed Feb 22 2023 Gris Ge - 1.4.2-2 +- Enable YAML API in rust clib. + +* Sat Feb 18 2023 Gris Ge - 1.4.2-1 +- Upgrade to nmstate 1.4.2 + +* Mon Jan 09 2023 Gris Ge - 1.4.1-1 +- Upgrade to nmstate-1.4.1 + +* Wed Dec 14 2022 Gris Ge - 1.4.0-1 +- Upgrade to nmstate-1.4.0 + +* Thu Dec 01 2022 Fernando Fernandez Mancera - 1.4.0.alpha.20221201 +- Upgrade to nmstate-1.4.0.alpha.20221201 + +* Fri Nov 18 2022 Fernando Fernandez Mancera - 1.3.4.alpha.20221118 +- Upgrade to nmstate-1.3.4.alpha.20221118 + +* Mon Oct 24 2022 Fernando Fernandez Mancera - 1.3.4.alpha.20221024 +- Undo the branching misdone by Fernando. + +* Mon Aug 15 2022 Gris Ge - 1.3.3-1 +- Upgrade to nmstate-1.3.3 + +* Tue Aug 02 2022 Fernando Fernandez Mancera - 1.3.2-1 +- Upgrade to nmstate-1.3.2 + +* Wed Jul 20 2022 Fernando Fernandez Mancera - 1.3.1-1 +- Upgrade to nmstate-1.3.1 + +* Fri Jul 01 2022 Fernando Fernandez Mancera - 1.3.1-0.alpha.20220701 +- Upgrade to nmstate-1.3.1-0.alpha.20220701 + +* Mon Jun 13 2022 Fernando Fernandez Mancera - 1.3.0-1 +- Upgrade to nmstate-1.3.0-1 + +* Thu May 05 2022 Fernando Fernandez Mancera - 1.3.0-0.alpha.20220505 +- Upgrade to nmstate-1.3.0.alpha.20220505 + +* Thu Apr 07 2022 Fernando Fernandez Mancera - 1.3.0-0.alpha.20220407 +- Upgrade to nmstate-1.3.0.alpha.20220407 + +* Thu Mar 10 2022 Gris Ge - 1.3.0-0.alpha.20220310 +Upgrade to nmstate-1.3.0-0.alpha.20220310 + +* Mon Feb 14 2022 Gris Ge - 1.2.1-1 +- Upgrade to 1.2.1. RHBZ#1996618 + +* Thu Jan 27 2022 Gris Ge - 1.2.1-0.2.alpha2 +- Upgrade to 1.2.1 alpha2. RHBZ#1996618 + +* Thu Jan 13 2022 Gris Ge - 1.2.1-0.1.alpha1 +- Upgrade to 1.2.1 alpha1. RHBZ#1996618 + +* Thu Dec 16 2021 Fernando Fernandez Mancera - 1.2.0-1 +- Upgrade to 1.2.0. RHBZ#1996618 + +* Thu Dec 09 2021 Gris Ge - 1.2.0-0.1.alpha2 +- Upgrade to 1.2.0 alpha2. RHBZ#1996618 + +* Tue Oct 12 2021 Gris Ge - 1.2.0-0.1.alpha1 +- Upgrade to 1.2.0 alpha1. + +* Wed Sep 15 2021 Ana Cabral - 1.1.1-0.1.alpha1 +- Upgrade to 1.1.1 alpha1. +- Canonicalize ipv6 addresses for dns nameservers. RHBZ#1911241 +- Throw better error when peer is missing for veth interfaces. RHBZ#1973973 + +* Tue Jul 27 2021 Gris Ge - 1.1.0-3 +- Fix state=ignore for OVS interface. RHBZ#1944054 +- Fix verification for next hop address 0.0.0.0. RHBZ#1985879 + +* Fri Jul 23 2021 Gris Ge - 1.1.0-2 +- Preserving existing ethtool settings. RHBZ#1984764 + +* Thu Jul 15 2021 Gris Ge - 1.1.0-1 +- Upgrade to 1.1.0. + +* Fri Jul 09 2021 Gris Ge - 1.1.0-0.7.alpha7 +- Upgarde to 1.1.0 alpha7. + +* Thu Jul 01 2021 Gris Ge - 1.1.0-0.6.alpha6 +- Upgrade to 1.1.0 alpha6. + +* Mon Jun 21 2021 Fernando Fernandez Mancera - 1.1.0-0.5.alpha4 +- Upgrade to 1.1.0 alpha4. + +* Wed Jun 16 2021 Fernando Fernandez Mancera - 1.1.0-0.4.alpha3 +- Rebuild to introduce CI gating tier1 tests. RHBZ#1813357 + +* Tue Jun 08 2021 Gris Ge - 1.1.0-0.3.alpha3 +- Upgrade to 1.1.0 alpha3. + +* Mon Jun 07 2021 Fernando Fernandez Mancera - 1.1.0-0.2 +- Upgrade to 1.1.0 alpha2. + +* Wed May 19 2021 Wen Liang - 1.1.0-0.1 +- Upgrade to 1.1.0 alpha1. + +* Tue Apr 20 2021 Fernando Fernandez Mancera - 1.0.3-1 +- Upgrade to 1.0.3. RHBZ#1942458 + +* Fri Mar 26 2021 Fernando Fernandez Mancera - 1.0.2-6 +- Rebuild for RHEL 8.5. RHBZ#1935710 + +* Fri Mar 26 2021 Fernando Fernandez Mancera - 1.0.2-5 +- New patch for fixing unmanaged interfaces being managed. RHBZ#1935710 + +* Tue Feb 23 2021 Gris Ge - 1.0.2-4 +- New patch for SRIOV decrease VF amount. RHBZ#1931355 + +* Tue Feb 23 2021 Gris Ge - 1.0.2-3 +- Fix actiation failure when decrease VF mount on i40e. RHBZ#1931355 + +* Tue Feb 23 2021 Gris Ge - 1.0.2-2 +- Fix nmstatectl return code of `set` command. RHBZ#1931751 + +* Fri Feb 19 2021 Gris Ge - 1.0.2-1 +- Upgrade to 1.0.2. + +* Wed Feb 10 2021 Fernando Fernandez Mancera - 1.0.2-0.3 +- Fix sources name + +* Wed Feb 10 2021 Fernando Fernandez Mancera - 1.0.2-0.2 +- Upgrade to 1.0.2 alpha 2 + +* Tue Jan 26 2021 Fernando Fernandez Mancera - 1.0.2-0.1 +- Upgrade to 1.0.2 alpha 1 + +* Tue Jan 19 2021 Fernando Fernandez Mancera - 1.0.1-1 +- Upgrade to 1.0.1. RHBZ#1881287 + +* Tue Jan 05 2021 Gris Ge - 1.0.1-0.1 +- Upgrade to 1.0.1 alpha 1 + +* Tue Dec 08 2020 Fernando Fernandez Mancera - 1.0.0-1 +- Upgrade to 1.0.0 + +* Mon Nov 16 2020 Gris Ge - 1.0.0-0.1 +- Upgrade to 1.0.0 alpha 1 + +* Wed Oct 28 2020 Fernando Fernandez Mancera - 0.4.1-2 +- Allow VRF port to hold IP information + +* Thu Oct 22 2020 Fernando Fernandez Mancera - 0.4.1-1 +- Upgrade to 0.4.1 + +* Tue Oct 20 2020 Fernando Fernandez Mancera - 0.4.0-3 +- Add nispor as a dependency for CI gating + +* Tue Oct 20 2020 Fernando Fernandez Mancera - 0.4.0-2 +- Rebuild for CI gating +- Remove old patches from the repository + +* Mon Sep 14 2020 Fernando Fernandez Mancera - 0.4.0-1 +- Upgrade to 0.4.0 +- Sync. up with upstream spec file. + +* Tue Aug 18 2020 Gris Ge - 0.3.4-12 +- New patch: OVSDB: Allowing remove all OVS ports. RHBZ#1869345 + +* Tue Aug 18 2020 Gris Ge - 0.3.4-11 +- OVSDB: Allowing remove all OVS ports. RHBZ#1869345 + +* Thu Aug 06 2020 Gris Ge - 0.3.4-10 +- OVSDB: Preserv old external_ids. RHBZ#1866269 + +* Tue Aug 04 2020 Gris Ge - 0.3.4-9 +- Fix converting memory only profile to persistent. RHBZ#1859844 + +* Mon Aug 03 2020 Gris Ge - 0.3.4-8 +- Fix failure when adding ovs bond to existing bridge. RHBZ#1858758 + +* Thu Jul 30 2020 Gris Ge - 0.3.4-7 +- Remove existing inactivate NM profiles. RHBZ#1862025 + +* Wed Jul 29 2020 Gris Ge - 0.3.4-6 +- New build to retrigger the CI gating. + +* Wed Jul 29 2020 Gris Ge - 0.3.4-5 +- Use new patch. RHBZ#1861668 + +* Wed Jul 29 2020 Gris Ge - 0.3.4-4 +- Ignore unknown interface. RHBZ#1861668 + +* Tue Jul 28 2020 Gris Ge - 0.3.4-3 +- Add support NetworkManaged exteranl managed interface. RHBZ#1861263 + +* Tue Jul 28 2020 Gris Ge - 0.3.4-2 +- Hide MTU for OVS patch port. RHBZ#1858762 + +* Sat Jul 25 2020 Fernando Fernandez Mancera - 0.3.4-1 +- Upgrade to 0.3.4 + +* Fri Jul 24 2020 Gris Ge - 0.3.3-3 +- Allowing child been marked absent. RHBZ#1859148 + +* Mon Jul 06 2020 Fernando Fernandez Mancera - 0.3.3-2 +- Fix bug 1850698 + +* Thu Jul 02 2020 Fernando Fernandez Mancera - 0.3.3-1 +- Upgrade to 0.3.3 + +* Mon Jun 29 2020 Gris Ge - 0.3.2-6 +- Improve performance by remove unneeded calls. RHBZ#1820009 + +* Mon Jun 29 2020 Gris Ge - 0.3.2-5 +- Sort the pretty state with priority. RHBZ#1806474 + +* Mon Jun 29 2020 Gris Ge - 0.3.2-4 +- Canonicalize IP address. RHBZ#1816612 + +* Mon Jun 29 2020 Gris Ge - 0.3.2-3 +- Improve VLAN MTU error message. RHBZ#1788763 + +* Mon Jun 29 2020 Gris Ge - 0.3.2-2 +- Fix bug 1850698 + +* Mon Jun 15 2020 Fernando Fernandez Mancera - 0.3.2-1 +- Upgrade to 0.3.2 +- Sync. up with upstream spec file + +* Thu Jun 11 2020 Gris Ge - 0.3.1-1 +- Upgrade to 0.3.1 + +* Wed May 13 2020 Fernando Fernandez Mancera - 0.3.0-1 +- Upgrade to 0.3.0 +- Sync. up with upstream spec file. +- Update signature verification. + +* 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 + +* Fri Mar 20 2020 Gris Ge - 0.2.6-5 +- Support static DNS with DHCP. RHBZ #1815112 + +* Thu Mar 12 2020 Fernando Fernandez Mancera - 0.2.6-4.8 +- Fix bond mac and options regression. RHBZ #1809330 + +* Mon Mar 09 2020 Gris Ge - 0.2.6-3.8 +- Fix change bond mode. RHBZ #1809330 + +* Mon Mar 02 2020 Fernando Fernandez Mancera - 0.2.6-2.7 +- Fix cmd stuck when trying to create ovs-bond. RHBZ #1806249. + +* Tue Feb 25 2020 Gris Ge - 0.2.6-1 +- Upgrade to 0.2.6 + +* Thu Feb 20 2020 Gris Ge - 0.2.5-1 +- Upgrade to 0.2.5 + +* Thu Feb 13 2020 Gris Ge - 0.2.4-2 +- Fix failure when editing existing OVS interface. RHBZ #1786935 + +* Thu Feb 13 2020 Gris Ge - 0.2.4-1 +- Upgrade to 0.2.4 + +* Wed Feb 05 2020 Fernando Fernandez Mancera - 0.2.3-1 +- Upgrade to 0.2.3 + +* Tue Feb 04 2020 Fernando Fernandez Mancera - 0.2.2-3 +- Fix the incorrect source + +* Tue Feb 04 2020 Fernando Fernandez Mancera - 0.2.2-2 +- Upgrade to 0.2.2 + +* Wed Jan 22 2020 Gris Ge - 0.2.0-3.1 +- Fix the memeory leak of NM.Client. RHBZ #1784707 + +* Mon Dec 02 2019 Gris Ge - 0.2.0-2 +- Fix the incorrect source tarbal. + +* Mon Dec 02 2019 Gris Ge - 0.2.0-1 +- Upgrade to nmstate 0.2.0 + +* Mon Dec 02 2019 Gris Ge - 0.1.1-4 +- Fix the problem found by CI gating. + +* Mon Dec 02 2019 Gris Ge - 0.1.1-3 +- Bump dist number as RHEL 8.1.1 took 0.1.1-2. + +* Mon Dec 02 2019 Gris Ge - 0.1.1-2 +- Upgrade to nmstate 0.1.1. + +* Tue Sep 10 2019 Gris Ge - 0.0.8-15 +- Detach slaves without deleting them: RHBZ #1749632 + +* Fri Sep 06 2019 Gris Ge - 0.0.8-14 +- Preserve (dynamic) IPv6 address base on MAC address: RHBZ #1748825 + +* Fri Sep 06 2019 Gris Ge - 0.0.8-13 +- Prioritize master interfaces activaction: RHBZ #1749314 + +* Mon Sep 02 2019 Gris Ge - 0.0.8-12 +- Fix slave activatoin race: RHBZ #1741440 + +* Mon Sep 02 2019 Gris Ge - 0.0.8-10 +- Fix RHBZ #1740125 + +* Wed Aug 14 2019 Gris Ge - 0.0.8-9 +- Fix RHBZ #1741049 + +* Wed Aug 14 2019 Gris Ge - 0.0.8-8 +- Fix RHBZ #1740584 + +* Tue Aug 13 2019 Gris Ge - 0.0.8-7 +- Fix RHBZ #1740554 + +* Tue Aug 13 2019 Gris Ge - 0.0.8-6 +- Bump release tag as CNV took the -5. + +* Tue Aug 13 2019 Gris Ge - 0.0.8-5 +- Bump release tag as CNV took the -4. + +* Tue Aug 13 2019 Gris Ge - 0.0.8-4 +- Disable reapply on ipv6 to fix bug 1738101. + +* Fri Jul 26 2019 Gris Ge - 0.0.8-3 +- Fix the license to meet Fedora/RHEL guideline. + +* Fri Jul 26 2019 Gris Ge - 0.0.8-2 +- Relicense to LGPL2.1+. + +* Fri Jul 26 2019 Gris Ge - 0.0.8-1 +- Upgrade to 0.0.8. + +* Fri Jun 14 2019 Gris Ge - 0.0.7-1 +- Upgrade to 0.0.7. + +* Mon Apr 22 2019 Gris Ge - 0.0.5-3 +- Add missing runtime dependency. + +* Thu Mar 21 2019 Gris Ge - 0.0.5-2 +- Rebuild to enable CI testing. + +* Mon Mar 18 2019 Gris Ge - 0.0.5-1 +- Initial release