|
|
f955d2 |
From ad2bfa136290e72cdfd4b7877b49b3fc07203f9c Mon Sep 17 00:00:00 2001
|
|
|
f955d2 |
From: Gris Ge <fge@redhat.com>
|
|
|
f955d2 |
Date: Tue, 21 Feb 2023 16:26:22 +0800
|
|
|
f955d2 |
Subject: [PATCH] clib: Introduce YAML support
|
|
|
f955d2 |
|
|
|
f955d2 |
Allowing both YAML and JSON input, the output format will matching input
|
|
|
f955d2 |
format.
|
|
|
f955d2 |
|
|
|
f955d2 |
For `nmstate_net_state_retrieve()`, user can use
|
|
|
f955d2 |
`NMSTATE_FLAG_YAML_OUTPUT` flag to instruct the output to be YAML
|
|
|
f955d2 |
format.
|
|
|
f955d2 |
|
|
|
f955d2 |
Signed-off-by: Gris Ge <fge@redhat.com>
|
|
|
f955d2 |
---
|
|
|
f955d2 |
rust/src/clib/Cargo.toml | 1 +
|
|
|
f955d2 |
rust/src/clib/apply.rs | 2 +-
|
|
|
f955d2 |
rust/src/clib/gen_conf.rs | 52 +++++++-----
|
|
|
f955d2 |
rust/src/clib/nmstate.h.in | 55 +++++++------
|
|
|
f955d2 |
rust/src/clib/policy.rs | 57 ++++++++-----
|
|
|
f955d2 |
rust/src/clib/query.rs | 49 ++++++++----
|
|
|
f955d2 |
.../{nmpolicy_test.c => nmpolicy_json_test.c} | 5 ++
|
|
|
f955d2 |
rust/src/clib/test/nmpolicy_yaml_test.c | 80 +++++++++++++++++++
|
|
|
f955d2 |
.../{nmstate_test.c => nmstate_json_test.c} | 5 ++
|
|
|
f955d2 |
rust/src/clib/test/nmstate_yaml_test.c | 34 ++++++++
|
|
|
f955d2 |
rust/src/lib/Cargo.toml | 3 +
|
|
|
f955d2 |
rust/src/lib/net_state.rs | 14 +++-
|
|
|
f955d2 |
12 files changed, 274 insertions(+), 83 deletions(-)
|
|
|
f955d2 |
rename rust/src/clib/test/{nmpolicy_test.c => nmpolicy_json_test.c} (96%)
|
|
|
f955d2 |
create mode 100644 rust/src/clib/test/nmpolicy_yaml_test.c
|
|
|
f955d2 |
rename rust/src/clib/test/{nmstate_test.c => nmstate_json_test.c} (87%)
|
|
|
f955d2 |
create mode 100644 rust/src/clib/test/nmstate_yaml_test.c
|
|
|
f955d2 |
|
|
|
f955d2 |
diff --git a/rust/src/clib/Cargo.toml b/rust/src/clib/Cargo.toml
|
|
|
f955d2 |
index 97e4128c..ed391b3a 100644
|
|
|
f955d2 |
--- a/rust/src/clib/Cargo.toml
|
|
|
f955d2 |
+++ b/rust/src/clib/Cargo.toml
|
|
|
f955d2 |
@@ -16,6 +16,7 @@ crate-type = ["cdylib", "staticlib"]
|
|
|
f955d2 |
nmstate = { path = "../lib", default-features = false }
|
|
|
f955d2 |
libc = "0.2.74"
|
|
|
f955d2 |
serde_json = "1.0"
|
|
|
f955d2 |
+serde_yaml = "0.9"
|
|
|
f955d2 |
log = "0.4.17"
|
|
|
f955d2 |
serde = { version = "1.0.137", features = ["derive"] }
|
|
|
f955d2 |
once_cell = "1.12.0"
|
|
|
f955d2 |
diff --git a/rust/src/clib/apply.rs b/rust/src/clib/apply.rs
|
|
|
f955d2 |
index 9a0d6fbc..67d39730 100644
|
|
|
f955d2 |
--- a/rust/src/clib/apply.rs
|
|
|
f955d2 |
+++ b/rust/src/clib/apply.rs
|
|
|
f955d2 |
@@ -74,7 +74,7 @@ pub extern "C" fn nmstate_net_state_apply(
|
|
|
f955d2 |
};
|
|
|
f955d2 |
|
|
|
f955d2 |
let mut net_state =
|
|
|
f955d2 |
- match nmstate::NetworkState::new_from_json(net_state_str) {
|
|
|
f955d2 |
+ match nmstate::NetworkState::new_from_yaml(net_state_str) {
|
|
|
f955d2 |
Ok(n) => n,
|
|
|
f955d2 |
Err(e) => {
|
|
|
f955d2 |
unsafe {
|
|
|
f955d2 |
diff --git a/rust/src/clib/gen_conf.rs b/rust/src/clib/gen_conf.rs
|
|
|
f955d2 |
index f63fb7b0..1ad7156b 100644
|
|
|
f955d2 |
--- a/rust/src/clib/gen_conf.rs
|
|
|
f955d2 |
+++ b/rust/src/clib/gen_conf.rs
|
|
|
f955d2 |
@@ -68,7 +68,7 @@ pub extern "C" fn nmstate_generate_configurations(
|
|
|
f955d2 |
}
|
|
|
f955d2 |
};
|
|
|
f955d2 |
|
|
|
f955d2 |
- let net_state = match nmstate::NetworkState::new_from_json(net_state_str) {
|
|
|
f955d2 |
+ let net_state = match nmstate::NetworkState::new_from_yaml(net_state_str) {
|
|
|
f955d2 |
Ok(n) => n,
|
|
|
f955d2 |
Err(e) => {
|
|
|
f955d2 |
unsafe {
|
|
|
f955d2 |
@@ -80,28 +80,44 @@ pub extern "C" fn nmstate_generate_configurations(
|
|
|
f955d2 |
}
|
|
|
f955d2 |
};
|
|
|
f955d2 |
|
|
|
f955d2 |
+ let input_is_json =
|
|
|
f955d2 |
+ serde_json::from_str::<serde_json::Value>(net_state_str).is_ok();
|
|
|
f955d2 |
let result = net_state.gen_conf();
|
|
|
f955d2 |
unsafe {
|
|
|
f955d2 |
*log = CString::new(logger.drain(now)).unwrap().into_raw();
|
|
|
f955d2 |
}
|
|
|
f955d2 |
match result {
|
|
|
f955d2 |
- Ok(s) => match serde_json::to_string(&s) {
|
|
|
f955d2 |
- Ok(cfgs) => unsafe {
|
|
|
f955d2 |
- *configs = CString::new(cfgs).unwrap().into_raw();
|
|
|
f955d2 |
- NMSTATE_PASS
|
|
|
f955d2 |
- },
|
|
|
f955d2 |
- Err(e) => unsafe {
|
|
|
f955d2 |
- *err_msg =
|
|
|
f955d2 |
- CString::new(format!("serde_json::to_string failure: {e}"))
|
|
|
f955d2 |
- .unwrap()
|
|
|
f955d2 |
- .into_raw();
|
|
|
f955d2 |
- *err_kind =
|
|
|
f955d2 |
- CString::new(format!("{}", nmstate::ErrorKind::Bug))
|
|
|
f955d2 |
- .unwrap()
|
|
|
f955d2 |
- .into_raw();
|
|
|
f955d2 |
- NMSTATE_FAIL
|
|
|
f955d2 |
- },
|
|
|
f955d2 |
- },
|
|
|
f955d2 |
+ Ok(s) => {
|
|
|
f955d2 |
+ let serialize = if input_is_json {
|
|
|
f955d2 |
+ serde_json::to_string(&s).map_err(|e| {
|
|
|
f955d2 |
+ nmstate::NmstateError::new(
|
|
|
f955d2 |
+ nmstate::ErrorKind::Bug,
|
|
|
f955d2 |
+ format!("Failed to convert state {s:?} to JSON: {e}"),
|
|
|
f955d2 |
+ )
|
|
|
f955d2 |
+ })
|
|
|
f955d2 |
+ } else {
|
|
|
f955d2 |
+ serde_yaml::to_string(&s).map_err(|e| {
|
|
|
f955d2 |
+ nmstate::NmstateError::new(
|
|
|
f955d2 |
+ nmstate::ErrorKind::Bug,
|
|
|
f955d2 |
+ format!("Failed to convert state {s:?} to YAML: {e}"),
|
|
|
f955d2 |
+ )
|
|
|
f955d2 |
+ })
|
|
|
f955d2 |
+ };
|
|
|
f955d2 |
+
|
|
|
f955d2 |
+ match serialize {
|
|
|
f955d2 |
+ Ok(cfgs) => unsafe {
|
|
|
f955d2 |
+ *configs = CString::new(cfgs).unwrap().into_raw();
|
|
|
f955d2 |
+ NMSTATE_PASS
|
|
|
f955d2 |
+ },
|
|
|
f955d2 |
+ Err(e) => unsafe {
|
|
|
f955d2 |
+ *err_msg =
|
|
|
f955d2 |
+ CString::new(e.msg().to_string()).unwrap().into_raw();
|
|
|
f955d2 |
+ *err_kind =
|
|
|
f955d2 |
+ CString::new(e.kind().to_string()).unwrap().into_raw();
|
|
|
f955d2 |
+ NMSTATE_FAIL
|
|
|
f955d2 |
+ },
|
|
|
f955d2 |
+ }
|
|
|
f955d2 |
+ }
|
|
|
f955d2 |
Err(e) => {
|
|
|
f955d2 |
unsafe {
|
|
|
f955d2 |
*err_msg = CString::new(e.msg()).unwrap().into_raw();
|
|
|
f955d2 |
diff --git a/rust/src/clib/nmstate.h.in b/rust/src/clib/nmstate.h.in
|
|
|
f955d2 |
index 0879d47e..391477fd 100644
|
|
|
f955d2 |
--- a/rust/src/clib/nmstate.h.in
|
|
|
f955d2 |
+++ b/rust/src/clib/nmstate.h.in
|
|
|
f955d2 |
@@ -1,19 +1,4 @@
|
|
|
f955d2 |
-/*
|
|
|
f955d2 |
- * Copyright 2021 Red Hat
|
|
|
f955d2 |
- *
|
|
|
f955d2 |
- * Licensed under the Apache License, Version 2.0 (the "License");
|
|
|
f955d2 |
- * you may not use this file except in compliance with the License.
|
|
|
f955d2 |
- * You may obtain a copy of the License at
|
|
|
f955d2 |
- *
|
|
|
f955d2 |
- * http://www.apache.org/licenses/LICENSE-2.0
|
|
|
f955d2 |
- *
|
|
|
f955d2 |
- * Unless required by applicable law or agreed to in writing, software
|
|
|
f955d2 |
- * distributed under the License is distributed on an "AS IS" BASIS,
|
|
|
f955d2 |
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
|
f955d2 |
- * See the License for the specific language governing permissions and
|
|
|
f955d2 |
- * limitations under the License.
|
|
|
f955d2 |
- */
|
|
|
f955d2 |
-
|
|
|
f955d2 |
+// SPDX-License-Identifier: Apache-2.0
|
|
|
f955d2 |
|
|
|
f955d2 |
#ifndef _LIBNMSTATE_H_
|
|
|
f955d2 |
#define _LIBNMSTATE_H_
|
|
|
f955d2 |
@@ -44,6 +29,7 @@ extern "C" {
|
|
|
f955d2 |
#define NMSTATE_FLAG_NO_COMMIT 1 << 5
|
|
|
f955d2 |
#define NMSTATE_FLAG_MEMORY_ONLY 1 << 6
|
|
|
f955d2 |
#define NMSTATE_FLAG_RUNNING_CONFIG_ONLY 1 << 7
|
|
|
f955d2 |
+#define NMSTATE_FLAG_YAML_OUTPUT 1 << 8
|
|
|
f955d2 |
|
|
|
f955d2 |
/**
|
|
|
f955d2 |
* nmstate_net_state_retrieve - Retrieve network state
|
|
|
f955d2 |
@@ -52,7 +38,7 @@ extern "C" {
|
|
|
f955d2 |
* 0.1
|
|
|
f955d2 |
*
|
|
|
f955d2 |
* Description:
|
|
|
f955d2 |
- * Retrieve network state in the format of JSON.
|
|
|
f955d2 |
+ * Retrieve network state in the format of JSON or YAML.
|
|
|
f955d2 |
*
|
|
|
f955d2 |
* @flags:
|
|
|
f955d2 |
* Flags for special use cases:
|
|
|
f955d2 |
@@ -60,6 +46,13 @@ extern "C" {
|
|
|
f955d2 |
* No flag
|
|
|
f955d2 |
* * NMSTATE_FLAG_KERNEL_ONLY
|
|
|
f955d2 |
* Do not use external plugins, show kernel status only.
|
|
|
f955d2 |
+ * * NMSTATE_FLAG_INCLUDE_SECRETS
|
|
|
f955d2 |
+ * No not hide sercerts like password.
|
|
|
f955d2 |
+ * * NMSTATE_FLAG_RUNNING_CONFIG_ONLY
|
|
|
f955d2 |
+ * Only include running config excluding running status like auto
|
|
|
f955d2 |
+ * IP addresses and routes, LLDP neighbors.
|
|
|
f955d2 |
+ * * NMSTATE_FLAG_YAML_OUTPUT
|
|
|
f955d2 |
+ * Show the state in YAML format
|
|
|
f955d2 |
* @state:
|
|
|
f955d2 |
* Output pointer of char array for network state in json format.
|
|
|
f955d2 |
* The memory should be freed by nmstate_net_state_free().
|
|
|
f955d2 |
@@ -90,7 +83,7 @@ int nmstate_net_state_retrieve(uint32_t flags, char **state, char **log,
|
|
|
f955d2 |
* 0.1
|
|
|
f955d2 |
*
|
|
|
f955d2 |
* Description:
|
|
|
f955d2 |
- * Apply network state in the format of JSON.
|
|
|
f955d2 |
+ * Apply network state in the format of JSON or YAML.
|
|
|
f955d2 |
*
|
|
|
f955d2 |
* @flags:
|
|
|
f955d2 |
* Flags for special use cases:
|
|
|
f955d2 |
@@ -98,8 +91,12 @@ int nmstate_net_state_retrieve(uint32_t flags, char **state, char **log,
|
|
|
f955d2 |
* No flag
|
|
|
f955d2 |
* * NMSTATE_FLAG_KERNEL_ONLY
|
|
|
f955d2 |
* Do not use external plugins, apply to kernel only.
|
|
|
f955d2 |
+ * * NMSTATE_FLAG_NO_VERIFY
|
|
|
f955d2 |
+ * Do not verify state after applied
|
|
|
f955d2 |
* * NMSTATE_FLAG_NO_COMMIT
|
|
|
f955d2 |
* Do not commit new state after verification
|
|
|
f955d2 |
+ * * NMSTATE_FLAG_MEMORY_ONLY
|
|
|
f955d2 |
+ * No not store network state to persistent.
|
|
|
f955d2 |
* @state:
|
|
|
f955d2 |
* Pointer of char array for network state in json format.
|
|
|
f955d2 |
* @log:
|
|
|
f955d2 |
@@ -119,7 +116,8 @@ int nmstate_net_state_retrieve(uint32_t flags, char **state, char **log,
|
|
|
f955d2 |
* * NMSTATE_FAIL
|
|
|
f955d2 |
* On failure.
|
|
|
f955d2 |
*/
|
|
|
f955d2 |
-int nmstate_net_state_apply(uint32_t flags, const char *state, uint32_t rollback_timeout, char **log,
|
|
|
f955d2 |
+int nmstate_net_state_apply(uint32_t flags, const char *state,
|
|
|
f955d2 |
+ uint32_t rollback_timeout, char **log,
|
|
|
f955d2 |
char **err_kind, char **err_msg);
|
|
|
f955d2 |
|
|
|
f955d2 |
/**
|
|
|
f955d2 |
@@ -151,8 +149,8 @@ int nmstate_net_state_apply(uint32_t flags, const char *state, uint32_t rollback
|
|
|
f955d2 |
* * NMSTATE_FAIL
|
|
|
f955d2 |
* On failure.
|
|
|
f955d2 |
*/
|
|
|
f955d2 |
-int nmstate_checkpoint_commit(const char *checkpoint, char **log, char **err_kind,
|
|
|
f955d2 |
- char **err_msg);
|
|
|
f955d2 |
+int nmstate_checkpoint_commit(const char *checkpoint, char **log,
|
|
|
f955d2 |
+ char **err_kind, char **err_msg);
|
|
|
f955d2 |
|
|
|
f955d2 |
/**
|
|
|
f955d2 |
* nmstate_checkpoint_rollback - Rollback the checkpoint
|
|
|
f955d2 |
@@ -183,8 +181,8 @@ int nmstate_checkpoint_commit(const char *checkpoint, char **log, char **err_kin
|
|
|
f955d2 |
* * NMSTATE_FAIL
|
|
|
f955d2 |
* On failure.
|
|
|
f955d2 |
*/
|
|
|
f955d2 |
-int nmstate_checkpoint_rollback(const char *checkpoint, char **log, char **err_kind,
|
|
|
f955d2 |
- char **err_msg);
|
|
|
f955d2 |
+int nmstate_checkpoint_rollback(const char *checkpoint, char **log,
|
|
|
f955d2 |
+ char **err_kind, char **err_msg);
|
|
|
f955d2 |
|
|
|
f955d2 |
/**
|
|
|
f955d2 |
* nmstate_generate_configurations - Generate network configurations
|
|
|
f955d2 |
@@ -199,9 +197,10 @@ int nmstate_checkpoint_rollback(const char *checkpoint, char **log, char **err_k
|
|
|
f955d2 |
* as value.
|
|
|
f955d2 |
*
|
|
|
f955d2 |
* @state:
|
|
|
f955d2 |
- * Pointer of char array for network state in json format.
|
|
|
f955d2 |
+ * Pointer of char array for network state in JSON or YAML format.
|
|
|
f955d2 |
* @configs:
|
|
|
f955d2 |
- * Output pointer of char array for network configures in json format.
|
|
|
f955d2 |
+ * Output pointer of char array for network configures in JSON or
|
|
|
f955d2 |
+ * YAML(depend on which format you use in @state) format.
|
|
|
f955d2 |
* The memory should be freed by nmstate_net_state_free().
|
|
|
f955d2 |
* @log:
|
|
|
f955d2 |
* Output pointer of char array for logging.
|
|
|
f955d2 |
@@ -231,14 +230,14 @@ int nmstate_generate_configurations(const char *state, char **configs,
|
|
|
f955d2 |
* 2.2
|
|
|
f955d2 |
*
|
|
|
f955d2 |
* Description:
|
|
|
f955d2 |
- * Generate new network state from policy again specifed state
|
|
|
f955d2 |
+ * Generate new network state from policy again specified state
|
|
|
f955d2 |
*
|
|
|
f955d2 |
* @policy:
|
|
|
f955d2 |
- * Pointer of char array for network policy in json format.
|
|
|
f955d2 |
+ * Pointer of char array for network policy in JSON/YAML format.
|
|
|
f955d2 |
* @current_state:
|
|
|
f955d2 |
* Pointer of char array for current network state.
|
|
|
f955d2 |
* @state:
|
|
|
f955d2 |
- * Output pointer of char array for network state in json format.
|
|
|
f955d2 |
+ * Output pointer of char array for network state in JSON/YAML format.
|
|
|
f955d2 |
* The memory should be freed by nmstate_net_state_free().
|
|
|
f955d2 |
* @log:
|
|
|
f955d2 |
* Output pointer of char array for logging.
|
|
|
f955d2 |
diff --git a/rust/src/clib/policy.rs b/rust/src/clib/policy.rs
|
|
|
f955d2 |
index ec8c46c1..ea7dd036 100644
|
|
|
f955d2 |
--- a/rust/src/clib/policy.rs
|
|
|
f955d2 |
+++ b/rust/src/clib/policy.rs
|
|
|
f955d2 |
@@ -67,6 +67,13 @@ pub extern "C" fn nmstate_net_state_from_policy(
|
|
|
f955d2 |
}
|
|
|
f955d2 |
};
|
|
|
f955d2 |
|
|
|
f955d2 |
+ let input_is_json =
|
|
|
f955d2 |
+ if let Ok(policy_str) = unsafe { CStr::from_ptr(policy) }.to_str() {
|
|
|
f955d2 |
+ serde_json::from_str::<serde_json::Value>(policy_str).is_ok()
|
|
|
f955d2 |
+ } else {
|
|
|
f955d2 |
+ false
|
|
|
f955d2 |
+ };
|
|
|
f955d2 |
+
|
|
|
f955d2 |
let mut policy = match deserilize_from_c_char::<NetworkPolicy>(
|
|
|
f955d2 |
policy, err_kind, err_msg,
|
|
|
f955d2 |
) {
|
|
|
f955d2 |
@@ -86,23 +93,37 @@ pub extern "C" fn nmstate_net_state_from_policy(
|
|
|
f955d2 |
}
|
|
|
f955d2 |
|
|
|
f955d2 |
match result {
|
|
|
f955d2 |
- Ok(s) => match serde_json::to_string(&s) {
|
|
|
f955d2 |
- Ok(state_str) => unsafe {
|
|
|
f955d2 |
- *state = CString::new(state_str).unwrap().into_raw();
|
|
|
f955d2 |
- NMSTATE_PASS
|
|
|
f955d2 |
- },
|
|
|
f955d2 |
- Err(e) => unsafe {
|
|
|
f955d2 |
- *err_msg =
|
|
|
f955d2 |
- CString::new(format!("serde_json::to_string failure: {e}"))
|
|
|
f955d2 |
- .unwrap()
|
|
|
f955d2 |
- .into_raw();
|
|
|
f955d2 |
- *err_kind =
|
|
|
f955d2 |
- CString::new(format!("{}", nmstate::ErrorKind::Bug))
|
|
|
f955d2 |
- .unwrap()
|
|
|
f955d2 |
- .into_raw();
|
|
|
f955d2 |
- NMSTATE_FAIL
|
|
|
f955d2 |
- },
|
|
|
f955d2 |
- },
|
|
|
f955d2 |
+ Ok(s) => {
|
|
|
f955d2 |
+ let serialize = if input_is_json {
|
|
|
f955d2 |
+ serde_json::to_string(&s).map_err(|e| {
|
|
|
f955d2 |
+ nmstate::NmstateError::new(
|
|
|
f955d2 |
+ nmstate::ErrorKind::Bug,
|
|
|
f955d2 |
+ format!("Failed to convert state {s:?} to JSON: {e}"),
|
|
|
f955d2 |
+ )
|
|
|
f955d2 |
+ })
|
|
|
f955d2 |
+ } else {
|
|
|
f955d2 |
+ serde_yaml::to_string(&s).map_err(|e| {
|
|
|
f955d2 |
+ nmstate::NmstateError::new(
|
|
|
f955d2 |
+ nmstate::ErrorKind::Bug,
|
|
|
f955d2 |
+ format!("Failed to convert state {s:?} to YAML: {e}"),
|
|
|
f955d2 |
+ )
|
|
|
f955d2 |
+ })
|
|
|
f955d2 |
+ };
|
|
|
f955d2 |
+
|
|
|
f955d2 |
+ match serialize {
|
|
|
f955d2 |
+ Ok(state_str) => unsafe {
|
|
|
f955d2 |
+ *state = CString::new(state_str).unwrap().into_raw();
|
|
|
f955d2 |
+ NMSTATE_PASS
|
|
|
f955d2 |
+ },
|
|
|
f955d2 |
+ Err(e) => unsafe {
|
|
|
f955d2 |
+ *err_msg =
|
|
|
f955d2 |
+ CString::new(e.msg().to_string()).unwrap().into_raw();
|
|
|
f955d2 |
+ *err_kind =
|
|
|
f955d2 |
+ CString::new(e.kind().to_string()).unwrap().into_raw();
|
|
|
f955d2 |
+ NMSTATE_FAIL
|
|
|
f955d2 |
+ },
|
|
|
f955d2 |
+ }
|
|
|
f955d2 |
+ }
|
|
|
f955d2 |
Err(e) => {
|
|
|
f955d2 |
unsafe {
|
|
|
f955d2 |
*err_msg = CString::new(e.msg()).unwrap().into_raw();
|
|
|
f955d2 |
@@ -144,7 +165,7 @@ where
|
|
|
f955d2 |
}
|
|
|
f955d2 |
};
|
|
|
f955d2 |
|
|
|
f955d2 |
- match serde_json::from_str(content_str) {
|
|
|
f955d2 |
+ match serde_yaml::from_str(content_str) {
|
|
|
f955d2 |
Ok(n) => Some(n),
|
|
|
f955d2 |
Err(e) => {
|
|
|
f955d2 |
unsafe {
|
|
|
f955d2 |
diff --git a/rust/src/clib/query.rs b/rust/src/clib/query.rs
|
|
|
f955d2 |
index a24b9c83..12e44d05 100644
|
|
|
f955d2 |
--- a/rust/src/clib/query.rs
|
|
|
f955d2 |
+++ b/rust/src/clib/query.rs
|
|
|
f955d2 |
@@ -14,6 +14,7 @@ pub(crate) const NMSTATE_FLAG_INCLUDE_SECRETS: u32 = 1 << 4;
|
|
|
f955d2 |
pub(crate) const NMSTATE_FLAG_NO_COMMIT: u32 = 1 << 5;
|
|
|
f955d2 |
pub(crate) const NMSTATE_FLAG_MEMORY_ONLY: u32 = 1 << 6;
|
|
|
f955d2 |
pub(crate) const NMSTATE_FLAG_RUNNING_CONFIG_ONLY: u32 = 1 << 7;
|
|
|
f955d2 |
+pub(crate) const NMSTATE_FLAG_YAML_OUTPUT: u32 = 1 << 8;
|
|
|
f955d2 |
|
|
|
f955d2 |
#[allow(clippy::not_unsafe_ptr_arg_deref)]
|
|
|
f955d2 |
#[no_mangle]
|
|
|
f955d2 |
@@ -72,23 +73,37 @@ pub extern "C" fn nmstate_net_state_retrieve(
|
|
|
f955d2 |
}
|
|
|
f955d2 |
|
|
|
f955d2 |
match result {
|
|
|
f955d2 |
- Ok(s) => match serde_json::to_string(&s) {
|
|
|
f955d2 |
- Ok(state_str) => unsafe {
|
|
|
f955d2 |
- *state = CString::new(state_str).unwrap().into_raw();
|
|
|
f955d2 |
- NMSTATE_PASS
|
|
|
f955d2 |
- },
|
|
|
f955d2 |
- Err(e) => unsafe {
|
|
|
f955d2 |
- *err_msg =
|
|
|
f955d2 |
- CString::new(format!("serde_json::to_string failure: {e}"))
|
|
|
f955d2 |
- .unwrap()
|
|
|
f955d2 |
- .into_raw();
|
|
|
f955d2 |
- *err_kind =
|
|
|
f955d2 |
- CString::new(format!("{}", nmstate::ErrorKind::Bug))
|
|
|
f955d2 |
- .unwrap()
|
|
|
f955d2 |
- .into_raw();
|
|
|
f955d2 |
- NMSTATE_FAIL
|
|
|
f955d2 |
- },
|
|
|
f955d2 |
- },
|
|
|
f955d2 |
+ Ok(s) => {
|
|
|
f955d2 |
+ let serialize = if (flags & NMSTATE_FLAG_YAML_OUTPUT) > 0 {
|
|
|
f955d2 |
+ serde_yaml::to_string(&s).map_err(|e| {
|
|
|
f955d2 |
+ nmstate::NmstateError::new(
|
|
|
f955d2 |
+ nmstate::ErrorKind::Bug,
|
|
|
f955d2 |
+ format!("Failed to convert state {s:?} to YAML: {e}"),
|
|
|
f955d2 |
+ )
|
|
|
f955d2 |
+ })
|
|
|
f955d2 |
+ } else {
|
|
|
f955d2 |
+ serde_json::to_string(&s).map_err(|e| {
|
|
|
f955d2 |
+ nmstate::NmstateError::new(
|
|
|
f955d2 |
+ nmstate::ErrorKind::Bug,
|
|
|
f955d2 |
+ format!("Failed to convert state {s:?} to JSON: {e}"),
|
|
|
f955d2 |
+ )
|
|
|
f955d2 |
+ })
|
|
|
f955d2 |
+ };
|
|
|
f955d2 |
+
|
|
|
f955d2 |
+ match serialize {
|
|
|
f955d2 |
+ Ok(state_str) => unsafe {
|
|
|
f955d2 |
+ *state = CString::new(state_str).unwrap().into_raw();
|
|
|
f955d2 |
+ NMSTATE_PASS
|
|
|
f955d2 |
+ },
|
|
|
f955d2 |
+ Err(e) => unsafe {
|
|
|
f955d2 |
+ *err_msg =
|
|
|
f955d2 |
+ CString::new(e.msg().to_string()).unwrap().into_raw();
|
|
|
f955d2 |
+ *err_kind =
|
|
|
f955d2 |
+ CString::new(e.kind().to_string()).unwrap().into_raw();
|
|
|
f955d2 |
+ NMSTATE_FAIL
|
|
|
f955d2 |
+ },
|
|
|
f955d2 |
+ }
|
|
|
f955d2 |
+ }
|
|
|
f955d2 |
Err(e) => {
|
|
|
f955d2 |
unsafe {
|
|
|
f955d2 |
*err_msg = CString::new(e.msg()).unwrap().into_raw();
|
|
|
f955d2 |
diff --git a/rust/src/clib/test/nmpolicy_test.c b/rust/src/clib/test/nmpolicy_json_test.c
|
|
|
f955d2 |
similarity index 96%
|
|
|
f955d2 |
rename from rust/src/clib/test/nmpolicy_test.c
|
|
|
f955d2 |
rename to rust/src/clib/test/nmpolicy_json_test.c
|
|
|
f955d2 |
index 7a71a5f5..8a0444d4 100644
|
|
|
f955d2 |
--- a/rust/src/clib/test/nmpolicy_test.c
|
|
|
f955d2 |
+++ b/rust/src/clib/test/nmpolicy_json_test.c
|
|
|
f955d2 |
@@ -1,3 +1,6 @@
|
|
|
f955d2 |
+// SPDX-License-Identifier: Apache-2.0
|
|
|
f955d2 |
+
|
|
|
f955d2 |
+#include <assert.h>
|
|
|
f955d2 |
#include <stddef.h>
|
|
|
f955d2 |
#include <stdint.h>
|
|
|
f955d2 |
#include <stdio.h>
|
|
|
f955d2 |
@@ -91,6 +94,8 @@ int main(void) {
|
|
|
f955d2 |
rc = EXIT_FAILURE;
|
|
|
f955d2 |
}
|
|
|
f955d2 |
|
|
|
f955d2 |
+ assert(state[0] == '{');
|
|
|
f955d2 |
+
|
|
|
f955d2 |
nmstate_cstring_free(state);
|
|
|
f955d2 |
nmstate_cstring_free(err_kind);
|
|
|
f955d2 |
nmstate_cstring_free(err_msg);
|
|
|
f955d2 |
diff --git a/rust/src/clib/test/nmpolicy_yaml_test.c b/rust/src/clib/test/nmpolicy_yaml_test.c
|
|
|
f955d2 |
new file mode 100644
|
|
|
f955d2 |
index 00000000..7984f509
|
|
|
f955d2 |
--- /dev/null
|
|
|
f955d2 |
+++ b/rust/src/clib/test/nmpolicy_yaml_test.c
|
|
|
f955d2 |
@@ -0,0 +1,80 @@
|
|
|
f955d2 |
+// SPDX-License-Identifier: Apache-2.0
|
|
|
f955d2 |
+
|
|
|
f955d2 |
+#include <assert.h>
|
|
|
f955d2 |
+#include <stddef.h>
|
|
|
f955d2 |
+#include <stdint.h>
|
|
|
f955d2 |
+#include <stdio.h>
|
|
|
f955d2 |
+#include <stdlib.h>
|
|
|
f955d2 |
+
|
|
|
f955d2 |
+#include <nmstate.h>
|
|
|
f955d2 |
+
|
|
|
f955d2 |
+int main(void) {
|
|
|
f955d2 |
+ int rc = EXIT_SUCCESS;
|
|
|
f955d2 |
+ const char *policy = "\
|
|
|
f955d2 |
+capture:\n\
|
|
|
f955d2 |
+ default-gw: override me with the cache\n\
|
|
|
f955d2 |
+ base-iface: >\n\
|
|
|
f955d2 |
+ interfaces.name == capture.default-gw.routes.running.0.next-hop-interface\n\
|
|
|
f955d2 |
+ base-iface-routes: >\n\
|
|
|
f955d2 |
+ routes.running.next-hop-interface ==\n\
|
|
|
f955d2 |
+ capture.default-gw.routes.running.0.next-hop-interface\n\
|
|
|
f955d2 |
+ bridge-routes: >\n\
|
|
|
f955d2 |
+ capture.base-iface-routes | routes.running.next-hop-interface:=\"br1\"\n\
|
|
|
f955d2 |
+desired:\n\
|
|
|
f955d2 |
+ interfaces:\n\
|
|
|
f955d2 |
+ - name: br1\n\
|
|
|
f955d2 |
+ description: Linux bridge with base interface as a port\n\
|
|
|
f955d2 |
+ type: linux-bridge\n\
|
|
|
f955d2 |
+ state: up\n\
|
|
|
f955d2 |
+ bridge:\n\
|
|
|
f955d2 |
+ options:\n\
|
|
|
f955d2 |
+ stp:\n\
|
|
|
f955d2 |
+ enabled: false\n\
|
|
|
f955d2 |
+ port:\n\
|
|
|
f955d2 |
+ - name: '{{ capture.base-iface.interfaces.0.name }}'\n\
|
|
|
f955d2 |
+ ipv4: '{{ capture.base-iface.interfaces.0.ipv4 }}'\n\
|
|
|
f955d2 |
+ routes:\n\
|
|
|
f955d2 |
+ config: '{{ capture.bridge-routes.routes.running }}'";
|
|
|
f955d2 |
+ const char *current_state = "\
|
|
|
f955d2 |
+interfaces:\n\
|
|
|
f955d2 |
+- name: eth1\n\
|
|
|
f955d2 |
+ type: ethernet\n\
|
|
|
f955d2 |
+ state: up\n\
|
|
|
f955d2 |
+ mac-address: 1c:c1:0c:32:3b:ff\n\
|
|
|
f955d2 |
+ ipv4:\n\
|
|
|
f955d2 |
+ address:\n\
|
|
|
f955d2 |
+ - ip: 192.0.2.251\n\
|
|
|
f955d2 |
+ prefix-length: 24\n\
|
|
|
f955d2 |
+ dhcp: false\n\
|
|
|
f955d2 |
+ enabled: true\n\
|
|
|
f955d2 |
+routes:\n\
|
|
|
f955d2 |
+ config:\n\
|
|
|
f955d2 |
+ - destination: 0.0.0.0/0\n\
|
|
|
f955d2 |
+ next-hop-address: 192.0.2.1\n\
|
|
|
f955d2 |
+ next-hop-interface: eth1\n\
|
|
|
f955d2 |
+ running:\n\
|
|
|
f955d2 |
+ - destination: 0.0.0.0/0\n\
|
|
|
f955d2 |
+ next-hop-address: 192.0.2.1\n\
|
|
|
f955d2 |
+ next-hop-interface: eth1";
|
|
|
f955d2 |
+ char *state = NULL;
|
|
|
f955d2 |
+ char *err_kind = NULL;
|
|
|
f955d2 |
+ char *err_msg = NULL;
|
|
|
f955d2 |
+ char *log = NULL;
|
|
|
f955d2 |
+
|
|
|
f955d2 |
+ if (nmstate_net_state_from_policy(policy, current_state, &state, &log,
|
|
|
f955d2 |
+ &err_kind, &err_msg) == NMSTATE_PASS)
|
|
|
f955d2 |
+ {
|
|
|
f955d2 |
+ printf("%s\n", state);
|
|
|
f955d2 |
+ } else {
|
|
|
f955d2 |
+ printf("%s: %s\n", err_kind, err_msg);
|
|
|
f955d2 |
+ rc = EXIT_FAILURE;
|
|
|
f955d2 |
+ }
|
|
|
f955d2 |
+
|
|
|
f955d2 |
+ assert(state[0] != '{');
|
|
|
f955d2 |
+
|
|
|
f955d2 |
+ nmstate_cstring_free(state);
|
|
|
f955d2 |
+ nmstate_cstring_free(err_kind);
|
|
|
f955d2 |
+ nmstate_cstring_free(err_msg);
|
|
|
f955d2 |
+ nmstate_cstring_free(log);
|
|
|
f955d2 |
+ exit(rc);
|
|
|
f955d2 |
+}
|
|
|
f955d2 |
diff --git a/rust/src/clib/test/nmstate_test.c b/rust/src/clib/test/nmstate_json_test.c
|
|
|
f955d2 |
similarity index 87%
|
|
|
f955d2 |
rename from rust/src/clib/test/nmstate_test.c
|
|
|
f955d2 |
rename to rust/src/clib/test/nmstate_json_test.c
|
|
|
f955d2 |
index 0e79cb15..1bfbcda7 100644
|
|
|
f955d2 |
--- a/rust/src/clib/test/nmstate_test.c
|
|
|
f955d2 |
+++ b/rust/src/clib/test/nmstate_json_test.c
|
|
|
f955d2 |
@@ -1,3 +1,6 @@
|
|
|
f955d2 |
+// SPDX-License-Identifier: Apache-2.0
|
|
|
f955d2 |
+
|
|
|
f955d2 |
+#include <assert.h>
|
|
|
f955d2 |
#include <stddef.h>
|
|
|
f955d2 |
#include <stdint.h>
|
|
|
f955d2 |
#include <stdio.h>
|
|
|
f955d2 |
@@ -21,6 +24,8 @@ int main(void) {
|
|
|
f955d2 |
rc = EXIT_FAILURE;
|
|
|
f955d2 |
}
|
|
|
f955d2 |
|
|
|
f955d2 |
+ assert(state[0] == '{');
|
|
|
f955d2 |
+
|
|
|
f955d2 |
nmstate_cstring_free(state);
|
|
|
f955d2 |
nmstate_cstring_free(err_kind);
|
|
|
f955d2 |
nmstate_cstring_free(err_msg);
|
|
|
f955d2 |
diff --git a/rust/src/clib/test/nmstate_yaml_test.c b/rust/src/clib/test/nmstate_yaml_test.c
|
|
|
f955d2 |
new file mode 100644
|
|
|
f955d2 |
index 00000000..de0f2486
|
|
|
f955d2 |
--- /dev/null
|
|
|
f955d2 |
+++ b/rust/src/clib/test/nmstate_yaml_test.c
|
|
|
f955d2 |
@@ -0,0 +1,34 @@
|
|
|
f955d2 |
+// SPDX-License-Identifier: Apache-2.0
|
|
|
f955d2 |
+
|
|
|
f955d2 |
+#include <assert.h>
|
|
|
f955d2 |
+#include <stddef.h>
|
|
|
f955d2 |
+#include <stdint.h>
|
|
|
f955d2 |
+#include <stdio.h>
|
|
|
f955d2 |
+#include <stdlib.h>
|
|
|
f955d2 |
+
|
|
|
f955d2 |
+#include <nmstate.h>
|
|
|
f955d2 |
+
|
|
|
f955d2 |
+int main(void) {
|
|
|
f955d2 |
+ int rc = EXIT_SUCCESS;
|
|
|
f955d2 |
+ char *state = NULL;
|
|
|
f955d2 |
+ char *err_kind = NULL;
|
|
|
f955d2 |
+ char *err_msg = NULL;
|
|
|
f955d2 |
+ char *log = NULL;
|
|
|
f955d2 |
+ uint32_t flag = NMSTATE_FLAG_KERNEL_ONLY | NMSTATE_FLAG_YAML_OUTPUT;
|
|
|
f955d2 |
+
|
|
|
f955d2 |
+ if (nmstate_net_state_retrieve(flag, &state, &log, &err_kind, &err_msg)
|
|
|
f955d2 |
+ == NMSTATE_PASS) {
|
|
|
f955d2 |
+ printf("%s\n", state);
|
|
|
f955d2 |
+ } else {
|
|
|
f955d2 |
+ printf("%s: %s\n", err_kind, err_msg);
|
|
|
f955d2 |
+ rc = EXIT_FAILURE;
|
|
|
f955d2 |
+ }
|
|
|
f955d2 |
+
|
|
|
f955d2 |
+ assert(state[0] != '{');
|
|
|
f955d2 |
+
|
|
|
f955d2 |
+ nmstate_cstring_free(state);
|
|
|
f955d2 |
+ nmstate_cstring_free(err_kind);
|
|
|
f955d2 |
+ nmstate_cstring_free(err_msg);
|
|
|
f955d2 |
+ nmstate_cstring_free(log);
|
|
|
f955d2 |
+ exit(rc);
|
|
|
f955d2 |
+}
|
|
|
f955d2 |
diff --git a/rust/src/lib/Cargo.toml b/rust/src/lib/Cargo.toml
|
|
|
f955d2 |
index a27d0e1a..0142026d 100644
|
|
|
f955d2 |
--- a/rust/src/lib/Cargo.toml
|
|
|
f955d2 |
+++ b/rust/src/lib/Cargo.toml
|
|
|
f955d2 |
@@ -15,6 +15,9 @@ edition = "2018"
|
|
|
f955d2 |
[lib]
|
|
|
f955d2 |
path = "lib.rs"
|
|
|
f955d2 |
|
|
|
f955d2 |
+[dependencies]
|
|
|
f955d2 |
+serde_yaml = "0.9"
|
|
|
f955d2 |
+
|
|
|
f955d2 |
[dependencies.nispor]
|
|
|
f955d2 |
version = "1.2.9"
|
|
|
f955d2 |
optional = true
|
|
|
f955d2 |
diff --git a/rust/src/lib/net_state.rs b/rust/src/lib/net_state.rs
|
|
|
f955d2 |
index 8ab79642..fe5fea78 100644
|
|
|
f955d2 |
--- a/rust/src/lib/net_state.rs
|
|
|
f955d2 |
+++ b/rust/src/lib/net_state.rs
|
|
|
f955d2 |
@@ -274,7 +274,19 @@ impl NetworkState {
|
|
|
f955d2 |
Ok(s) => Ok(s),
|
|
|
f955d2 |
Err(e) => Err(NmstateError::new(
|
|
|
f955d2 |
ErrorKind::InvalidArgument,
|
|
|
f955d2 |
- format!("Invalid json string: {e}"),
|
|
|
f955d2 |
+ format!("Invalid JSON string: {e}"),
|
|
|
f955d2 |
+ )),
|
|
|
f955d2 |
+ }
|
|
|
f955d2 |
+ }
|
|
|
f955d2 |
+
|
|
|
f955d2 |
+ /// Wrapping function of [serde_yaml::from_str()] with error mapped to
|
|
|
f955d2 |
+ /// [NmstateError].
|
|
|
f955d2 |
+ pub fn new_from_yaml(net_state_yaml: &str) -> Result<Self, NmstateError> {
|
|
|
f955d2 |
+ match serde_yaml::from_str(net_state_yaml) {
|
|
|
f955d2 |
+ Ok(s) => Ok(s),
|
|
|
f955d2 |
+ Err(e) => Err(NmstateError::new(
|
|
|
f955d2 |
+ ErrorKind::InvalidArgument,
|
|
|
f955d2 |
+ format!("Invalid YAML string: {e}"),
|
|
|
f955d2 |
)),
|
|
|
f955d2 |
}
|
|
|
f955d2 |
}
|
|
|
f955d2 |
--
|
|
|
f955d2 |
2.39.2
|
|
|
f955d2 |
|