Yes, Fernando is fine.
Fernando, he's going to talk about using Rust for
your network management tools. Take it away.
All right. Thank you.
All right. So, welcome everyone.
My name is Fernando.
I'm a senior software engineer at Drehat.
I work for the Networking Services Team,
mainly in focus on network management tools,
and today we are going to talk what was our journey,
building a Rust tool for network management.
So, okay. We did not start with Rust.
We have started with Python,
but after some time we decide that we wanted to shift to Rust.
So, this is two talks in one.
One is how we did build the project in Rust,
and what we learned when moving from Python to Rust.
Okay. So, network management.
What's network management?
Basically, it's all the operations that you do
to configure your networking.
Roots, interfaces, DNS,
firewalling, whatever you do,
it's network management.
So, it's a process that is quite complex because it requires
a lot of coordination between user space and kernel space.
We need to check when we get
notification for kernel space because all the tools
could modify the network status.
We also need to communicate with
kernel in order to configure stuff.
So, it's a quite complex task.
There is already a tool which is network manager.
It's by default, the tool that is in almost all situations used
for managing your Linux network configuration,
and we were willing to use it and we were
willing to build in top of a network manager because
implementing everything was really, really complex.
So, we created NMS state,
and NMS state is a tool that communicates with
network manager and it's a library with a command line tool,
and allow us to configure the network with using declarative states.
So, you can define what do you want,
and you don't need to care about
how is network manager or how is the kernel doing,
and what's going to do or what are the dependencies.
You don't need to care about any of that.
NMS state is going to manage it,
so it makes everything easier.
So, as I say, we started to build NMS state in Python,
and one day we noticed that a lot of our users were
willing to chip a binary and not Python,
don't use the Python environment,
and well, there were also some performance issues
because we need to do a lot of operations.
So, we decided to give it a try to REST,
and we have a problem is that we have a library and a binary,
and we needed to move both of them to REST,
and also we already have a big base of users.
So, we could not break them,
and we need to do it in a way that we are going to support,
we need to support all the features that we already did in Python.
So, well, we created our own NMS state library in REST,
I will tell you how,
and also the NMS state CTL tool,
which is the command line tool.
All right. So, the first thing is that we are using
Jamel files and JSON files, and we are parsing them.
So, in Python, this was quite trivial with an schema,
and we needed to find a way to do it.
In Python, we were using dictionary,
so the user could create a dictionary,
and it was using a Jamel library,
it was quite trivial to convert that Jamel into a dictionary,
and we needed something in REST to do this.
So, we end up looking at CD.
CD is a framework for serializing and
deserializing REST data structures efficiently and
generically we use it for Jamel and JSON,
but it supports other formats.
This allows us to keep our declarative state,
keep our API, so that was pretty good,
and we noticed that CD allow us to
implement our own serializers and deserializers.
So, that was also a big plus because we
could do validation steps and simplify
the validation work when
getting the configuration file from the user,
and then there were a lot of decorators on server,
so it was quite good for creating aliases,
for creating multiple helper functions,
and also some conditional deserialization and serializations.
So, here's an example.
For example, this is a interface state for a general bond,
and we basically define it is app,
it is have an IPv4 address with this address,
with this prefix length,
and it is enabled,
and then we define the link aggregation options.
So, we have the mod options and the ports.
One really good thing that we have is that we have a partial editing.
So, you can define what you want to change,
and we are going to merge it with
what you already have on configure on the system.
About the decorators, as you can see there,
we were able to use the decorator for example,
accepting numbers as a string,
accepting strings, accepting only the number,
custom strings, creating alias, renaming,
yeah, all of that, and it was quite good.
So, okay. We communicate with
Neville Manager and we communicate with
Neville Manager to configure the network state,
and we have a problem is that before we were using
the Lebanon bindings, Python bindings,
and they were not available in trust,
and we tried to create a trust bindings,
but it was quite complex because they use
gObject and we did not have gObject,
and it was a big mess,
but we noticed that Neville Manager is providing a Divas API.
So, we say, okay, let's use Divas then,
and we noticed that there is a create which is Zitabas,
and with Zitabas, we were able to communicate with
Neville Manager using the Divas API,
and with Zitabas, and we were able to
encode the data structures that we were using
to communicate with Neville Manager
and configure the settings that we wanted.
So, using this, we solved one of the problems,
which is telling Neville Manager what we want to do,
and also fetching what already Neville Manager have,
which is also important because,
all right, there are some options
that maybe we do not want to overwrite
because the user configured it that way,
and for patch editing, that is important.
We need to know what the user configured
and what the user was to modify.
So, okay, one problem solved.
Then, we have another problem.
So, Neville Manager does not provide
at all real-time information from kernel,
and we needed that because we also do verification.
So, when you configure something,
NMS state do a verification step,
which what it does is compare what the user defined,
which what is configured on the system.
We have a problem because Neville Manager
was not providing real-time information,
and sometimes it took quite
sometimes to get the information that we wanted,
and we were having some problems on the verification.
So, we were looking for a library,
and we did not find any library that
certified our requirements, but we noticed
that there is already a Rastnet link library,
and that link is a kernel API for
communication between user place and kernel,
also, I think, between kernel components,
and it was perfect.
We could use Rastnet link,
which is an existing library,
to build another tool, which is NISPOR.
So, NISPOR only queries information from kernel,
and show you in a jammel file,
or basically, proper data structures.
Well, it was quite good because we
started to contribute to Rastnet link,
because Rastnet link was an independent project,
and they didn't support everything.
So, we were able to help there,
and currently, a lot of people use Rastnet link,
and it's a quite big project,
and probably the one that most of
the people use when need to work with NEL link and REST.
So, we have one more problem.
Okay. Now, we have network manager working,
we have verification working, validation working,
we can read the configuration,
we can do a lot of stuff.
But then, networking is complex,
and there is one thing that is called OBS,
OBSDB, and network manager configure OBS, right?
But they do not configure global OBSDB settings.
And that was a problem because we wanted to do that.
So, how we did?
We basically started to use sockets,
and using the Rast SDD library for stream sockets,
we were able to communicate with OBSDB send petitions,
read what they already have stored on the OBSDB,
and configure whatever OBSDB settings
the user want to configure.
So, we created our own set of
JSON or using set of JSON libraries,
we created our own JSON RPC to communicate with OBSDB.
This is internal of NMS state.
We have considered to put it on a separate crate,
but we did not yet.
Then, we had another problem.
Okay. I promise this will end.
We are going to have a solution.
It will stop at some point.
So, we had users,
the users were using our Python library,
and some of them were willing to move to Rast,
some of them were willing to move to Goland,
but we were already developing a Rast solution.
And some of them didn't want to move
from the Python code to Rast.
So, what we did is create bindings,
and we create plenty of them.
First of all, we created C bindings.
So, C users could use the Rast library.
Then, from the C bindings,
we created the Python and Goland bindings.
And finally, one of the other problem that we had is that
we got a huge integration test base,
and we wanted to reuse them.
So, with the Python bindings,
we were able to integrate the Python integration test
that we had into our Rast library.
So, it was quite cool because we were able to start
building the new Rast NMS date,
but at the same time,
using the Python integration test.
And this way, we were sure that we were not
breaking any existing use case that we already support.
So, that's it. It was a success.
And we are quite proud because most of the people that were
using it liked the idea,
and even the ones that did not care about if you use Python or Rast,
we're happy because the change was
completely transparent for the final user.
If you were using Python,
nothing will change for you.
The code is the same.
You didn't need to do anything different.
So, it will be a transparent update.
And if you are using Python and are willing to use Rast,
okay, you need to change your code.
But basically, the API is the same.
So, well, you were able to use the same Jamel files,
and the same JSON files,
and everything will work.
So, we got a lot of adoptions,
and right now, the user base of NMS date is still growing,
and we are quite happy.
Also, it was recreated goal and bindings because
OpenShift people and Kubernetes people were
wiling to use it and it's written in goal and bindings.
So, we provided them with goal and bindings,
and they really liked it.
So, yeah, it was a success story.
Yeah. So, basically, that was our journey.
I would like to hear,
I think we have time for questions.
So, please, as whatever you want,
I promise you there are no dumb questions.
So, thank you very much.
All right, any question? Okay.
I wondered what your experience was in terms of time to
implement in Rust versus Python.
All right.
From a developer point of view.
I think it took us around two years,
two developers mainly working on it.
It was full-time.
It was a long journey,
but it helped us a lot having
the Python integration test working with the new library,
because we were sure that we were not
breaking the existing cases and speed up the things a little bit.
Absolutely. Do you have a feeling for how long it would have
taken you if you had re-implemented it in Python?
I mean, I know that's not really a thing,
but roughly how long if you had said right?
Going back to Python.
No, if you had said, right,
we've got it in Python, but for no good reason,
we're going to rewrite it from scratch in
Python to make it cleaner, let's say.
Just as like, how long does it take to write something in
Python versus Rust or maybe it's not possible to guess?
Well, I think it depends.
In my opinion, this is a personal opinion,
writing Python is much easier,
but then you have more bugs.
This was my experience.
When I implement something in Python,
I do it in 30 minutes,
one hour, two hours, but then I got bugs.
When I do it in Rust,
it took me more longer,
a lot of compiler errors,
a lot of unsafe stuff everywhere,
so we need to avoid that,
but then it's quite stable.
I can say that nowadays,
the Rust version,
it is younger that the Python one is more stable.
We got less bug reports and we have more users.
Thank you.
Yeah, thank you.
Did you run into any problems in terms of
compatibility when you created
C bindings from the Rust code?
No, not at all. To be honest,
we did not have any problem.
It was quite straightforward.
We did not have any problem.
I must say that the NMS state library is,
well, we spoke to the users,
it's quite simple, so that makes it simple for us.
We did not have any problem. That's it.
Okay, thanks.
Before. You mentioned that it was
a long journey when you implemented this in Rust.
Could you compare what you have
expected in the beginning of this journey and with the reality?
I must say that I'm not the only one person working on this.
There is my teammate, Chris,
and Chris was the lead here.
I must say that I did not trust very much,
that we were able to do it in two years.
So we were like, yeah, in two years,
we are going to have Rust and I was like, I don't think so.
But he was right.
So I think my expectation is that it will take much longer,
but it was much simpler than what I thought.
So also, I thought that we could have more problems
with finding the libraries that we
need to do all the positions that we needed.
But I must say that Rust have a great ecosystem.
So the libraries that we are using,
they are really, really well maintained and that's great.
Let's work for us.
We have a question from the matrix.
Sure.
So that's a bit weird.
Tanya is asking, how long did it take
your team to learn Rust or did they know Rust already?
No.
We did not know Rust.
I mean, we didn't know what Rust was
and we did some work on Rust.
But we did one thing here.
We started with NISPOR instead with NMS state.
So when we noticed what are the missing pieces,
we first started with NISPOR, which
is much simpler than NMS state, and we learned on the way.
I must say that I am most surprised
with all the Rust resources that it was quite easy to learn.
But we learned on the way.
When we needed something, we started learning it.
And then we revisited the code and we changed things.
For example, initially, we did not
understood correctly how to use traits,
so we did not use them.
And then we noticed, right, traits are really useful.
We are not using them.
And then we started to implement traits everywhere
and make it more flexible.
Thank you.
Great.
There's no more questions.
Thank you for your time.
Thank you for listening.
Thank you very much.