From Networking To DevOps
Probably the most common fear that people, working with networks, have when they hear about DevOps is the huge gap between a developer and themselves. This leads to the most common question: do I have to become developer to be useful in a DevOps team?
In my view the answer is no BUT we have to learn a few tricks from them. They key is being able to translate the network configurations for developers who can then translate it further into code.
I’m going to use the following short Cisco configuration as example throughout the article.
interface loopback0
ip address 10.0.255.12 255.255.255.255
interface GigabitEthernet2
description Customer_X WAN router
ip address 10.22.130.2 255.255.255.252
negotiation auto
no shutdown
router bgp 65000
bgp router-id 10.0.255.12
bgp log-neighbor-changes
neighbor 10.22.130.2 remote as 65222
neighbor 10.22.130.2 soft-reconfiguration inbound
neighbor 10.22.130.2 prefix-list PL-Customer_X-accepted-prefixes in
ip prefix-list PL-Customer_X-accepted-prefixes seq 10 permit 10.0.0.0/8
ip prefix-list PL-Customer_X-accepted-prefixes seq 30 permit 172.16.0.0/12
It is readable for a network guy working with Cisco devices but means almost nothing to a developer. How can we help them?
Variables
This is the easiest; identify which sections of the configuration is fixed and which are variables. This is obvious in some cases (e.g. IP addresses or the “bgp log-neighbor-changes” command) but can be an automation design decision in others. For example, depending if we’re only one central running control tower or one for each region, the local BGP AS number varies (variable in the first case, fixed value in the second).
Let us assume the first case and replace the actual data with variable names. Please keep in mind that it is not important how you mark them; the goal is showing the developer the variable but not necessarily matching with any programming language – just be consistent throughout your configuration.
interface loopback0
ip address %LO0_IPV4% 255.255.255.255
interface %CUSTOMER_FACING_INT%
description %CUSTOMER_NAME% WAN router
ip address %CUSTOMER_FACING_INT_IPV4% 255.255.255.252
negotiation auto
no shutdown
router bgp $LOCAL_ASN%
bgp router-id %LO0_IPV4%
bgp log-neighbor-changes
neighbor %CUSTOMER_RTR_IPV4% remote as %CUSTOMER_ASN%
neighbor %CUSTOMER_RTR_IPV4% soft-reconfiguration inbound
neighbor %CUSTOMER_RTR_IPV4% prefix-list PL-%CUSTOMER_NAME%-accepted-prefixes in
ip prefix-list PL-%CUSTOMER_NAME%-accepted-prefixes seq %PL_SEQ% permit %PL_ENTRY_1%
ip prefix-list PL-Customer_%CUSTOMER_NAME%-accepted-prefixes seq 30 permit %PL_ENTRY_2%
We keep the netmasks as fixed values because loopback interfaces will always be /32 and we use point-to-point links.
Data types, structures
The second, and probably most important, step is recognizing what type of data our configuration has. Although it does not need hardcore programming knowledge, doing an easy “Introduction to programming” course is strongly recommended. I suggest learning the basics of Python as this language became the de-facto standard language for network automation; the rest of this article relies on Python too. Knowing the configuration’s and programming structures is also important; it helps you identify conditions, loops, etc. In our example, we can create a loop to define the prefix-list.
To identify data types, let’s list our variables along with their types:
Variable | Type |
---|---|
LO0_IPV4 | String |
CUSTOMER_NAME | String |
CUSTOMER_FACING_INT | String |
CUSTOMER_FACING_INT_IPV4 | String |
LOCAL_ASN | Integer |
CUSTOMER_RTR_IPV4 | String |
CUSTOMER_ASN | Integer |
prefix-list (structure, not variable) | List |
PL_SEQ | Integer |
PL_ENTRY_x | String |
The usual data types are strings, integers, lists, and dictionaries.
Data sources
This is again something that does not require hardcore programming skills. We should collect all variables in a table and discuss with the developers where they should come from. The usual data sources are:
- Customer input
- A database (e.g network automation internal / CMDB / OSS & BSS systems)
- Auto-generated
Let’s add a column to our previous table:
Variable | Type | Source |
---|---|---|
LO0_IPV4 | String | Internal CMDB |
CUSTOMER_NAME | String | BSS (e.g. ServiceNow) |
CUSTOMER_FACING_INT | String | Internal CMDB |
CUSTOMER_FACING_INT_IPV4 | String | Internal CMDB |
LOCAL_ASN | Integer | Internal CMDB |
CUSTOMER_RTR_IPV4 | String | Customer input |
CUSTOMER_ASN | Integer | Customer input |
prefix-list (structure, not variable) | List | |
PL_SEQ | Integer | Generated |
PL_ENTRY_x | String | Customer input |
Data formats
This is again something that’s not hard to tell with a networking background. We need to define what values are valid for each variable. We’re expanding our table again with this information:
Variable | Type | Source | Format |
---|---|---|---|
LO0_IPV4 | String | Internal CMDB | [0-255].[0-255].[0-255].[0-255] |
CUSTOMER_NAME | String | BSS (e.g. ServiceNow) | Max. length: 32 |
CUSTOMER_FACING_INT | String | Internal CMDB | Max. length: 32 |
CUSTOMER_FACING_INT_IPV4 | String | Internal CMDB | [0-255].[0-255].[0-255].[0-255] |
LOCAL_ASN | Integer | Internal CMDB | 4 bytes |
CUSTOMER_RTR_IPV4 | String | Customer input | [0-255].[0-255].[0-255].[0-255] |
CUSTOMER_ASN | Integer | Customer input | 4 bytes |
prefix-list (structure, not variable) | List | ||
PL_SEQ | Integer | Generated | 2 bytes |
PL_ENTRY_x | String | Customer input | [0-255].[0-255].[0-255].[0-255]/[0-30] |
Pseudo-code
If you completed the Python 101 course that I suggested in the Data types section, writing a pseudo-code will be a no-brainer. The example code is now expanded; the customer can choose whether to use BGP or static routes.
interface loopback0
ip address %LO0_IPV4% 255.255.255.255
interface %CUSTOMER_FACING_INT%
description %CUSTOMER_NAME% WAN router
ip address %CUSTOMER_FACING_INT_IPV4% 255.255.255.252
negotiation auto
no shutdown
<if %IS_BGP% == True>
router bgp $LOCAL_ASN%
bgp router-id %LO0_IPV4%
bgp log-neighbor-changes
neighbor %CUSTOMER_RTR_IPV4% remote as %CUSTOMER_ASN%
neighbor %CUSTOMER_RTR_IPV4% soft-reconfiguration inbound
neighbor %CUSTOMER_RTR_IPV4% prefix-list PL-%CUSTOMER_NAME%-accepted-prefixes in
<foreach %PL_ENTRY%>
ip prefix-list PL-%CUSTOMER_NAME%-accepted-prefixes seq %PL_SEQ% permit %PL_ENTRY%
<endfor>
<endif>
<if %IS_BGP% == False>
<foreach %STATIC_ROUTE%>
ip route %STATIC_SUBNET% %STATIC_MASK% %STATIC_NEXT_HOP%
<endfor>
<endif>
If you got to this point, your pseudo-code along with the last table will be sufficient for a developer to create the network automation code – and it wasn’t even that hard, is it? By the way, can you add the IS_BGP, STATIC_ROUTE, STATIC_SUBNET, STATIC_MASK, and STATIC_NEXT_HOP to table?
Final words
You can see from these examples that moving on to DevOps is not a giant leap but a series of small steps, which are not that hard to take. My suggestion is to learn the basics of the following:
- Python
- Regular expressions or regex (to describe data patterns)
- Data formats: XML, JSON, YAML
- New way of configuring devices: Rest API, NETCONF, RESTCONF
- Linux
One more thing: the article was about the “from networking to coding” but it doesn’t mean the developer can just wait for us. Learning basic networking, subnetting, etc. is necessary for a developer too so we can come closer to each other from both directions.