From c7c689e44561f33f307b119235fd7abd224903d8 Mon Sep 17 00:00:00 2001 From: Paul-weqe Date: Mon, 22 Jun 2026 20:05:32 +0300 Subject: [PATCH] grpc: separate state & configuration retrievals Complementary to holo-daemon commit: https://github.com/holo-routing/holo/commit/1aef4401f3b961367dc9450241cfbda5de254889 Making sure there is synchrony in fetching state and config data from the CLI. Signed-off-by: Paul Wekesa --- Cargo.lock | 4 +- proto/holo.proto | 54 ++++++----- src/grpc.rs | 45 ++++++++-- src/internal_commands.rs | 187 +++++++++++++++++++++++---------------- src/session.rs | 24 ++--- 5 files changed, 197 insertions(+), 117 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 6c50519..7d2bc85 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2029,9 +2029,9 @@ checksum = "a62ce76d9b56901b19a74f19431b0d8b3bc7ca4ad685a746dfd78ca8f4fc6bda" [[package]] name = "yang5" -version = "0.1.0" +version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8e5ebbf669599b5c407efa54e675230eb61d963a3d7452ddea205b6819a24064" +checksum = "1da35149085196bd35c11637c084c0723157c05d97766033cec6d90db535bd19" dependencies = [ "bitflags 2.9.0", "libc", diff --git a/proto/holo.proto b/proto/holo.proto index 4af9a94..2aa5803 100644 --- a/proto/holo.proto +++ b/proto/holo.proto @@ -32,8 +32,11 @@ service Northbound { // Retrieve the specified schema data from the target. rpc GetSchema(GetSchemaRequest) returns (GetSchemaResponse) {} - // Retrieve configuration data, state data or both from the target. - rpc Get(GetRequest) returns (GetResponse) {} + // Retrieve state data from the target. + rpc GetState(GetStateRequest) returns (GetStateResponse) {} + + // Retrieve configuration data from the target. + rpc GetConfig(GetConfigRequest) returns (GetConfigResponse) {} // Validate the configuration without committing it. rpc Validate(ValidateRequest) returns (ValidateResponse) {} @@ -106,35 +109,46 @@ message GetSchemaResponse { } // -// RPC: Get() +// RPC: GetState() // -message GetRequest { - // Type of elements within the data tree. - enum DataType { - // All data elements. - ALL = 0; +message GetStateRequest { + // Encoding to be used. + Encoding encoding = 1; - // Config elements. - CONFIG = 1; + // Include implicit default nodes. + bool with_defaults = 2; - // State elements. - STATE = 2; - } + // Target YANG path. + Path path = 3; +} + +message GetStateResponse { + // Return values: + // - grpc::StatusCode::OK: Success. + // - grpc::StatusCode::INVALID_ARGUMENT: Invalid YANG data path. - // The type of data being requested. - DataType type = 1; + // Timestamp in nanoseconds since Epoch. + int64 timestamp = 1; + + // The requested state data. + DataTree data = 2; +} +// +// RPC: GetConfig() +// +message GetConfigRequest { // Encoding to be used. - Encoding encoding = 2; + Encoding encoding = 1; // Include implicit default nodes. - bool with_defaults = 3; + bool with_defaults = 2; // Target YANG path. - Path path = 4; + Path path = 3; } -message GetResponse { +message GetConfigResponse { // Return values: // - grpc::StatusCode::OK: Success. // - grpc::StatusCode::INVALID_ARGUMENT: Invalid YANG data path. @@ -142,7 +156,7 @@ message GetResponse { // Timestamp in nanoseconds since Epoch. int64 timestamp = 1; - // The requested data. + // The requested configuration data. DataTree data = 2; } diff --git a/src/grpc.rs b/src/grpc.rs index e77f8a7..f62065a 100644 --- a/src/grpc.rs +++ b/src/grpc.rs @@ -95,17 +95,35 @@ impl GrpcClient { } } - pub fn get( + pub fn get_config( &mut self, - data_type: proto::get_request::DataType, format: DataFormat, with_defaults: bool, xpath: Option, ) -> Result { let path = xpath.map(|x| proto::Path::from_xpath(&x)); let data = self - .rpc_sync_get(proto::GetRequest { - r#type: data_type as i32, + .rpc_sync_get_config(proto::GetConfigRequest { + encoding: proto::Encoding::from(format) as i32, + with_defaults, + path, + }) + .map_err(Error::Backend)? + .into_inner() + .data + .unwrap(); + Ok(data.data.unwrap()) + } + + pub fn get_state( + &mut self, + format: DataFormat, + with_defaults: bool, + xpath: Option, + ) -> Result { + let path = xpath.map(|x| proto::Path::from_xpath(&x)); + let data = self + .rpc_sync_get_state(proto::GetStateRequest { encoding: proto::Encoding::from(format) as i32, with_defaults, path, @@ -183,12 +201,20 @@ impl GrpcClient { self.runtime.block_on(self.client.get_schema(request)) } - fn rpc_sync_get( + fn rpc_sync_get_config( + &mut self, + request: proto::GetConfigRequest, + ) -> Result, tonic::Status> { + let request = tonic::Request::new(request); + self.runtime.block_on(self.client.get_config(request)) + } + + fn rpc_sync_get_state( &mut self, - request: proto::GetRequest, - ) -> Result, tonic::Status> { + request: proto::GetStateRequest, + ) -> Result, tonic::Status> { let request = tonic::Request::new(request); - self.runtime.block_on(self.client.get(request)) + self.runtime.block_on(self.client.get_state(request)) } fn rpc_sync_commit( @@ -266,7 +292,8 @@ impl proto::Path { Some(pos) => { let name = &segment[..pos]; let mut keys = HashMap::new(); - for kv in segment[pos..].split('[').filter(|s| !s.is_empty()) + for kv in + segment[pos..].split('[').filter(|s| !s.is_empty()) { let kv = kv.trim_end_matches(']'); if let Some(eq_pos) = kv.find('=') { diff --git a/src/internal_commands.rs b/src/internal_commands.rs index 7be2056..ed67b7e 100644 --- a/src/internal_commands.rs +++ b/src/internal_commands.rs @@ -30,7 +30,6 @@ const XPATH_RIB: &str = "/ietf-routing:routing/ribs/rib"; struct YangTableBuilder<'a> { session: &'a mut Session, - data_type: proto::get_request::DataType, paths: Vec<(String, Vec)>, } @@ -54,13 +53,9 @@ enum YangValueDisplayFormat { impl<'a> YangTableBuilder<'a> { // Initializes the builder. - pub fn new( - session: &'a mut Session, - data_type: proto::get_request::DataType, - ) -> Self { + pub fn new(session: &'a mut Session) -> Self { Self { session, - data_type, paths: Vec::new(), } } @@ -202,7 +197,30 @@ impl<'a> YangTableBuilder<'a> { let xpath_req = "/ietf-routing:routing/control-plane-protocols"; // Fetch data. - let data = fetch_data(self.session, self.data_type, xpath_req)?; + let data = fetch_data(self.session, xpath_req)?; + self.create_table(data) + } + + pub fn _show_config(self) -> Result<(), CallbackError> { + let xpath_req = "/ietf-routing:routing/control-plane-protocols"; + + // Fetch config data. + let data = fetch_config_data(self.session, xpath_req)?; + self.create_table(data) + } + + pub fn show_state(self) -> Result<(), CallbackError> { + let xpath_req = "/ietf-routing:routing/control-plane-protocols"; + + // Fetch state data. + let data = fetch_state_data(self.session, xpath_req)?; + self.create_table(data) + } + + fn create_table( + self, + data: DataTree<'static>, + ) -> Result<(), CallbackError> { let Some(dnode) = data.reference() else { return Ok(()); }; @@ -260,13 +278,50 @@ fn write_output( fn fetch_data( session: &mut Session, - data_type: proto::get_request::DataType, + xpath: &str, +) -> Result, String> { + let yang_ctx = YANG_CTX.get().unwrap(); + let mut dtree = DataTree::new(yang_ctx); + + let config_data = fetch_config_data(session, xpath)?; + let state_data = fetch_state_data(session, xpath)?; + + dtree.merge(&config_data).map_err(|error| { + format!("% failed to merge config data: {} %", error) + })?; + dtree.merge(&state_data).map_err(|error| { + format!("% failed to merge state data: {} %", error) + })?; + Ok(dtree) +} + +fn fetch_config_data( + session: &mut Session, xpath: &str, ) -> Result, String> { let yang_ctx = YANG_CTX.get().unwrap(); let data_format = DataFormat::LYB; let data = session - .get(data_type, data_format, true, Some(xpath.to_owned())) + .get_config(data_format, true, Some(xpath.to_owned())) + .map_err(|error| format!("% failed to fetch config data: {}", error))?; + DataTree::parse_string( + yang_ctx, + data.as_bytes().unwrap(), + data_format, + DataParserFlags::NO_VALIDATION, + DataValidationFlags::PRESENT, + ) + .map_err(|error| format!("% failed to parse data: {}", error)) +} + +fn fetch_state_data( + session: &mut Session, + xpath: &str, +) -> Result, String> { + let yang_ctx = YANG_CTX.get().unwrap(); + let data_format = DataFormat::LYB; + let data = session + .get_state(data_format, true, Some(xpath.to_owned())) .map_err(|error| format!("% failed to fetch state data: {}", error))?; DataTree::parse_string( yang_ctx, @@ -645,8 +700,7 @@ pub fn cmd_show_state( None => DataFormat::JSON, }; - match session.get(proto::get_request::DataType::State, format, false, xpath) - { + match session.get_state(format, false, xpath) { Ok(proto::data_tree::Data::DataString(data)) => { write_output(session, &data)?; } @@ -710,7 +764,7 @@ pub fn cmd_show_isis_interface( session: &mut Session, mut args: ParsedArgs, ) -> Result { - YangTableBuilder::new(session, proto::get_request::DataType::All) + YangTableBuilder::new(session) .xpath(XPATH_PROTOCOL) .filter_list_key("type", Some(PROTOCOL_ISIS)) .column_leaf("Instance", "name") @@ -731,7 +785,7 @@ pub fn cmd_show_isis_adjacency( mut args: ParsedArgs, ) -> Result { let hostnames = isis_hostnames(session)?; - YangTableBuilder::new(session, proto::get_request::DataType::State) + YangTableBuilder::new(session) .xpath(XPATH_PROTOCOL) .filter_list_key("type", Some(PROTOCOL_ISIS)) .column_leaf("Instance", "name") @@ -761,7 +815,7 @@ pub fn cmd_show_isis_database( _args: ParsedArgs, ) -> Result { let hostnames = isis_hostnames(session)?; - YangTableBuilder::new(session, proto::get_request::DataType::State) + YangTableBuilder::new(session) .xpath(XPATH_PROTOCOL) .filter_list_key("type", Some(PROTOCOL_ISIS)) .column_leaf("Instance", "name") @@ -792,7 +846,7 @@ pub fn cmd_show_isis_route( session: &mut Session, _args: ParsedArgs, ) -> Result { - YangTableBuilder::new(session, proto::get_request::DataType::State) + YangTableBuilder::new(session) .xpath(XPATH_PROTOCOL) .filter_list_key("type", Some(PROTOCOL_ISIS)) .column_leaf("Instance", "name") @@ -803,7 +857,7 @@ pub fn cmd_show_isis_route( .xpath(XPATH_ISIS_NEXTHOP) .column_leaf("Nexthop Interface", "outgoing-interface") .column_leaf("Nexthop Address", "next-hop") - .show()?; + .show_state()?; Ok(false) } @@ -817,8 +871,7 @@ fn isis_hostnames( ); // Fetch hostname mappings. - let data = - fetch_data(session, proto::get_request::DataType::State, &xpath)?; + let data = fetch_state_data(session, &xpath)?; // Collect hostname mappings into a binary tree. let hostnames = data @@ -866,7 +919,7 @@ pub fn cmd_show_ospf_interface( "ospfv3" => PROTOCOL_OSPFV3, _ => unreachable!(), }; - YangTableBuilder::new(session, proto::get_request::DataType::All) + YangTableBuilder::new(session) .xpath(XPATH_PROTOCOL) .filter_list_key("type", Some(protocol)) .column_leaf("Instance", "name") @@ -919,8 +972,7 @@ pub fn cmd_show_ospf_interface_detail( if let Some(name) = &name { xpath_iface = format!("{}[name='{}']", xpath_iface, name); } - let data = - fetch_data(session, proto::get_request::DataType::All, xpath_req)?; + let data = fetch_data(session, xpath_req)?; // Iterate over OSPF instances. for dnode in data.find_xpath(&xpath_instance).unwrap() { @@ -975,7 +1027,7 @@ pub fn cmd_show_ospf_vlink( _ => unreachable!(), }; let hostnames = ospf_hostnames(session, protocol)?; - YangTableBuilder::new(session, proto::get_request::DataType::All) + YangTableBuilder::new(session) .xpath(XPATH_PROTOCOL) .filter_list_key("type", Some(protocol)) .column_leaf("Instance", "name") @@ -1016,7 +1068,7 @@ pub fn cmd_show_ospf_neighbor( _ => unreachable!(), }; let hostnames = ospf_hostnames(session, protocol)?; - YangTableBuilder::new(session, proto::get_request::DataType::All) + YangTableBuilder::new(session) .xpath(XPATH_PROTOCOL) .filter_list_key("type", Some(protocol)) .column_leaf("Instance", "name") @@ -1077,8 +1129,7 @@ pub fn cmd_show_ospf_neighbor_detail( xpath_nbr = format!("{}[neighbor-router-id='{}']", xpath_nbr, router_id); } - let data = - fetch_data(session, proto::get_request::DataType::All, xpath_req)?; + let data = fetch_data(session, xpath_req)?; // Iterate over OSPF instances. let output = session.writer(); @@ -1151,7 +1202,7 @@ pub fn cmd_show_ospf_database_as( _ => unreachable!(), }; let hostnames = ospf_hostnames(session, protocol)?; - YangTableBuilder::new(session, proto::get_request::DataType::State) + YangTableBuilder::new(session) .xpath(XPATH_PROTOCOL) .filter_list_key("type", Some(protocol)) .column_leaf("Instance", "name") @@ -1178,7 +1229,7 @@ pub fn cmd_show_ospf_database_as( .column_leaf("Age", "age") .column_leaf_hex32("Sequence", "seq-num") .column_leaf("Checksum", "checksum") - .show()?; + .show_state()?; Ok(false) } @@ -1194,7 +1245,7 @@ pub fn cmd_show_ospf_database_area( _ => unreachable!(), }; let hostnames = ospf_hostnames(session, protocol)?; - YangTableBuilder::new(session, proto::get_request::DataType::State) + YangTableBuilder::new(session) .xpath(XPATH_PROTOCOL) .filter_list_key("type", Some(protocol)) .column_leaf("Instance", "name") @@ -1223,7 +1274,7 @@ pub fn cmd_show_ospf_database_area( .column_leaf("Age", "age") .column_leaf_hex32("Sequence", "seq-num") .column_leaf("Checksum", "checksum") - .show()?; + .show_state()?; Ok(false) } @@ -1239,7 +1290,7 @@ pub fn cmd_show_ospf_database_link( _ => unreachable!(), }; let hostnames = ospf_hostnames(session, protocol)?; - YangTableBuilder::new(session, proto::get_request::DataType::State) + YangTableBuilder::new(session) .xpath(XPATH_PROTOCOL) .filter_list_key("type", Some(protocol)) .column_leaf("Instance", "name") @@ -1270,7 +1321,7 @@ pub fn cmd_show_ospf_database_link( .column_leaf("Age", "age") .column_leaf_hex32("Sequence", "seq-num") .column_leaf("Checksum", "checksum") - .show()?; + .show_state()?; Ok(false) } @@ -1285,7 +1336,7 @@ pub fn cmd_show_ospf_route( "ospfv3" => PROTOCOL_OSPFV3, _ => unreachable!(), }; - YangTableBuilder::new(session, proto::get_request::DataType::State) + YangTableBuilder::new(session) .xpath(XPATH_PROTOCOL) .filter_list_key("type", Some(protocol)) .column_leaf("Instance", "name") @@ -1298,7 +1349,7 @@ pub fn cmd_show_ospf_route( .xpath(XPATH_OSPF_NEXTHOP) .column_leaf("Nexthop Interface", "outgoing-interface") .column_leaf("Nexthop Address", "next-hop") - .show()?; + .show_state()?; Ok(false) } @@ -1314,14 +1365,14 @@ pub fn cmd_show_ospf_hostnames( _ => unreachable!(), }; - YangTableBuilder::new(session, proto::get_request::DataType::State) + YangTableBuilder::new(session) .xpath(XPATH_PROTOCOL) .filter_list_key("type", Some(protocol)) .column_leaf("Instance", "name") .xpath(XPATH_OSPF_HOSTNAMES) .column_leaf("Router ID", "router-id") .column_leaf("Hostname", "hostname") - .show()?; + .show_state()?; Ok(false) } @@ -1336,8 +1387,7 @@ fn ospf_hostnames( ); // Fetch hostname mappings. - let data = - fetch_data(session, proto::get_request::DataType::State, &xpath)?; + let data = fetch_state_data(session, &xpath)?; // Collect hostname mappings into a binary tree. let hostnames = data @@ -1375,7 +1425,7 @@ pub fn cmd_show_rip_interface( "ripng" => PROTOCOL_RIPNG, _ => unreachable!(), }; - YangTableBuilder::new(session, proto::get_request::DataType::State) + YangTableBuilder::new(session) .xpath(XPATH_PROTOCOL) .filter_list_key("type", Some(protocol)) .column_leaf("Instance", "name") @@ -1383,7 +1433,7 @@ pub fn cmd_show_rip_interface( .filter_list_key("interface", get_opt_arg(&mut args, "name")) .column_leaf("Name", "interface") .column_leaf("State", "oper-status") - .show()?; + .show_state()?; Ok(false) } @@ -1416,8 +1466,7 @@ pub fn cmd_show_rip_interface_detail( xpath_iface = format!("{}[interface='{}']", xpath_iface, name); } - let data = - fetch_data(session, proto::get_request::DataType::State, xpath_req)?; + let data = fetch_state_data(session, xpath_req)?; // Iterate over RIP instances. let output = session.writer(); @@ -1471,7 +1520,7 @@ pub fn cmd_show_rip_neighbor( let xpath_rip_neighbor = format!("ietf-rip:rip/{}/neighbors/neighbor", afi); - YangTableBuilder::new(session, proto::get_request::DataType::State) + YangTableBuilder::new(session) .xpath(XPATH_PROTOCOL) .filter_list_key("type", Some(protocol)) .column_leaf("Instance", "name") @@ -1479,7 +1528,7 @@ pub fn cmd_show_rip_neighbor( .filter_list_key(address, get_opt_arg(&mut args, "address")) .column_leaf("Address", address) .column_leaf("Last update", "last-update") - .show()?; + .show_state()?; Ok(false) } @@ -1513,8 +1562,7 @@ pub fn cmd_show_rip_neighbor_detail( format!("{}[{}='{}']", xpath_neighbor, address, nb_address); } - let data = - fetch_data(session, proto::get_request::DataType::State, xpath_req)?; + let data = fetch_state_data(session, xpath_req)?; // Iterate over RIP instances. let output = session.writer(); @@ -1558,7 +1606,7 @@ pub fn cmd_show_rip_route( let xpath_rip_rib = format!("ietf-rip:rip/{}/routes/route", afi); - YangTableBuilder::new(session, proto::get_request::DataType::State) + YangTableBuilder::new(session) .xpath(XPATH_PROTOCOL) .filter_list_key("type", Some(protocol)) .column_leaf("Instance", "name") @@ -1570,7 +1618,7 @@ pub fn cmd_show_rip_route( .column_leaf("Tag", "route-tag") .column_leaf("Nexthop Interface", "interface") .column_leaf("Nexthop Address", "next-hop") - .show()?; + .show_state()?; Ok(false) } @@ -1596,7 +1644,7 @@ pub fn cmd_show_mpls_ldp_discovery( session: &mut Session, mut args: ParsedArgs, ) -> Result { - YangTableBuilder::new(session, proto::get_request::DataType::State) + YangTableBuilder::new(session) .xpath(XPATH_PROTOCOL) .filter_list_key("type", Some(PROTOCOL_MPLS_LDP)) .column_leaf("Instance", "name") @@ -1607,7 +1655,7 @@ pub fn cmd_show_mpls_ldp_discovery( .column_leaf("Adjacent Address", "adjacent-address") .xpath(XPATH_MPLS_LDP_ADJACENCY_PEER) .column_leaf("LSR Id", "lsr-id") - .show()?; + .show_state()?; Ok(false) } @@ -1636,8 +1684,7 @@ pub fn cmd_show_mpls_ldp_discovery_detail( // when find_xpath is invoked current node is address-families let xpath_adjacency = "ipv4/hello-adjacencies/hello-adjacency".to_owned(); - let data = - fetch_data(session, proto::get_request::DataType::State, xpath_req)?; + let data = fetch_state_data(session, xpath_req)?; // Iterate over MPLS LDP instances. let output = session.writer(); @@ -1706,7 +1753,7 @@ pub fn cmd_show_mpls_ldp_peer( session: &mut Session, mut args: ParsedArgs, ) -> Result { - YangTableBuilder::new(session, proto::get_request::DataType::State) + YangTableBuilder::new(session) .xpath(XPATH_PROTOCOL) .filter_list_key("type", Some(PROTOCOL_MPLS_LDP)) .column_leaf("Instance", "name") @@ -1718,7 +1765,7 @@ pub fn cmd_show_mpls_ldp_peer( .xpath(XPATH_MPLS_LDP_ADJACENCY) .column_leaf("Local address", "local-address") .column_leaf("Adjacent address", "adjacent-address") - .show()?; + .show_state()?; Ok(false) } @@ -1747,8 +1794,7 @@ pub fn cmd_show_mpls_ldp_peer_detail( let xpath_capability = "capability".to_owned(); - let data = - fetch_data(session, proto::get_request::DataType::State, xpath_req)?; + let data = fetch_state_data(session, xpath_req)?; // Iterate over MPLS LDP instances. let output = session.writer(); @@ -1878,7 +1924,7 @@ pub fn cmd_show_mpls_ldp_binding_address( session: &mut Session, mut args: ParsedArgs, ) -> Result { - YangTableBuilder::new(session, proto::get_request::DataType::State) + YangTableBuilder::new(session) .xpath(XPATH_PROTOCOL) .filter_list_key("type", Some(PROTOCOL_MPLS_LDP)) .column_leaf("Instance", "name") @@ -1902,7 +1948,7 @@ pub fn cmd_show_mpls_ldp_binding_address( output }), ) - .show()?; + .show_state()?; Ok(false) } @@ -1912,7 +1958,7 @@ pub fn cmd_show_mpls_ldp_binding_fec( session: &mut Session, mut args: ParsedArgs, ) -> Result { - YangTableBuilder::new(session, proto::get_request::DataType::State) + YangTableBuilder::new(session) .xpath(XPATH_PROTOCOL) .filter_list_key("type", Some(PROTOCOL_MPLS_LDP)) .column_leaf("Instance", "name") @@ -1946,7 +1992,7 @@ pub fn cmd_show_mpls_ldp_binding_fec( }), ) .column_leaf("In use", "used-in-forwarding") - .show()?; + .show_state()?; Ok(false) } @@ -1994,7 +2040,7 @@ pub fn cmd_show_bgp_summary( let afi_xpath = format!("afi-safis/afi-safi[name='{}']/prefixes", afi); - YangTableBuilder::new(session, proto::get_request::DataType::All) + YangTableBuilder::new(session) .xpath(XPATH_PROTOCOL) .filter_list_key("type", Some(PROTOCOL_BGP)) .column_leaf("Instance", "name") @@ -2049,8 +2095,7 @@ fn bgp_get_attrs( XPATH_PROTOCOL, PROTOCOL_BGP, "main", XPATH_BGP_RIB_ATTR_SET ); - let data = - fetch_data(session, proto::get_request::DataType::State, &xpath)?; + let data = fetch_state_data(session, &xpath)?; let attributes = data .find_path(&xpath) @@ -2132,10 +2177,9 @@ pub fn cmd_show_bgp_neighbor( rt_type ); - let data = - fetch_data(session, proto::get_request::DataType::State, &xpath_req)?; + let data = fetch_state_data(session, &xpath_req)?; - let xpath_routes = format!("{}/route", &xpath_req); + let xpath_routes = format!("{}/route", xpath_req); let output = session.writer(); @@ -2181,11 +2225,7 @@ pub fn cmd_show_bgp_neighbor_detail( format!("{}[remote-address='{}']", xpath_neighbor, addr); } - let data = fetch_data( - session, - proto::get_request::DataType::All, - &xpath_bgp_instance, - )?; + let data = fetch_data(session, &xpath_bgp_instance)?; let output = session.writer(); for dnode_inst in data.find_xpath(&xpath_bgp_instance).unwrap() { @@ -2461,12 +2501,12 @@ pub fn cmd_clear_bgp_neighbor( "soft-in" => "soft-inbound", op => op, }; - let xpath = format!("{}/{}", &xpath, operation); + let xpath = format!("{}/{}", xpath, operation); clear_req.new_path(&xpath, None, false).unwrap(); } if neighbor.is_some() { - let xpath = format!("{}/holo-bgp:remote-addr", &xpath); + let xpath = format!("{}/holo-bgp:remote-addr", xpath); clear_req .new_path(&xpath, neighbor.as_deref(), false) .unwrap(); @@ -2517,8 +2557,7 @@ pub fn cmd_show_route( let fetch_xpath = format!("{}[name='{}']", XPATH_RIB, rib_name); let route_xpath = format!("{}/routes/route", fetch_xpath); - let data = - fetch_data(session, proto::get_request::DataType::All, &fetch_xpath)?; + let data = fetch_data(session, &fetch_xpath)?; let Some(dnode) = data.reference() else { return Ok(false); diff --git a/src/session.rs b/src/session.rs index a45f6a6..8483150 100644 --- a/src/session.rs +++ b/src/session.rs @@ -56,14 +56,7 @@ impl Session { pub fn new(use_pager: bool, mut grpc_client: GrpcClient) -> Session { let yang_ctx = YANG_CTX.get().unwrap(); let data_format = DataFormat::LYB; - let running = grpc_client - .get( - proto::get_request::DataType::Config, - data_format, - false, - None, - ) - .unwrap(); + let running = grpc_client.get_config(data_format, false, None).unwrap(); let running = DataTree::parse_string( yang_ctx, running.as_bytes().unwrap(), @@ -308,15 +301,22 @@ impl Session { } } - pub fn get( + pub fn get_config( &mut self, - data_type: proto::get_request::DataType, format: DataFormat, with_defaults: bool, xpath: Option, ) -> Result { - self.grpc_client - .get(data_type, format, with_defaults, xpath) + self.grpc_client.get_config(format, with_defaults, xpath) + } + + pub fn get_state( + &mut self, + format: DataFormat, + with_defaults: bool, + xpath: Option, + ) -> Result { + self.grpc_client.get_state(format, with_defaults, xpath) } pub fn execute(